Postfinance e-payment configuration - Bad Request

advertisement
CREDIT CARD PAYMENTS
Document created on 2014-09-23
Nicolas Bondier
[pdf][doc][htm]
*
*
Page 1/57
*
Copyright © 2016 by Switzernet
Contents
Introduction ............................................................................................................................................................. 3
Postfinance integration with portabilling................................................................................................................ 3
Postfinance e-payment configuration .................................................................................................................. 3
Direclink activation ............................................................................................................................................. 3
Create an API user .............................................................................................................................................. 3
Allow access for portabilling slave IP address .................................................................................................... 4
Configure return parameters ............................................................................................................................. 5
Porta-billing configuration ................................................................................................................................... 5
Use PostFinance gateway in Ogone payment processing module on slave. ..................................................... 5
Add PostFinance to the Porta-Billing payments systems. .................................................................................. 6
Payments on website .............................................................................................................................................. 6
Main payment page ............................................................................................................................................. 9
PayPal ................................................................................................................................................................. 25
Process PayPal payments ................................................................................................................................. 25
PayPal payment notifications and update payment on billing ........................................................................ 31
PostFinance ........................................................................................................................................................ 42
Process Postfinance payments ......................................................................................................................... 42
Postfinance payment notifications and update payment in portabilling ........................................................ 45
Liens ...........................................................................................................................Error! Bookmark not defined.
Page 2/57
Introduction
This document describes the configuration and scripts used for setting different payments systems in PortaBilling and on the main website pay.switzernet.com.
Postfinance integration with portabilling
PostFinance e-payment have a partnership with Ogone for their e-payment gateway. As the billing permit
to use Ogone as payment processor, we could set-up the payment gateway for Postfinance using Ogone as
processor with some modifications.
Postfinance e-payment configuration
Direclink activation
First, it is required to set-up the Postfinance account e-payment.postfinance.ch.
Go to ‘Configuration’  ‘Abonnement’  ‘Vos options’. DirectLink is the method used by the billing for
processing the payments. The options showed in the picture bellow must be activated.
To activate them, we had to contact Postfinance e-payment and send an order letter.
Create an API user
Go to ‘Configuration’  ‘Utilisateurs’ and click the add user button.
In the form, enter the data of the new user as bellow and choose ‘”API” user’ option. Save and manually
choose a password for your new API user.
Page 3/57
Allow access for portabilling slave IP address
Under "Configuration"  "Informations Techniques"  "Controles de données et d’origine", fill the section
"Contrôles pour PostFinance DirectLink".
The IP addresses to authorize are separated with ";". Here I put all the slave portabilling IP addresses.
Page 4/57
Configure return parameters
Under "Configuration" -> "Informations Techniques" -> "Retour d'information sur la transaction", go to
section "DirectLink".
Move all parameters to "Seléctionné" as bellow and save.
Porta-billing configuration
Use PostFinance gateway in Ogone payment processing module on slave.
Connect with ssh to the portabilling slave server and edit the file ‘/home/portaadmin/site_lib/Business/OnlinePayment/Ogone.pm’.
Under the ‘set_fefaults’ subroutine, we have the connection settings to Ogone. The server
‘secure.ogone.com’ must be replaced with ‘e-payment.postfinance.ch’ as bellow.
Page 5/57
sub set_defaults{
my $self = shift;
$self->server('e-payment.postfinance.ch');
$self->port('443');
$self->build_subs('test_path');
$self->build_subs('order_number');
$self->test_path('/ncol/test/orderdirect.asp');
$self->path('/ncol/prod/orderdirect.asp');
}
Add PostFinance to the Porta-Billing payments systems.
In the slave portabilling server, add a new payment system as follow [link].
Under the login field, enter PostFinance PSID followed by the API user id created before. The both logins
must be separated with ‘:’ like ‘PSID:API_userid’.
The password to fill is the API user password created before.
Then, we can set the Payment System for each currencies [link]. Here is an example.
Payments on website
In order to facilitate customer’s payments, it is possible to pay directly from the main website or directly
access the payment page through pay.switzernet.com.
The sections bellow describe the main script made for using PayPal and Postfinance on the website.
Files and folders
There are three new subfolders added to the /public/ directory on Switzernet.com web site. 140819-epay
contains the payment page for the customer and 140824-paypal-notification and 140915postfinance-notification contain the notification system for PayPal and PostFinance.
Page 6/57
140819-epay/
├── custom_icon.png
├── images
│
├── menubar.gif
│
└── switzernet.gif
├── include
│
├── db.config.php
│
├── geoiploc.php
│
├── languages
│
│
├── get_language.php
│
│
├── language_DE.php
│
│
├── language_EN.php
│
│
├── language_ES.php
│
│
├── language_FR.php
│
│
└── language_RU.php
│
├── Mobile-Detect-master
│
│
├── composer.json
│
│
├── composer.lock
│
│
├── examples
│
│
│
├── demo.php
│
│
│
└── session_example.php
│
│
├── export
│
│
│
└── exportToJSON.php
│
│
├── LICENSE.txt
│
│
├── Mobile_Detect.json
│
│
├── Mobile_Detect.php
│
│
├── namespaced
│
│
│
└── Detection
│
│
│
└── MobileDetect.php
│
│
├── README.md
│
│
└── tests
│
│
├── BasicsTest.php
│
│
├── bootstrap.php
│
│
├── phpunit.xml
│
│
├── UA_List.inc.php
│
│
├── UA_List.pending.txt
│
│
├── ualist.json
│
│
├── UserAgentTest.php
│
│
└── VendorsTest.php
│
├── pay.config.php
│
├── paypal.class.php
│
└── paypal.config.php
├── index.php
├── js
│
├── parsley.min.js
│
└── parsley_locales
│
├── de.js
│
├── en.js
│
├── es.js
│
├── fr.js
Page 7/57
│
├──
├──
├──
├──
└──
└── ru.js
paypalProcess.php
postfinanceProcess.php
postfinanceTemplate.css
postfinanceTemplate.php
style
├── ie.css
├── mobile.css
├── parsley.css
├── style.css
└── style2.css
140824-paypal-notification/
├── live.php
├── PortaBillingSoapClient.php
└── sandbox.php
140915-postfinance-notification
├── index.php
└── PortaBillingSoapClient.php
Page 8/57
Main payment page
[index.php]
CODE
COMMENT
<?
if(!isset($_SESSION)){session_start();}
Session start
include_once "include/pay.config.php";
Including general
configuration file.
Getting information posted
to this page.
if ( isset($_GET['amount']) ){
if ( preg_match('/^[0-9]+(\.[0-9]{0,2})?$/', $_GET['amount']) ){
$price = $_GET['amount'];
}
}
if ( isset($_POST['amount']) ){
if ( preg_match('/^[0-9]+(\.[0-9]{0,2})?$/', $_POST['amount']) ){
$price = $_POST['amount'];
}
}
$number = "";
if ( isset( $_POST['action'] ) ){
$_SESSION['action'] = $_POST['action'];
}
if ( isset( $_GET['action'] ) ){
$_SESSION['action'] = $_GET['action'];
}
$debug_IE = TRUE;
$using_ie6 = (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6.') !==
FALSE);
Page 9/57
Debug for displaying on old
web browsers
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initialscale=1,maximum-scale=1.0">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="custom_icon.png">
<meta name="format-detection" content="telephone=no">
<?php if ( $debug_IE ) { ?>
<meta http-equiv="X-UA-Compatible" content="IE=6" />
<?php } else { ?>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
<?php } ?>
<meta name="author" content="Nicolas Bondier - Switzernet">
<link rel="stylesheet" href="../070608-subscribe/pure-min.css">
<link href="../060801-web/style.css" rel="stylesheet"
type="text/css">
<link href="style/style2.css" rel="stylesheet" type="text/css">
<link href="style/mobile.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="../070608-subscribe/jquery1.7.2.min.js"></script>
<script type="text/javascript" src="js/parsley.min.js" ></script>
<link href="style/parsley.css" rel="stylesheet" type="text/css">
<?php
if ( isset( $_SESSION['language']['code'] ) && file_exists(
"js/parsley_locales/".strtolower($_SESSION['language']['code']).".js")
) {
?>
<script src="js/parsley_locales/<?=
strtolower($_SESSION["language"]["code"]) ?>.js"></script>
<script type="text/javascript">
window.ParsleyValidator.setLocale('<?=
strtolower($_SESSION["language"]["code"]) ?>');
</script>
<?php
Page 10/57
HTML begins here.
The head content contains
information for better
displaying on mobile
applications and old
browser.
Getting the localization files
(language) for error
handling for the customer.
}
?>
<script type="text/javascript">
function changeLanguage(selectLanguage){
var lang = selectLanguage.value;
var form = document.getElementById("formLanguage");
form.submit();
}
function changeCurrency(selectCurrency){
var value =
selectCurrency.options[selectCurrency.selectedIndex].value;
window.location.href = '?currency_code='+value+'';
}
function getParentElementByTagName( element , tag ){
while( element.tagName.toLowerCase() != tag.toLowerCase() ){
element = element.parentNode;
if (!element.tagName) {
return;
}
}
return element;
}
</script>
<!--[if lte IE 8]>
<link rel="stylesheet" href="style/ie.css" type="text/css"
media="screen,projection" />
<![endif]-->
<script type="text/javascript">
function initFormAction(){
var select = document.getElementById("paymentType");
if ( select !== null ){
updateFormAction(select);
}
}
Page 11/57
Some JavaScript functions
for submitting language
and currency changes.
A function to simplify the
selection of a parent
element.
Special CSS style sheet for
internet explorer.
Function to update the
“action” parameter of the
form after having choose
the payment method. It
changes the “action”
parameter to the
function updateFormAction(select){
var form=document.getElementById("payForm");
var option = select.options[select.selectedIndex].value;
var ts = "ts="+Date.now();
if ( option == "creditcard" ){
form.action="postfinanceProcess.php?"+ts;
} else {
form.action="paypalProcess.php?"+ts;
}
}
</script>
PostFinance processing
script or PayPal processing
script.
Piwik script for getting
statistics.
<!-- Piwik -->
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
(function() {
var u=(("https:" == document.location.protocol) ? "https" :
"http") + "://switzernet.com/3/public/120427-site-stats/";
_paq.push(["setTrackerUrl", u+"piwik.php"]);
_paq.push(["setSiteId", "1"]);
var d=document, g=d.createElement("script"),
s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
g.defer=true; g.async=true; g.src=u+"piwik.js";
s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Piwik Code -->
<title><?= TITLE_PAYMENT_SWITZERNET ?></title>
</head>
<body style="" onload="initFormAction()">
<div id="container">
<div id="head" style="text-align: center;">
<table style="">
<tbody>
<tr>
Page 12/57
Starting of the body and
the page header.
<td align="left">
<a href="http://www.switzernet.com/">
<img style="" class="pure-img" src="../060801web/images/switzernet.gif" alt="Switzernet VoIP téléphonie IP
Suisse"></a>
<img id="calltheworld" class="pure-img"
style="margin:10px"
src="../060801-web/images/slogan_6.gif" alt="appeler le monde pour
presque rien">
</td>
<td style="vertical-align: top;" align="right">
<div class="pure-form pure-form-aligned">
<form id="formLanguage" action="#" method="get">
<fieldset>
<select name="language" id="language_select"
onchange="changeLanguage(this)">
<?php
foreach ($LANGUAGES as $ISO => $text) {
if ( $_SESSION['language']['code'] == $ISO ){
echo "<option value='".$ISO."'
selected='selected'>".$text."</option>";
} else {
echo "<option
value='".$ISO."'>".$text."</option>";
}
}
?>
</select>
</fieldset>
</form>
Language selection
End of page header
</div>
</td>
</tr>
</tbody>
</table>
</div>
Page 13/57
Starting of the man content
div.
<div id="pay_div" style="">
<?php
if ( $_SERVER['REMOTE_ADDR'] == '46.14.170.24' && FALSE ){
echo time();
}
if ( isset( $_SESSION['action'] ) && $_SESSION['action'] ==
'cancel' ) {
?>
<h1 style="text-align:center;"><?= H1_PAYMENT_CANCELED ?></h1>
<table>
<tr>
<td><?= TEXT_PAYMENT_CANCELED_1 ?></td>
</tr>
<tr style="text-align:center;">
<td><br><button class="pure-button"
onclick="window.location.href='<?= $WEBURL ?>?action=number'"><?=
BUTTON_BACK ?></button></td>
</tr>
</table>
<?php
} elseif ( isset( $_SESSION['action'] ) && $_SESSION['action']
== 'paymentok' ){
?>
<h1 style="text-align:center;"><?= H1_PAYMENT_OK ?></h1>
<table>
<tr>
<td><?= TEXT_PAYMENT_OK_1 ?><?= $_SESSION['ItemNumber']
?><?= TEXT_PAYMENT_OK_2 ?></td>
</tr>
<tr style="text-align:center;">
<td><br><button class="pure-button"
onclick="window.location.href='<?= $WEBURL ?>?action=number'"><?=
BUTTON_BACK ?></button></td>
</tr>
Page 14/57
When the action received is
cancel (from PayPal or
PostFinance), we display
the corresponding content.
When the action received is
paymentok (from PayPal or
PostFinance), we display
the corresponding content.
</table>
<?php
} elseif ( isset( $_SESSION['action'] ) && $_SESSION['action']
== 'paymentpending' ){
?>
<h1 style="text-align:center;"><?= H1_PAYMENT_PENDING ?></h1>
<table>
<tr>
<td><?= TEXT_PAYMENT_PENDING_1 ?></td>
</tr>
<tr style="text-align:center;">
<td><br><button class="pure-button"
onclick="window.location.href='<?= $WEBURL ?>?action=number'"><?=
BUTTON_BACK ?></button></td>
</tr>
</table>
<?php
} elseif ( isset( $_SESSION['action'] ) && $_SESSION['action']
== 'paymentfailed' ){
?>
<h1 style="text-align:center;"><?= H1_PAYMENT_FAILED ?></h1>
<table>
<tr>
<td><?= TEXT_PAYMENT_FAILED_1 ?></td>
</tr>
When the action received is
paymentpending (from
PayPal), we display the
corresponding content.
When the action received is
paymentfailed (from PayPal
or Postfinance), we display
the corresponding content.
<tr style="text-align:center;">
<td><br><button class="pure-button"
onclick="window.location.href='<?= $WEBURL ?>?action=number'"><?=
BUTTON_BACK ?></button></td>
</tr>
</table>
<?php
} elseif ( isset( $_SESSION['action'] ) && $_SESSION['action']
== 'paymenterror' ){
?>
<h1 style="text-align:center;"><?= H1_PAYMENT_FAILED ?></h1>
Page 15/57
Error during the payment
(from PayPal), we display
the corresponding content.
<table>
<tr>
<td><?= TEXT_PAYMENT_FAILED_1 ?></td>
</tr>
<tr style="text-align:center;">
<td><br><button class="pure-button"
onclick="window.location.href='<?= $WEBURL ?>?action=number'"><?=
BUTTON_BACK ?></button></td>
</tr>
</table>
<?php
} elseif ( ( isset( $_SESSION['action'] ) &&
$_SESSION['action'] == "payment" ) ){
$number = "";
if ( isset( $_SESSION["postdata"]["num_part_1"] ) && isset(
$_SESSION["postdata"]["num_part_2"] ) ){
$_SESSION['accountToCredit'] =
$_SESSION["postdata"]["num_part_1"]."".$_SESSION["postdata"]["num_part_2"];
unset($_SESSION["postdata"]["num_part_1"]);
unset($_SESSION["postdata"]["num_part_2"]);
}
if ( isset( $_SESSION["postdata"]['number'] ) ){
$_SESSION['accountToCredit'] =
$_SESSION["postdata"]['number'];
unset($_SESSION["postdata"]["number"]);
}
$number = $_SESSION['accountToCredit'];
$number = preg_replace('/[^0-9,]|,[0-9]*$/','',$number);
$number = preg_replace('/^0([0-9]{9})$/', "41$1", $number);
if ( ! preg_match('/^41[0-9]{9}$/', $number) ){
?>
<h1 style="text-align:center;"><?= H1_PAYMENT ?></h1>
<table>
<tr>
<td><?= TEXT_INVALID_NUMBER_1 ?><?= $number ?><?=
TEXT_INVALID_NUMBER_2 ?></td>
</tr>
<tr style="text-align:center;">
Page 16/57
Text when received an
action called payment. It
refers to the last page
before submitting the
payment to PostFinance or
PayPal.
We get the numbers from
different post forms and
test if it match a valid
number format
(41XXXXXXXXX).
If the number format is
wring we inform with a
text.
<td><br><button class="pure-button"
onclick="window.location.href='<?= $WEBURL ?>?action=number'"><?=
BUTTON_BACK ?></button></td>
</tr>
</table>
<?php
} else {
$accountFound = FALSE;
$currency = 'CHF';
$connection2=mysql_connect(DB2_SERVER.':'.DB2_SERVER_PORT,DB2_SERVER_U
SERNAME, DB2_SERVER_PASSWORD) or die(mysql_error().' : erreur de
connexion a la base de donnee !');
If the format is correct, we
get the account currency to
display it on the web page.
mysql_select_db(DB2_DATABASE) or die("erreur de connexion a
la base de donnees");
$sql = "SELECT iso_4217 FROM Accounts WHERE id =
'".$number."' LIMIT 1";
$result = mysql_query($sql,$connection2);
if ( mysql_num_rows($result) == 1 ){
$accountFound = TRUE;
$value = mysql_fetch_object($result);
if ( isset( $currencyNotations[$value->iso_4217] ) ){
$currency = $value->iso_4217;
} else {
$currency = 'CHF';
}
$_SESSION['currency_code'] = $currency;
} else {
include("include/geoiploc.php");
$ip = $_SERVER["REMOTE_ADDR"];
if ( getCountryFromIP($ip) == 'CH' ){
$_SESSION['currency_code'] = 'CHF';
} else {
$_SESSION['currency_code'] = 'EUR';
}
}
mysql_close($connection2);
Page 17/57
If we find the currency,
then we set in session.
Else, it means no account
have been found, we try to
find it with the IP address
of the customer.
The library used for locating
the country of the IP can be
found here
$_SESSION['phone_number'] = $number;
http://chir.ag/projects/geoi
ploc
if ( $_SESSION['currency_code'] != '' ){
$currency = $_SESSION['currency_code'];
}
?>
<h1 style="text-align:center;"><?= H1_PAYMENT ?></h1>
<form data-parsley-validate class="pure-form" method="post"
action="paypalProcess.php" id="payForm"><br>
<table>
<tr>
<td class="label" width="40%">
<label><?= TEXT_SIP_ACCOUNT ?></label>
</td>
<td>
<?= $number ?>
</td>
</tr>
<tr class="parsleyError">
<td></td>
</tr>
<tr>
<td class="label">
<label for="amountInput"><?= TEXT_AMOUNT ?> <span
style="color: #777;font-size:12px;white-space:nowrap;">(min. 5 <?=
$currency ?>)</span></label>
</td>
<td class="td_input">
<?php if ( $accountFound ){ ?>
<?php if ( $layoutType != 'classic' ) { ?>
<input class="input_text" data-parsley-errorscontainer="#amountError" name="itemprice" style="width:80px;textalign:left;" min="5" size="10" placeholder="XXX.XX" required
value="<?= $_SESSION['postdata']['amount'] ?>" />
<?php } else { ?>
<input id="amountInput" class="input_text" dataparsley-errors-container="#amountError" data-parsley-type="number"
name="itemprice" style="text-align:left;" min="5" type="text"
Page 18/57
Here we display the final
payment page before the
processor. It permits to
select the
The final form for selecting
the payment processor and
amount.
size="10" placeholder="XXX.XX" required value="<?=
$_SESSION['postdata']['amount'] ?>" />
<?php } ?>
<span style="color: #777;font-size:14px;whitespace:nowrap;">  <?= $currency ?></span>
<?php } else { ?>
<?php if ( $layoutType != 'classic' ) { ?>
<input class="input_text" data-parsley-errorscontainer="#amountError" name="itemprice" style="width:50px;textalign:left;" min="5" size="10" placeholder="XXX.XX" required
value="<?= $_SESSION['postdata']['amount'] ?>" />
<?php } else { ?>
<input id="amountInput" class="input_text" dataparsley-errors-container="#amountError" data-parsley-type="number"
name="itemprice" style="text-align:left;" min="5" type="text"
size="10" placeholder="XXX.XX" required value="<?=
$_SESSION['postdata']['amount'] ?>" />
<?php } ?> 
<select data-parsley-errorscontainer="#amountError" name="currency"
onchange="changeCurrency(this)" changeCurrency>
<?php
foreach ($currencyNotations as $key =>
$value) {
$selected = "";
if ( $_SESSION['currency_code'] == $key ){
$selected = ' selected="selected" ';}
echo "<option value='".$key."'
".$selected.">".$key."</option>";
}
?>
</select>
<?php } ?>
</td>
</tr>
<tr class="parsleyError">
<td id="amountError" colspan="2"></td>
</tr>
<tr>
<?php if ( $currency == 'CHF' ){ ?>
<td class="label">
Page 19/57
<label for="paymentType"><?= TEXT_PAIEMENT_METHOD
?></label>
</td>
<td>
<select id="paymentType"
onchange="updateFormAction(this)" name="paiementType">
<option value="creditcard" selected="selected"><?=
TEXT_CREDIT_CARD ?></option>
<option value="paypal" ><?= TEXT_PAYPAL
?></option>
<select>
</td>
<?php } else { ?>
<td>
<input type="hidden" name="paiementType"
value="paypal" />
</td>
<?php } ?>
</tr>
<tr>
<td colspan="3" style="text-align:center;"><br>
<button type='button' class="pure-button"
onclick="window.location.href='<?= $WEBURL ?>?action=number'"><?=
BUTTON_BACK ?></button>
<input type='submit' name="submitbutt" class="purebutton pure-button-primary" value="<?= BUTTON_PAY ?>"/>
</td>
</tr>
</table>
<input type="hidden" name="number" value="<?= $number ?>"
/>
</form>
<?php
}
} else {
?>
<h1 style="text-align:center;"><?= H1_PAYMENT ?></h1>
<form data-parsley-validate class="pure-form" method="post"
action="#"><br>
Page 20/57
If action parameter is not
defined or is not in the list
of action triggered before,
we display the input fields
<table>
<tr>
<td class="label">
<label for="num_part_1"><?= TEXT_SIP_ACCOUNT ?></label>
</td>
<td class="td_input" >
<select data-parsley-errors-container="#numberError1"
name="num_part_1" id="num_part_1" required>
<option value="" >---</option>
<?php
foreach ($pref1_pref2 as $id_pref => $prefixes){
if ( $prefixes[0]==$part1 && $prefixes[1]==$part2 && $found=="" ){
$found=$id_pref;
}
}
if ($found==""){
foreach ($pref1_pref2 as $id_pref => $prefixes){
if ($prefixes[0]==$part1){
$found=$id_pref;
}
}
}
foreach ($pref1_pref2 as $id_pref => $prefixes){
echo '<option value="'.$prefixes[0].'-'.$prefixes[1].'" ';
if ( $id_pref==$found ) {
echo "selected = \"selected\"";
}
echo '>'.$prefixes[0].'-'.$prefixes[1].'</option>'."\n";
}
?>
</select>
</td>
<td class="td_input" >
<?php if ( $layoutType != 'classic' ) { ?>
<input class="input_text" data-parsley-errorscontainer="#numberError2" style="width:55px;" name="num_part_2"
Page 21/57
for selecting the account to
credit.
Selection of the prefixes.
Selection of the last 4
digits.
type="number" data-parsley-length="[4, 4]" size="4" placeholder="XXXX"
value="<?= $part3 ?>" required/>
<?php } else { ?>
<input class="input_text" data-parsley-errorscontainer="#numberError2" data-parsley-type="number" data-parsleylength="[4, 4]" name="num_part_2" type="text" maxlength="4" size="5"
placeholder="XXXX" value="<?= $part3 ?>" required/>
<?php } ?>
</td>
</tr>
This is some hidden cells for
displaying error in input
cells.
<tr class="parsleyError">
<td></td>
<td id="numberError1"></td>
<td id="numberError2"></td>
</tr>
<tr>
<td colspan="3" style="text-align:center;"><br>
<input type="submit" name="submitbutt" class="purebutton pure-button-primary" value="<?= BUTTON_CONTINUE ?>"/>
</td>
</tr>
</table>
<input type="hidden" name="action" value="payment" />
<input type="hidden" name="itemname" value="Account crediting"
/>
<input type="hidden" name="itemQty" value="1" />
<input type="hidden" name="itemdesc" value="Credit your
Switzernet account with credit card or paypal." />
</form>
<?php } ?>
</div>
<?php if ( $layoutType != 'classic' ){ ?>
<footer>
<?php } else { ?>
<div id="footer_div">
Page 22/57
Button for validating the
form and continuing to last
page.
Footer with logos of the
available payment
methods.
<?php } ?>
<center>
<?php
if ( $layoutType != 'classic' ){
echo '<hr style="color: #eee;border: 0;width: 90%;height:
3px;background-color: #eee;">';
} else { ?>
<br>
<br>
<br>
<?php } ?>
<?php if ( $_SESSION['currency_code'] == 'CHF' ||
$_SESSION['action'] != 'payment' ){ ?>
<a href="https://www.postfinance.ch/pf/content/fr.html"
target="_blank"><img height="30" src="/public/060801web/images/logoPoste.gif" border="0"></a>  
<a href="http://www.mastercard.com/" target="_blank"><img
height="30" src='/public/060801-web/images/mastercard.gif'
border="0"></a>  
<a href="http://www.visa.com/" target="_blank"><img
height="30" src='/public/060801-web/images/visa.gif'
border="0"></a>  
<a href="https://www.paypal.com/fr/webapps/mpp/paypal-popup"
title="PayPal Comment Ca Marche"
onclick="javascript:window.open('https://www.paypal.com/fr/webapps/mpp
/paypal-popup','WIPaypal','toolbar=no, location=no, directories=no,
status=no, menubar=no, scrollbars=yes, resizable=yes, width=1060,
height=700'); return false;"><img height="30"
src="https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_37x2
3.jpg" border="0" alt="PayPal Logo" /></a>
<?php } else { ?>
<a href="https://www.paypal.com/fr/webapps/mpp/paypal-popup"
title="PayPal Comment Ca Marche"
onclick="javascript:window.open('https://www.paypal.com/fr/webapps/mpp
/paypal-popup','WIPaypal','toolbar=no, location=no, directories=no,
status=no, menubar=no, scrollbars=yes, resizable=yes, width=1060,
height=700'); return false;"><img style="width:290px;"
src="https://www.paypalobjects.com/webstatic/mktg/logocenter/logo_paypal_moyens_paiement_fr.jpg" border="0" alt="PayPal
Acceptance Mark" /></a>
<?php } ?>
Page 23/57
</center>
<?php if ( $layoutType != 'classic' ){ ?>
</footer>
<?php } else { ?>
</div>
<?php } ?>
</div>
</body>
</html>
End of the html
Function for getting the
prefixes from
<?php
function pref1_pref2(){
$connection =
mysql_connect(DB1_SERVER,DB1_SERVER_USERNAME,DB1_SERVER_PASSWORD,
TRUE);
mysql_select_db(DB1_DATABASE, $connection);
$prefs=array();
$sql = "SELECT id_prefix, prefix1, prefix2 FROM prefixes";
$req = mysql_query($sql) or die('Erreur SQL
!<br>'.$sql.'<br>'.mysql_error());
while($prefix = mysql_fetch_assoc($req)){
$prefs[$prefix["id_prefix"]] =
array(ereg_replace("^41","0",$prefix["prefix1"]),$prefix["prefix2"]);
}
mysql_close($connection);
return $prefs;
}
function layoutTypes(){
return array('classic', 'mobile', 'tablet');
}
function initLayoutType(){
// Safety check.
if (!class_exists('Mobile_Detect')) { return 'classic'; }
$detect = new Mobile_Detect;
$isMobile = $detect->isMobile();
$isTablet = $detect->isTablet();
Page 24/57
Function for detecting
mobile devices. This is
required for all displaying
differences added to the
html and CSS.
$layoutTypes = layoutTypes();
// Set the layout type.
if ( isset($_GET['layoutType']) ) {
$layoutType = $_GET['layoutType'];
} else {
if (empty($_SESSION['layoutType'])) {
$layoutType = ($isMobile ? ($isTablet ? 'tablet' : 'mobile') :
'classic');
} else {
$layoutType = $_SESSION['layoutType'];
}
}
// Fallback. If everything fails choose classic layout.
if ( !in_array($layoutType, $layoutTypes) ) { $layoutType =
'classic'; }
// Store the layout type for future use.
$_SESSION['layoutType'] = $layoutType;
return $layoutType;
}
?>
PayPal
Process PayPal payments
[paypalProcess.php]
CODE
COMMENT
<?php
Starting session and
including configuration
files and a PayPal class for
if(!isset($_SESSION)){session_start();}
Page 25/57
processing the payment
easier.
include_once("include/pay.config.php");
include_once("include/paypal.config.php");
include_once("include/paypal.class.php");
$paypalmode = ($PayPalMode=='sandbox') ? '.sandbox' : '';
$PaypalLocalCode = 'CH';
if ( isset( $defaultLocale[$PayPalCurrencyCode] ) ){
$PaypalLocalCode = $defaultLocale[$PayPalCurrencyCode];
}
if($_POST) //Post Data received from product list page.
{
$number = $_POST['number'];
if ( ! preg_match('/^41[0-9]{9}$/', $number) ){
die ("wrong number format $number");
}
$credit = "";
if ( isset($_POST['itemprice']) ){
$credit = str_replace(',', '.', $_POST['itemprice']);
if ( ! preg_match('/^[0-9]+(\.[0-9]{0,2})?$/', $credit ) ){
die ("wrong amount format $credit");
}
}
Page 26/57
Defining the string for the
PayPal URL to reach in case
of we are using the
sandbox account or the
live account.
The PayPal variable to
define the localization to
display.
The available localization
codes are in the
paypal.config.php file.
I data has been submitted
to this page with POST.
We get the VOIP number
to credit and verify the
format.
We get the amount the
customer wants to credit
on his account.
$ItemName
= "Credit compte"; //Item Name
$ItemPrice
= $credit; //Item Price
$ItemNumber
= $number; //Item Number
$ItemDesc
= "Switzernet account crediting with credit card or paypal."; //Item
Number
$ItemCustomDesc = "SIP_account:".$number;
$ItemQty
= 1; // Item Quantity
$ItemTotalPrice = ($ItemPrice*$ItemQty); //(Item Price x Quantity = Total) Get
total amount of product;
//Grand total including all tax, insurance, shipping cost and discount
$GrandTotal = ($ItemTotalPrice + $TotalTaxAmount + $HandalingCost + $InsuranceCost
+ $ShippinCost + $ShippinDiscount);
//Parameters for SetExpressCheckout, which will be sent to PayPal
$padata =
'&METHOD=SetExpressCheckout'.
'&RETURNURL='.urlencode($PayPalReturnURL).
'&CANCELURL='.urlencode($PayPalCancelURL).
'&PAYMENTREQUEST_0_PAYMENTACTION='.urlencode("SALE").
'&L_PAYMENTREQUEST_0_NAME0='.urlencode($ItemName).
'&L_PAYMENTREQUEST_0_NUMBER0='.urlencode($ItemNumber).
'&L_PAYMENTREQUEST_0_DESC0='.urlencode($ItemDesc).
'&L_PAYMENTREQUEST_0_AMT0='.urlencode($ItemPrice).
'&NOSHIPPING=1'. //set 1 to hide buyer's shipping address, in-case products
that does not require shipping
'&PAYMENTREQUEST_0_ITEMAMT='.urlencode($ItemTotalPrice).
'&PAYMENTREQUEST_0_TAXAMT='.urlencode($TotalTaxAmount).
'&PAYMENTREQUEST_0_SHIPPINGAMT='.urlencode($ShippinCost).
'&PAYMENTREQUEST_0_HANDLINGAMT='.urlencode($HandalingCost).
'&PAYMENTREQUEST_0_SHIPDISCAMT='.urlencode($ShippinDiscount).
'&PAYMENTREQUEST_0_INSURANCEAMT='.urlencode($InsuranceCost).
'&PAYMENTREQUEST_0_CUSTOM='.urlencode($ItemCustomDesc).
'&PAYMENTREQUEST_0_AMT='.urlencode($GrandTotal).
'&PAYMENTREQUEST_0_CURRENCYCODE='.urlencode($PayPalCurrencyCode).
Page 27/57
Main parameters we have
to set for account
crediting.
This is the part for
preparing the
SetExpressCheckout
method.
A full documentation of
the parameters can be
found on PayPal developer
website [link].
'&LOCALECODE='.$PaypalLocalCode . //PayPal pages to match the language on
your website.
'&LOGOIMG=https://slave.switzernet.com:8444/brandpane/logo-switzernet-com2.png'. //site logo
'&LANDINGPAGE=Billing'.
//Show crdit card
'&SOLUTIONTYPE=Sole'.
//Show crdit card
'&USERSELECTEDFUNDINGSOURCE=CreditCard'.
'&CARTBORDERCOLOR=6699FF'. //border color of cart
'&ALLOWNOTE=0';
############# set session variable we need later for
"DoExpressCheckoutPayment" #######
$_SESSION['ItemName']
= $ItemName; //Item Name
$_SESSION['ItemPrice']
= $ItemPrice; //Item Price
$_SESSION['ItemNumber']
= $ItemNumber; //Item Number
$_SESSION['ItemDesc']
= $ItemDesc; //Item Description
$_SESSION['ItemCustomDesc']
= $ItemCustomDesc; // Item Customer
Description
$_SESSION['ItemQty']
= $ItemQty; // Item Quantity
$_SESSION['ItemTotalPrice']
= $ItemTotalPrice;
$_SESSION['TotalTaxAmount']
= $TotalTaxAmount;
$_SESSION['HandalingCost']
= $HandalingCost;
$_SESSION['InsuranceCost']
= $InsuranceCost;
$_SESSION['ShippinDiscount']
= $ShippinDiscount;
$_SESSION['ShippinCost']
=
$ShippinCost;
$_SESSION['GrandTotal']
= $GrandTotal;
In the same time, we save
the data in the session.
Executing the
SetExpressCheckOut
method to obtain the
PayPal token.
If the PayPal answer is
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING"
success, we redirect the
== strtoupper($httpParsedResponseAr["ACK"])) {
$paypalurl ='https://www'.$paypalmode.'.paypal.com/cgi-bin/webscr?cmd=_express- user to PayPal with the
checkout&token='.$httpParsedResponseAr["TOKEN"].'';
received token in the URL.
$paypal= new MyPayPal();
$httpParsedResponseAr = $paypal->PPHttpPost('SetExpressCheckout', $padata,
$PayPalApiUsername, $PayPalApiPassword, $PayPalApiSignature, $PayPalMode);
header('Location: '.$paypalurl);
Page 28/57
Else we show the error
message.
} else {
echo '<div style="color:red"><b>Error :
</b>'.urldecode($httpParsedResponseAr["L_LONGMESSAGE0"]).'</div>';
echo '<pre>';
//print_r($httpParsedResponseAr);
echo '</pre>';
}
}
When the user confirmed
the payment, it used the
ReturnURL we set in the
SetExpressCheckout
method witch is the same
page. We receive a token
and a Payer ID of the
DoExpressCheckout
method.
if(isset($_GET["token"]) && isset($_GET["PayerID"]))
$token = $_GET["token"];
$payer_id = $_GET["PayerID"];
//get session variables
$ItemName
= $_SESSION['ItemName'];
$ItemPrice
= $_SESSION['ItemPrice'] ;
$ItemNumber
= $_SESSION['ItemNumber'];
$ItemDesc
= $_SESSION['ItemDesc'];
$ItemCustomDesc
= $_SESSION['ItemCustomDesc'];
$ItemQty
= $_SESSION['ItemQty'];
$ItemTotalPrice
= $_SESSION['ItemTotalPrice'];
$TotalTaxAmount
= $_SESSION['TotalTaxAmount'];
$HandalingCost
= $_SESSION['HandalingCost'];
$InsuranceCost
= $_SESSION['InsuranceCost'];
$ShippinDiscount
= $_SESSION['ShippinDiscount'];
$ShippinCost
= $_SESSION['ShippinCost']; $GrandTotal
$_SESSION['GrandTotal'];
$padata =
'&TOKEN='.urlencode($token).
'&PAYERID='.urlencode($payer_id).
'&PAYMENTREQUEST_0_PAYMENTACTION='.urlencode("SALE").
'&L_PAYMENTREQUEST_0_NAME0='.urlencode($ItemName).
'&L_PAYMENTREQUEST_0_NUMBER0='.urlencode($ItemNumber).
'&L_PAYMENTREQUEST_0_DESC0='.urlencode($ItemDesc).
'&L_PAYMENTREQUEST_0_AMT0='.urlencode($ItemPrice).
'&PAYMENTREQUEST_0_CUSTOM='.urlencode($ItemCustomDesc).
'&PAYMENTREQUEST_0_ITEMAMT='.urlencode($ItemTotalPrice).
Page 29/57
We haven’t received the
payment yet.
=
We also get all the session
variables.
Preparing the data for
DoExpressCheckout
method.
'&PAYMENTREQUEST_0_TAXAMT='.urlencode($TotalTaxAmount).
'&PAYMENTREQUEST_0_SHIPPINGAMT='.urlencode($ShippinCost).
'&PAYMENTREQUEST_0_HANDLINGAMT='.urlencode($HandalingCost).
'&PAYMENTREQUEST_0_SHIPDISCAMT='.urlencode($ShippinDiscount).
'&PAYMENTREQUEST_0_INSURANCEAMT='.urlencode($InsuranceCost).
'&PAYMENTREQUEST_0_AMT='.urlencode($GrandTotal).
'&PAYMENTREQUEST_0_CURRENCYCODE='.urlencode($PayPalCurrencyCode);
//We need to execute the "DoExpressCheckoutPayment" at this point to Receive
payment from user.
$paypal= new MyPayPal();
$httpParsedResponseAr = $paypal->PPHttpPost('DoExpressCheckoutPayment', $padata,
$PayPalApiUsername, $PayPalApiPassword, $PayPalApiSignature, $PayPalMode);
//Check if everything went ok..
if ( "SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) ||
"SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {
if('Completed' == $httpParsedResponseAr["PAYMENTINFO_0_PAYMENTSTATUS"]) {
header('Location: '. $ReturnURL ."?action=paymentok&tid=".
$httpParsedResponseAr["PAYMENTINFO_0_TRANSACTIONID"]);
} elseif('Pending' == $httpParsedResponseAr["PAYMENTINFO_0_PAYMENTSTATUS"]) {
header('Location: '. $ReturnURL ."?action=paymentpending&tid=".
$httpParsedResponseAr["PAYMENTINFO_0_TRANSACTIONID"]);
}
$padata =
'&TOKEN='.urlencode($token);
$paypal= new MyPayPal();
$httpParsedResponseAr = $paypal->PPHttpPost('GetExpressCheckoutDetails',
$padata, $PayPalApiUsername, $PayPalApiPassword, $PayPalApiSignature, $PayPalMode);
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING"
== strtoupper($httpParsedResponseAr["ACK"])) {
header('Location: ' . $ReturnURL . "?action=paymentok
&tid=".$httpParsedResponseAr["PAYMENTINFO_0_TRANSACTIONID"]);
Page 30/57
Executing the
DoExpressCheckout
method with the same
parameters.
If the DoExpressCheckout
method succeed …
And the status of payment
is Completed we redirect
the customer to the
corresponding page.
And the status of payment
is Pending we redirect the
customer to the
corresponding page.
We can also get some
more information with the
GetExpressCheckoutDetails
method.
} else {
header('Location: ' . $ReturnURL .
"?action=paymentfailed&tid=".$httpParsedResponseAr["PAYMENTINFO_0_TRANSACTIONID"]);
}
} else {
header('Location: '.$ReturnURL."?action=paymenterror&tid=" .
$httpParsedResponseAr["PAYMENTINFO_0_TRANSACTIONID"]);
}
}
?>
PayPal payment notifications and update payment on billing
[live.php]
CODE
COMMENT
<?php
SOAP login and
password.
$SOAP_user = 'xxxxxx';
$SOAP_password = 'xxxxxx';
$sandbox = FALSE;
include "PortaBillingSoapClient.php";
// Send an empty HTTP 200 OK response to acknowledge receipt of the
notification
header('HTTP/1.1 200 OK');
Page 31/57
A PHP library for
the SOAP
connection to
porta-billing.
When the page is
called, we send a
200 OK header to
PayPal to inform
we got the
payment
notification. This
$item_name
$item_number
$payment_status
$payment_amount
$payment_currency
$receiver_email
$payer_email
$transaction_id
$custom
=
=
=
=
=
=
=
=
=
$_POST['item_name1'];
$_POST['item_number1'];
$_POST['payment_status'];
$_POST['mc_gross'];
$_POST['mc_currency'];
$_POST['receiver_email'];
$_POST['payer_email'];
$_POST['txn_id'];
$_POST['custom'];
$mail_To
= "cash@switzernet.com";
$mail_From
= "PayPal_IPN@switzernet.com";
$mail_Footer = "\nRegards\n\n--\n\nThis is an automatic message.\n\nhost
".php_uname('n')."\nscript ".__FILE__."\n\n\nSwitzernet ©2014 - Nicolas
Bondier\n";
.
.
.
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
"\r\n";
$mail_Header .= 'Reply-To: '.$mail_To
"\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
"\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
"\r\n";
$mail_Subject = "PayPal new payment notification arrived";
$mail_Body
Some variables
for all the emails
that will be sent
to cash [at]
switzernet.com.
This part set up
variables when
testing in sandbox
mode.
if ( $sandbox == TRUE ){
$payment_currency = 'CHF';
$PayPalURL = "www.sandbox.paypal.com";
$mail_To
= "developer@domain.com";
.
way, PayPal will
not resend the
message.
We get the
required data
from PayPal to
process the
payment on
Portabilling.
= "Notification details.\n\n";
Page 32/57
We also send an
email with all the
data send by
PayPal for
verification.
foreach ($_POST as $key => $value) {
$mailreq .= "$key = $value\n";
$mail_Body .= "$key:$value\n";
}
$mail_Body
.= $mail_Footer;
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
} else {
$PayPalURL = "www.paypal.com";
}
$message_id_prefix = $transaction_id . '.' . $item_number;
// Build the required acknowledgement message out of the notification just
received
$req = 'cmd=_notify-validate';
$mailreq = "";
foreach ($_POST as $key => $value) {
notification NV pairs
$mailreq .= "$key = $value\n";
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// Loop through the
// Set up the acknowledgement request headers
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Host: ".$PayPalURL."\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Connection: close\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
Page 33/57
A unique message
id is generated.
We need to save
it for keeping a
thread in our
mailboxes.
We build the
acknowledgement
message with all
parameters sent
by PayPal.
The header for to
send to PayPal.
// Open a socket for the acknowledgement request
$fp = fsockopen('ssl://'.$PayPalURL, 443, $errno, $errstr, 30);
// Send the HTTP POST request back to PayPal for validation
fputs($fp, $header . $req);
while (!feof($fp)) {
// While not EOF
if (strcmp (chomp($res), "VERIFIED") == 0) {
VERIFIED - process notification
// Response contains
// Authentication protocol is complete - OK to process notification
contents
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: '.$mail_To
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
$mail_Subject = "PayPal new payment notification /
account:".$item_number." / transaction id:".$transaction_id." /
status:".$payment_status."";
$mail_Body
$mail_Body
= "A new transaction as been processed by paypal.\n";
.= "\n";
Page 34/57
The answer
message is posted
to PayPal server
through secured
connection with
all the parameters
we have received.
When posting, we
read the content
of the message
send by PayPal
until the end of
file of the socket.
If PayPal answers
VERIFIED, it
means the
received
parameters match
with a PayPal
payment for
which we
received a
notification.
We send an email
to @cash with the
transaction
details.
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
$mail_Body
.=
.=
.=
.=
.=
.=
.=
.=
.=
.=
.=
.=
.=
.=
"**********************************************\n";
"*
Transaction details
*\n";
"**********************************************\n";
"\n";
"item_name
: " . $item_name
. "\n";
"item_number
: " . $item_number
. "\n";
"payment_status
: " . $payment_status
. "\n";
"payment_amount
: " . $payment_amount
. "\n";
"payment_currency : " . $payment_currency
. "\n";
"receiver_email
: " . $receiver_email
. "\n";
"payer_email
: " . $payer_email
. "\n";
"transaction_id
: " . $transaction_id
. "\n";
"custom trx name : " . $custom
. "\n";
$mail_Footer;
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
file_put_contents("log/".$message_id_prefix.".log","step:transaction_auth
ok\n",FILE_APPEND);
// Possible processing steps for a payment include the following:
// Check that the payment_status is Completed
if ( $payment_status == 'Completed' ){
$ServiceAccount = new
PortaBillingSoapClient('https://slave.switzernet.com:8444', 'Admin',
'Account');
$session_id = $ServiceAccount->_login($SOAP_user, $SOAP_password);
$ServiceAccount->_setSessionId($session_id);
// Getting i_customer
$GetAccountInfoRequest = array( 'id' => $item_number );
$GetAccountInfoResponse = $ServiceAccount>get_account_info($GetAccountInfoRequest);
$i_customer = '';
Page 35/57
If the payment is
Completed,
according to the
initial submit from
PayPal, we
connect to
portabilling to the
SOAP account API
to search the
customer account
to update with
the payment.
file_put_contents("log/" . $message_id_prefix .
".log","step:payment_completed ok\n",FILE_APPEND);
if ( !isset($GetAccountInfoResponse->account_info) ){ // Account
does not exist
$mail_Subject = "[account_not_found] PayPal new payment
notification / account:".$item_number." / transaction id:".$transaction_id." /
status:".$payment_status."";
$mail_Body = "";
$mail_Body .= "The tansaction could not be done because the
account '".$item_number."' could not be found.\n\n";
$mail_Body .= "Please open or check the account '".$item_number."'
and manually add the payment.\n\n";
$mail_Body .= "Once the payment has been manually entered, please
answer this email with '[done] PayPal new ...'.\n\n";
$mail_Body .= $mail_Footer;
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: '.$mail_To
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.account_not_found@ipn.switzernet.com>' . "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'X-Priority: 1'
. "\r\n";
$mail_Header .= 'X-MSMail-Priority: High'
. "\r\n";
$mail_Header .= 'Importance: High'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
Page 36/57
If the account is
not found, we
send an email
replying the
precedent email,
informing the
account could not
be found.
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
file_put_contents("log/".$message_id_prefix.".log","step:account_exist
no\n",FILE_APPEND);
} else {
$i_customer = $GetAccountInfoResponse->account_info->i_customer;
$account_currency = $GetAccountInfoResponse->account_info>iso_4217;
Else, if the
account is found,
we get the ID of
the customer and
the currency.
file_put_contents("log/".$message_id_prefix.".log","step:account_exist
ok\n",FILE_APPEND);
if ( $payment_currency != $account_currency ){
file_put_contents("log/".$message_id_prefix.".log","step:currency_match
no\n",FILE_APPEND);
$mail_Subject = "[wrong_currency] PayPal new payment
notification / account:".$item_number." / transaction id:".$transaction_id." /
status:".$payment_status."";
$mail_Body = "";
$mail_Body .= "The tansaction could not be processed because the
payment currency '".$payment_currency."' is not the same as the
'".$item_number."' account's currency '".$account_currency."'.\n\n";
$mail_Body .= "Please convert and manually process the payment
to the customer account of voip account '".$item_number."'.\n\n";
Page 37/57
If the customer
currency does not
match the
currency of the
payment, we send
an email
informing of this
and do not
process the
payment.
$mail_Body .= "Once the payment has been manually made, please
answer this email with '[done] PayPal new ...'.\n\n";
$mail_Body .= $mail_Footer;
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: '.$mail_To
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.wrong_currency@ipn.switzernet.com>' . "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
} else {
file_put_contents("log/".$message_id_prefix.".log","step:currency_match
ok\n",FILE_APPEND);
$ServiceCustomer = new
PortaBillingSoapClient('https://slave.switzernet.com:8444', 'Admin',
'Customer');
$session_id = $ServiceCustomer->_login($SOAP_user,
$SOAP_password);
$ServiceCustomer->_setSessionId($session_id);
$MakeCustomerTransactionRequest = array(
'i_customer'
=> $i_customer,
'visible_comment'
=> 'paiement paypal',
'internal_comment'
=> 'paiement paypal',
'action'
=> 'Manual payment',
Page 38/57
If currencies
match, we
prepare a
payment request
on portabilling on
the SOAP
customer API.
'amount'
'suppress_notification'
'transaction_id'
'h323_conf_id'
=>
=>
=>
=>
$payment_amount,
0,
$transaction_id,
''
);
try{ // do the transaction
$MakeCustomerTransactionResponse = $ServiceCustomer>make_transaction($MakeCustomerTransactionRequest);
file_put_contents("log/".$message_id_prefix.".log","step:make_transaction
ok\n",FILE_APPEND);
$mail_Subject = "[done] PayPal new payment notification /
account:".$item_number." / transaction id:".$transaction_id." /
status:".$payment_status."";
$mail_Body = "";
$mail_Body .= "A payment of ".$payment_amount."
".$payment_currency." has been processed on account '".$item_number."'\n\n";
$mail_Body .= "YOU HAVE NOTHING TO DO\n\n";
$mail_Body .= "Transaction result :\n";
$mail_Body .= "amount
:".$payment_amount."\n";
$mail_Body .= "new balace :".$MakeCustomerTransactionResponse>balance."\n";
$mail_Body .= "id of cdr :".$MakeCustomerTransactionResponse>i_xdr . "\n";
$mail_Body .= $mail_Footer;
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: '.$mail_To
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.done@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
Page 39/57
To process the
payment, we use
the “try { . . . }
catch { . . . }”
method to avoid
the PHP script to
exit on an error.
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
} catch (SoapFault $fault) {
file_put_contents("log/".$message_id_prefix.".log",
"step:make_transaction failed\n",FILE_APPEND);
$mail_Subject = "[payment_error] PayPal new payment
notification / account:".$item_number." / transaction id:".$transaction_id." /
status:".$payment_status."";
$mail_Body = "";
$mail_Body .= "An error occured during the payment on customer
account on porta-billing\n\n";
$mail_Body .= "SOAP Fault: (faultcode: {$fault->faultcode},
faultstring: {$fault->faultstring})";
$mail_Body .= $mail_Footer;
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: '.$mail_To
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.payment_error@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'X-Priority: 1'
. "\r\n";
$mail_Header .= 'X-MSMail-Priority: High'
. "\r\n";
Page 40/57
If an error
happen, we send
an email to cash
for informing.
$mail_Header .= 'Importance: High'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
}
Logout from the
SOAP customer
API.
Logout from the
SOAP account
API.
$ServiceCustomer->_logout();
}
}
$ServiceAccount->_logout();
}
} else if (strcmp ($res, "INVALID") == 0) {
$mail_From
= "IPN@switzernet.com";
$mail_Subject = "INVALID IPN";
$mail_Header = 'From: ' . $mail_From . "\r\n" .
'Reply-To: ' . $mail_To. "\r\n" .
'X-Mailer: PHP/' . phpversion();
$mail_Body
= $req;
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
If PayPal return
INVALID to our
script, we send an
email with the
information to
@cash.
}
}
function chomp($string){
return trim(preg_replace('/\s+/', ' ', $string));
}
?>
Page 41/57
Function for
deleting bad end
of line.
PostFinance
Process Postfinance payments
[postfinanceProcess.php]
CODE
COMMENT
<?php
Setting language
and locales
correspondences
for PostFinance
payment page.
if(!isset($_SESSION)){session_start();}
$locales = array('FR' => 'fr_FR',
'EN' => 'en_EN',
'DE' => 'de_DE'
);
if ( ! isset( $_SESSION['language']['code'] ) ){
$_SESSION['language']['code'] = 'FR';
}
if ( isset( $_GET['language'] ) && isset( $locales[ $_GET['language'] ] ) ){
$_SESSION['language']['code'] = $_GET['language'];
}
Verifying the
number format.
$number = $_POST['number'];
if ( ! preg_match('/^41[0-9]{9}$/', $number) ){
die ("wrong number format $number");
}
$credit = "";
if ( isset($_POST['itemprice']) ){
$credit = str_replace(',', '.', $_POST['itemprice']);
if ( ! preg_match('/^[0-9]+(\.[0-9]{0,2})?$/', $credit ) ){
Page 42/57
Getting the
amount the
customer want
die ("wrong amount format $credit");
to credit on his
account.
}
}
if ( isset( $_POST['paiementType'] ) && $_POST['paiementType'] == "creditcard"
){
$orderTotal = $credit;
$params = array('orderID', 'amount', 'currency', 'PSPID', 'Operation',
'logo', 'language', 'paramplus', 'SHASIGN');
usort($params, "cmp");
$hashSeed = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// post account informations
$data['PSPID'] = "xxxxxxxxxxxxxxxxxxxx";
// payment informations
$data['orderID'] = htmlentities("VOIP-" . convert_to_0XX_XXX_XXXX($number) );
$data['amount'] = (int)($orderTotal*100. ); // Format the number in integer
after being mutliplied by 100 to fit to e-pay requirements
$data['currency'] = "CHF";
$data['Operation'] = "SAL";
// view informations
$data['language'] = $locales[ $_SESSION['language']['code'] ];
$data['logo'] = "https://www.intarnetinc.com/images/switzernet.gif";
$data['paramplus'] = "numeroSIP=".convert_to_0XX_XXX_XXXX($number);
$data['TP'] = "http://switzernet.com/public/140819epay/postfinanceTemplate.php";
$request = "";
// Create the signature
foreach ($params as $i => $p){
if (isset($data[$p]))
Page 43/57
We prepare the
parameters to
post to
PostFinance.
To permit to
PostFinance to
verify the data,
we create a
string with all
defined
parameters
under the
format defined
in PostFinance
documentation.
It is a string of
key=value pairs
separated with
the SHA-IN
defined in the
PostFinance
account. Keys
must always be
in uppercase.
$request .= strtoupper($p)."=".$data[$p] . $hashSeed;
}
$data['SHASIGN'] = strtoupper(sha1($request));
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title></title>
<script type="text/javascript">
function postFinancePost(){
var form=document.getElementById("postfinanceForm");
form.submit();
}
window.onload = function() {
postFinancePost();
};
</script>
</head>
<body>
<FORM id="postfinanceForm" METHOD=post ACTION="https://epayment.postfinance.ch/ncol/prod/orderstandard.asp">
<?php
foreach ($params as $i => $p){
if (isset($data[$p])){
echo "<INPUT TYPE=hidden name=$p value=\"$data[$p]\">\n";
}
}
?>
<br/>
<center>
<INPUT TYPE=hidden value="ACCEPT">
</center>
</FORM>
</body>
</html>
Page 44/57
The string must
then be hashed.
It is the field to
post called
SHASIGN.
We create a
form with our
data and tell the
browser to
submit it to
PostFinance.
<?php
function convert_to_0XX_XXX_XXXX($number){
$number = ereg_replace("[^0-9]", "", $number);
if (ereg('^41[0-9]{9}$',$number)){
$number=substr_replace(substr_replace(ereg_replace("^41","0",$number),"",3,0),"-",7,0);
return $number;
} elseif ( ereg('^0[0-9]{9}$',$number) ) {
$number=substr_replace(substr_replace($number,"-",3,0),"-",7,0);
return $number;
} else {
return FALSE;
}
}
Function to
convert a phone
number to 0XXXXX-XXXX.
?>
Postfinance payment notifications and update payment in portabilling
[index.php]
CODE
COMMENT
<?php
SOAP user and password.
$SOAP_user = 'xxxxxxx';
$SOAP_password = 'xxxxxxxxxxxxxxxxxxxxxx';
$postFinanceSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
Page 45/57
Postfinance SHA-OUT
defined in PostFinance
interface.
A PHP library for the SOAP
connection to portabilling.
include "PortaBillingSoapClient.php";
Test mode is disabled.
$test = FALSE;
$mail_To
$mail_From
= "cash@switzernet.com";
= "PostFinance_IPN@switzernet.com";
Some variables for all the
emails that will be sent to
cash [at] switzernet.com.
$mail_Footer = "\nRegards\n\n--\n\nThis is an automatic
message.\n\nhost ".php_uname('n')."\nscript
".__FILE__."\n\n\nSwitzernet ©2014 - Nicolas Bondier\n";
if ( $test == TRUE ){
$mail_To
= "developer@domain.com";
$postFinanceSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$mail_From
= "TEST_PostFinance_IPN@switzernet.com";
}
$message_id_prefix = time() . '-' . md5('postfinance-notification' .
$mail_To);
if ( isset($_POST['SHASIGN']) && $_POST['SHASIGN'] ==
ogone_hash_parameters_in( $_POST, $postFinanceSecret ) ){
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
Page 46/57
This part set up variables in
testing mode.
Secret may not be the same
as we use the test account
of PostFinance.
A unique message id is
generated. We need to
save it for keeping a thread
in our mailboxes.
If the SHASIGN received by
PostFinance is the same as
the one we calculated in
the
ogone_hash_parameters_in
function, it means the
payment notification is
valid.
We send an email to @cash
with the received request.
$mail_Subject = "Postfinance new payment notification /
PAYID:".$_POST['PAYID']." / orderID:".$_POST['orderID']." /
STATUS:".$_POST['STATUS']."";
$mail_Body
= "";
$mail_Body
.= "RECEIVED PARAMETER
:\n".print_r($_REQUEST,TRUE)."\n";
$mail_Body
.= $mail_Footer;
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
if ( $_POST['STATUS'] == '9' ){
$ServiceAccount = new
PortaBillingSoapClient('https://slave.switzernet.com:8444', 'Admin',
'Account');
$session_id = $ServiceAccount->_login($SOAP_user, $SOAP_password);
$ServiceAccount->_setSessionId($session_id);
// Getting i_customer
$GetAccountInfoRequest = array( 'id' =>
format_account($_POST['numeroSIP']) );
$GetAccountInfoResponse = $ServiceAccount>get_account_info($GetAccountInfoRequest);
if ( !isset($GetAccountInfoResponse->account_info) ){ // Account
does not exist
$mail_Subject = "[account_not_found] Postfinance new payment
notification / PAYID:".$_POST['PAYID']." /
orderID:".$_POST['orderID']." / STATUS:".$_POST['STATUS']."";
$mail_Body = "";
$mail_Body .= "The tansaction could not be done because the
account '".$_POST['numeroSIP']."' could not be found.\n\n";
$mail_Body .= "Please open or check the account
'".$_POST['numeroSIP']."' and manually add the payment.\n\n";
$mail_Body .= "Once the payment has been manually entered,
please answer this email with '[done] PostFinance new ...'.\n\n";
$mail_Body .= $mail_Footer;
$mail_Header = "";
Page 47/57
In the PostFinance
submitted data, the status
9 means the payment is
accepted.
In the case we connect to
portabilling in order to find
the account of the
customer who paid.
If we cannot find the
account, an email is send to
@cash informing the
account could not be
found.
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.account_not_found@ipn.switzernet.com>' . "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'X-Priority: 1'
. "\r\n";
$mail_Header .= 'X-MSMail-Priority: High'
. "\r\n";
$mail_Header .= 'Importance: High'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
} else {
$i_customer = $GetAccountInfoResponse->account_info->i_customer;
$account_currency = $GetAccountInfoResponse->account_info>iso_4217;
if ( $_POST['currency'] != $account_currency ){
$mail_Subject = "[account_not_found] Postfinance new payment
notification / PAYID:".$_POST['PAYID']." /
orderID:".$_POST['orderID']." / STATUS:".$_POST['STATUS']."";
$mail_Body = "";
$mail_Body .= "The tansaction could not be processed because
the payment currency '".$_POST['numeroSIP']."' is not the same as the
'".$_POST['numeroSIP']."' account's currency
'".$account_currency."'.\n\n";
$mail_Body .= "Please convert and manually process the payment
to the customer account of voip account
'".$_POST['numeroSIP']."'.\n\n";
Page 48/57
Else, we search for the ID of
customer and currency of
the account before entering
the payment.
If the currencies do not
match, we inform by
sending an email to @cash.
$mail_Body .= "Once the payment has been manually made, please
answer this email with '[done] PostFinance new ...'.\n\n";
$mail_Body .= $mail_Footer;
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.wrong_currency@ipn.switzernet.com>' . "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
} else {
$ServiceCustomer = new
PortaBillingSoapClient('https://slave.switzernet.com:8444', 'Admin',
'Customer');
$session_id = $ServiceCustomer->_login($SOAP_user,
$SOAP_password);
$ServiceCustomer->_setSessionId($session_id);
$MakeCustomerTransactionRequest = array(
'i_customer'
=> $i_customer,
'visible_comment'
=> 'e-paiement',
'internal_comment'
=> 'e-paiement postfinance',
'action'
=> 'Manual payment',
'amount'
=> $_POST['amount'],
'suppress_notification' => 0,
'transaction_id'
=> $_POST['PAYID'],
'h323_conf_id'
=> ''
);
Page 49/57
If the currencies match, we
connect to the customer
service of the SOAP API and
prepare the payment
request.
try{ // do the transaction
$MakeCustomerTransactionResponse = $ServiceCustomer>make_transaction($MakeCustomerTransactionRequest);
$mail_Subject = "[done] Postfinance new payment notification
/ PAYID:".$_POST['PAYID']." / orderID:".$_POST['orderID']." /
STATUS:".$_POST['STATUS']."";
$mail_Body = "";
$mail_Body .= "A payment of ".$_POST['amount']."
".$_POST['currency']." has been processed on account
'".$_POST['numeroSIP']."'\n\n";
$mail_Body .= "YOU HAVE NOTHING TO DO\n\n";
$mail_Body .= "Transaction result :\n";
$mail_Body .= "amount
:".$$_POST['amount']."\n";
$mail_Body .= "new balace
:".$MakeCustomerTransactionResponse->balance."\n";
$mail_Body .= "id of cdr
:".$MakeCustomerTransactionResponse->i_xdr."\n";
$mail_Body .= $mail_Footer;
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.done@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
Page 50/57
If the transaction executes
without exception, we reply
to the first email with
[done] to confirm the
payment has been correctly
entered.
Else the error message is
sent to @cash.
} catch (SoapFault $fault) {
$mail_Subject = "[payment_error] Postfinance new payment
notification / PAYID:".$_POST['PAYID']." /
orderID:".$_POST['orderID']." / STATUS:".$_POST['STATUS']."";
$mail_Body = "";
$mail_Body .= "An error occured during the payment on
customer account on porta-billing\n\n";
$mail_Body .= "SOAP Fault: (faultcode: {$fault->faultcode},
faultstring: {$fault->faultstring})";
$mail_Body .= $mail_Footer;
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.payment_error@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'X-Priority: 1'
. "\r\n";
$mail_Header .= 'X-MSMail-Priority: High'
. "\r\n";
$mail_Header .= 'Importance: High'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
}
$ServiceCustomer->_logout();
}
Page 51/57
}
$ServiceAccount->_logout();
} elseif ( $_POST['STATUS'] == '1' ) {
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.unknown_status@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
$mail_Subject = "[payment cancelled] Postfinance new payment
notification / PAYID:".$_POST['PAYID']." /
orderID:".$_POST['orderID']." / STATUS:".$_POST['STATUS']."";
$mail_Body
= "The payment has been cancelled by customer\n\n";
$mail_Body
.= "YOU HAVE NOTHING TO DO\n\n";
$mail_Body
.= "RECEIVED PARAMETER
:\n".print_r($_REQUEST,TRUE)."\n";
$mail_Body
.= $mail_Footer;
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
} else {
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'.unknown_status@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'References: <' . $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
Page 52/57
Payment cancellation
notice when the status is 1:
the payment has been
cancelled by the payer.
For other statuses, we send
an [unknown status]
notification in reply to
@cash.
$mail_Header .= 'In-Reply-To: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
$mail_Subject = "[unknown status] Postfinance new payment
notification / PAYID:".$_POST['PAYID']." /
orderID:".$_POST['orderID']." / STATUS:".$_POST['STATUS']."";
$mail_Body
= "";
$mail_Body
.= "RECEIVED PARAMETER
:\n".print_r($_REQUEST,TRUE)."\n";
$mail_Body
.= $mail_Footer;
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
}
} else {
$mail_Header = "";
$mail_Header .= 'From: ' . $mail_From
. "\r\n";
$mail_Header .= 'Reply-To: cash@switzernet.com'
. "\r\n";
$mail_Header .= 'Message-Id: <'. $message_id_prefix .
'@ipn.switzernet.com>'
. "\r\n";
$mail_Header .= 'Content-type: text/plain; charset=utf-8'
. "\r\n";
$mail_Header .= 'X-Mailer: PHP/' . phpversion()
. "\r\n";
$mail_Subject = "Postfinance INVALID payment notification";
$mail_Body
= "";
$mail_Body
.= "RECEIVED PARAMETER :\n".print_r($_REQUEST,TRUE)."\n
Calculated hash : ".ogone_hash_parameters_in( $_POST,
$postFinanceSecret );
$mail_Body
.= $mail_Footer;
mail($mail_To, $mail_Subject, $mail_Body, $mail_Header);
}
Page 53/57
If the calculated hash does
not correspond to the one
sent by PostFinance, we
send an email will all the
data to @cash.
function ogone_hash_parameters_in($parameters = array(), $secretkey =
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') {
$str = '';
$param = array();
/* On s'assure que toutes les clés sont en majuscules et rangées par
ordre alphabétique*/
$txt = '';
if ( !empty($parameters) ) {
foreach ($parameters as $i => $j) {
$param[strtoupper($i)] = $j;
}
}
/* Trier par ordre alphabetique */
ksort($param);
if ( !empty($param) ) {
foreach($param as $i=> $j) {
if ( $j != "" && valid_param(strtoupper($i)) ){
$str .= $i. '=' . $j. $secretkey;
$txt .= $i. '=' . $j."\n";
}
}
}
$str = utf8_encode ($str);
return strtoupper(sha1($str));
}
function format_account( $id ){
$id = preg_replace('/[^0-9,]|,[0-9]*$/','',$id);
$id = preg_replace('/^0([0-9]{9})$/', "41$1", $id);
return $id;
}
function valid_param ($key
$sha_out_param = array(
'AAVADDRESS'
'AAVCHECK'
'AAVMAIL'
The function for calculating
the hash from received
parameters from
PostFinance.
The key is a hashed string
of value/pair separated by
the SHA-OUT secret key
defined in e-payment
PostFinance account.
Each keys must be in
uppercase and all
value/pair key must be in
the alphabetical order.
A simple function of
formatting account id.
The list of valid parameters
to include in the hash. The
list comes from the
following document [pdf].
= ""){
=> 1,
=> 1,
=> 1,
Page 54/57
'AAVNAME'
'AAVPHONE'
'AAVZIP'
'ACCEPTANCE'
'ALIAS'
'AMOUNT'
'BIC'
'BIN'
'BRAND'
'CARDNO'
'CCCTY'
'CN'
'COMPLUS'
'CREATION_STATUS'
'CURRENCY'
'CVCCHECK'
'DCC_COMMPERCENTAGE'
'DCC_CONVAMOUNT'
'DCC_CONVCCY'
'DCC_EXCHRATE'
'DCC_EXCHRATESOURCE'
'DCC_EXCHRATETS'
'DCC_INDICATOR'
'DCC_MARGINPERCENTAGE'
'DCC_VALIDHOURS'
'DIGESTCARDNO'
'ECI'
'ED'
'ENCCARDNO'
'FXAMOUNT'
'FXCURRENCY'
'IBAN'
'IP'
'IPCTY'
'NBREMAILUSAGE'
'NBRIPUSAGE'
'NBRIPUSAGE_ALLTX'
'NBRUSAGE'
'NCERROR'
'NCERRORCARDNO'
'NCERRORCN'
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
Page 55/57
'NCERRORCVC'
'NCERRORED'
'ORDERID'
'PAYID'
'PM'
'SCO_CATEGORY'
'SCORING'
'STATUS'
'SUBBRAND'
'SUBSCRIPTION_ID'
'TRXDATE'
'VC'
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
);
if ( $sha_out_param[$key] ){
return true;
}
return false;
}
?>
Page 56/57
Links
Ce document : http://switzernet.com/3/public/140923-payments/
Online payment page : http://pay.switzernet.com
Switzernet customer interface : https://account.switzernet.com/
*
*
*
Copyright © 2016 by Switzernet
Page 57/57
Download