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. 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.comIn 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.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.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");
}
?>
HTML
- 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>
JQUERY
- 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.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.
}
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
- 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"]);
}
?>