@agent-cards/sdk 0.23.21 → 0.23.23

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.
Files changed (56) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/PREFLIGHT.md +4 -0
  3. package/README.md +53 -4
  4. package/dist/aci.generated.js +3 -3
  5. package/dist/agent-amount.generated.d.ts +7 -0
  6. package/dist/agent-amount.generated.js +3 -0
  7. package/dist/amadeus-checkout.generated.d.ts +6 -1
  8. package/dist/amadeus-checkout.generated.js +26 -2
  9. package/dist/capabilities.generated.d.ts +2 -0
  10. package/dist/capabilities.generated.js +3 -0
  11. package/dist/card-fields.generated.js +2574 -186
  12. package/dist/cdp.js +103 -29
  13. package/dist/client.d.ts +130 -9
  14. package/dist/client.js +304 -115
  15. package/dist/creditguard.generated.js +4 -2
  16. package/dist/cse-body.js +11 -0
  17. package/dist/ebanx.d.ts +1 -1
  18. package/dist/ebanx.js +1 -1
  19. package/dist/eximbay.d.ts +46 -0
  20. package/dist/eximbay.js +69 -0
  21. package/dist/hosted-entry.js +2 -1
  22. package/dist/hosted-form.d.ts +5 -0
  23. package/dist/hosted-form.js +5 -0
  24. package/dist/lifecycle.d.ts +9 -4
  25. package/dist/lifecycle.js +16 -4
  26. package/dist/paygent.generated.d.ts +60 -0
  27. package/dist/paygent.generated.js +425 -0
  28. package/dist/payrexx.d.ts +91 -0
  29. package/dist/payrexx.generated.d.ts +91 -0
  30. package/dist/payrexx.generated.js +536 -0
  31. package/dist/payrexx.js +141 -0
  32. package/dist/paytrail.d.ts +58 -0
  33. package/dist/paytrail.js +98 -0
  34. package/dist/pre-claim.d.ts +27 -0
  35. package/dist/pre-claim.js +175 -20
  36. package/dist/prepared-processor.d.ts +7 -2
  37. package/dist/prepared-processor.js +16 -2
  38. package/dist/primer.generated.js +2709 -321
  39. package/dist/registry.d.ts +4 -3
  40. package/dist/registry.js +12 -4
  41. package/dist/sbps.d.ts +57 -0
  42. package/dist/sbps.generated.d.ts +96 -0
  43. package/dist/sbps.generated.js +427 -0
  44. package/dist/sbps.js +90 -0
  45. package/dist/stripe-checkout.generated.js +744 -27
  46. package/dist/toast-seal.generated.d.ts +37 -0
  47. package/dist/toast-seal.generated.js +625 -0
  48. package/dist/toast.generated.d.ts +41 -0
  49. package/dist/toast.generated.js +113 -0
  50. package/dist/transbank.d.ts +33 -0
  51. package/dist/transbank.js +62 -0
  52. package/dist/url-mask-parts.d.ts +24 -0
  53. package/dist/url-mask-parts.js +22 -0
  54. package/dist/url-masks.generated.d.ts +3 -0
  55. package/dist/url-masks.generated.js +2 -0
  56. package/package.json +4 -4
