The PayPal Adaptive Payments API is used to transfer money from a sender’s PayPal account to one or more than one PayPal receiver PayPal accounts. You can use PayPal Adaptive Payments to make simple payments, chained payments and parallels payments.

In this tutorial, we are going to demonstrate how we use PayPal adaptive apartment to make parallel payment.

Parallel payments are useful in cases when a buyer intends to make a single payment for items from multiple sellers.

Here we are demonstrating a trip planning website where a customer, can book a flight, hotel, and car, where total amount will send to the three different merchant’s PayPal business account.

 


Watch the live demo or download code from the link given below

paypal-parallel payments-using php


Note : PayPal offers sandbox account for development and testing purpose. Here we are using Sandbox for the demo, so if you would like to test our demo you can use your PayPal sandbox credentials.

 

Project Integration

For configuration of adaptivepayments-sdk-php, add your account credentials in the configuration.php.

You can find this file in downloaded project “root folder”.

// Demo Signature Credential
"acct1.UserName" => "Demo-facilitator_api1.outlook.com",
"acct1.Password" => "PDRdd9FTWWU6FDBNKY",
"acct1.Signature" => "ANGx9dddfhOMduIxwcbkuUqPMh-9L15RAO6JJD8BDCZSxcx8nbBWeDOIbzW1",

Then you will be ready to run the project. You can also refer the  PHPProjectInstall.pdf  file given in the download code folder.

Parallel Payments Overview

PayPal Parallel payments enable a single buyer to pay multiple merchants in a single checkout session. A parallel payment is a payment from a sender that is then splitted directly among two to six different receivers.

Here we are showing an example which is a trip planning website, where customer, can book a flight, hotel and car together and pay the total amount in one checkout session. Using parallel payments that amount will split into three parts and all three merchants get their respected amounts as well.

paypal-parallel payments-and-adpative payment-using-php

 


Tutorial Scripts in detail

Below are the details of the code used in this tutorial with proper explanation.

Index.php

Index.php contain code for showing Facility information.



<html>
<head>
<title>Paypal Parallel Payments Using PHP</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="css/loadding.css">
<link rel="stylesheet" type="text/css" href="css/popup-style.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
<div id="main">
<center><h1>Paypal Parallel Payments Using PHP</h1></center>

<div id="container">
<center><h2>Book Together and Save Money and Time</h2></center>
<hr/>
<table id="results" >
<tbody>
<tr>
<td style=" padding-bottom: 20px;">
<b><p style="color: rgb(77, 125, 179);">Flight = $300<br></p></b>

</td >
<td style=" padding-bottom: 20px;">
<b><p style="color: rgb(77, 125, 179);">Hotel = $200</p></b>
</td >
<td style=" padding-bottom: 20px;">
<b><p style="color: rgb(77, 125, 179);">Cab = $100<br></p></b>
</td>
</tr>
</tbody>
</table>
<center><h3>Select Your Plan</h3></center>
<form action="process.php" name="form" method="POST">
<div id="item-container">
<input type="radio" name="booking" value="f" checked="true">Flight Only( $300 )<br>
<input type="radio" name="booking" value="h">Hotel Only( $200 )<br>
<input type="radio" name="booking" value="c">Car Only( $100 )<br>
<input type="radio" name="booking" value="fh">Flight + Hotel ( $500 )<br>
<input type="radio" name="booking" value="fc">Flight + Car ( $400 )<br>
<input type="radio" name="booking" value="hc">Hotel + Car ( $300 )<br>
<input type="radio" name="booking" value="fhc">Flight + Hotel + Car ( $585 )<br>
</div>
<div id="item-container">
<div class="f" id="merchants-details"><p id="title-text">Book Flight<br> and <br> Pay Direct to airline</p><i class="fa fa-plane fa-4x"></i></div>
<div class="h" id="merchants-details"><p id="title-text">Book Hotel<br> and <br> Pay to Company</p><i class="fa fa-bed fa-3x"></i></div>
<div class="c"id="merchants-details"><p id="title-text">Book Car<br> and <br> Pay Direct to Owner</p><i class="fa fa-car fa-3x"></i></div>
</div>
<input type="submit" id="tatalamount" value="Pay Now : $000"/>
</form>

