@tagadapay/headless-sdk 1.8.0-rc.0 → 1.8.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/README.md +216 -1
- package/dist/core/client.d.ts +68 -0
- package/dist/core/client.js +71 -0
- package/dist/core/errors.d.ts +46 -0
- package/dist/core/errors.js +57 -0
- package/dist/core/helpers/autocomplete.d.ts +89 -0
- package/dist/core/helpers/autocomplete.js +186 -0
- package/dist/core/helpers/countries.d.ts +45 -0
- package/dist/core/helpers/countries.js +65 -0
- package/dist/core/helpers/currency.d.ts +26 -0
- package/dist/core/helpers/currency.js +72 -0
- package/dist/core/helpers/index.d.ts +5 -0
- package/dist/core/helpers/index.js +5 -0
- package/dist/core/helpers/iso3166.d.ts +28 -0
- package/dist/core/helpers/iso3166.js +84 -0
- package/dist/core/http.d.ts +27 -0
- package/dist/core/http.js +116 -0
- package/dist/core/index.d.ts +15 -0
- package/dist/core/index.js +13 -0
- package/dist/core/modules/catalog.d.ts +27 -0
- package/dist/core/modules/catalog.js +38 -0
- package/dist/core/modules/checkout.d.ts +268 -0
- package/dist/core/modules/checkout.js +470 -0
- package/dist/core/modules/customer.d.ts +33 -0
- package/dist/core/modules/customer.js +53 -0
- package/dist/core/modules/funnel.d.ts +38 -0
- package/dist/core/modules/funnel.js +138 -0
- package/dist/core/modules/offers.d.ts +137 -0
- package/dist/core/modules/offers.js +141 -0
- package/dist/core/modules/payment.d.ts +298 -0
- package/dist/core/modules/payment.js +701 -0
- package/dist/core/modules/rx.d.ts +162 -0
- package/dist/core/modules/rx.js +46 -0
- package/dist/core/types.d.ts +505 -0
- package/dist/core/types.js +5 -0
- package/dist/react/hooks/useCatalog.d.ts +25 -0
- package/dist/react/hooks/useCatalog.js +58 -0
- package/dist/react/hooks/useCheckout.d.ts +58 -0
- package/dist/react/hooks/useCheckout.js +177 -0
- package/dist/react/hooks/useCustomer.d.ts +28 -0
- package/dist/react/hooks/useCustomer.js +77 -0
- package/dist/react/hooks/useGoogleAutocomplete.d.ts +26 -0
- package/dist/react/hooks/useGoogleAutocomplete.js +70 -0
- package/dist/react/hooks/useISOData.d.ts +23 -0
- package/dist/react/hooks/useISOData.js +63 -0
- package/dist/react/hooks/useOffers.d.ts +134 -0
- package/dist/react/hooks/useOffers.js +171 -0
- package/dist/react/hooks/usePayment.d.ts +108 -0
- package/dist/react/hooks/usePayment.js +233 -0
- package/dist/react/hooks/useRx.d.ts +64 -0
- package/dist/react/hooks/useRx.js +145 -0
- package/dist/react/index.d.ts +22 -0
- package/dist/react/index.js +12 -0
- package/dist/react/internal/redirectGuard.d.ts +9 -0
- package/dist/react/internal/redirectGuard.js +25 -0
- package/dist/react/provider.d.ts +31 -0
- package/dist/react/provider.js +32 -0
- package/dist/stripe/StripeExpressButton.d.ts +30 -0
- package/dist/stripe/StripeExpressButton.js +32 -0
- package/dist/stripe/StripeExpressCheckout.d.ts +98 -0
- package/dist/stripe/StripeExpressCheckout.js +198 -0
- package/dist/stripe/index.d.ts +8 -0
- package/dist/stripe/index.js +15 -0
- package/dist/stripe/useStripeExpress.d.ts +54 -0
- package/dist/stripe/useStripeExpress.js +126 -0
- package/package.json +2 -3
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { TagadaError } from '../errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Initialize a funnel session from the SDK's current cart and produce a
|
|
4
|
+
* redirect URL into a funnel step.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors the WooCommerce checkout plugin
|
|
7
|
+
* (`public/assets/php/woocommerce/tagada-checkout-plugin.php`):
|
|
8
|
+
*
|
|
9
|
+
* 1. `POST /api/v1/cms/session/anonymous` — public, returns a CMS token.
|
|
10
|
+
* 2. `POST /api/v1/cms/session/v2/init` — uses the token, returns a CMS customer id.
|
|
11
|
+
* 3. `POST /api/v1/funnel/initialize` — creates the funnel session.
|
|
12
|
+
* 4. `POST /api/v1/funnel/navigate` — fires an `INIT_CHECKOUT` event and returns `{ url }`.
|
|
13
|
+
*
|
|
14
|
+
* Steps 1–3 are cached on the module instance, so repeat `navigate()` calls in
|
|
15
|
+
* the same page only fire step 4.
|
|
16
|
+
*
|
|
17
|
+
* **Prerequisite**: the SDK must have a loaded `CheckoutSession`
|
|
18
|
+
* (`sdk.checkout.loadSession(...)`). The cart is sourced from `session.items`,
|
|
19
|
+
* the currency from `session.currency`, the customer email from
|
|
20
|
+
* `session.customer.email`, and the promotion code from `session.promotionCode`.
|
|
21
|
+
*/
|
|
22
|
+
export class FunnelModule {
|
|
23
|
+
constructor(http, storeId, checkout, accountId) {
|
|
24
|
+
this.http = http;
|
|
25
|
+
this.storeId = storeId;
|
|
26
|
+
this.checkout = checkout;
|
|
27
|
+
this.accountId = accountId;
|
|
28
|
+
}
|
|
29
|
+
async navigate(input) {
|
|
30
|
+
const session = this.checkout.getCurrentSession();
|
|
31
|
+
if (!session) {
|
|
32
|
+
throw new TagadaError('No checkout session loaded. Call sdk.checkout.loadSession(...) before sdk.funnel.navigate(...).', 'no_cart_loaded');
|
|
33
|
+
}
|
|
34
|
+
const accountId = input.accountId ?? this.accountId;
|
|
35
|
+
if (!accountId) {
|
|
36
|
+
throw new TagadaError('accountId is required for funnel.navigate(). Set it on createHeadlessClient({ accountId }) or pass it per call.', 'missing_account_id');
|
|
37
|
+
}
|
|
38
|
+
const currentUrl = input.currentUrl ?? (typeof globalThis !== 'undefined' ? globalThis.location?.href : undefined);
|
|
39
|
+
await this.ensureCmsSession(session, accountId, input);
|
|
40
|
+
const funnelSessionId = await this.initializeFunnel({
|
|
41
|
+
funnelId: input.funnelId,
|
|
42
|
+
stepId: input.stepId,
|
|
43
|
+
accountId,
|
|
44
|
+
currentUrl,
|
|
45
|
+
});
|
|
46
|
+
const url = await this.runNavigate({
|
|
47
|
+
funnelSessionId,
|
|
48
|
+
stepId: input.stepId,
|
|
49
|
+
session,
|
|
50
|
+
input,
|
|
51
|
+
currentUrl,
|
|
52
|
+
});
|
|
53
|
+
return { url, funnelSessionId };
|
|
54
|
+
}
|
|
55
|
+
// -------------------------------------------------------------------------
|
|
56
|
+
// Internals
|
|
57
|
+
// -------------------------------------------------------------------------
|
|
58
|
+
async ensureCmsSession(session, accountId, input) {
|
|
59
|
+
if (this._cmsToken && this._cmsSessionId && this._cmsCustomerId)
|
|
60
|
+
return;
|
|
61
|
+
const anon = await this.http.post('/api/v1/cms/session/anonymous', { storeId: this.storeId, role: 'anonymous', draft: false });
|
|
62
|
+
this._cmsToken = anon.token;
|
|
63
|
+
this._cmsSessionId = anon.sessionId;
|
|
64
|
+
const init = await this.http.post('/api/v1/cms/session/v2/init', {
|
|
65
|
+
storeId: this.storeId,
|
|
66
|
+
accountId,
|
|
67
|
+
customerId: 'anon_placeholder',
|
|
68
|
+
browserLocale: input.customer?.locale ?? defaultLocale(),
|
|
69
|
+
userAgent: defaultUserAgent(),
|
|
70
|
+
queryCurrency: input.customer?.currency ?? session.currency,
|
|
71
|
+
queryLocale: input.customer?.locale,
|
|
72
|
+
}, { token: this._cmsToken });
|
|
73
|
+
this._cmsCustomerId = init.customer.id;
|
|
74
|
+
}
|
|
75
|
+
async initializeFunnel(args) {
|
|
76
|
+
const res = await this.http.post('/api/v1/funnel/initialize', {
|
|
77
|
+
cmsSession: {
|
|
78
|
+
customerId: this._cmsCustomerId,
|
|
79
|
+
sessionId: this._cmsSessionId,
|
|
80
|
+
storeId: this.storeId,
|
|
81
|
+
accountId: args.accountId,
|
|
82
|
+
},
|
|
83
|
+
funnelId: args.funnelId,
|
|
84
|
+
entryStepId: args.stepId,
|
|
85
|
+
funnelStepId: args.stepId,
|
|
86
|
+
currentUrl: args.currentUrl,
|
|
87
|
+
draft: false,
|
|
88
|
+
}, { token: this._cmsToken });
|
|
89
|
+
return res.context.sessionId;
|
|
90
|
+
}
|
|
91
|
+
async runNavigate(args) {
|
|
92
|
+
const { funnelSessionId, stepId, session, input, currentUrl } = args;
|
|
93
|
+
const lineItems = session.items.map((i) => ({
|
|
94
|
+
variantId: i.variantId,
|
|
95
|
+
priceId: i.priceId,
|
|
96
|
+
quantity: i.quantity,
|
|
97
|
+
}));
|
|
98
|
+
const discountCodes = input.discountCodes ??
|
|
99
|
+
(session.promotionCode ? [session.promotionCode] : undefined);
|
|
100
|
+
const customer = {
|
|
101
|
+
email: input.customer?.email ?? session.customer?.email,
|
|
102
|
+
currency: input.customer?.currency ?? session.currency,
|
|
103
|
+
locale: input.customer?.locale,
|
|
104
|
+
};
|
|
105
|
+
const res = await this.http.post('/api/v1/funnel/navigate', {
|
|
106
|
+
sessionId: funnelSessionId,
|
|
107
|
+
currentUrl,
|
|
108
|
+
funnelStepId: stepId,
|
|
109
|
+
fireAndForget: false,
|
|
110
|
+
event: {
|
|
111
|
+
type: 'INIT_CHECKOUT',
|
|
112
|
+
data: {
|
|
113
|
+
checkoutInit: {
|
|
114
|
+
cartToken: session.id,
|
|
115
|
+
lineItems,
|
|
116
|
+
customer,
|
|
117
|
+
returnUrl: input.returnUrl,
|
|
118
|
+
storeId: this.storeId,
|
|
119
|
+
metadata: input.metadata,
|
|
120
|
+
discountCodes,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
}, { token: this._cmsToken });
|
|
125
|
+
return res.result.url;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function defaultLocale() {
|
|
129
|
+
if (typeof navigator !== 'undefined' && navigator.language)
|
|
130
|
+
return navigator.language;
|
|
131
|
+
return 'en-US';
|
|
132
|
+
}
|
|
133
|
+
function defaultUserAgent() {
|
|
134
|
+
if (typeof navigator !== 'undefined' && navigator.userAgent)
|
|
135
|
+
return navigator.userAgent;
|
|
136
|
+
return 'tagadapay-headless-sdk';
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=funnel.js.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { HttpClient } from '../http.js';
|
|
2
|
+
import type { Offer, OfferPreview, OfferPayResult, ProcessPaymentResult } from '../types.js';
|
|
3
|
+
import type { PaymentModule } from './payment.js';
|
|
4
|
+
/**
|
|
5
|
+
* Offers — upsells, downsells, order bumps, and post-purchase offers.
|
|
6
|
+
*
|
|
7
|
+
* Endpoints align with the plugin-sdk patterns:
|
|
8
|
+
* GET /api/v1/offers/:id — single offer
|
|
9
|
+
* GET /api/v1/stores/:storeId/offers — list store offers
|
|
10
|
+
* POST /api/v1/offers/:offerId/preview — preview pricing
|
|
11
|
+
* POST /api/v1/offers/:offerId/pay-preview — pay a previewed offer (one-click)
|
|
12
|
+
* POST /api/v1/checkout-sessions/:id/toggle-order-bump — toggle order bump
|
|
13
|
+
* GET /api/v1/post-purchase/:orderId/offers — post-purchase offers for an order
|
|
14
|
+
* POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/accept — accept
|
|
15
|
+
* POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/decline — decline
|
|
16
|
+
*/
|
|
17
|
+
export declare class OffersModule {
|
|
18
|
+
private readonly http;
|
|
19
|
+
private readonly storeId;
|
|
20
|
+
private readonly payment?;
|
|
21
|
+
constructor(http: HttpClient, storeId: string, payment?: PaymentModule | undefined);
|
|
22
|
+
/** Get a single offer by ID. */
|
|
23
|
+
getOffer(offerId: string): Promise<Offer>;
|
|
24
|
+
/** List offers for the current store. Optionally filter by type or a set of IDs. */
|
|
25
|
+
listOffers(opts?: {
|
|
26
|
+
type?: 'upsell' | 'orderbump';
|
|
27
|
+
ids?: string[];
|
|
28
|
+
}): Promise<Offer[]>;
|
|
29
|
+
/** Preview offer pricing. Returns line items with amounts and totals. */
|
|
30
|
+
previewOffer(opts: {
|
|
31
|
+
offerId: string;
|
|
32
|
+
currency?: string;
|
|
33
|
+
lineItems?: Array<{
|
|
34
|
+
lineItemId?: string;
|
|
35
|
+
productId?: string;
|
|
36
|
+
variantId: string;
|
|
37
|
+
quantity: number;
|
|
38
|
+
}>;
|
|
39
|
+
}): Promise<OfferPreview>;
|
|
40
|
+
/**
|
|
41
|
+
* Pay a previously previewed offer (one-click charge).
|
|
42
|
+
* Used after a main order so the stored payment instrument is reused.
|
|
43
|
+
*
|
|
44
|
+
* **Low-level API.** Returns the raw `OfferPayResult` — `requireAction`,
|
|
45
|
+
* polling, and 3DS redirects are NOT handled. For most cases, use
|
|
46
|
+
* {@link processOfferPayment} which orchestrates the full lifecycle.
|
|
47
|
+
*/
|
|
48
|
+
payPreviewedOffer(opts: {
|
|
49
|
+
offerId: string;
|
|
50
|
+
mainOrderId: string;
|
|
51
|
+
currency?: string;
|
|
52
|
+
lineItems?: Array<{
|
|
53
|
+
lineItemId?: string;
|
|
54
|
+
productId?: string;
|
|
55
|
+
variantId: string;
|
|
56
|
+
quantity: number;
|
|
57
|
+
}>;
|
|
58
|
+
returnUrl?: string;
|
|
59
|
+
paymentInstrumentId?: string;
|
|
60
|
+
}): Promise<OfferPayResult>;
|
|
61
|
+
/**
|
|
62
|
+
* One-click upsell with full lifecycle handling.
|
|
63
|
+
*
|
|
64
|
+
* Like `payment.processPayment()` but for previewed offers: charges the
|
|
65
|
+
* stored instrument from `mainOrderId`, runs any 3DS challenge or bank
|
|
66
|
+
* redirect, polls until terminal, and returns a typed
|
|
67
|
+
* `ProcessPaymentResult` (`succeeded` / `requires_redirect` /
|
|
68
|
+
* `failed` / `pending`).
|
|
69
|
+
*
|
|
70
|
+
* Use this instead of the lower-level `payPreviewedOffer()` whenever you
|
|
71
|
+
* don't need to inspect the raw `OfferPayResult` shape — which is most
|
|
72
|
+
* of the time.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const result = await tagada.offers.processOfferPayment({
|
|
77
|
+
* offerId: 'offer_xxx',
|
|
78
|
+
* mainOrderId: order.id,
|
|
79
|
+
* returnUrl: window.location.href,
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* switch (result.status) {
|
|
83
|
+
* case 'succeeded':
|
|
84
|
+
* window.location.href = '/upsell-2';
|
|
85
|
+
* break;
|
|
86
|
+
* case 'requires_redirect':
|
|
87
|
+
* window.location.href = result.redirectUrl;
|
|
88
|
+
* break;
|
|
89
|
+
* case 'failed':
|
|
90
|
+
* showError(result.error);
|
|
91
|
+
* break;
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
processOfferPayment(opts: {
|
|
96
|
+
offerId: string;
|
|
97
|
+
mainOrderId: string;
|
|
98
|
+
currency?: string;
|
|
99
|
+
lineItems?: Array<{
|
|
100
|
+
lineItemId?: string;
|
|
101
|
+
productId?: string;
|
|
102
|
+
variantId: string;
|
|
103
|
+
quantity: number;
|
|
104
|
+
}>;
|
|
105
|
+
returnUrl?: string;
|
|
106
|
+
paymentInstrumentId?: string;
|
|
107
|
+
}): Promise<ProcessPaymentResult>;
|
|
108
|
+
/** Toggle an order bump on/off within a checkout session. */
|
|
109
|
+
toggleOrderBump(opts: {
|
|
110
|
+
checkoutSessionId: string;
|
|
111
|
+
orderBumpOfferId: string;
|
|
112
|
+
selected: boolean;
|
|
113
|
+
}): Promise<unknown>;
|
|
114
|
+
/** List post-purchase offers for an order. */
|
|
115
|
+
listPostPurchaseOffers(orderId: string): Promise<Offer[]>;
|
|
116
|
+
/** Accept a post-purchase offer. */
|
|
117
|
+
acceptPostPurchaseOffer(opts: {
|
|
118
|
+
orderId: string;
|
|
119
|
+
offerId: string;
|
|
120
|
+
items?: Array<{
|
|
121
|
+
variantId: string;
|
|
122
|
+
quantity: number;
|
|
123
|
+
}>;
|
|
124
|
+
}): Promise<{
|
|
125
|
+
success: boolean;
|
|
126
|
+
error?: string;
|
|
127
|
+
}>;
|
|
128
|
+
/** Decline a post-purchase offer. */
|
|
129
|
+
declinePostPurchaseOffer(opts: {
|
|
130
|
+
orderId: string;
|
|
131
|
+
offerId: string;
|
|
132
|
+
}): Promise<{
|
|
133
|
+
success: boolean;
|
|
134
|
+
error?: string;
|
|
135
|
+
}>;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=offers.d.ts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offers — upsells, downsells, order bumps, and post-purchase offers.
|
|
3
|
+
*
|
|
4
|
+
* Endpoints align with the plugin-sdk patterns:
|
|
5
|
+
* GET /api/v1/offers/:id — single offer
|
|
6
|
+
* GET /api/v1/stores/:storeId/offers — list store offers
|
|
7
|
+
* POST /api/v1/offers/:offerId/preview — preview pricing
|
|
8
|
+
* POST /api/v1/offers/:offerId/pay-preview — pay a previewed offer (one-click)
|
|
9
|
+
* POST /api/v1/checkout-sessions/:id/toggle-order-bump — toggle order bump
|
|
10
|
+
* GET /api/v1/post-purchase/:orderId/offers — post-purchase offers for an order
|
|
11
|
+
* POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/accept — accept
|
|
12
|
+
* POST /api/v1/orders/:orderId/post-purchase-offers/:offerId/decline — decline
|
|
13
|
+
*/
|
|
14
|
+
export class OffersModule {
|
|
15
|
+
constructor(http, storeId, payment) {
|
|
16
|
+
this.http = http;
|
|
17
|
+
this.storeId = storeId;
|
|
18
|
+
this.payment = payment;
|
|
19
|
+
}
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Offer loading
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/** Get a single offer by ID. */
|
|
24
|
+
async getOffer(offerId) {
|
|
25
|
+
return this.http.get(`/api/v1/offers/${offerId}`);
|
|
26
|
+
}
|
|
27
|
+
/** List offers for the current store. Optionally filter by type or a set of IDs. */
|
|
28
|
+
async listOffers(opts) {
|
|
29
|
+
let url = `/api/v1/stores/${this.storeId}/offers`;
|
|
30
|
+
const queryParts = [];
|
|
31
|
+
if (opts?.type)
|
|
32
|
+
queryParts.push(`type=${encodeURIComponent(opts.type)}`);
|
|
33
|
+
if (opts?.ids?.length) {
|
|
34
|
+
for (const id of opts.ids)
|
|
35
|
+
queryParts.push(`ids=${encodeURIComponent(id)}`);
|
|
36
|
+
}
|
|
37
|
+
if (queryParts.length)
|
|
38
|
+
url += `?${queryParts.join('&')}`;
|
|
39
|
+
const res = await this.http.get(url);
|
|
40
|
+
return res.offers ?? [];
|
|
41
|
+
}
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Preview & pay (one-click upsell flow from plugin-sdk)
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
/** Preview offer pricing. Returns line items with amounts and totals. */
|
|
46
|
+
async previewOffer(opts) {
|
|
47
|
+
return this.http.post(`/api/v1/offers/${opts.offerId}/preview`, {
|
|
48
|
+
offerId: opts.offerId,
|
|
49
|
+
currency: opts.currency ?? '',
|
|
50
|
+
lineItems: opts.lineItems,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Pay a previously previewed offer (one-click charge).
|
|
55
|
+
* Used after a main order so the stored payment instrument is reused.
|
|
56
|
+
*
|
|
57
|
+
* **Low-level API.** Returns the raw `OfferPayResult` — `requireAction`,
|
|
58
|
+
* polling, and 3DS redirects are NOT handled. For most cases, use
|
|
59
|
+
* {@link processOfferPayment} which orchestrates the full lifecycle.
|
|
60
|
+
*/
|
|
61
|
+
async payPreviewedOffer(opts) {
|
|
62
|
+
return this.http.post(`/api/v1/offers/${opts.offerId}/pay-preview`, {
|
|
63
|
+
offerId: opts.offerId,
|
|
64
|
+
currency: opts.currency ?? '',
|
|
65
|
+
lineItems: opts.lineItems,
|
|
66
|
+
returnUrl: opts.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : ''),
|
|
67
|
+
mainOrderId: opts.mainOrderId,
|
|
68
|
+
paymentInstrumentId: opts.paymentInstrumentId,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* One-click upsell with full lifecycle handling.
|
|
73
|
+
*
|
|
74
|
+
* Like `payment.processPayment()` but for previewed offers: charges the
|
|
75
|
+
* stored instrument from `mainOrderId`, runs any 3DS challenge or bank
|
|
76
|
+
* redirect, polls until terminal, and returns a typed
|
|
77
|
+
* `ProcessPaymentResult` (`succeeded` / `requires_redirect` /
|
|
78
|
+
* `failed` / `pending`).
|
|
79
|
+
*
|
|
80
|
+
* Use this instead of the lower-level `payPreviewedOffer()` whenever you
|
|
81
|
+
* don't need to inspect the raw `OfferPayResult` shape — which is most
|
|
82
|
+
* of the time.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const result = await tagada.offers.processOfferPayment({
|
|
87
|
+
* offerId: 'offer_xxx',
|
|
88
|
+
* mainOrderId: order.id,
|
|
89
|
+
* returnUrl: window.location.href,
|
|
90
|
+
* });
|
|
91
|
+
*
|
|
92
|
+
* switch (result.status) {
|
|
93
|
+
* case 'succeeded':
|
|
94
|
+
* window.location.href = '/upsell-2';
|
|
95
|
+
* break;
|
|
96
|
+
* case 'requires_redirect':
|
|
97
|
+
* window.location.href = result.redirectUrl;
|
|
98
|
+
* break;
|
|
99
|
+
* case 'failed':
|
|
100
|
+
* showError(result.error);
|
|
101
|
+
* break;
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
async processOfferPayment(opts) {
|
|
106
|
+
if (!this.payment) {
|
|
107
|
+
throw new Error('OffersModule: no PaymentModule injected. ' +
|
|
108
|
+
'Use createHeadlessClient() instead of constructing OffersModule directly.');
|
|
109
|
+
}
|
|
110
|
+
const returnUrl = opts.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : undefined);
|
|
111
|
+
const payResult = await this.payPreviewedOffer({ ...opts, returnUrl });
|
|
112
|
+
return this.payment.finalize({ payment: payResult.payment, order: payResult.order }, { returnUrl });
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Order bumps (checkout-session scoped)
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
/** Toggle an order bump on/off within a checkout session. */
|
|
118
|
+
async toggleOrderBump(opts) {
|
|
119
|
+
return this.http.post(`/api/v1/checkout-sessions/${opts.checkoutSessionId}/toggle-order-bump`, {
|
|
120
|
+
orderBumpOfferId: opts.orderBumpOfferId,
|
|
121
|
+
selected: opts.selected,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Post-purchase offers (order-scoped)
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
/** List post-purchase offers for an order. */
|
|
128
|
+
async listPostPurchaseOffers(orderId) {
|
|
129
|
+
const res = await this.http.get(`/api/v1/post-purchase/${orderId}/offers`);
|
|
130
|
+
return Array.isArray(res) ? res : [];
|
|
131
|
+
}
|
|
132
|
+
/** Accept a post-purchase offer. */
|
|
133
|
+
async acceptPostPurchaseOffer(opts) {
|
|
134
|
+
return this.http.post(`/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/accept`, { items: opts.items ?? [] });
|
|
135
|
+
}
|
|
136
|
+
/** Decline a post-purchase offer. */
|
|
137
|
+
async declinePostPurchaseOffer(opts) {
|
|
138
|
+
return this.http.post(`/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/decline`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=offers.js.map
|