@edx/frontend-app-subscription-checkout 1.15.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/checkoutPage/CheckoutPage.js +2 -6
  2. package/dist/checkoutPage/CheckoutPage.js.map +1 -1
  3. package/dist/components/Checkout/Checkout.d.ts +2 -0
  4. package/dist/components/Checkout/Checkout.js +7 -3
  5. package/dist/components/Checkout/Checkout.js.map +1 -1
  6. package/dist/components/Checkout/Messages.d.ts +8 -0
  7. package/dist/components/Checkout/Messages.js +10 -0
  8. package/dist/components/Checkout/Messages.js.map +1 -0
  9. package/dist/components/CheckoutGate/CheckoutGate.js +7 -3
  10. package/dist/components/CheckoutGate/CheckoutGate.js.map +1 -1
  11. package/dist/components/CheckoutGate/Messages.d.ts +8 -0
  12. package/dist/components/CheckoutGate/Messages.js +10 -0
  13. package/dist/components/CheckoutGate/Messages.js.map +1 -0
  14. package/dist/components/PaymentForm/Messages.d.ts +6 -1
  15. package/dist/components/PaymentForm/Messages.js +9 -4
  16. package/dist/components/PaymentForm/Messages.js.map +1 -1
  17. package/dist/components/PaymentForm/PaymentForm.d.ts +4 -3
  18. package/dist/components/PaymentForm/PaymentForm.js +40 -12
  19. package/dist/components/PaymentForm/PaymentForm.js.map +1 -1
  20. package/dist/constants.d.ts +2 -3
  21. package/dist/constants.js +6 -5
  22. package/dist/constants.js.map +1 -1
  23. package/dist/data/hooks/useCheckout.d.ts +2 -2
  24. package/dist/data/hooks/useCheckout.js +9 -2
  25. package/dist/data/hooks/useCheckout.js.map +1 -1
  26. package/dist/data/hooks/useCheckoutGate.d.ts +4 -3
  27. package/dist/data/hooks/useCheckoutGate.js +28 -6
  28. package/dist/data/hooks/useCheckoutGate.js.map +1 -1
  29. package/dist/data/hooks/useCheckoutMutations.d.ts +2 -2
  30. package/dist/data/hooks/useCheckoutMutations.js +4 -3
  31. package/dist/data/hooks/useCheckoutMutations.js.map +1 -1
  32. package/dist/data/hooks/useCheckoutQueries.d.ts +2 -0
  33. package/dist/data/hooks/useCheckoutQueries.js +10 -0
  34. package/dist/data/hooks/useCheckoutQueries.js.map +1 -1
  35. package/dist/types.d.ts +1 -0
  36. package/dist/types.js.map +1 -1
  37. package/dist/utils/checkoutErrors.d.ts +1 -0
  38. package/dist/utils/checkoutErrors.js +11 -0
  39. package/dist/utils/checkoutErrors.js.map +1 -0
  40. package/dist/utils/provision.d.ts +24 -1
  41. package/dist/utils/provision.js +69 -3
  42. package/dist/utils/provision.js.map +1 -1
  43. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"PaymentForm.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/PaymentForm.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,aAAa,MAAM,gCAAgC,CAAC;AAG3D,OAAO,EAAE,KAAK,EAAE,iCAAiC,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC9F,OAAO,QAAQ,MAAM,YAAY,CAAC;AAyBlC,MAAM,WAAW,GAAG,CAAC,EACnB,OAAO,EACP,QAAQ,EACR,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,QAAQ,EACR,WAAW,EACX,WAAW,GAAG,IAAI,EAClB,WAAW,GAAG,CAAC,EACf,oBAAoB,GAAG,IAAI,GACV,EAAE,EAAE;;IACrB,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAiB,CAAC;IACxC,MAAM,eAAe,GAAG,MAAM,CAAC,iBAA2B,CAAC;IAC3D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAgB,MAAM,CAAC,CAAC;IAC1E,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1D,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,iCAAiC,CAAC,CAAC;IAEpF,MAAM,gBAAgB,GAClB,CAAC,CAAC,WAAW,IAAI,iCAAiC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE7E,MAAM,WAAW,GAAG,aAAa,KAAK,QAAQ,CAAC;IAC/C,MAAM,IAAI,GAAG,UAAU,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC;IAE1E,IAAI,WAAW,GAAG,aAAa,KAAK,QAAQ;QAC1C,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC5C,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAChD,IAAI,UAAU;QAAE,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;SAC5D,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC;QAAE,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAE9G,MAAM,SAAS,GAAG,WAAW,KAAK,SAAS,CAAC;IAC5C,MAAM,SAAS,GAAG,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,MAAM,SAAS,GAAG,CAAC,CAAC;IACpB,MAAM,OAAO,GAAG,SAAS;QACvB,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,mBAAmB,EAAE;YAC1C,WAAW;YACX,WAAW;YACX,aAAa,EAAE,oBAAoB;SACpC,CAAC;QACJ,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,kBAAkB,EAAE;YACzC,MAAM,EAAE,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,mCAAI,EAAE;YACjC,SAAS;SACV,CAAC,CAAC;IACP,MAAM,oBAAoB,GAAG,SAAS;QACpC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,uBAAuB,EAAE;YAC9C,WAAW;YACX,WAAW;YACX,aAAa,EAAE,oBAAoB;SACpC,CAAC;QACJ,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,sBAAsB,EAAE;YAC7C,MAAM,EAAE,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,mCAAI,EAAE;SAClC,CAAC,CAAC;IAEP,MAAM,iBAAiB,GAAG;QACxB,OAAO;QACP,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC7C,UAAU,EAAE,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC;KACjD,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS;QACzB,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,kCAC7B,iBAAiB,KACpB,SAAS,EACT,IAAI,EAAE,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,QAAQ,IAC1B;QACJ,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IAEjE,MAAM,YAAY,GAAG,GAAoB,EAAE;QACzC,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;QACvD,IAAI,gBAAgB,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,OAAO;YACL,iBAAiB,EAAE,SAAS;YAC5B,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI;YACrD,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;SACxC,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,uBAAuB,aACpC,aAAI,SAAS,EAAC,8DAA8D,YACzE,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GACzC,EAEL,aAAG,SAAS,EAAC,+BAA+B,aAC1C,iBAAQ,SAAS,EAAC,0BAA0B,YACzC,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,GAChC,EAAC,GAAG,EACb,eAAM,SAAS,EAAC,eAAe,YAC5B,aAAa,CAAC,QAAQ,CAAC,kBAAkB,EAAE;4BAC1C,IAAI,EAAE,CACJ,YACE,IAAI,EAAC,yBAAyB,EAC9B,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,eAAe,YAExB,aAAa,CAAC,QAAQ,CAAC,iBAAiB,CAAC,GACxC,CACL;yBACF,CAAC,GACG,IACL,EAGJ,eAAK,SAAS,EAAC,4BAA4B,aAEzC,eACE,SAAS,EAAE,uBAAuB,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,EAAE,aAGrG,iBACE,OAAO,EAAC,oBAAoB,EAC5B,SAAS,EAAC,6BAA6B,aAEvC,gBACE,EAAE,EAAC,oBAAoB,EACvB,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,KAAK,EAAC,MAAM,EACZ,OAAO,EAAE,aAAa,KAAK,MAAM,EACjC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,EACxC,SAAS,EAAC,qBAAqB,GAC/B,EACF,cACE,KAAK,EAAC,4BAA4B,EAClC,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,YAEX,eACE,QAAQ,EAAC,SAAS,EAClB,QAAQ,EAAC,SAAS,EAClB,CAAC,EAAC,2nBAA2nB,EAC7nB,IAAI,EAAC,SAAS,GACd,GACE,EACN,eAAM,SAAS,EAAC,yCAAyC,YACtD,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,GACxB,IACD,EAGR,eACE,SAAS,EAAE,2BAA2B,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,sCAAsC,EAAE,iBACjG,aAAa,KAAK,MAAM,aAErC,KAAC,aAAa,IACZ,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,GACpB,EACF,MAAC,IAAI,CAAC,KAAK,IACT,SAAS,EAAC,SAAS,EACnB,SAAS,EAAC,mCAAmC,aAE7C,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,mBAAmB,YACtC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,GACrB,EACb,KAAC,IAAI,CAAC,OAAO,IACX,EAAE,EAAC,QAAQ,EACX,KAAK,EAAE,OAAO,CAAC,OAAO,EACtB,QAAQ,EAAE,CAAC,CAAuC,EAAE,EAAE,CACpD,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,YAEpC,iBAAiB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;oDACjC,OAAO,CACL,iBAAyB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,YACvC,OAAO,CAAC,CAAC,CAAC,IADA,OAAO,CAAC,CAAC,CAAC,CAEd,CACV,CAAC;gDACJ,CAAC,CAAC,GACW,IACJ,IACT,IACF,EAGN,cACE,SAAS,EAAE,yDAAyD,aAAa,KAAK,WAAW,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,EAAE,YAE5I,iBACE,OAAO,EAAC,yBAAyB,EACjC,SAAS,EAAC,6BAA6B,aAEvC,gBACE,EAAE,EAAC,yBAAyB,EAC5B,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,KAAK,EAAC,WAAW,EACjB,OAAO,EAAE,aAAa,KAAK,WAAW,EACtC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,EAC7C,SAAS,EAAC,qBAAqB,GAC/B,EACF,eACE,SAAS,EAAC,2DAA2D,iBACzD,MAAM,kBAGb,EACP,eAAM,SAAS,EAAC,2BAA2B,YACxC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,GAC7B,IACD,GACJ,EAGN,cACE,SAAS,EAAE,4BAA4B,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,EAAE,EAAE,YAE5G,iBACE,OAAO,EAAC,sBAAsB,EAC9B,SAAS,EAAC,6BAA6B,aAEvC,gBACE,EAAE,EAAC,sBAAsB,EACzB,IAAI,EAAC,OAAO,EACZ,IAAI,EAAC,eAAe,EACpB,KAAK,EAAC,QAAQ,EACd,OAAO,EAAE,aAAa,KAAK,QAAQ,EACnC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAC1C,SAAS,EAAC,qBAAqB,GAC/B,EACF,eACE,SAAS,EAAC,6DAA6D,iBAC3D,MAAM,kBAGb,EACP,eAAM,SAAS,EAAC,2BAA2B,YACxC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,GAC1B,IACD,GACJ,IACF,EAGN,YAAG,SAAS,EAAC,wCAAwC,YAClD,SAAS;oBACR,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,EAAE;wBAClC,SAAS;wBACT,IAAI,EAAE,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,QAAQ;wBAC1B,OAAO;wBACP,SAAS,EAAE,CACT,YACE,SAAS,EAAC,eAAe,EACzB,IAAI,EAAE,MAAM,YAEX,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,GACjC,CACL;wBACD,UAAU,EAAE,CACV,YACE,SAAS,EAAC,eAAe,EACzB,IAAI,EAAE,eAAe,YAEpB,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,GACnC,CACL;qBACF,CAAC;oBACJ,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,iBAAiB,EAAE;wBACxC,OAAO;wBACP,SAAS,EAAE,CACT,YACE,SAAS,EAAC,eAAe,EACzB,IAAI,EAAE,MAAM,YAEX,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,GACjC,CACL;wBACD,UAAU,EAAE,CACV,YACE,SAAS,EAAC,eAAe,EACzB,IAAI,EAAE,eAAe,YAEpB,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,GACnC,CACL;qBACF,CAAC,GACJ,EAGJ,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,kBAAkB,EAAC,SAAS,EAAC,4BAA4B,YAC7E,KAAC,IAAI,CAAC,QAAQ,IACZ,EAAE,EAAC,kBAAkB,EACrB,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,CAAC,CAAsC,EAAE,EAAE,CACnD,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,YAEhC,eAAM,SAAS,EAAC,2CAA2C,YACxD,oBAAoB,GAChB,GACO,GACL,EAEZ,gBAAgB,IAAI,CACnB,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,aAAa,EAAC,SAAS,EAAC,4BAA4B,YACxE,KAAC,IAAI,CAAC,QAAQ,IACZ,EAAE,EAAC,aAAa,EAChB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,CAAC,CAAsC,EAAE,EAAE,CACnD,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,YAEpC,eAAM,SAAS,EAAC,2CAA2C,YACxD,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GACvC,GACO,GACL,CACd,EAGD,MAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,SAAS,EAAC,sBAAsB,EAChC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,EAC1D,QAAQ,EACN,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC;uBAC1B,UAAU;uBACV,CAAC,SAAS;uBACV,CAAC,gBAAgB,IAAI,CAAC,aAAa,CAAC,aAGxC,IAAI,IAAI,CACP,KAAC,OAAO,IACN,SAAS,EAAC,QAAQ,EAClB,IAAI,EAAC,IAAI,EACT,SAAS,EAAC,MAAM,EAChB,gBAAgB,EAAE,aAAa,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GACjE,CACH,EACA,WAAW,IACL,IACL,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC","sourcesContent":["import React, { useState } from 'react';\nimport type { Ref } from 'react';\nimport { Button, Form, Spinner } from '@openedx/paragon';\nimport { useIntl, getAppConfig } from '@openedx/frontend-base';\nimport PaymentFields from '../PaymentFields/PaymentFields';\nimport type { BillingInfo, CheckoutConsent, PaymentMethod } from '../../types';\nimport type { PlanPrice } from '../../utils/billingDetails';\nimport { appId, COUNTRIES_REQUIRING_EXTRA_CONFIRM, BILLING_COUNTRIES } from '../../constants';\nimport messages from './Messages';\n\nexport interface PaymentFormProps {\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n cardError: string,\n stripeReady: boolean,\n sessionReady: boolean,\n submitting: boolean,\n onPlaceOrder: (consent: CheckoutConsent, paymentMethod: PaymentMethod) => void,\n priceToShow: PlanPrice | null,\n cycleToShow: string,\n trialEnd?: string,\n userCountry?: string | null,\n /** Promotional monthly price e.g. \"39\" — monthly plans only. */\n promoAmount?: string,\n /** Length of the promotional period in months. */\n promoMonths?: number,\n /** Regular monthly price after the promo period e.g. \"59\". */\n monthlyRegularAmount?: string,\n}\n\nconst PaymentForm = ({\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n cardError,\n stripeReady,\n sessionReady,\n submitting,\n onPlaceOrder,\n priceToShow,\n cycleToShow,\n trialEnd,\n userCountry,\n promoAmount = '39',\n promoMonths = 3,\n monthlyRegularAmount = '59',\n}: PaymentFormProps) => {\n const { formatMessage } = useIntl();\n const config = getAppConfig(appId);\n const tosUrl = config.TOS_URL as string;\n const refundPolicyUrl = config.REFUND_POLICY_URL as string;\n const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>('card');\n const [confirmed, setConfirmed] = useState(false);\n const [ukCaConfirmed, setUkCaConfirmed] = useState(false);\n\n console.log('userCountry', userCountry);\n console.log('COUNTRIES_REQUIRING_EXTRA_CONFIRM', COUNTRIES_REQUIRING_EXTRA_CONFIRM);\n\n const showExtraConfirm\n = !!userCountry && COUNTRIES_REQUIRING_EXTRA_CONFIRM.includes(userCountry);\n\n const needsStripe = paymentMethod !== 'paypal';\n const busy = submitting || (needsStripe && !stripeReady) || !sessionReady;\n\n let buttonLabel = paymentMethod === 'paypal'\n ? formatMessage(messages.continueWithPaypal)\n : formatMessage(messages.confirmSubscription);\n if (submitting) buttonLabel = formatMessage(messages.processing);\n else if (!sessionReady || (needsStripe && !stripeReady)) buttonLabel = formatMessage(messages.loadingPayment);\n\n const isMonthly = cycleToShow === 'monthly';\n const frequency = cycleToShow === 'annual' ? 'year' : 'month';\n const trialDays = 7;\n const pricing = isMonthly\n ? formatMessage(messages.termsPricingMonthly, {\n promoAmount,\n promoMonths,\n regularAmount: monthlyRegularAmount,\n })\n : formatMessage(messages.termsPricingAnnual, {\n amount: priceToShow?.amount ?? '',\n frequency,\n });\n const recurringConfirmText = isMonthly\n ? formatMessage(messages.recurringConfirmMonthly, {\n promoAmount,\n promoMonths,\n regularAmount: monthlyRegularAmount,\n })\n : formatMessage(messages.recurringConfirmAnnual, {\n amount: priceToShow?.amount ?? '',\n });\n\n const termsNoticeValues = {\n pricing,\n termsLink: formatMessage(messages.termsOfUse),\n refundLink: formatMessage(messages.refundPolicy),\n };\n\n const termsText = isMonthly\n ? formatMessage(messages.termsNotice, {\n ...termsNoticeValues,\n trialDays,\n date: trialEnd ?? '{date}',\n })\n : formatMessage(messages.termsNoticeAnnual, termsNoticeValues);\n\n const buildConsent = (): CheckoutConsent => {\n const consentParts = [termsText, recurringConfirmText];\n if (showExtraConfirm) {\n consentParts.push(formatMessage(messages.ukCaResidentConfirm));\n }\n return {\n tConsentRecurring: confirmed,\n tConsentUkCa: showExtraConfirm ? ukCaConfirmed : null,\n tConsentAt: new Date().toISOString(),\n tConsentText: consentParts.join('\\n\\n'),\n };\n };\n\n return (\n <div className=\"payment-form bg-white\">\n <h2 className=\"payment-form__heading font-weight-bold mb-3 text-primary-500\">\n {formatMessage(messages.selectPaymentMethod)}\n </h2>\n\n <p className=\"payment-form__help small mb-4\">\n <strong className=\"d-block text-primary-500\">\n {formatMessage(messages.needAssistance)}\n </strong>{' '}\n <span className=\"text-gray-700\">\n {formatMessage(messages.needAssistanceBody, {\n link: (\n <a\n href=\"https://support.edx.org\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-gray-700\"\n >\n {formatMessage(messages.learnerHelpCenter)}\n </a>\n ),\n })}\n </span>\n </p>\n\n {/* ── Payment method accordion ── */}\n <div className=\"payment-form__methods mb-4\">\n {/* ── Card ── */}\n <div\n className={`payment-form__method${paymentMethod === 'card' ? ' payment-form__method--selected' : ''}`}\n >\n {/* Header row — always visible */}\n <label\n htmlFor=\"paymentMethod-card\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-card\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"card\"\n checked={paymentMethod === 'card'}\n onChange={() => setPaymentMethod('card')}\n className=\"payment-form__radio\"\n />\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0 4C0 3.46957 0.210714 2.96086 0.585786 2.58579C0.960859 2.21071 1.46957 2 2 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4H0ZM0 6V12C0 12.5304 0.210714 13.0391 0.585786 13.4142C0.960859 13.7893 1.46957 14 2 14H14C14.5304 14 15.0391 13.7893 15.4142 13.4142C15.7893 13.0391 16 12.5304 16 12V6H0ZM3 11C3 10.7348 3.10536 10.4804 3.29289 10.2929C3.48043 10.1054 3.73478 10 4 10H5C5.26522 10 5.51957 10.1054 5.70711 10.2929C5.89464 10.4804 6 10.7348 6 11C6 11.2652 5.89464 11.5196 5.70711 11.7071C5.51957 11.8946 5.26522 12 5 12H4C3.73478 12 3.48043 11.8946 3.29289 11.7071C3.10536 11.5196 3 11.2652 3 11Z\"\n fill=\"#0270DE\"\n />\n </svg>\n <span className=\"payment-form__method-name text-info-500\">\n {formatMessage(messages.card)}\n </span>\n </label>\n\n {/* Keep Stripe host nodes mounted so Elements stay interactive after toggling methods. */}\n <div\n className={`payment-form__card-panel${paymentMethod === 'card' ? '' : ' payment-form__card-panel--collapsed'}`}\n aria-hidden={paymentMethod !== 'card'}\n >\n <PaymentFields\n numberMountRef={numberMountRef}\n expiryMountRef={expiryMountRef}\n cvcMountRef={cvcMountRef}\n cardError={cardError}\n />\n <Form.Group\n controlId=\"country\"\n className=\"mt-3 mb-0 payment__field--country\"\n >\n <Form.Label className=\"small m-0 x-small\">\n {formatMessage(messages.country)}\n </Form.Label>\n <Form.Control\n as=\"select\"\n value={billing.country}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>\n setField('country', e.target.value)}\n >\n {BILLING_COUNTRIES.map((country) => {\n return (\n <option key={country[0]} value={country[0]}>\n {country[1]}\n </option>\n );\n })}\n </Form.Control>\n </Form.Group>\n </div>\n </div>\n\n {/* ── Google Pay (hidden for now) ── */}\n <div\n className={`my-3 payment-form__method payment-form__method--hidden${paymentMethod === 'googlepay' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-googlepay\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-googlepay\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"googlepay\"\n checked={paymentMethod === 'googlepay'}\n onChange={() => setPaymentMethod('googlepay')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--gpay\"\n aria-hidden=\"true\"\n >\n G\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.googlePay)}\n </span>\n </label>\n </div>\n\n {/* ── PayPal ── */}\n <div\n className={`my-3 payment-form__method${paymentMethod === 'paypal' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-paypal\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-paypal\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"paypal\"\n checked={paymentMethod === 'paypal'}\n onChange={() => setPaymentMethod('paypal')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--paypal\"\n aria-hidden=\"true\"\n >\n P\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.paypal)}\n </span>\n </label>\n </div>\n </div>\n\n {/* ── Terms ── */}\n <p className=\"payment-form__terms text-gray-700 mb-3\">\n {isMonthly\n ? formatMessage(messages.termsNotice, {\n trialDays,\n date: trialEnd ?? '{date}',\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })\n : formatMessage(messages.termsNoticeAnnual, {\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })}\n </p>\n\n {/* ── Checkboxes ── */}\n <Form.Group controlId=\"recurringConfirm\" className=\"mb-3 payment-form__confirm\">\n <Form.Checkbox\n id=\"recurringConfirm\"\n checked={confirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {recurringConfirmText}\n </span>\n </Form.Checkbox>\n </Form.Group>\n\n {showExtraConfirm && (\n <Form.Group controlId=\"ukCaConfirm\" className=\"mb-4 payment-form__confirm\">\n <Form.Checkbox\n id=\"ukCaConfirm\"\n checked={ukCaConfirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setUkCaConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {formatMessage(messages.ukCaResidentConfirm)}\n </span>\n </Form.Checkbox>\n </Form.Group>\n )}\n\n {/* ── Submit ── */}\n <Button\n variant=\"brand\"\n className=\"payment-form__submit\"\n onClick={() => onPlaceOrder(buildConsent(), paymentMethod)}\n disabled={\n (needsStripe && !stripeReady)\n || submitting\n || !confirmed\n || (showExtraConfirm && !ukCaConfirmed)\n }\n >\n {busy && (\n <Spinner\n animation=\"border\"\n size=\"sm\"\n className=\"mr-2\"\n screenReaderText={formatMessage(messages.spinnerScreenReaderText)}\n />\n )}\n {buttonLabel}\n </Button>\n </div>\n );\n};\n\nexport default PaymentForm;\n"]}
