Auto renew subscriptions
Auto-renewing subscriptions are a crucial feature in many subscription-based services that aim to provide a seamless and uninterrupted experience for users. This guide focuses on the VIA Monetise Auto Renew Subscriptions feature, which is responsible for handling the auto-renewal process for subscriptions within your application. By understanding the functionalities and strategies involved in auto-renewing subscriptions with VIA Monetise, developers can ensure that users’ access remains uninterrupted and efficiently handle potential payment failures.
The subscription updater job extends only those subscriptions, which has a product provider, which fits the following requirements
- product type is SUBSCRIPTION (product_provider.product_id->product.product_period_id->product_period.payment_type=1).
- payment provider has auto renewal method AUTORENEW_METHOD_CHECK or AUTORENEW_METHOD_NOTIFY (product_provider.provider_id->payment_provider.autorenew_method=1 or 2).
📘 This documentation will use ‘subscription’ for such member accesses
VIA Monetise Subscription Updater
Section titled “VIA Monetise Subscription Updater”Currently, this job is used for the auto-renewal of the subscriptions.
First, it looks for the subscriptions, which is expired and due to auto-renewal:
- the earliest end date has not been reached or auto-renewal status is ACTIVE or not defined (autorenew_status=0 or autorenew_status is null or earliest_enddate>now)
- status is ACTIVE (status_id=0)
- expired (enddate < now)
- due to the next try of auto-renew, meaning this auto-renew is the first try or the last attempt of auto-renewal has failed, and since that 3 hours have passed
Before the job tries to extend the subscription, it runs a sanity check, which fetches the same subscription from the database again, and compares the end date to the calculated end date (member_access.enddate.toMilliseconds + member_access.period*1000), so that it is sure there is no concurrent extending of this subscription going on.
First, the actual payment transaction is handled by the payment provider. The amount charged is the price of the subscription.
If the payment was successful
Section titled “If the payment was successful”The subscription gets a new end date, which is calculated by the following formula: member_access.enddate.toMilliseconds + member_access.period*1000.
The access end date is set to 5 hours + new end date.
The status text is changed to “Autorenew successful (yyyy-MM-dd HH:mm:ss)”
The auto-renew error number is set to 0, and the number of active periods is increased by one.
The last activity date is set to the current date.
ExtendedTime is set to null.
A new payment transaction object is created with the information from captureVO, which was returned from the payment provider, and firedRules, which is the rule used for calculating the price.
And this payment transaction’s id is set to the subscription’s last payment transaction id.
A new payment status log is created with the member id, member access id, orderRef, log status USER_SUBSCRIPTION_EXTENDED (value 7), and a message “Captured - Autorenew @ host name”
Also, a transaction log is created with the member access id, log status USER_SUBSCRIPTION_EXTENDED (value 7), the message “Captured - Autorenew”, and a success flag true.
If the payment was not successful*
Section titled “If the payment was not successful*”A payment status log is created with the member id, member access id, orderRef, log status CAPTURE_FAILED_AUTORENEW (value 203), and a message is the exception message.
For locking subscriptions (earliest_enddate>enddate)
- if the auto-renewal has failed 5 or more times, it sets the earliest_enddate to enddate’s value and stops the subscription. No mail is sent out in this case.
- if it failed 4 times, then it applies the renew failure strategy and sends an email about it.
- in other cases, it handles it the same way as the non-locking subscriptions.
For non-locking subscriptions (earliest_enddate is null or earliest_enddate<=enddate)
- if it failed 5 times, then it stops the subscription and sends an email about it
- if it failed 4 times, then it applies the renew failure strategy and sends an email about it
- otherwise, the access end date gets extended 3 hours, and the following changes are made to log the failure, by doing the following: member access status is set to ACTIVE (status_id=0), then status text saying “Autorenew failed, try n (yyyy-MM-dd HH:mm:ss)”, “try 0” meaning the first attempt of auto-renewal. Then we increase the auto-renew error number on the subscription by one and set the last activity date to the current date. The auto-renew error number will not increase to more than 4 for non-locking subscriptions.
📘 The default strategy is to extend by one week. This means, that if the payment provider doesn’t have renewal failure strategy defined (payment_provider.renewal_failure_strategy), then extend by one week will be used.
Renewal failure strategy options
Section titled “Renewal failure strategy options”- EXTEND_ONE_WEEK: Extend by one week: adds one week to both the end date and access end date.
- EXTEND_TO_27TH: Extend to 27th of the month: sets the end date and the access end date to the following 27th of the month. ExtendedTime is updated and extendePrice is used when attempting renewal again.
- EXTEND_TO_FIRST_DAY_OF_NEXT_MONTH: Extend to first day of next month: sets the end date and the access end date to the first day of the following month. ExtendedTime is updated and extendePrice is used when attempting renewal again.
- EXTEND_31_DAYS: Extend by 31 days: adds 31 days to both end date and access end date.
- EXTEND_BY_PERIOD_X_TIMES: Extend by a configurable period of time, a configurable number of times. ExtendedTime is updated and extendedPrice is used when attempting renewal again. This renewal failure strategy supports handling more than the default maximum number of renewal error and uses the following configurations (defined in PaymentProviderConfig table)
- renew.failstrategy.extendbyperiodxtimes.maxattempts: The number of times the renewal failure strategy is to be used (and the number of times the subscripton will be extended) after 3 autoRenewErrors. Minimum value is 1, and default value is 1 (if wrongfully configured)
- renew.failstrategy.extendbyperiodxtimes.periodiso: The amount of time the subscription should be extended when renewal fails (after 3 renewErrors). Supported formats are seconds (example: 86400) and ISO 8601 (example: P2D). The minimum value is 86400 or P1D (which equals to one day), and the default value is 86400 if wrongfully configured.
Afterward, the failure is logged on the subscription.
📘 ExtendedPrice is not stored on the Member_Access, Instead it is calculated based on the extendedTime on renewal. If renewal succeeds, the transaction is logged with price equal to the actual amount on money withdrawn (extendedPrice)
Renewal Failure Strategy EXTEND_BY_PERIOD_X_TIMES
Section titled “Renewal Failure Strategy EXTEND_BY_PERIOD_X_TIMES”Introduction
Strategy EXTEND_BY_PERIOD_X_TIMES extends orders that have failed 3 times on renewal. Both the extend period and the number of times it should be extended (the number of times it should try again after first period extension) is configurable in PaymentProviderConfig table in the Oracle DB.
Logic
After 3 failed renewal attempts, the renewal strategy will kick in, and the following configurations will be fetched from PaymentProviderConfig:
- renew.failstrategy.extendbyperiodxtimes.maxattempts
- renew.failstrategy.extendbyperiodxtimes.periodiso
The strategy will then make the following changes to the order:
- Enddate = Enddate + Value of config renew.failstrategy.extendbyperiodxtimes.periodiso in seconds/ISO 8601
- AccessEnddate = AccessEnddate + Value of config renew.failstrategy.extendbyperiodxtimes.periodiso in seconds/ISO 8601
- ExtendedTime = ExtendedTime + Value of config renew.failstrategy.extendbyperiodxtimes.periodiso in seconds/ISO 8601
After the order has been extended, the number of renewal errors will be incremented. The strategy will then keep track of how many times the order has been extended using the following formula:
📘 NumberOfAttempts = AutoRenewErrors - 3
For each renewal attempt, the strategy will extend the order according to the configured extend period until the following expression returns true:
📘 (AutoRenewErrors-3) >=
For each renewal, the price that will be used is based the regular price and amount of “free access” the user has been given due to renewal errors.
Example
- renew.failstrategy.extendbyperiodxtimes.maxattempts = 3
- renew.failstrategy.extendbyperiodxtimes.periodiso = P1D
- Order period = 1 day
- Order price = 1 USD
- Initial enddate = 2017-01-01 12:00
| Renewal attempt | Renewal price | AutoRenewErrors | Number of extensions after 3 autoRenewErrors/ Number of times Renewal Failure Strategy triggered | Action triggered | Enddate |
|---|---|---|---|---|---|
| 1 | 1 USD | Goes from 0 to 1 | 0 | Order access extended 3 hours | 2017-01-01 12:00 |
| 2 | 1 USD | Goes from 1 to 2 | 0 | Order access extended 3 hours | 2017-01-01 12:00 |
| 3 | 1 USD | Goes from 2 to 3 | 0 | Order access extended 3 hours | 2017-01-01 12:00 |
| 4 | 1 USD | Goes from 3 to 4 | Goes from 0 to 1 | Order extended | Goes from 2017-01-01 12:00 - 2017-01-02 12:00 |
| 5 | 2 USD | Goes from 4 to 5 | Goes from 1 to 2 | Order extended | Goes from 2017-01-02 12:00 - 2017-01-03 12:00 |
| 6 | 3 USD | Goes from 5 to 6 | Goes from 2 to 3 | Order extended | Goes from 2017-01-03 12:00 - 2017-01-04 12:00 |
| 7 | 4 USD | Goes from 6 to 7 | 3 | Order stopped | 2017-01-04 12:00 |
Configuration
The strategy is applied to a given paymentProvider through the CoreAdmin GUI: Database → Provider → Edit → renewalFailureStrategy → EXTEND_BY_PERIOD_X_TIMES. The configurations which determine the extend period and number of attempts are fetched from PaymentProviderConfig table in the Oracle DB. The configuration keys and values are:
[block:parameters] { “data”: { “h-0”: “Oracle DB table”, “h-1”: “Key”, “h-2”: “Value format”, “h-3”: “Minimum value”, “h-4”: “Default value (if wrongfully configured)”, “h-5”: “Example value”, “0-0”: “PaymentProviderConfig”, “0-1”: “renew.failstrategy.extendbyperiodxtimes.maxattempts”, “0-2”: “Integer”, “0-3”: “1”, “0-4”: “1”, “0-5”: “3”, “1-0”: “PaymentProviderConfig”, “1-1”: “renew.failstrategy.extendbyperiodxtimes.periodiso”, “1-2”: “Integer (number of seconds) \n \nISO 8601”, “1-3”: “86400 \n \nP1D”, “1-4”: “86400 \n \nP1D”, “1-5”: “259200 \n \nP3D” }, “cols”: 6, “rows”: 2, “align”: [ “left”, “left”, “left”, “left”, “left”, “left” ] } [/block]
Renewal Failure Strategy DO_NOT_EXTEND
Section titled “Renewal Failure Strategy DO_NOT_EXTEND”Introduction
Strategy DO_NOT_EXTEND does not extend orders that have failed 3 times on renewal. The order is stopped by setting the AutorenewStatus of the order to STOPPED.
Logic
After 3 failed renewal attempts, the renewal strategy will kick in, and setting the AutorenewStatus of the order to STOPPED. The user will have access until the AccessEndDate of the order is reached.
Configuration
The strategy is applied to a given paymentProvider through the CoreAdmin GUI: Database → Provider → Edit → renewalFailureStrategy → DO_NOT_EXTEND.
Email about auto-renewal failure
Email is sent if the followings are true:
- auto stop notification enabled global value is set to true. This value is set through the message resource “sumo.core.property.email.autostop.inuse”. The value should be true and the locale is global.
- payment provider has enabled the error notification (payment_provider.error_notification_enabled=1)
- if the subscription is stopped or extended by one week, or extended till 27th and the actual date is not 27th (if the subscription is extended till 27th but the date is 27th, auto-renewal will be attempted again later on)
The email template key is /email/plain/subscription/autostop/all_all.vm
To test the auto-renew job you can use this action: /admin/user/autorenew.do?action=memberTest&memberId=&providerId=
📘 Note
The providerId is the product provider id.