In the ever changing world of website development, there are often times when a peculiar request from a client forms the bedrock of a new product that answers the call of many ailing web developers.
This is a story of one such request that we took an as an opportunity to develop something new and robust.
The Background:
There is a sports-niche coaching website that we have developed and have been continuously adding features to it since the last 2 years.
The most recent request from the client focused on facilitating Recurring Payments for users who have subscribed to the coaching programme.
The twist in the tale was that the client also requested that the Recurring Payments be split in several parts.
This was a challenge as in its current form – WooCommerce Recurring payments do not support Payment Splitting.
The crux of this task lies in customising these two robust plugins – PayPal Adaptive & WooCommerce Subscription – and then coupling their code structure and integrations into one strong and cohesive plugin that allows for Recurring Subscription Payment With Split Functionality.
We have had good hands at customising Payment-Order systems before as well – here you can read about how we Split Magento Orders for one of our clients.
This blog details how we combined the goodness of the WooCommerce Subscription plugin and PayPal Adaptive plugin to fulfill the client’s request and in the process developed a robust plugin geared towards enabling the web developers to add another dimension to the website payment integration of WooCommerce and PayPal.
The Basic Setup:
As of now, WooCommerce offers two different kinds of payment modes:
-
- Simple Payment Method – where in one-time funds are transferred from the buyer to the seller.
- Subscription Payment Method – wherein the buyers have to pay a certain amount of money on a periodic basis to the seller.
PayPal, on the other hand, also facilitates Split payments with WooCommerce – they call it PayPal Adaptive. Split payments are useful in cases where the cost of a product/service has to be divided into multiple parts.
A common instance of this kind of integration is when a commission has to be paid by the seller on each order on the website.
Our focus for this blog will be on the Subscription & Split Payment methods.
While WooCommerce integration with PayPal is fairly straightforward with Simple Payment method, it’s unheard of with PayPal Adaptive.
The Way It Works: WooCommerce Subscription
For the uninitiated, the way WooCommerce Subscription works is that a product is firstly assigned as a “Simple Subscription” product.
Once a product is set as a subscription product, the details regarding the price of the product, the period of active subscription among other details are entered by the website’s admin.
Every time, a user “subscribes” to a product/service, an “Approval Request” is sent to the user during the checkout process.
Once the user “approves” the subscription, an “Approval Key” is generated in WooCommerce that stores all the details related to the subscription such as the value of the order, date of the subscription, and other information regarding the subscription.
This approval key is stored for each user in WooCommerce which is then used to verify the next subscription cycle.
Taming The Beasts – How We Did The Integration
The focal point of this integration revolves around the fact that both the plugins have a different code structure and an entirely different set of parameters.
For the final plugin, we used PayPal Adaptive’s code to implement Split Payments and WooCommerce’s Subscription Plugin’s code to realise the Recurring Subscription feature for the plugin.
For this particular integration, the target file that was altered and modified as per the WooCommerce’s code structure was: class-wc-paypal-adaptive-payments-gateway.php
Below are the module-wise steps with code snippets for better understanding of the process:
Modifications To The PayPal Adaptive: Generating The Approval Key
The below code snippets detail the process of generating an Approval key:
Using Order Request From Payment Data
$params = array(
'body' => json_encode( $data ),
'timeout' => 60,
'httpversion' => '1.1',
'headers' => array(
'X-PAYPAL-SECURITY-USERID' => $this->api_username,
'X-PAYPAL-SECURITY-PASSWORD' => $this->api_password,
'X-PAYPAL-SECURITY-SIGNATURE' => $this->api_signature,
'X-PAYPAL-REQUEST-DATA-FORMAT' => 'JSON',
'X-PAYPAL-RESPONSE-DATA-FORMAT' => 'JSON',
'X-PAYPAL-APPLICATION-ID' => $this->app_id,
)
);
$response = wp_safe_remote_post( $url . 'Preapproval', $params );
Checking For The Approval Key From The Response Data:
$args = array(
'ClientDetails' => array(
'applicationId' => $memos,
),
'startingDate' => gmdate("Y-m-d\TH:i:s\Z"),
'endingDate' => $final_end_date,
'maxAmountPerPayment' => $order_total_at_one_time,
'maxNumberOfPayments' => $maxNumberOfPayments,
'maxTotalAmountOfAllPayments' => $maxTotalAmountOfAllPayments,
'maxNumberOfPaymentsPerPeriod' => 1,
'currencyCode' => get_woocommerce_currency(),
'returnUrl' => $sucess_url_new,
'cancelUrl' => str_replace('&', '&', $order->get_cancel_order_url()),
'memo' => $memos,
'requestEnvelope' => array(
'errorLanguage' => 'en_US',
'detailLevel' => 'ReturnAll'
)
);
Updating The Post Meta To Process The Recurring Payments For Later:
if ( 200 == $response['response']['code'] && 'OK' == $response['response']['message'] ) {
$body = json_decode( $response['body'], true );
if ( isset( $body['preapprovalKey'] ) ) {
$pay_key = esc_attr( $body['preapprovalKey'] );
if ( 'yes' == $this->debug ) {
$this->log->add( $this->id, 'Payment key successfully created! The key is: ' . $pay_key );
}
// Just set the payment options.
//store this paykey for fututre use
update_post_meta( $order_id, '_preapproval_Key', $pay_key );
update_post_meta( $order_id, '_paypal_adaptive_all_receivers', $product_receivers_current);
return array( ‘success’ => true, ‘message’ => ”, ‘key’ => $pay_key ); }
if ( isset( $body[‘error’] ) ) { if ( ‘yes’ == $this->debug ) { $this->log->add( $this->id, ‘Failed to generate the payment key: ‘ . print_r( $body, true ) ); }
foreach ( $body[‘error’] as $error ) {
if ( ‘579042’ == $error[‘errorId’] ) { $error_message = sprintf( __( ‘Your order has expired, please %s to try again.’, ‘woocommerce-gateway-paypal-adaptive-payments’ ), ” . __( ‘click here’, ‘woocommerce-gateway-paypal-adaptive-payments’ ) . ” ); break; } else if ( isset( $error[‘message’] ) ) { $order->add_order_note( sprintf( __( ‘PayPal Adaptive Payments error: %s’, ‘woocommerce-gateway-paypal-adaptive-payments’ ), esc_html( $error[‘message’] ) ) ); } } } }
Redirecting The User To PayPal After Successful Creation of Approval Key:
return array(
'result' => 'success',
'redirect' => esc_url_raw( add_query_arg( array( 'cmd' => '_ap-preapproval', 'preapprovalkey' => $payment_data['key'] ), $url ) )
);
After the user logs into the PayPal, he/she will be able to see a approve button clicking on which redirects the user onto the Thank-You page.
Cron Job:
The integration also required the implementation of a Cron Job that could repeatedly sweep all the existing orders to identify the orders that require Recurring Subscription Payments.
The Cron Job is executed twice a day in our plugin; however, you can set it for as many times as you prefer.
-
- Create a file within the PayPal adaptive payment plugin
- Include the wp-load.php
- Now setup the Cron Job /path for that particular file
- To verify if the Cron Job is working or not, test for a PHP mail function – if the mail is received successfully, then the Cron Job is working fine.
Setting Up A Curl Function
Since our custom plugin has PayPal Adaptive as the major component, the user will be redirected to PayPal portal once the “Approval Key” is successfully created.
In order to avoid this redirection and to process the recurring autonomously on the website itself, we also implemented a Curl function.
Curl: A command line tool and library for transferring data with URL, execute it and take a valuable response from there.
Below is the code snippet for the Curl implementation:
a) Initializing the Curl
$ch = curl_init();
b) Setting Up The Curl Variable
curl_setopt($ch, CURLOPT_URL, $url . 'Pay');
curl_setopt($ch, CURLOPT_VERBOSE, 1);
c) Executing The Curl To Get A Valid Response
$response = curl_exec($ch);
Here is the complete code snippet to set up the curl to make the payment from your own end :
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url . 'Pay');
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"X-PAYPAL-SECURITY-USERID: " . $api_username,
"X-PAYPAL-SECURITY-PASSWORD: " . $api_password,
"X-PAYPAL-SECURITY-SIGNATURE: " . $api_signature,
"X-PAYPAL-REQUEST-DATA-FORMAT: NV",
"X-PAYPAL-RESPONSE-DATA-FORMAT: JSON",
"X-PAYPAL-APPLICATION-ID: " . $app_id,
));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
$responsefrompayment = curl_exec($ch);
The response from the Payment action will be received in the JSON format as set in “X-PAYPAL-RESPONSE-DATA-FORMAT: JSON”,
Once these independent modules were crafted, we integrated all these modules into one plugin, thereby delivering to the client’s requirement and coming out with a robust plugin in the end.
And after all these WooCommerce tricks, we recently delved into a Shopify project where we were tasked to deliver a custom feature. The client wanted us to help them add a functionality that allowed them to add Custom Product Filters to their Shopify store.
Here is another quick post that we did earlier back in 2016 comparing WooCommerce vs Shopify – as an eCommerce Store Solution.
If you wish to have the same implemented on your website, feel free to drop us a mail at info@clixlogix.com – we’ll be more than happy to help you with the integration.