@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 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 buyers from your site to the Waffo checkout page.
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 buyer to the checkout page (opens in new tab)
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 buyer's identity:
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 buyer is — they have user accounts, login systems, or collect buyer info before checkout. The merchant provides the buyer's identity upfront, and the checkout form arrives pre-filled.
58
- - **Template stores and shared links** have no prior buyer context — the buyer arrives directly at the checkout page and fills in their own details.
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 | Buyer Identity | Form State | Use Case |
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 buyer changes the email on the checkout form, the order is still tied to the identity you specified. In anonymous mode, the buyer 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).
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 | Anonymous |
68
- > | ----------------- | ----------------------------------------------------------------- | -------------------------------------------------- |
69
- > | **Identity** | Merchant-provided, stable across orders | Self-reported email, may vary |
70
- > | **Form** | Pre-filled from merchant-provided identity | Empty, buyer fills manually |
71
- > | **Post-purchase** | Full self-service (see [Buyer Self-Service](#buyer-self-service)) | Create orders only — no post-purchase self-service |
72
- > | **Session** | 5-minute TTL, auto-refreshes | 1-minute, single-use |
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 buyer 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.
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 — buyer identity only (checkout page email field stays empty)
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 buyer identity required — the buyer fills in billing details manually on the checkout page.
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
- - Buyers can return to your site immediately after payment or if they close the checkout tab
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 buyers from returning to your site without browser back navigation.
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 buyer 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
+ 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}, Buyer: ${event.data.buyerEmail}`);
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
- ## Buyer Self-Service
230
+ ## Customer Self-Service
230
231
 
231
- Beyond checkout, you can let buyers manage their own orders and subscriptions — for example, embedding a "Cancel Subscription" or "Request Refund" button in your site.
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.buyer(token)` to get a session with self-service methods:
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 buyer
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 buyer session
243
- const buyer = client.buyer(token);
243
+ // Create a customer session
244
+ const customer = client.customer(token);
244
245
 
245
246
  // Cancel a subscription
246
- const { orderId, status } = await buyer.cancelSubscription({ orderId: "ORD_xxx" });
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 buyer.reactivateSubscription({ orderId: "ORD_xxx" });
251
+ await customer.reactivateSubscription({ orderId: "ORD_xxx" });
251
252
 
252
253
  // Cancel a one-time order (while payment is pending)
253
- await buyer.cancelOnetimeOrder({ orderId: "ORD_yyy" });
254
+ await customer.cancelOnetimeOrder({ orderId: "ORD_yyy" });
254
255
 
255
256
  // Submit a refund request
256
- const { ticket } = await buyer.createRefundTicket({
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 buyer.resubmitRefundTicket({
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 buyer's own orders via GraphQL
272
- const result = await buyer.graphql.query({
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 buyer identity — buyers can only access their own data. Token TTL is 5 minutes and auto-refreshes on each API call.
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 buyer can manage them later with a token issued here.
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` | `buyer.createRefundTicket` | `RefundTicket`, `Refund` |
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.buyer(token)` | `cancelSubscription()` `cancelOnetimeOrder()` `reactivateSubscription()` `createRefundTicket()` `resubmitRefundTicket()` | Buyer self-service |
535
- | `client.buyer(token).graphql` | `query<T>()` | Buyer-scoped GraphQL queries |
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 buyer session token (JWT) |
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
- ├── buyer-http-client.ts # HTTP client (Bearer token, buyer self-service)
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
- ├── buyer.ts
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/buyer-http-client.ts
56
+ // src/customer-http-client.ts
57
57
  var DEFAULT_BASE_URL = "https://api.waffo.ai";
58
- var BuyerHttpClient = class {
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 buyer.
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 buyer identity required)
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 — buyer fills everything on the page
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 buyer identity
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 buyer identity, empty form. */
507
+ /** Anonymous checkout — no customer identity, empty form. */
624
508
  anonymous;
625
- /** Authenticated checkout — merchant provides buyer identity. */
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 buyer session for self-service operations.
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 buyer session with self-service methods
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 buyer = client.buyer(token);
1357
- * await buyer.cancelSubscription({ orderId: "ORD_xxx" });
1356
+ * const customer = client.customer(token);
1357
+ * await customer.cancelSubscription({ orderId: "ORD_xxx" });
1358
1358
  */
1359
- buyer(token) {
1360
- const buyerHttp = new BuyerHttpClient(token, {
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 BuyerSession(buyerHttp);
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