no refs
The data structure for subscriptions object on member has changed in 4.x from` stripe.subscriptions` to direct `subscriptions`, the change here updates parsing of subscriptions data
refs https://github.com/TryGhost/Team/issues/479
* Fixed updating payment method for canceled subscriptions
Stripe considers canceled subscriptions as non-existent, so any attempts
to update them will fail with a 404 not found. Prior to this change we
were attempting to update *all* subscriptions for a customer, including
those which were canceled. This would cause an error and the loop to
break.
* 🐛 Fixed errors for members with multiple active customers
Members with multiple active customers would have their first active
customer found updated with the new payment method. We would then
iterate through *all* active subscription, and attempt to update their
payment method. If a subscription was not owned by the customer that was
just updated, it would error and cause the loop to break out.
* Added ability to update a specific subscription's payment method
In order to remove ambiguity we add the ability to update the payment
method for a specific subscription. This will remove room for errors as
we will not have to worry about if a subscription belong to the customer
or not.
refs https://github.com/TryGhost/Team/issues/475
The subscription object here is a database model rather than an
ISubscription from the stripe library, and we need to 1) use the `get`
method to read attributes and 2) read the `subscription_id` attribute,
as the `id` is our internal one.
no-issue
Fetching relations via the model returns a promise, and this was missing
the `await` keyword. We also need to `get` the subscription_id attribute
as we're working with models rather than subscription objects.
no-issue
If we receive webhooks out of order, e.g. a
`customer.subscription.updated` with a status of 'active', followed by a
`customer.subscription.created` with a status of 'incomplete'. We would
overwrite the correct value with data from the "older" webhook. This
ensures that we always fetch the latest data from the Stripe API before
storing in the database.
no-issue
related to ef9cb0862c
In the last patch which fixes the bug for not passing custom redirect urls when a checkout session is created, we missed updating the case where a logged in member tries to update the subscription.
no issue
The logic to fetch member for a checkout session was incorrectly creating a new customer instead of finding an existing one, so the member's billing details was not getting updated.
no-issue
This refactors the members-api module so that it is easier to test going forward,
as well as easier to understand & navigate. The Stripe API no longer contains
storage code, this is all handled via the member repository. And we have dedicated
services for webhooks, and stripe plans initialisation.
no-issue
- Was not used by the importer and removed for simplicity.
- Updates the header mapping to happen in place, rather than in a loop
- Updates the parsing of values to give correct types
no issue
- In case of a member updating their email, the `updateEmail` type was overridden with `signup` or `signin` without the force option. The fix forces the correct email type for when member requests to update their email.
refs https://github.com/TryGhost/Ghost/issues/12253
Allows reading `requestSrc` from Stripe checkout flow metadata to send signup emails with customized action param when requesting from Portal
no issue
`getSigninUrl` takes an optional param `requestSrc` to allow customizing signin url based on source like Portal. Fixes tests and adds default value in case no `requestSrc` is present.
no issue
refs https://github.com/TryGhost/Ghost/issues/12253
Currently, Ghost uses standard query params like action, success and stripe for all actions and redirects to a site for member events. This needed to be extended to allow for portal specific query params so it doesn't overlap with specific theme handling or custom notifications.
The change here adds an extra option - `requestSrc` - which can be passed when using magic link API to send a link which is passed down to `getSigninURL`, and allows the `action` param to configured to `portal-action` when magic links are sent from Portal
no issue
Previously, we were sending a magic link email to signup in case a logged-in member upgrades to a paid account, as we didn't check for logged in status while sending the magic link and always sent one on finishing checkout. Since Portal allows members to upgrade their account from free, it doesn't make sense to send another email to signup after completing checkout.
The fix here adds a metadata `checkoutType` to checkout session creation which can be passed in with `upgrade` value to denote an existing member is upgrading and doesn't need an email.
refs https://github.com/TryGhost/Ghost/issues/12256 , https://github.com/TryGhost/Ghost/issues/12255
Currently when listing subscriptions for Members, we were only showing the subscriptions which have a status of trialing or active.
Based on discussion, the `unpaid` and `past_due` states on Stripe also represent owner's intention of considering a subscription as active instead of `cancelled`, so we allow any subscriptions under these 2 states to be also listed for a member and consider them as `paid`.
- Subscriptions will go into a past_due state if the payment is missed, this should be considered a grace period where the member still has access.
- After this the subscriptions will either go to the unpaid or the cancelled state - this can be configured on an account by account basis in the Stripe dashboard. `unpaid` is considered as an intention to keep the subscription to allow for re-activation later.
refs https://github.com/TryGhost/Ghost/issues/12270
Previously we would create the member, and then update their name from
stripe data, this mean that webhooks would be sent _without_ a name,
despite us possibly having the information to provide one.
Here we've updated the creation of members to include the name attached
to the default billing method, this will ensure that webhooks are sent
with all availiable information.
no-issue
Subscription created events are required for migrating Stripe subscriptions from
alternative platforms, which involves creating a new subscription for a customer
(outside of Ghost) before cancelling the original subscription.
no issue
- Email update magic link was not sent out for sites which did not allow self signup as it didn't find the member on new email, which is expected.
- Updates sending magic link check in case an old email is found to correctly trigger update email
no-issue
We were passing a string rather than an object to find the member to set
the geolocation on, this was causing us to always find the same member
each time, and so newer members would never have their geolocation set.
no-issue
This paves the way for Ghost to be able to pass in a custom token
provider which will handle the shortening of tokens and making them
single use.
no-issue
This adds a layer of abstraction between the magic-link module and the
token generation, allowing us to switch out the token generation in the
future, when implementing single use tokens stored in a database
no-issue
This removes the concept of `subject` & `payload` from the function
signatures, making the implementation a little more generic, and less
JWT centric.
We also replace getUserFromToken and getPayloadFromToken with a single
method getDataFromToken, which will contain all the necessary data.
* Updated members-api to use new magic-link module
This updates the usage of magic-link to work with the new interface
* Fixed labels not saving for new members
Due to how bookshelf-relations works, we must fetch the labels before
saving a member, otherwise the labels are all deleted.
* Used a proper class rather than constructor function
This just moves the code to a more modern standard
* Updated methods to be async
This prepares us for a future where token generation and validation may
require access to storage and thus be an asyncronous operation