@burdenoff/microfe-billing 2026.918.1 → 2026.1005.2
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/billing/lib/native-purchases.js +2 -2
- package/dist/billing/modules/checkout/hooks/useNativeCheckout.js +81 -67
- package/dist/billing/modules/checkout/hooks/useNativeCheckout.js.map +1 -1
- package/dist/billing/modules/checkout/pages/CheckoutPage.js +59 -59
- package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
- package/dist/generated/global-operations.js +4 -0
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { acknowledgeNativePurchase as e, getNativeProducts as t,
|
|
2
|
-
export { e as acknowledgeNativePurchase, t as getNativeProducts, n as
|
|
1
|
+
import { acknowledgeNativePurchase as e, getNativeProducts as t, getNativePurchases as n, installNativeIAP as r, isNativeIAPAvailable as i, purchaseNativeProduct as a, restoreNativePurchases as o } from "@burdenoff/fe-libs/shared/native/purchases";
|
|
2
|
+
export { e as acknowledgeNativePurchase, t as getNativeProducts, n as getNativePurchases, r as installNativeIAP, i as isNativeIAPAvailable, a as purchaseNativeProduct, o as restoreNativePurchases };
|
|
@@ -1,92 +1,106 @@
|
|
|
1
1
|
import { useBilling as e } from "../../../providers/BillingProvider.js";
|
|
2
2
|
import { normalizeGlobalGatewayBaseUrl as t } from "../../../shared/utils/gatewayGraphql.js";
|
|
3
3
|
import { Capacitor as n } from "../../../../node_modules/@capacitor/core/dist/index.js";
|
|
4
|
-
import { acknowledgeNativePurchase as r, getNativeProducts as i,
|
|
5
|
-
import { useCallback as
|
|
4
|
+
import { acknowledgeNativePurchase as r, getNativeProducts as i, getNativePurchases as a, installNativeIAP as o, isNativeIAPAvailable as s, purchaseNativeProduct as c, restoreNativePurchases as l } from "../../../lib/native-purchases.js";
|
|
5
|
+
import { useCallback as u, useEffect as d, useState as f } from "react";
|
|
6
6
|
//#region src/billing/modules/checkout/hooks/useNativeCheckout.ts
|
|
7
|
-
function
|
|
8
|
-
let { apiGatewayUrl:
|
|
9
|
-
if (!
|
|
10
|
-
let
|
|
7
|
+
function p({ billingAccountId: p, purchaseType: m, productId: h } = {}) {
|
|
8
|
+
let { apiGatewayUrl: g, authToken: _ } = e(), [v, y] = f([]), [b, x] = f("idle"), [S, C] = f(null), [w, T] = f(!1), E = u(async (e, i, a) => {
|
|
9
|
+
if (!p) throw Error("No billing account selected");
|
|
10
|
+
let o = `${t(g) ?? ""}/global/rest/billing/iap/validate`, s = n.getPlatform();
|
|
11
|
+
if (s !== "ios" && s !== "android") throw Error("Native purchases require an iOS or Android app");
|
|
12
|
+
let c = await fetch(o, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
..._ ? { Authorization: `Bearer ${_}` } : {}
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
platform: s,
|
|
20
|
+
transactionId: e.transactionId,
|
|
21
|
+
productIdentifier: e.productIdentifier,
|
|
22
|
+
receipt: e.receipt,
|
|
23
|
+
jwsRepresentation: e.jwsRepresentation,
|
|
24
|
+
purchaseToken: e.purchaseToken,
|
|
25
|
+
appAccountToken: a ?? e.appAccountToken ?? void 0,
|
|
26
|
+
billingAccountId: p,
|
|
27
|
+
purchaseType: m ?? "PLAN",
|
|
28
|
+
nativePurchaseType: m === "PLAN" ? "SUBS" : "INAPP",
|
|
29
|
+
price: i?.price,
|
|
30
|
+
currency: i?.currencyCode
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
if (!c.ok) {
|
|
34
|
+
let e = await c.json().catch(() => ({}));
|
|
35
|
+
throw Error(e.message ?? `Validation failed (${c.status})`);
|
|
36
|
+
}
|
|
37
|
+
await r(e.purchaseToken ?? e.transactionId);
|
|
38
|
+
}, [
|
|
39
|
+
g,
|
|
40
|
+
_,
|
|
41
|
+
p,
|
|
42
|
+
m
|
|
43
|
+
]);
|
|
44
|
+
d(() => {
|
|
45
|
+
!s() || !p || o((e) => {
|
|
46
|
+
E(e).catch(() => {});
|
|
47
|
+
});
|
|
48
|
+
}, [p, E]);
|
|
49
|
+
let D = u(async (e) => {
|
|
50
|
+
if (!s()) return;
|
|
51
|
+
let t = e ?? (h ? [h] : []);
|
|
11
52
|
if (t.length !== 0) {
|
|
12
|
-
|
|
53
|
+
T(!0), C(null);
|
|
13
54
|
try {
|
|
14
|
-
|
|
55
|
+
y(await i(t, m === "PLAN" ? "subs" : "inapp"));
|
|
15
56
|
} catch (e) {
|
|
16
|
-
|
|
57
|
+
C(e instanceof Error ? e.message : "Failed to load products");
|
|
17
58
|
} finally {
|
|
18
|
-
|
|
59
|
+
T(!1);
|
|
19
60
|
}
|
|
20
61
|
}
|
|
21
|
-
}, [
|
|
22
|
-
if (!
|
|
23
|
-
|
|
24
|
-
let
|
|
62
|
+
}, [h, m]), O = u(async (e) => {
|
|
63
|
+
if (!p) return C("No billing account selected"), { success: !1 };
|
|
64
|
+
x("processing"), C(null);
|
|
65
|
+
let t;
|
|
25
66
|
try {
|
|
26
|
-
let
|
|
27
|
-
|
|
67
|
+
let n = m === "CREDITS" || m === "ADDON", r = crypto.randomUUID();
|
|
68
|
+
return t = await c(e.identifier, {
|
|
28
69
|
autoAcknowledgePurchases: !1,
|
|
29
|
-
isConsumable:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
method: "POST",
|
|
35
|
-
headers: {
|
|
36
|
-
"Content-Type": "application/json",
|
|
37
|
-
...m ? { Authorization: `Bearer ${m}` } : {}
|
|
38
|
-
},
|
|
39
|
-
body: JSON.stringify({
|
|
40
|
-
platform: l,
|
|
41
|
-
transactionId: i.transactionId,
|
|
42
|
-
productIdentifier: i.productIdentifier,
|
|
43
|
-
receipt: i.receipt,
|
|
44
|
-
jwsRepresentation: i.jwsRepresentation,
|
|
45
|
-
purchaseToken: i.purchaseToken,
|
|
46
|
-
appAccountToken: s,
|
|
47
|
-
billingAccountId: u,
|
|
48
|
-
purchaseType: d,
|
|
49
|
-
nativePurchaseType: f,
|
|
50
|
-
price: e.price,
|
|
51
|
-
currency: e.currencyCode
|
|
52
|
-
})
|
|
53
|
-
});
|
|
54
|
-
if (!h.ok) {
|
|
55
|
-
let e = await h.json().catch(() => ({}));
|
|
56
|
-
throw Error(e.message ?? `Validation failed (${h.status})`);
|
|
57
|
-
}
|
|
58
|
-
return await r(i.purchaseToken ?? i.transactionId), v("success"), { success: !0 };
|
|
70
|
+
isConsumable: n,
|
|
71
|
+
productType: m === "PLAN" ? "subs" : "inapp",
|
|
72
|
+
planIdentifier: m === "PLAN" ? e.planIdentifier ?? void 0 : void 0,
|
|
73
|
+
appAccountToken: r
|
|
74
|
+
}), await E(t, e, r), x("success"), { success: !0 };
|
|
59
75
|
} catch (e) {
|
|
60
76
|
let t = e instanceof Error ? e.message : "Purchase failed";
|
|
61
|
-
return t.toLowerCase().includes("cancel") || t.toLowerCase().includes("dismiss") || t.toLowerCase().includes("abort") ?
|
|
77
|
+
return t.toLowerCase().includes("cancel") || t.toLowerCase().includes("dismiss") || t.toLowerCase().includes("abort") ? x("idle") : (C(t), x("error")), { success: !1 };
|
|
62
78
|
}
|
|
63
|
-
}, [
|
|
64
|
-
|
|
65
|
-
p,
|
|
66
|
-
m,
|
|
67
|
-
d
|
|
68
|
-
]), T = c(async () => {
|
|
69
|
-
S(!0), b(null);
|
|
79
|
+
}, [m, E]), k = u(async () => {
|
|
80
|
+
T(!0), C(null);
|
|
70
81
|
try {
|
|
71
|
-
|
|
82
|
+
await l();
|
|
83
|
+
let e = await a({ productType: m === "PLAN" ? "subs" : "inapp" });
|
|
84
|
+
for (let t of e) await E(t);
|
|
85
|
+
return { success: !0 };
|
|
72
86
|
} catch (e) {
|
|
73
|
-
return
|
|
87
|
+
return C(e instanceof Error ? e.message : "Restore failed"), { success: !1 };
|
|
74
88
|
} finally {
|
|
75
|
-
|
|
89
|
+
T(!1);
|
|
76
90
|
}
|
|
77
|
-
}, []);
|
|
91
|
+
}, [E]);
|
|
78
92
|
return {
|
|
79
|
-
isAvailable:
|
|
80
|
-
products:
|
|
81
|
-
checkoutState:
|
|
82
|
-
error:
|
|
83
|
-
isLoading:
|
|
84
|
-
loadProducts:
|
|
85
|
-
purchaseProduct:
|
|
86
|
-
restorePurchases:
|
|
93
|
+
isAvailable: s(),
|
|
94
|
+
products: v,
|
|
95
|
+
checkoutState: b,
|
|
96
|
+
error: S,
|
|
97
|
+
isLoading: w,
|
|
98
|
+
loadProducts: D,
|
|
99
|
+
purchaseProduct: O,
|
|
100
|
+
restorePurchases: k
|
|
87
101
|
};
|
|
88
102
|
}
|
|
89
103
|
//#endregion
|
|
90
|
-
export {
|
|
104
|
+
export { p as useNativeCheckout };
|
|
91
105
|
|
|
92
106
|
//# sourceMappingURL=useNativeCheckout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNativeCheckout.js","names":[],"sources":["../../../../../src/billing/modules/checkout/hooks/useNativeCheckout.ts"],"sourcesContent":["/**\n * Native IAP checkout hook — Apple StoreKit / Google Play Billing.\n *\n * Manages the full native purchase lifecycle:\n * 1. Load product info from the App Store / Play Store\n * 2. Trigger the native payment sheet\n * 3. Send the receipt / JWS / purchase token to the backend for validation\n * 4. Acknowledge the transaction after the backend confirms it\n *\n * The backend endpoint POST /rest/billing/iap/validate validates with Apple\n * or Google servers and then activates the subscription or credits — no\n * RevenueCat or third-party account required.\n */\n\nimport { useState, useCallback } from 'react';\nimport { Capacitor } from '@capacitor/core';\nimport {\n getNativeProducts,\n purchaseNativeProduct,\n acknowledgeNativePurchase,\n restoreNativePurchases,\n isNativeIAPAvailable,\n} from '../../../lib/native-purchases';\nimport type { Product, Transaction } from '@capgo/native-purchases';\nimport type { CheckoutState, PurchaseType } from '../types';\nimport { useBilling } from '../../../providers/BillingProvider';\nimport { normalizeGlobalGatewayBaseUrl } from '../../../shared/utils/gatewayGraphql';\n\nexport type { Product, Transaction };\n\ninterface UseNativeCheckoutOptions {\n billingAccountId?: string;\n purchaseType?: PurchaseType;\n /** Store product identifier — passed to getProducts to load the specific product. */\n productId?: string;\n}\n\ninterface UseNativeCheckoutResult {\n isAvailable: boolean;\n products: Product[];\n checkoutState: CheckoutState;\n error: string | null;\n isLoading: boolean;\n loadProducts: (productIdentifiers?: string[]) => Promise<void>;\n purchaseProduct: (product: Product) => Promise<{ success: boolean }>;\n restorePurchases: () => Promise<{ success: boolean }>;\n}\n\nexport function useNativeCheckout({\n billingAccountId,\n purchaseType,\n productId,\n}: UseNativeCheckoutOptions = {}): UseNativeCheckoutResult {\n const { apiGatewayUrl, authToken } = useBilling();\n const [products, setProducts] = useState<Product[]>([]);\n const [checkoutState, setCheckoutState] = useState<CheckoutState>('idle');\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const loadProducts = useCallback(\n async (productIdentifiers?: string[]) => {\n if (!isNativeIAPAvailable()) return;\n const ids = productIdentifiers ?? (productId ? [productId] : []);\n if (ids.length === 0) return;\n setIsLoading(true);\n setError(null);\n try {\n const result = await getNativeProducts(ids);\n setProducts(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load products');\n } finally {\n setIsLoading(false);\n }\n },\n [productId]\n );\n\n const purchaseProduct = useCallback(\n async (product: Product): Promise<{ success: boolean }> => {\n if (!billingAccountId) {\n setError('No billing account selected');\n return { success: false };\n }\n\n setCheckoutState('processing');\n setError(null);\n\n let transaction: Transaction | undefined;\n try {\n // Trigger native payment sheet — deferred ack so we validate server-side first.\n // planIdentifier is required for Android subscriptions (base plan ID from Play Console).\n // isConsumable allows credits to be re-purchased on Android.\n const isCredits = purchaseType === 'CREDITS';\n // appAccountToken: UUID passed to Apple/Google so they echo it in server notifications,\n // allowing us to link renewals/cancellations to this billing account.\n // iOS requires UUID format; Android (obfuscatedExternalAccountId) accepts any string ≤ 64 chars.\n const appAccountToken = crypto.randomUUID();\n transaction = await purchaseNativeProduct(product.identifier, {\n autoAcknowledgePurchases: false,\n isConsumable: isCredits,\n planIdentifier: !isCredits ? (product.planIdentifier ?? undefined) : undefined,\n appAccountToken,\n });\n\n // Send receipt / token to backend for server-side validation and entitlement activation.\n // apiGatewayUrl is the GraphQL endpoint (e.g. https://graphql.burdenoff.com/global/graphql);\n // strip the /global/graphql suffix to get the base URL, then use the REST path.\n const gatewayBase = normalizeGlobalGatewayBaseUrl(apiGatewayUrl) ?? '';\n const iapValidateUrl = `${gatewayBase}/global/rest/billing/iap/validate`;\n const platform = Capacitor.getPlatform() as 'ios' | 'android';\n // nativePurchaseType: credits are consumable (INAPP); plans and addons are subscriptions (SUBS).\n const nativePurchaseType = isCredits ? 'INAPP' : 'SUBS';\n const response = await fetch(iapValidateUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n },\n body: JSON.stringify({\n platform,\n transactionId: transaction.transactionId,\n productIdentifier: transaction.productIdentifier,\n receipt: transaction.receipt,\n jwsRepresentation: transaction.jwsRepresentation,\n purchaseToken: transaction.purchaseToken,\n appAccountToken,\n billingAccountId,\n purchaseType,\n nativePurchaseType,\n price: product.price,\n currency: product.currencyCode,\n }),\n });\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as { message?: string };\n throw new Error(body.message ?? `Validation failed (${response.status})`);\n }\n\n // Acknowledge only after backend confirms the purchase is valid\n await acknowledgeNativePurchase(transaction.purchaseToken ?? transaction.transactionId);\n\n setCheckoutState('success');\n return { success: true };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Purchase failed';\n // User cancellation is not an error worth surfacing as \"error\" state\n if (\n message.toLowerCase().includes('cancel') ||\n message.toLowerCase().includes('dismiss') ||\n message.toLowerCase().includes('abort')\n ) {\n setCheckoutState('idle');\n } else {\n setError(message);\n setCheckoutState('error');\n }\n return { success: false };\n }\n },\n [billingAccountId, apiGatewayUrl, authToken, purchaseType]\n );\n\n const restorePurchases = useCallback(async (): Promise<{ success: boolean }> => {\n setIsLoading(true);\n setError(null);\n try {\n await restoreNativePurchases();\n return { success: true };\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Restore failed');\n return { success: false };\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n return {\n isAvailable: isNativeIAPAvailable(),\n products,\n checkoutState,\n error,\n isLoading,\n loadProducts,\n purchaseProduct,\n restorePurchases,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useNativeCheckout.js","names":[],"sources":["../../../../../src/billing/modules/checkout/hooks/useNativeCheckout.ts"],"sourcesContent":["/**\n * Native IAP checkout hook — Apple StoreKit / Google Play Billing.\n *\n * Manages the full native purchase lifecycle:\n * 1. Load product info from the App Store / Play Store\n * 2. Trigger the native payment sheet\n * 3. Send the receipt / JWS / purchase token to the backend for validation\n * 4. Acknowledge the transaction after the backend confirms it\n *\n * The backend endpoint POST /rest/billing/iap/validate validates with Apple\n * or Google servers and then activates the subscription or credits — no\n * RevenueCat or third-party account required.\n */\n\nimport { useState, useCallback, useEffect } from 'react';\nimport { Capacitor } from '@capacitor/core';\nimport {\n getNativeProducts,\n purchaseNativeProduct,\n acknowledgeNativePurchase,\n restoreNativePurchases,\n getNativePurchases,\n installNativeIAP,\n isNativeIAPAvailable,\n} from '../../../lib/native-purchases';\nimport type { PURCHASE_TYPE, Product, Transaction } from '@capgo/native-purchases';\nimport type { CheckoutState, PurchaseType } from '../types';\nimport { useBilling } from '../../../providers/BillingProvider';\nimport { normalizeGlobalGatewayBaseUrl } from '../../../shared/utils/gatewayGraphql';\n\nexport type { Product, Transaction };\n\ninterface UseNativeCheckoutOptions {\n billingAccountId?: string;\n purchaseType?: PurchaseType;\n /** Store product identifier — passed to getProducts to load the specific product. */\n productId?: string;\n}\n\ninterface UseNativeCheckoutResult {\n isAvailable: boolean;\n products: Product[];\n checkoutState: CheckoutState;\n error: string | null;\n isLoading: boolean;\n loadProducts: (productIdentifiers?: string[]) => Promise<void>;\n purchaseProduct: (product: Product) => Promise<{ success: boolean }>;\n restorePurchases: () => Promise<{ success: boolean }>;\n}\n\nexport function useNativeCheckout({\n billingAccountId,\n purchaseType,\n productId,\n}: UseNativeCheckoutOptions = {}): UseNativeCheckoutResult {\n const { apiGatewayUrl, authToken } = useBilling();\n const [products, setProducts] = useState<Product[]>([]);\n const [checkoutState, setCheckoutState] = useState<CheckoutState>('idle');\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const validateTransaction = useCallback(\n async (\n transaction: Transaction,\n product?: Product,\n appAccountToken?: string\n ): Promise<void> => {\n if (!billingAccountId) throw new Error('No billing account selected');\n\n const gatewayBase = normalizeGlobalGatewayBaseUrl(apiGatewayUrl) ?? '';\n const iapValidateUrl = `${gatewayBase}/global/rest/billing/iap/validate`;\n const platform = Capacitor.getPlatform();\n if (platform !== 'ios' && platform !== 'android') {\n throw new Error('Native purchases require an iOS or Android app');\n }\n\n const response = await fetch(iapValidateUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n },\n body: JSON.stringify({\n platform,\n transactionId: transaction.transactionId,\n productIdentifier: transaction.productIdentifier,\n receipt: transaction.receipt,\n jwsRepresentation: transaction.jwsRepresentation,\n purchaseToken: transaction.purchaseToken,\n appAccountToken: appAccountToken ?? transaction.appAccountToken ?? undefined,\n billingAccountId,\n purchaseType: purchaseType ?? 'PLAN',\n // Plans are recurring subscriptions. Credits and addons are\n // one-time in-app products; the backend activates their entitlement\n // after validating the store transaction.\n nativePurchaseType: purchaseType === 'PLAN' ? 'SUBS' : 'INAPP',\n price: product?.price,\n currency: product?.currencyCode,\n }),\n });\n\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as { message?: string };\n throw new Error(body.message ?? `Validation failed (${response.status})`);\n }\n\n const purchaseToken = transaction.purchaseToken ?? transaction.transactionId;\n await acknowledgeNativePurchase(purchaseToken);\n },\n [apiGatewayUrl, authToken, billingAccountId, purchaseType]\n );\n\n useEffect(() => {\n if (!isNativeIAPAvailable() || !billingAccountId) return;\n void installNativeIAP((transaction) => {\n void validateTransaction(transaction).catch(() => {\n // The store webhook remains authoritative; the next restore retries this\n // transaction without granting anything before server validation succeeds.\n });\n });\n }, [billingAccountId, validateTransaction]);\n\n const loadProducts = useCallback(\n async (productIdentifiers?: string[]) => {\n if (!isNativeIAPAvailable()) return;\n const ids = productIdentifiers ?? (productId ? [productId] : []);\n if (ids.length === 0) return;\n setIsLoading(true);\n setError(null);\n try {\n const productType = (purchaseType === 'PLAN' ? 'subs' : 'inapp') as PURCHASE_TYPE;\n const result = await getNativeProducts(ids, productType);\n setProducts(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load products');\n } finally {\n setIsLoading(false);\n }\n },\n [productId, purchaseType]\n );\n\n const purchaseProduct = useCallback(\n async (product: Product): Promise<{ success: boolean }> => {\n if (!billingAccountId) {\n setError('No billing account selected');\n return { success: false };\n }\n\n setCheckoutState('processing');\n setError(null);\n\n let transaction: Transaction | undefined;\n try {\n // Trigger native payment sheet — deferred ack so we validate server-side first.\n // planIdentifier is required for Android subscriptions (base plan ID from Play Console).\n // Consumable products can be purchased again after entitlement grant;\n // this applies to credits and time-limited addons on Android.\n const isConsumable = purchaseType === 'CREDITS' || purchaseType === 'ADDON';\n // appAccountToken: UUID passed to Apple/Google so they echo it in server notifications,\n // allowing us to link renewals/cancellations to this billing account.\n // iOS requires UUID format; Android (obfuscatedExternalAccountId) accepts any string ≤ 64 chars.\n const appAccountToken = crypto.randomUUID();\n transaction = await purchaseNativeProduct(product.identifier, {\n autoAcknowledgePurchases: false,\n isConsumable,\n productType: (purchaseType === 'PLAN' ? 'subs' : 'inapp') as PURCHASE_TYPE,\n planIdentifier:\n purchaseType === 'PLAN' ? (product.planIdentifier ?? undefined) : undefined,\n appAccountToken,\n });\n\n // Validate and grant only through the same backend-owned path used by\n // restored/interrupted transactions and store notifications.\n await validateTransaction(transaction, product, appAccountToken);\n\n setCheckoutState('success');\n return { success: true };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Purchase failed';\n // User cancellation is not an error worth surfacing as \"error\" state\n if (\n message.toLowerCase().includes('cancel') ||\n message.toLowerCase().includes('dismiss') ||\n message.toLowerCase().includes('abort')\n ) {\n setCheckoutState('idle');\n } else {\n setError(message);\n setCheckoutState('error');\n }\n return { success: false };\n }\n },\n [purchaseType, validateTransaction]\n );\n\n const restorePurchases = useCallback(async (): Promise<{ success: boolean }> => {\n setIsLoading(true);\n setError(null);\n try {\n await restoreNativePurchases();\n const restored = await getNativePurchases({\n productType: (purchaseType === 'PLAN' ? 'subs' : 'inapp') as PURCHASE_TYPE,\n });\n for (const transaction of restored) {\n await validateTransaction(transaction);\n }\n return { success: true };\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Restore failed');\n return { success: false };\n } finally {\n setIsLoading(false);\n }\n }, [validateTransaction]);\n\n return {\n isAvailable: isNativeIAPAvailable(),\n products,\n checkoutState,\n error,\n isLoading,\n loadProducts,\n purchaseProduct,\n restorePurchases,\n };\n}\n"],"mappings":"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"}
|
|
@@ -136,7 +136,7 @@ var et = () => {
|
|
|
136
136
|
quotaMode: "dedicated"
|
|
137
137
|
};
|
|
138
138
|
});
|
|
139
|
-
e.length > 0 && (xt(e),
|
|
139
|
+
e.length > 0 && (xt(e), Jt().then((e) => {
|
|
140
140
|
let t = e.data?.getActiveSubscriptions?.find((e) => e.planId === D);
|
|
141
141
|
t && Ct(t.id);
|
|
142
142
|
}), pt.length > 1 && yt(!0));
|
|
@@ -157,39 +157,39 @@ var et = () => {
|
|
|
157
157
|
}), { data: R } = ie({
|
|
158
158
|
variables: { id: g },
|
|
159
159
|
skip: !T || !g
|
|
160
|
-
}), zt = u(() => {
|
|
160
|
+
}), zt = E === "PLAN" ? I?.getPlan?.nativeProductId ?? D : E === "ADDON" && !w ? L?.getSelectedAddons?.[0]?.nativeProductId ?? D : void 0, Bt = u(() => {
|
|
161
161
|
let e = R?.getStoreOrder?.lineItems;
|
|
162
162
|
return Array.isArray(e) ? e : [];
|
|
163
|
-
}, [R]), z = T &&
|
|
163
|
+
}, [R]), z = T && Bt.some((e) => String(e.itemType).toUpperCase() === "PHYSICAL"), Vt = Me(R?.getStoreOrder?.currency), [B, Ht] = d({
|
|
164
164
|
shippingAddressId: null,
|
|
165
165
|
shippingMethodId: null,
|
|
166
166
|
shippingCost: 0,
|
|
167
167
|
destinationCountry: null
|
|
168
|
-
}), [
|
|
168
|
+
}), [Ut] = ue(), { data: Wt, loading: Gt } = s({
|
|
169
169
|
variables: { billingAccountId: F.billingAccount?.id },
|
|
170
170
|
skip: !F.billingAccount?.id
|
|
171
|
-
}), { data:
|
|
171
|
+
}), { data: Kt, loading: qt, refetch: Jt } = o({
|
|
172
172
|
variables: { billingAccountId: F.billingAccount?.id },
|
|
173
173
|
skip: !F.billingAccount?.id || E !== "ADDON" && E !== "PLAN" || T
|
|
174
|
-
}), V = u(() =>
|
|
174
|
+
}), V = u(() => Kt?.getActiveSubscriptions ?? [], [Kt]), H = u(() => !F.selectedSubscriptionId || V.length === 0 ? null : V.find((e) => e.id === F.selectedSubscriptionId) ?? null, [F.selectedSubscriptionId, V]), U = F.items[0]?.type === "CREDITS" ? F.items[0].quantity : 100, { data: Yt, loading: Xt } = te({
|
|
175
175
|
variables: {
|
|
176
176
|
creditAmount: U,
|
|
177
177
|
currency: F.selectedCurrency || "USD"
|
|
178
178
|
},
|
|
179
179
|
skip: E !== "CREDITS"
|
|
180
|
-
}), W = u(() =>
|
|
180
|
+
}), W = u(() => Yt?.getCostOfCredits?.amount && U > 0 ? Yt.getCostOfCredits.amount / U : .01, [Yt, U]), G = u(() => Wt?.getPaymentMethods ?? [], [Wt]), K = u(() => Pt?.myBillingAccounts ?? [], [Pt]), q = u(() => {
|
|
181
181
|
if (!F.billingAccount) return;
|
|
182
182
|
let e = K.find((e) => e.id === F.billingAccount?.id)?.billingAddresses;
|
|
183
183
|
if (e && e.length > 0) return e[0]?.country || void 0;
|
|
184
|
-
}, [F.billingAccount, K]), [
|
|
184
|
+
}, [F.billingAccount, K]), [Zt, Qt] = d(null);
|
|
185
185
|
l(() => {
|
|
186
|
-
if (q) if (q === "IN") F.selectedCurrency !== "INR" && F.setCurrency("INR"), jt &&
|
|
186
|
+
if (q) if (q === "IN") F.selectedCurrency !== "INR" && F.setCurrency("INR"), jt && Zt !== q && F.selectedProvider !== "CREDITS" && (F.setPaymentProvider("RAZORPAY"), Qt(q));
|
|
187
187
|
else {
|
|
188
188
|
if (F.selectedCurrency === "INR") {
|
|
189
189
|
let e = F.billingAccount?.currency, t = e && e !== "INR" ? e : "USD";
|
|
190
190
|
F.setCurrency(t);
|
|
191
191
|
}
|
|
192
|
-
F.selectedProvider === "RAZORPAY" && (F.setPaymentProvider("STRIPE"),
|
|
192
|
+
F.selectedProvider === "RAZORPAY" && (F.setPaymentProvider("STRIPE"), Qt(q));
|
|
193
193
|
}
|
|
194
194
|
}, [
|
|
195
195
|
q,
|
|
@@ -199,40 +199,40 @@ var et = () => {
|
|
|
199
199
|
F.setPaymentProvider,
|
|
200
200
|
F.billingAccount?.currency,
|
|
201
201
|
jt,
|
|
202
|
-
|
|
202
|
+
Zt
|
|
203
203
|
]);
|
|
204
|
-
let { billingAccount:
|
|
204
|
+
let { billingAccount: $t, canPayWithCredits: en, hasEnoughCredits: tn, selectedCurrency: J, selectedPaymentMethodId: nn, selectedProvider: rn, setCurrency: Y, setPaymentProvider: X, setSelectedPaymentMethodId: an } = F;
|
|
205
205
|
l(() => {
|
|
206
|
-
if (
|
|
207
|
-
let e =
|
|
206
|
+
if (!$t?.currency || q === "IN") return;
|
|
207
|
+
let e = $t.currency;
|
|
208
208
|
e !== "INR" && J !== e && Y(e);
|
|
209
209
|
}, [
|
|
210
210
|
q,
|
|
211
|
-
|
|
211
|
+
$t,
|
|
212
212
|
J,
|
|
213
213
|
Y
|
|
214
214
|
]), l(() => {
|
|
215
|
-
if (!(
|
|
216
|
-
if (
|
|
217
|
-
X("CREDITS"),
|
|
215
|
+
if (!(rn !== "AUTO" && rn !== null)) {
|
|
216
|
+
if (en && tn) {
|
|
217
|
+
X("CREDITS"), an(null);
|
|
218
218
|
return;
|
|
219
219
|
}
|
|
220
|
-
if (G.length > 0 && !
|
|
220
|
+
if (G.length > 0 && !nn) {
|
|
221
221
|
let e = G.find((e) => e.isDefault && e.isVerified), t = G.find((e) => e.isVerified), n = e || t;
|
|
222
222
|
if (n) {
|
|
223
|
-
|
|
223
|
+
an(n.id), n.razorpayPaymentMethodId ? X("RAZORPAY") : n.stripePaymentMethodId && X("STRIPE");
|
|
224
224
|
return;
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
}, [
|
|
229
|
-
$t,
|
|
230
229
|
en,
|
|
231
|
-
G,
|
|
232
230
|
tn,
|
|
231
|
+
G,
|
|
233
232
|
nn,
|
|
233
|
+
rn,
|
|
234
234
|
X,
|
|
235
|
-
|
|
235
|
+
an
|
|
236
236
|
]);
|
|
237
237
|
let [Z, Q] = d(!1);
|
|
238
238
|
l(() => {
|
|
@@ -395,7 +395,7 @@ var et = () => {
|
|
|
395
395
|
let $ = Ne(null);
|
|
396
396
|
l(() => {
|
|
397
397
|
if (z) if (B.shippingCost > 0) {
|
|
398
|
-
let e = F.selectedCurrency, t =
|
|
398
|
+
let e = F.selectedCurrency, t = Vt !== e && F.convertedAmount !== null ? B.shippingCost * F.conversionRate : B.shippingCost, n = $.current;
|
|
399
399
|
if (n && n.price === t && n.currency === e) return;
|
|
400
400
|
n === null ? F.addItem({
|
|
401
401
|
id: le,
|
|
@@ -416,7 +416,7 @@ var et = () => {
|
|
|
416
416
|
}, [
|
|
417
417
|
z,
|
|
418
418
|
B.shippingCost,
|
|
419
|
-
|
|
419
|
+
Vt,
|
|
420
420
|
F.selectedCurrency,
|
|
421
421
|
F.conversionRate,
|
|
422
422
|
F.convertedAmount,
|
|
@@ -491,7 +491,7 @@ var et = () => {
|
|
|
491
491
|
v?.billingAccountId,
|
|
492
492
|
b
|
|
493
493
|
]);
|
|
494
|
-
let
|
|
494
|
+
let on = !!(v?.upgradeFromSubscriptionId || v?.downgradeFromSubscriptionId);
|
|
495
495
|
l(() => {
|
|
496
496
|
w && C && S.length === 0 && !Z && _("/addons", { replace: !0 });
|
|
497
497
|
}, [
|
|
@@ -501,11 +501,11 @@ var et = () => {
|
|
|
501
501
|
Z,
|
|
502
502
|
_
|
|
503
503
|
]);
|
|
504
|
-
let
|
|
504
|
+
let sn = pe({
|
|
505
505
|
billingAccountId: F.billingAccount?.id,
|
|
506
506
|
purchaseType: E,
|
|
507
|
-
productId:
|
|
508
|
-
}),
|
|
507
|
+
productId: zt
|
|
508
|
+
}), cn = c(async () => {
|
|
509
509
|
if (!F.billingAccount) return;
|
|
510
510
|
let e = _t.current;
|
|
511
511
|
if (_t.current = !1, !e && !De(F.billingAccount)) {
|
|
@@ -513,12 +513,12 @@ var et = () => {
|
|
|
513
513
|
return;
|
|
514
514
|
}
|
|
515
515
|
if (j(null), z) try {
|
|
516
|
-
let e = (await
|
|
516
|
+
let e = (await Ut({ variables: { input: {
|
|
517
517
|
orderId: g,
|
|
518
518
|
shippingMethodId: B.shippingMethodId,
|
|
519
519
|
...B.shippingAddressId ? { shippingAddressId: B.shippingAddressId } : {}
|
|
520
520
|
} } })).data?.setStoreOrderShipping?.shippingCost;
|
|
521
|
-
typeof e == "number" && e !== B.shippingCost &&
|
|
521
|
+
typeof e == "number" && e !== B.shippingCost && Ht((t) => ({
|
|
522
522
|
...t,
|
|
523
523
|
shippingCost: e
|
|
524
524
|
}));
|
|
@@ -588,9 +588,9 @@ var et = () => {
|
|
|
588
588
|
z,
|
|
589
589
|
B,
|
|
590
590
|
g,
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
]),
|
|
591
|
+
Vt,
|
|
592
|
+
Ut
|
|
593
|
+
]), ln = c((e) => {
|
|
594
594
|
y("billing.payment.succeeded", {
|
|
595
595
|
route: "/billing/checkout",
|
|
596
596
|
entityId: A?.paymentId ?? A?.orderId,
|
|
@@ -600,7 +600,7 @@ var et = () => {
|
|
|
600
600
|
y,
|
|
601
601
|
A?.orderId,
|
|
602
602
|
A?.paymentId
|
|
603
|
-
]),
|
|
603
|
+
]), un = c((e) => {
|
|
604
604
|
y("billing.payment.failed", {
|
|
605
605
|
route: "/billing/checkout",
|
|
606
606
|
entityId: A?.paymentId ?? A?.orderId,
|
|
@@ -611,20 +611,20 @@ var et = () => {
|
|
|
611
611
|
y,
|
|
612
612
|
A?.orderId,
|
|
613
613
|
A?.paymentId
|
|
614
|
-
]),
|
|
614
|
+
]), dn = c((e) => {
|
|
615
615
|
F.updateItemQuantity("credits-purchase", e);
|
|
616
616
|
}, [F]);
|
|
617
617
|
if (!it.canProcessPayment) return /* @__PURE__ */ p(t, { message: "You don't have permission to make purchases." });
|
|
618
|
-
if (fe()) return /* @__PURE__ */ p(ge, {
|
|
618
|
+
if (fe() && (E === "PLAN" || E === "ADDON" && !w) && zt) return /* @__PURE__ */ p(ge, {
|
|
619
619
|
purchaseType: E,
|
|
620
|
-
productId:
|
|
620
|
+
productId: zt,
|
|
621
621
|
billingAccountId: F.billingAccount?.id,
|
|
622
|
-
nativeCheckout:
|
|
622
|
+
nativeCheckout: sn,
|
|
623
623
|
onBack: () => _("dashboard")
|
|
624
624
|
});
|
|
625
|
-
let
|
|
625
|
+
let fn = Ft || Lt && E === "PLAN" || Rt && E === "ADDON" && !w || w && !C;
|
|
626
626
|
if (w && C && S.length === 0 && !Z) return null;
|
|
627
|
-
let
|
|
627
|
+
let pn = () => {
|
|
628
628
|
if (w) {
|
|
629
629
|
let e = F.items.length;
|
|
630
630
|
return `Purchase ${e} Add-on${e === 1 ? "" : "s"}`;
|
|
@@ -635,7 +635,7 @@ var et = () => {
|
|
|
635
635
|
case "ADDON": return "Purchase Add-on";
|
|
636
636
|
default: return "Checkout";
|
|
637
637
|
}
|
|
638
|
-
},
|
|
638
|
+
}, mn = () => {
|
|
639
639
|
switch (E) {
|
|
640
640
|
case "CREDITS": return /* @__PURE__ */ p(Re, { className: "size-6" });
|
|
641
641
|
case "PLAN": return /* @__PURE__ */ p(Ve, { className: "size-6" });
|
|
@@ -643,7 +643,7 @@ var et = () => {
|
|
|
643
643
|
default: return /* @__PURE__ */ p(We, { className: "size-6" });
|
|
644
644
|
}
|
|
645
645
|
};
|
|
646
|
-
if (
|
|
646
|
+
if (fn) return /* @__PURE__ */ p("div", {
|
|
647
647
|
className: "flex items-center justify-center min-h-[400px]",
|
|
648
648
|
children: /* @__PURE__ */ m("div", {
|
|
649
649
|
className: "text-center space-y-4",
|
|
@@ -1039,8 +1039,8 @@ var et = () => {
|
|
|
1039
1039
|
publishableKey: at || kt?.stripePublishableKey || "",
|
|
1040
1040
|
amount: Math.round((A.total ?? F.total) * 100),
|
|
1041
1041
|
currency: A.currency || F.selectedCurrency,
|
|
1042
|
-
onSuccess:
|
|
1043
|
-
onError:
|
|
1042
|
+
onSuccess: ln,
|
|
1043
|
+
onError: un,
|
|
1044
1044
|
onCancel: () => k("select"),
|
|
1045
1045
|
isCompletingExistingPayment: !!F.selectedPaymentMethodId
|
|
1046
1046
|
})
|
|
@@ -1072,8 +1072,8 @@ var et = () => {
|
|
|
1072
1072
|
email: A.prefillEmail,
|
|
1073
1073
|
contact: A.prefillContact
|
|
1074
1074
|
},
|
|
1075
|
-
onSuccess: (e) =>
|
|
1076
|
-
onError:
|
|
1075
|
+
onSuccess: (e) => ln(e.razorpay_payment_id),
|
|
1076
|
+
onError: un,
|
|
1077
1077
|
onCancel: () => k("select")
|
|
1078
1078
|
})]
|
|
1079
1079
|
})
|
|
@@ -1094,10 +1094,10 @@ var et = () => {
|
|
|
1094
1094
|
className: "flex items-center gap-3 mb-6",
|
|
1095
1095
|
children: [/* @__PURE__ */ p("div", {
|
|
1096
1096
|
className: "p-2 rounded-lg bg-[var(--color-accent-soft)] text-text-link",
|
|
1097
|
-
children:
|
|
1097
|
+
children: mn()
|
|
1098
1098
|
}), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h1", {
|
|
1099
1099
|
className: "text-2xl font-bold text-text-primary",
|
|
1100
|
-
children:
|
|
1100
|
+
children: pn()
|
|
1101
1101
|
}), /* @__PURE__ */ p("p", {
|
|
1102
1102
|
className: "text-sm text-text-secondary",
|
|
1103
1103
|
children: "Complete your purchase securely"
|
|
@@ -1168,10 +1168,10 @@ var et = () => {
|
|
|
1168
1168
|
className: "rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6",
|
|
1169
1169
|
children: /* @__PURE__ */ p(be, {
|
|
1170
1170
|
value: F.items[0].quantity,
|
|
1171
|
-
onChange:
|
|
1171
|
+
onChange: dn,
|
|
1172
1172
|
costPerCredit: W,
|
|
1173
1173
|
currency: F.selectedCurrency,
|
|
1174
|
-
disabled:
|
|
1174
|
+
disabled: Xt
|
|
1175
1175
|
})
|
|
1176
1176
|
}),
|
|
1177
1177
|
/* @__PURE__ */ m("div", {
|
|
@@ -1181,19 +1181,19 @@ var et = () => {
|
|
|
1181
1181
|
selectedAccountId: F.billingAccount?.id ?? null,
|
|
1182
1182
|
onSelect: F.setBillingAccount,
|
|
1183
1183
|
isLoading: Ft,
|
|
1184
|
-
disabled:
|
|
1185
|
-
disabledMessage:
|
|
1184
|
+
disabled: on,
|
|
1185
|
+
disabledMessage: on ? "Billing account is locked for plan changes" : void 0
|
|
1186
1186
|
}), E === "ADDON" && !T && F.billingAccount && /* @__PURE__ */ p(Ce, {
|
|
1187
1187
|
subscriptions: V,
|
|
1188
1188
|
selectedSubscriptionId: F.selectedSubscriptionId,
|
|
1189
1189
|
onSelect: F.setSelectedSubscriptionId,
|
|
1190
|
-
isLoading:
|
|
1190
|
+
isLoading: qt
|
|
1191
1191
|
})]
|
|
1192
1192
|
}),
|
|
1193
1193
|
z && /* @__PURE__ */ p(Oe, {
|
|
1194
1194
|
storeOrderId: g,
|
|
1195
1195
|
currency: F.selectedCurrency,
|
|
1196
|
-
onChange:
|
|
1196
|
+
onChange: Ht
|
|
1197
1197
|
}),
|
|
1198
1198
|
/* @__PURE__ */ m("div", {
|
|
1199
1199
|
className: "rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6 space-y-4",
|
|
@@ -1213,7 +1213,7 @@ var et = () => {
|
|
|
1213
1213
|
saveCard: F.saveCard,
|
|
1214
1214
|
onSaveCardChange: F.setSaveCard,
|
|
1215
1215
|
autoRenewEnabled: E === "PLAN" && F.autoRenew,
|
|
1216
|
-
isLoading:
|
|
1216
|
+
isLoading: Gt
|
|
1217
1217
|
}),
|
|
1218
1218
|
F.selectedProvider !== "CREDITS" && F.selectedProvider !== "AUTO" && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("div", { className: "border-t border-border-subtle" }), /* @__PURE__ */ p("div", {
|
|
1219
1219
|
className: "bg-bg-sunken p-4 rounded-button",
|
|
@@ -1385,8 +1385,8 @@ var et = () => {
|
|
|
1385
1385
|
}),
|
|
1386
1386
|
/* @__PURE__ */ p("button", {
|
|
1387
1387
|
type: "button",
|
|
1388
|
-
onClick:
|
|
1389
|
-
disabled: F.isProcessing || !F.billingAccount || F.items.length === 0 || F.selectedProvider === "CREDITS" && !
|
|
1388
|
+
onClick: cn,
|
|
1389
|
+
disabled: F.isProcessing || !F.billingAccount || F.items.length === 0 || F.selectedProvider === "CREDITS" && !tn || E === "ADDON" && !T && qt || E === "ADDON" && !T && V.length === 0 || E === "ADDON" && !T && !F.selectedSubscriptionId || z && (!B.shippingAddressId || !B.shippingMethodId),
|
|
1390
1390
|
className: "w-full px-6 py-4 rounded-lg bg-action-primary-bg text-action-primary-text font-semibold\n hover:bg-action-primary-bgHover disabled:opacity-50 disabled:cursor-not-allowed\n transition-colors flex items-center justify-center gap-2",
|
|
1391
1391
|
children: F.isProcessing ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(Be, { className: "size-5 animate-spin" }), "Processing…"] }) : F.selectedProvider === "CREDITS" ? "Pay with Credits" : "Proceed to Payment"
|
|
1392
1392
|
}),
|
|
@@ -1403,7 +1403,7 @@ var et = () => {
|
|
|
1403
1403
|
hasPhone: !!F.billingAccount.contactNumber?.trim(),
|
|
1404
1404
|
hasAddress: !!(F.billingAccount.billingAddresses?.[0]?.line1?.trim() && F.billingAccount.billingAddresses?.[0]?.postalCode?.trim()),
|
|
1405
1405
|
onCompleted: () => {
|
|
1406
|
-
_t.current = !0, gt(!1),
|
|
1406
|
+
_t.current = !0, gt(!1), cn(), It().then((e) => {
|
|
1407
1407
|
let t = (e.data?.myBillingAccounts ?? []).map($e).find((e) => e?.id === F.billingAccount?.id);
|
|
1408
1408
|
t && F.setBillingAccount(t);
|
|
1409
1409
|
});
|