package/dist/pre-claim.js CHANGED
@@ -80,12 +80,14 @@ import { cardEndpointCarriesCard, cardEndpointDetail, cardEndpointFor, cardEndpo
80
80
  import { cardEndpointStoppedPage, refusedNavigationOutcome } from './card-endpoint-page.js';
81
81
  import { PAYRAILS_HOLDING_REASONS, PAYRAILS_SESSION_MESSAGE, isPayrailsHost, isPayrailsPaymentUrl, isPayrailsStaticHost, payrailsKeyRefusal, payrailsPaymentRefusal, payrailsRequestKind, payrailsSaveRefusal, } from './payrails.js';
82
82
  import { classifyVerifoneProfileRequest, verifoneTemplatedUrl } from './verifone.js';
83
+ import { isPaymentHighwayCardLookup, isPaymentHighwayHost, isPaytrailCardMethodUrl, isPaytrailEntry, isPaytrailServed } from './paytrail.js';
83
84
  import { ekashuEntryUrl, isEkashuEntry, isEkashuHost } from './ekashu.js';
84
85
  import { isArmedTransbankUrl } from './transbank.js';
85
86
  import { isRedsysEntry, isRedsysHost, redsysEntryUrl } from './redsys.js';
86
87
  import { isArmedPrzelewy24Url, isPrzelewy24PayStep } from './przelewy24.js';
87
88
  import { isQuickpayCardLookup, isQuickpayEntry, quickpayEntryUrl } from './quickpay.js';
88
89
  import { isArmedComgateUrl } from './comgate.js';
90
+ import { isArmedEximbayUrl, isEximbayEntry } from './eximbay.js';
89
91
  import { PAYPAL_HOSTED_FIELDS_REASON, isPaypalHostedFieldsConfirm, paypalHostedFieldsBody } from './paypal-hosted-fields.js';
90
92
  import { PAYPAL_CARD_FIELDS_REASON, PAYPAL_GUEST_CHECKOUT_REASON, isPaypalCardFieldsConfirm, isPaypalGraphql, paypalCardFieldsBody, paypalGraphqlCard, paypalGraphqlNamesCardOperation, } from './paypal-card-forms.js';
91
93
  import { CYBERSOURCE_SECURE_ACCEPTANCE_REASON, CYBERSOURCE_SECURE_ACCEPTANCE_RECIPIENT, cybersourceSecureAcceptanceRequest, isCybersourceSecureAcceptanceUrl, isSecureAcceptanceFramePost, } from './cybersource-secure-acceptance.js';
@@ -93,6 +95,7 @@ import { isWorldlineMyCheckoutEndpoint } from './worldline-mycheckout.js';
93
95
  import { paddleVgsPayEventUrl } from './paddle-vgs-pay.js';
94
96
  import { HIPAY_PSP, HIPAY_TOKEN_URLS, HIPAY_UPDATE_PATH, HIPAY_VAULT_HOSTS, hipayNumberOnlyRequest } from './hipay.generated.js';
95
97
  import { EBANX_RESEND_REASON, EbanxFollowUpError, ebanxResendRefusalOf, isEbanxResendUrl, } from './ebanx.js';
98
+ import { PAYREXX_RESEND_REASON, PayrexxFollowUpError, isPayrexxResend, } from './payrexx.js';
96
99
  /**
97
100
  * The URL an event may name for a request. For an armed merchant profile's
98
101
  * endpoint or a sibling of it: the endpoint origin, the path TEMPLATE and the
@@ -1507,6 +1510,23 @@ const eprotectPreClaim = (ctx) => {
1507
1510
  return eprotectFailoverAbort(ctx);
1508
1511
  return unsupportedAbort(ctx);
1509
1512
  };
1513
+ // SB Payment Service, once the registry serves it (a synced build that declares its capability, for
1514
+ // an org the API enabled); for every other client the gate defers on everything, so nothing changes.
1515
+ // On SBPS's token hosts:
1516
+ // - the token request GET the recognizer admits defers to the arbiter, which pauses it for the vault
1517
+ // claim flow; one the registry does not cover aborts as unsupported instead of reaching SBPS;
1518
+ // - any other request on /token/generateToken (another method, query or spelling) aborts as an
1519
+ // unsupported checkout, so the placeholder's ciphertext never leaves;
1520
+ // - everything else there (the scripts, the 3-D Secure info request) continues.
1521
+ // Synchronous for a token request, so it pauses in the microtask it paused in.
1522
+ const sbpsPreClaim = (ctx) => {
1523
+ const request = ctx.sbps?.classify(ctx.request.url, ctx.request.method);
1524
+ if (!request || request.kind === 'sibling')
1525
+ return undefined;
1526
+ if (request.kind === 'token_request')
1527
+ return ctx.vault.isCardRequest(ctx.request.url, ctx.request.method) ? undefined : unsupportedAbort(ctx);
1528
+ return unsupportedAbort(ctx);
1529
+ };
1510
1530
  async function eprotectFailoverAbort(ctx) {
1511
1531
  ctx.onEvent?.({ type: 'blocked', detail: 'eprotect_failover_aborted' });
1512
1532
  await ctx.effects.abort();
@@ -1667,7 +1687,7 @@ export const ekashuPreClaim = (ctx) => {
1667
1687
  return processorPageAbort(ctx);
1668
1688
  };
1669
1689
  // The stop for a card post into a processor's own page that only the cardholder's device may pay (NMI's, Redsys's,
1670
- // QuickPay's).
1690
+ // QuickPay's, Eximbay's).
1671
1691
  async function processorPageAbort(ctx) {
1672
1692
  const { url, method } = ctx.request;
1673
1693
  ctx.preparationGate.invalidate('unsupported_checkout');
@@ -1697,6 +1717,32 @@ export const transbankPreClaim = (ctx) => {
1697
1717
  return undefined;
1698
1718
  return processorPageAbort(ctx);
1699
1719
  };
1720
+ // Paytrail's card method (paytrail.ts). Once this build's registry serves Paytrail's entry (a capability the API serves
1721
+ // only to a company Agentcard turned Paytrail on for), every request to Paytrail's entry host and to Payment Highway's
1722
+ // card page host pauses, and this gate judges the card method's posts and the card page's card lookup:
1723
+ // - the merchant's entry (the card method's loading-and-redirect route for one transaction, exactly) defers, and the
1724
+ // terminal arbiter pauses it for the claim flow like any card request: the cardholder's device pays it;
1725
+ // - every other post of the card method on Paytrail's host (the loading page's post to initialize-payment, which
1726
+ // opens Payment Highway's card page, or the entry in another spelling) aborts as an unsupported checkout, and so do
1727
+ // every POST to Payment Highway (the card post, the Click to Pay posts, the 3-D Secure step, the older card form's
1728
+ // post) and the card page's GET that looks up the typed card's first digits, so Payment Highway never sees the card
1729
+ // the agent typed. The agent's browser reaches Payment Highway only when the entry was not paused (an attachment
1730
+ // made too late, say), and then only the cardholder's device can pay.
1731
+ // Any other request (another payment method's form, the card page itself, its scripts and images) is not this gate's
1732
+ // and continues. With Paytrail not served, the entry is no card request, the gate defers, and every request continues
1733
+ // as before. Synchronous until it must abort, like every gate. Exported for the gate registry's tests.
1734
+ export const paytrailPreClaim = (ctx) => {
1735
+ const { url, method } = ctx.request;
1736
+ const post = String(method).toUpperCase() === 'POST';
1737
+ const paymentHighway = isPaymentHighwayHost(url) && (post || isPaymentHighwayCardLookup(url, method));
1738
+ if (!paymentHighway && !(post && isPaytrailCardMethodUrl(url)))
1739
+ return undefined;
1740
+ if (!isPaytrailServed(ctx.vault))
1741
+ return undefined;
1742
+ if (isPaytrailEntry(url, method))
1743
+ return undefined;
1744
+ return processorPageAbort(ctx);
1745
+ };
1700
1746
  // Redsys's hosted payment page (redsys.ts). Once this build's registry serves Redsys's entry (a
1701
1747
  // capability the API serves only to a company Agentcard turned Redsys on for), every request to
1702
1748
  // Redsys's hosts pauses, and this gate judges the POSTs:
@@ -1762,6 +1808,25 @@ export const comgatePreClaim = (ctx) => {
1762
1808
  return undefined;
1763
1809
  return processorPageAbort(ctx);
1764
1810
  };
1811
+ // Eximbay's payment window (eximbay.ts). Once this build's registry serves Eximbay's entry on a host (a capability the
1812
+ // API serves only to a company Agentcard turned Eximbay on for), every request to that host pauses, and this gate
1813
+ // judges the POSTs:
1814
+ // - the merchant's entry (the entry path exactly, no query) defers, and the terminal arbiter pauses it for the claim
1815
+ // flow like any card request: the cardholder's device pays it;
1816
+ // - every other POST to Eximbay (the step that opens the window, the window's amount query and its card lookup,
1817
+ // which carries the typed card's first eight digits, its card post, and its close and method posts) aborts as an
1818
+ // unsupported checkout, so Eximbay never sees the card the agent typed. The agent's browser only reaches Eximbay's
1819
+ // window when the entry was not paused (an attachment made too late, say), and then only the cardholder's device
1820
+ // can pay.
1821
+ // A GET (the window's scripts and images) is not this gate's and continues. With Eximbay not served, the entry is no
1822
+ // card request, the gate defers, and every request continues as before. Synchronous until it must abort, like every
1823
+ // gate. Exported for the gate registry's tests.
1824
+ export const eximbayPreClaim = (ctx) => {
1825
+ const { url, method } = ctx.request;
1826
+ if (String(method).toUpperCase() !== 'POST' || !isArmedEximbayUrl(ctx.vault, url) || isEximbayEntry(url, method))
1827
+ return undefined;
1828
+ return processorPageAbort(ctx);
1829
+ };
1765
1830
  // PayPal's legacy Hosted Fields (paypal-hosted-fields.ts). Its tokenization frame posts the card the
1766
1831
  // agent typed to the Orders v2 confirm-payment-source on cors.api.paypal.com (or its sandbox), which
1767
1832
  // no Vault mode takes over, so every company's adapters hand each POST there to this gate:
@@ -2144,7 +2209,7 @@ async function hipayRefused(ctx, reason) {
2144
2209
  // again. A checkout whose token request was already approved keeps that approval's state (lifecycle.unsupported),
2145
2210
  // and its follow-ups stop (EbanxFollowUps.stop): a later request the approval would cover is refused too, so the
2146
2211
  // page cannot finish 3-D Secure and pay through the confirm after a refusal. A failed send stops them the same way.
2147
- // A send goes on only while the checkout itself names the remembered approval (ebanxMaySend): it awaits the
2212
+ // A send goes on only while the checkout itself names the remembered approval (followUpMaySend): it awaits the
2148
2213
  // merchant, reports the bank's challenge, or holds that approval's answer for the page (awaiting_approval while
2149
2214
  // the token's answer is on its way, since the adapters remember the approval before they hand the answer over, or
2150
2215
  // ready_to_submit while the approval waits for the page's retry). A new token request awaiting the person, a new
@@ -2173,38 +2238,39 @@ export const ebanxPreClaim = (ctx) => {
2173
2238
  catch {
2174
2239
  body = null;
2175
2240
  }
2176
- const claim = ctx.ebanx && typeof ctx.vault.sendEbanxFollowUp === 'function' && ebanxMaySend(ctx)
2241
+ const claim = ctx.ebanx && typeof ctx.vault.sendEbanxFollowUp === 'function' && followUpMaySend(ctx, ctx.ebanx)
2177
2242
  ? ctx.ebanx.claim({ url, method: 'POST', headers: ctx.request.headers ?? {}, body }) : null;
2178
2243
  return claim ? ebanxFollowUp(ctx, claim) : ebanxResendRefused(ctx, refusal);
2179
2244
  };
2180
2245
  /**
2181
2246
  * The checkout states in which a send may go on under the remembered approval, an allowlist: the checkout awaits the
2182
- * merchant, the application reported the bank's challenge (requestUserAction), the token's answer is still on its way
2247
+ * merchant, the application reported the bank's challenge (requestUserAction), the approved answer is still on its way
2183
2248
  * to the page (awaiting_approval: the page may send its first 3-D Secure call the moment the answer lands), or the
2184
2249
  * approval waits for the page's retry (ready_to_submit). Every other state refuses, idle and the final ones among them.
2250
+ * The same for EBANX's sends and Payrexx's.
2185
2251
  */
2186
- const EBANX_SENDING_STATES = new Set(['awaiting_merchant', 'requires_user_action', 'awaiting_approval', 'ready_to_submit']);
2252
+ const FOLLOW_UP_SENDING_STATES = new Set(['awaiting_merchant', 'requires_user_action', 'awaiting_approval', 'ready_to_submit']);
2187
2253
  /**
2188
2254
  * Whether a send may go on: nothing aborted the checkout, no reconciliation of the merchant's order is running (one
2189
2255
  * that resolves failed while a confirm is out would let the application start another attempt), it is in one of
2190
- * EBANX_SENDING_STATES, and its state names the approval the attachment remembered. A new token request awaiting the
2191
- * person (awaiting_approval with no approval, or another one), a new attempt after a merchant failure, a prepared
2192
- * checkout and another approval's state all refuse.
2256
+ * FOLLOW_UP_SENDING_STATES, and its state names the approval the attachment remembered (`followUps`, EBANX's or
2257
+ * Payrexx's). A new card request awaiting the person (awaiting_approval with no approval, or another one), a new
2258
+ * attempt after a merchant failure, a prepared checkout and another approval's state all refuse.
2193
2259
  */
2194
- function ebanxMaySend(ctx) {
2195
- if (ctx.lifecycleAborted() || ctx.terminal() || !ctx.ebanx || ctx.lifecycle.isReconciling())
2260
+ function followUpMaySend(ctx, followUps) {
2261
+ if (ctx.lifecycleAborted() || ctx.terminal() || !followUps || ctx.lifecycle.isReconciling())
2196
2262
  return false;
2197
- const approval = ctx.ebanx.authorizationId;
2263
+ const approval = followUps.authorizationId;
2198
2264
  const state = ctx.lifecycle.getState();
2199
- return approval !== null && EBANX_SENDING_STATES.has(state.status) && state.authorizationId === approval;
2265
+ return approval !== null && FOLLOW_UP_SENDING_STATES.has(state.status) && state.authorizationId === approval;
2200
2266
  }
2201
2267
  /**
2202
2268
  * The checkout's final merchant results: completed, failed, declined, timed out, cancelled, an unknown outcome, or an
2203
2269
  * unsupported request. A 3-D Secure call, which charges nothing, that fails in one of them leaves that outcome alone.
2204
2270
  */
2205
- const EBANX_FINAL_STATES = new Set(['completed', 'failed', 'declined', 'timed_out', 'cancelled', 'outcome_unknown', 'unsupported']);
2206
- /** Whether the checkout already ended (EBANX_FINAL_STATES): its state and reason stand, whatever a later 3-D Secure call does. */
2207
- const ebanxCheckoutEnded = (ctx) => EBANX_FINAL_STATES.has(ctx.lifecycle.getState().status);
2271
+ const FOLLOW_UP_FINAL_STATES = new Set(['completed', 'failed', 'declined', 'timed_out', 'cancelled', 'outcome_unknown', 'unsupported']);
2272
+ /** Whether the checkout already ended (FOLLOW_UP_FINAL_STATES): its state and reason stand, whatever a later 3-D Secure call does. */
2273
+ const followUpCheckoutEnded = (ctx) => FOLLOW_UP_FINAL_STATES.has(ctx.lifecycle.getState().status);
2208
2274
  /**
2209
2275
  * A confirm whose card may have reached EBANX and whose answer the page never got: only a payment the merchant
2210
2276
  * already confirmed (completed) stands, and every other state of this approval turns unknown, since EBANX may have
@@ -2245,7 +2311,7 @@ async function ebanxUnreadable(ctx) {
2245
2311
  * (CheckoutLifecycle.followUpStarted): meanwhile reconcile() and retryAfterMerchantFailure() throw, so the application
2246
2312
  * starts no other attempt while a confirm may pay. A confirm that may have left keeps only a payment the merchant
2247
2313
  * confirmed (completed); any other state of its approval turns unknown (ebanxConfirmUnconfirmed). Any other send keeps
2248
- * a final outcome (EBANX_FINAL_STATES) with its reason.
2314
+ * a final outcome (FOLLOW_UP_FINAL_STATES) with its reason.
2249
2315
  */
2250
2316
  async function ebanxFollowUp(ctx, claim) {
2251
2317
  const settle = ctx.lifecycle.followUpStarted();
@@ -2271,7 +2337,7 @@ async function sendEbanxFollowUp(ctx, claim) {
2271
2337
  ctx.onEvent?.({ type: 'ebanx_follow_up_failed', detail: { ...detail, reason, cardSent } });
2272
2338
  if (cardSent && claim.kind === 'confirm')
2273
2339
  ebanxConfirmUnconfirmed(ctx, claim.authorizationId, 'ebanx_confirm_unconfirmed');
2274
- else if (!ebanxCheckoutEnded(ctx))
2340
+ else if (!followUpCheckoutEnded(ctx))
2275
2341
  ctx.lifecycle.unsupported(EBANX_RESEND_REASON);
2276
2342
  await ctx.effects.abort();
2277
2343
  return { kind: 'abort' };
@@ -2286,7 +2352,7 @@ async function sendEbanxFollowUp(ctx, claim) {
2286
2352
  ctx.onEvent?.({ type: 'ebanx_follow_up_failed', detail: { ...detail, reason: 'handoff_failed', cardSent: true } });
2287
2353
  if (claim.kind === 'confirm')
2288
2354
  ebanxConfirmUnconfirmed(ctx, claim.authorizationId, 'ebanx_follow_up_handoff_failed');
2289
- else if (!ebanxCheckoutEnded(ctx))
2355
+ else if (!followUpCheckoutEnded(ctx))
2290
2356
  ctx.lifecycle.unsupported(EBANX_RESEND_REASON);
2291
2357
  await ctx.effects.abort();
2292
2358
  return { kind: 'abort' };
@@ -2294,6 +2360,95 @@ async function sendEbanxFollowUp(ctx, claim) {
2294
2360
  ctx.onEvent?.({ type: 'ebanx_follow_up_answered', detail: { ...detail, status: answer.status } });
2295
2361
  return { kind: 'answer' };
2296
2362
  }
2363
+ // Payrexx Pay's card frame after its card request (payrexx.ts, payment-core payrexx.js). When Payrexx answers the card
2364
+ // request by starting 3-D Secure, the frame posts the card again to its own URL for the authentication after the ACS
2365
+ // method and the post-authentication after the bank's challenge. On a page this SDK is attached to that card is the
2366
+ // agent's placeholder, and the frame's URL is the card request's, so this gate judges each such post before the
2367
+ // card-request arbiter would pause it as a new card request:
2368
+ // - one the approved card request on this attachment covers (PayrexxFollowUps.claim) goes to the cardholder's device
2369
+ // under that approval (payrexxFollowUp below), and the frame receives Payrexx's answer to the real card;
2370
+ // - any other aborts as an unsupported checkout, reason `unsupported_payrexx_card_resend`, with no claim, create or
2371
+ // prompt, so Payrexx never receives the placeholder as a card, and the attachment holds. A checkout whose card
2372
+ // request was already approved keeps that approval's state, and its sends stop (PayrexxFollowUps.stop), as
2373
+ // EBANX's do. A send goes on only while the checkout itself names the remembered approval (followUpMaySend).
2374
+ // The card request itself, a wallet's body with no card value, a body the adapter could not read and every other
2375
+ // request defer: the arbiter pauses the card request for its recognizer and judges the rest (card-fields.js).
2376
+ // Synchronous until it must abort or send, like every gate. Exported for the gate registry's tests.
2377
+ export const payrexxPreClaim = (ctx) => {
2378
+ const { url, method } = ctx.request;
2379
+ if (!isPayrexxResend(url, method, () => ctx.request.body))
2380
+ return undefined;
2381
+ let body;
2382
+ try {
2383
+ body = ctx.request.body;
2384
+ }
2385
+ catch {
2386
+ body = null;
2387
+ }
2388
+ const claim = ctx.payrexx && typeof ctx.vault.sendPayrexxFollowUp === 'function' && followUpMaySend(ctx, ctx.payrexx)
2389
+ ? ctx.payrexx.claim({ url, method: 'POST', headers: ctx.request.headers ?? {}, body }) : null;
2390
+ return claim ? payrexxFollowUp(ctx, claim) : payrexxResendRefused(ctx);
2391
+ };
2392
+ async function payrexxResendRefused(ctx) {
2393
+ const { url, method } = ctx.request;
2394
+ ctx.preparationGate.invalidate('unsupported_checkout');
2395
+ ctx.payrexx?.stop();
2396
+ ctx.lifecycle.unsupported(PAYREXX_RESEND_REASON);
2397
+ ctx.onEvent?.({ type: 'unsupported_checkout', detail: { url: eventUrl(ctx.vault, url), method, reason: PAYREXX_RESEND_REASON, step: 'three_d_secure' } });
2398
+ await ctx.effects.abort();
2399
+ return { kind: 'abort' };
2400
+ }
2401
+ /**
2402
+ * A 3-D Secure send the approved card request covers: the cardholder's device sends it with the real card
2403
+ * (VaultClient.sendPayrexxFollowUp), and the frame receives Payrexx's answer, with no second prompt. The events name the
2404
+ * approval and the step, never the request, the card or Payrexx's answer. A send charges nothing: the merchant's page
2405
+ * charges only the token a later answer names, at its own validateForm. So a send that gets no answer, or whose answer
2406
+ * the frame never receives, leaves no payment behind it: the frame's request fails, the attachment holds as the
2407
+ * refusal above does (a final outcome keeps its state and reason), and nothing more is sent. While a send is out it
2408
+ * counts as work in flight (CheckoutLifecycle.followUpStarted), so the application starts no other attempt over it.
2409
+ */
2410
+ async function payrexxFollowUp(ctx, claim) {
2411
+ const settle = ctx.lifecycle.followUpStarted();
2412
+ try {
2413
+ return await sendPayrexxFollowUp(ctx, claim);
2414
+ }
2415
+ finally {
2416
+ settle();
2417
+ }
2418
+ }
2419
+ async function sendPayrexxFollowUp(ctx, claim) {
2420
+ const detail = { authorizationId: claim.authorizationId, step: claim.kind };
2421
+ ctx.onEvent?.({ type: 'payrexx_follow_up_requested', detail });
2422
+ let answer;
2423
+ try {
2424
+ answer = await ctx.vault.sendPayrexxFollowUp(claim.authorizationId, claim.request, { signal: ctx.lifecycle.abort.signal, until: claim.until });
2425
+ }
2426
+ catch (error) {
2427
+ claim.settle(null);
2428
+ ctx.payrexx?.stop();
2429
+ const reason = error instanceof PayrexxFollowUpError ? error.reason : 'follow_up_unavailable';
2430
+ const cardSent = error instanceof PayrexxFollowUpError ? error.cardSent : true;
2431
+ ctx.onEvent?.({ type: 'payrexx_follow_up_failed', detail: { ...detail, reason, cardSent } });
2432
+ if (!followUpCheckoutEnded(ctx))
2433
+ ctx.lifecycle.unsupported(PAYREXX_RESEND_REASON);
2434
+ await ctx.effects.abort();
2435
+ return { kind: 'abort' };
2436
+ }
2437
+ claim.settle({ status: answer.status, text: answer.body });
2438
+ try {
2439
+ await ctx.effects.answer({ status: answer.status, headers: answer.headers, body: answer.body });
2440
+ }
2441
+ catch {
2442
+ ctx.payrexx?.stop();
2443
+ ctx.onEvent?.({ type: 'payrexx_follow_up_failed', detail: { ...detail, reason: 'handoff_failed', cardSent: true } });
2444
+ if (!followUpCheckoutEnded(ctx))
2445
+ ctx.lifecycle.unsupported(PAYREXX_RESEND_REASON);
2446
+ await ctx.effects.abort();
2447
+ return { kind: 'abort' };
2448
+ }
2449
+ ctx.onEvent?.({ type: 'payrexx_follow_up_answered', detail: { ...detail, status: answer.status } });
2450
+ return { kind: 'answer' };
2451
+ }
2297
2452
  // The terminal arbiter, always last. A request that no gate claimed and that is
2298
2453
  // neither a native Stripe step nor a recognized card request continues, unless
2299
2454
  // it matches a declared payment endpoint we do not support (then it aborts as an
@@ -2327,8 +2482,8 @@ async function unsupportedContinue(ctx) {
2327
2482
  * arbiter runs after all of them and is not part of this list. A gate appended
2328
2483
  * after Stripe is never offered a step Stripe claimed: Stripe answers, aborts or
2329
2484
  * pauses each one itself. */
2330
- export const PSP_PRE_CLAIM_GATES = [cardEndpointResendPreClaim, cardEndpointPreClaim, mercadoPreClaim, juspayPreClaim, braintreePreClaim, stripePreClaim, merchantHostedPreClaim, verifonePreClaim, fiservPreClaim, gmoPreClaim, cybersourceFlexPreClaim, datatransPreClaim, tokenexIframePreClaim, pelecardPreClaim, aciPreClaim, creditguardPreClaim, primerPreClaim, payrailsPreClaim, convergePreClaim, eprotectPreClaim, wspayPreClaim, shijiStsPreClaim, ekashuPreClaim, redsysPreClaim, quickpayPreClaim, comgatePreClaim, przelewy24PreClaim, transbankPreClaim, paypalHostedFieldsPreClaim,
2331
- paypalCardFormsPreClaim, cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim, ebanxPreClaim, hipayPreClaim];
2485
+ export const PSP_PRE_CLAIM_GATES = [cardEndpointResendPreClaim, cardEndpointPreClaim, mercadoPreClaim, juspayPreClaim, braintreePreClaim, stripePreClaim, merchantHostedPreClaim, verifonePreClaim, fiservPreClaim, gmoPreClaim, cybersourceFlexPreClaim, datatransPreClaim, tokenexIframePreClaim, pelecardPreClaim, aciPreClaim, creditguardPreClaim, primerPreClaim, payrailsPreClaim, convergePreClaim, eprotectPreClaim, sbpsPreClaim, wspayPreClaim, shijiStsPreClaim, ekashuPreClaim, redsysPreClaim, quickpayPreClaim, comgatePreClaim, przelewy24PreClaim, transbankPreClaim, eximbayPreClaim, paypalHostedFieldsPreClaim,
2486
+ paypalCardFormsPreClaim, cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim, ebanxPreClaim, payrexxPreClaim, hipayPreClaim, paytrailPreClaim];
2332
2487
  /** Run each gate in order; the first to return a decision wins. If none does,
2333
2488
  * the terminal arbiter decides between continue, abort (unsupported) and pause.
2334
2489
  * Returns synchronously while every gate defers synchronously (an ordinary card
@@ -25,11 +25,15 @@
25
25
  * Cashier's card frame for a token, too soon for an approval after Pay. Its one environment is
26
26
  * production: Wix's tokenizer has no test host.
27
27
  *
28
+ * paygent: prepared only. Paygent's PaygentToken.js abandons its token request 35 seconds after the
29
+ * merchant's press sends it, too soon for an approval after the press. Its environments are its two token
30
+ * hosts: token.paygent.co.jp (production) and sandbox.paygent.co.jp (sandbox).
31
+ *
28
32
  * hipay: prepared only. The merchant's page gives HiPay's hosted fields 20 seconds after Pay, too soon for an
29
33
  * approval after Pay. Its environments are its two vault hosts: secure2-vault (production) and
30
34
  * stage-secure2-vault (sandbox).
31
35
  */
32
- export type PreparationProcessor = 'square' | 'braintree' | 'worldpay' | 'bambora' | 'mercado_pago' | 'recurly' | 'spreedly' | 'adyen' | 'checkout_com' | 'paysafe' | 'fiserv' | 'cybersource_flex' | 'aci' | 'creditguard' | 'worldpay_eprotect' | 'amadeus_checkout' | 'verifone' | 'cybersource_secure_acceptance' | 'paddle_vgs' | 'wix_payments' | 'hipay';
36
+ export type PreparationProcessor = 'square' | 'braintree' | 'worldpay' | 'bambora' | 'mercado_pago' | 'recurly' | 'spreedly' | 'adyen' | 'checkout_com' | 'paysafe' | 'fiserv' | 'cybersource_flex' | 'aci' | 'creditguard' | 'worldpay_eprotect' | 'amadeus_checkout' | 'verifone' | 'cybersource_secure_acceptance' | 'paddle_vgs' | 'wix_payments' | 'paygent' | 'hipay';
33
37
  export type PreparationEnvironment = 'production' | 'sandbox' | 'shared';
34
38
  /**
35
39
  * How the approved card reaches the processor: the device's own request (token), or
@@ -66,7 +70,8 @@ export declare function preparedApprovalAnswersRetry(psp: string): boolean;
66
70
  * its own signing keys. A Verifone preparation pays in the environment of the key its reviewed
67
71
  * profile pins. CyberSource Secure Acceptance's are separate hosts too: secureacceptance is
68
72
  * live, testsecureacceptance is test. So are Paddle VGS's two card URLs: vault is live,
69
- * sandbox-vault is test. So are HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test.
73
+ * sandbox-vault is test. So are Paygent's two token hosts: token is live, sandbox is test. So are
74
+ * HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test.
70
75
  */
71
76
  export declare function validPreparationEnvironment(psp: string, environment: string): boolean;
72
77
  /**
@@ -15,6 +15,7 @@ import { isPreparedVerifoneRequest } from './verifone.js';
15
15
  import { isPreparedSecureAcceptanceRequest, secureAcceptanceEnvironment, secureAcceptancePreparationUrl, secureAcceptanceRequestRefusal, } from './cybersource-secure-acceptance.generated.js';
16
16
  import { PADDLE_VGS_CARDS_URLS, isPreparedPaddleVgsRequest } from './paddle-vgs.generated.js';
17
17
  import { WIX_PAYMENTS_TOKENIZE_URL, isPreparedWixPaymentsRequest } from './wix-payments.generated.js';
18
+ import { paygentEnvironment, paygentPreparationUrl, paygentRequestRefusal } from './paygent.generated.js';
18
19
  import { HIPAY_TOKEN_URLS, hipayRequestRefusal, hipayTokenEnvironment, isPreparedHipayRequest } from './hipay.generated.js';
19
20
  export function preparationMode(psp) {
20
21
  return psp === 'adyen' || psp === 'fiserv' || psp === 'verifone' ? 'cse' : 'token';
@@ -50,7 +51,8 @@ export function preparedApprovalAnswersRetry(psp) {
50
51
  * its own signing keys. A Verifone preparation pays in the environment of the key its reviewed
51
52
  * profile pins. CyberSource Secure Acceptance's are separate hosts too: secureacceptance is
52
53
  * live, testsecureacceptance is test. So are Paddle VGS's two card URLs: vault is live,
53
- * sandbox-vault is test. So are HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test.
54
+ * sandbox-vault is test. So are Paygent's two token hosts: token is live, sandbox is test. So are
55
+ * HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test.
54
56
  */
55
57
  export function validPreparationEnvironment(psp, environment) {
56
58
  if (psp === 'bambora' || psp === 'mercado_pago' || psp === 'recurly' || psp === 'spreedly')
@@ -59,7 +61,7 @@ export function validPreparationEnvironment(psp, environment) {
59
61
  if (psp === 'wix_payments')
60
62
  return environment === 'production';
61
63
  return ['square', 'braintree', 'worldpay', 'adyen', 'checkout_com', 'paysafe', 'fiserv', 'cybersource_flex', 'aci', 'creditguard', 'worldpay_eprotect', 'amadeus_checkout', 'verifone',
62
- 'cybersource_secure_acceptance', 'paddle_vgs', 'hipay'].includes(psp) && ['production', 'sandbox'].includes(environment);
64
+ 'cybersource_secure_acceptance', 'paddle_vgs', 'paygent', 'hipay'].includes(psp) && ['production', 'sandbox'].includes(environment);
63
65
  }
64
66
  /**
65
67
  * ACI's prepared endpoint, the literal the API names (backend checkout-prepared-processor.ts): its
@@ -107,6 +109,9 @@ export function preparationEndpoint(psp, environment) {
107
109
  // Wix Payments: the tokenize URL, the only URL the claim takes for it.
108
110
  if (psp === 'wix_payments')
109
111
  return WIX_PAYMENTS_TOKENIZE_URL;
112
+ // Paygent: the token URL on the environment's host, the only URL the claim takes for it.
113
+ if (psp === 'paygent')
114
+ return paygentPreparationUrl(environment);
110
115
  // HiPay: the token create on the environment's vault, the only URL the claim takes for it.
111
116
  if (psp === 'hipay')
112
117
  return HIPAY_TOKEN_URLS[environment];
@@ -267,6 +272,15 @@ export function matchesPreparedRequest(psp, environment, requestUrl, method, bod
267
272
  // site's app instance and the card frame's body), the rule the API and the Vault bind with too.
268
273
  if (psp === 'wix_payments')
269
274
  return isPreparedWixPaymentsRequest(requestUrl, method.toUpperCase(), body ?? null, environment, headers ?? {});
275
+ // Paygent: the environment's own token URL and payment-core's whole request rule (the script's text/plain
276
+ // and createToken's body byte for byte), the rule the API and the Vault bind with too. The method as the page
277
+ // sent it: the device sends only an uppercase POST. Which merchant_id and token key a live request may name
278
+ // is the API's to judge at the bind and the Vault's before it writes the card, against the reviewed pins
279
+ // each of them holds, so a merchant a later release reviews needs no new build of this library.
280
+ if (psp === 'paygent') {
281
+ return paygentEnvironment(requestUrl) === environment
282
+ && paygentRequestRefusal({ url: requestUrl, method, headers: headers ?? {}, body: body ?? null }) === null;
283
+ }
270
284
  // HiPay: the environment's own vault and payment-core's whole request rule (a JSON content type, a public username of
271
285
  // that environment and a complete create, never the hosted fields' number-only post), the rule the API and the Vault
272
286
  // bind with too.