Multi Items Payment with PayPal REST API (PHP)

To simplify things I created a simple Payment System with PayPal REST API in my previous post. But today I want to extend that tutorial making it bit complex and allowing customers to either pay with PayPal payment method or credit cards directly. Yes PayPal allows people to pay for your products directly using credit cards, which requires absolutely no user sign-in or sign-ups with PayPal.

pay-with-credit-card-or-pay-pal

Before we begin get your Client Id and Client Secret from developer.paypal.com account for sandbox testing. Or to sell your products live, you will need Client Id and Client Secret from Paypal.com

In my previous post, I had created four files, but here I’ve add two more file called payment_option.php and config.php. payment_option.php file allows customer to choose Payment method, which is either PayPal or Credit Card, and you can guess what config.php is all about.

  • config.php – Stores information needed by the application.
  • Index.php – (Products page) contains list of products for sale.
  • Payment_option.php – Allows customer to choose payment method
  • Order_process.php – Processes PayPal payment.
  • Functions.inc.php – Helper script, contains functions needed for processing.
  • Payment_cancel.html – PayPal redirects user to this page in-case of cancellation.

Products Page

Let’s talk about product page (Index.php) a bit, as you can see in PHP code below, I have listed the products stored in database, each item contains a quantity field and a checkbox. User selects the item he wants to buy, selects the quantity and these information will be posted to payment_option.php.

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
<?php
//select product information from database
$results = $mysqli->query("SELECT id, product_code, product_name, product_price, image_name FROM my_products");

//wrap with form tag
print   '<form action="payment_option.php" method="post">';
print '<ul>';

//list products from database
while($row = $results->fetch_object()) {
    print '<li>';
    print '<img src="images/' . $row->image_name . '" width="220" height="220">';
    print '<div class="item-name">' . $row->product_name . '</div>';
    print '<div class="btn-wrap">';
    print   'Qty:';
    print   '<select name="'.$row->product_code.'_qty">';
    print       '<option>1</option>';
    print       '<option>2</option>';
    print       '<option>3</option>';
    print       '<option>4</option>';
    print       '<option>5</option>';
    print       '<option>8</option>';
    print       '<option>10</option>';
    print   '</select> ';
    print   '<input type="checkbox" name="item_id[]" value="' . $row->id . '" />';
    print '</div>';
    print '</li>';
}

print '</ul>';
print '<div align="center">';
print '<input type="submit" value="Buy Selected Items" />';
print '</div>';
print '</form>';
?>

Payment Method Selection

When a user is redirected to this page along with item ids and quantity, we need to make sure selected items exist in database, then we can fetch prices and product codes from database and construct a collection of items array in $_SESSION[“items”], which we will use in order_process.php.

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
<?php
session_start(); //start the session
include_once "config.php";

//continue if item_ids are set in post
if(isset($_POST["item_id"])){
   
    //make sure ids are numbers
    foreach ($_POST["item_id"] as $itm_id) {
        if (!(is_numeric($itm_id))) {
            die("Product id passed must be integers!");
        }
    }
   
    //convert item ids into string using implode(), seperated by comma.
    $item_codes = implode(',', $_POST["item_id"]);
   
    //select products using given ids
    $results = $mysqli->query("SELECT product_code, product_name, product_price FROM my_products WHERE id IN (".$item_codes.")");
    if($results->num_rows){
        $item_total = 0;
        while($row = $results->fetch_object()){
            //item quantity
            $item_quantity = ( isset( $_POST[$row->product_code."_qty"] ) && is_numeric( $_POST[$row->product_code."_qty"] ) ) ? $_POST[$row->product_code."_qty"] : 1;
           
            //add item array to $items variable, it will be used in order_process.php
            $items[] = array(
                            'name' => $row->product_name,
                            'quantity' => $item_quantity,
                            'price' => $row->product_price,
                            'sku' => $row->product_code,
                            'currency' => PP_CURRENCY
                            );
            //calculate total price of all items       
            $item_total = $item_total + ($row->product_price * $item_quantity);
        }
    }else{
        die("Selected item(s) not found in database!");
    }
   
    //Set session variables of items and total price for later use.
    $_SESSION["items"] = $items;
    $_SESSION["items_total"] = $item_total;
                                       
}else{
    die("Please select atlease 1 product");
}
?>

If everything looks good, it’s time to display Payment Option page to user. As you can see I have two HTML forms here, first one is for PayPal Payment method, and second HTML form is for credit card Payment method, it contains all the fields required for credit card information.

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
<div class="payment_method">
<div class="select_method">
Select a Payment Method.
<form action="order_process.php" method="post" >
<select id="payment_method">
    <option value="paypal">PayPal</option>
    <option value="credit_card">Credit Card</option>
