Managing a subscription
If you're using Digital River's subscription service, gain a better understanding of how to manage subscriptions after the acquisition process is complete
If you're using Digital River's subscription service, you'll need to manage the subscription after completing the acquisition checkout process. On this page, you'll find information on how to:
Activating a subscription
After the order's state
moves to accepted
, you can activate a subscription. To do this, retrieve each items[].subscriptionInfo.subscriptionId
from the data.object
of the event with a type
of order.accepted
and send it as a path parameter in a POST /subscriptions/{subscriptionId}
.
If you're using the Direct Integrations checkout solution, you could also get each items[].subscriptionInfo.subscriptionId
from the body of the POST/ orders
response.
In the body of the request, set state
to active
.
No other values can be sent in the body of this request. If you attempt to do so, then the following error is returned:
You can activate a subscription any time after an order's state
moves to accepted
. For example, if you're selling a digital service subscription that requires no provisioning, you might build your integration so that the activation request is immediately submitted. In other scenarios, such as when a customer must install and initialize a device, you may decide to build a delay into the activation process.
When you activate the subscription, we search the acquisition order for the primary payment source, retrieve its identifier, and assign that value to sourceId
in the subscription object. On the next invoice date, we then both create a charge and attempt to capture payment using this reusable source.
After activation, the following key subscription attributes are populated: contractBindingUntil
, nextReminderDate
, currentPeriodEndDate
, nextInvoiceDate
, and activated
.
Every subscription contains a billingAgreementId
that references a billing agreement. For PSD2 and SCA compliance purposes, we continue to associate this billing agreement with the subscription throughout the subscription's lifecycle.
Fulfilling the acquisition
Once the order's state
is accepted
, you should fulfill the goods and then submit the payment capture request.
Notifying customers of a subscription acquisition
Once a subscription is successfully acquired, you can use the event with a type
of order.accepted
to trigger an acquisition confirmation notification.
Renewing subscriptions
On a subscription's nextReminderDate
, make sure you send a renewal reminder to customers. Your integration should also be able to handle both successful and failed billing attempts.
Sending a reminder
Before attempting to collect a recurring payment, our subscription service determines whether the necessary pre-conditions are met. If they are, the service opens a draft
invoice and, on the subscription's nextRemiderDate
, creates an event with a type
of subscription.reminder
.
You can configure when you receive this event by setting the plan's reminderOffsetDays
.
The event's data.object
contains the subscription
along with an invoice
.
Use the event's data to obtain the customer's contact information and populate your renewal reminder notification. This notification (typically an email) should include the subscription's name and a description of its goods, the amount the customer is to be charged, and the upcoming billing date.
A complete list of renewal reminder requirements is included in the Subscription Notifications article (refer to Learning tools for access information).
In invoice.items[].productDetails
you can access the subscription's product data (such as name
, description
, image
, and url
) and pass this information to customers in the notification, thereby making them aware of what they're being billed for.
For details, refer to How Digital River returns product data.
There are numerous ways to build your notification. However, we suggest that you convert any date-time values into a more human-readable form. The following are some (partial) examples of what you might add:
This is a reminder that your invoice.description
subscription is set to renew on or after nextInvoiceDate
. To ensure that your subscription continues without interruption, your creditCard.brand
credit card ending in creditCard.lastFourDigits
will be charged invoice.totalAmount
in invoice.currency
.
For digital services (such as SaaS), you might also want to include the date and time that customers activated their subscription:
You activated your subscription via our online store on stateTransitions.activated
.
Additionally, we suggest you use the reminder event to determine whether the subscription's designated credit card is set to expire before the nextInvoiceDate
. If this is the case, remind customers to update their payment information and provide a link to the appropriate page on your site. For example:
We noticed that your credit card ending in lastFourDigits
is set to expire expirationMonth
, expirationYear
. This expiration date is prior to your next recurring payment on nextInvoiceDate
. To avoid disruptions to your subscription, please visit your account management page and update your payment information.
Handling successful renewals
To be notified of a successful billing attempt, configure a webhook to listen for the event with a type
of subscription.extended
.
The event's data.object
contains the subscription
along with the invoice
used to capture payment. Since settlement has successfully occurred, the invoice's state
is paid
.
You could handle subscription.extended
by calling a function that moves the subscription in your system into a ready to fulfill state and then initiates the fulfillment process.
The event should also trigger a renewal confirmation message that gets sent to the customer. The following is a partial list of the data you might retrieve from the event and pass in this notification:
orderId
: Gives customers access to the identifier of the transaction's order.nextInvoiceDate
: Provides customers with the date of the next billing attempt.name
andimage
initems[].productDetails
: Reminds customers what products and/or services are included in the subscription.payment.sources[]
: Contains source data that you can share with customers so they have basic information on what payment method is funding the subscription.totalAmount
andtotalTax
: Informs customers how much they were charged and taxed. The event also contains similar amounts at theitems[]
-level.
The Subscription Notifications article (refer to Learning tools for access information) provides a comprehensive list of the information you're required to include in the renewal notification.
Handling failed renewals
To be notified of renewal problems, you can configure a webhook(s) to listen for:
Invalid sources and lapsed subscriptions
If Digital River can't create a billing invoice because there's a problem with the subscription's saved source (in the case of credit cards, this is often an invalid expiration date), then we create an event with a type
of subscription.invalid_source
.
We recommend handling it by informing shoppers that their subscription is at risk of cancellation, requesting a different payment method from them, and then, assuming they provide this information, updating the subscription's source.
If you don't make this update during the grace period (i.e., the collectionPeriodDays
of the subscription’s plan), then Digital River moves the subscription’s state
to lapsed
and creates subscription.lapsed
.
Since this is a terminal state
, reactivating the subscription isn't possible, which means you'll likely want to discontinue customers' access to the service and provide instructions on how to restore it.
Payment failures
An event with a type
of subscription.payment_failed
indicates that Digital River's autorenewal service made an unsuccessful attempt to capture payment.
The event's data.object
contains both the subscription
and the invoice
.
The event most likely stems from changes to the subscription's payment source. For example, if a subscription is funded with a credit card, its billing address could have changed, the customer might have cancelled it, or it might have reached its credit limit.
However, since the state
of the subscription remains activePendingInvoice
, you might still be able to collect payment.
Whatever the structure of your dunning process, we recommend you handle subscription.payment_failed
by using the event's data.object
to construct a billing failed notification that:
Informs customers of the failed payment capture attempt. For example: We were unable to charge your
creditCard.brand
ending increditCard.lastFourDigits
.\Provides a link to a page on your site where customers can resolve the issue. For example: To avoid disruptions to your subscription, please visit your account management page.\
Provide your contact information. For example: If you have any questions, visit our support site at <web address>, contact us at <email address>, or call <phone number>.
If customers click the link, redirect them to a page where they can provide a new payment method.
For details, refer to Account management flows on the Building payment workflows page.
Once you create a new source or authenticate an existing source, you must associate it with the customer.
You'll also need to pass the source's identifier in the body of an update subscription request.
Before the next billing attempt, Digital River voids the invoice that we couldn't collect and creates a new invoice using the subscription's updated source.
Subscription failures
An event with a type
of subscription.failed
indicates that our autorenewal service was unable to capture payment during the designated collection period. As a result, the invoice has become uncollectible
and the subscription has moved into a terminally failed
state.
We recommend you handle subscription.failed
by setting the status of the subscription in your own system to failed as well.
You should also send customers a failure notification that provides them the ability to reactivate their subscription. If customers select this option, you'll need to take them through the acquisition process again.
For example, the notification might:
Inform customers of the failed renewal. Despite repeated attempts, we were unable to charge your designated payment method, and as a result, your subscription has been deactivated. \
Provide a link to the page on your site where customers can resolve the issue. To reactivate your subscription, please visit your account management page. \
Provide your contact information. If you have any questions, visit our support site at <web address>, contact us at <email address>, or call <phone number>.
Trial subscription management
In this section, you'll find information on:
Activating trial subscriptions
You can use the same process to activate both trial and non-trial subscriptions. For details, refer to Activating a subscription.
Once activated, a free trial subscription's state
transitions from draft
to activeFree
and the activatedFree
timestamp is populated.
Updating the subscription's price and plan
Immediately following a successful activation request, we recommend that your integration use a POST /subscriptions/{id}
to (1) update the subscription's planId
so that it references a paid period plan and, (2) for each items[]
, set the price
or aggregatePrice
equal to the post-trial period amount that customers agreed to pay during the subscription acquisition process.
After you submit this request, the subscription's planId
references the paid period plan. However, until currentPeriodEndDate
elapses, the trial period plan controls the subscription's behavior.
On the nextReminderDate
, Digital River creates an event whose type
is subscription.reminder
and whose data.object
contains an invoice in a draft
state.
Assuming you updated the subscription's items[].price
or items[].aggregatePrice
, the invoice's totalAmount
will be greater than zero and equal to the aggregated price of all the subscription's items[]
, plus taxes and fees calculated by Digital River.
This totalAmount
is how much customers will be charged for the subscription's nextInvoiceDate
, which (if you configured your trial period plan correctly) should be the same as the currentPeriodEndDate
. In other words, customers won't be charged until the free trial period is over.
Handling trial conversions
Before a trial converts to a paid subscription, you should send customers an expiration reminder. After a successful conversion occurs, make sure you also send a conversion notification.
Sending a free trial expiration reminder
We recommend that you use subscription.reminder
to trigger an email (or some other type of notification) to the customer. In the event's payload, currentPeriodEndDate
, nextInvoiceDate
, and totalAmount
provide the data you need to inform customers (1) on what date their free trial is scheduled to expire, (2) when their first payment is scheduled, and (3) in what amount.
Sending a trial conversion notification
On the nextInvoiceDate
, Digital River moves the invoice to open
and the subscription to activePendingInvoice
and then attempts to collect payment for the number of days specified by the trial period plan's collectionPeriodDays
.
If any of these collection attempts are successful, Digital River marks the invoice as paid
and the subscription as active
, populates the subscription's activated
timestamp and creates an event whose type
is subscription.extended
.
You should use subscription.extended
as a trigger to notify customers that the trial has been converted into a paid subscription.
If payment capture fails, then the invoice becomes uncollectible
and the subscription moves into a failed
state. To learn more, refer to Handling failed renewals.
Ending trial subscriptions
To avoid getting charged, customers may opt to cancel their subscription during its trial period. In these cases, you have two options:
If the subscription's
state
isdraft
(i.e, you haven't activated it yet), you should delete the subscription.If you activated the subscription (i.e., its
state
isactiveFree
) then cancel the subscription.
Extending free trial periods
Sometimes you might want to extend a customer's free trial period or keep customers at a no-charge level indefinitely. To do this, after you activate the subscription, do not update its price. By not performing this operation, a subscription's items[]
will have a price
or aggregatePrice
of 0.0
on the nextInvoiceDate
, and, as a result, Digital River doesn't make any invoice collection attempts, and the subscription's state
remains activeFree
.
Reverting to a free subscription
You can also push an active
subscription back into an activeFree
state. This is useful if you offer various subscription pricing tiers and customers request that their access be downgraded to the basic, free level.
To do this, send a POST /subscriptions/{id}
request that updates the price
or aggregatePrice
of each of the subscription's items[]
to 0.0
and the planId
to an appropriate plan. On the nextInvoiceDate
, the subscription's state
reverts to activeFree
.
Modifying subscription payments
For more details on how subscriptions can be modified, refer to Updating subscriptions.
When customers want to manage their subscriptions, you can retrieve a list of subscriptions associated with their record:
For each subscription, access its payment source by passing sourceId
in a GET /sources/{sourceId}
request.
To modify a subscription's payment source, its state
must be active
, activeFree
, or activePendingInvoice
. If this precondition is met, you can:
Update credit card information
If a subscription's sourceId
references a source with a type
of creditCard
, then you can provide customers the ability to update that card's billing information or expiration date.
If you want to display the card's current billing information and card information to customers, you can retrieve that data from the source's owner
and creditCard
blocks.
Billing address information
If customers opt to edit their billing information, present them with a form to enter the full name, email, and address (line 1, line 2, city, state, country, postal code) associated with the credit card.
Card expiration date
If customers opt to edit their credit card's expiration date, use a cardexpiration
element to provide them with an input field.
Configuring the update source method
Once customers enter and save their changes, pass the submitted data to updateSource()
. Make sure you configure the appropriate version of the method, depending on whether customers submit updated (a) billing address information, (b) card expiration information, or (c) both. In both versions, you need to add the source's id
and clientSecret
to the method's configuration object.
Replace an existing source with a new source
When customers want to change how they pay for a subscription, you can allow them to supply a new payment method.
How you replace a subscription's current source with a new source depends on whether you're using Drop-in payments or DigitalRiver.js with Elements.
In both cases, first collect and store the customer's billing information.
Build the createDropin()
method's configuration object:
In
options
, set:flow
tomanagePaymentMethods
usage
tosubscription
showTermsOfSaleDisclosure
totrue
showComplianceSection
totrue
Since this is an account management flow, you can't use the checkout's payment session identifier to set
sessionId
. As a result, you must pass the billing information you collect from customers inbillingAddress
.
Pass the configuration object to createDropin()
. If the request is successful, the onReady
event contains the transaction's eligible payment methods:
Each payment method and its disclosures are displayed in the window. If customers click the button without accepting these agreements and terms, Drop-in blocks the transaction from proceeding.
If customers accept the terms, submit their information, and the resulting create source request is successful, the onSuccess
event contains a source that is readyForStorage
and chargeable
.
For more details, refer to the Drop-in payments integration guide and the Drop-in payments builder tool.
Send the source, customer, and subscription identifiers to your backend.
Use a POST /customers/{customerId}/sources/{sourceId}
to attach the source to the customer. This flips the source's reusable
attribute to true
.
To update the subscription, send its identifier as a path parameter in a POST /subscriptions/{subscriptionId}
. In the body of the request, specify the new sourceId
.
If you receive a 200 OK
, notify customers that their subscription's designated payment method has been successfully updated.
Replace an existing source with a saved source
When customers want to change how they pay for a subscription, you can give them the option of selecting one of their saved payment sources.
To access these sources, send the customer's identifier in a GET /customers/{customerId}
request. From the response, you can retrieve any of the sources[]
, since, by default, they're all chargeable
and reusable
.
Use a selection control to display these saved sources to customers. With credit cards, you can retrieve brand
, expirationMonth
, expirationYear
, and lastFourDigits
and display this information to customers so they are able to identify the card. If the customer opts to use a saved source, retrieve its unique identifier.
To update the subscription, send its identifier as a path parameter in a POST/ subscriptions/{subscriptionId}
and, in the request body, specify the selected sourceId
.
If you receive a 200 OK
, notify customers that their subscription's designated payment method has been successfully updated.
Cancelling subscriptions
When you either (1) receive a request from the customer to cancel a subscription, and the request adheres to the terms of the agreement (or you grant the customer a waiver), or (2) you decide to cancel the subscription, send aPOST /subscriptions/{subscriptionId}
with state
set to cancelled
in the request's payload.
No other values can be passed in the body of a cancellation request. If you attempt to do so, the following error is returned:
Only active
, activeFree
, and activePendingInvoice
subscriptions can be cancelled. When you cancel an activePendingInvoice
subscription, the underlying open
invoice is moved into a void
state.
A successful cancellation request returns a 200 OK
, moves the subscription into a cancelled
state and prevents billing from occurring on the nextInvoiceDate
.
On your site's subscription management page, include a cancellation button that, when clicked, sends this cancellation request to Digital River. When you receive a successful response, send the customer a subscription cancellation confirmation email and indicate that no future billing will occur.
Deleting subscriptions
To delete a draft
subscription, retrieve its unique identifier, and pass it as a path parameter in a DELETE /subscriptions/{id}
request.
A successful request results in the creation of an event with a type
of subscription.deleted
.
Only subscriptions whose state
is draft
can be deleted. If you attempt to delete a non-draft
subscription, then the following error is thrown:
If you want to stop recurring payments on an activated subscription, you can either cancel the subscription or deactivate its plan.
Deactivating a plan terminates all subscriptions that belong to that plan.
Updating plans
Updating a plan changes the behavior of all the subscriptions it controls. As a result, we generally recommend only using the POST /plans/{planId}
operation to optimize or phase it out.
For details on how changing a plan's state
affects a subscription, refer to Lifecycle of a plan.
Ending subscription reminders
To stop renewal reminders from getting generated on a subscription, you need to update its plan by assigning a negative integer to reminderOffSetDays
.