@stardeck-customer-apps/testing 0.26.0 → 0.27.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/SKILL.md +33 -1
- package/dist/index.d.mts +81 -2
- package/dist/index.d.ts +81 -2
- package/dist/index.js +415 -16
- package/dist/index.mjs +415 -16
- package/dist/next/headers-shim.js +5 -0
- package/dist/next/headers-shim.mjs +5 -0
- package/dist/setup.js +319 -15
- package/dist/setup.mjs +319 -15
- package/package.json +5 -3
package/SKILL.md
CHANGED
|
@@ -216,6 +216,23 @@ app.payments.failNext("stripe.getCheckoutSessionStatus", {
|
|
|
216
216
|
// Beam payment links reject idempotencyKey ("idempotency_unsupported") and echo expiresAt.
|
|
217
217
|
// The simulator does not model Stripe's 24 h key retention.
|
|
218
218
|
|
|
219
|
+
// Stripe inline payments (payments-sdk >= 4.12.0): PaymentIntents, same routes and shapes as
|
|
220
|
+
// the platform. Card → clientSecret + actionRequired "CLIENT_CONFIRM"; PromptPay (THB only) →
|
|
221
|
+
// qr.imageUrlPng + "ENCODED_IMAGE". Events are built from the stored payment, so the webhook
|
|
222
|
+
// carries the amount, currency and metadata (incl. stardeckReferenceId, projectId) the app sent.
|
|
223
|
+
const pi = await payments.createStripePaymentIntent({
|
|
224
|
+
amount: 12000, currency: "thb", method: "promptpay",
|
|
225
|
+
referenceId: order.id, idempotencyKey: `attempt-${order.id}`, metadata: { orderId: order.id },
|
|
226
|
+
});
|
|
227
|
+
expect(pi.qr?.imageUrlPng).toBeTruthy();
|
|
228
|
+
app.payments.markPaid(pi.id); // the shopper scanned and paid
|
|
229
|
+
await app.payments.deliverStripeEvent(POST, { paymentIntentId: pi.id }); // payment_intent.succeeded
|
|
230
|
+
// app.payments.failPayment(pi.id, "card_declined") → payment_intent.payment_failed (retryable)
|
|
231
|
+
// app.payments.cancelPayment(pi.id) → payment_intent.canceled
|
|
232
|
+
app.payments.setStripePaymentMethods(["card"]); // merchant turned PromptPay off:
|
|
233
|
+
await expect(payments.createStripePaymentIntent({ ...req, method: "promptpay" }))
|
|
234
|
+
.rejects.toMatchObject({ statusCode: 422, code: "method_not_allowed" });
|
|
235
|
+
|
|
219
236
|
// File upload
|
|
220
237
|
const storage = new StorageClient();
|
|
221
238
|
await storage.upload(new File(["hi"], "note.txt", { type: "text/plain" }));
|
|
@@ -437,6 +454,19 @@ externalId })` helper models a trusted platform/channel link, and
|
|
|
437
454
|
`.setSessionStatus(id, status)`, `.setPaymentLinkStatus(id, status)`,
|
|
438
455
|
`.failNext(operation, failure)`,
|
|
439
456
|
`.deliverStripeEvent(handler, event)`, `.deliverBeamEvent(handler, event)`,
|
|
457
|
+
Stripe inline payments: `.stripePaymentIntents`, `.getStripePaymentIntent(id)`,
|
|
458
|
+
`.markPaid(piId)` (succeeds the PaymentIntent), `.failPayment(piId, code = "card_declined")`
|
|
459
|
+
(back to `requires_payment_method` with `lastPaymentError`), `.cancelPayment(piId)`,
|
|
460
|
+
`.deliverStripeEvent(handler, { paymentIntentId })` (sends `payment_intent.succeeded`,
|
|
461
|
+
`.payment_failed` or `.canceled` for the payment's current state, built from the stored
|
|
462
|
+
payment), `.setStripePaymentMethods(methods)` (the merchant's allowed methods, default
|
|
463
|
+
`["card", "promptpay"]`; readiness lists only these and create refuses others with 422
|
|
464
|
+
`method_not_allowed`), `.setStripeChargesEnabled(false)` (readiness not ready, create → 503
|
|
465
|
+
`account_not_ready`). Validation matches the platform (400 `invalid_request`, PromptPay
|
|
466
|
+
non-THB → 422 `currency_not_supported`, idempotent create, 409 `idempotency_conflict`, 409
|
|
467
|
+
`already_succeeded` on cancel after payment), and another project's payment id → 404
|
|
468
|
+
`not_found`. The app's `POST /api/payments/payment-intents` route refuses card (403
|
|
469
|
+
`CARD_CHARGE_SERVER_ONLY`); create card payments from server code.
|
|
440
470
|
Bolt+ controls: `.approveBoltIntent(id)`, `.declineBoltIntent(id)`,
|
|
441
471
|
`.expireBoltIntent(id)`, `.listBoltIntents()`, `.getBoltIntent(id)`,
|
|
442
472
|
`.count`, `.clear()`. Approve marks PAID and records a charge; deliver the
|
|
@@ -541,7 +571,7 @@ true })` remains source-compatible but the simulator (like the control plane)
|
|
|
541
571
|
- For merge-correct reads, request aliases in batches and include every id in
|
|
542
572
|
the returned canonical set. Page directory UIs through `search({ query,
|
|
543
573
|
cursor, limit })`; `list()` intentionally keeps its previous array shape.
|
|
544
|
-
- `PaymentsServerClient` (Stripe checkout + Beam payment links + Beam direct
|
|
574
|
+
- `PaymentsServerClient` (Stripe checkout + Stripe inline payments + Beam payment links + Beam direct
|
|
545
575
|
charges and card tokenization + Bolt+ connections/intents/charges, product list) — captured in `app.payments`;
|
|
546
576
|
fulfill checkout via `markPaid` (poll) or `deliverStripeEvent` /
|
|
547
577
|
`deliverBeamEvent` (webhook push). Drive a terminal without hardware via
|
|
@@ -556,6 +586,8 @@ cursor, limit })`; `list()` intentionally keeps its previous array shape.
|
|
|
556
586
|
one-shot HTTP or network failures during Stripe checkout creation/status polling
|
|
557
587
|
and Beam payment-link creation/status polling. The operation names are
|
|
558
588
|
`stripe.createCheckout`, `stripe.getCheckoutSessionStatus`,
|
|
589
|
+
`stripe.createPaymentIntent`, `stripe.getPaymentIntent`, `stripe.findPaymentIntents`,
|
|
590
|
+
`stripe.cancelPaymentIntent`, `stripe.getElementsConfig`, `stripe.getReadiness`,
|
|
559
591
|
`beam.createPaymentLink`, `beam.getPaymentLinkStatus`, `beam.createDirectCharge`,
|
|
560
592
|
and `beam.getCharge`. HTTP failures support
|
|
561
593
|
statuses 400, 402, 409, 429, 500, and 503 plus optional `code`, `details`, and
|
package/dist/index.d.mts
CHANGED
|
@@ -216,10 +216,10 @@ interface CapturedCheckout {
|
|
|
216
216
|
metadata?: Record<string, string>;
|
|
217
217
|
createdAt: Date;
|
|
218
218
|
}
|
|
219
|
-
type PaymentSimulatorOperation = "stripe.createCheckout" | "stripe.getCheckoutSessionStatus" | "beam.createPaymentLink" | "beam.getPaymentLinkStatus" | "beam.createDirectCharge" | "beam.getCharge";
|
|
219
|
+
type PaymentSimulatorOperation = "stripe.createCheckout" | "stripe.getCheckoutSessionStatus" | "beam.createPaymentLink" | "beam.getPaymentLinkStatus" | "beam.createDirectCharge" | "beam.getCharge" | "stripe.createPaymentIntent" | "stripe.getPaymentIntent" | "stripe.findPaymentIntents" | "stripe.cancelPaymentIntent" | "stripe.getElementsConfig" | "stripe.getReadiness";
|
|
220
220
|
type PaymentSimulatorFailure = {
|
|
221
221
|
kind?: "http";
|
|
222
|
-
status: 400 | 402 | 409 | 429 | 500 | 503;
|
|
222
|
+
status: 400 | 402 | 404 | 409 | 422 | 429 | 500 | 502 | 503;
|
|
223
223
|
message: string;
|
|
224
224
|
code?: string;
|
|
225
225
|
details?: unknown;
|
|
@@ -295,19 +295,98 @@ interface SimDirectCharge {
|
|
|
295
295
|
idempotencyKey: string | null;
|
|
296
296
|
createdAt: string;
|
|
297
297
|
}
|
|
298
|
+
/** Inline Stripe payment methods (mirrors the payments SDK's `StripePaymentMethod`). */
|
|
299
|
+
type SimStripePaymentMethod = "card" | "promptpay";
|
|
300
|
+
/** A Stripe PaymentIntent as the simulator holds it. */
|
|
301
|
+
interface SimStripePaymentIntent {
|
|
302
|
+
id: string;
|
|
303
|
+
/** The project whose signed request created it; other projects get 404. */
|
|
304
|
+
projectId: string;
|
|
305
|
+
/** The account selector from the request path (`acct_…`, "default", "playground"). */
|
|
306
|
+
account: string;
|
|
307
|
+
/** The connected account it lives on; null on the playground. */
|
|
308
|
+
connectedAccountId: string | null;
|
|
309
|
+
playground: boolean;
|
|
310
|
+
status: "requires_payment_method" | "requires_confirmation" | "requires_action" | "processing" | "requires_capture" | "canceled" | "succeeded";
|
|
311
|
+
amount: number;
|
|
312
|
+
/** Lowercase. */
|
|
313
|
+
currency: string;
|
|
314
|
+
method: SimStripePaymentMethod;
|
|
315
|
+
referenceId: string;
|
|
316
|
+
/** The app's metadata, with Stardeck's reserved keys removed. */
|
|
317
|
+
appMetadata: Record<string, string>;
|
|
318
|
+
/** What Stripe holds: app metadata plus `projectId` and `stardeckReferenceId`. */
|
|
319
|
+
metadata: Record<string, string>;
|
|
320
|
+
description: string | null;
|
|
321
|
+
receiptEmail: string | null;
|
|
322
|
+
returnUrl: string | null;
|
|
323
|
+
clientSecret: string;
|
|
324
|
+
qr: {
|
|
325
|
+
imageUrlPng: string;
|
|
326
|
+
imageUrlSvg: string | null;
|
|
327
|
+
data: string | null;
|
|
328
|
+
hostedInstructionsUrl: string | null;
|
|
329
|
+
expiresAt: number | null;
|
|
330
|
+
} | null;
|
|
331
|
+
latestChargeId: string | null;
|
|
332
|
+
amountRefunded: number;
|
|
333
|
+
lastPaymentError: {
|
|
334
|
+
code: string | null;
|
|
335
|
+
declineCode: string | null;
|
|
336
|
+
message: string | null;
|
|
337
|
+
} | null;
|
|
338
|
+
/** Unix seconds. */
|
|
339
|
+
created: number;
|
|
340
|
+
}
|
|
298
341
|
interface TestPayments {
|
|
299
342
|
get checkouts(): CapturedCheckout[];
|
|
300
343
|
latest(): CapturedCheckout | undefined;
|
|
301
344
|
setProducts(products: _stardeck_customer_apps_payments_sdk.Product[]): void;
|
|
302
345
|
/** Fail the next matching SDK request once, then resume normal simulator behavior. */
|
|
303
346
|
failNext(operation: PaymentSimulatorOperation, failure: PaymentSimulatorFailure): void;
|
|
347
|
+
/**
|
|
348
|
+
* The customer paid. Takes a Stripe Checkout session id, a Beam payment link
|
|
349
|
+
* id, or a Stripe PaymentIntent id (`pi_sim_…`). For a PaymentIntent, follow
|
|
350
|
+
* with `deliverStripeEvent(handler, { paymentIntentId })` to send the
|
|
351
|
+
* `payment_intent.succeeded` webhook.
|
|
352
|
+
*/
|
|
304
353
|
markPaid(id: string): void;
|
|
354
|
+
/**
|
|
355
|
+
* A Stripe PaymentIntent's payment attempt failed with `code` (default
|
|
356
|
+
* "card_declined"). It goes back to `requires_payment_method` with
|
|
357
|
+
* `lastPaymentError` set; deliver `payment_intent.payment_failed` with
|
|
358
|
+
* `deliverStripeEvent(handler, { paymentIntentId })`.
|
|
359
|
+
*/
|
|
360
|
+
failPayment(paymentIntentId: string, code?: string): void;
|
|
361
|
+
/**
|
|
362
|
+
* The Stripe PaymentIntent was canceled outside the app (expired QR, merchant
|
|
363
|
+
* dashboard). Deliver `payment_intent.canceled` with `deliverStripeEvent`.
|
|
364
|
+
*/
|
|
365
|
+
cancelPayment(paymentIntentId: string): void;
|
|
366
|
+
/** Every Stripe PaymentIntent created so far, oldest first, as stored. */
|
|
367
|
+
get stripePaymentIntents(): SimStripePaymentIntent[];
|
|
368
|
+
getStripePaymentIntent(paymentIntentId: string): SimStripePaymentIntent | undefined;
|
|
369
|
+
/**
|
|
370
|
+
* The inline Stripe methods the merchant allows (default `["card", "promptpay"]`).
|
|
371
|
+
* Create refuses others with 422 `method_not_allowed`; readiness lists only these.
|
|
372
|
+
*/
|
|
373
|
+
setStripePaymentMethods(methods: SimStripePaymentMethod[]): void;
|
|
374
|
+
/** Turn Stripe charges off (readiness not ready; create → 503 `account_not_ready`). On by default. */
|
|
375
|
+
setStripeChargesEnabled(enabled: boolean): void;
|
|
305
376
|
setSessionStatus(id: string, status: Partial<_stardeck_customer_apps_payments_sdk.CheckoutSessionStatus>): void;
|
|
306
377
|
setPaymentLinkStatus(id: string, status: _stardeck_customer_apps_payments_sdk.BeamPaymentLinkStatus): void;
|
|
378
|
+
/**
|
|
379
|
+
* Deliver a Stripe webhook to the app's payments route, signed like the
|
|
380
|
+
* platform. Pass `{ paymentIntentId }` to send the `payment_intent.*` event
|
|
381
|
+
* for that PaymentIntent's current state, built from the stored intent
|
|
382
|
+
* (amount, currency, metadata incl. `stardeckReferenceId` and `projectId`).
|
|
383
|
+
*/
|
|
307
384
|
deliverStripeEvent(handler: PaymentsWebhookHandler, event: {
|
|
308
385
|
type: string;
|
|
309
386
|
data: unknown;
|
|
310
387
|
accountId?: string;
|
|
388
|
+
} | {
|
|
389
|
+
paymentIntentId: string;
|
|
311
390
|
}, options?: {
|
|
312
391
|
path?: string;
|
|
313
392
|
deploymentSecret?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -216,10 +216,10 @@ interface CapturedCheckout {
|
|
|
216
216
|
metadata?: Record<string, string>;
|
|
217
217
|
createdAt: Date;
|
|
218
218
|
}
|
|
219
|
-
type PaymentSimulatorOperation = "stripe.createCheckout" | "stripe.getCheckoutSessionStatus" | "beam.createPaymentLink" | "beam.getPaymentLinkStatus" | "beam.createDirectCharge" | "beam.getCharge";
|
|
219
|
+
type PaymentSimulatorOperation = "stripe.createCheckout" | "stripe.getCheckoutSessionStatus" | "beam.createPaymentLink" | "beam.getPaymentLinkStatus" | "beam.createDirectCharge" | "beam.getCharge" | "stripe.createPaymentIntent" | "stripe.getPaymentIntent" | "stripe.findPaymentIntents" | "stripe.cancelPaymentIntent" | "stripe.getElementsConfig" | "stripe.getReadiness";
|
|
220
220
|
type PaymentSimulatorFailure = {
|
|
221
221
|
kind?: "http";
|
|
222
|
-
status: 400 | 402 | 409 | 429 | 500 | 503;
|
|
222
|
+
status: 400 | 402 | 404 | 409 | 422 | 429 | 500 | 502 | 503;
|
|
223
223
|
message: string;
|
|
224
224
|
code?: string;
|
|
225
225
|
details?: unknown;
|
|
@@ -295,19 +295,98 @@ interface SimDirectCharge {
|
|
|
295
295
|
idempotencyKey: string | null;
|
|
296
296
|
createdAt: string;
|
|
297
297
|
}
|
|
298
|
+
/** Inline Stripe payment methods (mirrors the payments SDK's `StripePaymentMethod`). */
|
|
299
|
+
type SimStripePaymentMethod = "card" | "promptpay";
|
|
300
|
+
/** A Stripe PaymentIntent as the simulator holds it. */
|
|
301
|
+
interface SimStripePaymentIntent {
|
|
302
|
+
id: string;
|
|
303
|
+
/** The project whose signed request created it; other projects get 404. */
|
|
304
|
+
projectId: string;
|
|
305
|
+
/** The account selector from the request path (`acct_…`, "default", "playground"). */
|
|
306
|
+
account: string;
|
|
307
|
+
/** The connected account it lives on; null on the playground. */
|
|
308
|
+
connectedAccountId: string | null;
|
|
309
|
+
playground: boolean;
|
|
310
|
+
status: "requires_payment_method" | "requires_confirmation" | "requires_action" | "processing" | "requires_capture" | "canceled" | "succeeded";
|
|
311
|
+
amount: number;
|
|
312
|
+
/** Lowercase. */
|
|
313
|
+
currency: string;
|
|
314
|
+
method: SimStripePaymentMethod;
|
|
315
|
+
referenceId: string;
|
|
316
|
+
/** The app's metadata, with Stardeck's reserved keys removed. */
|
|
317
|
+
appMetadata: Record<string, string>;
|
|
318
|
+
/** What Stripe holds: app metadata plus `projectId` and `stardeckReferenceId`. */
|
|
319
|
+
metadata: Record<string, string>;
|
|
320
|
+
description: string | null;
|
|
321
|
+
receiptEmail: string | null;
|
|
322
|
+
returnUrl: string | null;
|
|
323
|
+
clientSecret: string;
|
|
324
|
+
qr: {
|
|
325
|
+
imageUrlPng: string;
|
|
326
|
+
imageUrlSvg: string | null;
|
|
327
|
+
data: string | null;
|
|
328
|
+
hostedInstructionsUrl: string | null;
|
|
329
|
+
expiresAt: number | null;
|
|
330
|
+
} | null;
|
|
331
|
+
latestChargeId: string | null;
|
|
332
|
+
amountRefunded: number;
|
|
333
|
+
lastPaymentError: {
|
|
334
|
+
code: string | null;
|
|
335
|
+
declineCode: string | null;
|
|
336
|
+
message: string | null;
|
|
337
|
+
} | null;
|
|
338
|
+
/** Unix seconds. */
|
|
339
|
+
created: number;
|
|
340
|
+
}
|
|
298
341
|
interface TestPayments {
|
|
299
342
|
get checkouts(): CapturedCheckout[];
|
|
300
343
|
latest(): CapturedCheckout | undefined;
|
|
301
344
|
setProducts(products: _stardeck_customer_apps_payments_sdk.Product[]): void;
|
|
302
345
|
/** Fail the next matching SDK request once, then resume normal simulator behavior. */
|
|
303
346
|
failNext(operation: PaymentSimulatorOperation, failure: PaymentSimulatorFailure): void;
|
|
347
|
+
/**
|
|
348
|
+
* The customer paid. Takes a Stripe Checkout session id, a Beam payment link
|
|
349
|
+
* id, or a Stripe PaymentIntent id (`pi_sim_…`). For a PaymentIntent, follow
|
|
350
|
+
* with `deliverStripeEvent(handler, { paymentIntentId })` to send the
|
|
351
|
+
* `payment_intent.succeeded` webhook.
|
|
352
|
+
*/
|
|
304
353
|
markPaid(id: string): void;
|
|
354
|
+
/**
|
|
355
|
+
* A Stripe PaymentIntent's payment attempt failed with `code` (default
|
|
356
|
+
* "card_declined"). It goes back to `requires_payment_method` with
|
|
357
|
+
* `lastPaymentError` set; deliver `payment_intent.payment_failed` with
|
|
358
|
+
* `deliverStripeEvent(handler, { paymentIntentId })`.
|
|
359
|
+
*/
|
|
360
|
+
failPayment(paymentIntentId: string, code?: string): void;
|
|
361
|
+
/**
|
|
362
|
+
* The Stripe PaymentIntent was canceled outside the app (expired QR, merchant
|
|
363
|
+
* dashboard). Deliver `payment_intent.canceled` with `deliverStripeEvent`.
|
|
364
|
+
*/
|
|
365
|
+
cancelPayment(paymentIntentId: string): void;
|
|
366
|
+
/** Every Stripe PaymentIntent created so far, oldest first, as stored. */
|
|
367
|
+
get stripePaymentIntents(): SimStripePaymentIntent[];
|
|
368
|
+
getStripePaymentIntent(paymentIntentId: string): SimStripePaymentIntent | undefined;
|
|
369
|
+
/**
|
|
370
|
+
* The inline Stripe methods the merchant allows (default `["card", "promptpay"]`).
|
|
371
|
+
* Create refuses others with 422 `method_not_allowed`; readiness lists only these.
|
|
372
|
+
*/
|
|
373
|
+
setStripePaymentMethods(methods: SimStripePaymentMethod[]): void;
|
|
374
|
+
/** Turn Stripe charges off (readiness not ready; create → 503 `account_not_ready`). On by default. */
|
|
375
|
+
setStripeChargesEnabled(enabled: boolean): void;
|
|
305
376
|
setSessionStatus(id: string, status: Partial<_stardeck_customer_apps_payments_sdk.CheckoutSessionStatus>): void;
|
|
306
377
|
setPaymentLinkStatus(id: string, status: _stardeck_customer_apps_payments_sdk.BeamPaymentLinkStatus): void;
|
|
378
|
+
/**
|
|
379
|
+
* Deliver a Stripe webhook to the app's payments route, signed like the
|
|
380
|
+
* platform. Pass `{ paymentIntentId }` to send the `payment_intent.*` event
|
|
381
|
+
* for that PaymentIntent's current state, built from the stored intent
|
|
382
|
+
* (amount, currency, metadata incl. `stardeckReferenceId` and `projectId`).
|
|
383
|
+
*/
|
|
307
384
|
deliverStripeEvent(handler: PaymentsWebhookHandler, event: {
|
|
308
385
|
type: string;
|
|
309
386
|
data: unknown;
|
|
310
387
|
accountId?: string;
|
|
388
|
+
} | {
|
|
389
|
+
paymentIntentId: string;
|
|
311
390
|
}, options?: {
|
|
312
391
|
path?: string;
|
|
313
392
|
deploymentSecret?: string;
|