</select>

<input type="hidden" name="payment_method" value="paypal" />

<input type="submit" value="Go">
</form>
</div>

<form action="order_process.php" method="post" id="credit_cart_pay"  class="credit_card_info" style="display:none" novalidate>
<label><span>First Name :</span><input type="text" name="credit_card_first_name" required="true"  /></label>
<label><span>Last Name :</span><input type="text" name="credit_card_last_name" required="true"  /></label>
<label><span>Card Type :</span><select name="credit_card_type">
                               <option value="visa">Visa</option>
                               <option value="mastercard">Mastercard</option>
                               </select>
</label>
<label><span>Credit Card Number :</span><input type="text" name="credit_card_number" required="true" /></label>
<label><span>Expire Month :</span><input type="text" name="credit_card_expire_month" required="true" /></label>
<label><span>Expire Year :</span><input type="text" name="credit_card_expire_year" required="true" /></label>
<label><span>cvv2 :</span> <input type="text" name="credit_card_cvv2" required="true" /></label>
<input type="hidden" name="payment_method" value="credit_card" />
<div align="center" id="button_wrp"><input type="submit" value="Pay with Credit Card"></div>
</form>
</div>

You may be wondering, why show two forms to customer? he will get confused! Well the solution is pretty simple, we will just use jQuery here, and we hide/show credit card form when customer selects a payment method. You might want to use some credit card validation script here to make things more solid.

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
<script type="text/javascript">
$(document).ready(function() {
   
    //Payment method selection by user
    $( "#payment_method" ).change(function() {
        if($(this).val()=="credit_card"){
            $( ".credit_card_info").fadeIn();
            $(this).parent().find('input[type="submit"]').hide();
        }else{
            $( ".credit_card_info").fadeOut();
            $(this).parent().find('input[type="submit"]').show();
        }
    });
   
    $("#credit_cart_pay").submit(function( event ){
        $("#credit_cart_pay input[required=true]").each(function(){
                    $(this).css('border-color','');
                    if(!$.trim($(this).val())){ //if this field is empty
                        $(this).css('border-color','red'); //change border color to red  
                        event.preventDefault();
                    }
        });
        $("#button_wrp").html("Please wait..");
    });
   
});
</script>

Order Processes

Order process is actually pretty straight forward if you examine the code carefully. I have really tried hard to make it look less complicated, I just hope it doesn’t take you too much time to understand the whole process.
Here’s the sample flow of order_process.php.

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
//we have user payment method and session items
if(isset($_POST["payment_method"]) && isset($_SESSION["items"])){
    try{
        if($_POST["payment_method"] == "paypal"){
            //redirect to paypal with items and prices
        }
        if($_POST["payment_method"] == "credit_card"){
            //pay using credit card, no paypal redirection required
            //set $_SESSION["results"] and redirect user back to this page
        }
    }catch(PPConnectionException $ex){
        //show errors
    }
}


if(isset($_GET["token"]) && isset($_GET["PayerID"]) && isset($_SESSION["payment_id"])){
    //if PayPal payment method was used, paypal redirects back to this page with PayerID and Payment ID
    //execute payment using PayerID and Payment ID
    //set $_SESSION["results"] and redirect user back to this page
}

if(isset($_SESSION["results"]))
{
    //If results session was set in actions above, display results set in session.
}

And here’s the whole code, just take your time to read each comment line to understand it more clearly.

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<?php
session_start(); //start session
include_once "config.php";
include_once "vendor/autoload.php"; //include PayPal SDK
include_once "functions.inc.php"; //our PayPal functions