1
+ {"version":3,"file":"PaymentForm.js","sourceRoot":"","sources":["../../../src/components/PaymentForm/PaymentForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useState } from 'react';\nimport type { Ref } from 'react';\nimport { Button, Form, Spinner } from '@openedx/paragon';\nimport { useIntl, getAppConfig } from '@openedx/frontend-base';\nimport PaymentFields from '../PaymentFields/PaymentFields';\nimport type { BillingInfo, CheckoutConsent, PaymentMethod, SupportedPaymentMethod } from '../../types';\nimport type { PlanPrice } from '../../utils/billingDetails';\nimport {\n appId,\n COUNTRIES_REQUIRING_EXTRA_CONFIRM,\n BILLING_COUNTRIES,\n} from '../../constants';\nimport { fetchIpGeolocation, fetchPublicIp } from '../../utils/provision';\nimport messages from './Messages';\n\nexport interface PaymentFormProps {\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n cardError: string,\n stripeReady: boolean,\n sessionReady: boolean,\n submitting: boolean,\n onPlaceOrder: (consent: CheckoutConsent, paymentMethod: SupportedPaymentMethod) => void,\n priceToShow: PlanPrice | null,\n cycleToShow: string,\n trialEnd?: string,\n userCountry?: string | null,\n /** Promotional monthly price e.g. \"39\" — monthly plans only. */\n promoAmount?: string,\n /** Length of the promotional period in months. */\n promoMonths?: number,\n /** Regular monthly price after the promo period e.g. \"59\". */\n monthlyRegularAmount?: string,\n geolocationUrl?: string,\n}\n\nconst PaymentForm = ({\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n cardError,\n stripeReady,\n sessionReady,\n submitting,\n onPlaceOrder,\n priceToShow,\n cycleToShow,\n trialEnd,\n promoAmount = '39',\n promoMonths = 3,\n monthlyRegularAmount = '59',\n geolocationUrl,\n}: PaymentFormProps) => {\n const { formatMessage } = useIntl();\n const config = getAppConfig(appId);\n const tosUrl = config.TOS_URL as string;\n const refundPolicyUrl = config.REFUND_POLICY_URL as string;\n const [paymentMethod, setPaymentMethod] = useState<PaymentMethod>('card');\n const [confirmed, setConfirmed] = useState(false);\n const [extraConfirmed, setExtraConfirmed] = useState(false);\n\n const showExtraConfirm = COUNTRIES_REQUIRING_EXTRA_CONFIRM.includes(billing.country);\n const extraConfirmMessage = billing.country === 'CA'\n ? messages.canadaQuebecConfirm\n : messages.ukWithdrawalConfirm;\n const extraConfirmId = billing.country === 'CA'\n ? 'canadaQuebecConfirm'\n : 'ukWithdrawalConfirm';\n\n useEffect(() => {\n if (!geolocationUrl) return;\n\n void fetchPublicIp()\n .then((ipAddress) => fetchIpGeolocation(geolocationUrl, ipAddress))\n .then((geolocation) => {\n const countryCode = geolocation.country_code?.toUpperCase();\n if (countryCode && BILLING_COUNTRIES.some(([code]) => code === countryCode)) {\n setField('country', countryCode);\n }\n })\n .catch(() => undefined);\n }, [geolocationUrl, setField]);\n\n const needsStripe = paymentMethod !== 'paypal';\n const busy = submitting || (needsStripe && !stripeReady) || !sessionReady;\n\n let buttonLabel = paymentMethod === 'paypal'\n ? formatMessage(messages.continueWithPaypal)\n : formatMessage(messages.confirmSubscription);\n if (submitting) buttonLabel = formatMessage(messages.processing);\n else if (!sessionReady || (needsStripe && !stripeReady)) buttonLabel = formatMessage(messages.loadingPayment);\n\n const isMonthly = cycleToShow === 'monthly';\n const frequency = cycleToShow === 'annual' ? 'year' : 'month';\n const trialDays = 7;\n const pricing = isMonthly\n ? formatMessage(messages.termsPricingMonthly, {\n promoAmount,\n promoMonths,\n regularAmount: monthlyRegularAmount,\n })\n : formatMessage(messages.termsPricingAnnual, {\n amount: priceToShow?.amount ?? '',\n frequency,\n });\n const recurringConfirmText = isMonthly\n ? formatMessage(messages.recurringConfirmMonthly, {\n promoAmount,\n promoMonths,\n regularAmount: monthlyRegularAmount,\n })\n : formatMessage(messages.recurringConfirmAnnual, {\n amount: priceToShow?.amount ?? '',\n });\n\n const termsNoticeValues = {\n pricing,\n termsLink: formatMessage(messages.termsOfUse),\n refundLink: formatMessage(messages.refundPolicy),\n };\n\n const termsText = isMonthly\n ? formatMessage(messages.termsNotice, {\n ...termsNoticeValues,\n trialDays,\n date: trialEnd ?? '{date}',\n })\n : formatMessage(messages.termsNoticeAnnual, termsNoticeValues);\n\n const buildConsent = (): CheckoutConsent => {\n const consentParts = [termsText, recurringConfirmText];\n if (showExtraConfirm) {\n consentParts.push(formatMessage(extraConfirmMessage));\n }\n return {\n tConsentRecurring: confirmed,\n tConsentUkCa: showExtraConfirm ? extraConfirmed : null,\n tConsentAt: new Date().toISOString(),\n tConsentText: consentParts.join('\\n\\n'),\n };\n };\n\n return (\n <div className=\"payment-form bg-white\">\n <h2 className=\"payment-form__heading font-weight-bold mb-3 text-primary-500\">\n {formatMessage(messages.selectPaymentMethod)}\n </h2>\n\n <p className=\"payment-form__help small mb-4\">\n <strong className=\"d-block text-primary-500\">\n {formatMessage(messages.needAssistance)}\n </strong>{' '}\n <span className=\"text-gray-700\">\n {formatMessage(messages.needAssistanceBody, {\n link: (\n <a\n href=\"https://support.edx.org\"\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-gray-700\"\n >\n {formatMessage(messages.learnerHelpCenter)}\n </a>\n ),\n })}\n </span>\n </p>\n\n {/* ── Payment method accordion ── */}\n <div className=\"payment-form__methods mb-4\">\n {/* ── Card ── */}\n <div\n className={`payment-form__method${paymentMethod === 'card' ? ' payment-form__method--selected' : ''}`}\n >\n {/* Header row — always visible */}\n <label\n htmlFor=\"paymentMethod-card\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-card\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"card\"\n checked={paymentMethod === 'card'}\n onChange={() => setPaymentMethod('card')}\n className=\"payment-form__radio\"\n />\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0 4C0 3.46957 0.210714 2.96086 0.585786 2.58579C0.960859 2.21071 1.46957 2 2 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4H0ZM0 6V12C0 12.5304 0.210714 13.0391 0.585786 13.4142C0.960859 13.7893 1.46957 14 2 14H14C14.5304 14 15.0391 13.7893 15.4142 13.4142C15.7893 13.0391 16 12.5304 16 12V6H0ZM3 11C3 10.7348 3.10536 10.4804 3.29289 10.2929C3.48043 10.1054 3.73478 10 4 10H5C5.26522 10 5.51957 10.1054 5.70711 10.2929C5.89464 10.4804 6 10.7348 6 11C6 11.2652 5.89464 11.5196 5.70711 11.7071C5.51957 11.8946 5.26522 12 5 12H4C3.73478 12 3.48043 11.8946 3.29289 11.7071C3.10536 11.5196 3 11.2652 3 11Z\"\n fill=\"#0270DE\"\n />\n </svg>\n <span className=\"payment-form__method-name text-info-500\">\n {formatMessage(messages.card)}\n </span>\n </label>\n\n {/* Keep Stripe host nodes mounted so Elements stay interactive after toggling methods. */}\n <div\n className={`payment-form__card-panel${paymentMethod === 'card' ? '' : ' payment-form__card-panel--collapsed'}`}\n aria-hidden={paymentMethod !== 'card'}\n >\n <PaymentFields\n numberMountRef={numberMountRef}\n expiryMountRef={expiryMountRef}\n cvcMountRef={cvcMountRef}\n cardError={cardError}\n />\n <Form.Group\n controlId=\"country\"\n className=\"mt-3 mb-0 payment__field--country\"\n >\n <Form.Label className=\"small m-0 x-small\">\n {formatMessage(messages.country)}\n </Form.Label>\n <Form.Control\n as=\"select\"\n value={billing.country}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {\n const selectedCountry = e.target.value;\n setField('country', selectedCountry);\n setExtraConfirmed(false);\n }}\n >\n {BILLING_COUNTRIES.map((country) => {\n return (\n <option key={country[0]} value={country[0]}>\n {country[1]}\n </option>\n );\n })}\n </Form.Control>\n </Form.Group>\n </div>\n </div>\n\n {/* ── Google Pay (hidden for now) ── */}\n <div\n className={`my-3 payment-form__method payment-form__method--hidden${paymentMethod === 'googlepay' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-googlepay\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-googlepay\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"googlepay\"\n checked={paymentMethod === 'googlepay'}\n onChange={() => setPaymentMethod('googlepay')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--gpay\"\n aria-hidden=\"true\"\n >\n G\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.googlePay)}\n </span>\n </label>\n </div>\n\n {/* ── PayPal ── */}\n <div\n className={`my-3 payment-form__method${paymentMethod === 'paypal' ? ' payment-form__method--selected' : ''}`}\n >\n <label\n htmlFor=\"paymentMethod-paypal\"\n className=\"payment-form__method-header\"\n >\n <input\n id=\"paymentMethod-paypal\"\n type=\"radio\"\n name=\"paymentMethod\"\n value=\"paypal\"\n checked={paymentMethod === 'paypal'}\n onChange={() => setPaymentMethod('paypal')}\n className=\"payment-form__radio\"\n />\n <span\n className=\"payment-form__method-icon payment-form__method-icon--paypal\"\n aria-hidden=\"true\"\n >\n P\n </span>\n <span className=\"payment-form__method-name\">\n {formatMessage(messages.paypal)}\n </span>\n </label>\n </div>\n </div>\n\n {/* ── Terms ── */}\n <p className=\"payment-form__terms text-gray-700 mb-3\">\n {isMonthly\n ? formatMessage(messages.termsNotice, {\n trialDays,\n date: trialEnd ?? '{date}',\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })\n : formatMessage(messages.termsNoticeAnnual, {\n pricing,\n termsLink: (\n <a\n className=\"text-gray-700\"\n href={tosUrl}\n >\n {formatMessage(messages.termsOfUse)}\n </a>\n ),\n refundLink: (\n <a\n className=\"text-gray-700\"\n href={refundPolicyUrl}\n >\n {formatMessage(messages.refundPolicy)}\n </a>\n ),\n })}\n </p>\n\n {/* ── Checkboxes ── */}\n <Form.Group controlId=\"recurringConfirm\" className=\"mb-3 payment-form__confirm\">\n <Form.Checkbox\n id=\"recurringConfirm\"\n checked={confirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {recurringConfirmText}\n </span>\n </Form.Checkbox>\n </Form.Group>\n\n {showExtraConfirm && (\n <Form.Group controlId={extraConfirmId} className=\"mb-4 payment-form__confirm\">\n <Form.Checkbox\n id={extraConfirmId}\n checked={extraConfirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setExtraConfirmed(e.target.checked)}\n >\n <span className=\"text-gray-700 payment-form__confirm-label\">\n {formatMessage(extraConfirmMessage)}\n </span>\n </Form.Checkbox>\n </Form.Group>\n )}\n\n {/* ── Submit ── */}\n <Button\n variant=\"brand\"\n className=\"payment-form__submit\"\n onClick={() => {\n if (paymentMethod !== 'googlepay') {\n onPlaceOrder(buildConsent(), paymentMethod);\n }\n }}\n disabled={\n (needsStripe && !stripeReady)\n || submitting\n || !confirmed\n || paymentMethod === 'googlepay'\n || (showExtraConfirm && !extraConfirmed)\n }\n >\n {busy && (\n <Spinner\n animation=\"border\"\n size=\"sm\"\n className=\"mr-2\"\n screenReaderText={formatMessage(messages.spinnerScreenReaderText)}\n />\n )}\n {buttonLabel}\n </Button>\n </div>\n );\n};\n\nexport default PaymentForm;\n"]}
@@ -36,15 +36,14 @@ export declare const GATE_CHECK_COUNTRY = true;
36
36
  /**
37
37
  * ISO 3166-1 alpha-2 country codes that are permitted to complete checkout.
38
38
  * Add or remove codes here to open or restrict access by country.
39
- * e.g. ['US', 'CA', 'GB'] to allow US, Canada, and UK.
40
39
  */
