The PayPal Adaptive payments split payments to one or more than one receiver PayPal accounts. Using PayPal adaptive payment, we can make simple pay, parallel payments and chained payments.

What is Chained Payment..?

  1. Chained payment is part of PayPal Adaptive payments.
  2. Using chained payment sender can send a full amount of payment to primary receiver.
  3. After getting the full amount by primary receiver that amount will automatically split and sent to secondary receiver. For example: Product’s Marketplace and commission based website.

In our previous blog post we have covered PayPal adaptive payments to make Parallel Payments.

In this tutorial we are going to demonstrate how we can use PayPal adaptive payments to make a chained payments for marketplace using PHP.

 


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

paypal-chained-adaptive-payments-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.

 


Chained Payments Overview

With PayPal chained payment, when the sender lands at PayPal, the sender will make only a single payment and get one payment recipient. Back-end full amount will get by primary receiver and via primary receiver that amount will split and sends to secondary receiver.

paypal-chained-adaptive-payments-working

Note : Here if you buy a script,some part of payment will transfer to the website admin and some part of payment to script author.

It’s useful when

  1. You are selling products and want to share the total selling amount with other partners.
  2. If you are a site operator and take 20% of each item sold.
  3. You are making marketplace site to get commissions, etc.

 

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 Script information.

<html>
<head>
<title>PayPal Marketplace</title>
<link rel="stylesheet" type="text/css" href="css/style.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 Adaptive Payments to build a Marketplace in PHP</h1></center>
<div id="conatiner">
<h2>Buy '' jQuery Enter Key Form Submit '' Script</h2>
<hr/>
<div id="first">
<img src="images/submit-form-on-enter-key-feature.png">
<div id="content">
<form action="proccess.php" method="POST">
<input type="hidden" name="id" value="<?php echo base64_encode(1); ?>">
<input type="submit" style="float:left;"class="fg-button yellow" value="Buy Now $50" name="submit" id="tatalamount">
<div id="preview"><a href="https://www.formget.com/tutorial/submit_form_on_enter_key_live_demo/form.html" target="_blank"class="fg-button teal">Live Preview</a></div>
</form>
</div>
</div><div id="second">
<h4 id="author">Author</h4>
<img src="images/fugo.png"><p>Fugo of FormGet</p>
<hr class="type_1">
<h4 id="author">What will I get</h4>
<ul>
<li>Well Coded Script</li>
<li>Instant Product Access</li>
<li>All Future Updates</li>
</ul>
</div>
</div>
</div>
<div class="cr"></div>
<div id="footer">
<span id="Note">Note : </span><span style="color:black;" > A chained payment is a payment from a sender that is indirectly split among multiple receivers. <br/>Here if you buy a script,some part of payment will transfer to the web site admin and some part <br/>of payment to script author.</span>
<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();
});
});
</script>
</body>
</html>

 

Process.php

This file contains code to process Adaptive (chained) amount to PayPal.

<?php

