I have a custom code to execute for subscriptions and another one for one-time payments.
I have already written both codes and they are working fine. Now I would like to move each code to the right section where it must be executed. So I would like to ask you
if the payment_intent.succeeded only fires when we have a one time payment and the invoice.payment_succeeded event only fires when we have a subscription ? If that's the case I will be able to place my codes when I capture those 2 events.
Related
I'm subscribed to stripe webhook charge.refund.updated event. On that event, I need to attach specific metadata to stripe refund entity (accounting needs this data in stripe exports so I need it there), but this causes same charge.refund.updated event being called again, which causes circular requests.
Only solution I'm thinking of right now is to add some kind of additional ignore field to metadata and then just ignore webhook if that value is true, but I don't really like that solution because it would persist on the refund entity, and if something actually did change on refund, my handler would ignore it.
I guess the best option would be something like stripe.refunds.update(..., { ignoreWebhook: true }), but that's not an option because API doesn't support anything like that (as far as I've investigated).
It’s recommended that you need to design your webhook endpoint to treat duplicates events. Because regardless of your circular call on Charge updates, Stripe occasionally sends the same event more than once [1]. One of the solutions: is to log the event you’ve processed and then not process already-logged events.
In your case, you can add a metadata that contains a version number of the charge. Something like this:
1 - Received an event charge.refund.updated
2- Add your logic along with another version of metadata.
3- You log the charge id, version any other field you are basing your logic while adding metadata (example: status)
4- You’ll receive another event charge.refund.updated, you check if you have already treated that charge based on what you logged already (id, version, status…)
Meanwhile, if you hit the same update charge request API [3] multiple times, only one webhook event is triggered you can test it on your own.
[1] https://stripe.com/docs/webhooks/best-practices#duplicate-events
[2] https://stripe.com/docs/webhooks/best-practices#duplicate-events:~:text=One%20way%20of%20doing%20this%20is%20logging%20the%20events%20you%E2%80%99ve%20processed%2C%20and%20then%20not%20processing%20already%2Dlogged%20events.
[3] https://stripe.com/docs/api/refunds/update
I'm using stripe for subscription. Where i need to fire an event after 3 successfully charges.
For this i am using invoice.payment_succeeded webhook.
But there is no key which specify the number of this recurring payment means whether it is first or second or nth charge. So how could i get the number of successfully payment made on a subscription.
You can call the https://api.stripe.com/v1/invoices API endpoint with the customer's ID, the status parameter set to paid and optionally, the subscription parameter and then count how many invoices were returned.
There are some other parameters, like limit, starting_after, etc. that you can send it too.
The invoice.payment_succeeded webhook sends the invoice object in the data.object field so you should be able to get the customer and subscription values from it.
I'd recommend doing the invoices call asynchronously to ensure that the webhook call doesn't time out.
FYI there is an expand to it, like with the current node api;
const ret = await stripe.invoices.list(
{
expand: ["total_count"],
limit: 0,
});
console.log(ret.total_count)
It can be called with ${url}?expand[]=total_count&limit=0 too, if you need to write it by hand.
I did not found this in the documentation, but some libs using it, and it is indeed works. (But be careful, if it is not documented it could stop working too.)
Here is the docs; https://stripe.com/docs/api/pagination/search#search_pagination-total_count
Yes, as it is stated in the answer by D Malan, you can use the https://api.stripe.com/v1/invoices endpoint.
Though there is one thing to keep in mind when retrieving data from Stripe.
You can only get 100 items per call. Therefore, if you had recurring payment that generates more than 100 invoices after some time, you wouldn't be able to get the total count in one call. I suggest storing invoices/payment intents to your database and then using your DB engine to count the results.
Keep in mind that you should listen to invoice.payment_succeeded event in order to keep your database in sync, if you store the invoice or payment intent beforehand, while its status is not paid or succeeded, respectively.
Context: There is a Stripe plan "Starter". The customer subscribes to the "Starter" plan. Within a subscription period the user wants to up- or downgrade the subscription (in my case: the quantity will be increased or decreased). Programmatically I want to achieve this with a subscription update.
Problem: Stripe wants to make the update immediately. But I want to have it changed at the end of the period.
Alternatives:
I saw this Stackoverflow asking exact the same question, but is six years ago -> Stripe: downgrade a user at "period end". The proposed solutions are not really reflecting the desired solution and also do not work for me.
I saw that Stripe has a subscription schedule API. Is this probably related to the problem solution?
I'm relly looking forward for (high-level) solutions to solve this problem. Thank you in advance.
So you want to update the subscription details at the end of the current period. In that case, you may want to use the subscription webhook events mentioned here
"When the subscription period elapses, invoice.created event is sent, indicating the creation of a draft invoice."
"About an hour after the invoice is created, it is finalized (changes are no longer permitted), and an invoice.finalized event is sent."
So you can listen to that invoice.created event and then update the subscription.
This is what I discussed with the Stripe support channel:
I understand that scheduling is not the best fit for you, as you'd
have to release the schedule once the update is made so the new
subscription rolls over, and this doesn't cancel the subscription, but
start a new one.
What you could do, is to cancel the first subscription at_period_end,
and then start the next one when the event
customer.subscription.deleted comes through:
https://stripe.com/docs/api/events/types#event_types-customer.subscription.deleted
If you don't want to use Webhooks, you can also cancel at period end
and then generate the new subscription at the same time using the
billing cycle anchor
https://stripe.com/docs/api/subscriptions/create#create_subscription-billing_cycle_anchor.
This will only work though for subscriptions with the same interval,
or if the second subscription interval is shorter than the first.
I implemented the webhook solution. It works perfectly for me.
I'm updating a webapp to Stripes SCA ready flow with PaymentIntent.
So far I have working (on my local test server):
Generate Intent on frontend and pass secret to form
Use Elements to collect card into
Use handleCardPayment to create the charge
Now here's the part where I am unsure. The handleCardPayment responses all seem to indicate a succeeded event, but the documentation warns to not use this repsonse, but instead wait for the Webhook response and only then fulfill customer orders.
Step 5: Asynchronously fulfill the customer’s order
You can use the PaymentIntent returned by Stripe.js to provide
immediate feedback to your customers when the payment completes on the
client. However, your integration should not attempt to handle order
fulfillment on the client side because it is possible for customers to
leave the page after payment is complete but before the fulfillment
process initiates. Instead, you will need to handle asynchronous
events in order to be notified and drive fulfillment when the payment
succeeds. Documentation
So far so good, I've set up test webhooks and tunneling through ngrok I can actually receive the paymentIntent from the Stripe webhook.
Now, my question comes at this point, where the Stripe documentation ends. How should I deal with the UI from the point of the "Pay" button being pressed, and how do I in the frontend detect that the webhook has been triggered?
I am wondering if I should poll my own server, which in turn retrieves a database result that indicated if the webhook for this order has been received? Or what is a reasonable way to deal with this, technically and from an UX perspective?
Any pointers?
I just implemented this, and I decided to poll my own server for the update and ask the user to wait. The webhook marks our internal representation as "paid", so we don't need to poll Stripe. If the webhook doesn't come within 30 seconds, we tell the user that it's ok to leave the page, and we'll email them the result.
Technically, these webhooks can take up to 7 days to come in, so that's why Stripe doesn't want you to have the user wait. In reality, it almost always comes in within 5 seconds, and I would rather just have the user wait and see a final confirmation in the same session.
I'm building an event signup system and integrating it with Ubercart. Each event is a product and has a price and a start time.
I wish to be able to trigger an action one week before the event starts. The action is supposed to send an email to the users that bought the event and perform a capture on the registrant's credit card. But where do I define the action and how do I trigger it one week before event start?
I assume you're talking about Drupal 6, since you're mentioning ubercart. Does the action to send the email you're takling about already exist?
If it does, you can assign it under Site Building | Triggers | Cron. If it doesn't show up in the list of actions, you might need the Triggerunlock module.
If the action doesn't exist, you're going to have to write the PHP code to send the emails and do the calculations. You will need to create your own module and either use hook_cron, or create a custom action.