if(isset($_POST["payment_method"]) && isset($_SESSION["items"])){
   
    //card details for credit card payemnt
    if($_POST["payment_method"] == "credit_card"){
        $cc_first_name      = (isset($_POST["credit_card_first_name"]))? $_POST["credit_card_first_name"] : die("First Name Empty");
        $cc_last_name       = (isset($_POST["credit_card_last_name"]))? $_POST["credit_card_last_name"] : die("Last Name Empty");
        $cc_card_type       = (isset($_POST["credit_card_type"]))? $_POST["credit_card_type"] : die("Credit Card type Empty");
        $cc_card_number     = (isset($_POST["credit_card_number"]))? $_POST["credit_card_number"] : die("Credit Card Number Empty");
        $cc_card_month      = (isset($_POST["credit_card_expire_month"]))? $_POST["credit_card_expire_month"] : die("Expire Month Empty");
        $cc_card_year       = (isset($_POST["credit_card_expire_year"]))? $_POST["credit_card_expire_year"] : die("Expire Year Empty");
        $cc_card_cvv2       = (isset($_POST["credit_card_cvv2"]))? $_POST["credit_card_cvv2"] : die("CVV month empty");
    }
       
    //set array of items details from session, single or multiple
    $items = $_SESSION["items"];

    //get total amount from session.
    $total_amount = $_SESSION["items_total"];

    // try a payment request
    try{
        ######## if payment method is PayPal ##############
        if($_POST["payment_method"] == "paypal"){
            //if payment method was PayPal, we need to redirect user to PayPal approval URL
            $result = create_paypal_payment($total_amount, PP_CURRENCY, '', $items, RETURN_URL, CANCEL_URL);
            if($result->state == "created" && $result->payer->payment_method == "paypal"){
                $_SESSION["payment_id"] = $result->id; //set payment id for later use, we need this to execute payment
                unset($_SESSION["items"]); //unset item session, not required anymore.
                unset($_SESSION["items_total"]); //unset items_total session, not required anymore.
                header("location: ". $result->links[1]->href); //after success redirect user to approval URL
                exit();
            }
       
        }
       
        ######## if payment method is Credit Card ##############   
        if($_POST["payment_method"] == "credit_card"){
            $credit_card = array(
                                'type'=> $cc_card_type,
                                'number' => $cc_card_number,
                                'expire_month'=>$cc_card_month,
                                'expire_year'=>$cc_card_year,
                                'cvv2'=>$cc_card_cvv2,
                                'first_name'=>$cc_first_name,
                                'last_name'=>$cc_last_name
                                );
                                   
            //pay directly using credit card information.
            $result = pay_direct_with_credit_card($credit_card, PP_CURRENCY , $total_amount, $items, '') ;     
               
                //If credit card payment is succesful, get results
                if($result->state == "approved" && $result->payer->payment_method == "credit_card"){
                    unset($_SESSION["items"]); //unset item session, not required anymore.
                    unset($_SESSION["items_total"]); //unset items_total session, not required anymore.
       
                    //get transaction details
                    $transaction_id         = $result->transactions[0]->related_resources[0]->sale->id;
                    $transaction_time       = $result->transactions[0]->related_resources[0]->sale->create_time;
                    $transaction_currency   = $result->transactions[0]->related_resources[0]->sale->amount->currency;
                    $transaction_amount     = $result->transactions[0]->related_resources[0]->sale->amount->total;
                    $transaction_method     = $result->payer->payment_method;
                    $transaction_state      = $result->transactions[0]->related_resources[0]->sale->state;
                   
                    //get payer details
                    $payer_first_name       = $result->payer->payer_info->first_name;
                    $payer_last_name        = $result->payer->payer_info->last_name;
                    $payer_email            = $result->payer->payer_info->email;
                    $payer_id               = $result->payer->payer_info->payer_id;
                   
                    //get shipping details
                    $shipping_recipient     = $result->transactions[0]->item_list->shipping_address->recipient_name;
                    $shipping_line1         = $result->transactions[0]->item_list->shipping_address->line1;
                    $shipping_line2         = $result->transactions[0]->item_list->shipping_address->line2;
                    $shipping_city          = $result->transactions[0]->item_list->shipping_address->city;
                    $shipping_state         = $result->transactions[0]->item_list->shipping_address->state;
                    $shipping_postal_code   = $result->transactions[0]->item_list->shipping_address->postal_code;
                    $shipping_country_code  = $result->transactions[0]->item_list->shipping_address->country_code;

                    //insert into database         
                    $insert_row = $mysqli->query("INSERT INTO my_orders (transaction_id, transaction_currency, transaction_amount, transaction_method, transaction_state)
                            VALUES ('$transaction_id', '$transaction_currency', '$transaction_amount', '$transaction_method', '$transaction_state')"
);
   
                    //set $_SESSION["results"] session, print_r($result); to see what is returned
                    $_SESSION["results"]  = array(
                            'transaction_id' => $transaction_id,
                            'transaction_time' => $transaction_time,
                            'transaction_currency' => $transaction_currency,
                            'transaction_amount' => $transaction_amount,
                            'transaction_method' => $transaction_method,
                            'transaction_state' => $transaction_state
                            );
                               
                    header("location: ". RETURN_URL); //$_SESSION["results"] is set, redirect back to order_process.php
                    exit();
                }
        }

    }catch(PPConnectionException $ex) {
        echo parseApiError($ex->getData());
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }

}


