With the new Stripe SCA implementation (which makes use of webhooks) there is a limit to the number of possible stores due to the webhook limit in Stripe.
We have one site that has over 16 stores (small front-end branded stores) but Stripe has a limit of 16 webhooks per live instance. As such it is not possible to hook every store up and hence the payment provider won't work past 16 stores.
Is there any way around this with the current setup?
It feels inefficient to have multiple webhooks for one instance of Umbraco (which may contain multiple stores) but I note the webhooks contain the store ID and possibly some other ID?
Failing that the alternative would be to write a custom webhook which then dispatches the relevant TC hooks or calls into the library directly.
Once you have a means of retrieving the Store ID, what I'd be tempted to do is write a custom controller to act as your webhook entry point, then lookup the Store ID and then redirect to the built in webhook URL (the format being /base/TC/PaymentCommunicationWithoutOrderId/[storeId]/Stripe%20-%20inline/[paymentMethodId]) for TC to do what it needs to do.
This should get your setup working.
Another option would be to run on a completely custom Stripe provider build that uses a synchronous approach to handling payment intents (ie, something that doesn't need webhooks at all). This would need to be custom written though. We went the webhooks route as a) it's the Stripe recommended approach and b) it meant logic could be shared between the standard Stripe provider and the Stripe Subscription provider, which can ONLY work via webhooks.
In terms of what could be done to our Stripe payment provider / Tea Commerce itself to allow the sharing of a webhook URL, I'd need to have a think about this. It would be a pretty big change to how things currently work (payment method configs being independent of each other).
Incase you want to go the later approach of a synchronous Stripe flow, you can read more on how this would be implemented here https://stripe.com/docs/payments/payment-intents/migration If you do go that approach, you should at least be able to use the existing provider as a starting point.
So, I had a little think about this yesterday, and I think I've come up with a longer term solution, however this will be a future update as it will require quite a few changes.
Ultimately, I think I'm going to take a look at separating out "Account Settings" on payment providers, such that these can be shared across multiple providers, so things like API keys + secrets etc. On a payment provider config then, you'd either be able to reuse an existing "account" or setup another one. This way it allows stores to share credentials if they can, but can still be per store if needs be.
Once these are broken out, I think it should then be possible to have a webhook endpoint per provider + account combination (rather than per provider + payment method combo we currently have), and have these webhook endpoints be able to work out the store + order + payment method instances the request is associated with. This ultimately means then that only 1 webhook per account is needed, resolving the issue presented here.
As I say though, this is going to have to be a long term fix so is unlikely to resolve your issue right now. For that, I think you'll need to go with one of the solutions highlighted above.
On a side note, I'd really love to know more about your project as we don't get to hear from a lot of customers, and this project sounds kind of interesting. Would love to know more so we can make these types of projects simpler in the future.
What you are suggesting makes sense and would help out in this scenario (and make it simpler for multi-store solutions in general with shared payment provider).
We appear to have had an issue yesterday after deploying this where an incorrect order has been finalised and marked as captured following a webhook call (i.e. a webhook call for one store has incorrectly finalised an order in another store - most likely because we have multiple webhooks being fired at once but I'm surprised it finalised a totally invalid order). I need to look into this a bit more this morning but I would assume the webhook would be validating the order ID at the very least when fetching the order for a webhook request?
I'll let you know once I've found out more and if we put a workaround in place for the time being for the multiple webooks.
More than happy to share more on the project setup. I should imagine it's not a common scenario for sure. Are you going to Umbraco UK Festival this year?
I have seen that issue before and it usually comes about because stores share the same cart / order prefixes. The problem is, all orders are issued a cart number, but those cart numbers are sequential per store. The problem is, that when a webhook is hit, it fetches the cart number stored in the stripe order then looks it up. If you have a cart with that same number in the store, then it thinks it needs to finalize it. So really, you need to give each store a unique cart / order number prefix.
Personally, I'm not entirely sure why the cart number is used to pass to payment gateways, over say the order ID which is unique across the entire install, but this is how the legacy providers were built.
Anyways, I hope this helps solve this problem for you too.
RE UK Fest, yes, I should be attending so will be good to catch up 👍
Ah yes, it was the cart prefixed causing the issue. We had implemented custom order prefixes but not cart prefixed per site.
Adding custom cart prefixes seems to have sorted the issue and I can see from the db that the orders did indeed share the same cart ID so that make sense.
OK great, I should be attending so will let you know nearer the time.
These are both untested however, but hopefully it'll give you a good starting point.
With this approach, you shouldn't need the webhooks for standard Stripe payments. However, if you do modify a payment in some way in Stripe, it won't be updated in TC.
Give this a try and see how you get on. If it works out, I might make this the default as the webhooks stuff is just causing quite a few headaches, even though it is the recommended approach.
I'll do some more testing when I can and see what to do about merging it in. I need to decide the best approach as I don't want to annoy people who have upgraded already and we force them to have to redo the checkout flow again.
Glad we were able to resolve the issue for you though 👍
Multiple stores and Stripe webhook limit
With the new Stripe SCA implementation (which makes use of webhooks) there is a limit to the number of possible stores due to the webhook limit in Stripe.
We have one site that has over 16 stores (small front-end branded stores) but Stripe has a limit of 16 webhooks per live instance. As such it is not possible to hook every store up and hence the payment provider won't work past 16 stores.
Is there any way around this with the current setup?
It feels inefficient to have multiple webhooks for one instance of Umbraco (which may contain multiple stores) but I note the webhooks contain the store ID and possibly some other ID?
Failing that the alternative would be to write a custom webhook which then dispatches the relevant TC hooks or calls into the library directly.
Thanks
Matt
Man, this Stripe provider + the SCA changes are quickly becoming the bane of my life.
I think that given in the recent updates to the provider we register the webhook automatically on save, it's probably going to need you to run on a custom build of the payment provider, removing that functionality (Remove these
PreApplicationStartMethod
attributes https://github.com/TeaCommerce/Tea-Commerce-Payment-Providers/blob/master/Source/TeaCommerce.PaymentProviders.Stripe/Stripe.cs#L15).You can grab the source for the payment provider here and build it separately https://github.com/TeaCommerce/Tea-Commerce-Payment-Providers/tree/master/Source/TeaCommerce.PaymentProviders.Stripe (though, if you are using other providers, you may need to compile them separately too and remove the default payment providers dll, or, rename your custom stripe provider so that it doesn't conflict).
Now, we do currently record the order number in the Stripe payment intents meta data https://github.com/TeaCommerce/Tea-Commerce-Payment-Providers/blob/master/Source/TeaCommerce.PaymentProviders.Stripe/Stripe.cs#L167 but you may need to extend this to also store the StoreId (or you could write a custom SQL statement to lookup the store from the Order ID, but to try and load an order via the TC API will require a Store ID https://docs.teacommerce.net/3.3.2/api/order/#getorder).
Once you have a means of retrieving the Store ID, what I'd be tempted to do is write a custom controller to act as your webhook entry point, then lookup the Store ID and then redirect to the built in webhook URL (the format being
/base/TC/PaymentCommunicationWithoutOrderId/[storeId]/Stripe%20-%20inline/[paymentMethodId]
) for TC to do what it needs to do.This should get your setup working.
Another option would be to run on a completely custom Stripe provider build that uses a synchronous approach to handling payment intents (ie, something that doesn't need webhooks at all). This would need to be custom written though. We went the webhooks route as a) it's the Stripe recommended approach and b) it meant logic could be shared between the standard Stripe provider and the Stripe Subscription provider, which can ONLY work via webhooks.
In terms of what could be done to our Stripe payment provider / Tea Commerce itself to allow the sharing of a webhook URL, I'd need to have a think about this. It would be a pretty big change to how things currently work (payment method configs being independent of each other).
I hope this gives you some direction to move in.
Matt
Incase you want to go the later approach of a synchronous Stripe flow, you can read more on how this would be implemented here https://stripe.com/docs/payments/payment-intents/migration If you do go that approach, you should at least be able to use the existing provider as a starting point.
So, I had a little think about this yesterday, and I think I've come up with a longer term solution, however this will be a future update as it will require quite a few changes.
Ultimately, I think I'm going to take a look at separating out "Account Settings" on payment providers, such that these can be shared across multiple providers, so things like API keys + secrets etc. On a payment provider config then, you'd either be able to reuse an existing "account" or setup another one. This way it allows stores to share credentials if they can, but can still be per store if needs be.
Once these are broken out, I think it should then be possible to have a webhook endpoint per provider + account combination (rather than per provider + payment method combo we currently have), and have these webhook endpoints be able to work out the store + order + payment method instances the request is associated with. This ultimately means then that only 1 webhook per account is needed, resolving the issue presented here.
As I say though, this is going to have to be a long term fix so is unlikely to resolve your issue right now. For that, I think you'll need to go with one of the solutions highlighted above.
On a side note, I'd really love to know more about your project as we don't get to hear from a lot of customers, and this project sounds kind of interesting. Would love to know more so we can make these types of projects simpler in the future.
Many thanks
Matt
Hi Matt
Thanks for looking into this and for the info.
What you are suggesting makes sense and would help out in this scenario (and make it simpler for multi-store solutions in general with shared payment provider).
We appear to have had an issue yesterday after deploying this where an incorrect order has been finalised and marked as captured following a webhook call (i.e. a webhook call for one store has incorrectly finalised an order in another store - most likely because we have multiple webhooks being fired at once but I'm surprised it finalised a totally invalid order). I need to look into this a bit more this morning but I would assume the webhook would be validating the order ID at the very least when fetching the order for a webhook request?
I'll let you know once I've found out more and if we put a workaround in place for the time being for the multiple webooks.
More than happy to share more on the project setup. I should imagine it's not a common scenario for sure. Are you going to Umbraco UK Festival this year?
Hi Matt,
I have seen that issue before and it usually comes about because stores share the same cart / order prefixes. The problem is, all orders are issued a cart number, but those cart numbers are sequential per store. The problem is, that when a webhook is hit, it fetches the cart number stored in the stripe order then looks it up. If you have a cart with that same number in the store, then it thinks it needs to finalize it. So really, you need to give each store a unique cart / order number prefix.
Personally, I'm not entirely sure why the cart number is used to pass to payment gateways, over say the order ID which is unique across the entire install, but this is how the legacy providers were built.
Anyways, I hope this helps solve this problem for you too.
RE UK Fest, yes, I should be attending so will be good to catch up 👍
Ah yes, it was the cart prefixed causing the issue. We had implemented custom order prefixes but not cart prefixed per site.
Adding custom cart prefixes seems to have sorted the issue and I can see from the db that the orders did indeed share the same cart ID so that make sense.
OK great, I should be attending so will let you know nearer the time.
Hi Matt,
I've had a look to see what it would take to convert the provider back into a synchronous one, and I think it could be doable.
I've modified the code of the Stripe provider which you can find here:
https://github.com/TeaCommerce/Tea-Commerce-Payment-Providers/blob/wip/stripe-sync/Source/TeaCommerce.PaymentProviders.Stripe/Stripe.cs
As well as the Stripe payment form example you can find here:
https://github.com/TeaCommerce/Tea-Commerce-Payment-Providers/blob/wip/stripe-sync/Source/TeaCommerce.PaymentProviders.UI/Views/Partials/StripePaymentForm.cshtml
These are both untested however, but hopefully it'll give you a good starting point.
With this approach, you shouldn't need the webhooks for standard Stripe payments. However, if you do modify a payment in some way in Stripe, it won't be updated in TC.
Give this a try and see how you get on. If it works out, I might make this the default as the webhooks stuff is just causing quite a few headaches, even though it is the recommended approach.
Hi Matt
We've been successfully running with this approach. Haven't had to make any changes. Worked out the box.
Thanks for looking into a solution. We removed all webhooks and running as s synch now with this flow.
Cheers
Matt
Hey Matt,
That's awesome. Thank you for testing this out.
I'll do some more testing when I can and see what to do about merging it in. I need to decide the best approach as I don't want to annoy people who have upgraded already and we force them to have to redo the checkout flow again.
Glad we were able to resolve the issue for you though 👍
Matt
is working on a reply...