Paypal Client Side Express Checkout Popup PHP Cart Example Code

I recently needed to setup the Paypal express checkout (which is a lightbox style pop-up that can be integrated into any web page) on a site and while there is documentation and example code to get an initial and basic payment working, I found passing a custom PHP shopping cart in was a little tricky to get working along with making some customisations to the code. Hence I have put together this blog post around how I expanded the basic code to push in a shopping cart.

The Basic Code & API Reference Docs

Now, don’t get me wrong, Paypal has put up some great starting point examples for web developers to build upon. I found the below resource page to be very helpful:

Client Side Express Checkout using REST
https://developer.paypal.com/demo/checkout/#/pattern/client

Payments API Reference
https://developer.paypal.com/docs/api/payments/#payment

My problem was that I couldn’t locate an example which passed a shopping cart or set of products over to Paypal.

If you would like a shortcut, click here to download the full working script files for a few bucks.

My Expanded PHP Cart Version

So here is my expanded example HTML and JS code which should work on any custom PHP script or session based shopping cart.

<!DOCTYPE html>

<head>
 <meta http-equiv="X-UA-Compatible" content="IE=edge" />
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <script src="https://www.paypalobjects.com/api/checkout.js"></script>
</head>

<body>
 <div id="paypal-button-container"></div>

 <script>
 paypal.Button.render({
 // selection for sandbox or production
 env: 'sandbox', // sandbox | production
 // PayPal Client IDs, these are the example defaults - replace with your own
 client: {
 sandbox: 'AZDxjDScFpQtjWTOUtWKbyN_bDt4OgqaF4eYXlewfBP4-8aqX3PiV8e1GWU6liB2CUXlkA59kJXE7M6R',
 production: '<insert production client id>'
 },
 // Show the buyer a 'Pay Now' button in the checkout flow
 commit: true,
 // payment() is called when the button is clicked
 payment: function(data, actions) {

 // Make a call to the REST api to create the payment
 return actions.payment.create({
 payment: {
 transactions: [
 {
 // This is your cart totals, shipping, tax etc, just remove items you dont need
 amount: { 
 total: '30.11', 
 currency: 'AUD',
 details: {
 subtotal: '30.00',
 tax: '0.07',
 shipping: '0.03',
 handling_fee: '1.00',
 shipping_discount: '-1.00',
 insurance: '0.01'
 }
 },
 description: 'The payment transaction description.',
 custom: 'EBAY_EMS_90048630024435',
 invoice_number: '48787589673',
 payment_options: {
 allowed_payment_method: 'INSTANT_FUNDING_SOURCE'
 },
 soft_descriptor: 'ECHI5786786',
 item_list: {
 // Loop through your cart here, must add up to sub total set above
 items: [
 {
 name: 'hat',
 description: 'Brown hat.',
 quantity: '5',
 price: '3',
 tax: '0.01',
 sku: '1',
 currency: 'AUD'
 },
 {
 name: 'handbag',
 description: 'Black handbag.',
 quantity: '1',
 price: '15',
 tax: '0.02',
 sku: 'product34',
 currency: 'AUD'
 }
 ],
 shipping_address: {
 recipient_name: 'Brian Robinson',
 line1: '4th Floor',
 line2: 'Unit #34',
 city: 'Sydney',
 country_code: 'AU',
 postal_code: '2000',
 phone: '011862212345678',
 state: 'NSW'
 }

 }
 
 }
 ]
 }
 });
 },
 onAuthorize: function(data, actions) {
 // Make a call to the REST api to execute the payment
 return actions.payment.execute().then(function() {
 // If the transaction is successful on Paypal, you can then Post to a script to run actions on your site like emailing the user etc
 return actions.request.post('complete-order.php', {
 paymentID: data.paymentID,
 payerID: data.payerID
 }).then(function(res) {
 if (res == 'error') {
 // Show an alter if there was an error 
 window.alert('Error');
 } else {
 // Redirect to a success page if everything completed okay
 window.location = 'success.php'; 
 }
 });
 });
 },
 onCancel: function(data, actions) {
 // Show an alert if user cancels
 window.alert('Canceled by user');
 },
 onError: function(err) {
 // Show an alert with error
 window.alert('Error: '+err); 
 }

 }, '#paypal-button-container');

 </script>
</body>
 

A couple of things to note:

  • If you do use tax, shipping or the item properties, these all need to add up correctly otherwise you will get an error.
  • The included onAuthorize code will POST variables over to a script file that you define, this is where you would run all the magic on your website, link firing off emails, adding to a database etc. If successful, the script can also redirect to a success page.
  • You can change the window.alert messages for onError or onCancel to perhaps display notifications in divs based on how your site works, or even redirect the user for example.

A PHP Script For Successful Payments

If you needed to handle successful orders in some way, like sending an email to the user, then here is a very basic PHP script which can be added to:

if ($_POST['paymentID'] && $_POST['payerID']) {
   // add your functions like emailing, adding to database here
   echo "success";
} else {
   echo "error";
}

You can even reference $_POST[‘paymentID’] and $_POST[‘payerID’] returned from Paypal with successful transactions for use in your script.

Sandbox Testing

Before going live, you will want to do some offline / sandbox testing. This was another area that I found very confusing on Paypal’s developer portal.

Here is a very basic run down of the sandbox testing process that worked for myself:

  1. Setup a Paypal business account if you don’t already have access to one
  2. Go to the following page:
    https://developer.paypal.com/developer/applications/create
  3. You need to first create an app, so enter a name and hit create
  4. If successful, you should then be transferred to the Application page, where you can copy the Client ID for use in the above script. There is a toggle button in the top right corner of this page to switch between the sandbox and production (or live as they call it in the portal) versions of the client ID.
  5. Update your code with these IDs and your store name should show up to confirm all is pointing to the right place.
  6. To test in sandbox mode some transactions, you can visit the below link, which should contain a buyer email address, this is your test account, simply expand the email and client on the profile link and it will allow you to set a password
    https://developer.paypal.com/developer/accounts/
  7. You can also use this section to see notifications from your test orders.

I hope this helps someone get this working.