### If Payment method was PayPal, user is redirected back to this page with token and Payer ID ###
if(isset($_GET["token"]) && isset($_GET["PayerID"]) && isset($_SESSION["payment_id"])){
    try{
        $result = execute_payment($_SESSION["payment_id"], $_GET["PayerID"]);  //call execute payment function.

        if($result->state == "approved"){ //if state = approved continue..
            //SUCESS
           
            unset($_SESSION["payment_id"]); //unset payment_id, it is no longer needed
           
            //get transaction details
            $transaction_id         = $result->transactions[0]->related_resources[0]->sale->id;
            $transaction_time       = $result->transactions[0]->related_resources[0]->sale->create_time;
            $transaction_currency   = $result->transactions[0]->related_resources[0]->sale->amount->currency;
            $transaction_amount     = $result->transactions[0]->related_resources[0]->sale->amount->total;
            $transaction_method     = $result->payer->payment_method;
            $transaction_state      = $result->transactions[0]->related_resources[0]->sale->state;
           
            //get payer details
            $payer_first_name       = $result->payer->payer_info->first_name;
            $payer_last_name        = $result->payer->payer_info->last_name;
            $payer_email            = $result->payer->payer_info->email;
            $payer_id               = $result->payer->payer_info->payer_id;
           
            //get shipping details
            $shipping_recipient     = $result->transactions[0]->item_list->shipping_address->recipient_name;
            $shipping_line1         = $result->transactions[0]->item_list->shipping_address->line1;
            $shipping_line2         = $result->transactions[0]->item_list->shipping_address->line2;
            $shipping_city          = $result->transactions[0]->item_list->shipping_address->city;
            $shipping_state         = $result->transactions[0]->item_list->shipping_address->state;
            $shipping_postal_code   = $result->transactions[0]->item_list->shipping_address->postal_code;
            $shipping_country_code  = $result->transactions[0]->item_list->shipping_address->country_code;
                       
            //insert into database         
            $insert_row = $mysqli->query("INSERT INTO my_orders (transaction_id, transaction_currency, transaction_amount, transaction_method, transaction_state)
                    VALUES ('$transaction_id', '$transaction_currency', '$transaction_amount', '$transaction_method', '$transaction_state')"
);
           
                       
            //Set session for later use, print_r($result); to see what is returned
            $_SESSION["results"]  = array(
                    'transaction_id' => $transaction_id,
                    'transaction_time' => $transaction_time,
                    'transaction_currency' => $transaction_currency,
                    'transaction_amount' => $transaction_amount,
                    'transaction_method' => $transaction_method,
                    'transaction_state' => $transaction_state
                    );
                       
            header("location: ". RETURN_URL); //$_SESSION["results"] is set, redirect back to order_process.php
            exit();
        }
       
    }catch(PPConnectionException $ex) {
        $ex->getData();
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }

}