41
40
  export declare const ALLOWED_CHECKOUT_COUNTRIES: readonly string[];
42
41
  /**
43
42
  * ISO 3166-1 alpha-2 country codes that require the extra billing-consent checkbox.
44
- * Add or remove codes here to control which residents see the second checkbox.
43
+ * Add or remove codes here to control which selected billing countries show it.
45
44
  */
46
45
  export declare const COUNTRIES_REQUIRING_EXTRA_CONFIRM: readonly string[];
47
- /** Billing country dropdown options. Swap back to COUNTRIES when expanding internationally. */
46
+ /** Billing country dropdown options for the supported countries in this checkout flow. */
48
47
  export declare const BILLING_COUNTRIES: readonly (readonly [string, string])[];
49
48
  export declare const STRIPE_FIELD_STYLE: CSSProperties;
50
49
  export declare const STRIPE_ELEMENT_OPTS: {
package/dist/constants.js CHANGED
@@ -61,12 +61,11 @@ export const GATE_CHECK_COUNTRY = true;
61
61
  /**
62
62
  * ISO 3166-1 alpha-2 country codes that are permitted to complete checkout.
63
63
  * Add or remove codes here to open or restrict access by country.
64
- * e.g. ['US', 'CA', 'GB'] to allow US, Canada, and UK.
65
64
  */
66
- export const ALLOWED_CHECKOUT_COUNTRIES = ['US', 'CA'];
65
+ export const ALLOWED_CHECKOUT_COUNTRIES = ['GB', 'AU', 'CA', 'US'];
67
66
  /**
68
67
  * ISO 3166-1 alpha-2 country codes that require the extra billing-consent checkbox.
69
- * Add or remove codes here to control which residents see the second checkbox.
68
+ * Add or remove codes here to control which selected billing countries show it.
70
69
  */
71
70
  export const COUNTRIES_REQUIRING_EXTRA_CONFIRM = ['GB', 'CA'];
72
71
  // export const COUNTRIES: readonly (readonly [string, string])[] = [
@@ -146,7 +145,6 @@ export const COUNTRIES_REQUIRING_EXTRA_CONFIRM = ['GB', 'CA'];
146
145
  // ['HN', 'Honduras'],
147
146
  // ['HU', 'Hungary'],
148
147
  // ['IS', 'Iceland'],
149
- // ['IN', 'India'],
150
148
  // ['ID', 'Indonesia'],
151
149
  // ['IR', 'Iran'],
152
150
  // ['IQ', 'Iraq'],
@@ -266,8 +264,11 @@ export const COUNTRIES_REQUIRING_EXTRA_CONFIRM = ['GB', 'CA'];
266
264
  // ['ZM', 'Zambia'],
267
265
  // ['ZW', 'Zimbabwe'],
268
266
  // ];
269
- /** Billing country dropdown options. Swap back to COUNTRIES when expanding internationally. */
267
+ /** Billing country dropdown options for the supported countries in this checkout flow. */
270
268
  export const BILLING_COUNTRIES = [
269
+ ['GB', 'United Kingdom'],
270
+ ['AU', 'Australia'],
271
+ ['CA', 'Canada'],
271
272
  ['US', 'United States'],
272
273
  ];
273
274
  // --- Stripe Element presentation ---------------------------------------------
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAG,gDAAgD,CAAC;AACtE,MAAM,CAAC,MAAM,wBAAwB,GAAG,iDAAiD,CAAC;AAE1F,gFAAgF;AAChF,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,gBAAgB,EAAE,kBAAkB;IACpC,eAAe,EAAE,iBAAiB;IAClC,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,iBAAiB,EAAE,mBAAmB;IACtC,4BAA4B,EAAE,8BAA8B;IAC5D,WAAW,EAAE,aAAa;IAC1B,oBAAoB,EAAE,sBAAsB;CACpC,CAAC;AAMX,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,MAAM,CAAC,oBAAoB;IAC3B,MAAM,CAAC,cAAc;IACrB,MAAM,CAAC,WAAW;CACnB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,OAAO,EAAE,cAAc;IACvB,OAAO,EAAE,iBAAiB;IAC1B,gBAAgB,EAAE,qBAAqB;IACvC,eAAe,EAAE,6CAA6C;IAC9D,cAAc,EAAE,eAAe;IAC/B,cAAc,EAAE,+BAA+B;IAC/C,4BAA4B,EAAE,4BAA4B;IAC1D,iBAAiB,EAAE,6BAA6B;IAChD,WAAW,EAAE,gBAAgB;IAC7B,oBAAoB,EAAE,sBAAsB;CAC7C,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAiC,EAAW,EAAE,CAC7E,eAAe,CAAC,QAAQ,CAAC,MAAgB,CAAC,CAAC;AAE7C,oEAAoE;AACpE,MAAM,UAAU,QAAQ,CAAC,MAAqB,EAAE,KAAc;IAC5D,IAAI,MAAM,KAAK,MAAM,CAAC,oBAAoB;QAAE,OAAO,SAAS,CAAC;IAC7D,IAAI,MAAM,KAAK,MAAM,CAAC,cAAc;QAAE,OAAO,SAAS,CAAC;IACvD,IAAI,MAAM,KAAK,MAAM,CAAC,WAAW;QAAE,OAAO,QAAQ,CAAC;IACnD,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM,CAAC,OAAO;QAAE,OAAO,YAAY,CAAC;IAC7D,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAClC,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,MAAM,EAAE,cAAc;IACtB,gBAAgB,EAAE,wBAAwB;IAC1C,WAAW,EAAE,sCAAsC;IACnD,UAAU,EAAE,sCAAsC;IAClD,iDAAiD;IACjD,cAAc,EAAE,sCAAsC;CACvD,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC;AAEtE,iFAAiF;AACjF,oEAAoE;AACpE,gFAAgF;AAEhF,oFAAoF;AACpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAE1E;;;GAGG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAEjF,qEAAqE;AACrE,2BAA2B;AAC3B,uBAAuB;AACvB,uBAAuB;AACvB,uBAAuB;AACvB,sBAAsB;AACtB,mCAAmC;AACnC,yBAAyB;AACzB,uBAAuB;AACvB,yBAAyB;AACzB,uBAAuB;AACvB,0BAA0B;AAC1B,uBAAuB;AACvB,uBAAuB;AACvB,0BAA0B;AAC1B,wBAAwB;AACxB,uBAAuB;AACvB,uBAAuB;AACvB,sBAAsB;AACtB,qBAAqB;AACrB,sBAAsB;AACtB,uBAAuB;AACvB,sCAAsC;AACtC,wBAAwB;AACxB,sBAAsB;AACtB,sBAAsB;AACtB,wBAAwB;AACxB,4BAA4B;AAC5B,uBAAuB;AACvB,0BAA0B;AAC1B,wBAAwB;AACxB,wBAAwB;AACxB,sBAAsB;AACtB,wCAAwC;AACxC,oBAAoB;AACpB,qBAAqB;AACrB,qBAAqB;AACrB,wBAAwB;AACxB,uBAAuB;AACvB,yCAAyC;AACzC,0BAA0B;AAC1B,uBAAuB;AACvB,oBAAoB;AACpB,sBAAsB;AACtB,wCAAwC;AACxC,gDAAgD;AAChD,uBAAuB;AACvB,wBAAwB;AACxB,wBAAwB;AACxB,kCAAkC;AAClC,uBAAuB;AACvB,qBAAqB;AACrB,2BAA2B;AAC3B,iCAAiC;AACjC,uBAAuB;AACvB,uBAAuB;AACvB,wBAAwB;AACxB,wBAAwB;AACxB,oBAAoB;AACpB,uBAAuB;AACvB,sBAAsB;AACtB,qBAAqB;AACrB,sBAAsB;AACtB,uBAAuB;AACvB,uBAAuB;AACvB,qBAAqB;AACrB,sBAAsB;AACtB,uBAAuB;AACvB,yBAAyB;AACzB,sBAAsB;AACtB,6BAA6B;AAC7B,sBAAsB;AACtB,qBAAqB;AACrB,uCAAuC;AACvC,wBAAwB;AACxB,uBAAuB;AACvB,uBAAuB;AACvB,qBAAqB;AACrB,yBAAyB;AACzB,oBAAoB;AACpB,oBAAoB;AACpB,uBAAuB;AACvB,sBAAsB;AACtB,qBAAqB;AACrB,2CAA2C;AAC3C,uBAAuB;AACvB,qBAAqB;AACrB,sBAAsB;AACtB,0BAA0B;AAC1B,qBAAqB;AACrB,wBAAwB;AACxB,sBAAsB;AACtB,0BAA0B;AAC1B,oBAAoB;AACpB,sBAAsB;AACtB,uBAAuB;AACvB,uBAAuB;AACvB,uBAAuB;AACvB,qBAAqB;AACrB,6BAA6B;AAC7B,yBAAyB;AACzB,0BAA0B;AAC1B,0BAA0B;AAC1B,sBAAsB;AACtB,wBAAwB;AACxB,wBAAwB;AACxB,oBAAoB;AACpB,qBAAqB;AACrB,gCAAgC;AAChC,0BAA0B;AAC1B,yBAAyB;AACzB,sBAAsB;AACtB,0BAA0B;AAC1B,uBAAuB;AACvB,sBAAsB;AACtB,wBAAwB;AACxB,0BAA0B;AAC1B,uBAAuB;AACvB,0BAA0B;AAC1B,+BAA+B;AAC/B,uBAAuB;AACvB,qBAAqB;AACrB,qBAAqB;AACrB,2BAA2B;AAC3B,2BAA2B;AAC3B,yBAAyB;AACzB,qBAAqB;AACrB,uBAAuB;AACvB,2BAA2B;AAC3B,+BAA+B;AAC/B,sBAAsB;AACtB,oBAAoB;AACpB,wBAAwB;AACxB,qBAAqB;AACrB,+BAA+B;AAC/B,sBAAsB;AACtB,gCAAgC;AAChC,wBAAwB;AACxB,oBAAoB;AACpB,2BAA2B;AAC3B,sBAAsB;AACtB,wBAAwB;AACxB,qBAAqB;AACrB,uBAAuB;AACvB,sBAAsB;AACtB,sBAAsB;AACtB,qCAAqC;AACrC,2BAA2B;AAC3B,gDAAgD;AAChD,qBAAqB;AACrB,0BAA0B;AAC1B,qCAAqC;AACrC,4BAA4B;AAC5B,uBAAuB;AACvB,sBAAsB;AACtB,0BAA0B;AAC1B,4BAA4B;AAC5B,yBAAyB;AACzB,wBAAwB;AACxB,wBAAwB;AACxB,+BAA+B;AAC/B,uBAAuB;AACvB,4BAA4B;AAC5B,2BAA2B;AAC3B,2BAA2B;AAC3B,qBAAqB;AACrB,yBAAyB;AACzB,qBAAqB;AACrB,wBAAwB;AACxB,sBAAsB;AACtB,2BAA2B;AAC3B,qBAAqB;AACrB,0BAA0B;AAC1B,wBAAwB;AACxB,wBAAwB;AACxB,2BAA2B;AAC3B,oBAAoB;AACpB,qBAAqB;AACrB,mCAAmC;AACnC,uBAAuB;AACvB,sBAAsB;AACtB,4BAA4B;AAC5B,sBAAsB;AACtB,sBAAsB;AACtB,uBAAuB;AACvB,oCAAoC;AACpC,8BAA8B;AAC9B,6BAA6B;AAC7B,uBAAuB;AACvB,0BAA0B;AAC1B,uBAAuB;AACvB,yBAAyB;AACzB,uBAAuB;AACvB,qBAAqB;AACrB,sBAAsB;AACtB,wBAAwB;AACxB,KAAK;AAEL,+FAA+F;AAC/F,MAAM,CAAC,MAAM,iBAAiB,GAA2C;IACvE,CAAC,IAAI,EAAE,eAAe,CAAC;CACxB,CAAC;AAEF,gFAAgF;AAChF,oEAAoE;AACpE,MAAM,CAAC,MAAM,kBAAkB,GAAkB;IAC/C,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ;CAC7E,CAAC;AACF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE;CAC/F,CAAC","sourcesContent":["import type { CSSProperties } from 'react';\n\nexport const appId = 'org.openedx.frontend.app.subscription.checkout';\nexport const subscriptionCheckoutRole = 'org.openedx.frontend.role.subscription.checkout';\n\n// --- Cart BI state machine ---------------------------------------------------\nexport const STATUS = {\n IN_CART: 'IN_CART',\n CONFIRM: 'CONFIRM',\n SANCTION_STARTED: 'SANCTION_STARTED',\n SANCTION_PASSED: 'SANCTION_PASSED',\n SANCTION_BLOCK: 'SANCTION_BLOCK',\n STRIPE_STARTED: 'STRIPE_STARTED',\n STRIPE_SUBSCRIBED: 'STRIPE_SUBSCRIBED',\n STRIPE_CONFIRMATION_REQUIRED: 'STRIPE_CONFIRMATION_REQUIRED',\n STRIPE_FAIL: 'STRIPE_FAIL',\n SUBSCRIPTION_CREATED: 'SUBSCRIPTION_CREATED',\n} as const;\n\nexport type Status = typeof STATUS[keyof typeof STATUS];\n\nexport type Phase = 'init' | 'ready' | 'processing' | 'threeds' | 'success' | 'blocked' | 'failed';\n\nexport const TERMINAL_STATES: Status[] = [\n STATUS.SUBSCRIPTION_CREATED,\n STATUS.SANCTION_BLOCK,\n STATUS.STRIPE_FAIL,\n];\n\nexport const STATUS_LABELS: Record<string, string> = {\n IN_CART: 'Cart created',\n CONFIRM: 'Order confirmed',\n SANCTION_STARTED: 'Checking sanctions…',\n SANCTION_PASSED: 'Sanctions passed — setting up your account…',\n SANCTION_BLOCK: 'Order blocked',\n STRIPE_STARTED: 'Setting up your subscription…',\n STRIPE_CONFIRMATION_REQUIRED: 'Card verification required',\n STRIPE_SUBSCRIBED: 'Card verified — finalizing…',\n STRIPE_FAIL: 'Payment failed',\n SUBSCRIPTION_CREATED: 'Subscription created',\n};\n\nexport const isTerminalStatus = (status: Status | null | undefined): boolean =>\n TERMINAL_STATES.includes(status as Status);\n\n/** UI phase derived from the raw bpStatus code + cart readiness. */\nexport function phaseFor(status: Status | null, ready: boolean): Phase {\n if (status === STATUS.SUBSCRIPTION_CREATED) return 'success';\n if (status === STATUS.SANCTION_BLOCK) return 'blocked';\n if (status === STATUS.STRIPE_FAIL) return 'failed';\n if (status && status !== STATUS.IN_CART) return 'processing';\n return ready ? 'ready' : 'init';\n}\n\n// --- Dev defaults (match the local test harness) -----------------------------\nexport const DEFAULTS = {\n apiUrl: '/api/graphql',\n confirmIntentUrl: '/api/stripe/confirm-pi',\n customerUid: '019d2bde-f769-743d-88f9-8bf0d1a7a002',\n salableUid: '019d2ce7-05bc-7dd6-b141-e32df9ac86c1',\n // Monthly Subscription template uid (not Annual)\n billingPlanUid: '019d2ce7-05bf-733c-ba56-0fcafafeb69b',\n};\n\nexport const LS_KEYS = { biId: 'twou.cartBiId', uid: 'twou.cartUid' };\n\n// ─── Checkout gate feature flags (dev controls) ───────────────────────────────\n// Set to false during development to bypass the country gate check.\n// Should be true in production. Subscriber access is enforced outside this app.\n\n/** When false, the country check is skipped — all countries can access checkout. */\nexport const GATE_CHECK_COUNTRY = true;\n\n/**\n * ISO 3166-1 alpha-2 country codes that are permitted to complete checkout.\n * Add or remove codes here to open or restrict access by country.\n * e.g. ['US', 'CA', 'GB'] to allow US, Canada, and UK.\n */\nexport const ALLOWED_CHECKOUT_COUNTRIES: readonly string[] = ['US', 'CA'];\n\n/**\n * ISO 3166-1 alpha-2 country codes that require the extra billing-consent checkbox.\n * Add or remove codes here to control which residents see the second checkbox.\n */\nexport const COUNTRIES_REQUIRING_EXTRA_CONFIRM: readonly string[] = ['GB', 'CA'];\n\n// export const COUNTRIES: readonly (readonly [string, string])[] = [\n// ['AF', 'Afghanistan'],\n// ['AL', 'Albania'],\n// ['DZ', 'Algeria'],\n// ['AD', 'Andorra'],\n// ['AO', 'Angola'],\n// ['AG', 'Antigua and Barbuda'],\n// ['AR', 'Argentina'],\n// ['AM', 'Armenia'],\n// ['AU', 'Australia'],\n// ['AT', 'Austria'],\n// ['AZ', 'Azerbaijan'],\n// ['BS', 'Bahamas'],\n// ['BH', 'Bahrain'],\n// ['BD', 'Bangladesh'],\n// ['BB', 'Barbados'],\n// ['BY', 'Belarus'],\n// ['BE', 'Belgium'],\n// ['BZ', 'Belize'],\n// ['BJ', 'Benin'],\n// ['BT', 'Bhutan'],\n// ['BO', 'Bolivia'],\n// ['BA', 'Bosnia and Herzegovina'],\n// ['BW', 'Botswana'],\n// ['BR', 'Brazil'],\n// ['BN', 'Brunei'],\n// ['BG', 'Bulgaria'],\n// ['BF', 'Burkina Faso'],\n// ['BI', 'Burundi'],\n// ['CV', 'Cabo Verde'],\n// ['KH', 'Cambodia'],\n// ['CM', 'Cameroon'],\n// ['CA', 'Canada'],\n// ['CF', 'Central African Republic'],\n// ['TD', 'Chad'],\n// ['CL', 'Chile'],\n// ['CN', 'China'],\n// ['CO', 'Colombia'],\n// ['KM', 'Comoros'],\n// ['CG', 'Congo (Congo-Brazzaville)'],\n// ['CR', 'Costa Rica'],\n// ['HR', 'Croatia'],\n// ['CU', 'Cuba'],\n// ['CY', 'Cyprus'],\n// ['CZ', 'Czechia (Czech Republic)'],\n// ['CD', 'Democratic Republic of the Congo'],\n// ['DK', 'Denmark'],\n// ['DJ', 'Djibouti'],\n// ['DM', 'Dominica'],\n// ['DO', 'Dominican Republic'],\n// ['EC', 'Ecuador'],\n// ['EG', 'Egypt'],\n// ['SV', 'El Salvador'],\n// ['GQ', 'Equatorial Guinea'],\n// ['ER', 'Eritrea'],\n// ['EE', 'Estonia'],\n// ['SZ', 'Eswatini'],\n// ['ET', 'Ethiopia'],\n// ['FJ', 'Fiji'],\n// ['FI', 'Finland'],\n// ['FR', 'France'],\n// ['GA', 'Gabon'],\n// ['GM', 'Gambia'],\n// ['GE', 'Georgia'],\n// ['DE', 'Germany'],\n// ['GH', 'Ghana'],\n// ['GR', 'Greece'],\n// ['GD', 'Grenada'],\n// ['GT', 'Guatemala'],\n// ['GN', 'Guinea'],\n// ['GW', 'Guinea-Bissau'],\n// ['GY', 'Guyana'],\n// ['HT', 'Haiti'],\n// ['VA', 'Holy See (Vatican City)'],\n// ['HN', 'Honduras'],\n// ['HU', 'Hungary'],\n// ['IS', 'Iceland'],\n// ['IN', 'India'],\n// ['ID', 'Indonesia'],\n// ['IR', 'Iran'],\n// ['IQ', 'Iraq'],\n// ['IE', 'Ireland'],\n// ['IL', 'Israel'],\n// ['IT', 'Italy'],\n// ['CI', \"Ivory Coast (Côte d'Ivoire)\"],\n// ['JM', 'Jamaica'],\n// ['JP', 'Japan'],\n// ['JO', 'Jordan'],\n// ['KZ', 'Kazakhstan'],\n// ['KE', 'Kenya'],\n// ['KI', 'Kiribati'],\n// ['KW', 'Kuwait'],\n// ['KG', 'Kyrgyzstan'],\n// ['LA', 'Laos'],\n// ['LV', 'Latvia'],\n// ['LB', 'Lebanon'],\n// ['LS', 'Lesotho'],\n// ['LR', 'Liberia'],\n// ['LY', 'Libya'],\n// ['LI', 'Liechtenstein'],\n// ['LT', 'Lithuania'],\n// ['LU', 'Luxembourg'],\n// ['MG', 'Madagascar'],\n// ['MW', 'Malawi'],\n// ['MY', 'Malaysia'],\n// ['MV', 'Maldives'],\n// ['ML', 'Mali'],\n// ['MT', 'Malta'],\n// ['MH', 'Marshall Islands'],\n// ['MR', 'Mauritania'],\n// ['MU', 'Mauritius'],\n// ['MX', 'Mexico'],\n// ['FM', 'Micronesia'],\n// ['MD', 'Moldova'],\n// ['MC', 'Monaco'],\n// ['MN', 'Mongolia'],\n// ['ME', 'Montenegro'],\n// ['MA', 'Morocco'],\n// ['MZ', 'Mozambique'],\n// ['MM', 'Myanmar (Burma)'],\n// ['NA', 'Namibia'],\n// ['NR', 'Nauru'],\n// ['NP', 'Nepal'],\n// ['NL', 'Netherlands'],\n// ['NZ', 'New Zealand'],\n// ['NI', 'Nicaragua'],\n// ['NE', 'Niger'],\n// ['NG', 'Nigeria'],\n// ['KP', 'North Korea'],\n// ['MK', 'North Macedonia'],\n// ['NO', 'Norway'],\n// ['OM', 'Oman'],\n// ['PK', 'Pakistan'],\n// ['PW', 'Palau'],\n// ['PS', 'Palestine State'],\n// ['PA', 'Panama'],\n// ['PG', 'Papua New Guinea'],\n// ['PY', 'Paraguay'],\n// ['PE', 'Peru'],\n// ['PH', 'Philippines'],\n// ['PL', 'Poland'],\n// ['PT', 'Portugal'],\n// ['QA', 'Qatar'],\n// ['RO', 'Romania'],\n// ['RU', 'Russia'],\n// ['RW', 'Rwanda'],\n// ['KN', 'Saint Kitts and Nevis'],\n// ['LC', 'Saint Lucia'],\n// ['VC', 'Saint Vincent and the Grenadines'],\n// ['WS', 'Samoa'],\n// ['SM', 'San Marino'],\n// ['ST', 'Sao Tome and Principe'],\n// ['SA', 'Saudi Arabia'],\n// ['SN', 'Senegal'],\n// ['RS', 'Serbia'],\n// ['SC', 'Seychelles'],\n// ['SL', 'Sierra Leone'],\n// ['SG', 'Singapore'],\n// ['SK', 'Slovakia'],\n// ['SI', 'Slovenia'],\n// ['SB', 'Solomon Islands'],\n// ['SO', 'Somalia'],\n// ['ZA', 'South Africa'],\n// ['KR', 'South Korea'],\n// ['SS', 'South Sudan'],\n// ['ES', 'Spain'],\n// ['LK', 'Sri Lanka'],\n// ['SD', 'Sudan'],\n// ['SR', 'Suriname'],\n// ['SE', 'Sweden'],\n// ['CH', 'Switzerland'],\n// ['SY', 'Syria'],\n// ['TJ', 'Tajikistan'],\n// ['TZ', 'Tanzania'],\n// ['TH', 'Thailand'],\n// ['TL', 'Timor-Leste'],\n// ['TG', 'Togo'],\n// ['TO', 'Tonga'],\n// ['TT', 'Trinidad and Tobago'],\n// ['TN', 'Tunisia'],\n// ['TR', 'Turkey'],\n// ['TM', 'Turkmenistan'],\n// ['TV', 'Tuvalu'],\n// ['UG', 'Uganda'],\n// ['UA', 'Ukraine'],\n// ['AE', 'United Arab Emirates'],\n// ['GB', 'United Kingdom'],\n// ['US', 'United States'],\n// ['UY', 'Uruguay'],\n// ['UZ', 'Uzbekistan'],\n// ['VU', 'Vanuatu'],\n// ['VE', 'Venezuela'],\n// ['VN', 'Vietnam'],\n// ['YE', 'Yemen'],\n// ['ZM', 'Zambia'],\n// ['ZW', 'Zimbabwe'],\n// ];\n\n/** Billing country dropdown options. Swap back to COUNTRIES when expanding internationally. */\nexport const BILLING_COUNTRIES: readonly (readonly [string, string])[] = [\n ['US', 'United States'],\n];\n\n// --- Stripe Element presentation ---------------------------------------------\n// A div that hosts a Stripe Element but reads like a Paragon input.\nexport const STRIPE_FIELD_STYLE: CSSProperties = {\n height: 'auto', minHeight: '2.875rem', display: 'flex', alignItems: 'center',\n};\nexport const STRIPE_ELEMENT_OPTS = {\n style: { base: { fontSize: '16px', color: '#1a1a1a', '::placeholder': { color: '#8f8f8f' } } },\n};\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CSSProperties } from 'react';\n\nexport const appId = 'org.openedx.frontend.app.subscription.checkout';\nexport const subscriptionCheckoutRole = 'org.openedx.frontend.role.subscription.checkout';\n\n// --- Cart BI state machine ---------------------------------------------------\nexport const STATUS = {\n IN_CART: 'IN_CART',\n CONFIRM: 'CONFIRM',\n SANCTION_STARTED: 'SANCTION_STARTED',\n SANCTION_PASSED: 'SANCTION_PASSED',\n SANCTION_BLOCK: 'SANCTION_BLOCK',\n STRIPE_STARTED: 'STRIPE_STARTED',\n STRIPE_SUBSCRIBED: 'STRIPE_SUBSCRIBED',\n STRIPE_CONFIRMATION_REQUIRED: 'STRIPE_CONFIRMATION_REQUIRED',\n STRIPE_FAIL: 'STRIPE_FAIL',\n SUBSCRIPTION_CREATED: 'SUBSCRIPTION_CREATED',\n} as const;\n\nexport type Status = typeof STATUS[keyof typeof STATUS];\n\nexport type Phase = 'init' | 'ready' | 'processing' | 'threeds' | 'success' | 'blocked' | 'failed';\n\nexport const TERMINAL_STATES: Status[] = [\n STATUS.SUBSCRIPTION_CREATED,\n STATUS.SANCTION_BLOCK,\n STATUS.STRIPE_FAIL,\n];\n\nexport const STATUS_LABELS: Record<string, string> = {\n IN_CART: 'Cart created',\n CONFIRM: 'Order confirmed',\n SANCTION_STARTED: 'Checking sanctions…',\n SANCTION_PASSED: 'Sanctions passed — setting up your account…',\n SANCTION_BLOCK: 'Order blocked',\n STRIPE_STARTED: 'Setting up your subscription…',\n STRIPE_CONFIRMATION_REQUIRED: 'Card verification required',\n STRIPE_SUBSCRIBED: 'Card verified — finalizing…',\n STRIPE_FAIL: 'Payment failed',\n SUBSCRIPTION_CREATED: 'Subscription created',\n};\n\nexport const isTerminalStatus = (status: Status | null | undefined): boolean =>\n TERMINAL_STATES.includes(status as Status);\n\n/** UI phase derived from the raw bpStatus code + cart readiness. */\nexport function phaseFor(status: Status | null, ready: boolean): Phase {\n if (status === STATUS.SUBSCRIPTION_CREATED) return 'success';\n if (status === STATUS.SANCTION_BLOCK) return 'blocked';\n if (status === STATUS.STRIPE_FAIL) return 'failed';\n if (status && status !== STATUS.IN_CART) return 'processing';\n return ready ? 'ready' : 'init';\n}\n\n// --- Dev defaults (match the local test harness) -----------------------------\nexport const DEFAULTS = {\n apiUrl: '/api/graphql',\n confirmIntentUrl: '/api/stripe/confirm-pi',\n customerUid: '019d2bde-f769-743d-88f9-8bf0d1a7a002',\n salableUid: '019d2ce7-05bc-7dd6-b141-e32df9ac86c1',\n // Monthly Subscription template uid (not Annual)\n billingPlanUid: '019d2ce7-05bf-733c-ba56-0fcafafeb69b',\n};\n\nexport const LS_KEYS = { biId: 'twou.cartBiId', uid: 'twou.cartUid' };\n\n// ─── Checkout gate feature flags (dev controls) ───────────────────────────────\n// Set to false during development to bypass the country gate check.\n// Should be true in production. Subscriber access is enforced outside this app.\n\n/** When false, the country check is skipped — all countries can access checkout. */\nexport const GATE_CHECK_COUNTRY = true;\n\n/**\n * ISO 3166-1 alpha-2 country codes that are permitted to complete checkout.\n * Add or remove codes here to open or restrict access by country.\n */\nexport const ALLOWED_CHECKOUT_COUNTRIES: readonly string[] = ['GB', 'AU', 'CA', 'US'];\n\n/**\n * ISO 3166-1 alpha-2 country codes that require the extra billing-consent checkbox.\n * Add or remove codes here to control which selected billing countries show it.\n */\nexport const COUNTRIES_REQUIRING_EXTRA_CONFIRM: readonly string[] = ['GB', 'CA'];\n\n// export const COUNTRIES: readonly (readonly [string, string])[] = [\n// ['AF', 'Afghanistan'],\n// ['AL', 'Albania'],\n// ['DZ', 'Algeria'],\n// ['AD', 'Andorra'],\n// ['AO', 'Angola'],\n// ['AG', 'Antigua and Barbuda'],\n// ['AR', 'Argentina'],\n// ['AM', 'Armenia'],\n// ['AU', 'Australia'],\n// ['AT', 'Austria'],\n// ['AZ', 'Azerbaijan'],\n// ['BS', 'Bahamas'],\n// ['BH', 'Bahrain'],\n// ['BD', 'Bangladesh'],\n// ['BB', 'Barbados'],\n// ['BY', 'Belarus'],\n// ['BE', 'Belgium'],\n// ['BZ', 'Belize'],\n// ['BJ', 'Benin'],\n// ['BT', 'Bhutan'],\n// ['BO', 'Bolivia'],\n// ['BA', 'Bosnia and Herzegovina'],\n// ['BW', 'Botswana'],\n// ['BR', 'Brazil'],\n// ['BN', 'Brunei'],\n// ['BG', 'Bulgaria'],\n// ['BF', 'Burkina Faso'],\n// ['BI', 'Burundi'],\n// ['CV', 'Cabo Verde'],\n// ['KH', 'Cambodia'],\n// ['CM', 'Cameroon'],\n// ['CA', 'Canada'],\n// ['CF', 'Central African Republic'],\n// ['TD', 'Chad'],\n// ['CL', 'Chile'],\n// ['CN', 'China'],\n// ['CO', 'Colombia'],\n// ['KM', 'Comoros'],\n// ['CG', 'Congo (Congo-Brazzaville)'],\n// ['CR', 'Costa Rica'],\n// ['HR', 'Croatia'],\n// ['CU', 'Cuba'],\n// ['CY', 'Cyprus'],\n// ['CZ', 'Czechia (Czech Republic)'],\n// ['CD', 'Democratic Republic of the Congo'],\n// ['DK', 'Denmark'],\n// ['DJ', 'Djibouti'],\n// ['DM', 'Dominica'],\n// ['DO', 'Dominican Republic'],\n// ['EC', 'Ecuador'],\n// ['EG', 'Egypt'],\n// ['SV', 'El Salvador'],\n// ['GQ', 'Equatorial Guinea'],\n// ['ER', 'Eritrea'],\n// ['EE', 'Estonia'],\n// ['SZ', 'Eswatini'],\n// ['ET', 'Ethiopia'],\n// ['FJ', 'Fiji'],\n// ['FI', 'Finland'],\n// ['FR', 'France'],\n// ['GA', 'Gabon'],\n// ['GM', 'Gambia'],\n// ['GE', 'Georgia'],\n// ['DE', 'Germany'],\n// ['GH', 'Ghana'],\n// ['GR', 'Greece'],\n// ['GD', 'Grenada'],\n// ['GT', 'Guatemala'],\n// ['GN', 'Guinea'],\n// ['GW', 'Guinea-Bissau'],\n// ['GY', 'Guyana'],\n// ['HT', 'Haiti'],\n// ['VA', 'Holy See (Vatican City)'],\n// ['HN', 'Honduras'],\n// ['HU', 'Hungary'],\n// ['IS', 'Iceland'],\n// ['ID', 'Indonesia'],\n// ['IR', 'Iran'],\n// ['IQ', 'Iraq'],\n// ['IE', 'Ireland'],\n// ['IL', 'Israel'],\n// ['IT', 'Italy'],\n// ['CI', \"Ivory Coast (Côte d'Ivoire)\"],\n// ['JM', 'Jamaica'],\n// ['JP', 'Japan'],\n// ['JO', 'Jordan'],\n// ['KZ', 'Kazakhstan'],\n// ['KE', 'Kenya'],\n// ['KI', 'Kiribati'],\n// ['KW', 'Kuwait'],\n// ['KG', 'Kyrgyzstan'],\n// ['LA', 'Laos'],\n// ['LV', 'Latvia'],\n// ['LB', 'Lebanon'],\n// ['LS', 'Lesotho'],\n// ['LR', 'Liberia'],\n// ['LY', 'Libya'],\n// ['LI', 'Liechtenstein'],\n// ['LT', 'Lithuania'],\n// ['LU', 'Luxembourg'],\n// ['MG', 'Madagascar'],\n// ['MW', 'Malawi'],\n// ['MY', 'Malaysia'],\n// ['MV', 'Maldives'],\n// ['ML', 'Mali'],\n// ['MT', 'Malta'],\n// ['MH', 'Marshall Islands'],\n// ['MR', 'Mauritania'],\n// ['MU', 'Mauritius'],\n// ['MX', 'Mexico'],\n// ['FM', 'Micronesia'],\n// ['MD', 'Moldova'],\n// ['MC', 'Monaco'],\n// ['MN', 'Mongolia'],\n// ['ME', 'Montenegro'],\n// ['MA', 'Morocco'],\n// ['MZ', 'Mozambique'],\n// ['MM', 'Myanmar (Burma)'],\n// ['NA', 'Namibia'],\n// ['NR', 'Nauru'],\n// ['NP', 'Nepal'],\n// ['NL', 'Netherlands'],\n// ['NZ', 'New Zealand'],\n// ['NI', 'Nicaragua'],\n// ['NE', 'Niger'],\n// ['NG', 'Nigeria'],\n// ['KP', 'North Korea'],\n// ['MK', 'North Macedonia'],\n// ['NO', 'Norway'],\n// ['OM', 'Oman'],\n// ['PK', 'Pakistan'],\n// ['PW', 'Palau'],\n// ['PS', 'Palestine State'],\n// ['PA', 'Panama'],\n// ['PG', 'Papua New Guinea'],\n// ['PY', 'Paraguay'],\n// ['PE', 'Peru'],\n// ['PH', 'Philippines'],\n// ['PL', 'Poland'],\n// ['PT', 'Portugal'],\n// ['QA', 'Qatar'],\n// ['RO', 'Romania'],\n// ['RU', 'Russia'],\n// ['RW', 'Rwanda'],\n// ['KN', 'Saint Kitts and Nevis'],\n// ['LC', 'Saint Lucia'],\n// ['VC', 'Saint Vincent and the Grenadines'],\n// ['WS', 'Samoa'],\n// ['SM', 'San Marino'],\n// ['ST', 'Sao Tome and Principe'],\n// ['SA', 'Saudi Arabia'],\n// ['SN', 'Senegal'],\n// ['RS', 'Serbia'],\n// ['SC', 'Seychelles'],\n// ['SL', 'Sierra Leone'],\n// ['SG', 'Singapore'],\n// ['SK', 'Slovakia'],\n// ['SI', 'Slovenia'],\n// ['SB', 'Solomon Islands'],\n// ['SO', 'Somalia'],\n// ['ZA', 'South Africa'],\n// ['KR', 'South Korea'],\n// ['SS', 'South Sudan'],\n// ['ES', 'Spain'],\n// ['LK', 'Sri Lanka'],\n// ['SD', 'Sudan'],\n// ['SR', 'Suriname'],\n// ['SE', 'Sweden'],\n// ['CH', 'Switzerland'],\n// ['SY', 'Syria'],\n// ['TJ', 'Tajikistan'],\n// ['TZ', 'Tanzania'],\n// ['TH', 'Thailand'],\n// ['TL', 'Timor-Leste'],\n// ['TG', 'Togo'],\n// ['TO', 'Tonga'],\n// ['TT', 'Trinidad and Tobago'],\n// ['TN', 'Tunisia'],\n// ['TR', 'Turkey'],\n// ['TM', 'Turkmenistan'],\n// ['TV', 'Tuvalu'],\n// ['UG', 'Uganda'],\n// ['UA', 'Ukraine'],\n// ['AE', 'United Arab Emirates'],\n// ['GB', 'United Kingdom'],\n// ['US', 'United States'],\n// ['UY', 'Uruguay'],\n// ['UZ', 'Uzbekistan'],\n// ['VU', 'Vanuatu'],\n// ['VE', 'Venezuela'],\n// ['VN', 'Vietnam'],\n// ['YE', 'Yemen'],\n// ['ZM', 'Zambia'],\n// ['ZW', 'Zimbabwe'],\n// ];\n\n/** Billing country dropdown options for the supported countries in this checkout flow. */\nexport const BILLING_COUNTRIES: readonly (readonly [string, string])[] = [\n ['GB', 'United Kingdom'],\n ['AU', 'Australia'],\n ['CA', 'Canada'],\n ['US', 'United States'],\n];\n\n// --- Stripe Element presentation ---------------------------------------------\n// A div that hosts a Stripe Element but reads like a Paragon input.\nexport const STRIPE_FIELD_STYLE: CSSProperties = {\n height: 'auto', minHeight: '2.875rem', display: 'flex', alignItems: 'center',\n};\nexport const STRIPE_ELEMENT_OPTS = {\n style: { base: { fontSize: '16px', color: '#1a1a1a', '::placeholder': { color: '#8f8f8f' } } },\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { Ref } from 'react';
2
2
  import type { BillingCycle } from '../../types';
3
- import type { Status, Phase, BillingInfo, BillingPlan, CheckoutConsent, PaymentMethod } from '../../types';
3
+ import type { Status, Phase, BillingInfo, BillingPlan, CheckoutConsent, SupportedPaymentMethod } from '../../types';
4
4
  export interface UseCheckoutOptions {
5
5
  apiUrl?: string;
6
6
  edxSessionUrl?: string;
@@ -42,7 +42,7 @@ export interface UseCheckoutResult {
42
42
  processingSubscription: boolean;
43
43
  /** True when Stripe sent the learner back with ?cart_bi_id=. */
44
44
  returningFromStripe: boolean;
45
- placeOrder: (consent: CheckoutConsent, paymentMethod?: PaymentMethod) => void;
45
+ placeOrder: (consent: CheckoutConsent, paymentMethod?: SupportedPaymentMethod) => void;
46
46
  /** Billing plans fetched on mount — includes prices for display in CartSummary. */
47
47
  billingPlans: BillingPlan[];
48
48
  /** Live active subscriber count for display in CartSummary. */
@@ -11,7 +11,7 @@ import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
11
11
  import { createCheckoutClient } from '../../utils/checkout';
12
12
  import { getPlanFromUrl, writePlanQueryParam } from '../../utils/planQuery';
13
13
  import { getReturnedCartBiIdFromUrl, loadStripe } from '../../utils/stripe';
14
- import { STATUS, STATUS_LABELS, STRIPE_ELEMENT_OPTS, phaseFor, DEFAULTS, } from '../../constants';
14
+ import { STATUS, STATUS_LABELS, STRIPE_ELEMENT_OPTS, phaseFor, DEFAULTS, BILLING_COUNTRIES, } from '../../constants';
15
15
  import { useCartStatusQuery, useSubscriptionIdQuery, useBillingPlansQuery, useActiveSubscriptionsQuery, useViaxSessionQuery, useCourseDetailQuery, } from './useCheckoutQueries';
16
16
  import { useCheckoutMutations } from './useCheckoutMutations';
17
17
  /**
@@ -36,6 +36,13 @@ function getCourseRunKeyFromUrl() {
36
36
  const redirectBrowser = (url) => {
37
37
  window.location.assign(url);
38
38
  };
39
+ const getInitialBillingCountry = (userCountry) => {
40
+ const normalized = userCountry === null || userCountry === void 0 ? void 0 : userCountry.trim().toUpperCase();
41
+ if (normalized && BILLING_COUNTRIES.some(([countryCode]) => countryCode === normalized)) {
42
+ return normalized;
43
+ }
44
+ return 'US';
45
+ };
39
46
  export default function useCheckout(options = {}) {
40
47
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
41
48
  const { apiUrl = DEFAULTS.apiUrl, edxSessionUrl, stripePublishableKey, onComplete, userCountry = null, courseRunKey: courseRunKeyProp, redirectToUrl = redirectBrowser, } = options;
@@ -67,7 +74,7 @@ export default function useCheckout(options = {}) {
67
74
  const [error, setError] = useState('');
68
75
  const [cardError, setCardError] = useState('');
69
76
  const [billing, setBilling] = useState({
70
- firstName: '', lastName: '', city: '', zip: '', country: 'US', line1: '', state: '',
77
+ firstName: '', lastName: '', city: '', zip: '', country: getInitialBillingCountry(userCountry), line1: '', state: '',
71
78
  });
72
79
  const [selectedCycle, setSelectedCycle] = useState(getPlanFromUrl);
73
80
  // Set when Stripe returns from a 3DS challenge; cleared once a new attempt starts.
@@ -1 +1 @@
1
- {"version":3,"file":"useCheckout.js","sourceRoot":"","sources":["../../../src/data/hooks/useCheckout.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback, useEffect, useMemo, useRef, useState,\n} from 'react';\nimport type { Ref } from 'react';\nimport type { BillingCycle } from '../../types';\nimport { createCheckoutClient } from '../../utils/checkout';\nimport { getPlanFromUrl, writePlanQueryParam } from '../../utils/planQuery';\nimport { getReturnedCartBiIdFromUrl, loadStripe } from '../../utils/stripe';\nimport {\n STATUS, STATUS_LABELS, STRIPE_ELEMENT_OPTS, phaseFor, DEFAULTS,\n} from '../../constants';\nimport type {\n Status, Phase, Cart, BillingInfo, CheckoutClient, StripeLike, StripeElementLike,\n StripeElementsLike, BillingPlan, CheckoutConsent, PaymentMethod,\n} from '../../types';\nimport {\n useCartStatusQuery, useSubscriptionIdQuery, useBillingPlansQuery,\n useActiveSubscriptionsQuery, useViaxSessionQuery, useCourseDetailQuery,\n} from './useCheckoutQueries';\nimport type { EdxSessionResult } from '../../utils/provision';\nimport { useCheckoutMutations } from './useCheckoutMutations';\n\n/**\n * Read ?course_run_key= from the current URL.\n * Avoid URLSearchParams — it treats bare `+` as a space, which would turn\n * HarvardX+CS50+X into \"HarvardX CS50 X\". decodeURIComponent keeps `+` intact.\n */\nfunction getCourseRunKeyFromUrl(): string | null {\n if (typeof window === 'undefined') return null;\n const match = /[?&]course_run_key=([^&]*)/.exec(window.location.search);\n if (!match) return null;\n try {\n // Preserve literal `+` (treat as %2B) then decode %XX sequences.\n return decodeURIComponent(match[1].replace(/\\+/g, '%2B')).trim() || null;\n } catch {\n return match[1].trim() || null;\n }\n}\n\nconst redirectBrowser = (url: string): void => {\n window.location.assign(url);\n};\n\nexport interface UseCheckoutOptions {\n apiUrl?: string,\n edxSessionUrl?: string,\n stripePublishableKey?: string,\n onComplete?: (subscriptionBiId: string | null) => void,\n /** Country code resolved by CheckoutGate — used to show/hide the UK/CA extra checkbox. */\n userCountry?: string | null,\n /**\n * Course run key from the URL (e.g. course-v1:HarvardX+CS50+X).\n * When omitted, read from ?course_run_key=.\n */\n courseRunKey?: string | null,\n /** Override only for tests; production performs a full-page browser redirect. */\n redirectToUrl?: (url: string) => void,\n}\n\nexport interface UseCheckoutResult {\n phase: Phase,\n status: Status | null,\n statusLabel: string,\n stripeReady: boolean,\n /** True once the Stripe card Element iframe is fully initialised and interactive. */\n cardReady: boolean,\n notConfigured: boolean,\n showBanner: boolean,\n dismissBanner: () => void,\n error: string,\n clearError: () => void,\n cardError: string,\n lastComment: string,\n /** Full subscription details including card last 4 — available after SUBSCRIPTION_CREATED. */\n subscriptionDetails: import('../../types').SubscriptionDetails | null,\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n submitting: boolean,\n /** True from Place order click until a terminal status is reached. */\n processingSubscription: boolean,\n /** True when Stripe sent the learner back with ?cart_bi_id=. */\n returningFromStripe: boolean,\n placeOrder: (consent: CheckoutConsent, paymentMethod?: PaymentMethod) => void,\n /** Billing plans fetched on mount — includes prices for display in CartSummary. */\n billingPlans: BillingPlan[],\n /** Live active subscriber count for display in CartSummary. */\n activeSubscriberCount: number | null,\n /** Currently selected billing cycle. */\n selectedCycle: BillingCycle,\n /** Switch between monthly and annual billing. */\n setCycle: (cycle: BillingCycle) => void,\n /** True once GET /edx-session has returned and the viax token is set. */\n sessionReady: boolean,\n /** ISO 3166-1 alpha-2 country code — passed in from CheckoutGate for the UK/CA checkbox. */\n userCountry: string | null,\n /** Course details when arrived via ?course_run_key=; null for standard checkout. */\n course: import('../../types').CourseDetail | null,\n}\n\nexport default function useCheckout(options: UseCheckoutOptions = {}): UseCheckoutResult {\n const {\n apiUrl = DEFAULTS.apiUrl,\n edxSessionUrl,\n stripePublishableKey,\n onComplete,\n userCountry = null,\n courseRunKey: courseRunKeyProp,\n redirectToUrl = redirectBrowser,\n } = options;\n\n const courseRunKey = useMemo(\n () => courseRunKeyProp ?? getCourseRunKeyFromUrl(),\n [courseRunKeyProp],\n );\n\n const client = useMemo<CheckoutClient | null>(() => {\n if (!apiUrl) return null;\n return createCheckoutClient({ apiUrl });\n }, [apiUrl]);\n\n const notConfigured = !client || !stripePublishableKey || !edxSessionUrl;\n\n // Exchange edX session for viax token on page load.\n const sessionQuery = useViaxSessionQuery(notConfigured ? null : edxSessionUrl!);\n const sessionReady = !!sessionQuery.data;\n\n useEffect(() => {\n if (sessionQuery.data && client) {\n client.setToken(sessionQuery.data.viaxToken);\n }\n }, [sessionQuery.data, client]);\n\n // Fetch billing plans, subscriber count, and optional course once the viax session is ready.\n const billingPlansQuery = useBillingPlansQuery(client, sessionReady);\n const activeSubscriptionsQuery = useActiveSubscriptionsQuery(client, sessionReady);\n const courseDetailQuery = useCourseDetailQuery(client, sessionReady, courseRunKey);\n\n // --- state ---\n const [showBanner, setShowBanner] = useState(true);\n const [cart, setCart] = useState<Cart | null>(null);\n const [stripe, setStripe] = useState<StripeLike | null>(null);\n const [stripeReady, setStripeReady] = useState(false);\n const [cardReady, setCardReady] = useState(false);\n const [error, setError] = useState('');\n const [cardError, setCardError] = useState('');\n const [billing, setBilling] = useState<BillingInfo>({\n firstName: '', lastName: '', city: '', zip: '', country: 'US', line1: '', state: '',\n });\n const [selectedCycle, setSelectedCycle] = useState<BillingCycle>(getPlanFromUrl);\n // Set when Stripe returns from a 3DS challenge; cleared once a new attempt starts.\n const [returnedCartBiId, setReturnedCartBiId] = useState<string | null>(getReturnedCartBiIdFromUrl);\n const [processingSubscription, setProcessingSubscription] = useState(\n () => getReturnedCartBiIdFromUrl() !== null,\n );\n\n const setCycle = useCallback((cycle: BillingCycle) => {\n setSelectedCycle(cycle);\n writePlanQueryParam(cycle);\n }, []);\n\n useEffect(() => {\n if (sessionQuery.error) {\n setError(sessionQuery.error.message);\n }\n }, [sessionQuery.error]);\n\n const setField = useCallback(\n (field: keyof BillingInfo, value: string) => setBilling((p: BillingInfo) => ({ ...p, [field]: value })),\n [],\n );\n\n // --- refs ---\n // Stripe instances — written inside useEffect and mutations.\n const stripeInstanceRef = useRef<StripeLike | null>(null);\n const cardNumberElementRef = useRef<StripeElementLike | null>(null);\n const cardExpiryElementRef = useRef<StripeElementLike | null>(null);\n const cardCvcElementRef = useRef<StripeElementLike | null>(null);\n const elementsRef = useRef<StripeElementsLike | null>(null);\n // DOM mount targets — callback refs so we remount when hosts leave and return.\n const numberMountNodeRef = useRef<HTMLDivElement | null>(null);\n const expiryMountNodeRef = useRef<HTMLDivElement | null>(null);\n const cvcMountNodeRef = useRef<HTMLDivElement | null>(null);\n const [cardHostsEpoch, setCardHostsEpoch] = useState(0);\n\n const assignCardHost = useCallback((\n store: { current: HTMLDivElement | null },\n node: HTMLDivElement | null,\n ) => {\n store.current = node;\n if (\n numberMountNodeRef.current\n && expiryMountNodeRef.current\n && cvcMountNodeRef.current\n ) {\n setCardHostsEpoch((n) => n + 1);\n return;\n }\n // Hosts are leaving the DOM — detach so Stripe is not bound to dead nodes.\n cardNumberElementRef.current?.unmount?.();\n cardExpiryElementRef.current?.unmount?.();\n cardCvcElementRef.current?.unmount?.();\n }, []);\n\n const numberMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(numberMountNodeRef, node);\n }, [assignCardHost]);\n const expiryMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(expiryMountNodeRef, node);\n }, [assignCardHost]);\n const cvcMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(cvcMountNodeRef, node);\n }, [assignCardHost]);\n const mountedRef = useRef(true);\n const completedRef = useRef(false);\n const redirectedUrlRef = useRef<string | null>(null);\n const sessionRef = useRef<EdxSessionResult | null>(null);\n\n useEffect(() => {\n sessionRef.current = sessionQuery.data ?? null;\n }, [sessionQuery.data]);\n\n // Mirror state into refs so mutations can read current values without stale closures.\n const cartRef = useRef<Cart | null>(null);\n const billingRef = useRef<BillingInfo>(billing);\n const selectedCycleRef = useRef<BillingCycle>(selectedCycle);\n\n useEffect(() => {\n cartRef.current = cart;\n }, [cart]);\n useEffect(() => {\n billingRef.current = billing;\n }, [billing]);\n useEffect(() => {\n selectedCycleRef.current = selectedCycle;\n }, [selectedCycle]);\n useEffect(() => {\n stripeInstanceRef.current = stripe;\n }, [stripe]);\n\n // --- server state ---\n // Poll the cart created in this session, or the one Stripe just returned\n // from. The returned cart waits for the viax session so the status request\n // carries a valid token.\n const cartBiId = cart?.biId ?? (sessionReady ? returnedCartBiId : null);\n const statusQuery = useCartStatusQuery(client, cartBiId);\n const status: Status | null = statusQuery.data?.status ?? null;\n const lastComment = statusQuery.data?.lastComment ?? '';\n\n // Phase is 'ready' until a cart exists, then driven by bpStatus.\n const phase: Phase = cartBiId ? phaseFor(status, status === STATUS.IN_CART) : 'ready';\n const subscriptionIdQuery = useSubscriptionIdQuery(\n client, cartBiId, status === STATUS.SUBSCRIPTION_CREATED,\n );\n\n // --- mutations ---\n const { placeOrder: placeMutation } = useCheckoutMutations({\n client,\n sessionRef,\n stripeRef: stripeInstanceRef,\n cardNumberElRef: cardNumberElementRef,\n billingRef,\n selectedCycleRef,\n setError: (msg: string) => {\n setProcessingSubscription(false);\n setError(msg);\n },\n setCardError: (msg: string) => {\n setProcessingSubscription(false);\n setCardError(msg);\n },\n onCartCreated: (created: Cart) => {\n // Sync the ref immediately so any same-tick readers see the cart\n // before the setCart → useEffect mirror runs.\n cartRef.current = created;\n if (mountedRef.current) setCart(created);\n },\n });\n\n // --- load Stripe.js on mount ---\n useEffect(() => {\n mountedRef.current = true;\n if (!stripePublishableKey) return undefined;\n\n (async () => {\n try {\n const instance = await loadStripe(stripePublishableKey);\n if (mountedRef.current) {\n setStripe(instance);\n setStripeReady(true);\n }\n } catch (e: unknown) {\n if (mountedRef.current) setError((e as Error).message);\n }\n })();\n\n return () => {\n mountedRef.current = false;\n };\n }, [stripePublishableKey]);\n\n // --- mount Stripe Elements once Stripe is loaded; remount if hosts return ---\n useEffect(() => {\n if (!stripe) return;\n const numberNode = numberMountNodeRef.current;\n const expiryNode = expiryMountNodeRef.current;\n const cvcNode = cvcMountNodeRef.current;\n if (!numberNode || !expiryNode || !cvcNode) return;\n\n if (cardNumberElementRef.current && cardExpiryElementRef.current && cardCvcElementRef.current) {\n try {\n cardNumberElementRef.current.unmount?.();\n cardExpiryElementRef.current.unmount?.();\n cardCvcElementRef.current.unmount?.();\n cardNumberElementRef.current.mount(numberNode);\n cardExpiryElementRef.current.mount(expiryNode);\n cardCvcElementRef.current.mount(cvcNode);\n return;\n } catch {\n // Element is bound to a destroyed host — create a fresh Elements group.\n cardNumberElementRef.current = null;\n cardExpiryElementRef.current = null;\n cardCvcElementRef.current = null;\n elementsRef.current = null;\n }\n }\n\n setCardReady(false);\n\n const elements = stripe.elements();\n elementsRef.current = elements;\n\n const number = elements.create('cardNumber', { ...STRIPE_ELEMENT_OPTS, showIcon: true });\n const expiry = elements.create('cardExpiry', STRIPE_ELEMENT_OPTS);\n const cvc = elements.create('cardCvc', STRIPE_ELEMENT_OPTS);\n\n number.mount(numberNode);\n expiry.mount(expiryNode);\n cvc.mount(cvcNode);\n\n number.on('ready', () => {\n if (mountedRef.current) setCardReady(true);\n });\n number.on('change', (e: { error?: { message?: string } }) => {\n if (mountedRef.current) setCardError(e.error?.message || '');\n });\n\n cardNumberElementRef.current = number;\n cardExpiryElementRef.current = expiry;\n cardCvcElementRef.current = cvc;\n }, [stripe, cardHostsEpoch]);\n\n // --- on success ---\n useEffect(() => {\n if (status !== STATUS.SUBSCRIPTION_CREATED || completedRef.current) return;\n completedRef.current = true;\n if (onComplete) onComplete(subscriptionIdQuery.data?.biId ?? null);\n }, [status, subscriptionIdQuery.data, onComplete]);\n\n // Stripe and PayPal both authenticate the buyer on a hosted page before\n // returning the browser to checkout, so this must be a full-page\n // navigation (not an API request) for either flow.\n useEffect(() => {\n const redirectUrl = statusQuery.data?.stripeConfirmationRedirectUrl\n || statusQuery.data?.paypalApprovalUrl;\n if (\n status !== STATUS.STRIPE_CONFIRMATION_REQUIRED\n || !redirectUrl\n || redirectedUrlRef.current === redirectUrl\n ) return;\n\n redirectedUrlRef.current = redirectUrl;\n redirectToUrl(redirectUrl);\n }, [\n status,\n statusQuery.data?.stripeConfirmationRedirectUrl,\n statusQuery.data?.paypalApprovalUrl,\n redirectToUrl,\n ]);\n\n // --- actions ---\n const placeOrder = useCallback((consent: CheckoutConsent, paymentMethod: PaymentMethod = 'card') => {\n setError('');\n setCardError('');\n if (phase === 'failed') setCart(null);\n // Each attempt creates its own cart, so stop reporting on the returned one.\n setReturnedCartBiId(null);\n setProcessingSubscription(true);\n placeMutation.mutate({ consent, paymentMethod });\n }, [placeMutation, phase]);\n\n // Turn off processingSubscription once we reach a terminal status.\n useEffect(() => {\n if (!status) return;\n const terminalStatuses: Status[] = [\n STATUS.SUBSCRIPTION_CREATED,\n STATUS.STRIPE_FAIL,\n STATUS.SANCTION_BLOCK,\n ];\n if (terminalStatuses.includes(status)) {\n setProcessingSubscription(false);\n }\n }, [status]);\n\n return {\n phase,\n status,\n statusLabel: (status && STATUS_LABELS[status]) || 'Processing your order…',\n stripeReady,\n cardReady,\n notConfigured,\n showBanner,\n dismissBanner: () => setShowBanner(false),\n error,\n clearError: () => setError(''),\n cardError,\n lastComment,\n subscriptionDetails: subscriptionIdQuery.data ?? null,\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n submitting: placeMutation.isPending,\n processingSubscription,\n returningFromStripe: returnedCartBiId !== null,\n placeOrder,\n billingPlans: billingPlansQuery.data?.plans ?? [],\n activeSubscriberCount: activeSubscriptionsQuery.data?.active ?? null,\n selectedCycle,\n setCycle,\n sessionReady,\n userCountry,\n course: courseDetailQuery.data ?? null,\n };\n}\n"]}
1
+ {"version":3,"file":"useCheckout.js","sourceRoot":"","sources":["../../../src/data/hooks/useCheckout.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback, useEffect, useMemo, useRef, useState,\n} from 'react';\nimport type { Ref } from 'react';\nimport type { BillingCycle } from '../../types';\nimport { createCheckoutClient } from '../../utils/checkout';\nimport { getPlanFromUrl, writePlanQueryParam } from '../../utils/planQuery';\nimport { getReturnedCartBiIdFromUrl, loadStripe } from '../../utils/stripe';\nimport {\n STATUS,\n STATUS_LABELS,\n STRIPE_ELEMENT_OPTS,\n phaseFor,\n DEFAULTS,\n BILLING_COUNTRIES,\n} from '../../constants';\nimport type {\n Status, Phase, Cart, BillingInfo, CheckoutClient, StripeLike, StripeElementLike,\n StripeElementsLike, BillingPlan, CheckoutConsent, SupportedPaymentMethod,\n} from '../../types';\nimport {\n useCartStatusQuery, useSubscriptionIdQuery, useBillingPlansQuery,\n useActiveSubscriptionsQuery, useViaxSessionQuery, useCourseDetailQuery,\n} from './useCheckoutQueries';\nimport type { EdxSessionResult } from '../../utils/provision';\nimport { useCheckoutMutations } from './useCheckoutMutations';\n\n/**\n * Read ?course_run_key= from the current URL.\n * Avoid URLSearchParams — it treats bare `+` as a space, which would turn\n * HarvardX+CS50+X into \"HarvardX CS50 X\". decodeURIComponent keeps `+` intact.\n */\nfunction getCourseRunKeyFromUrl(): string | null {\n if (typeof window === 'undefined') return null;\n const match = /[?&]course_run_key=([^&]*)/.exec(window.location.search);\n if (!match) return null;\n try {\n // Preserve literal `+` (treat as %2B) then decode %XX sequences.\n return decodeURIComponent(match[1].replace(/\\+/g, '%2B')).trim() || null;\n } catch {\n return match[1].trim() || null;\n }\n}\n\nconst redirectBrowser = (url: string): void => {\n window.location.assign(url);\n};\n\nconst getInitialBillingCountry = (userCountry: string | null): string => {\n const normalized = userCountry?.trim().toUpperCase();\n if (normalized && BILLING_COUNTRIES.some(([countryCode]) => countryCode === normalized)) {\n return normalized;\n }\n return 'US';\n};\n\nexport interface UseCheckoutOptions {\n apiUrl?: string,\n edxSessionUrl?: string,\n stripePublishableKey?: string,\n onComplete?: (subscriptionBiId: string | null) => void,\n /** Country code resolved by CheckoutGate — used to show/hide the UK/CA extra checkbox. */\n userCountry?: string | null,\n /**\n * Course run key from the URL (e.g. course-v1:HarvardX+CS50+X).\n * When omitted, read from ?course_run_key=.\n */\n courseRunKey?: string | null,\n /** Override only for tests; production performs a full-page browser redirect. */\n redirectToUrl?: (url: string) => void,\n}\n\nexport interface UseCheckoutResult {\n phase: Phase,\n status: Status | null,\n statusLabel: string,\n stripeReady: boolean,\n /** True once the Stripe card Element iframe is fully initialised and interactive. */\n cardReady: boolean,\n notConfigured: boolean,\n showBanner: boolean,\n dismissBanner: () => void,\n error: string,\n clearError: () => void,\n cardError: string,\n lastComment: string,\n /** Full subscription details including card last 4 — available after SUBSCRIPTION_CREATED. */\n subscriptionDetails: import('../../types').SubscriptionDetails | null,\n billing: BillingInfo,\n setField: (field: keyof BillingInfo, value: string) => void,\n numberMountRef: Ref<HTMLDivElement>,\n expiryMountRef: Ref<HTMLDivElement>,\n cvcMountRef: Ref<HTMLDivElement>,\n submitting: boolean,\n /** True from Place order click until a terminal status is reached. */\n processingSubscription: boolean,\n /** True when Stripe sent the learner back with ?cart_bi_id=. */\n returningFromStripe: boolean,\n placeOrder: (consent: CheckoutConsent, paymentMethod?: SupportedPaymentMethod) => void,\n /** Billing plans fetched on mount — includes prices for display in CartSummary. */\n billingPlans: BillingPlan[],\n /** Live active subscriber count for display in CartSummary. */\n activeSubscriberCount: number | null,\n /** Currently selected billing cycle. */\n selectedCycle: BillingCycle,\n /** Switch between monthly and annual billing. */\n setCycle: (cycle: BillingCycle) => void,\n /** True once GET /edx-session has returned and the viax token is set. */\n sessionReady: boolean,\n /** ISO 3166-1 alpha-2 country code — passed in from CheckoutGate for the UK/CA checkbox. */\n userCountry: string | null,\n /** Course details when arrived via ?course_run_key=; null for standard checkout. */\n course: import('../../types').CourseDetail | null,\n}\n\nexport default function useCheckout(options: UseCheckoutOptions = {}): UseCheckoutResult {\n const {\n apiUrl = DEFAULTS.apiUrl,\n edxSessionUrl,\n stripePublishableKey,\n onComplete,\n userCountry = null,\n courseRunKey: courseRunKeyProp,\n redirectToUrl = redirectBrowser,\n } = options;\n\n const courseRunKey = useMemo(\n () => courseRunKeyProp ?? getCourseRunKeyFromUrl(),\n [courseRunKeyProp],\n );\n\n const client = useMemo<CheckoutClient | null>(() => {\n if (!apiUrl) return null;\n return createCheckoutClient({ apiUrl });\n }, [apiUrl]);\n\n const notConfigured = !client || !stripePublishableKey || !edxSessionUrl;\n\n // Exchange edX session for viax token on page load.\n const sessionQuery = useViaxSessionQuery(notConfigured ? null : edxSessionUrl!);\n const sessionReady = !!sessionQuery.data;\n\n useEffect(() => {\n if (sessionQuery.data && client) {\n client.setToken(sessionQuery.data.viaxToken);\n }\n }, [sessionQuery.data, client]);\n\n // Fetch billing plans, subscriber count, and optional course once the viax session is ready.\n const billingPlansQuery = useBillingPlansQuery(client, sessionReady);\n const activeSubscriptionsQuery = useActiveSubscriptionsQuery(client, sessionReady);\n const courseDetailQuery = useCourseDetailQuery(client, sessionReady, courseRunKey);\n\n // --- state ---\n const [showBanner, setShowBanner] = useState(true);\n const [cart, setCart] = useState<Cart | null>(null);\n const [stripe, setStripe] = useState<StripeLike | null>(null);\n const [stripeReady, setStripeReady] = useState(false);\n const [cardReady, setCardReady] = useState(false);\n const [error, setError] = useState('');\n const [cardError, setCardError] = useState('');\n const [billing, setBilling] = useState<BillingInfo>({\n firstName: '', lastName: '', city: '', zip: '', country: getInitialBillingCountry(userCountry), line1: '', state: '',\n });\n const [selectedCycle, setSelectedCycle] = useState<BillingCycle>(getPlanFromUrl);\n // Set when Stripe returns from a 3DS challenge; cleared once a new attempt starts.\n const [returnedCartBiId, setReturnedCartBiId] = useState<string | null>(getReturnedCartBiIdFromUrl);\n const [processingSubscription, setProcessingSubscription] = useState(\n () => getReturnedCartBiIdFromUrl() !== null,\n );\n\n const setCycle = useCallback((cycle: BillingCycle) => {\n setSelectedCycle(cycle);\n writePlanQueryParam(cycle);\n }, []);\n\n useEffect(() => {\n if (sessionQuery.error) {\n setError(sessionQuery.error.message);\n }\n }, [sessionQuery.error]);\n\n const setField = useCallback(\n (field: keyof BillingInfo, value: string) => setBilling((p: BillingInfo) => ({ ...p, [field]: value })),\n [],\n );\n\n // --- refs ---\n // Stripe instances — written inside useEffect and mutations.\n const stripeInstanceRef = useRef<StripeLike | null>(null);\n const cardNumberElementRef = useRef<StripeElementLike | null>(null);\n const cardExpiryElementRef = useRef<StripeElementLike | null>(null);\n const cardCvcElementRef = useRef<StripeElementLike | null>(null);\n const elementsRef = useRef<StripeElementsLike | null>(null);\n // DOM mount targets — callback refs so we remount when hosts leave and return.\n const numberMountNodeRef = useRef<HTMLDivElement | null>(null);\n const expiryMountNodeRef = useRef<HTMLDivElement | null>(null);\n const cvcMountNodeRef = useRef<HTMLDivElement | null>(null);\n const [cardHostsEpoch, setCardHostsEpoch] = useState(0);\n\n const assignCardHost = useCallback((\n store: { current: HTMLDivElement | null },\n node: HTMLDivElement | null,\n ) => {\n store.current = node;\n if (\n numberMountNodeRef.current\n && expiryMountNodeRef.current\n && cvcMountNodeRef.current\n ) {\n setCardHostsEpoch((n) => n + 1);\n return;\n }\n // Hosts are leaving the DOM — detach so Stripe is not bound to dead nodes.\n cardNumberElementRef.current?.unmount?.();\n cardExpiryElementRef.current?.unmount?.();\n cardCvcElementRef.current?.unmount?.();\n }, []);\n\n const numberMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(numberMountNodeRef, node);\n }, [assignCardHost]);\n const expiryMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(expiryMountNodeRef, node);\n }, [assignCardHost]);\n const cvcMountRef = useCallback((node: HTMLDivElement | null) => {\n assignCardHost(cvcMountNodeRef, node);\n }, [assignCardHost]);\n const mountedRef = useRef(true);\n const completedRef = useRef(false);\n const redirectedUrlRef = useRef<string | null>(null);\n const sessionRef = useRef<EdxSessionResult | null>(null);\n\n useEffect(() => {\n sessionRef.current = sessionQuery.data ?? null;\n }, [sessionQuery.data]);\n\n // Mirror state into refs so mutations can read current values without stale closures.\n const cartRef = useRef<Cart | null>(null);\n const billingRef = useRef<BillingInfo>(billing);\n const selectedCycleRef = useRef<BillingCycle>(selectedCycle);\n\n useEffect(() => {\n cartRef.current = cart;\n }, [cart]);\n useEffect(() => {\n billingRef.current = billing;\n }, [billing]);\n useEffect(() => {\n selectedCycleRef.current = selectedCycle;\n }, [selectedCycle]);\n useEffect(() => {\n stripeInstanceRef.current = stripe;\n }, [stripe]);\n\n // --- server state ---\n // Poll the cart created in this session, or the one Stripe just returned\n // from. The returned cart waits for the viax session so the status request\n // carries a valid token.\n const cartBiId = cart?.biId ?? (sessionReady ? returnedCartBiId : null);\n const statusQuery = useCartStatusQuery(client, cartBiId);\n const status: Status | null = statusQuery.data?.status ?? null;\n const lastComment = statusQuery.data?.lastComment ?? '';\n\n // Phase is 'ready' until a cart exists, then driven by bpStatus.\n const phase: Phase = cartBiId ? phaseFor(status, status === STATUS.IN_CART) : 'ready';\n const subscriptionIdQuery = useSubscriptionIdQuery(\n client, cartBiId, status === STATUS.SUBSCRIPTION_CREATED,\n );\n\n // --- mutations ---\n const { placeOrder: placeMutation } = useCheckoutMutations({\n client,\n sessionRef,\n stripeRef: stripeInstanceRef,\n cardNumberElRef: cardNumberElementRef,\n billingRef,\n selectedCycleRef,\n setError: (msg: string) => {\n setProcessingSubscription(false);\n setError(msg);\n },\n setCardError: (msg: string) => {\n setProcessingSubscription(false);\n setCardError(msg);\n },\n onCartCreated: (created: Cart) => {\n // Sync the ref immediately so any same-tick readers see the cart\n // before the setCart → useEffect mirror runs.\n cartRef.current = created;\n if (mountedRef.current) setCart(created);\n },\n });\n\n // --- load Stripe.js on mount ---\n useEffect(() => {\n mountedRef.current = true;\n if (!stripePublishableKey) return undefined;\n\n (async () => {\n try {\n const instance = await loadStripe(stripePublishableKey);\n if (mountedRef.current) {\n setStripe(instance);\n setStripeReady(true);\n }\n } catch (e: unknown) {\n if (mountedRef.current) setError((e as Error).message);\n }\n })();\n\n return () => {\n mountedRef.current = false;\n };\n }, [stripePublishableKey]);\n\n // --- mount Stripe Elements once Stripe is loaded; remount if hosts return ---\n useEffect(() => {\n if (!stripe) return;\n const numberNode = numberMountNodeRef.current;\n const expiryNode = expiryMountNodeRef.current;\n const cvcNode = cvcMountNodeRef.current;\n if (!numberNode || !expiryNode || !cvcNode) return;\n\n if (cardNumberElementRef.current && cardExpiryElementRef.current && cardCvcElementRef.current) {\n try {\n cardNumberElementRef.current.unmount?.();\n cardExpiryElementRef.current.unmount?.();\n cardCvcElementRef.current.unmount?.();\n cardNumberElementRef.current.mount(numberNode);\n cardExpiryElementRef.current.mount(expiryNode);\n cardCvcElementRef.current.mount(cvcNode);\n return;\n } catch {\n // Element is bound to a destroyed host — create a fresh Elements group.\n cardNumberElementRef.current = null;\n cardExpiryElementRef.current = null;\n cardCvcElementRef.current = null;\n elementsRef.current = null;\n }\n }\n\n setCardReady(false);\n\n const elements = stripe.elements();\n elementsRef.current = elements;\n\n const number = elements.create('cardNumber', { ...STRIPE_ELEMENT_OPTS, showIcon: true });\n const expiry = elements.create('cardExpiry', STRIPE_ELEMENT_OPTS);\n const cvc = elements.create('cardCvc', STRIPE_ELEMENT_OPTS);\n\n number.mount(numberNode);\n expiry.mount(expiryNode);\n cvc.mount(cvcNode);\n\n number.on('ready', () => {\n if (mountedRef.current) setCardReady(true);\n });\n number.on('change', (e: { error?: { message?: string } }) => {\n if (mountedRef.current) setCardError(e.error?.message || '');\n });\n\n cardNumberElementRef.current = number;\n cardExpiryElementRef.current = expiry;\n cardCvcElementRef.current = cvc;\n }, [stripe, cardHostsEpoch]);\n\n // --- on success ---\n useEffect(() => {\n if (status !== STATUS.SUBSCRIPTION_CREATED || completedRef.current) return;\n completedRef.current = true;\n if (onComplete) onComplete(subscriptionIdQuery.data?.biId ?? null);\n }, [status, subscriptionIdQuery.data, onComplete]);\n\n // Stripe and PayPal both authenticate the buyer on a hosted page before\n // returning the browser to checkout, so this must be a full-page\n // navigation (not an API request) for either flow.\n useEffect(() => {\n const redirectUrl = statusQuery.data?.stripeConfirmationRedirectUrl\n || statusQuery.data?.paypalApprovalUrl;\n if (\n status !== STATUS.STRIPE_CONFIRMATION_REQUIRED\n || !redirectUrl\n || redirectedUrlRef.current === redirectUrl\n ) return;\n\n redirectedUrlRef.current = redirectUrl;\n redirectToUrl(redirectUrl);\n }, [\n status,\n statusQuery.data?.stripeConfirmationRedirectUrl,\n statusQuery.data?.paypalApprovalUrl,\n redirectToUrl,\n ]);\n\n // --- actions ---\n const placeOrder = useCallback((consent: CheckoutConsent, paymentMethod: SupportedPaymentMethod = 'card') => {\n setError('');\n setCardError('');\n if (phase === 'failed') setCart(null);\n // Each attempt creates its own cart, so stop reporting on the returned one.\n setReturnedCartBiId(null);\n setProcessingSubscription(true);\n placeMutation.mutate({ consent, paymentMethod });\n }, [placeMutation, phase]);\n\n // Turn off processingSubscription once we reach a terminal status.\n useEffect(() => {\n if (!status) return;\n const terminalStatuses: Status[] = [\n STATUS.SUBSCRIPTION_CREATED,\n STATUS.STRIPE_FAIL,\n STATUS.SANCTION_BLOCK,\n ];\n if (terminalStatuses.includes(status)) {\n setProcessingSubscription(false);\n }\n }, [status]);\n\n return {\n phase,\n status,\n statusLabel: (status && STATUS_LABELS[status]) || 'Processing your order…',\n stripeReady,\n cardReady,\n notConfigured,\n showBanner,\n dismissBanner: () => setShowBanner(false),\n error,\n clearError: () => setError(''),\n cardError,\n lastComment,\n subscriptionDetails: subscriptionIdQuery.data ?? null,\n billing,\n setField,\n numberMountRef,\n expiryMountRef,\n cvcMountRef,\n submitting: placeMutation.isPending,\n processingSubscription,\n returningFromStripe: returnedCartBiId !== null,\n placeOrder,\n billingPlans: billingPlansQuery.data?.plans ?? [],\n activeSubscriberCount: activeSubscriptionsQuery.data?.active ?? null,\n selectedCycle,\n setCycle,\n sessionReady,\n userCountry,\n course: courseDetailQuery.data ?? null,\n };\n}\n"]}
@@ -1,15 +1,16 @@
1
1
  export interface UseCheckoutGateOptions {
2
+ apiUrl?: string;
2
3
  edxSessionUrl?: string;
3
4
  learnerDashboardUrl?: string;
4
5
  }
5
- export type GateStatus = 'loading' | 'blocked' | 'allowed' | 'error';
6
+ export type GateStatus = 'loading' | 'blocked' | 'allowed' | 'error' | 'existingSubscriber';
6
7
  export interface UseCheckoutGateResult {
7
8
  /** 'loading' while session/checks are in flight, 'blocked' if country not allowed, 'allowed' if clear, 'error' if session failed. */
8
9
  gateStatus: GateStatus;
9
10
  /** ISO 3166-1 alpha-2 country code — passed down to Checkout for the UK/CA checkbox. */
10
11
  userCountry: string | null;
11
12
  learnerDashboardUrl: string | undefined;
12
- /** Message when gateStatus is 'error' (typically a failed edx-session exchange). */
13
- errorMessage: string | null;
13
+ /** Message shown when gateStatus is not 'allowed'. */
14
+ gateMessage: string | null;
14
15
  }
15
16
  export declare function useCheckoutGate(options?: UseCheckoutGateOptions): UseCheckoutGateResult;
@@ -1,16 +1,28 @@
1
+ import { useEffect, useMemo } from 'react';
1
2
  import { ALLOWED_CHECKOUT_COUNTRIES, GATE_CHECK_COUNTRY, } from '../../constants';
2
- import { useViaxSessionQuery, useUserCountryQuery, } from './useCheckoutQueries';
3
+ import { createCheckoutClient } from '../../utils/checkout';
4
+ import { getLearnerFacingCheckoutMessage } from '../../utils/checkoutErrors';
5
+ import { useCurrentUserSubscriberQuery, useViaxSessionQuery, useUserCountryQuery, } from './useCheckoutQueries';
3
6
  export function useCheckoutGate(options = {}) {
4
- var _a, _b, _c;
5
- const { edxSessionUrl, learnerDashboardUrl, } = options;
7
+ var _a, _b, _c, _d;
8
+ const { apiUrl, edxSessionUrl, learnerDashboardUrl, } = options;
9
+ const client = useMemo(() => (apiUrl ? createCheckoutClient({ apiUrl }) : null), [apiUrl]);
6
10
  const sessionQuery = useViaxSessionQuery(edxSessionUrl !== null && edxSessionUrl !== void 0 ? edxSessionUrl : null);
7
11
  const sessionReady = !!sessionQuery.data;
12
+ useEffect(() => {
13
+ if (sessionQuery.data && client) {
14
+ client.setToken(sessionQuery.data.viaxToken);
15
+ }
16
+ }, [sessionQuery.data, client]);
17
+ const currentUserSubscriberQuery = useCurrentUserSubscriberQuery(client, sessionReady);
8
18
  const userCountryQuery = useUserCountryQuery(sessionReady && GATE_CHECK_COUNTRY ? (edxSessionUrl !== null && edxSessionUrl !== void 0 ? edxSessionUrl : null) : null, (_b = (_a = sessionQuery.data) === null || _a === void 0 ? void 0 : _a.username) !== null && _b !== void 0 ? _b : null);
9
19
  const userCountry = (_c = userCountryQuery.data) !== null && _c !== void 0 ? _c : null;
20
+ const isExistingSubscriber = ((_d = currentUserSubscriberQuery.data) === null || _d === void 0 ? void 0 : _d.isSubscriber) === true;
10
21
  // Use isLoading (isPending && isFetching), not isPending alone.
11
22
  // In TanStack Query v5, disabled queries with no data stay isPending forever —
12
23
  // e.g. country check when username is missing from the session response.
13
24
  const loading = (!sessionReady && !sessionQuery.isError)
25
+ || currentUserSubscriberQuery.isLoading
14
26
  || (GATE_CHECK_COUNTRY && userCountryQuery.isLoading);
15
27
  // GATE_CHECK_COUNTRY=false → treat all countries as allowed.
16
28
  const isCountryAllowed = !GATE_CHECK_COUNTRY
@@ -23,17 +35,27 @@ export function useCheckoutGate(options = {}) {
23
35
  else if (loading) {
24
36
  gateStatus = 'loading';
25
37
  }
38
+ else if (isExistingSubscriber) {
39
+ gateStatus = 'existingSubscriber';
40
+ }
26
41
  else if (!isCountryAllowed) {
27
42
  gateStatus = 'blocked';
28
43
  }
29
44
  else {
30
45
  gateStatus = 'allowed';
31
46
  }
32
- const errorMessage = sessionQuery.isError
47
+ const gateMessage = gateStatus === 'error'
33
48
  ? (sessionQuery.error instanceof Error
34
49
  ? sessionQuery.error.message
35
50
  : 'Failed to establish checkout session.')
36
- : null;
37
- return { gateStatus, userCountry, learnerDashboardUrl, errorMessage };
51
+ : gateStatus === 'existingSubscriber'
52
+ ? getLearnerFacingCheckoutMessage('duplicate_active_subscription')
53
+ : null;
54
+ return {
55
+ gateStatus,
56
+ userCountry,
57
+ learnerDashboardUrl,
58
+ gateMessage,
59
+ };
38
60
  }
39
61
  //# sourceMappingURL=useCheckoutGate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCheckoutGate.js","sourceRoot":"","sources":["../../../src/data/hooks/useCheckoutGate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAmB9B,MAAM,UAAU,eAAe,CAAC,UAAkC,EAAE;;IAClE,MAAM,EACJ,aAAa,EACb,mBAAmB,GACpB,GAAG,OAAO,CAAC;IAEZ,MAAM,YAAY,GAAG,mBAAmB,CAAC,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,IAAI,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC;IAEzC,MAAM,gBAAgB,GAAG,mBAAmB,CAC1C,YAAY,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EACnE,MAAA,MAAA,YAAY,CAAC,IAAI,0CAAE,QAAQ,mCAAI,IAAI,CACpC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAA,gBAAgB,CAAC,IAAI,mCAAI,IAAI,CAAC;IAElD,gEAAgE;IAChE,+EAA+E;IAC/E,yEAAyE;IACzE,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;WACnD,CAAC,kBAAkB,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAExD,6DAA6D;IAC7D,MAAM,gBAAgB,GAAG,CAAC,kBAAkB;WACvC,WAAW,KAAK,IAAI;WACpB,0BAA0B,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEtD,IAAI,UAAsB,CAAC;IAC3B,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;QACzB,UAAU,GAAG,OAAO,CAAC;IACvB,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;SAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC7B,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;IAED,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO;QACvC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,YAAY,KAAK;YAClC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO;YAC5B,CAAC,CAAC,uCAAuC,CAAC;QAC9C,CAAC,CAAC,IAAI,CAAC;IAET,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,CAAC;AACxE,CAAC","sourcesContent":["import {\n ALLOWED_CHECKOUT_COUNTRIES,\n GATE_CHECK_COUNTRY,\n} from '../../constants';\nimport {\n useViaxSessionQuery,\n useUserCountryQuery,\n} from './useCheckoutQueries';\n\nexport interface UseCheckoutGateOptions {\n edxSessionUrl?: string,\n learnerDashboardUrl?: string,\n}\n\nexport type GateStatus = 'loading' | 'blocked' | 'allowed' | 'error';\n\nexport interface UseCheckoutGateResult {\n /** 'loading' while session/checks are in flight, 'blocked' if country not allowed, 'allowed' if clear, 'error' if session failed. */\n gateStatus: GateStatus,\n /** ISO 3166-1 alpha-2 country code — passed down to Checkout for the UK/CA checkbox. */\n userCountry: string | null,\n learnerDashboardUrl: string | undefined,\n /** Message when gateStatus is 'error' (typically a failed edx-session exchange). */\n errorMessage: string | null,\n}\n\nexport function useCheckoutGate(options: UseCheckoutGateOptions = {}): UseCheckoutGateResult {\n const {\n edxSessionUrl,\n learnerDashboardUrl,\n } = options;\n\n const sessionQuery = useViaxSessionQuery(edxSessionUrl ?? null);\n const sessionReady = !!sessionQuery.data;\n\n const userCountryQuery = useUserCountryQuery(\n sessionReady && GATE_CHECK_COUNTRY ? (edxSessionUrl ?? null) : null,\n sessionQuery.data?.username ?? null,\n );\n\n const userCountry = userCountryQuery.data ?? null;\n\n // Use isLoading (isPending && isFetching), not isPending alone.\n // In TanStack Query v5, disabled queries with no data stay isPending forever —\n // e.g. country check when username is missing from the session response.\n const loading = (!sessionReady && !sessionQuery.isError)\n || (GATE_CHECK_COUNTRY && userCountryQuery.isLoading);\n\n // GATE_CHECK_COUNTRY=false → treat all countries as allowed.\n const isCountryAllowed = !GATE_CHECK_COUNTRY\n || userCountry === null\n || ALLOWED_CHECKOUT_COUNTRIES.includes(userCountry);\n\n let gateStatus: GateStatus;\n if (sessionQuery.isError) {\n gateStatus = 'error';\n } else if (loading) {\n gateStatus = 'loading';\n } else if (!isCountryAllowed) {\n gateStatus = 'blocked';\n } else {\n gateStatus = 'allowed';\n }\n\n const errorMessage = sessionQuery.isError\n ? (sessionQuery.error instanceof Error\n ? sessionQuery.error.message\n : 'Failed to establish checkout session.')\n : null;\n\n return { gateStatus, userCountry, learnerDashboardUrl, errorMessage };\n}\n"]}
1
+ {"version":3,"file":"useCheckoutGate.js","sourceRoot":"","sources":["../../../src/data/hooks/useCheckoutGate.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo } from 'react';\nimport {\n ALLOWED_CHECKOUT_COUNTRIES,\n GATE_CHECK_COUNTRY,\n} from '../../constants';\nimport { createCheckoutClient } from '../../utils/checkout';\nimport { getLearnerFacingCheckoutMessage } from '../../utils/checkoutErrors';\nimport {\n useCurrentUserSubscriberQuery,\n useViaxSessionQuery,\n useUserCountryQuery,\n} from './useCheckoutQueries';\n\nexport interface UseCheckoutGateOptions {\n apiUrl?: string,\n edxSessionUrl?: string,\n learnerDashboardUrl?: string,\n}\n\nexport type GateStatus = 'loading' | 'blocked' | 'allowed' | 'error' | 'existingSubscriber';\n\nexport interface UseCheckoutGateResult {\n /** 'loading' while session/checks are in flight, 'blocked' if country not allowed, 'allowed' if clear, 'error' if session failed. */\n gateStatus: GateStatus,\n /** ISO 3166-1 alpha-2 country code — passed down to Checkout for the UK/CA checkbox. */\n userCountry: string | null,\n learnerDashboardUrl: string | undefined,\n /** Message shown when gateStatus is not 'allowed'. */\n gateMessage: string | null,\n}\n\nexport function useCheckoutGate(options: UseCheckoutGateOptions = {}): UseCheckoutGateResult {\n const {\n apiUrl,\n edxSessionUrl,\n learnerDashboardUrl,\n } = options;\n\n const client = useMemo(\n () => (apiUrl ? createCheckoutClient({ apiUrl }) : null),\n [apiUrl],\n );\n const sessionQuery = useViaxSessionQuery(edxSessionUrl ?? null);\n const sessionReady = !!sessionQuery.data;\n\n useEffect(() => {\n if (sessionQuery.data && client) {\n client.setToken(sessionQuery.data.viaxToken);\n }\n }, [sessionQuery.data, client]);\n\n const currentUserSubscriberQuery = useCurrentUserSubscriberQuery(client, sessionReady);\n const userCountryQuery = useUserCountryQuery(\n sessionReady && GATE_CHECK_COUNTRY ? (edxSessionUrl ?? null) : null,\n sessionQuery.data?.username ?? null,\n );\n\n const userCountry = userCountryQuery.data ?? null;\n const isExistingSubscriber = currentUserSubscriberQuery.data?.isSubscriber === true;\n\n // Use isLoading (isPending && isFetching), not isPending alone.\n // In TanStack Query v5, disabled queries with no data stay isPending forever —\n // e.g. country check when username is missing from the session response.\n const loading = (!sessionReady && !sessionQuery.isError)\n || currentUserSubscriberQuery.isLoading\n || (GATE_CHECK_COUNTRY && userCountryQuery.isLoading);\n\n // GATE_CHECK_COUNTRY=false → treat all countries as allowed.\n const isCountryAllowed = !GATE_CHECK_COUNTRY\n || userCountry === null\n || ALLOWED_CHECKOUT_COUNTRIES.includes(userCountry);\n\n let gateStatus: GateStatus;\n if (sessionQuery.isError) {\n gateStatus = 'error';\n } else if (loading) {\n gateStatus = 'loading';\n } else if (isExistingSubscriber) {\n gateStatus = 'existingSubscriber';\n } else if (!isCountryAllowed) {\n gateStatus = 'blocked';\n } else {\n gateStatus = 'allowed';\n }\n\n const gateMessage = gateStatus === 'error'\n ? (sessionQuery.error instanceof Error\n ? sessionQuery.error.message\n : 'Failed to establish checkout session.')\n : gateStatus === 'existingSubscriber'\n ? getLearnerFacingCheckoutMessage('duplicate_active_subscription')\n : null;\n\n return {\n gateStatus,\n userCountry,\n learnerDashboardUrl,\n gateMessage,\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { RefObject } from 'react';
2
2
  import type { EdxSessionResult } from '../../utils/provision';
3
- import type { CheckoutClient, StripeLike, StripeElementLike, Cart, BillingInfo, CheckoutConsent, BillingCycle, PaymentMethod } from '../../types';
3
+ import type { CheckoutClient, StripeLike, StripeElementLike, Cart, BillingInfo, CheckoutConsent, BillingCycle, SupportedPaymentMethod } from '../../types';
4
4
  export interface CheckoutMutationsCtx {
5
5
  client: CheckoutClient | null;
6
6
  sessionRef: RefObject<EdxSessionResult | null>;
@@ -15,7 +15,7 @@ export interface CheckoutMutationsCtx {
15
15
  }
16
16
  export interface PlaceOrderArgs {
17
17
  consent: CheckoutConsent;
18
- paymentMethod: PaymentMethod;
18
+ paymentMethod: SupportedPaymentMethod;
19
19
  }
20
20
  export declare function useCheckoutMutations(ctx: CheckoutMutationsCtx): {
21
21
  placeOrder: import("@tanstack/react-query").UseMutationResult<Cart, Error, PlaceOrderArgs, unknown>;