Log PayPal and Stripe subscription renewals - #15663
Conversation
73e933c to
615bf18
Compare
4bebde2 to
bdb6364
Compare
SabreCat
left a comment
There was a problem hiding this comment.
A unit test is failing, unable to find this.constants when looking up PAYMENT_METHOD. The refactoring must have changed the this context.
67d5063 to
9db9adc
Compare
There was a problem hiding this comment.
Pull request overview
This PR extends Habitica’s server-side payment/analytics pipeline to record subscription renewal events for Stripe and PayPal, and enriches subscription analytics with a “group vs. individual” flag.
Changes:
- Adds a new analytics event type (
renewed) and records renewal events from Stripe webhooks and PayPal IPN. - Extends subscription analytics payload/storage with
isGroupSubscription. - Switches the
in-app-purchasedependency to a GitHub-sourced package.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| website/server/models/analytics/subscriptionEvent.js | Adds renewed event type and stores isGroupSubscription in the analytics schema. |
| website/server/libs/payments/subscriptions.js | Tracks isGroupSubscription on subscribe/cancel and introduces handleSubscriptionRenewal. |
| website/server/libs/payments/stripe/webhooks.js | Hooks renewal tracking into Stripe invoice.payment_succeeded events. |
| website/server/libs/payments/paypal.js | Adds PayPal IPN renewal handling, refactors cancellation helper, and adds optional IPN verification bypass. |
| website/server/libs/localAnalytics.js | Persists isGroupSubscription when saving subscription analytics events. |
| package.json | Switches in-app-purchase to a GitHub dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "heapdump": "^0.3.15", | ||
| "helmet": "^4.6.0", | ||
| "in-app-purchase": "^1.11.3", | ||
| "in-app-purchase": "github:HabitRPG/in-app-purchase", |
| if (plan) { | ||
| await trackSubscriptionEvent({ | ||
| eventType: 'renewed', | ||
| user: ownerId, |
| const { txn_type, recurring_payment_id } = options; | ||
|
|
||
| if (repayTypes.indexOf(txn_type) !== -1) { | ||
| payments.handleSubscriptionRenewal(recurring_payment_id); |
| if (!PAYPAL_DISABLE_IPN_VERIFICATION) { | ||
| await this.ipnVerifyAsync(options, { | ||
| allow_sandbox: PAYPAL_MODE === 'sandbox', | ||
| }); | ||
| } |
SabreCat
left a comment
There was a problem hiding this comment.
I did some debugging to get the events to file without errors, but some data still isn't coming through. Give it a look?
{
_id: 'e3f874ed-6c8b-436f-a049-e03e7da0c129',
userId: '90931b7b-14f0-49ca-a8ef-503e3f533d94',
eventType: 'renewed',
paymentMethod: null,
customerId: null,
planId: null,
isGroupSubscription: false,
createdAt: ISODate('2026-07-30T14:28:40.374Z'),
updatedAt: ISODate('2026-07-30T14:28:40.374Z'),
__v: 0
}
No description provided.