</div>
<img id="paypal_logo" src="images/secure-paypal-logo.jpg">
</div>
<div id="pop2" class="simplePopup">
<div id="loader">
<div id="circularG">
<div id="circularG_1" class="circularG">
</div>
<div id="circularG_2" class="circularG">
</div>
<div id="circularG_3" class="circularG">
</div>
<div id="circularG_4" class="circularG">
</div>
<div id="circularG_5" class="circularG">
</div>
<div id="circularG_6" class="circularG">
</div>
<div id="circularG_7" class="circularG">
</div>
<div id="circularG_8" class="circularG">
</div>
</div>
</div>
</div>
<script src="js/jquery.simplePopup.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('input#tatalamount').click(function() {
$('#pop2').simplePopup();
});
$("div.f i").css('color', '#FFBC00');
$("div.f").css('border', '3px solid rgb(255, 188, 0)');
$("div.f").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$('input#tatalamount').val('Pay Now : $300');
});
// get list of radio buttons with name 'size'
var sz = document.forms['form'].elements['booking'];
// loop through list
for (var i = 0, len = sz.length; i < len; i++) {
sz[i].onclick = function() {
rdata = this.value;
$("div.f i").css('color', '');
$("div.f").css('box-shadow', '');
$("div.h i").css('color', '');
$("div.h").css('box-shadow', '');
$("div.c i").css('color', '');
$("div.c").css('box-shadow', '');
$("div.f").css('border', '');
$("div.h").css('border', '');
$("div.c").css('border', '');
if (rdata === 'f') {
$("div.f i").css('color', '#FFBC00');
$("div.f").css('border', '3px solid rgb(255, 188, 0)');
$("div.f").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$('input#tatalamount').val('Pay Now : $300');
}
if (rdata === 'h') {
$("div.h i").css('color', '#FFBC00');
$("div.h").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.h").css('border', '3px solid rgb(255, 188, 0)');
$('input#tatalamount').val('Pay Now : $200');
}
if (rdata === 'c') {
$("div.c i").css('color', '#FFBC00');
$("div.c").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.c").css('border', '3px solid rgb(255, 188, 0)');
$('input#tatalamount').val('Pay Now : $100');
}
if (rdata === 'fh') {
$("div.f i").css('color', '#FFBC00');
$("div.f").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.f").css('border', '3px solid rgb(255, 188, 0)');
$("div.h i").css('color', '#FFBC00');
$("div.h").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.h").css('border', '3px solid rgb(255, 188, 0)');
$('input#tatalamount').val('Pay Now : $500');
}
if (rdata === 'fc') {
$("div.f i").css('color', '#FFBC00');
$("div.f").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.f").css('border', '3px solid rgb(255, 188, 0)');
$("div.c i").css('color', '#FFBC00');
$("div.c").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.c").css('border', '3px solid rgb(255, 188, 0)');
$('input#tatalamount').val('Pay Now : $400');
}
if (rdata === 'hc') {
$("div.h i").css('color', '#FFBC00');
$("div.h").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.h").css('border', '3px solid rgb(255, 188, 0)');
$("div.c i").css('color', '#FFBC00');
$("div.c").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.c").css('border', '3px solid rgb(255, 188, 0)');
$('input#tatalamount').val('Pay Now : $300');
}
if (rdata === 'fhc') {
$("div.f i").css('color', '#FFBC00');
$("div.f").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.f").css('border', '3px solid rgb(255, 188, 0)');
$("div.h i").css('color', '#FFBC00');
$("div.h").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.h").css('border', '3px solid rgb(255, 188, 0)');
$("div.c i").css('color', '#FFBC00');
$("div.c").css('box-shadow', '0px 5px 17px 1px #99A3AD, 0px 0px 40px #EEEEEE');
$("div.c").css('border', '3px solid rgb(255, 188, 0)');
$('input#tatalamount').val('Pay Now : $585');
}
};
}
</script>
</body>
</html>

 

Proccess.php

This file contains code to process Adaptive amount to PayPal.



<?php
session_start();
require_once('../PPBootStrap.php');
require_once('../Common/Constants.php');
define("DEFAULT_SELECT", "- Select -");
$returnUrl = "https://www.formget.com/tutorial/paypal-adaptive-payment/parallel/success.php";
$cancelUrl = "https://www.formget.com/tutorial/paypal-adaptive-payment/parallel/index.php";
$memo = "Adaptive Payment";
$actionType = "PAY";
$currencyCode = "USD";

