handle-stripe-payment-action.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { FetchError, postJSON } from '@/infrastructure/fetch-json'
  2. import getMeta from '@/utils/meta'
  3. import { loadStripe } from '@stripe/stripe-js/pure'
  4. export default async function handleStripePaymentAction(
  5. error: FetchError,
  6. options?: { successPath?: string }
  7. ): Promise<{ handled: boolean }> {
  8. const clientSecret = error?.data?.clientSecret
  9. const publicKey = error?.data?.publicKey
  10. if (clientSecret && publicKey) {
  11. const stripe = await loadStripe(publicKey)
  12. if (stripe) {
  13. const currentPath = window.location.pathname + window.location.search
  14. const returnUrl = new URL(
  15. '/user/subscription/offsite',
  16. getMeta('ol-ExposedSettings').siteUrl
  17. )
  18. const returnParams = new URLSearchParams({ path: currentPath })
  19. if (options?.successPath) {
  20. returnParams.set('successPath', options.successPath)
  21. }
  22. returnUrl.search = returnParams.toString()
  23. const manualConfirmationFlow = await stripe.confirmPayment({
  24. clientSecret,
  25. redirect: 'if_required',
  26. confirmParams: {
  27. return_url: returnUrl.toString(),
  28. },
  29. })
  30. if (manualConfirmationFlow.error) {
  31. const paymentIntentId = manualConfirmationFlow.error.payment_intent?.id
  32. try {
  33. await postJSON(
  34. `/user/subscription/void-change?payment_intent_id=${paymentIntentId}`
  35. )
  36. } catch (error) {
  37. // do nothing
  38. }
  39. return { handled: false }
  40. } else {
  41. try {
  42. await postJSON(`/user/subscription/sync`)
  43. } catch (error) {
  44. // if the sync fails, there may be stale data until the webhook is
  45. // processed but we can't do any special handling for that in here
  46. }
  47. return { handled: true }
  48. }
  49. }
  50. }
  51. return { handled: false }
  52. }