Today I would like to describe our updated Subscriptions module for PrestaShop, which lets customers to purchase a product periodically (for instance, each Monday every week).
The first version of the module received a lot of feedback on how to improve the performance as well as a lot of feature requests. One of the requests was to let you subscribe to a specific product, so you would not need to return back to the product page each time to pay for it. The problem was that not every payment processor lets you to pay for products without manual transaction approve. It is also hard to create a multi-platform integrator for the most of popular payment processors. However, it appeared, that PayPal had the functionality that could meet our demands, specifically the Subscribe Buttons feature. This function lets you pay for products via your PayPal account:
Or by your credit card:
In order to add Subscribe Button widget to the Subscriptions module I used PayPal SOAP API. PayPal suggests using Button Manager PHP SDK for developers (you can find many more libraries on the sdks list).
So, let’s begin: we will need to create a business PayPal account to get access to the PayPal SOAP API. You can create account on the PayPal Developer portal (later use it even for testing purposes). We need to create and place the Subscribe button somewhere on the website (for instance, product page) to let customers subscribe for the product. For that we will use this code:
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 |
$config = array( //live or sandbox mode 'mode' => Configuration::get('PPS_MODE') ? 'sandbox' : 'live', //user name, password, signature with you business account 'acct1.UserName' => ‘user_name’, 'acct1.Password' => ‘************’, 'acct1.Signature' => ‘signature’, ); $buttonCreateReq = new \PayPal\PayPalAPI\BMCreateButtonReq(); $buttonCreateReq->BMCreateButtonRequest = new \PayPal\PayPalAPI\BMCreateButtonRequestType(); //type button $buttonCreateReq->BMCreateButtonRequest->ButtonType = 'SUBSCRIBE'; $buttonCreateReq->BMCreateButtonRequest->ButtonSubType = 'PRODUCTS'; $ButtonVar = array( 'item_name' => $product->name, 'item_number' => $period_name, 'currency_code' => $this->context->currency->iso_code, 'custom' => 'id_product:' . $id_product, 'a3' => $product->getPrice(), 't3' => $period, 'p3' => $count, 'src' => 1, 'notify_url' => Tools::getHttpHost(true) . __PS_BASE_URI__ . 'modules/' . $this->name . '/notify.php', 'return' => $this->context->link->getProductLink($product), 'cancel_return' => $this->context->link->getProductLink($product), 'rm' => 2, ); //method setButtonVar return array('a3=10.50', …); $buttonCreateReq->BMCreateButtonRequest->ButtonVar = $this->setButtonVar($ButtonVar); $paypalService = new \PayPal\Service\PayPalAPIInterfaceServiceService($config); $buttonCreateResponse = $paypalService->BMCreateButton($buttonCreateReq); if(strtoupper($buttonCreateResponse->Ack) == 'SUCCESS') { // Success return $buttonCreateResponse; } |
This gives us back a “Subscribe button” code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
PayPal\PayPalAPI\BMCreateButtonResponseType Object ( [Website] => <form target="_top" action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post"> <input type="hidden" name="cmd" value="_s-xclick"> <input type="hidden" name="hosted_button_id" value="XYBSXRBVLU93Y"> <input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_subscribe_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"> <img alt="" border="0" src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1"> </form> [Email] => https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XYBSXRBVLU93Y [Mobile] => [HostedButtonID] => XYBSXRBVLU93Y [Timestamp] => 2016-03-06T08:40:02Z [Ack] => Success [CorrelationID] => 8795584dcdeb4 [Errors] => [Version] => 106.0 [Build] => 18316154 ) |
Now to subscribe a customer we can either place HTML code from the $responce->Website property directly on the page or use the link from $responce->Email to redirect a customer to the subscription page.
Some situations require to modify already created subscription based on the dynamic customer’s choice. In this case we can use the Update button method:
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 |
$config = array( //live or sandbox mode 'mode' => Configuration::get('PPS_MODE') ? 'sandbox' : 'live', //user name, password, signature with you business account 'acct1.UserName' => ‘user_name’, 'acct1.Password' => ‘************’, 'acct1.Signature' => ‘signature’, ); $updateButtonReq = new \PayPal\PayPalAPI\BMUpdateButtonReq(); $updateButtonReq->BMUpdateButtonRequest = new \PayPal\PayPalAPI\BMUpdateButtonRequestType(); $updateButtonReq->BMUpdateButtonRequest->ButtonType = 'SUBSCRIBE'; $updateButtonReq->BMUpdateButtonRequest->ButtonSubType = 'PRODUCTS'; //id previously created subscription button $updateButtonReq->BMUpdateButtonRequest->HostedButtonID = $HostedButtonID; $ButtonVar = array( 'item_name' => $product->name, 'item_number' => $period_name, 'currency_code' => $this->context->currency->iso_code, 'custom' => serialize($custom_data), 'a3' => $product->getPrice(), 't3' => $period, 'p3' => $count, 'src' => 1, 'notify_url' => Tools::getHttpHost(true) . __PS_BASE_URI__ . 'modules/' . $this->name . '/notify.php', 'return' => $this->context->link->getProductLink($product), 'cancel_return' => $this->context->link->getProductLink($product), 'rm' => 2, ); //method setButtonVar return array('a3=10.50', …); $updateButtonReq->BMUpdateButtonRequest->ButtonVar = $this->setButtonVar($ButtonVar); $paypalService = new \PayPal\Service\PayPalAPIInterfaceServiceService($config); $buttonUpdateResponse = $paypalService->BMUpdateButton($updateButtonReq); if(strtoupper($buttonUpdateResponse->Ack) == 'SUCCESS') { // Success return $buttonUpdateResponse; } |
It is all practically the same except that we are using the classes BMUpdateButtonReq and HostedButtonID (this is the id of the subscription button that we already have created).
This solution will let customers to use subscriptions and automatic payments functionality on the store, while the site owner will be receiving all the information about the payments and products delivery.
Brilliant post. Helped me with these bloody settings.