if ($_POST['booking'] == 'f') {
$receiverEmail = array("airline@outlook.com");
$receiverAmount = array("300.00");
$primaryReceiver = array("false");
$_SESSION['facilty_provider'] = array("AirGo Airline's Test Store");
} elseif ($_POST['booking'] == 'h') {
$receiverEmail = array("hotel@outlook.com");
$receiverAmount = array("200.00");
$primaryReceiver = array("false");
$_SESSION['facilty_provider'] = array("Hotel TheCompany's Test Store");
} elseif ($_POST['booking'] == 'c') {
$receiverEmail = array("car-merchants@outlook.com");
$receiverAmount = array("100.00");
$primaryReceiver = array("false");
$_SESSION['facilty_provider'] = array("MyCar Car Company's Test Store");
} elseif ($_POST['booking'] == 'fh') {
$receiverEmail = array("airline@outlook.com", "hotel@outlook.com");
$receiverAmount = array("300.00", "200.00");
$primaryReceiver = array("false", "false");
$_SESSION['facilty_provider'] = array("AirGo Airline's Test Store", "Hotel TheCompany's Test Store");
} elseif ($_POST['booking'] == 'fc') {
$receiverEmail = array("airline@outlook.com", "car-merchants@outlook.com");
$receiverAmount = array("300.00", "100.00");
$primaryReceiver = array("false", "false");
$_SESSION['facilty_provider'] = array("AirGo Airline's Test Store", "MyCar Car Company's Test Store");
} elseif ($_POST['booking'] == 'hc') {
$receiverEmail = array("hotel@outlook.com", "car-merchants@outlook.com");
$receiverAmount = array("200.00", "100.00");
$primaryReceiver = array("false", "false");
$_SESSION['facilty_provider'] = array("Hotel TheCompany's Test Store", "MyCar Car Company's Test Store");
} elseif ($_POST['booking'] == 'fhc') {
$receiverEmail = array("airline@outlook.com", "hotel@outlook.com", "car-merchants@outlook.com");
$receiverAmount = array("295.00", "195.00", "95.00");
$primaryReceiver = array("false", "false", "false");
$_SESSION['facilty_provider'] = array("AirGo Airline's Test Store", "Hotel TheCompany's Test Store", "MyCar Car Company's Test Store");
} else {
$receiverEmail = array("airline@outlook.com");
$receiverAmount = array("300.00");
$primaryReceiver = array("false");
$_SESSION['facilty_provider'] = array("AirGo Airline's Test Store");
}
if (isset($receiverEmail)) {
$receiver = array();
/*
* A receiver's email address
*/
for ($i = 0; $i < count($receiverEmail); $i++) {
$receiver[$i] = new Receiver();
$receiver[$i]->email = $receiverEmail[$i];
/*
* Amount to be credited to the receiver's account
*/
$receiver[$i]->amount = $receiverAmount[$i];
/*
* Set to true to indicate a chained payment; only one receiver can be a primary receiver. Omit this field, or set it to false for simple and parallel payments.
*/
$receiver[$i]->primary = $primaryReceiver[$i];
}
$receiverList = new ReceiverList($receiver);
}
$payRequest = new PayRequest(new RequestEnvelope("en_US"), $actionType, $cancelUrl, $currencyCode, $receiverList, $returnUrl);
// Add optional params
if ($memo != "") {
$payRequest->memo = $memo;
}
/*
* ## Creating service wrapper object
Creating service wrapper object to make API call and loading
Configuration::getAcctAndConfig() returns array that contains credential and config parameters
*/
$service = new AdaptivePaymentsService(Configuration::getAcctAndConfig());
try {
/* wrap API method calls on the service object with a try catch */
$response = $service->Pay($payRequest);
$ack = strtoupper($response->responseEnvelope->ack);
if ($ack == "SUCCESS") {
$_SESSION['pay_key'] = $payKey = $response->payKey;
$payKey = $response->payKey;
$payPalURL = PAYPAL_REDIRECT_URL . '_ap-payment&paykey=' . $payKey;
header('Location: ' . $payPalURL);
}
} catch (Exception $ex) {
require_once '../Common/Error.php';
exit;
}

 

Success.php

This file contains $response array ,which contains all transaction details and displayed in the front end.



