From a2ada3b49bd63bcf9c04d3af26afc54931cd8b99 Mon Sep 17 00:00:00 2001 From: Michal Borychowski Date: Thu, 20 Feb 2014 11:09:43 +0100 Subject: [PATCH 1/5] configuration.md: how to use the sandbox environment --- docs/configuration.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 54e7d32..77dde8b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -14,6 +14,11 @@ Credentials consist of the following: Different PayPal APIs use different authentication mechanisms. Consult with the PayPal developer documentation which to use. +In order to run in a sandbox mode use: +```php +Payment::environment(Payment::ENVIRONMENT_SANDBOX); +``` + Instance configuration ---------------------- From 0cc0e67fc5264856e1277317fe1a2c5d6f6c6036 Mon Sep 17 00:00:00 2001 From: Michal Borychowski Date: Thu, 20 Feb 2014 11:20:54 +0100 Subject: [PATCH 2/5] ExpressCheckout: order items are necessary to pass as request params --- .../PayPal/Payment/ExpressCheckout.php | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php b/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php index 4f815a9..14c9bf3 100644 --- a/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php +++ b/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php @@ -26,53 +26,31 @@ public function get_express_checkout_details(array $params) */ public function set_express_checkout(array $params = array()) { + $startParams = array( + 'RETURNURL' => $this->return_url(), + 'CANCELURL' => $this->cancel_url() + ); + $params = array_merge($startParams, $params); + return $this->_request('SetExpressCheckout', $this->_set_params($params)); } public function do_express_checkout_payment($token, $payer_id) { - $order = $this->order(); - - return $this->_request('DoExpressCheckoutPayment', array( - 'TOKEN' => $token, - 'PAYERID' => $payer_id, - - // Total amount of the order - 'PAYMENTREQUEST_0_AMT' => number_format($order['total_price'], 2, '.', ''), - - // Price of the items being sold - 'PAYMENTREQUEST_0_ITEMAMT' => number_format($order['items_price'], 2, '.', ''), - - // Shipping costs for the whole transaction - 'PAYMENTREQUEST_0_SHIPPINGAMT' => number_format($order['shipping_price'], 2, '.', ''), - - 'PAYMENTREQUEST_0_CURRENCYCODE' => $this->config('currency'), + $params = array( + 'TOKEN' => $token, + 'PAYERID' => $payer_id + ); - 'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale' - )); + return $this->_request('DoExpressCheckoutPayment', $this->_set_params($params)); } protected function _set_params(array $params = array()) { - $order = $this->order(); - $defaultParams = array( - // Total amount for the transaction - 'PAYMENTREQUEST_0_AMT' => number_format($order['total_price'], 2, '.', ''), - - // Price of the items being sold - 'PAYMENTREQUEST_0_ITEMAMT' => number_format($order['items_price'], 2, '.', ''), - - // Shipping costs for the whole transaction - 'PAYMENTREQUEST_0_SHIPPINGAMT' => number_format($order['shipping_price'], 2, '.', ''), - 'PAYMENTREQUEST_0_CURRENCYCODE' => $this->config('currency'), 'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', - - 'RETURNURL' => $this->return_url(), - - 'CANCELURL' => $this->cancel_url(), 'useraction' => 'commit', @@ -80,8 +58,22 @@ protected function _set_params(array $params = array()) // For digital goods this field is required and it must be set to 1. 'NOSHIPPING' => 1, + 'REQCONFIRMSHIPPING' => 0, + 'ADDROVERRIDE' => 0, ); + + $totalPrice = 0; + foreach($this->order() as $index => $item) { + $defaultParams['L_PAYMENTREQUEST_0_NAME' . $index] = $item["name"]; + $defaultParams['L_PAYMENTREQUEST_0_AMT' . $index] = $item["price"]; + $defaultParams['L_PAYMENTREQUEST_0_QTY' . $index] = $item["quantity"]; + $defaultParams['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $index] = "Digital"; + + $totalPrice += $item["price"] * $item["quantity"]; + } + $params['PAYMENTREQUEST_0_AMT'] = number_format($totalPrice, 2, '.', ''); + $params = array_merge($defaultParams, $params); if ($this->notify_url()) From e24984861dde07e27f3a8a29ccc55575fabebbaa Mon Sep 17 00:00:00 2001 From: Michal Borychowski Date: Thu, 20 Feb 2014 12:57:51 +0100 Subject: [PATCH 3/5] ExpressCheckout: more detailed documentation --- docs/ExpressCheckout.md | 85 ++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/docs/ExpressCheckout.md b/docs/ExpressCheckout.md index ee1feb6..927984d 100644 --- a/docs/ExpressCheckout.md +++ b/docs/ExpressCheckout.md @@ -1,32 +1,83 @@ +PayPal Express Checkout provides a very easy and user friendly way for users to make payment. All transactions happen in an overlayer modal box or popup window (it mostly depends on the user choice of "Remember Me Cookie"). It seems like users don't need to leave your site during the whole process unlike other methods, where users will be redirected to the 'full' PayPal official site to make payment. + ExpressCheckout does not use any other configurations than those for authentication. -The order has three required fields: - - `total_price` - - `items_price` - - `shipping_price` +The order is an array of items with three required fields: + - `name` + - `price` + - `quantity` **Example**: -``` php +```php +$items = array(); +$items[] = array('name' => 'Item Name #1', 'price' => 3, 'quantity' => 1); +$items[] = array('name' => 'Item Name #2', 'price' => 5, 'quantity' => 3); + $express_checkout = Payment::instance('ExpressCheckout') - ->order(array( - 'items_price' => 50, - 'shipping_price' => 10, - 'total_price' => 60 - )) + ->order($items) ->return_url('example.com/success') - ->cancel_url('example.com/cancelled') - ->notify_url('example.com/ipn'); + ->cancel_url('example.com/cancelled'); $response = $express_checkout ->set_express_checkout(); - -// Redirecting the user to confirm the payment using $response['TOKEN'] +``` -$express_checkout - ->do_express_checkout_payment($response['TOKEN'], $response['PAYERID']); +Now when you have ```$response['TOKEN']``` you need to open a popup with Paypal page: +```html +
+ +
+``` +Upon success Paypal redirects to your ```return_url``` where you need to finally complete the payment and act accordingly: +```php +$params['TOKEN'] = $_REQUEST['token']; +$params['PAYERID'] = $_REQUEST['PayerID']; + +$express_checkout = Payment::instance('ExpressCheckout') + ->order($items); //the same $items as before + +//In $response you'd have some extra important information like transaction id or fees taken by Paypal +$response = $express_checkout + ->do_express_checkout_payment($params['TOKEN'], $params['PAYERID']); + +$ack = strtoupper($response["ACK"]); +if("SUCCESS" == $ack || "SUCCESSWITHWARNING" == $ack) +{ + /* + * TODO: Proceed with desired action after the payment + * (ex: start download, start streaming, add coins to the game, etc.) + */ +} ``` **Notes**: -You should store the token or the whole response in a permanent or a session storage. They will be needed after the user has confirmed the payment on paypal.com. + - You should store the token or the whole response in a permanent or a session storage. They will be needed after the user has confirmed the payment on paypal.com. + + - You also need to have this code before `````` on your website with the Paypal button. A good choice for ```expType``` is ```instant``` but for more options you may refer to [Paypal documentation](https://developer.paypal.com/docs/classic/express-checkout/digital-goods/IntroducingExpressCheckoutDG/). +```html + + +``` + + - Don't forget to close the popup window, you may use a code like this: +```javascript +window.onload = function(){ + if(window.opener){ + window.close(); + } + else{ + if(top.dg.isOpen() == true){ + top.dg.closeFlow(); + return true; + } + } +}; +``` From 50d0d8f2c6979bedaf33bb269e4384f02a4a4d76 Mon Sep 17 00:00:00 2001 From: Michal Borychowski Date: Thu, 20 Feb 2014 14:17:42 +0100 Subject: [PATCH 4/5] ExpressCheckout: ec_form_action_url() for getting the form action url --- src/OpenBuildings/PayPal/Payment/ExpressCheckout.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php b/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php index 14c9bf3..13d3457 100644 --- a/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php +++ b/src/OpenBuildings/PayPal/Payment/ExpressCheckout.php @@ -11,6 +11,16 @@ class Payment_ExpressCheckout extends Payment { const API_VERSION = '98.0'; + const EXPRESSCHECKOUT_FORM_ACTION_END = 'paypal.com/incontext?token='; + + public function ec_form_action_url($token) + { + return Payment::ENDPOINT_START + .Payment::environment() + .self::EXPRESSCHECKOUT_FORM_ACTION_END + .$token; + } + public function get_express_checkout_details(array $params) { if ( ! isset($params['TOKEN'])) From fab632f8f31dd268ad597471d011d46e0ea9a601 Mon Sep 17 00:00:00 2001 From: Michal Borychowski Date: Thu, 20 Feb 2014 14:29:29 +0100 Subject: [PATCH 5/5] ExpressCheckout: documentation update --- docs/ExpressCheckout.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ExpressCheckout.md b/docs/ExpressCheckout.md index 927984d..969bb00 100644 --- a/docs/ExpressCheckout.md +++ b/docs/ExpressCheckout.md @@ -23,7 +23,7 @@ $response = $express_checkout ->set_express_checkout(); ``` -Now when you have ```$response['TOKEN']``` you need to open a popup with Paypal page: +Now when you have ```$response['TOKEN']``` you need to open a popup with Paypal page. You can get valid URL for the form action by ```$express_checkout->ec_form_action_url($response['TOKEN'])```: ```html