PayPal subscriptions allow to enable and manage recurring payments for your service. With this type of payment, PayPal provides options to set the billing interval, frequency, deadline and more. This will send automatic billings to the customer for accessing your service. In this tutorial, we are going to see how to manage recurring payment using PayPal Subscription using PHP.
Integrating PayPal subscription is the 4 step process and the steps are,
The Subscription payment flow will be simple with a two to three steps. Show a subscription button in the application through which you are promoting your product or services. Create a PHP service to invoke the subscription payment code to create and activate/approve the billing plan and agreement.
When the customer clicks the Subscription button, the service will be called to create the billing plan and the billing agreement. On successful creation of the billing agreement, it will be shown to the customer for getting his approval.
When the user approves the agreement or subscription, then the billing will be raised against the subscriber automatically. The subscriber will receive automatic billing in a periodic interval until the deadline. The interval, deadline, and more specifications are set with the billing plan.
In this example, I have implemented recurring payments by accessing REST API by using PayPal PHP SDK. Download the latest SDK library and load it into your application’s vendor folder. Previously, we have seen how to integrate single payment using PayPal payment gateway.
In the process of integrating recurring payment using PayPal Subscriptions, this is the first step to create the billing plan. This plan includes plan details, payment definition, and more. Based on the specification added with this plan, the customer will receive billings for accessing the subscribed services.
The code below shows how to create a plan by specifying the payment options, merchant preferences and more. In this example code, I have set the billing plan name, description and type with the reference of the plan object. Then, I specify payment definition and set charge models for the payment.
In this code, the merchant preferences contain appropriate callback URLs. The auto billing is enabled by setting it as Yes. It will send billing for the outstanding amount in the upcoming immediate payment cycle.
<?php
use PayPal\Api\ChargeModel;
use PayPal\Api\Currency;
use PayPal\Api\MerchantPreferences;
use PayPal\Api\PaymentDefinition;
use PayPal\Api\Plan;
use PayPal\Api\Patch;
use PayPal\Api\PatchRequest;
use PayPal\Common\PayPalModel;
// Create a new billing plan
if (! empty($_POST["plan_name"]) && ! empty($_POST["plan_description"])) {
$plan = new Plan();
$plan->setName($_POST["plan_name"])
->setDescription($_POST["plan_description"])
// Set billing plan definitions
$paymentDefinition = new PaymentDefinition();
$paymentDefinition->setName('Regular Payments')
->setType('REGULAR')
->setFrequency('DAY')
->setFrequencyInterval('1')
->setCycles('3')
->setAmount(new Currency(array(
'value' => 3,
'currency' => 'USD'
)));
// Set charge models
$chargeModel = new ChargeModel();
$chargeModel->setType('SHIPPING')->setAmount(new Currency(array(
'value' => 1,
'currency' => 'USD'
)));
$paymentDefinition->setChargeModels(array(
$chargeModel
));
// Set merchant preferences
$merchantPreferences = new MerchantPreferences();
$merchantPreferences->setReturnUrl('http://<host>/how-to-manage-recurring-payments- using-paypal-subscriptions-in-php/index.php?status=success')
->setCancelUrl('http://<host>/how-to-manage-recurring-payments-using-paypal- subscriptions-in-php/index.php?status=cancel')
->setAutoBillAmount('yes')
->setInitialFailAmountAction('CONTINUE')
->setMaxFailAttempts('0')
->setSetupFee(new Currency(array(
'value' => 1,
'currency' => 'USD'
)));
$plan->setPaymentDefinitions(array(
$paymentDefinition
));
$plan->setMerchantPreferences($merchantPreferences);
try {
$createdPlan = $plan->create($apiContext);
} catch (PayPal\Exception\PayPalConnectionException $ex) {
echo $ex->getCode();
echo $ex->getData();
die($ex);
} catch (Exception $ex) {
die($ex);
}
}
?>
After creating the billing plan, the plan object is used to get the properties to activate the plan. Activating a billing plan is required to prepare the billing agreement. The following code shows how to activate a created plan by patching up the PayPal model array instances.
try {
$patch = new Patch();
$value = new PayPalModel('{"state":"ACTIVE"}');
$patch->setOp('replace')
->setPath('/')
->setValue($value);
$patchRequest = new PatchRequest();
$patchRequest->addPatch($patch);
$createdPlan->update($patchRequest, $apiContext);
$patchedPlan = Plan::get($createdPlan->getId(), $apiContext);
require_once "createPHPTutorialSubscriptionAgreement.php";
} catch (PayPal\Exception\PayPalConnectionException $ex) {
echo $ex->getCode();
echo $ex->getData();
die($ex);
} catch (Exception $ex) {
die($ex);
}
Once the Billing Plan is activated, the request will be sent to prepare the billing agreement. This is supposed to be shown to the customer who wants to subscribe to access your product or application services.
The Billing Agreement instance has to be created to set the plan and payer information for preparing the agreement. In this code, after setting the agreement name, description the activated plan id is set to the agreement object.
It also includes payer and shipping details. Before calling the create-action, all the specifications are set as an object array.
<?php
use PayPal\Api\Agreement;
use PayPal\Api\Payer;
use PayPal\Api\ShippingAddress;
use PayPal\Api\Plan;
// Create new agreement
$startDate = date('c', time() + 3600);
$agreement = new Agreement();
$agreement->setName('PHP Tutorial Plan Subscription Agreement')
->setDescription('PHP Tutorial Plan Subscription Billing Agreement')
->setStartDate($startDate);
// Set plan id
$plan = new Plan();
$plan->setId($patchedPlan->getId());
$agreement->setPlan($plan);
// Add payer type
$payer = new Payer();
$payer->setPaymentMethod('paypal');
$agreement->setPayer($payer);
// Adding shipping details
$shippingAddress = new ShippingAddress();
$shippingAddress->setLine1('111 First Street')
->setCity('Saratoga')
->setState('CA')
->setPostalCode('95070')
->setCountryCode('US');
$agreement->setShippingAddress($shippingAddress);
try {
// Create agreement
$agreement = $agreement->create($apiContext);
// Extract approval URL to redirect user
$approvalUrl = $agreement->getApprovalLink();
header("Location: " . $approvalUrl);
exit();
} catch (PayPal\Exception\PayPalConnectionException $ex) {
echo $ex->getCode();
echo $ex->getData();
die($ex);
} catch (Exception $ex) {
die($ex);
}
?>
On successful billing agreement creation, the agreement object will contain approval-link. This is the URL where the customer has to be redirected to approve the billing agreement.
In the customer approval page, PayPal will show the option to agree and pay to access the services. By clicking the agree button then the customer has been considered as a subscriber until the subscription deadline if any.
When the customer approves the agreement and wants to continue payment, then return callback will be called as specified in the billing plan.
With this callback URL, the token will be sent with the query string. By using this token the agreement or subscription will be executed to process the payment.
if (!empty($_GET['status'])) {
if($_GET['status'] == "success") {
$token = $_GET['token'];
$agreement = new \PayPal\Api\Agreement();
try {
// Execute agreement
$agreement->execute($token, $apiContext);
} catch (PayPal\Exception\PayPalConnectionException $ex) {
echo $ex->getCode();
echo $ex->getData();
die($ex);
} catch (Exception $ex) {
die($ex);
}
} else {
echo "user canceled agreement";
}
exit;
}
The following HTML code is to display subscribe option to the customers. The subscription box will show the details about the services that the customer can access after successful subscription.
This box contains a HTML form with the plan title and description. By clicking the Subscribe button, the plan details will be posted to the PHP to process the steps we have discussed above.
In the PHP code, the PayPal API authentication request will be sent before creating the billing plan and agreement to be approved by the customer
<div id="subscription-plan">
<div class="plan-info">PHP jQuery Tutorials</div>
<div class="plan-desc">Read tutorials to learn PHP.</div>
<div class="price">$49 / month</div>
<div>
<form method="post">
<input type="hidden" name="plan_name"
value="PHP jQuery Tutorials" /> <input type="hidden"
name="plan_description"
value="Tutorials access to learn PHP with simple examples." />
<input type="submit" name="subscribe" value="Subscribe"
class="btn-subscribe" />
</form>
</div>
</div>
And the styles are,
body {
font-family: Arial;
color: #212121;
}
#subscription-plan {
padding: 20px;
border: #E0E0E0 2px solid;
text-align: center;
width: 200px;
border-radius: 3px;
margin: 40px auto;
}
.plan-info {
font-size: 1em;
}
.plan-desc {
margin: 10px 0px 20px 0px;
color: #a3a3a3;
font-size: 0.95em;
}
.price {
font-size: 1.5em;
padding: 30px 0px;
border-top: #f3f1f1 1px solid;
}
.btn-subscribe {
padding: 10px;
background: #e2bf56;
width: 100%;
border-radius: 3px;
border: #d4b759 1px solid;
font-size: 0.95em;
}
This PHP code will be executed on submitting the subscription form with the billing plan details. This code gets the PayPal API context object by authenticating with the API credentials. Replace the CLIENT_ID and CLIENT_SECRET which you have got by creating the PayPal REST API App. We have already seen about this while implementing PayPal Checkout.
<?php
require 'vendor/PayPal-PHP-SDK/autoload.php';
$apiContext = new \PayPal\Rest\ApiContext(new \PayPal\Auth\OAuthTokenCredential('CLIENT_ID', 'CLIENT_SECRET'));
if (! empty($_POST["subscribe"])) {
require_once "./Service/createPHPTutorialSubscriptionPlan.php";
}
?>
The following screenshot shows the output for the landing page that is created with the subscribe option.
What about capture the payment? Talking about Recurring Payments, capture the payments does not exists? Is automatic? How it works?
Rodrigo,
This can be used in usecases where you want to make monthly recurring automated payments. You will get consent from the user for monthly deductions and automatically charge their cards.
Hi, Firstly I’d like to thank you for the tutorial, it was very helpful! THANKS!
I have a question though, what about recurring “user-seat” based payments.
My recurring payments would have to be based on the number of users using my software, I’d charge 5$ for each user, for an example.
Have you ever implemented something like that?
Hi Victor,
Welcome! What you ask for requires custom logic. It is about how we arrive at the number that is going to be posted to PayPal. Sometimes, it will be a fixed amount, sometimes a derived amount. It depends on the specific business needs.
Hi Vincy,
Great tutorial about PayPal Subscription, but how store transactions into mySQL database?
Thanks
Thanks Martin. That requires custom coding / logic. I am planning to write a follow up article and focus on it in detail.
Thank you for taking your time and share this great tutorial!
I’m wondering, my clients need to create a PayPal account to process the payment?
Welcome Ivan. Yes a PayPal account is needed to process the payment.