<?php
require_once('../PPBootStrap.php');
session_start();
$requestEnvelope = new RequestEnvelope("en_US");
$paymentDetailsReq = new PaymentDetailsRequest($requestEnvelope);
if ($_SESSION['pay_key'] != "") {
$paymentDetailsReq->payKey = $_SESSION['pay_key'];
}
/*
* ## Creating service wrapper object
Creating service wrapper object to make API call and loading
Configuration::getAcctAndConfig() returns array that contains credential and config parameters
*/
$service = new AdaptivePaymentsService(Configuration::getAcctAndConfig());
try {
/* wrap API method calls on the service object with a try catch */
$response = $service->PaymentDetails($paymentDetailsReq);
?>
<html>
<head>
<title>Paypal Parallel Payments Using PHP</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<meta name="robots" content="noindex, nofollow">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-43981329-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="main">
<div class="success_main_heading">
<center><h1>Paypal Parallel Payments Using PHP</h1></center>
</div>
<div id="return">
<h2>Payment Status</h2>
<hr/>
<?php
//Rechecking the product price and currency details
/*
* The status of the payment. Possible values are:

* CREATED - The payment request was received; funds will be
transferred once the payment is approved
* COMPLETED - The payment was successful
* INCOMPLETE - Some transfers succeeded and some failed for a
parallel payment or, for a delayed chained payment, secondary
receivers have not been paid
* ERROR - The payment failed and all attempted transfers failed
or all completed transfers were successfully reversed
* REVERSALERROR - One or more transfers failed when attempting
to reverse a payment
* PROCESSING - The payment is in progress
* PENDING - The payment is awaiting processing
*/
if ($response->status == 'COMPLETED') {
echo "<h3 id='success'>Payment Successful</h3>";
$amount = 0;
?>
<table id="results" >
<thead>
<tr class="head">
<th>Facility Provider</th>
<th>Status</th>
</tr>

</thead>
<tbody>
<?php for ($i = 0; $i < count($response->paymentInfoList->paymentInfo); $i++) { ?>
<tr>
<td>
<b><p style="color: rgb(77, 125, 179);"><?php echo $_SESSION['facilty_provider'][$i]; ?></p></b>
<p>Transaction Id: <?php echo $response->paymentInfoList->paymentInfo[$i]->transactionId; ?></p>
<p>Amount: <?php
echo $response->paymentInfoList->paymentInfo[$i]->receiver->amount;
$amount = $amount + $response->paymentInfoList->paymentInfo[$i]->receiver->amount;
?></p>
</td>
<td>
<b><p style="color: rgb(77, 125, 179);"><?php echo $response->paymentInfoList->paymentInfo[$i]->transactionStatus; ?></p></b>
</td>
</tr>
<?php } ?>
<tr>
<td><b>Total Amount</b></td>
<td><b>$<?php echo $amount ?> USD</b></td>
</tr>
</tbody>
</table>
<div class='back_btn'><a href='index.php' id= 'btn'><< Back</a></div>
<?php
} else if ($response->status == 'INCOMPLETE') {
echo "<h3 id='fail'>Payment - Failed</h3>";
echo '<p><center>Error msg :- This transaction cannot be processed.</center></p>';
echo "<div class='back_btn'><a href='index.php' id= 'btn'><< Back</a></div>";
} else if ($response->status == 'ERROR') {
echo "<h3 id='fail'>Payment - Failed</h3>";
echo '<p><center>Error msg :- The payment failed and all attempted transfers failed</center></p>';
echo "<div class='back_btn'><a href='index.php' id= 'btn'><< Back</a></div>";
} else if ($response->status == 'PENDING') {
echo "<h3 id='fail'>Payment - PENDING</h3>";
echo '<p><center>Error msg :- The payment is awaiting processing</center></p>';
echo "<div class='back_btn'><a href='index.php' id= 'btn'><< Back</a></div>";
} else if ($response->status == 'CREATED') {
echo "<h3 id='fail'>Payment - CREATED</h3>";
echo '<p><center>Error msg :- The payment request was received; funds will be transferred once the payment is approved</center></p>';
echo "<div class='back_btn'><a href='index.php' id= 'btn'><< Back</a></div>";
} else {
echo "<h3 id='fail'>Payment - Failed</h3>";
echo '<p><center>Error msg :- This transaction cannot be processed.</center></p>';
echo "<div class='back_btn'><a href='index.php' id= 'btn'><< Back</a></div>";
}
session_unset();
session_destroy();
?>
</div>
<!-- Right side div -->
<div class="fr"id="formget">
<a href=https://www.formget.com/app><img style="margin-left: 12%;" src="images/formget.jpg" alt="Online Form Builder"/></a>
</div>
</div>
</body>
</html><?php
} catch (Exception $ex) {
require_once '../Common/Error.php';
exit;
}

 