session_start();
session_unset();
require_once('../PPBootStrap.php');
require_once('../Common/Constants.php');
define("DEFAULT_SELECT", "- Select -");
$returnUrl = "https://www.formget.com/tutorial/paypal-adaptive/chained-payment/success.php";
$cancelUrl = "https://www.formget.com/tutorial/paypal-adaptive/chained-payment/index.php";
$memo = "Adaptive Payment - chained Payment";
$actionType = "PAY";
$currencyCode = "USD";
if ($_POST['id'] == base64_encode(1)) {
$receiverEmail = array("formget-buyer@outlook.com", "sobhagya-buyer@outlook.com");
$receiverAmount = array("50", "35");
$primaryReceiver = array("true", "false");
}
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);
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") {
$payKey = $response->payKey;
$_SESSION['pay_key'] = $payKey;
$payPalURL = PAYPAL_REDIRECT_URL . '_ap-payment&paykey=' . $payKey;
header('Location:' . $payPalURL);
}
} catch (Exception $ex) {
require_once '../Common/Error.php';
exit;
}
/* Make the call to PayPal to get the Pay token
If the API call succeded, then redirect the buyer to PayPal
to begin to authorize payment. If an error occured, show the
resulting errors */

 

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");
/*
* PaymentDetailsRequest which takes,
`Request Envelope` - Information common to each API operation, such
as the language in which an error message is returned.
*/
$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 Marketplace</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
<div id="main">
<div class="success_main_heading">
<center><h1>PayPal Adaptive Payments to build a Marketplace in 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;
$secondry_total = 0;
?>
<script>
$(document).ready(function() {
var link = document.createElement('a');
link.href = "//d13dcw7qo4xgly.cloudfront.net/wp-content/uploads/2014/12/submit-form-on-enter-key-download.zip";
document.body.appendChild(link);
link.click();
});
</script>
<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 $response->paymentInfoList->paymentInfo[$i]->receiver->email; ?></p></b>
<p>Transaction Id: <?php echo $response->paymentInfoList->paymentInfo[$i]->transactionId; ?></p>
<p>Amount: $<?php
if ($response->paymentInfoList->paymentInfo[$i]->receiver->primary == "true") {
$totalamount = $response->paymentInfoList->paymentInfo[$i]->receiver->amount;
echo '<span style="color:black;" id="primary"></span>.00';
} else {
$secondry_total = $secondry_total + $response->paymentInfoList->paymentInfo[$i]->receiver->amount;
echo $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 }
?><input type="hidden" value="<?php echo $totalamount - $secondry_total; ?>" id="primary"/>
<tr>
<td><b>Total Amount</b></td>
<td><b>$<?php echo $totalamount ?> 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>";
}
?>
</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>
<script type="text/javascript">
$(document).ready(function() {
var primary = $('input#primary').val();
$('span#primary').html(primary);
});
</script>
</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:50px auto;
font-family:raleway;
}
span{
color:red;
}
h2{
background-color: #FEFFED;
text-align:center;
border-radius: 10px 10px 0 0;
margin: -10px -40px;
padding: 15px;
}
hr{
border:0;
border-bottom: 1px solid #ccc;
margin: 10px -40px;
margin-bottom: 30px;
}
#conatiner{
width: 100%;
float: left;
border-radius: 10px;
font-family:raleway;
border: 2px solid #ccc;
padding: 10px 40px 31PX;
margin-top: 37px;
margin-left: -40px;
}
#first{
padding: 10px;
width: 530px;
height: 350px;
float: left;
box-shadow: rgb(153, 163, 173) 0px 5px 17px 1px, rgb(238, 238, 238) 0px 0px 40px;
border: 1px dashed rgb(195, 195, 195);
}
#first img{
width: 98%;
margin-top: 15px;
padding: 5px;
border: 1px solid rgba(200, 200, 200, 0.84);
}
#second{
width: 380px;
height: 350px; float: right;
padding: 10px;
/* border: 2px solid red; */
box-shadow: rgb(153, 163, 173) 0px 5px 17px 1px, rgb(238, 238, 238) 0px 0px 40px;
border: 1px dashed rgb(195, 195, 195);
}
.fg-button{
position: relative;
top: 0px;
border-radius: 4px;
font-size: 18px;
padding: 11px 28px;
text-decoration: none;
border: 0px solid;
cursor: pointer;
border-bottom-width: 3px;
outline: none;
-webkit-transition: 0.3s background;
-moz-transition: 0.3s background;
transition: 0.3s background;
}

.fg-button:active{
top: 2px;
}
.fg-button.teal{
color: #fff;
border-color: #04A5A1;
background-color: #08BBB7;
}

.fg-button.teal:hover{
background: #0ACFCB;
}

.fg-button.teal:active{
background: #09cbc7;
top: 2px;
border-bottom-width: 1px;
}
.fg-button.yellow{
color: #fff;
border-color: #BD8C03;
background-color: #ffbc00;
}
.fg-button.yellow:hover{
background: #FFC92F;
}

.fg-button.yellow:active{
background: #FFBC00;
top: 2px;
border-bottom-width: 1px;
}

#preview{
width: 180px;
height: 60px;
margin-top: 10px;
margin-left: 20px;

float: left;
/* border: 1px solid black; */
}
h4#author{
margin-left: 28px;
}
#second img{
margin-left: 20px;
}
#second p{
float: right;
margin-top: 3px;
margin-right: 134px;
}
hr.type_1 {
border: 0;
height: 45px;
margin-left: 32px;
background-image: url(../images/hr.jpg);
background-repeat: no-repeat;
}
img#paypal_logo {
float: right;
margin-top: -35px;
margin-right: -45px;
}

#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;
}

.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;
}
#footer{
font-family:raleway;
width: 960px;
margin: 10px auto;
}
#content{
margin-left: 95px;
margin-top: 35px;
}
.cr{
clear: both;
}
#Note{
margin-left: -40px;
}

 

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 :)