Friday, April 12, 2013

PayPal Adaptive Payments - Parallel Payments, The Easy Way!

I recently encountered a very annoying problem called the Paypal API. Although Paypal API is currently going through some changes, the adaptive payments API hasn't changed yet.
So thanks to optikalefxx 's YouTube channel I've created a simplified code, that makes prallel payments in PHP.
Here is the class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
class Paypal {
     
    var $receiverList = array();
    var $receiverOption = array();
    var $requestEnvelope = array(
                    "errorLanguage" => "en_US",
                    "detailLevel" => "ReturnAll"
                );
         
    function __construct() {
        define("API_USER","YOUR-USER");
        define("API_PASS","YOUR-PASS");
        define("API_SIG","YOUR-SIGNATURE");
        define("APP_ID","APP-80W284485P519543T"); // This app ID is default for sandbox.
        $this->headers = array(
            "X-PAYPAL-SECURITY-USERID: ".API_USER,
            "X-PAYPAL-SECURITY-PASSWORD: ".API_PASS,
            "X-PAYPAL-SECURITY-SIGNATURE: ".API_SIG,
            "X-PAYPAL-REQUEST-DATA-FORMAT: JSON",  
            "X-PAYPAL-RESPONSE-DATA-FORMAT: JSON",
            "X-PAYPAL-APPLICATION-ID: ".APP_ID 
        );
    }
     
    function getPaymentOptions($paykey) {
        $packet = array(
            "requestEnvelope" => array(
                    "errorLanguage" => "en_US",
                    "detailLevel" => "ReturnAll"
                ),
            "payKey" => $paykey
        );
        return $this->_paypalSend($packet,"GetPaymentOptions");
    }
    function setPaymentOptions() {
         
    }
    function addReceiver($email,$amount,$itemsArr) {
        try {
            if(!filter_var($email, FILTER_VALIDATE_EMAIL) or !is_numeric($amount) or !is_array($itemsArr)) {
                throw new Exception("Email\Payment Details Invalid for : ". $email);
            }
            $sum;
            foreach ($itemsArr as $key=>$value) {
                $sum+=$value["price"];
            }
            if($sum != $amount) throw new Exception("Items Sum doesn't match the amount");
        }
        catch(Exception $e) {
            echo 'Message: ' .$e->getMessage();
            return FALSE;
        }
        try {
            if(count($this->receiverList) < 6) {
            $this->receiverList[] = array("amount" => $amount,"email" => $email);
            $item = array();
            foreach($itemsArr as $key=>$value) {
                $item[] = array(
                    "name"=>$value['name'],
                    "price"=>$value['price'],               
                );
            }
            $this->receiverOption[] =                    array(
                            "receiver"=>array("email"=>$email),
                            "invoiceData" => array(
                                    "item"=>$item,
                                ),
                        );
            return TRUE;
            }
            else {
                throw new Exception("Maximum amount of receivers reached");
                return FALSE;
            }  
        }
        catch(Exception $e) {
            echo 'Message: ' .$e->getMessage();
            return FALSE;
        }
    }
    function _paypalSend($data,$call) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->apiUrl.$call);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
        return json_decode(curl_exec($ch), TRUE);                      
    }
    function splitPay($currency,$returnUrl,$cancelUrl) {
        $createPacket = array (
            "actionType" => "PAY",
            "currencyCode" => $currency,
            "receiverList" => array(
                    "receiver" => $this->receiverList
                ),
            "returnUrl" => $returnUrl,
            "cancelUrl" => $cancelUrl,
            "requestEnvelope" => $this->requestEnvelope
        );
         
        $response = $this->_paypalSend($createPacket,"Pay");
        //print_r($response);
        $payKey = $response['payKey'];
        $detailsPacket = array(
            "requestEnvelope" => $this->requestEnvelope,
            "payKey" => $payKey,
            "receiverOptions" => $this->receiverOption
        );
         
        $response = $this->_paypalSend($detailsPacket,"SetPaymentOptions");
         
        $dets = $this->getPaymentOptions($payKey);
        header("Location: ".$this->paypalUrl.$payKey);
    }
}


Your App credentials can be accessed through your Business account profile.
change lines 13-16 to match your credentials, and remove ".sandbox" in line 6 if you wanna go Live.

In order to use the app simply add the following code:
1
2
3
4
5
6
$pp = new Paypal();
$pp->addReceiver('email1@email.com',5.00, array(array("name"=>"p1","price"=>"3.00"),array("name"=>"p1","price"=>"2.00")));
$pp->addReceiver('email2@email.com',5.00, array("name"=>"product2","price"=>"5.00"));
$pp->addReceiver('email3@email.com',5.00, array("name"=>"product3","price"=>"5.00"));
$pp->splitPay("USD"/*Currency Code*/,"http://localhost/"/*Return URL*/,"http://localhost/"/*Cancel URL*/);


The code above will redirect the buyer to the PayPal checkout.
As you can see there is an option to add multiple items per receiver, but if the sum of the prices won't match, the receiver won't get payed/
Hope this Helped!

3 comments:

  1. Hello,
    Above code is working fine but i want product name at paypal instead of account name. Just like product2 and product 1 is product name in your code.
    Please reply soon.

    ReplyDelete
  2. Hello,
    Above code is working fine but i want product name at paypal instead of account name. Just like product2 and product 1 is product name in your code.
    Please reply soon.
    I have same question. Please reply. or email me at chetan19.jdct@gmail.com

    ReplyDelete