@waffo/pancake-ts 0.11.0 → 0.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/CHANGELOG.md +21 -0
- package/README.md +43 -42
- package/dist/index.cjs +147 -131
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +201 -174
- package/dist/index.d.ts +201 -174
- package/dist/index.js +147 -131
- package/dist/index.js.map +1 -1
- package/docs/api-reference.md +31 -28
- package/docs/webhook-guide.md +14 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ All notable changes to `@waffo/pancake-ts` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.13.0] - 2026-07-17
|
|
8
|
+
|
|
9
|
+
Adds cashier language selection to checkout sessions.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`CashierLanguage`** — exported union type of the 22 supported checkout cashier languages (IETF BCP 47, e.g. `"en"`, `"pt-BR"`, `"zh-Hant-TW"`).
|
|
14
|
+
- **`CreateCheckoutSessionParams.language`** — optional cashier language, forwarded to `create-session`. Sets the hosted checkout page's default language; the customer can still switch it on the page. Omit to let the payment provider infer.
|
|
15
|
+
|
|
16
|
+
## [0.12.0] - 2026-07-14
|
|
17
|
+
|
|
18
|
+
Renames the "buyer" persona to "customer" across the SDK's public API — "customer" is the Waffo term for the merchant's end consumer (the session-token JWT role). Old names remain available as deprecated aliases. Wire-level request and webhook field names (`buyerIdentity`, `buyerEmail`, `merchantProvidedBuyerIdentity`) are part of the server contract and are unchanged.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **`client.customer(token)`** — creates the customer self-service session (class `CustomerSession`, previously `BuyerSession`). Same methods: `cancelSubscription()`, `cancelOnetimeOrder()`, `reactivateSubscription()`, `createRefundTicket()`, `resubmitRefundTicket()`, `graphql.query<T>()`.
|
|
23
|
+
|
|
24
|
+
### Deprecated
|
|
25
|
+
|
|
26
|
+
- **`client.buyer(token)`** — use `client.customer(token)` instead. Thin wrapper around `client.customer()`, identical behavior; will be removed in a future major version.
|
|
27
|
+
|
|
7
28
|
## [0.11.0] - 2026-06-05
|
|
8
29
|
|
|
9
30
|
Aligns Create/Update Product params with backend product-service v2026.6.4: `description` and `successUrl` accept `null` for explicit field clearing (previously only `undefined` / omitted). Backend also tightens `name` to ≤ 64 characters to match the PSP `goodsName` cap — passing a longer name now returns 400.
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ npm install @waffo/pancake-ts
|
|
|
15
15
|
|
|
16
16
|
## Quick Start
|
|
17
17
|
|
|
18
|
-
> Most merchants create stores and products in the [Dashboard](https://pancake.waffo.ai/dashboard). The SDK is primarily used for **checkout integration** — redirecting
|
|
18
|
+
> Most merchants create stores and products in the [Dashboard](https://pancake.waffo.ai/dashboard). The SDK is primarily used for **checkout integration** — redirecting customers from your site to the Waffo checkout page.
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
21
|
import { WaffoPancake } from "@waffo/pancake-ts";
|
|
@@ -33,7 +33,7 @@ const result = await client.checkout.authenticated.create({
|
|
|
33
33
|
buyerIdentity: req.user.email, // your user's identity
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
// Redirect
|
|
36
|
+
// Redirect customer to the checkout page (opens in new tab)
|
|
37
37
|
res.json({ checkoutUrl: result.checkoutUrl });
|
|
38
38
|
// => checkoutUrl includes #token=... (form pre-filled)
|
|
39
39
|
```
|
|
@@ -52,24 +52,24 @@ The SDK auto-normalizes key formats: standard PEM, PKCS#1, literal `\n` from env
|
|
|
52
52
|
|
|
53
53
|
## Checkout Integration
|
|
54
54
|
|
|
55
|
-
Waffo supports two checkout modes based on whether the merchant knows the
|
|
55
|
+
Waffo supports two checkout modes based on whether the merchant knows the customer's identity:
|
|
56
56
|
|
|
57
|
-
- **Merchants with their own sites** know who the
|
|
58
|
-
- **Template stores and shared links** have no prior
|
|
57
|
+
- **Merchants with their own sites** know who the customer is — they have user accounts, login systems, or collect customer info before checkout. The merchant provides the customer's identity upfront, and the checkout form arrives pre-filled.
|
|
58
|
+
- **Template stores and shared links** have no prior customer context — the customer arrives directly at the checkout page and fills in their own details.
|
|
59
59
|
|
|
60
|
-
| Mode | Method |
|
|
60
|
+
| Mode | Method | Customer Identity | Form State | Use Case |
|
|
61
61
|
| ----------------- | --------------------------------- | ----------------- | ---------- | ---------------------------------------- |
|
|
62
62
|
| **Authenticated** | `checkout.authenticated.create()` | Merchant provides | Pre-filled | Merchant sites with user accounts |
|
|
63
63
|
| **Anonymous** | `checkout.anonymous.create()` | Not provided | Empty | Template stores, one-time purchase links |
|
|
64
64
|
|
|
65
|
-
> **We recommend authenticated checkout whenever possible.** The most important reason: authenticated checkout binds the order to the `buyerIdentity` you provide, which is a **merchant-controlled stable identifier**. Even if the
|
|
65
|
+
> **We recommend authenticated checkout whenever possible.** The most important reason: authenticated checkout binds the order to the `buyerIdentity` you provide, which is a **merchant-controlled stable identifier**. Even if the customer changes the email on the checkout form, the order is still tied to the identity you specified. In anonymous mode, the customer self-reports their email on the form — if they enter a different address, the system treats them as a new user, which means **previous orders become unlinked** and **subscription trial periods can be exploited** (a new email = a new user = a fresh trial).
|
|
66
66
|
>
|
|
67
|
-
> | | Authenticated
|
|
68
|
-
> | ----------------- |
|
|
69
|
-
> | **Identity** | Merchant-provided, stable across orders
|
|
70
|
-
> | **Form** | Pre-filled from merchant-provided identity
|
|
71
|
-
> | **Post-purchase** | Full self-service (see [
|
|
72
|
-
> | **Session** | 5-minute TTL, auto-refreshes
|
|
67
|
+
> | | Authenticated | Anonymous |
|
|
68
|
+
> | ----------------- | ----------------------------------------------------------------------- | -------------------------------------------------- |
|
|
69
|
+
> | **Identity** | Merchant-provided, stable across orders | Self-reported email, may vary |
|
|
70
|
+
> | **Form** | Pre-filled from merchant-provided identity | Empty, customer fills manually |
|
|
71
|
+
> | **Post-purchase** | Full self-service (see [Customer Self-Service](#customer-self-service)) | Create orders only — no post-purchase self-service |
|
|
72
|
+
> | **Session** | 5-minute TTL, auto-refreshes | 1-minute, single-use |
|
|
73
73
|
|
|
74
74
|
Both modes support **dynamic pricing** and **trial control** at checkout time:
|
|
75
75
|
|
|
@@ -78,12 +78,12 @@ Both modes support **dynamic pricing** and **trial control** at checkout time:
|
|
|
78
78
|
|
|
79
79
|
### Authenticated Checkout (Recommended)
|
|
80
80
|
|
|
81
|
-
The merchant provides
|
|
81
|
+
The merchant provides customer identity — the SDK issues a session token, creates a checkout session, and returns a checkout URL with the token appended as a URL fragment. One call does everything.
|
|
82
82
|
|
|
83
83
|
`buyerIdentity` is for order attribution and trial tracking only — it is not rendered on the checkout page. To pre-fill the email field on the checkout form, pass `buyerEmail` explicitly.
|
|
84
84
|
|
|
85
85
|
```typescript
|
|
86
|
-
// Basic —
|
|
86
|
+
// Basic — customer identity only (checkout page email field stays empty)
|
|
87
87
|
const result = await client.checkout.authenticated.create({
|
|
88
88
|
productId: "PROD_xxx",
|
|
89
89
|
currency: "USD",
|
|
@@ -118,7 +118,7 @@ The token is passed via the URL fragment (after `#`), which is never sent to the
|
|
|
118
118
|
|
|
119
119
|
### Anonymous Checkout
|
|
120
120
|
|
|
121
|
-
No
|
|
121
|
+
No customer identity required — the customer fills in billing details manually on the checkout page.
|
|
122
122
|
|
|
123
123
|
```typescript
|
|
124
124
|
const result = await client.checkout.anonymous.create({
|
|
@@ -133,6 +133,7 @@ const result = await client.checkout.anonymous.create({
|
|
|
133
133
|
priceSnapshot: { amount: "4.99", taxCategory: "saas" },
|
|
134
134
|
withTrial: false, // skip trial for this session
|
|
135
135
|
orderMerchantExternalId: "ORDER-2026-00891", // optional, API Key auth only
|
|
136
|
+
language: "pt-BR", // optional, sets the default checkout language (IETF BCP 47)
|
|
136
137
|
});
|
|
137
138
|
|
|
138
139
|
window.open(result.checkoutUrl, "_blank", "noopener,noreferrer");
|
|
@@ -142,7 +143,7 @@ window.open(result.checkoutUrl, "_blank", "noopener,noreferrer");
|
|
|
142
143
|
|
|
143
144
|
**We recommend opening the checkout page in a new tab** rather than navigating in the current page:
|
|
144
145
|
|
|
145
|
-
-
|
|
146
|
+
- Customers can return to your site immediately after payment or if they close the checkout tab
|
|
146
147
|
- Merchant page state (cart, forms, scroll position) is preserved
|
|
147
148
|
- Payment flow is decoupled from the browsing experience, reducing checkout abandonment
|
|
148
149
|
|
|
@@ -154,13 +155,13 @@ window.open(result.checkoutUrl, "_blank", "noopener,noreferrer");
|
|
|
154
155
|
// <a href={checkoutUrl} target="_blank" rel="noopener noreferrer">Proceed to Checkout</a>
|
|
155
156
|
```
|
|
156
157
|
|
|
157
|
-
> **Not recommended:** `window.location.href = result.checkoutUrl` replaces the current page, preventing
|
|
158
|
+
> **Not recommended:** `window.location.href = result.checkoutUrl` replaces the current page, preventing customers from returning to your site without browser back navigation.
|
|
158
159
|
|
|
159
160
|
See [API Reference — Checkout](docs/api-reference.md#checkout) for full parameter tables and `BillingDetail` field requirements.
|
|
160
161
|
|
|
161
162
|
## Webhook Verification
|
|
162
163
|
|
|
163
|
-
After a
|
|
164
|
+
After a customer completes payment, Waffo sends webhook events to your server with rich data including order details, amounts, product info, and event-specific fields (payment, subscription, or refund). The SDK provides two ways to verify signatures:
|
|
164
165
|
|
|
165
166
|
### Standalone Function (built-in keys)
|
|
166
167
|
|
|
@@ -179,7 +180,7 @@ app.post("/webhooks", express.raw({ type: "application/json" }), (req, res) => {
|
|
|
179
180
|
case WebhookEventType.OrderCompleted:
|
|
180
181
|
// Rich data: order, amount, product, payment fields
|
|
181
182
|
console.log(`Order ${event.data.orderId} completed — ${event.data.total} ${event.data.currency}`);
|
|
182
|
-
console.log(`Product: ${event.data.productName},
|
|
183
|
+
console.log(`Product: ${event.data.productName}, Customer: ${event.data.buyerEmail}`);
|
|
183
184
|
if (event.data.orderMetadata) console.log("Metadata:", event.data.orderMetadata);
|
|
184
185
|
break;
|
|
185
186
|
case WebhookEventType.SubscriptionActivated:
|
|
@@ -226,34 +227,34 @@ const event = client.webhooks.verify(rawBody, sig, { environment: "prod" });
|
|
|
226
227
|
|
|
227
228
|
See [Webhook Guide](docs/webhook-guide.md) for event types, `WebhookEventData` field reference, dual-environment key architecture, key resolution chain, retry mechanism, and best practices.
|
|
228
229
|
|
|
229
|
-
##
|
|
230
|
+
## Customer Self-Service
|
|
230
231
|
|
|
231
|
-
Beyond checkout, you can let
|
|
232
|
+
Beyond checkout, you can let customers manage their own orders and subscriptions — for example, embedding a "Cancel Subscription" or "Request Refund" button in your site.
|
|
232
233
|
|
|
233
|
-
Issue a session token, then use `client.
|
|
234
|
+
Issue a session token, then use `client.customer(token)` to get a session with self-service methods:
|
|
234
235
|
|
|
235
236
|
```typescript
|
|
236
|
-
// Your backend — issue a session token for the
|
|
237
|
+
// Your backend — issue a session token for the customer
|
|
237
238
|
const { token } = await client.auth.issueSessionToken({
|
|
238
239
|
storeId: "STO_xxx",
|
|
239
240
|
buyerIdentity: req.user.email,
|
|
240
241
|
});
|
|
241
242
|
|
|
242
|
-
// Create a
|
|
243
|
-
const
|
|
243
|
+
// Create a customer session
|
|
244
|
+
const customer = client.customer(token);
|
|
244
245
|
|
|
245
246
|
// Cancel a subscription
|
|
246
|
-
const { orderId, status } = await
|
|
247
|
+
const { orderId, status } = await customer.cancelSubscription({ orderId: "ORD_xxx" });
|
|
247
248
|
// status: "canceling" (active) or "canceled" (pending)
|
|
248
249
|
|
|
249
250
|
// Reactivate a canceled subscription
|
|
250
|
-
await
|
|
251
|
+
await customer.reactivateSubscription({ orderId: "ORD_xxx" });
|
|
251
252
|
|
|
252
253
|
// Cancel a one-time order (while payment is pending)
|
|
253
|
-
await
|
|
254
|
+
await customer.cancelOnetimeOrder({ orderId: "ORD_yyy" });
|
|
254
255
|
|
|
255
256
|
// Submit a refund request
|
|
256
|
-
const { ticket } = await
|
|
257
|
+
const { ticket } = await customer.createRefundTicket({
|
|
257
258
|
paymentId: "PAY_xxx",
|
|
258
259
|
reason: "Product not as described",
|
|
259
260
|
requestedAmount: { amount: "29.00", currency: "USD" },
|
|
@@ -261,22 +262,22 @@ const { ticket } = await buyer.createRefundTicket({
|
|
|
261
262
|
});
|
|
262
263
|
|
|
263
264
|
// Resubmit a rejected refund ticket
|
|
264
|
-
await
|
|
265
|
+
await customer.resubmitRefundTicket({
|
|
265
266
|
ticketId: "TKT_xxx",
|
|
266
267
|
paymentId: "PAY_xxx",
|
|
267
268
|
reason: "Updated reason with more detail",
|
|
268
269
|
requestedAmount: { amount: "29.00", currency: "USD" },
|
|
269
270
|
});
|
|
270
271
|
|
|
271
|
-
// Query the
|
|
272
|
-
const result = await
|
|
272
|
+
// Query the customer's own orders via GraphQL
|
|
273
|
+
const result = await customer.graphql.query({
|
|
273
274
|
query: `query { orders { id status createdAt } }`,
|
|
274
275
|
});
|
|
275
276
|
```
|
|
276
277
|
|
|
277
|
-
The token is scoped to the specified store and
|
|
278
|
+
The token is scoped to the specified store and customer identity — customers can only access their own data. Token TTL is 5 minutes and auto-refreshes on each API call.
|
|
278
279
|
|
|
279
|
-
> **Note**: This uses the same `buyerIdentity` as `checkout.authenticated.create()`. Orders placed via authenticated checkout are automatically tied to this identity, so the
|
|
280
|
+
> **Note**: This uses the same `buyerIdentity` as `checkout.authenticated.create()`. Orders placed via authenticated checkout are automatically tied to this identity, so the customer can manage them later with a token issued here.
|
|
280
281
|
|
|
281
282
|
## Business-Side Identifiers
|
|
282
283
|
|
|
@@ -285,7 +286,7 @@ Attach your own internal references to a checkout or a refund ticket so cross-sy
|
|
|
285
286
|
| Field | Attach at | Inherited by |
|
|
286
287
|
| -------------------------------- | ------------------------------------------- | ---------------------------------------------------------- |
|
|
287
288
|
| `orderMerchantExternalId` | `checkout.{authenticated,anonymous}.create` | `Order`, `Payment` (incl. subscription renewals), `Refund` |
|
|
288
|
-
| `refundTicketMerchantExternalId` | `
|
|
289
|
+
| `refundTicketMerchantExternalId` | `customer.createRefundTicket` | `RefundTicket`, `Refund` |
|
|
289
290
|
|
|
290
291
|
The same field name appears at every layer it surfaces: request body, response entity, webhook payload (`data.orderMerchantExternalId` / `data.refundTicketMerchantExternalId`), and every GraphQL type that carries the value. A `refund.*` webhook event carries **both** keys (order key inherited from the originating order). Query by either key via GraphQL filters — see [GraphQL Guide](docs/graphql-guide.md).
|
|
291
292
|
|
|
@@ -531,11 +532,11 @@ try {
|
|
|
531
532
|
| `client.checkout.authenticated` | `create()` | Authenticated checkout (recommended) |
|
|
532
533
|
| `client.checkout.anonymous` | `create()` | Anonymous checkout |
|
|
533
534
|
| `client.checkout` | `createSession()` | Low-level checkout session |
|
|
534
|
-
| `client.
|
|
535
|
-
| `client.
|
|
535
|
+
| `client.customer(token)` | `cancelSubscription()` `cancelOnetimeOrder()` `reactivateSubscription()` `createRefundTicket()` `resubmitRefundTicket()` | Customer self-service |
|
|
536
|
+
| `client.customer(token).graphql` | `query<T>()` | Customer-scoped GraphQL queries |
|
|
536
537
|
| `client.webhooks` | `verify<T>()` `add()` `update()` `remove()` | Webhook config + signature verification |
|
|
537
538
|
| `client.graphql` | `query<T>()` | Merchant GraphQL queries |
|
|
538
|
-
| `client.auth` | `issueSessionToken()` | Issue a
|
|
539
|
+
| `client.auth` | `issueSessionToken()` | Issue a customer session token (JWT) |
|
|
539
540
|
| `client.stores` | `create()` `update()` `delete()` | Store management |
|
|
540
541
|
| `client.storeMerchants` | `add()` `remove()` `updateRole()` | Store members (coming soon) |
|
|
541
542
|
| `client.onetimeProducts` | `create()` `update()` `publish()` `updateStatus()` | One-time products |
|
|
@@ -584,7 +585,7 @@ try {
|
|
|
584
585
|
|
|
585
586
|
### Types
|
|
586
587
|
|
|
587
|
-
Key types: `WaffoPancakeConfig`, `AuthenticatedCheckoutParams`, `AuthenticatedCheckoutResult`, `AnonymousCheckoutParams`, `CheckoutSessionResult`, `Store`, `OnetimeProductDetail`, `SubscriptionProductDetail`, `WebhookEvent<T>`, `WebhookEventData`, `GraphQLResponse<T>`, and 30+ more. `WebhookEventData` includes rich fields organized by section: order info, amounts, product, payment, subscription, and refund (conditional by event type). See [API Reference](docs/api-reference.md#types) for the full list.
|
|
588
|
+
Key types: `WaffoPancakeConfig`, `AuthenticatedCheckoutParams`, `AuthenticatedCheckoutResult`, `AnonymousCheckoutParams`, `CheckoutSessionResult`, `CashierLanguage`, `Store`, `OnetimeProductDetail`, `SubscriptionProductDetail`, `WebhookEvent<T>`, `WebhookEventData`, `GraphQLResponse<T>`, and 30+ more. `WebhookEventData` includes rich fields organized by section: order info, amounts, product, payment, subscription, and refund (conditional by event type). See [API Reference](docs/api-reference.md#types) for the full list.
|
|
588
589
|
|
|
589
590
|
## Development
|
|
590
591
|
|
|
@@ -603,7 +604,7 @@ src/
|
|
|
603
604
|
├── index.ts # Unified export entry
|
|
604
605
|
├── client.ts # WaffoPancake main class
|
|
605
606
|
├── http-client.ts # HTTP client (API Key, auto-signing + idempotency)
|
|
606
|
-
├──
|
|
607
|
+
├── customer-http-client.ts # HTTP client (Bearer token, customer self-service)
|
|
607
608
|
├── signing.ts # RSA-SHA256 request signing
|
|
608
609
|
├── errors.ts # WaffoPancakeError
|
|
609
610
|
├── webhooks.ts # Webhook verification (embedded keys)
|
|
@@ -617,7 +618,7 @@ src/
|
|
|
617
618
|
├── onetime-products.ts
|
|
618
619
|
├── subscription-products.ts
|
|
619
620
|
├── subscription-product-groups.ts
|
|
620
|
-
├──
|
|
621
|
+
├── customer.ts
|
|
621
622
|
├── orders.ts
|
|
622
623
|
├── checkout.ts
|
|
623
624
|
├── checkout-anonymous.ts
|
package/dist/index.cjs
CHANGED
|
@@ -53,9 +53,9 @@ var WaffoPancakeError = class extends Error {
|
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
// src/
|
|
56
|
+
// src/customer-http-client.ts
|
|
57
57
|
var DEFAULT_BASE_URL = "https://api.waffo.ai";
|
|
58
|
-
var
|
|
58
|
+
var CustomerHttpClient = class {
|
|
59
59
|
token;
|
|
60
60
|
baseUrl;
|
|
61
61
|
_fetch;
|
|
@@ -369,7 +369,7 @@ var AuthResource = class {
|
|
|
369
369
|
this.http = http;
|
|
370
370
|
}
|
|
371
371
|
/**
|
|
372
|
-
* Issue a session token for a
|
|
372
|
+
* Issue a session token for a customer.
|
|
373
373
|
*
|
|
374
374
|
* @param params - Token issuance parameters
|
|
375
375
|
* @returns Issued session token with expiration
|
|
@@ -403,122 +403,6 @@ var AuthResource = class {
|
|
|
403
403
|
}
|
|
404
404
|
};
|
|
405
405
|
|
|
406
|
-
// src/resources/buyer.ts
|
|
407
|
-
var BuyerSession = class {
|
|
408
|
-
constructor(http) {
|
|
409
|
-
this.http = http;
|
|
410
|
-
this.graphql = new BuyerGraphQL(http);
|
|
411
|
-
}
|
|
412
|
-
/** GraphQL query access scoped to the buyer's data. */
|
|
413
|
-
graphql;
|
|
414
|
-
/**
|
|
415
|
-
* Cancel a subscription order.
|
|
416
|
-
*
|
|
417
|
-
* @param params - Order to cancel
|
|
418
|
-
* @returns Order ID and resulting status
|
|
419
|
-
*
|
|
420
|
-
* @example
|
|
421
|
-
* const { orderId, status } = await buyer.cancelSubscription({ orderId: "ORD_xxx" });
|
|
422
|
-
* // status: "canceled" (was pending) or "canceling" (was active)
|
|
423
|
-
*/
|
|
424
|
-
async cancelSubscription(params) {
|
|
425
|
-
validateShortId("orderId", params.orderId, "ORD");
|
|
426
|
-
return unwrapAction(await this.http.post("/v1/actions/subscription-order/cancel-order", params));
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Cancel a one-time order (only while payment is still pending).
|
|
430
|
-
*
|
|
431
|
-
* @param params - Order to cancel
|
|
432
|
-
* @returns Order ID and resulting status
|
|
433
|
-
*
|
|
434
|
-
* @example
|
|
435
|
-
* const { orderId, status } = await buyer.cancelOnetimeOrder({ orderId: "ORD_xxx" });
|
|
436
|
-
*/
|
|
437
|
-
async cancelOnetimeOrder(params) {
|
|
438
|
-
validateShortId("orderId", params.orderId, "ORD");
|
|
439
|
-
return unwrapAction(await this.http.post("/v1/actions/onetime-order/cancel-order", params));
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Reactivate a subscription that is in `canceling` status.
|
|
443
|
-
*
|
|
444
|
-
* @param params - Order to reactivate
|
|
445
|
-
* @returns Order ID and resulting status
|
|
446
|
-
*
|
|
447
|
-
* @example
|
|
448
|
-
* const { orderId, status } = await buyer.reactivateSubscription({ orderId: "ORD_xxx" });
|
|
449
|
-
* // status: "active"
|
|
450
|
-
*/
|
|
451
|
-
async reactivateSubscription(params) {
|
|
452
|
-
validateShortId("orderId", params.orderId, "ORD");
|
|
453
|
-
return unwrapAction(await this.http.post("/v1/actions/subscription-order/reactivate-order", params));
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* Submit a refund request for a payment.
|
|
457
|
-
*
|
|
458
|
-
* @param params - Refund ticket details
|
|
459
|
-
* @returns Created refund ticket
|
|
460
|
-
*
|
|
461
|
-
* @example
|
|
462
|
-
* const { ticket } = await buyer.createRefundTicket({
|
|
463
|
-
* paymentId: "PAY_xxx",
|
|
464
|
-
* reason: "Product not as described",
|
|
465
|
-
* requestedAmount: { amount: "29.00", currency: "USD" },
|
|
466
|
-
* refundTicketMerchantExternalId: "REF-2026-00891",
|
|
467
|
-
* });
|
|
468
|
-
*/
|
|
469
|
-
async createRefundTicket(params) {
|
|
470
|
-
validateShortId("paymentId", params.paymentId, "PAY");
|
|
471
|
-
validateRequired("reason", params.reason);
|
|
472
|
-
validateAmountString("requestedAmount.amount", params.requestedAmount.amount);
|
|
473
|
-
validateCurrencyCode("requestedAmount.currency", params.requestedAmount.currency);
|
|
474
|
-
validateMaxLength("refundTicketMerchantExternalId", params.refundTicketMerchantExternalId, 128);
|
|
475
|
-
return unwrapAction(await this.http.post("/v1/actions/refund-ticket/create-ticket", params));
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Resubmit a previously rejected refund ticket with updated details.
|
|
479
|
-
*
|
|
480
|
-
* @param params - Updated ticket details
|
|
481
|
-
* @returns Updated refund ticket
|
|
482
|
-
*
|
|
483
|
-
* @example
|
|
484
|
-
* const { ticket } = await buyer.resubmitRefundTicket({
|
|
485
|
-
* ticketId: "TKT_xxx",
|
|
486
|
-
* paymentId: "PAY_xxx",
|
|
487
|
-
* reason: "Updated reason with more detail",
|
|
488
|
-
* requestedAmount: { amount: "29.00", currency: "USD" },
|
|
489
|
-
* });
|
|
490
|
-
*/
|
|
491
|
-
async resubmitRefundTicket(params) {
|
|
492
|
-
validateShortId("ticketId", params.ticketId, "TKT");
|
|
493
|
-
validateShortId("paymentId", params.paymentId, "PAY");
|
|
494
|
-
validateRequired("reason", params.reason);
|
|
495
|
-
validateAmountString("requestedAmount.amount", params.requestedAmount.amount);
|
|
496
|
-
validateCurrencyCode("requestedAmount.currency", params.requestedAmount.currency);
|
|
497
|
-
return unwrapAction(await this.http.post("/v1/actions/refund-ticket/resubmit-ticket", params));
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
var BuyerGraphQL = class {
|
|
501
|
-
constructor(http) {
|
|
502
|
-
this.http = http;
|
|
503
|
-
}
|
|
504
|
-
/**
|
|
505
|
-
* Execute a GraphQL query scoped to the buyer's data.
|
|
506
|
-
*
|
|
507
|
-
* @param params - GraphQL query and variables
|
|
508
|
-
* @returns GraphQL response
|
|
509
|
-
*
|
|
510
|
-
* @example
|
|
511
|
-
* const result = await buyer.graphql.query({
|
|
512
|
-
* query: `query { orders { id status } }`,
|
|
513
|
-
* });
|
|
514
|
-
*/
|
|
515
|
-
async query(params) {
|
|
516
|
-
validateRequired("query", params.query);
|
|
517
|
-
const result = await this.http.post("/v1/graphql", params);
|
|
518
|
-
return { data: result.data, errors: result.errors, warnings: result.warnings };
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
|
|
522
406
|
// src/resources/checkout-anonymous.ts
|
|
523
407
|
var CheckoutAnonymousResource = class {
|
|
524
408
|
constructor(http) {
|
|
@@ -527,11 +411,11 @@ var CheckoutAnonymousResource = class {
|
|
|
527
411
|
/**
|
|
528
412
|
* Create an anonymous checkout session.
|
|
529
413
|
*
|
|
530
|
-
* @param params - Checkout parameters (no
|
|
414
|
+
* @param params - Checkout parameters (no customer identity required)
|
|
531
415
|
* @returns Session ID, checkout URL, and expiration
|
|
532
416
|
*
|
|
533
417
|
* @example
|
|
534
|
-
* // Minimal —
|
|
418
|
+
* // Minimal — customer fills everything on the page
|
|
535
419
|
* const result = await client.checkout.anonymous.create({
|
|
536
420
|
* productId: "PROD_xxx",
|
|
537
421
|
* currency: "USD",
|
|
@@ -571,7 +455,7 @@ var CheckoutAuthenticatedResource = class {
|
|
|
571
455
|
* `buyerIdentity` and `buyerEmail` are independent inputs: identity is for the JWT,
|
|
572
456
|
* email is for pre-filling the checkout page. The SDK forwards each to its own endpoint.
|
|
573
457
|
*
|
|
574
|
-
* @param params - Checkout parameters including
|
|
458
|
+
* @param params - Checkout parameters including customer identity
|
|
575
459
|
* @returns Session details with token-appended checkout URL
|
|
576
460
|
*
|
|
577
461
|
* @example
|
|
@@ -620,9 +504,9 @@ var CheckoutResource = class {
|
|
|
620
504
|
this.anonymous = new CheckoutAnonymousResource(http);
|
|
621
505
|
this.authenticated = new CheckoutAuthenticatedResource(http);
|
|
622
506
|
}
|
|
623
|
-
/** Anonymous checkout — no
|
|
507
|
+
/** Anonymous checkout — no customer identity, empty form. */
|
|
624
508
|
anonymous;
|
|
625
|
-
/** Authenticated checkout — merchant provides
|
|
509
|
+
/** Authenticated checkout — merchant provides customer identity. */
|
|
626
510
|
authenticated;
|
|
627
511
|
/**
|
|
628
512
|
* Create a checkout session (low-level). Returns a URL to redirect the customer to.
|
|
@@ -648,6 +532,122 @@ var CheckoutResource = class {
|
|
|
648
532
|
}
|
|
649
533
|
};
|
|
650
534
|
|
|
535
|
+
// src/resources/customer.ts
|
|
536
|
+
var CustomerSession = class {
|
|
537
|
+
constructor(http) {
|
|
538
|
+
this.http = http;
|
|
539
|
+
this.graphql = new CustomerGraphQL(http);
|
|
540
|
+
}
|
|
541
|
+
/** GraphQL query access scoped to the customer's data. */
|
|
542
|
+
graphql;
|
|
543
|
+
/**
|
|
544
|
+
* Cancel a subscription order.
|
|
545
|
+
*
|
|
546
|
+
* @param params - Order to cancel
|
|
547
|
+
* @returns Order ID and resulting status
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* const { orderId, status } = await customer.cancelSubscription({ orderId: "ORD_xxx" });
|
|
551
|
+
* // status: "canceled" (was pending) or "canceling" (was active)
|
|
552
|
+
*/
|
|
553
|
+
async cancelSubscription(params) {
|
|
554
|
+
validateShortId("orderId", params.orderId, "ORD");
|
|
555
|
+
return unwrapAction(await this.http.post("/v1/actions/subscription-order/cancel-order", params));
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Cancel a one-time order (only while payment is still pending).
|
|
559
|
+
*
|
|
560
|
+
* @param params - Order to cancel
|
|
561
|
+
* @returns Order ID and resulting status
|
|
562
|
+
*
|
|
563
|
+
* @example
|
|
564
|
+
* const { orderId, status } = await customer.cancelOnetimeOrder({ orderId: "ORD_xxx" });
|
|
565
|
+
*/
|
|
566
|
+
async cancelOnetimeOrder(params) {
|
|
567
|
+
validateShortId("orderId", params.orderId, "ORD");
|
|
568
|
+
return unwrapAction(await this.http.post("/v1/actions/onetime-order/cancel-order", params));
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Reactivate a subscription that is in `canceling` status.
|
|
572
|
+
*
|
|
573
|
+
* @param params - Order to reactivate
|
|
574
|
+
* @returns Order ID and resulting status
|
|
575
|
+
*
|
|
576
|
+
* @example
|
|
577
|
+
* const { orderId, status } = await customer.reactivateSubscription({ orderId: "ORD_xxx" });
|
|
578
|
+
* // status: "active"
|
|
579
|
+
*/
|
|
580
|
+
async reactivateSubscription(params) {
|
|
581
|
+
validateShortId("orderId", params.orderId, "ORD");
|
|
582
|
+
return unwrapAction(await this.http.post("/v1/actions/subscription-order/reactivate-order", params));
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Submit a refund request for a payment.
|
|
586
|
+
*
|
|
587
|
+
* @param params - Refund ticket details
|
|
588
|
+
* @returns Created refund ticket
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* const { ticket } = await customer.createRefundTicket({
|
|
592
|
+
* paymentId: "PAY_xxx",
|
|
593
|
+
* reason: "Product not as described",
|
|
594
|
+
* requestedAmount: { amount: "29.00", currency: "USD" },
|
|
595
|
+
* refundTicketMerchantExternalId: "REF-2026-00891",
|
|
596
|
+
* });
|
|
597
|
+
*/
|
|
598
|
+
async createRefundTicket(params) {
|
|
599
|
+
validateShortId("paymentId", params.paymentId, "PAY");
|
|
600
|
+
validateRequired("reason", params.reason);
|
|
601
|
+
validateAmountString("requestedAmount.amount", params.requestedAmount.amount);
|
|
602
|
+
validateCurrencyCode("requestedAmount.currency", params.requestedAmount.currency);
|
|
603
|
+
validateMaxLength("refundTicketMerchantExternalId", params.refundTicketMerchantExternalId, 128);
|
|
604
|
+
return unwrapAction(await this.http.post("/v1/actions/refund-ticket/create-ticket", params));
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Resubmit a previously rejected refund ticket with updated details.
|
|
608
|
+
*
|
|
609
|
+
* @param params - Updated ticket details
|
|
610
|
+
* @returns Updated refund ticket
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* const { ticket } = await customer.resubmitRefundTicket({
|
|
614
|
+
* ticketId: "TKT_xxx",
|
|
615
|
+
* paymentId: "PAY_xxx",
|
|
616
|
+
* reason: "Updated reason with more detail",
|
|
617
|
+
* requestedAmount: { amount: "29.00", currency: "USD" },
|
|
618
|
+
* });
|
|
619
|
+
*/
|
|
620
|
+
async resubmitRefundTicket(params) {
|
|
621
|
+
validateShortId("ticketId", params.ticketId, "TKT");
|
|
622
|
+
validateShortId("paymentId", params.paymentId, "PAY");
|
|
623
|
+
validateRequired("reason", params.reason);
|
|
624
|
+
validateAmountString("requestedAmount.amount", params.requestedAmount.amount);
|
|
625
|
+
validateCurrencyCode("requestedAmount.currency", params.requestedAmount.currency);
|
|
626
|
+
return unwrapAction(await this.http.post("/v1/actions/refund-ticket/resubmit-ticket", params));
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
var CustomerGraphQL = class {
|
|
630
|
+
constructor(http) {
|
|
631
|
+
this.http = http;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Execute a GraphQL query scoped to the customer's data.
|
|
635
|
+
*
|
|
636
|
+
* @param params - GraphQL query and variables
|
|
637
|
+
* @returns GraphQL response
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* const result = await customer.graphql.query({
|
|
641
|
+
* query: `query { orders { id status } }`,
|
|
642
|
+
* });
|
|
643
|
+
*/
|
|
644
|
+
async query(params) {
|
|
645
|
+
validateRequired("query", params.query);
|
|
646
|
+
const result = await this.http.post("/v1/graphql", params);
|
|
647
|
+
return { data: result.data, errors: result.errors, warnings: result.warnings };
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
|
|
651
651
|
// src/resources/graphql.ts
|
|
652
652
|
var GraphQLResource = class {
|
|
653
653
|
constructor(http) {
|
|
@@ -1339,29 +1339,45 @@ var WaffoPancake = class {
|
|
|
1339
1339
|
this.webhooks = new WebhooksResource(this.http, config.webhookPublicKey);
|
|
1340
1340
|
}
|
|
1341
1341
|
/**
|
|
1342
|
-
* Create a
|
|
1342
|
+
* Create a customer session for self-service operations.
|
|
1343
1343
|
*
|
|
1344
1344
|
* The returned session uses Bearer token authentication and provides
|
|
1345
1345
|
* methods for order cancellation, subscription management, refund tickets,
|
|
1346
1346
|
* and scoped GraphQL queries.
|
|
1347
1347
|
*
|
|
1348
1348
|
* @param token - Session token from `client.auth.issueSessionToken()`
|
|
1349
|
-
* @returns A
|
|
1349
|
+
* @returns A customer session with self-service methods
|
|
1350
1350
|
*
|
|
1351
1351
|
* @example
|
|
1352
1352
|
* const { token } = await client.auth.issueSessionToken({
|
|
1353
1353
|
* storeId: "STO_xxx",
|
|
1354
1354
|
* buyerIdentity: "customer@example.com",
|
|
1355
1355
|
* });
|
|
1356
|
-
* const
|
|
1357
|
-
* await
|
|
1356
|
+
* const customer = client.customer(token);
|
|
1357
|
+
* await customer.cancelSubscription({ orderId: "ORD_xxx" });
|
|
1358
1358
|
*/
|
|
1359
|
-
|
|
1360
|
-
const
|
|
1359
|
+
customer(token) {
|
|
1360
|
+
const customerHttp = new CustomerHttpClient(token, {
|
|
1361
1361
|
baseUrl: this.config.baseUrl,
|
|
1362
1362
|
fetch: this.config.fetch
|
|
1363
1363
|
});
|
|
1364
|
-
return new
|
|
1364
|
+
return new CustomerSession(customerHttp);
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* Create a customer session for self-service operations.
|
|
1368
|
+
*
|
|
1369
|
+
* @param token - Session token from `client.auth.issueSessionToken()`
|
|
1370
|
+
* @returns A customer session with self-service methods
|
|
1371
|
+
*
|
|
1372
|
+
* @example
|
|
1373
|
+
* ```typescript
|
|
1374
|
+
* const session = client.buyer(token); // prefer client.customer(token)
|
|
1375
|
+
* ```
|
|
1376
|
+
*
|
|
1377
|
+
* @deprecated Use {@link WaffoPancake.customer} instead.
|
|
1378
|
+
*/
|
|
1379
|
+
buyer(token) {
|
|
1380
|
+
return this.customer(token);
|
|
1365
1381
|
}
|
|
1366
1382
|
};
|
|
1367
1383
|
|