Recurring Payments with Digital Goods for Express Checkout is the 8 word name PayPal chose for their most convenient subscription product. The verbose name is a good indicator of the API’s complexity.
It’s actually quite easy to integrate Digital Goods subscriptions. We send and receive a few HTTP requests and voilà, PayPal creates a subscription.
Nate, a PayPal staff member, helped map the labyrinth with this blog post. He didn’t cover subscriptions though, so this post will. You should read Nate’s post before continuing with this post.
3 Steps to Subscriptions
In a nutshell, the process for creating a subscription is like so:
- Tell PayPal we want to create a subscription;
- Confirm the subscription;
- Activate the subscription.
This process is the same as that outlined in Nate’s blog post. However, the API request strings differ, so this post focuses on the request strings’ content.
You can use all the API request strings provided in this post with the
PPHttpPost() method Nate provides in his example.
Step 1: Request a Token
Before we can have a user agree to pay for a subscription, we need a token from PayPal to represent the subscription.
To request a subscription token, we Nate’s
PPHttpPost() function with the
$my_api_str parameter set to:
$my_api_str = $cred_str . "&METHOD=SetExpressCheckout" . "&RETURNURL=http://example.com/return.php?return=paid" . "&CANCELURL=http://example.com/return.php?return=cancel" . "&BILLINGTYPE=RecurringPayments" . "&BILLINGAGREEMENTDESCRIPTION=" . urlencode("Hacker Monthly Subscription") . "&CURRENCYCODE=USD" . "&MAXAMT=100";
At first, I thought when requesting a token I’d need to tell PayPal the details of the subscription, like the price, duration or frequency – we don’t. We just tell PayPal we want to create a subscription. We give PayPal the details of our subscription only when we activate it.
The MAXAMT Parameter
This parameter indicates the average price per billing period for the subscription. By default, PayPal sets this to $25.
If your subscription is for more than $25 per period, you must include the
MAXAMT parameter with a value equal to or greater than your price per period.
Step 2: Use the token to start the subscription.
Once we have a token and the user has agreed to subscribe, PayPal suggests we have them confirm the charges.
Referring again to Nate’s post, we can use
return.php and get the subscription’s details from PayPal with the API string:
$my_api_str = $cred_str . "&METHOD=GetExpressCheckoutDetails&TOKEN=" . urldecode($token);
We use the
GetExpressCheckoutDetails method regardless of whether the request is for a subscription or one-off purchase.
Although suggested by PayPal, in my opinion, this step is redundant. Display the subscription price, period & frequency before directing the user to PayPal, then they are already aware of the details when they return to the site. In such a case, we can skip this step and go to Step 3.
Step 3: Activate the Subscription
Once a subscriber has confirmed the subscription, we post a request to PayPal to give them the details of the subscription and ask them to activate the subscription.
To do this, we call the
PPHttpPost() function with:
$my_api_str = $cred_str . "&METHOD=CreateRecurringPaymentsProfile" . "&TOKEN=" . $_GET['token'] // Subscription we are activating . "&AMT=" . urlencode( '10.00' ) . "&CURRENCYCODE=USD" . "&PROFILESTARTDATE=" . urlencode( date( 'Y-m-d\TH:i:s', time() + ( 24 * 60 * 60 ) ) ) . "&BILLINGPERIOD=Month" . "&BILLINGFREQUENCY=1" . "&DESC=" . urlencode( 'Time Magazine subscription' ) . "&TOTALBILLINGCYCLES=3" . "&INITAMT=".urlencode("80.00")
This string creates a 3 month subscription for $10 per month, starting from tomorrow, with a $80 sign-up fee. You can customise the NVP parameters in this request to set the price, frequency, duration, sign-up fee and trial period of the subscription.
Never Mind the Bollocks, Here’s the PHP Library
If you want to bypass the PayPal labyrinth altogether, you’re in luck. I’ve released a PayPal Digital Goods PHP Class that is friendly to humans. It’s a work in progress, but it strives to make it simpler to interact with the PayPal API by:
- Human friendly variable names: To reduce request size, PayPal’s API uses shortened parameter names. As we create instances of the class server-side, it can afford to use longer, more human friendly names. For example,
initial_amountrefers to PayPal’s
- Abstracting PayPalisms: PayPal loves verbiage, I don’t. The class attempts to simplify some of PayPal terms to more colloquial terms. For example, the
get_subscription_details()function performs PayPal’s
- Not repeating code: we only need to create one instance of the class for each subscription in our application. The credential & NVP API strings for every request are then automatically built using simple function calls.
Check out the class on GitHub for more information.