Style.css

Includes basic styling of HTML elements.


@import url(http://fonts.googleapis.com/css?family=Raleway);
#main{
width:960px;
margin: 10px auto;
font-family:raleway;
}
span{
color:red;
}
hr{
border:0;
border-bottom:1px solid #ccc;
margin: 10px -40px;
margin-bottom: 30px;
}
#container{
width: 54%;
float: left;
border-radius: 10px;
font-family:raleway;
border: 2px solid #ccc;
padding: 10px 40px 10px;
margin-top: 2px;
margin-left: 180px;
}
input[type=radio]{
width: 6.5%;
padding: 10px;
margin-top: 25px;
border: 1px solid #ccc;
padding-left: 5px;
font-size: 16px;
font-family:raleway;
margin-right: 10px;
}
input[type=submit]{
width: 100%;
background-color: #FFBC00;
color: white;
border: 2px solid #FFCB00;
padding: 10px;
font-size: 20px;
cursor: pointer;
border-radius: 5px;
margin-bottom: 15px;
font-weight: 600;
}
a{
text-decoration:none;
color: cornflowerblue;
}
i{
color: cornflowerblue;
}
#formget{
float:right;
}
#item-container {
width: 247px;
height: 308px;
margin-left: 8px;
float: left;
margin-bottom: 40px;
/* border: 1px solid rgb(226, 226, 226); */

}
#merchants-details{
width: 85%;
height: 75px;
margin-top: 19px;
float: right;
border: 3px solid rgb(226, 226, 226);
}
#Button-container{
width:100px;
height:67px;
border:1px solid black;
}
i{
float: right;
color: rgba(0, 0, 0, 0.13);
margin: -75px 8px;
}
p#title-text{
float: left;
margin: 11px;
}
#results {
width: 100%;
margin-top: 30px;
//border: 1px solid #ccc;
table-layout: auto;
margin-bottom: 30px;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
thead {
display: table-header-group;
vertical-align: middle;
border-color: inherit;
}
.head {
font-size: 15px;
font-family: "proxima_novasemibold", sans-serif;
background: #FEFFED;
color: #1d4c55;
border: 1px solid #ccc;
}
tr {
display: table-row;
vertical-align: inherit;
border-color: inherit;
}
.head th{
//border-right: 1px solid #ccc;
//border-bottom: 1px solid #ccc;
line-height: normal;
padding: 10px 0px;
text-align: left;
padding-left: 3%;
}
td {
//border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
line-height: normal;
padding: 10px 0px;
text-align: left;
padding-left:3%;
vertical-align: top;
}
tbody {
display: table-row-group;
vertical-align: middle;
border-color: inherit;
}
tr {
display: table-row;
vertical-align: inherit;
border-color: inherit;
}
#return {
width: 492px;
height: auto;
float: left;
border-radius: 10px;
font-family: raleway;
border: 2px solid #ccc;
padding: 10px 40px 30px;
margin-bottom: 50px;
}
#return h3#success {
text-align: center;
font-size: 24px;
color: green;
margin-bottom: 10px;
}
#return P {
text-align: left;
}
#return .back_btn {
margin-top: 30px;
text-align: center;
}
#btn {
width: 100%;
background-color: #FFBC00;
color: white;
border: 2px solid #FFCB00;
padding: 10px 70px;
font-size: 20px;
cursor: pointer;
border-radius: 5px;
margin-bottom: 15px;
margin: 0 auto;
}
a{
text-decoration:none;
color: #33BADB;
}
img#paypal_logo {
clear: both;
float: right;
margin-right: 165px;
margin-top: 1%;
padding-bottom: 15px;
}
.success_main_heading{
margin-left: -40%;

}
#return h3#fail{
text-align: center;
font-size: 24px;
margin-top: 50px;
color: red;
margin-bottom: 10px;
}
.red{
color:red;
font-weight: bold;
}
h2{
background-color: #FEFFED;
text-align:center;
border-radius: 10px 10px 0 0;
margin: -10px -40px;
padding: 15px;
}

 

Conclusion :

After reading the above post, I am sure you will give a try to the script provided and implement it in your own projects as well. Feel free to visit our website again in the future to get in touch with new coding tricks. You can let us know about your feedback in the space provided below :)