### Display order confirmation if $_SESSION["results"] is set  ####
if(isset($_SESSION["results"]))
{
    $html = '<!DOCTYPE HTML>';
    $html .= '<html>';
   
   
    $html .= '<head>';
    $html .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
    $html .= '<title>Order Confirm Details</title>';
    $html .= '<style type="text/css">';
    $html .= '.transaction_info {margin:0px auto; background:#F2FCFF;; max-width: 750px; color:#555;}';
    $html .= '.transaction_info thead {background: #BCE4FA;font-weight: bold;}';
    $html .= '.transaction_info thead tr th {border-bottom: 1px solid #ddd;}';
    $html .= '</style>';
    $html .= '</head>';
    $html .= '<body>';

    $html .='<div align="center"><h2>Payment Success</h2></div>';
    $html .='<div align="center">Please note down your transaction ID, it will be required for further communication!</div>';
    $html .= '<table border="0" cellpadding="10" cellspacing="0" class="transaction_info">';
   
    $html .= '<thead><tr><td>Transaction ID</td><td>Date</td><td>Currency</td><td>Amount</td><td>Method</td><td>State</td></tr></thead>';
   
    $html .= '<tbody><tr>';
    $html .= '<td>'.$_SESSION["results"]["transaction_id"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_time"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_currency"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_amount"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_method"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_state"].'</td>';
    $html .= '</tr>';
    $html .= '<tr><td colspan="6"><div align="center"><a href="index.php">Back to Products Page</a></div></td></tr>';
    $html .= '</tbody>';
    $html .= '</table>';
    $html .= '</body>';
    $html .= '</html>';
   
    echo $html;
   
    unset($_SESSION["results"]);
}
?>

It may not be necessary, but don’t forget to look into functions.inc.php to understand how it uses PayPal SDK to interact to PayPal. I would love to discuss them here, but it will be out of the scope of this tutorial! You can checkout PayPal REST API Reference for the same.

Download Demo

1
  • Saran

  • Article written by Saran. Saran Chamling loves the web technology, and enjoys designing, exploring and writing about it @sanwebe.com. You can find him at Twitter, Google or Facebook.

22 Comments Add Comment

  • Chaiwat Trakanratsanti

    I try the sample code in my localhost. I found the error
    error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

    Pls, kindly advise. What I need to do to fix the error.

     Reply
  • hello.. I got this error when I run your script
    Got Http response code 401 when accessing https://api.sandbox.paypal.com/v1/oauth2/token.
    please help me .
    thanks

     Reply
    • Hello,
      I have the same problem, i changed the way to get the token, i add a value ‘signature’ in “config.php” and “functions.inc.php” and i got the same error message.
      If someone can help us, thank you !

  • Hi, i’m wondering how to add shipping amount plz ??????????

     Reply
  • After successful transaction, does is the order table updated base on item_number or item_name? What I am trying to know is if , we get a new for for each item in transaction.

     Reply
  • Hi
    when I did the demo of this page (http://www.sanwebe.com/2014/09/multi-items-payment-with-paypal-rest-api-php), After coming back from Paypal, got this error:
    Method PayPal\Api\Sale::getTransactionFee() does not exist

     Reply
  • Hi!
    I get an error
    Method PayPal\Api\Sale::getTransactionFee() does not exist
    It worked some days ago?
    Mars

     Reply
  • Hey nice tutorials on Paypal REST API! Just a question where ist the function “parseApiError($data)” defined?

    Thabks

     Reply
  • hi
    I have a error Fatal error: Call to a member function fetch_object() on a non-object in C:\wamp\www\paypal-rest-multi-items-payment\index.php on line 29
    Do you have any idea why?? I try to figure it out and imposible…
    Any help welcome

     Reply
  • It was really awesome post.

     Reply
  • I got response Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/payment.

    What’s wrong? I’m trying add shipping into it

     Reply
  • Just problem with paypal your script!

    return : error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

    look your demo!

     Reply
    • PayPal might have updated their systems, investigating.

    • PayPal did indeed update their SDK. I updated paypal/core/HTTPConfig.php or something like that. You update the CURLOPT_SSLVERSION to 1 or 4, see if that works.

    • Yes it was PayPal new SDK, just replaced vendor folder with new SDK and everything works perfectly. Also updated demo and downloadable files.

  • I cannot figure out for the life of me how to add a TAX to the total without it throwing 400 “Item amount must add up to specified amount subtotal (or total if amount details not specified)”. I modified $items[] array to include ‘tax’=>$myItemTax but everything I try it always gets that issue error message.

     Reply
  • SetExpressCheckout failed: (0)
    I am getting this error again and again. This demo is working properly but same code doesn’t work with me, Plz i need a quick solution, coz i have used same code for some live sites as well

     Reply
  • Hi Saran Chamling,

    I have problem in payment through credit card
    and this as below

    Uncaught exception ‘PayPal\Exception\PPConnectionException’ with message ‘Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/payment.’ in C:\xampp\htdocs\MyProject\includes\vendor\paypal\sdk-core-php\lib\PayPal\Core\PPHttpConnection.php:104 Stack trace: #0 C:\xampp\htdocs\MyProject\includes\vendor\paypal\sdk-core-php\lib\PayPal\Transport\PPRestCall.php(44): PayPal\Core\PPHttpConnection->execute(‘{“intent”:”sale…’) #1 C:\xampp\htdocs\MyProject\includes\vendor\paypal\rest-api-sdk-php\lib\PayPal\Api\Payment.php(246): PayPal\Transport\PPRestCall->execute(Array, ‘/v1/payments/pa…’, ‘POST’, ‘{“intent”:”sale…’) #2 C:\xampp\htdocs\MyProject\includes\functions.inc.php(109): PayPal\Api\Payment->create(Object(PayPal\Rest\ApiContext)) #3 C:\xampp\htdocs\MyProject\payment_credit_cart.php(49): pay_direct_with_credit_card(Array, ‘USD’, 41, Array, ”) #4 {main} thrown in C:\xampp\htdocs\MyProject\includes\vendor\paypal\sdk-core-php\lib\PayPal\Core\PPHttpConnection.php on line 104

     Reply
  • Good day sir. How can I connect this tutorial from this tutorial that you made. “http://www.sanwebe.com/2013/06/creating-simple-shopping-cart-with-php/comment-page-1” I’m doing my own shopping cart right now and I want to have this kind of payment. “Multi Items Payment with PayPal REST API (PHP)” Please help me sir.

     Reply