Trying to work with Paypal subscriptions using Smart Subscription buttons and webhooks. I'm basing my business logic on the webhook event PAYMENT.SALE.COMPLETED, as per previous advice I've been given. I'm hoping I've captured all likely scenarios but one scenario still seems a bit flaky where a user wants to renew a subscription after they cancelled.
Expected behaviour:
- Monthly subscription billing
- Ability to cancel subscription but keep access till the end of the current billing term
- Ability to renew a cancelled subscription before the term ends. (Is this strictly necessary from a usability POV? How would other websites handle this scenario?)
Local Database structure:
- subscriptionEnds: Date (similar to next_billing_time in subscription event?)
- status: String (Subbed/Grace/Unsubbed)
- subscriptionId: String (subscription Id from Paypal)
Webhook events
When the webhook event PAYMENT.SALE.COMPLETED is received, set subscriptionEnds to 1 month from date of transaction, set status to "Subbed", subscriptionId set to the event's billing_agreement_id.
Each renewal (webhook triggers PAYMENT.SALE.COMPLETED again) will then update the user's subscriptionEnds date to be 1 month from new transaction date.
If a user initiates an unsubscribe (through an unsubscribe button on the website or from their Paypal dashboard?) then the PAYMENT.SUBSCRIPTION.CANCELLED webhook event will fire, in my webhook receiver I set the status to "Grace."
Scheduled tasks to handle expiring accounts:
A daily task will check for any accounts where the subcriptionEnds date is at least X days old, set the status to "Unsubbed" and clear the subscriptionId and subscriptionEnd date. X would probably need to be similar in length to Paypal's retry period?
UI behaviour
For Unsubbed accounts, show the subscribe button (with custom_id set to a user identifier)
For Subbed accounts, the UI will show the next billing date (subscriptionEnds in db), and an unsubscribe button.
If the status is "Grace", then the UI will show "Subcription ends" date (subscriptionEnds in db) and a Paypal subscribe button, with a custom_id for the user, and start_time will be set to the subscriptionEnds value in the database, allowing a new subscription to be created as the current term ends.
Expected logic issue:
If they renew their sub, the PAYMENT.SALE.COMPLETED event won't fire until the new Paypal subscription starts? If the user returns to the website before this new start date, it will continue to show a "Grace" state which may confuse them into attempting to re-sub again. I could update their status back to "Subbed", but I don't think there's a web hook for this - unless there is a BILLING.SUBSCRIPTION.* event I can use, in which I then check the state of my local db record and update the status to Subbed?
Other thoughts
I know there is also the ability to pause a subscription and other possible events which might be relevant, but I'm not sure I need to consider them, the above scenarios and logic should cover everything?
- BILLING.SUBSCRIPTION.ACTIVATED
- BILLING.SUBSCRIPTION.UPDATED
- BILLING.SUBSCRIPTION.EXPIRED
- BILLING.SUBSCRIPTION.CANCELLED
- BILLING.SUBSCRIPTION.SUSPENDED
- BILLING.SUBSCRIPTION.PAYMENT.FAILED