How to test stripe charge.failed webhook on a subscription - stripe-payments

I've got a test subscription set up that is active. I'm trying to test what happens when the payment fails. I need to be able to pass some metadata (cognito user ID) to the webhook endpoint, I think I know how to do this but can't work out how to test it.
Using the test webhook doesn't work because it sends a fake charge ID. I've tried using the payment failure card but not having much luck as it doesn't seem to be triggering my endpoint.
Here is what I've been reading already:
https://stripe.com/docs/billing/testing
Stripe charge after subscription, get metadata from subscription
Stripe subscription webhooks missing metadata and client_reference_id
How can I test subscription renewal flows in stripe?

Getting charge.failed event, but struggling to associate this charge to subscription, because the charge has customerId and the customer has a list of subscriptions.
Now I think below code can help
From event can get charge id and then retrieve charge obj with 'expand' property.
params := &stripe.ChargeParams{}
params.AddExpand("customer")
params.AddExpand("invoice.subscription")
ch, err := charge.Get("ch_3K4yJG2eZvKYlo2C14TZsir9", params)

Related

How can I trigger a Stripe webhook event for a specific test customer with the Stripe CLI?

I have installed the Stripe CLI and I'm using it to test some PHP code I've written in the Drupal CMS.
Stripe and Drupal are linked through Stripe's webhooks functionality.
I have a test customer in Stripe with a valid subscription.
Now I want to test the webhook event when the subscription renewal payment fails for this customer.
Based on the Stripe trigger docs, I tried this:
stripe trigger invoice.payment_failed --stripe-account=cus_abcdefg
Where cus_abcdefg is the customer ID shown in the stripe dashboard at
https://dashboard.stripe.com/test/customers/cus_abcdefg
However, this gives the following error:
Running fixture for: customer
Trigger failed: Request failed, status=403, body={
"error": {
"code": "platform_account_required",
"doc_url": "https://stripe.com/docs/error-codes/platform-account-required",
"message": "Only Stripe Connect platforms can work with other accounts. If you specified a client_id parameter, make sure it's correct. If you need to setup a Stripe Connect platform, you can do so at https://dashboard.stripe.com/account/applications/settings.",
"type": "invalid_request_error"
}
}
It seems this error isn't relevant because I am using the official Stripe CLI, not some platform. So I guess I have the ID wrong.
What ID am I supposed to use for --stripe-account?
Actually with Stripe you can create and manage multiple Connected Accounts [1]. In order to do api calls on behalf of these accounts, Stripe provides header authentication [2] feature in order to achieve this.
The Stripe cli –stripe-account [3] flag that you are trying is that header authentication feature.
Thus, you can't use --stripe-account flag to trigger a webhook event for a specific customer.
As an alternative, you can take a look at stripe cli fixtures[4], you can create your own fixture that trigger a Failed payment for a specific customer, or if you just want to test your endpoint regardless of what customer the event[5] is generated for then you can simply resend an existing event using Stripe CLI[6].
[1] https://stripe.com/docs/connect
[2] https://stripe.com/docs/connect/authentication
[3] https://stripe.com/docs/cli/trigger#trigger-stripe_account:~:text=Set%20a%20header%20identifying%20the%20connected%20account.
[4] https://github.com/stripe/stripe-cli/wiki/fixtures-command
[5] https://dashboard.stripe.com/test/events
[6] https://stripe.com/docs/cli/events/resend

Is there a way to avoid creating "status: incomplete" subscriptions during Stripe Checkout?

Background:
When creating subscriptions through the Stripe API, you can use payment_behavior: error_if_incomplete when you want Stripe to return an HTTP 402 status code in case a subscription’s first invoice cannot be paid. In this case Stripe does not create a subscription at all if the payment fails.
Question:
Is there a way to achieve the same behavior when using Stripe Checkout?
My experience is that even if the payment fails, Stripe creates a subscription with status: incomplete which is then expired if no successful payment is made within 23 hours. I've checked the parameters for creating Checkout Sessions but found no option to set payment_behavior there.
Sources:
https://stripe.com/docs/api/subscriptions/create#create_subscription-payment_behavior
https://stripe.com/docs/api/checkout/sessions/create
Bad News
Unfortunately this is not something that can be configured presently. When Checkout creates a subscription, all the parameters not provided directly are set to the Subscription default. The default payment_behavior for a Subscription is default_incomplete.
Good News
You can achieve this behavior using Webhooks. You would listen for the invoice.payment_failed event, check the billing_reason property of the invoice is subscription_create (identifies the first invoice of a new subscription), and then cancel the related subscription.
If you are using Subscriptions and Invoices, it is recommended you use webhooks anyway to keep track of changes in status.

Stripe Elements update subscriber payment method

How to enable users to update their subscription's payment method using Stripe Elements?
I couldn't find any reference to this neither in the docs nor on Stackoverflow.
This is how I'm currently setting the default payment method when the user first subscribes to our service.
Create a Stripe subscription object
Render the React CardElement component.
On submit, I call the browser's side Stripe library with stripe.confirmCardPayment(cardElement)
This then triggers a invoice.payment_succeeded webhook event.
In the webhook event, I get the payment intent ID which I use to retrieve the payment intent object which has the ID of the payment_method attached to it.
I then update Stripe's subscription object to use the successful payment_method's ID as the default payment method.
Is there a way to update the subscription's payment method without making a payment_intent first? Link to docs would be appreciated.
Thank you
You can use SetupIntents to save a customer’s card without an initial payment : https://stripe.com/docs/payments/save-and-reuse-cards-only [until step 4]
Listen for the setup_intent.succeeded webhook event to know when the SetupIntent is successful since the customer could close the browser window or quit the app before the stripe.confirmPayment callback executes.
Update the Subscription to use the resulting PaymentMethod ID as the default payment method.
Alternatively, you could also make use of the Customer Portal to allow customers to update their payment method for a subscription : https://stripe.com/docs/billing/subscriptions/customer-portal

How to get the charge Id after subscribing a customer to a plan with recurring payment?

I have successfully created a customer in stripe with a subscription of plan .After successful payment I am not able to get the charge Id because after subscribing a customer to a plan.It automatically generates an invoice.So what is the way that I can get that particular charge stripe Id from stripe and store it in my system database.
Getting the charge ID for a subscription (or an invoice) can be done via their webhooks integration. You need to expose an API in your app where Stripe can fire these requests. You can subscribe to various events there, but in your case you'd need to do so on charge.succeeded. The charge ID will be in the data structure of the event object.
Take a look at the various other lifecycle events you can use with webhooks.

Stripe API - provide the reason for subscription cancellation

In Stripe's UI there's the REASON column:
As per Stripe's docs, it's possible to cancel a subscription via API:
var stripe = require("stripe")("sk_test_J7rbZuZ0bLvmPVnuEKPFnIEC");
stripe.subscriptions.del('sub_49ty4767H20z6a');
Now, how can I pass the cancellation reason (provided by a user) to Stripe's API?
While it is possible to cancel subscriptions you cannot currently set a reason.
The reason displayed in the Stripe Dashboard is a (currently) internal-only cancelation code of either "Unpaid" or "Canceled".
"Unpaid" when the subscription has been canceled due to failure to collect payment by Stripe Billing's engine, or "Canceled" when you, the admin user, has manually marked the subscription as canceled.
FWIW, you could add this as metadata against the subscription object. Metadata is available on most objects in Stripe with key/value pairs: https://stripe.com/docs/api/subscriptions/object#subscription_object-metadata

Resources