@waffo/pancake-ts 0.11.0 → 0.12.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,18 @@ 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.12.0] - 2026-07-14
8
+
9
+ 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.
10
+
11
+ ### Changed
12
+
13
+ - **`client.customer(token)`** — creates the customer self-service session (class `CustomerSession`, previously `BuyerSession`). Same methods: `cancelSubscription()`, `cancelOnetimeOrder()`, `reactivateSubscription()`, `createRefundTicket()`, `resubmitRefundTicket()`, `graphql.query<T>()`.
14
+
15
+ ### Deprecated
16
+
17
+ - **`client.buyer(token)`** — use `client.customer(token)` instead. Thin wrapper around `client.customer()`, identical behavior; will be removed in a future major version.
18
+
7
19
  ## [0.11.0] - 2026-06-05
8
20
 
9
21
  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({
@@ -142,7 +142,7 @@ window.open(result.checkoutUrl, "_blank", "noopener,noreferrer");
142
142
 
143
143
  **We recommend opening the checkout page in a new tab** rather than navigating in the current page:
144
144
 
145
- - Buyers can return to your site immediately after payment or if they close the checkout tab
145
+ - Customers can return to your site immediately after payment or if they close the checkout tab
146
146
  - Merchant page state (cart, forms, scroll position) is preserved
147
147
  - Payment flow is decoupled from the browsing experience, reducing checkout abandonment
148
148
 
@@ -154,13 +154,13 @@ window.open(result.checkoutUrl, "_blank", "noopener,noreferrer");
154
154
  // <a href={checkoutUrl} target="_blank" rel="noopener noreferrer">Proceed to Checkout</a>
155
155
  ```
156
156
 
157
- > **Not recommended:** `window.location.href = result.checkoutUrl` replaces the current page, preventing buyers from returning to your site without browser back navigation.
157
+ > **Not recommended:** `window.location.href = result.checkoutUrl` replaces the current page, preventing customers from returning to your site without browser back navigation.
158
158
 
159
159
  See [API Reference — Checkout](docs/api-reference.md#checkout) for full parameter tables and `BillingDetail` field requirements.
160
160
 
161
161
  ## Webhook Verification
162
162
 
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:
163
+ 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
164
 
165
165
  ### Standalone Function (built-in keys)
166
166
 
@@ -179,7 +179,7 @@ app.post("/webhooks", express.raw({ type: "application/json" }), (req, res) => {
179
179
  case WebhookEventType.OrderCompleted:
180
180
  // Rich data: order, amount, product, payment fields
181
181
  console.log(`Order ${event.data.orderId} completed — ${event.data.total} ${event.data.currency}`);
182
- console.log(`Product: ${event.data.productName}, Buyer: ${event.data.buyerEmail}`);
182
+ console.log(`Product: ${event.data.productName}, Customer: ${event.data.buyerEmail}`);
183
183
  if (event.data.orderMetadata) console.log("Metadata:", event.data.orderMetadata);
184
184
  break;
185
185
  case WebhookEventType.SubscriptionActivated:
@@ -226,34 +226,34 @@ const event = client.webhooks.verify(rawBody, sig, { environment: "prod" });
226
226
 
227
227
  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
228
 
229
- ## Buyer Self-Service
229
+ ## Customer Self-Service
230
230
 
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.
231
+ 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
232
 
233
- Issue a session token, then use `client.buyer(token)` to get a session with self-service methods:
233
+ Issue a session token, then use `client.customer(token)` to get a session with self-service methods:
234
234
 
235
235
  ```typescript
236
- // Your backend — issue a session token for the buyer
236
+ // Your backend — issue a session token for the customer
237
237
  const { token } = await client.auth.issueSessionToken({
238
238
  storeId: "STO_xxx",
239
239
  buyerIdentity: req.user.email,
240
240
  });
241
241
 
242
- // Create a buyer session
243
- const buyer = client.buyer(token);
242
+ // Create a customer session
243
+ const customer = client.customer(token);
244
244
 
245
245
  // Cancel a subscription
246
- const { orderId, status } = await buyer.cancelSubscription({ orderId: "ORD_xxx" });
246
+ const { orderId, status } = await customer.cancelSubscription({ orderId: "ORD_xxx" });
247
247
  // status: "canceling" (active) or "canceled" (pending)
248
248
 
249
249
  // Reactivate a canceled subscription
250
- await buyer.reactivateSubscription({ orderId: "ORD_xxx" });
250
+ await customer.reactivateSubscription({ orderId: "ORD_xxx" });
251
251
 
252
252
  // Cancel a one-time order (while payment is pending)
253
- await buyer.cancelOnetimeOrder({ orderId: "ORD_yyy" });
253
+ await customer.cancelOnetimeOrder({ orderId: "ORD_yyy" });
254
254
 
255
255
  // Submit a refund request
256
- const { ticket } = await buyer.createRefundTicket({
256
+ const { ticket } = await customer.createRefundTicket({
257
257
  paymentId: "PAY_xxx",
258
258
  reason: "Product not as described",
259
259
  requestedAmount: { amount: "29.00", currency: "USD" },
@@ -261,22 +261,22 @@ const { ticket } = await buyer.createRefundTicket({
261
261
  });
262
262
 
263
263
  // Resubmit a rejected refund ticket
264
- await buyer.resubmitRefundTicket({
264
+ await customer.resubmitRefundTicket({
265
265
  ticketId: "TKT_xxx",
266
266
  paymentId: "PAY_xxx",
267
267
  reason: "Updated reason with more detail",
268
268
  requestedAmount: { amount: "29.00", currency: "USD" },
269
269
  });
270
270
 
271
- // Query the buyer's own orders via GraphQL
272
- const result = await buyer.graphql.query({
271
+ // Query the customer's own orders via GraphQL
272
+ const result = await customer.graphql.query({
273
273
  query: `query { orders { id status createdAt } }`,
274
274
  });
275
275
  ```
276
276
 
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.
277
+ 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
278
 
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.
279
+ > **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
280
 
281
281
  ## Business-Side Identifiers
282
282
 
@@ -285,7 +285,7 @@ Attach your own internal references to a checkout or a refund ticket so cross-sy
285
285
  | Field | Attach at | Inherited by |
286
286
  | -------------------------------- | ------------------------------------------- | ---------------------------------------------------------- |
287
287
  | `orderMerchantExternalId` | `checkout.{authenticated,anonymous}.create` | `Order`, `Payment` (incl. subscription renewals), `Refund` |
288
- | `refundTicketMerchantExternalId` | `buyer.createRefundTicket` | `RefundTicket`, `Refund` |
288
+ | `refundTicketMerchantExternalId` | `customer.createRefundTicket` | `RefundTicket`, `Refund` |
289
289
 
290
290
  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
291
 
@@ -531,11 +531,11 @@ try {
531
531
  | `client.checkout.authenticated` | `create()` | Authenticated checkout (recommended) |
532
532
  | `client.checkout.anonymous` | `create()` | Anonymous checkout |
533
533
  | `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 |
534
+ | `client.customer(token)` | `cancelSubscription()` `cancelOnetimeOrder()` `reactivateSubscription()` `createRefundTicket()` `resubmitRefundTicket()` | Customer self-service |
535
+ | `client.customer(token).graphql` | `query<T>()` | Customer-scoped GraphQL queries |
536
536
  | `client.webhooks` | `verify<T>()` `add()` `update()` `remove()` | Webhook config + signature verification |
537
537
  | `client.graphql` | `query<T>()` | Merchant GraphQL queries |
538
- | `client.auth` | `issueSessionToken()` | Issue a buyer session token (JWT) |
538
+ | `client.auth` | `issueSessionToken()` | Issue a customer session token (JWT) |
539
539
  | `client.stores` | `create()` `update()` `delete()` | Store management |
540
540
  | `client.storeMerchants` | `add()` `remove()` `updateRole()` | Store members (coming soon) |
541
541
  | `client.onetimeProducts` | `create()` `update()` `publish()` `updateStatus()` | One-time products |
@@ -603,7 +603,7 @@ src/
603
603
  ├── index.ts # Unified export entry
604
604
  ├── client.ts # WaffoPancake main class
605
605
  ├── http-client.ts # HTTP client (API Key, auto-signing + idempotency)
606
- ├── buyer-http-client.ts # HTTP client (Bearer token, buyer self-service)
606
+ ├── customer-http-client.ts # HTTP client (Bearer token, customer self-service)
607
607
  ├── signing.ts # RSA-SHA256 request signing
608
608
  ├── errors.ts # WaffoPancakeError
609
609
  ├── webhooks.ts # Webhook verification (embedded keys)
@@ -617,7 +617,7 @@ src/
617
617
  ├── onetime-products.ts
618
618
  ├── subscription-products.ts
619
619
  ├── subscription-product-groups.ts
620
- ├── buyer.ts
620
+ ├── customer.ts
621
621
  ├── orders.ts
622
622
  ├── checkout.ts
623
623
  ├── 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