I am using the PayPal REST API to get information about a subscription after the user purchases.
The JS of Paypal suggests that on the onApprove event, we can for example redirect to a thank you page, and it provides us the Subscription ID.
Thus, one would assume the Subscription is done at this point, and one would assume that calling this REST route https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_transactions would return results. Yet, it does not -- initially.
It takes up to 10 minutes for the https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_transactions call to return anything else than an empty JSON string.
My code is pretty simple:
On onApprove I pass the approved subscription ID in a redirect to a page. When that page loads, I use https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_transactions via PHP cURL to get details of that transaction (buyer email) and check in my database if that email exists. If it exists, I redirect to another page, if not, I stay on this page.
Dead simple, and it works just fine - apart of course that PayPal takes about 10 minutes to actually return the transaction results.
Yes, I could add delays, but this is not the point. The point is that PayPal says the transaction is made, when the onApprove event happens. Thus, the data must be available in the REST API too. Is this a known issue? What can be done to avoid this delay? I fear the delay is probably arbitrary and might be more than 10 minutes for other users?
Here is the code I use:
JS button approval flow
<div id="paypal-button-container-P-1UU44524AX8090809MMVRJ3Y"></div>
<script src="https://www.paypal.com/sdk/js?client-id=AS-0AbQhD8wSxv0XMvjeRTAUsa-aZtSZm3fSq-qDp_ibhlq9S5XrkgCVDjchICdKS2IZP7IKVo-MTdz7&vault=true&intent=subscription" data-sdk-integration-source="button-factory" data-namespace = "paypal_sdk"></script>
<script>
paypal_sdk.Buttons({
style: {
shape: 'rect',
color: 'white',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: 'P-1UU44524AX8090809MMVRJ3Y'
});
},
onApprove: function(data, actions) {
window.location.replace("https://www.my-site.com/create-account/?subscription_id=" + data.subscriptionID);
}
}).render('#paypal-button-container-P-1UU44524AX8090809MMVRJ3Y'); // Renders the PayPal button
</script>
Server-side process when loading https://www.my-site.com/create-account/?subscription_id=" + data.subscriptionID
<?php
if ( isset( $_GET['subscription_id'] )
&& ! empty( $_GET['subscription_id'] )
&& is_page( 'create-account' )
) {
/**
* Get Access Token
*/
$ch_auth = curl_init();
curl_setopt($ch_auth, CURLOPT_URL, 'https://api-m.sandbox.paypal.com/v1/oauth2/token');
curl_setopt($ch_auth, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch_auth, CURLOPT_POST, 1);
curl_setopt($ch_auth, CURLOPT_POSTFIELDS, "grant_type=client_credentials");
curl_setopt($ch_auth, CURLOPT_USERPWD, 'USR' . ':' . 'PWD');
$headers_auth = array();
$headers_auth[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch_auth, CURLOPT_HTTPHEADER, $headers_auth);
$result_auth = curl_exec($ch_auth);
if (curl_errno($ch_auth)) {
echo 'Error:' . curl_error($ch_auth);
}
curl_close($ch_auth);
$auth_arr = json_decode($result_auth);
$auth = $auth_arr->access_token;
/**
* Get Subscription details
*/
$ch_sub = curl_init();
curl_setopt($ch_sub, CURLOPT_URL, 'https://api-m.sandbox.paypal.com/v1/billing/subscriptions/'.$_GET['subscription_id'].'/transactions?start_time=2022-01-21T07:50:20.940Z&end_time=2022-09-24T07:50:20.940Z');
curl_setopt($ch_sub, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch_sub, CURLOPT_CUSTOMREQUEST, 'GET');
$headers_sub = array();
$headers_sub[] = 'Content-Type: application/json';
$headers_sub[] = 'Authorization: Bearer ' . $auth;
curl_setopt($ch_sub, CURLOPT_HTTPHEADER, $headers_sub);
$result_sub = curl_exec($ch_sub);
if (curl_errno($ch_sub)) {
echo 'Error:' . curl_error($ch_sub);
}
curl_close($ch_sub);
$first = end(json_decode($result_sub)->transactions)->payer_name->given_name;
$last = end(json_decode($result_sub)->transactions)->payer_name->surname;
$mail = end(json_decode($result_sub)->transactions)->payer_email;
$exists = email_exists( $mail );
if ( $exists ) {
header('Location: '.'https://www.my-site.com/account/?subscription_id=' . $_GET['subscription_id'] . '&account=' . $exists);
die();
}
}
This always fails until I reload the page something between once and 100 times (it varies)