@edx/frontend-app-subscription-checkout 1.11.0 → 1.13.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.
- package/dist/components/CartSummary/CartSummary.js +7 -2
- package/dist/components/CartSummary/CartSummary.js.map +1 -1
- package/dist/components/CartSummary/Messages.d.ts +5 -0
- package/dist/components/CartSummary/Messages.js +6 -1
- package/dist/components/CartSummary/Messages.js.map +1 -1
- package/dist/components/Checkout/Checkout.js +17 -8
- package/dist/components/Checkout/Checkout.js.map +1 -1
- package/dist/components/EnrollmentSummary/EnrollmentSummary.js +7 -1
- package/dist/components/EnrollmentSummary/EnrollmentSummary.js.map +1 -1
- package/dist/components/EnrollmentSummary/Messages.d.ts +5 -0
- package/dist/components/EnrollmentSummary/Messages.js +8 -3
- package/dist/components/EnrollmentSummary/Messages.js.map +1 -1
- package/dist/components/PaymentForm/Messages.d.ts +10 -0
- package/dist/components/PaymentForm/Messages.js +13 -3
- package/dist/components/PaymentForm/Messages.js.map +1 -1
- package/dist/components/PaymentForm/PaymentForm.d.ts +2 -2
- package/dist/components/PaymentForm/PaymentForm.js +29 -20
- package/dist/components/PaymentForm/PaymentForm.js.map +1 -1
- package/dist/components/StatusScreens/Messages.d.ts +5 -0
- package/dist/components/StatusScreens/Messages.js +6 -0
- package/dist/components/StatusScreens/Messages.js.map +1 -1
- package/dist/components/StatusScreens/StatusScreens.d.ts +1 -0
- package/dist/components/StatusScreens/StatusScreens.js +8 -1
- package/dist/components/StatusScreens/StatusScreens.js.map +1 -1
- package/dist/data/hooks/useCheckout.d.ts +6 -2
- package/dist/data/hooks/useCheckout.js +45 -13
- package/dist/data/hooks/useCheckout.js.map +1 -1
- package/dist/data/hooks/useCheckoutMutations.d.ts +6 -2
- package/dist/data/hooks/useCheckoutMutations.js +62 -31
- package/dist/data/hooks/useCheckoutMutations.js.map +1 -1
- package/dist/routes.js +2 -2
- package/dist/routes.js.map +1 -1
- package/dist/styles/components/statusScreens.scss +10 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/cartApi.d.ts +4 -4
- package/dist/utils/cartApi.js +26 -14
- package/dist/utils/cartApi.js.map +1 -1
- package/dist/utils/provision.js +2 -2
- package/dist/utils/provision.js.map +1 -1
- package/dist/utils/queries.d.ts +1 -1
- package/dist/utils/queries.js +2 -0
- package/dist/utils/queries.js.map +1 -1
- package/dist/utils/stripe.d.ts +16 -0
- package/dist/utils/stripe.js +43 -0
- package/dist/utils/stripe.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cartApi.js","sourceRoot":"","sources":["../../src/utils/cartApi.ts"],"names":[],"mappings":";;;;;;;;;AAAA;;;;GAIG;AACH,OAAO,EACL,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EACzD,WAAW,EAAE,eAAe,EAAE,iBAAiB,GAChD,MAAM,WAAW,CAAC;AAMnB,qCAAqC;AACrC,MAAM,UAAgB,UAAU;yDAAC,GAAc,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAW;QACnG,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE;YAClC,KAAK,EAAE;gBACL,cAAc,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE;gBACpC,YAAY,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,CAAC;aAC9F;SACF,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAsB,CAAC;IACrC,CAAC;CAAA;AAED,iCAAiC;AACjC,MAAM,UAAgB,WAAW,CAAC,GAAc,EAAE,IAAY;;;QAC5D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,GAAG,IAAI,CAAC,sBAAsB,CAAC;QACvC,MAAM,OAAO,GAAG,EAAE,aAAF,EAAE,uBAAF,EAAE,CAAE,GAAyB,CAAC;QAC9C,MAAM,WAAW,GAAG,MAAA,MAAA,EAAE,aAAF,EAAE,uBAAF,EAAE,CAAE,YAAY,0CAAG,CAAC,CAAC,0CAAE,GAAyB,CAAC;QAErE,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,IAAI,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC;CAAA;AAED,MAAM,UAAgB,cAAc;yDAClC,GAAc,EACd,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAsB;
|
|
1
|
+
{"version":3,"file":"cartApi.js","sourceRoot":"","sources":["../../src/utils/cartApi.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api/cartApi.ts — one function per checkout operation.\n * Each takes the `gql` runner as its first argument so they stay pure and\n * independently testable (mock `gql`, assert the variables).\n */\nimport {\n CREATE_CART, GET_CART_ITEM, UPDATE_CART_ITEM, UPDATE_CART,\n PLACE_ORDER, GET_CART_STATUS, FIND_SUBSCRIPTION,\n} from './queries';\nimport type {\n GqlRunner, Cart, CartIds, CartStatusResult, UpdateCartItemArgs,\n UpdateCartConsentArgs, Status, SubscriptionDetails,\n} from '../types';\n\n/** createTwouCart → { biId, uid } */\nexport async function createCart(gql: GqlRunner, { customerUid, salableUid, billingPlanUid }: CartIds): Promise<Cart> {\n const data = await gql(CREATE_CART, {\n input: {\n prPartyPrimary: { uid: customerUid },\n hiConsistsOf: [{ biiSalable: { uid: salableUid }, paybBillingPlan: { uid: billingPlanUid } }],\n },\n });\n return data.createTwouCart as Cart;\n}\n\n/** → { cartUid, cartItemUid } */\nexport async function getCartItem(gql: GqlRunner, biId: string): Promise<{ cartUid: string, cartItemUid: string }> {\n const data = await gql(GET_CART_ITEM, { biId });\n const bi = data.getBusinessInteraction;\n const cartUid = bi?.uid as string | undefined;\n const cartItemUid = bi?.hiConsistsOf?.[0]?.uid as string | undefined;\n\n if (!cartUid || !cartItemUid) {\n throw new Error(`Cart item not found for cart \"${biId}\".`);\n }\n\n return { cartUid, cartItemUid };\n}\n\nexport async function updateCartItem(\n gql: GqlRunner,\n { cartItemUid, billingAddress, paymentMethodId, paypalEmail }: UpdateCartItemArgs,\n): Promise<void> {\n const input: Record<string, unknown> = { uid: cartItemUid };\n if (billingAddress) input.paybBillingAddress = { typeName: 'ViaxUrbanPropertyAddress', ...billingAddress };\n // paybPayment is the abstract CustomerPeriodicPaymentInput, which only declares\n // fields common to every payment type. Subtype fields such as\n // tStripePaymentMethodId go in the generated `_<subtype>` slot.\n if (paymentMethodId) {\n input.paybPayment = {\n typeName: 'TwouStripePayment',\n _twouStripePayment: { tStripePaymentMethodId: paymentMethodId },\n };\n } else if (paypalEmail !== undefined) {\n input.paybPayment = {\n typeName: 'TwouPaypalPayment',\n _twouPaypalPayment: paypalEmail ? { tPaypalEmail: paypalEmail } : {},\n };\n }\n await gql(UPDATE_CART_ITEM, { input });\n}\n\n/** Persist checkout consent checkboxes and the hosted-payment return URL onto the TwouCart BI. */\nexport async function updateCartConsent(\n gql: GqlRunner,\n { cartUid, consent, returnUrl }: UpdateCartConsentArgs,\n): Promise<void> {\n const input: Record<string, unknown> = {\n uid: cartUid,\n tConsentRecurring: consent.tConsentRecurring,\n tConsentUkCa: consent.tConsentUkCa,\n tConsentAt: consent.tConsentAt,\n tConsentText: consent.tConsentText,\n };\n if (returnUrl) input.tStripeReturnUrl = returnUrl;\n await gql(UPDATE_CART, { input });\n}\n\n/** \"Place order\" — triggers the server-side workflow. */\nexport async function placeOrder(gql: GqlRunner, cartUid: string): Promise<unknown> {\n const data = await gql(PLACE_ORDER, {\n input: {\n businessProcessable: { uid: cartUid, typeName: 'TwouCart' },\n transitionCode: 'Sanction_Check',\n },\n });\n return data.startBusinessProcessableTransition;\n}\n\n/** → current cart workflow status, Stripe details, and latest comment. */\nexport async function getCartStatus(gql: GqlRunner, biId: string): Promise<CartStatusResult> {\n const data = await gql(GET_CART_STATUS, { biId });\n const bi = data?.getBusinessInteraction || {};\n const comments: string[] = bi.cmComments?.edges?.map((e: { node: { comText: string } }) => e.node.comText) || [];\n return {\n status: (bi.bpStatus?.code ?? null) as Status | null,\n stripeSubscriptionId: bi.hiConsistsOf?.[0]?.tStripeSubscriptionId ?? null,\n stripeConfirmationRedirectUrl: bi.tStripeConfirmationRedirectUrl ?? null,\n paypalApprovalUrl: bi.tPaypalApprovalUrl ?? null,\n lastComment: comments.length ? comments[comments.length - 1] : '',\n };\n}\n\nexport async function findSubscriptionBiId(gql: GqlRunner, cartBiId: string): Promise<SubscriptionDetails | null> {\n try {\n const data = await gql(FIND_SUBSCRIPTION, { filter: `biRelatesTo.biId = '${cartBiId}'` });\n const node = data?.filterTwouSubscription?.edges?.[0]?.node;\n if (!node?.biId) return null;\n\n const item = node.hiConsistsOf?.[0];\n const payment = item?.paybPayment;\n\n return {\n biId: node.biId,\n // TwouSubscription exposes tTrialGranted / tTrialPeriod, not start/end dates.\n // Trial display dates are computed client-side via getTrialDateRange().\n trialStart: null,\n trialEnd: null,\n renewalType: node.tRenewalType ?? null,\n cardLast4: payment?.tPaymentMethodLast4 ?? null, // ← last four digits\n cardBrand: payment?.tPaymentMethodBrand ?? null, // ← card type (Visa, Mastercard etc)\n stripePaymentMethodId: payment?.tStripePaymentMethodId ?? null,\n planName: item?.paybBillingPlan?.bipOwnershipModel?.omName ?? null,\n };\n } catch {\n return null;\n }\n}\n"]}
|
package/dist/utils/provision.js
CHANGED
|
@@ -20,8 +20,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
20
20
|
import { EnvironmentTypes, getSiteConfig } from '@openedx/frontend-base';
|
|
21
21
|
/** Hardcoded edX JWT used only for local/dev checkout against stage Viax. */
|
|
22
22
|
const DEV_SESSION_BODY = {
|
|
23
|
-
payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.
|
|
24
|
-
signature: '
|
|
23
|
+
payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc4ODQ2ODgyNywiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzg4NDY1MjI3LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJBRF8yNjA5XzJQMlMiLCJzY29wZXMiOlsidXNlcl9pZCIsImVtYWlsIiwicHJvZmlsZSJdLCJ2ZXJzaW9uIjoiMS4yLjAiLCJzdWIiOiI3ZjVjNzlkMzgxODVjMjRkNzY4Mzc2NGY5MGZkMDViMCIsImZpbHRlcnMiOlsidXNlcjptZSJdLCJpc19yZXN0cmljdGVkIjpmYWxzZSwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ1c2VyX2lkIjo1Mjg1MTkwLCJlbWFpbCI6InhlcXhwZmVmeXlnbGFma2J3YkBvbmxkbS5uZXQiLCJuYW1lIjoiQWthc2ggRGV2Z2FuIChObyBzdWJzY3JpcHRpb24pIiwiZmFtaWx5X25hbWUiOiIiLCJnaXZlbl9uYW1lIjoiIiwiYWRtaW5pc3RyYXRvciI6ZmFsc2UsInN1cGVydXNlciI6ZmFsc2V9',
|
|
24
|
+
signature: 'Fli51TGZL_7Om-llJFKLXYopa9Lc0XsRCw61ycoi2-0q3gGTlYTYXrLA7CZh3wHoj7ja8nQU4SL9P00azxrgHRrvEYzIh_nTYgOkvmcyiYLTGtdxx9Kq0DKstD2DQzMqm6j82TXwekmJXn51Rk331kTwEaPXqpAyXsQWkOkbMF1v5eTsJIP3RkYJm-Mweq26dMZf5t-VOTvgN0oRv8st_vvfGVUrJkNeSomCCyWUwLzpzQHm5lxUigPawRYe-MJMaBatGaQedw5OySKLy7sUW-h-JG3Vlg-n-YepOCjBVXtDGRXO_5oOHGzNT71li-ujOg69rWoCSxhuvVVEHsQq1w'
|
|
25
25
|
};
|
|
26
26
|
function parseSessionResponse(data) {
|
|
27
27
|
var _a, _b, _c, _d;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../../src/utils/provision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;;;;;;;;;;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAWzE,6EAA6E;AAC7E,MAAM,gBAAgB,GAAG;IACvB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../../src/utils/provision.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api/provision.ts — exchange the edX session for a viax token.\n *\n * {LMS_BASE_URL}/api/edx-session\n * The LMS reads the edX JWT from browser cookies, exchanges it with viax,\n * and returns a per-user token for authenticated API calls.\n *\n * Dev uses POST with a hardcoded JWT payload (local LMS cookie exchange is\n * unavailable). Stage and prod use GET and rely on the browser session cookies.\n */\n\nimport { EnvironmentTypes, getSiteConfig } from '@openedx/frontend-base';\n\nexport interface EdxSessionResult {\n viaxToken: string, // raw JWT — add 'Bearer ' prefix before use\n customerUid: string,\n partyUid?: string,\n edxUserId?: string,\n username?: string,\n email?: string,\n}\n\n/** Hardcoded edX JWT used only for local/dev checkout against stage Viax. */\nconst DEV_SESSION_BODY = {\n payload: 'eyJhbGciOiJSUzUxMiIsImtpZCI6Imxtc3N0YWdlMDAyIiwidHlwIjoiSldUIn0.eyJhdWQiOiJJbmtvY3VqTGlreXVjc0Vkd2lXYXRkZWJyRWFja21ldkxha0R1aWZLb29zaGtha1dvdyIsImV4cCI6MTc4ODQ2ODgyNywiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwiaWF0IjoxNzg4NDY1MjI3LCJpc3MiOiJodHRwczovL2NvdXJzZXMuc3RhZ2UuZWR4Lm9yZy9vYXV0aDIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJBRF8yNjA5XzJQMlMiLCJzY29wZXMiOlsidXNlcl9pZCIsImVtYWlsIiwicHJvZmlsZSJdLCJ2ZXJzaW9uIjoiMS4yLjAiLCJzdWIiOiI3ZjVjNzlkMzgxODVjMjRkNzY4Mzc2NGY5MGZkMDViMCIsImZpbHRlcnMiOlsidXNlcjptZSJdLCJpc19yZXN0cmljdGVkIjpmYWxzZSwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ1c2VyX2lkIjo1Mjg1MTkwLCJlbWFpbCI6InhlcXhwZmVmeXlnbGFma2J3YkBvbmxkbS5uZXQiLCJuYW1lIjoiQWthc2ggRGV2Z2FuIChObyBzdWJzY3JpcHRpb24pIiwiZmFtaWx5X25hbWUiOiIiLCJnaXZlbl9uYW1lIjoiIiwiYWRtaW5pc3RyYXRvciI6ZmFsc2UsInN1cGVydXNlciI6ZmFsc2V9',\n signature: 'Fli51TGZL_7Om-llJFKLXYopa9Lc0XsRCw61ycoi2-0q3gGTlYTYXrLA7CZh3wHoj7ja8nQU4SL9P00azxrgHRrvEYzIh_nTYgOkvmcyiYLTGtdxx9Kq0DKstD2DQzMqm6j82TXwekmJXn51Rk331kTwEaPXqpAyXsQWkOkbMF1v5eTsJIP3RkYJm-Mweq26dMZf5t-VOTvgN0oRv8st_vvfGVUrJkNeSomCCyWUwLzpzQHm5lxUigPawRYe-MJMaBatGaQedw5OySKLy7sUW-h-JG3Vlg-n-YepOCjBVXtDGRXO_5oOHGzNT71li-ujOg69rWoCSxhuvVVEHsQq1w'\n};\nfunction parseSessionResponse(data: Record<string, unknown>): EdxSessionResult {\n const viaxToken = (\n data.viaxToken ?? data.token ?? data.access_token ?? data.accessToken\n ) as string | undefined;\n const customerUid = (data.customerUid ?? data.customer_uid) as string | undefined;\n\n if (!viaxToken) throw new Error('Session response missing viax token.');\n if (!customerUid) throw new Error('Session response missing customerUid.');\n\n return {\n viaxToken,\n customerUid,\n partyUid: data.partyUid as string | undefined,\n edxUserId: data.edxUserId as string | undefined,\n username: data.username as string | undefined,\n email: data.email as string | undefined,\n };\n}\n\n/**\n * Fetch the ISO 3166-1 alpha-2 country code from the user's edX account profile.\n * Returns null if the request fails or the field is absent.\n */\nexport async function fetchUserCountry(lmsBaseUrl: string, username: string): Promise<string | null> {\n try {\n const res = await fetch(`${lmsBaseUrl}/api/user/v1/accounts/${encodeURIComponent(username)}`, {\n credentials: 'include',\n });\n if (!res.ok) return null;\n const data = await res.json() as Record<string, unknown>;\n return typeof data.country === 'string' && data.country ? data.country : null;\n } catch {\n return null;\n }\n}\n\nfunction isDevelopment(): boolean {\n return getSiteConfig().environment === EnvironmentTypes.DEVELOPMENT;\n}\n\n/** Exchange the learner's edX session (cookies) for a viax token. */\nexport async function fetchEdxSession(sessionUrl: string): Promise<EdxSessionResult> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n\n let res: Response;\n if (isDevelopment()) {\n res = await fetch(sessionUrl, {\n method: 'POST',\n credentials: 'include',\n headers: {\n ...headers,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(DEV_SESSION_BODY),\n });\n } else {\n res = await fetch(sessionUrl, {\n method: 'POST',\n credentials: 'include',\n headers,\n });\n }\n\n if (!res.ok) {\n throw new Error(\n `Failed to establish checkout session (${res.status}). Please log into edX and try again.`,\n );\n }\n\n const data = await res.json() as Record<string, unknown> & { error?: string };\n if (data.error) throw new Error(String(data.error));\n\n return parseSessionResponse(data);\n}\n"]}
|
package/dist/utils/queries.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare const UPDATE_CART = "mutation UpdateCart($input: TwouCartInput!)
|
|
|
19
19
|
/** Triggers the backend workflow to place the order. */
|
|
20
20
|
export declare const PLACE_ORDER = "mutation PlaceOrder($input: StartBusinessProcessableTransitionInput!) {\n startBusinessProcessableTransition(input: $input) { uid bpStatus { code } }\n}";
|
|
21
21
|
export declare const GET_CART_ITEM = "query GetCartItem($biId: String!) {\n getBusinessInteraction(biId: $biId) {\n uid\n hiConsistsOf { ... on TwouCartItem { uid } }\n }\n}";
|
|
22
|
-
export declare const GET_CART_STATUS = "query GetCartStatus($biId: String!) {\n getBusinessInteraction(biId: $biId) {\n bpStatus { code }\n hiConsistsOf { ... on TwouCartItem { tStripeSubscriptionId } }\n ... on TwouCart {\n cmComments { edges { node { comText } } }\n }\n }\n}";
|
|
22
|
+
export declare const GET_CART_STATUS = "query GetCartStatus($biId: String!) {\n getBusinessInteraction(biId: $biId) {\n bpStatus { code }\n hiConsistsOf { ... on TwouCartItem { tStripeSubscriptionId } }\n ... on TwouCart {\n tStripeConfirmationRedirectUrl\n tPaypalApprovalUrl\n cmComments { edges { node { comText } } }\n }\n }\n}";
|
|
23
23
|
export declare const FIND_SUBSCRIPTION = "query FindSubscription($filter: String!) {\n filterTwouSubscription(_first: 1, _filter: $filter) {\n edges {\n node {\n biId\n tRenewalType\n hiConsistsOf {\n ... on TwouSubscriptionItem {\n paybBillingPlan {\n tStripePriceId\n bipOwnershipModel { omName }\n }\n paybPayment {\n ... on TwouStripePayment {\n tStripePaymentMethodId\n tPaymentMethodLast4\n tPaymentMethodBrand\n }\n }\n }\n }\n }\n }\n }\n}";
|
|
24
24
|
/** Fetch the viax customer uid by email using filterTwouCustomer. */
|
|
25
25
|
export declare const GET_CUSTOMER = "query GetCustomer($filter: String!) {\n filterTwouCustomer(_first: 1, _filter: $filter) {\n edges {\n node {\n uid\n parId\n parParty {\n paName\n paContacts {\n edges {\n node {\n ... on EmailAddressContactMedium {\n email\n }\n }\n }\n }\n ... on Individual {\n indFirstName\n indLastName\n }\n }\n }\n }\n }\n}";
|
package/dist/utils/queries.js
CHANGED
|
@@ -39,6 +39,8 @@ export const GET_CART_STATUS = `query GetCartStatus($biId: String!) {
|
|
|
39
39
|
bpStatus { code }
|
|
40
40
|
hiConsistsOf { ... on TwouCartItem { tStripeSubscriptionId } }
|
|
41
41
|
... on TwouCart {
|
|
42
|
+
tStripeConfirmationRedirectUrl
|
|
43
|
+
tPaypalApprovalUrl
|
|
42
44
|
cmComments { edges { node { comText } } }
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/utils/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,iFAAiF;AAEjF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,WAAW,GAAG;;EAEzB,CAAC;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAG;;EAE9B,CAAC;AAEH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,WAAW,GAAG;;EAEzB,CAAC;AAEH,wDAAwD;AACxD,MAAM,CAAC,MAAM,WAAW,GAAG;;EAEzB,CAAC;AAEH,iFAAiF;AAEjF,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;EAK3B,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/utils/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,iFAAiF;AAEjF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,WAAW,GAAG;;EAEzB,CAAC;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAG;;EAE9B,CAAC;AAEH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,WAAW,GAAG;;EAEzB,CAAC;AAEH,wDAAwD;AACxD,MAAM,CAAC,MAAM,WAAW,GAAG;;EAEzB,CAAC;AAEH,iFAAiF;AAEjF,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;EAK3B,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;EAU7B,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;EAwB/B,CAAC;AAEH,qEAAqE;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;EAyB1B,CAAC;AAEH,iFAAiF;AACjF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;EAWzB,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;EAe/B,CAAC;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,8BAA8B,GAAG;;EAE5C,CAAC;AAEH;0GAC0G;AAC1G,MAAM,CAAC,MAAM,8BAA8B,GAAG;;EAE5C,CAAC;AAEH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4B/B,CAAC","sourcesContent":["/**\n * api/queries.ts — GraphQL documents for the checkout flow.\n * Kept as plain strings so they can be reused, logged, or tested in isolation.\n *\n * Mutation reference (from API doc):\n * updateTwouCustomer — toggle Stripe test clock on/off\n * createTwouCart — user proceeds to payment\n * updateTwouCartItem — attach billing plan / payment method to cart\n * updateTwouCart — persist auto-renewal consent (SUBS-228)\n * startBusinessProcessableTransition — place order\n * updateTwouCartItem — retry: attach new payment method\n */\n\n// ─── Mutations ────────────────────────────────────────────────────────────────\n\n/** Creates a new cart during checkout. */\nexport const CREATE_CART = `mutation CreateCart($input: TwouCartInput!) {\n createTwouCart(input: $input) { biId uid }\n}`;\n\n/** Updates a cart item — attach billing plan / payment method. */\nexport const UPDATE_CART_ITEM = `mutation UpdateCartItem($input: TwouCartItemInput!) {\n updateTwouCartItem(input: $input) { uid }\n}`;\n\n/** Persists auto-renewal consent fields on the TwouCart BI (SUBS-228). */\nexport const UPDATE_CART = `mutation UpdateCart($input: TwouCartInput!) {\n updateTwouCart(input: $input) { uid }\n}`;\n\n/** Triggers the backend workflow to place the order. */\nexport const PLACE_ORDER = `mutation PlaceOrder($input: StartBusinessProcessableTransitionInput!) {\n startBusinessProcessableTransition(input: $input) { uid bpStatus { code } }\n}`;\n\n// ─── Queries ──────────────────────────────────────────────────────────────────\n\nexport const GET_CART_ITEM = `query GetCartItem($biId: String!) {\n getBusinessInteraction(biId: $biId) {\n uid\n hiConsistsOf { ... on TwouCartItem { uid } }\n }\n}`;\n\nexport const GET_CART_STATUS = `query GetCartStatus($biId: String!) {\n getBusinessInteraction(biId: $biId) {\n bpStatus { code }\n hiConsistsOf { ... on TwouCartItem { tStripeSubscriptionId } }\n ... on TwouCart {\n tStripeConfirmationRedirectUrl\n tPaypalApprovalUrl\n cmComments { edges { node { comText } } }\n }\n }\n}`;\n\nexport const FIND_SUBSCRIPTION = `query FindSubscription($filter: String!) {\n filterTwouSubscription(_first: 1, _filter: $filter) {\n edges {\n node {\n biId\n tRenewalType\n hiConsistsOf {\n ... on TwouSubscriptionItem {\n paybBillingPlan {\n tStripePriceId\n bipOwnershipModel { omName }\n }\n paybPayment {\n ... on TwouStripePayment {\n tStripePaymentMethodId\n tPaymentMethodLast4\n tPaymentMethodBrand\n }\n }\n }\n }\n }\n }\n }\n}`;\n\n/** Fetch the viax customer uid by email using filterTwouCustomer. */\nexport const GET_CUSTOMER = `query GetCustomer($filter: String!) {\n filterTwouCustomer(_first: 1, _filter: $filter) {\n edges {\n node {\n uid\n parId\n parParty {\n paName\n paContacts {\n edges {\n node {\n ... on EmailAddressContactMedium {\n email\n }\n }\n }\n }\n ... on Individual {\n indFirstName\n indLastName\n }\n }\n }\n }\n }\n}`;\n\n/** Fetch the TwouSubscriptionPlan uid to use as biiSalable in createTwouCart. */\nexport const GET_PRODUCT = `query GetProduct($maId: String!) {\n getProduct(maId: $maId) {\n maName\n uid\n ... on TwouSubscriptionPlan {\n saOwnershipModels {\n uid\n omName\n }\n }\n }\n}`;\n\nexport const GET_BILLING_PLANS = `query GetBillingPlans {\n filterCustomerBillingPlan(_first: 10) {\n edges {\n node {\n uid\n tStripePriceId\n tStripeAmount {\n amount\n units { code }\n }\n bipIsTemplate\n bipOwnershipModel { uid omName }\n }\n }\n }\n}`;\n\n/** Fetch the number of active subscriptions — unauthenticated. */\nexport const GET_ACTIVE_SUBSCRIPTIONS_STATE = `query activeSubscriptions {\n tActiveSubscriptionsState\n}`;\n\n/** Check whether the currently authenticated user already has an active subscription.\n * tIsCurrentUserSubscriber is a JSON scalar — returns the full object, no subfield selection allowed. */\nexport const GET_IS_CURRENT_USER_SUBSCRIBER = `query IsCurrentUserSubscriber {\n tIsCurrentUserSubscriber\n}`;\n\n/** Fetch a course for the enrollment card when ?course_run_key= is present. */\nexport const GET_COURSE_DETAIL = `query CourseDetail($filter: String!) {\n filterTwouCourse(_first: 1, _filter: $filter) {\n edges {\n node {\n maId\n maName\n maDescription\n tShortDescription\n imageUrl\n tCourseKey\n tBrandText\n tPrimarySubjectArea\n tLevelType\n tLanguage\n tPacingType { code }\n tDurationLow\n tDurationHigh\n tDurationUnit { code }\n tEffortLow\n tEffortHigh\n tEffortUnit { code }\n tUrlCourse\n tB2cSubscriptionInclusion\n tHasOfacRestrictions\n tCatalogActive\n }\n }\n }\n}`;\n"]}
|
package/dist/utils/stripe.d.ts
CHANGED
|
@@ -5,3 +5,19 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { StripeLike } from '../types';
|
|
7
7
|
export declare function loadStripe(publishableKey: string): Promise<StripeLike>;
|
|
8
|
+
/** Query parameter carrying the cart biId on Stripe's 3DS return URL. */
|
|
9
|
+
export declare const RETURN_CART_PARAM = "cart_bi_id";
|
|
10
|
+
export declare function getReturnedCartBiIdFromSearch(search: string): string | null;
|
|
11
|
+
export declare function getReturnedCartBiIdFromUrl(): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Set ?cart_bi_id= while preserving other params.
|
|
14
|
+
* Avoid URLSearchParams — it treats bare `+` as a space and would break
|
|
15
|
+
* course_run_key values like HarvardX+CS50+X.
|
|
16
|
+
*/
|
|
17
|
+
export declare function withReturnCartQuery(search: string, cartBiId: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Absolute URL for tStripeReturnUrl — Stripe rejects relative return URLs.
|
|
20
|
+
* Appends the cart biId so checkout can poll that attempt after 3DS.
|
|
21
|
+
* Keeps the learner's existing params (plan, course_run_key).
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildStripeReturnUrl(cartBiId: string): string | null;
|
package/dist/utils/stripe.js
CHANGED
|
@@ -40,4 +40,47 @@ export function loadStripe(publishableKey) {
|
|
|
40
40
|
}
|
|
41
41
|
return stripeLoadingPromise.then(() => window.Stripe(publishableKey));
|
|
42
42
|
}
|
|
43
|
+
/** Query parameter carrying the cart biId on Stripe's 3DS return URL. */
|
|
44
|
+
export const RETURN_CART_PARAM = 'cart_bi_id';
|
|
45
|
+
export function getReturnedCartBiIdFromSearch(search) {
|
|
46
|
+
const match = new RegExp(`[?&]${RETURN_CART_PARAM}=([^&]*)`, 'i').exec(search);
|
|
47
|
+
if (!match)
|
|
48
|
+
return null;
|
|
49
|
+
try {
|
|
50
|
+
return decodeURIComponent(match[1]).trim() || null;
|
|
51
|
+
}
|
|
52
|
+
catch (_a) {
|
|
53
|
+
return match[1].trim() || null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function getReturnedCartBiIdFromUrl() {
|
|
57
|
+
if (typeof window === 'undefined')
|
|
58
|
+
return null;
|
|
59
|
+
return getReturnedCartBiIdFromSearch(window.location.search);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Set ?cart_bi_id= while preserving other params.
|
|
63
|
+
* Avoid URLSearchParams — it treats bare `+` as a space and would break
|
|
64
|
+
* course_run_key values like HarvardX+CS50+X.
|
|
65
|
+
*/
|
|
66
|
+
export function withReturnCartQuery(search, cartBiId) {
|
|
67
|
+
const raw = search.startsWith('?') ? search.slice(1) : search;
|
|
68
|
+
const parts = raw
|
|
69
|
+
.split('&')
|
|
70
|
+
.filter((part) => (part.length > 0
|
|
71
|
+
&& !part.toLowerCase().startsWith(`${RETURN_CART_PARAM}=`)));
|
|
72
|
+
parts.push(`${RETURN_CART_PARAM}=${encodeURIComponent(cartBiId)}`);
|
|
73
|
+
return `?${parts.join('&')}`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Absolute URL for tStripeReturnUrl — Stripe rejects relative return URLs.
|
|
77
|
+
* Appends the cart biId so checkout can poll that attempt after 3DS.
|
|
78
|
+
* Keeps the learner's existing params (plan, course_run_key).
|
|
79
|
+
*/
|
|
80
|
+
export function buildStripeReturnUrl(cartBiId) {
|
|
81
|
+
if (typeof window === 'undefined')
|
|
82
|
+
return null;
|
|
83
|
+
const { origin, pathname, search } = window.location;
|
|
84
|
+
return `${origin}${pathname}${withReturnCartQuery(search, cartBiId)}`;
|
|
85
|
+
}
|
|
43
86
|
//# sourceMappingURL=stripe.js.map
|
package/dist/utils/stripe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../src/utils/stripe.ts"],"names":[],"mappings":"AAOA,IAAI,oBAAoB,GAAyB,IAAI,CAAC;AAEtD,MAAM,UAAU,UAAU,CAAC,cAAsB;IAC/C,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;IACzE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,oBAAoB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3D,MAAM,IAAI,GAAG,CAAC,GAAU,EAAE,EAAE;gBAC1B,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC;YAEF,MAAM,IAAI,GAAG,GAAG,EAAE;gBAChB,IAAI,MAAM,CAAC,MAAM;oBAAE,OAAO,EAAE,CAAC;;oBACxB,IAAI,CAAC,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC,CAAC;YACxE,CAAC,CAAC;YAEF,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,yCAAyC,CAAC,CAAC;YACnF,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBAClB,OAAO,EAAE,CAAC;oBACV,OAAO;gBACT,CAAC;gBACD,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBACxD,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtG,4EAA4E;gBAC5E,IAAI,MAAM,CAAC,MAAM;oBAAE,OAAO,EAAE,CAAC;gBAC7B,OAAO;YACT,CAAC;YAED,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC3C,CAAC,CAAC,GAAG,GAAG,2BAA2B,CAAC;YACpC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;YACf,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;YAC9D,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAO,CAAC,cAAc,CAAC,CAAC,CAAC;AACzE,CAAC","sourcesContent":["/**\n * api/stripe.ts — load Stripe.js and return a Stripe instance.\n * Injects the script tag if needed. In an MFE you may prefer\n * `@stripe/stripe-js`'s loadStripe(); swap this out if so.\n */\nimport type { StripeLike } from '../types';\n\nlet stripeLoadingPromise: Promise<void> | null = null;\n\nexport function loadStripe(publishableKey: string): Promise<StripeLike> {\n if (typeof window === 'undefined') {\n return Promise.reject(new Error('Stripe.js requires a browser environment'));\n }\n if (window.Stripe) return Promise.resolve(window.Stripe(publishableKey));\n if (!stripeLoadingPromise) {\n stripeLoadingPromise = new Promise<void>((resolve, reject) => {\n const fail = (err: Error) => {\n stripeLoadingPromise = null;\n reject(err);\n };\n\n const done = () => {\n if (window.Stripe) resolve();\n else fail(new Error('Stripe.js loaded but window.Stripe is missing'));\n };\n\n const existing = document.querySelector('script[src^=\"https://js.stripe.com/v3\"]');\n if (existing) {\n if (window.Stripe) {\n resolve();\n return;\n }\n existing.addEventListener('load', done, { once: true });\n existing.addEventListener('error', () => fail(new Error('Failed to load Stripe.js')), { once: true });\n // Race: load may have completed between querySelector and addEventListener.\n if (window.Stripe) resolve();\n return;\n }\n\n const s = document.createElement('script');\n s.src = 'https://js.stripe.com/v3/';\n s.async = true;\n s.onload = done;\n s.onerror = () => fail(new Error('Failed to load Stripe.js'));\n document.head.appendChild(s);\n });\n }\n return stripeLoadingPromise.then(() => window.Stripe!(publishableKey));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../src/utils/stripe.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api/stripe.ts — load Stripe.js and return a Stripe instance.\n * Injects the script tag if needed. In an MFE you may prefer\n * `@stripe/stripe-js`'s loadStripe(); swap this out if so.\n */\nimport type { StripeLike } from '../types';\n\nlet stripeLoadingPromise: Promise<void> | null = null;\n\nexport function loadStripe(publishableKey: string): Promise<StripeLike> {\n if (typeof window === 'undefined') {\n return Promise.reject(new Error('Stripe.js requires a browser environment'));\n }\n if (window.Stripe) return Promise.resolve(window.Stripe(publishableKey));\n if (!stripeLoadingPromise) {\n stripeLoadingPromise = new Promise<void>((resolve, reject) => {\n const fail = (err: Error) => {\n stripeLoadingPromise = null;\n reject(err);\n };\n\n const done = () => {\n if (window.Stripe) resolve();\n else fail(new Error('Stripe.js loaded but window.Stripe is missing'));\n };\n\n const existing = document.querySelector('script[src^=\"https://js.stripe.com/v3\"]');\n if (existing) {\n if (window.Stripe) {\n resolve();\n return;\n }\n existing.addEventListener('load', done, { once: true });\n existing.addEventListener('error', () => fail(new Error('Failed to load Stripe.js')), { once: true });\n // Race: load may have completed between querySelector and addEventListener.\n if (window.Stripe) resolve();\n return;\n }\n\n const s = document.createElement('script');\n s.src = 'https://js.stripe.com/v3/';\n s.async = true;\n s.onload = done;\n s.onerror = () => fail(new Error('Failed to load Stripe.js'));\n document.head.appendChild(s);\n });\n }\n return stripeLoadingPromise.then(() => window.Stripe!(publishableKey));\n}\n\n/** Query parameter carrying the cart biId on Stripe's 3DS return URL. */\nexport const RETURN_CART_PARAM = 'cart_bi_id';\n\nexport function getReturnedCartBiIdFromSearch(search: string): string | null {\n const match = new RegExp(`[?&]${RETURN_CART_PARAM}=([^&]*)`, 'i').exec(search);\n if (!match) return null;\n try {\n return decodeURIComponent(match[1]).trim() || null;\n } catch {\n return match[1].trim() || null;\n }\n}\n\nexport function getReturnedCartBiIdFromUrl(): string | null {\n if (typeof window === 'undefined') return null;\n return getReturnedCartBiIdFromSearch(window.location.search);\n}\n\n/**\n * Set ?cart_bi_id= while preserving other params.\n * Avoid URLSearchParams — it treats bare `+` as a space and would break\n * course_run_key values like HarvardX+CS50+X.\n */\nexport function withReturnCartQuery(search: string, cartBiId: string): string {\n const raw = search.startsWith('?') ? search.slice(1) : search;\n const parts = raw\n .split('&')\n .filter((part) => (\n part.length > 0\n && !part.toLowerCase().startsWith(`${RETURN_CART_PARAM}=`)\n ));\n parts.push(`${RETURN_CART_PARAM}=${encodeURIComponent(cartBiId)}`);\n return `?${parts.join('&')}`;\n}\n\n/**\n * Absolute URL for tStripeReturnUrl — Stripe rejects relative return URLs.\n * Appends the cart biId so checkout can poll that attempt after 3DS.\n * Keeps the learner's existing params (plan, course_run_key).\n */\nexport function buildStripeReturnUrl(cartBiId: string): string | null {\n if (typeof window === 'undefined') return null;\n const { origin, pathname, search } = window.location;\n return `${origin}${pathname}${withReturnCartQuery(search, cartBiId)}`;\n}\n"]}
|