@thavguard/arc-pay 0.1.11 → 0.1.12

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/README.md CHANGED
@@ -63,7 +63,7 @@ creation, execution, capture, void, refund, saved-card charges, payment links,
63
63
  and checkout sessions.
64
64
 
65
65
  Mutating server-client methods require an explicit `{ idempotencyKey }`:
66
- `createPayment`, `executePayment`, `capturePayment`, `voidPayment`,
66
+ `createPayment`, `createCardSetup`, `executePayment`, `capturePayment`, `voidPayment`,
67
67
  `createRefund`, `chargeSavedCard`, `createLink`, and
68
68
  `createCheckoutSession`. Missing idempotency raises `ArcPayError` with
69
69
  `code="missing_idempotency_key"` before any HTTP request is sent.
@@ -79,22 +79,40 @@ something in the browser. The SDK helper turns that action into the POST form
79
79
  descriptor you render in a hidden iframe or visible browser page:
80
80
 
81
81
  ```ts
82
- import { buildThreeDSBrowserForm, getThreeDSAction } from "@thavguard/arc-pay/server";
82
+ import {
83
+ buildThreeDSBrowserStep,
84
+ buildThreeDSMethodCompletion,
85
+ getThreeDSAction,
86
+ } from "@thavguard/arc-pay/server";
83
87
 
84
88
  const result = await client.executePayment(paymentId, body, { idempotencyKey });
85
89
  const action = getThreeDSAction(result.next_action);
86
90
 
87
91
  if (action) {
88
- const form = buildThreeDSBrowserForm(action);
89
- // Render POST form using form.action, form.method, form.target, form.fields.
90
- // For action.type === "three_ds_method", call completeThreeDSMethod from your
91
- // backend after the hidden iframe finishes or times out.
92
+ const step = buildThreeDSBrowserStep(action);
93
+ // Render step.form using form.action, form.method, form.target, form.fields.
94
+ // For step.kind === "method", call completeThreeDSMethod from your backend
95
+ // after the hidden iframe finishes or times out.
96
+ const completeBody = buildThreeDSMethodCompletion(action, "Y");
97
+ const afterMethod = await client.completeThreeDSMethod(paymentId, completeBody);
98
+ // If afterMethod.next_action is a challenge, render the returned browser step.
92
99
  }
93
100
  ```
94
101
 
95
102
  Do not branch on bank-specific 3DS fields. Arc Pay normalizes 3DS 1.x and 2.x
96
103
  into `next_action.three_ds.submit`.
97
104
 
105
+ After the browser step redirects or the customer returns to your order page,
106
+ use `waitForPaymentTerminal(paymentId)` or your own webhook/status loop. The
107
+ helper polls `GET /payments/{id}` and stops at terminal Arc Pay statuses; it
108
+ does not attempt to automate issuer ACS challenge pages.
109
+
110
+ For saved cards and subscriptions, create a setup intent with
111
+ `createCardSetup()`, tokenize through Hosted Fields, execute the setup payment,
112
+ complete any returned 3DS browser step, and wait for a terminal payment that
113
+ contains `card_token_id`. Later merchant-initiated charges use
114
+ `chargeSavedCard()`.
115
+
98
116
  The server client accepts an optional `apiBase` only for local or isolated test
99
117
  environments. Production integrations should use the default
100
118
  `https://api.arcpay.space/v1`; sandbox/live is selected by the key prefix.
@@ -4,6 +4,7 @@ type CaptureMode = "one_stage" | "two_stage";
4
4
  type PaymentFlowMode = "h2h" | "redirect";
5
5
  type Locale = "ru" | "en";
6
6
  type PaymentStatus = "created" | "pending" | "pending_3ds" | "authorized" | "captured" | "settled" | "voided" | "expired" | "refunded" | "chargeback" | "declined" | "failed" | "timeout";
7
+ type TerminalPaymentStatus = "authorized" | "captured" | "settled" | "voided" | "expired" | "refunded" | "chargeback" | "declined" | "failed";
7
8
  interface Payment {
8
9
  id: string;
9
10
  amount: number;
@@ -159,6 +160,12 @@ interface CompleteThreeDSMethodRequest {
159
160
  completion_indicator: "Y" | "N" | "U";
160
161
  three_ds_server_trans_id: string;
161
162
  }
163
+ interface WaitForPaymentOptions {
164
+ intervalMs?: number;
165
+ timeoutMs?: number;
166
+ terminalStatuses?: readonly TerminalPaymentStatus[];
167
+ signal?: AbortSignal;
168
+ }
162
169
  interface AvailablePaymentMethod {
163
170
  method: PaymentMethod;
164
171
  payment_mode: PaymentFlowMode;
@@ -305,11 +312,23 @@ interface BrowserPostForm {
305
312
  target: "hidden_iframe" | "browser";
306
313
  fields: BrowserFormField[];
307
314
  }
315
+ interface ThreeDSBrowserStep {
316
+ kind: "method" | "challenge";
317
+ protocolVersion: "1" | "2";
318
+ form: BrowserPostForm;
319
+ completionEndpoint?: string;
320
+ threeDSServerTransId?: string;
321
+ }
308
322
  declare const collectBrowserInfo: (acceptHeader?: string) => BrowserInfo;
309
323
  declare const getThreeDSAction: (nextAction?: PaymentNextAction) => PaymentNextAction | null;
310
324
  declare const isThreeDSMethodAction: (nextAction?: PaymentNextAction) => boolean;
311
325
  declare const isThreeDSChallengeAction: (nextAction?: PaymentNextAction) => boolean;
312
326
  declare const buildThreeDSBrowserForm: (nextAction: PaymentNextAction) => BrowserPostForm;
327
+ declare const buildThreeDSBrowserStep: (nextAction?: PaymentNextAction) => ThreeDSBrowserStep | null;
328
+ declare const buildThreeDSMethodCompletion: (nextAction: PaymentNextAction, completionIndicator?: "Y" | "N" | "U") => {
329
+ completion_indicator: "Y" | "N" | "U";
330
+ three_ds_server_trans_id: string;
331
+ };
313
332
  declare const buildThreeDSAutoSubmitHtml: (nextAction: PaymentNextAction) => string;
314
333
 
315
- export { type AvailablePaymentMethod as A, type BrowserFormField as B, type CaptureRequest as C, type ExecutePaymentRequest as E, type Link as L, type Payment as P, type Refund as R, type ThreeDSAction as T, type VoidRequest as V, type BrowserInfo as a, type BrowserPostForm as b, type ChargeSavedCardRequest as c, type CheckoutSession as d, type CompleteThreeDSMethodRequest as e, type CreateCardSetupRequest as f, type CreateCheckoutSessionRequest as g, type CreateLinkRequest as h, type CreatePaymentRequest as i, type CreateRefundRequest as j, type ExecutePaymentResponse as k, type ListAvailablePaymentMethodsQuery as l, type ListPaymentsQuery as m, type PaymentFlowMode as n, type PaymentList as o, type PaymentMethod as p, type PaymentNextAction as q, buildThreeDSAutoSubmitHtml as r, buildThreeDSBrowserForm as s, collectBrowserInfo as t, getThreeDSAction as u, isThreeDSChallengeAction as v, isThreeDSMethodAction as w };
334
+ export { type AvailablePaymentMethod as A, type BrowserFormField as B, type CaptureRequest as C, type ExecutePaymentRequest as E, type Link as L, type Payment as P, type Refund as R, type ThreeDSAction as T, type VoidRequest as V, type WaitForPaymentOptions as W, type BrowserInfo as a, type BrowserPostForm as b, type ChargeSavedCardRequest as c, type CheckoutSession as d, type CompleteThreeDSMethodRequest as e, type CreateCardSetupRequest as f, type CreateCheckoutSessionRequest as g, type CreateLinkRequest as h, type CreatePaymentRequest as i, type CreateRefundRequest as j, type ExecutePaymentResponse as k, type ListAvailablePaymentMethodsQuery as l, type ListPaymentsQuery as m, type PaymentFlowMode as n, type PaymentList as o, type PaymentMethod as p, type PaymentNextAction as q, type ThreeDSBrowserStep as r, buildThreeDSAutoSubmitHtml as s, buildThreeDSBrowserForm as t, buildThreeDSBrowserStep as u, buildThreeDSMethodCompletion as v, collectBrowserInfo as w, getThreeDSAction as x, isThreeDSChallengeAction as y, isThreeDSMethodAction as z };
@@ -4,6 +4,7 @@ type CaptureMode = "one_stage" | "two_stage";
4
4
  type PaymentFlowMode = "h2h" | "redirect";
5
5
  type Locale = "ru" | "en";
6
6
  type PaymentStatus = "created" | "pending" | "pending_3ds" | "authorized" | "captured" | "settled" | "voided" | "expired" | "refunded" | "chargeback" | "declined" | "failed" | "timeout";
7
+ type TerminalPaymentStatus = "authorized" | "captured" | "settled" | "voided" | "expired" | "refunded" | "chargeback" | "declined" | "failed";
7
8
  interface Payment {
8
9
  id: string;
9
10
  amount: number;
@@ -159,6 +160,12 @@ interface CompleteThreeDSMethodRequest {
159
160
  completion_indicator: "Y" | "N" | "U";
160
161
  three_ds_server_trans_id: string;
161
162
  }
163
+ interface WaitForPaymentOptions {
164
+ intervalMs?: number;
165
+ timeoutMs?: number;
166
+ terminalStatuses?: readonly TerminalPaymentStatus[];
167
+ signal?: AbortSignal;
168
+ }
162
169
  interface AvailablePaymentMethod {
163
170
  method: PaymentMethod;
164
171
  payment_mode: PaymentFlowMode;
@@ -305,11 +312,23 @@ interface BrowserPostForm {
305
312
  target: "hidden_iframe" | "browser";
306
313
  fields: BrowserFormField[];
307
314
  }
315
+ interface ThreeDSBrowserStep {
316
+ kind: "method" | "challenge";
317
+ protocolVersion: "1" | "2";
318
+ form: BrowserPostForm;
319
+ completionEndpoint?: string;
320
+ threeDSServerTransId?: string;
321
+ }
308
322
  declare const collectBrowserInfo: (acceptHeader?: string) => BrowserInfo;
309
323
  declare const getThreeDSAction: (nextAction?: PaymentNextAction) => PaymentNextAction | null;
310
324
  declare const isThreeDSMethodAction: (nextAction?: PaymentNextAction) => boolean;
311
325
  declare const isThreeDSChallengeAction: (nextAction?: PaymentNextAction) => boolean;
312
326
  declare const buildThreeDSBrowserForm: (nextAction: PaymentNextAction) => BrowserPostForm;
327
+ declare const buildThreeDSBrowserStep: (nextAction?: PaymentNextAction) => ThreeDSBrowserStep | null;
328
+ declare const buildThreeDSMethodCompletion: (nextAction: PaymentNextAction, completionIndicator?: "Y" | "N" | "U") => {
329
+ completion_indicator: "Y" | "N" | "U";
330
+ three_ds_server_trans_id: string;
331
+ };
313
332
  declare const buildThreeDSAutoSubmitHtml: (nextAction: PaymentNextAction) => string;
314
333
 
315
- export { type AvailablePaymentMethod as A, type BrowserFormField as B, type CaptureRequest as C, type ExecutePaymentRequest as E, type Link as L, type Payment as P, type Refund as R, type ThreeDSAction as T, type VoidRequest as V, type BrowserInfo as a, type BrowserPostForm as b, type ChargeSavedCardRequest as c, type CheckoutSession as d, type CompleteThreeDSMethodRequest as e, type CreateCardSetupRequest as f, type CreateCheckoutSessionRequest as g, type CreateLinkRequest as h, type CreatePaymentRequest as i, type CreateRefundRequest as j, type ExecutePaymentResponse as k, type ListAvailablePaymentMethodsQuery as l, type ListPaymentsQuery as m, type PaymentFlowMode as n, type PaymentList as o, type PaymentMethod as p, type PaymentNextAction as q, buildThreeDSAutoSubmitHtml as r, buildThreeDSBrowserForm as s, collectBrowserInfo as t, getThreeDSAction as u, isThreeDSChallengeAction as v, isThreeDSMethodAction as w };
334
+ export { type AvailablePaymentMethod as A, type BrowserFormField as B, type CaptureRequest as C, type ExecutePaymentRequest as E, type Link as L, type Payment as P, type Refund as R, type ThreeDSAction as T, type VoidRequest as V, type WaitForPaymentOptions as W, type BrowserInfo as a, type BrowserPostForm as b, type ChargeSavedCardRequest as c, type CheckoutSession as d, type CompleteThreeDSMethodRequest as e, type CreateCardSetupRequest as f, type CreateCheckoutSessionRequest as g, type CreateLinkRequest as h, type CreatePaymentRequest as i, type CreateRefundRequest as j, type ExecutePaymentResponse as k, type ListAvailablePaymentMethodsQuery as l, type ListPaymentsQuery as m, type PaymentFlowMode as n, type PaymentList as o, type PaymentMethod as p, type PaymentNextAction as q, type ThreeDSBrowserStep as r, buildThreeDSAutoSubmitHtml as s, buildThreeDSBrowserForm as t, buildThreeDSBrowserStep as u, buildThreeDSMethodCompletion as v, collectBrowserInfo as w, getThreeDSAction as x, isThreeDSChallengeAction as y, isThreeDSMethodAction as z };
@@ -1,3 +1,3 @@
1
- var ArcPay=(function(exports){'use strict';var n=class extends Error{constructor(t){super(t.message),this.name="ArcPayError",this.type=t.type,this.code=t.code,this.param=t.param,this.paymentId=t.paymentId,this.declineCode=t.declineCode,this.retryable=t.retryable,this.requestId=t.requestId;}},F=e=>e instanceof n&&e.type==="validation_error",R=e=>e instanceof n&&e.type==="authentication_error",C=e=>e instanceof n&&e.type==="authorization_error",D=e=>e instanceof n&&e.type==="state_error",M=e=>e instanceof n&&e.type==="rate_limit_error",L=e=>e instanceof n&&e.type==="api_error",O=e=>e instanceof n&&e.type==="network_error",N=e=>e instanceof n&&e.type==="challenge_aborted";var f=e=>e.startsWith("pk_test_")?"sandbox":"live",x=e=>{if(typeof e!="string"||e.length===0)throw new n({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must be a non-empty string",retryable:false});if(!e.startsWith("pk_test_")&&!e.startsWith("pk_live_"))throw new n({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.",retryable:false})};var T="data-arcpay-sandbox-banner",I=()=>{if(typeof document=="undefined"||document.querySelector(`[${T}]`))return;let e=document.createElement("div");e.setAttribute(T,""),e.style.cssText="position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);";let t=document.createElement("span");t.textContent="ARC PAY TEST MODE \u2014 payments are simulated",e.appendChild(t);let r=document.createElement("button");r.type="button",r.setAttribute("data-arcpay-banner-dismiss",""),r.textContent="\xD7",r.setAttribute("aria-label","Dismiss test mode banner"),r.style.cssText="margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;",r.addEventListener("click",()=>e.remove()),e.appendChild(r),document.body.appendChild(e);};var W="arcpay:",H=e=>typeof e=="object"&&e!==null&&"type"in e&&typeof e.type=="string"&&e.type.startsWith(W),h=(e,t,r)=>{if(r==="*")throw new n({type:"validation_error",code:"wildcard_origin_forbidden",message:"postToIframe: targetOrigin cannot be '*'",retryable:false});if(!e.contentWindow)throw new n({type:"validation_error",code:"iframe_not_loaded",message:"postToIframe: iframe.contentWindow is null (iframe not mounted)",retryable:false});e.contentWindow.postMessage(t,r);};var m=(e,t)=>e.origin!==t||!H(e.data)?null:e.data;var K=new Set(["position","transform","pointer-events","z-index","top","left","right","bottom","inset"]),u=e=>{let t={};for(let[r,o]of Object.entries(e)){let s=r.toLowerCase();K.has(s)||(t[r]=o);}return t},g=e=>{let t={base:u(e.base)};return e.invalid!==void 0&&(t.invalid=u(e.invalid)),e.focus!==void 0&&(t.focus=u(e.focus)),t};var y=class{constructor(t,r,o){this.field=t;this.options=r;this.context=o;this.iframe=null;this.listeners=new Set;this.status="pending";this.messageHandler=null;}mount(t){if(this.iframe)throw new n({type:"validation_error",code:"already_mounted",message:`Element ${this.field} is already mounted`,retryable:false});let r=typeof t=="string"?document.querySelector(t):t;if(!(r instanceof HTMLElement))throw new n({type:"validation_error",code:"mount_target_not_found",message:`mount target not found: ${String(t)}`,retryable:false});let o=document.createElement("iframe");o.src=`${this.context.iframeBase}/iframe/${this.field}`,o.style.cssText="border:0;width:100%;height:100%;display:block;",o.setAttribute("allow","payment"),o.setAttribute("data-arcpay-element",this.field),r.appendChild(o),this.iframe=o;let s=new URL(this.context.iframeBase).origin;this.messageHandler=a=>{var l;if(a.source!==((l=this.iframe)==null?void 0:l.contentWindow))return;let p=m(a,s);p&&this.handleMessage(p);},window.addEventListener("message",this.messageHandler),o.addEventListener("load",()=>{if(!this.iframe)return;let a={type:"arcpay:hello",origin:window.location.origin,publishableKey:this.context.publishableKey,channelId:this.context.channelId};h(this.iframe,a,s);},{once:true});}handleMessage(t){t.type==="arcpay:ready"?(this.status="ready",this.options.style&&this.send({type:"arcpay:style",payload:g(this.options.style)}),this.emit({type:"ready"})):t.type==="arcpay:rejected"?(this.status="error",this.emit({type:"error",reason:t.reason})):t.type==="arcpay:change"&&t.field===this.field&&this.emit({type:"change",isValid:t.isValid,brand:t.brand,lastFour:t.lastFour});}update(t){t.style&&this.send({type:"arcpay:style",payload:g(t.style)});}destroy(){this.iframe&&(this.iframe.remove(),this.iframe=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.listeners.clear(),this.status="pending";}on(t,r){return this.listeners.add(r),()=>this.listeners.delete(r)}focus(){this.send({type:"arcpay:focus"});}clear(){this.send({type:"arcpay:clear"});}isReady(){return this.status==="ready"}getIframeContentWindow(){var t,r;return (r=(t=this.iframe)==null?void 0:t.contentWindow)!=null?r:null}send(t){if(!this.iframe)throw new n({type:"validation_error",code:"not_mounted",message:`Element ${this.field} is not mounted`,retryable:false});h(this.iframe,t,new URL(this.context.iframeBase).origin);}emit(t){for(let r of this.listeners)r(t);}};var $="https://sdk.arcpay.space",q=()=>{var e;if(!((e=globalThis.crypto)!=null&&e.randomUUID))throw new n({type:"validation_error",code:"crypto_unavailable",message:"crypto.randomUUID is required for Hosted Fields",retryable:false});return globalThis.crypto.randomUUID()},d=class{constructor(t){this.elementMap=new Map;this.tokenizeInFlight=false;var r;this.publishableKey=t.publishableKey,this.iframeBase=(r=t.iframeBase)!=null?r:$,this.channelId=q();}create(t,r={}){if(this.elementMap.has(t))throw new n({type:"validation_error",code:"duplicate_element",message:`Element for ${t} already created`,retryable:false});let o={iframeBase:this.iframeBase,publishableKey:this.publishableKey,channelId:this.channelId},s=new y(t,r,o);return this.elementMap.set(t,s),s}async tokenize(t,r){if(this.tokenizeInFlight)throw new n({type:"validation_error",code:"tokenize_in_progress",message:"A tokenize() call is already in progress for this Elements instance",retryable:false});let o=this.elementMap.get("cardNumber"),s=this.elementMap.get("cardExpiry"),a=this.elementMap.get("cardCvv");if(!o||!s||!a)throw new n({type:"validation_error",code:"incomplete_elements",message:"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()",retryable:false});if(!o.isReady()||!s.isReady()||!a.isReady())throw new n({type:"validation_error",code:"elements_not_ready",message:"Wait for all elements to fire 'ready' event before tokenize()",retryable:false});this.tokenizeInFlight=true;try{return await this.doTokenize(o,t,r)}finally{this.tokenizeInFlight=false;}}doTokenize(t,r,o){let s=new URL(this.iframeBase).origin,a=t.getIframeContentWindow();return new Promise((p,l)=>{let E=window.setTimeout(()=>{window.removeEventListener("message",c),l(new n({type:"network_error",code:"tokenize_timeout",message:"tokenize() timed out after 30 seconds",retryable:true,paymentId:r}));},3e4),c=_=>{if(a!==null&&_.source!==a)return;let i=m(_,s);if(i){if(i.type==="arcpay:tokenize-result")clearTimeout(E),window.removeEventListener("message",c),p({cardTokenId:i.cardTokenId,cardMask:i.cardMask,cardScheme:i.cardScheme,cardBin:i.cardBin,expiresIn:i.expiresIn,expiresAt:i.expiresAt});else if(i.type==="arcpay:tokenize-error"){clearTimeout(E),window.removeEventListener("message",c);let B=i.errorType==="validation_error"||i.errorType==="api_error"?i.errorType:"api_error";l(new n({type:B,code:i.code,message:i.message,retryable:false,paymentId:r}));}}};window.addEventListener("message",c),t.send({type:"arcpay:tokenize",paymentId:r,idempotencyKey:o});})}destroy(){for(let t of this.elementMap.values())t.destroy();this.elementMap.clear();}};var U=x,b=new Map,j=e=>(f(e)==="sandbox"&&I(),{publishableKey:e,environment:f(e),elements:()=>new d({publishableKey:e})});function V(e){try{U(e);}catch(s){return Promise.reject(s)}let t=e,r=b.get(t);if(r)return r;let o=Promise.resolve(j(e));return b.set(t,o),o}var Y=()=>{b.clear();},X={load:V,__resetForTests:Y};var G=[1,4,8,15,16,24,32,48],J=e=>G.includes(e)?e:24,Q=e=>e>=1e3?"05":e>=600?"04":e>=500?"03":e>=390?"02":"01",P=(e="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")=>{if(typeof window=="undefined"||typeof navigator=="undefined"||typeof screen=="undefined")throw new Error("collectBrowserInfo must be called in a browser environment");return {accept_header:e,language:navigator.language||"en",screen_width:screen.width,screen_height:screen.height,color_depth:J(screen.colorDepth),timezone_offset_minutes:new Date().getTimezoneOffset(),java_enabled:false,user_agent:navigator.userAgent,window_size:Q(window.innerWidth||screen.width)}},k=e=>e!=null?e:null,S=e=>(e==null?void 0:e.type)==="three_ds_method"&&e.three_ds.phase==="method",A=e=>(e==null?void 0:e.type)==="three_ds_challenge"&&e.three_ds.phase==="challenge",v=e=>({action:e.three_ds.submit.url,method:e.three_ds.submit.method,target:e.three_ds.submit.target,fields:e.three_ds.submit.fields}),w=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;"),z=e=>{let t=v(e),r=t.target==="hidden_iframe"?"arcpay-three-ds-method":"_self",o=t.fields.map(a=>`<input type="hidden" name="${w(a.name)}" value="${w(a.value)}">`).join("");return `<!doctype html><html><head><meta charset="utf-8"></head><body>${t.target==="hidden_iframe"?'<iframe name="arcpay-three-ds-method" title="3-D Secure method" hidden></iframe>':""}<form method="POST" action="${w(t.action)}" target="${r}">${o}</form><script>document.forms[0].submit();</script></body></html>`};var Ee="0.1.11";
2
- exports.ArcPay=X;exports.ArcPayError=n;exports.Elements=d;exports.SDK_VERSION=Ee;exports.buildThreeDSAutoSubmitHtml=z;exports.buildThreeDSBrowserForm=v;exports.collectBrowserInfo=P;exports.getThreeDSAction=k;exports.isApiError=L;exports.isAuthenticationError=R;exports.isAuthorizationError=C;exports.isChallengeAborted=N;exports.isNetworkError=O;exports.isRateLimitError=M;exports.isStateError=D;exports.isThreeDSChallengeAction=A;exports.isThreeDSMethodAction=S;exports.isValidationError=F;return exports;})({});//# sourceMappingURL=arcpay.global.js.map
1
+ var ArcPay=(function(exports){'use strict';var n=class extends Error{constructor(t){super(t.message),this.name="ArcPayError",this.type=t.type,this.code=t.code,this.param=t.param,this.paymentId=t.paymentId,this.declineCode=t.declineCode,this.retryable=t.retryable,this.requestId=t.requestId;}},C=e=>e instanceof n&&e.type==="validation_error",M=e=>e instanceof n&&e.type==="authentication_error",R=e=>e instanceof n&&e.type==="authorization_error",L=e=>e instanceof n&&e.type==="state_error",N=e=>e instanceof n&&e.type==="rate_limit_error",O=e=>e instanceof n&&e.type==="api_error",W=e=>e instanceof n&&e.type==="network_error",H=e=>e instanceof n&&e.type==="challenge_aborted";var f=e=>e.startsWith("pk_test_")?"sandbox":"live",S=e=>{if(typeof e!="string"||e.length===0)throw new n({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must be a non-empty string",retryable:false});if(!e.startsWith("pk_test_")&&!e.startsWith("pk_live_"))throw new n({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.",retryable:false})};var I="data-arcpay-sandbox-banner",P=()=>{if(typeof document=="undefined"||document.querySelector(`[${I}]`))return;let e=document.createElement("div");e.setAttribute(I,""),e.style.cssText="position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);";let t=document.createElement("span");t.textContent="ARC PAY TEST MODE \u2014 payments are simulated",e.appendChild(t);let r=document.createElement("button");r.type="button",r.setAttribute("data-arcpay-banner-dismiss",""),r.textContent="\xD7",r.setAttribute("aria-label","Dismiss test mode banner"),r.style.cssText="margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;",r.addEventListener("click",()=>e.remove()),e.appendChild(r),document.body.appendChild(e);};var K="arcpay:",$=e=>typeof e=="object"&&e!==null&&"type"in e&&typeof e.type=="string"&&e.type.startsWith(K),u=(e,t,r)=>{if(r==="*")throw new n({type:"validation_error",code:"wildcard_origin_forbidden",message:"postToIframe: targetOrigin cannot be '*'",retryable:false});if(!e.contentWindow)throw new n({type:"validation_error",code:"iframe_not_loaded",message:"postToIframe: iframe.contentWindow is null (iframe not mounted)",retryable:false});e.contentWindow.postMessage(t,r);};var m=(e,t)=>e.origin!==t||!$(e.data)?null:e.data;var q=new Set(["position","transform","pointer-events","z-index","top","left","right","bottom","inset"]),g=e=>{let t={};for(let[r,o]of Object.entries(e)){let s=r.toLowerCase();q.has(s)||(t[r]=o);}return t},b=e=>{let t={base:g(e.base)};return e.invalid!==void 0&&(t.invalid=g(e.invalid)),e.focus!==void 0&&(t.focus=g(e.focus)),t};var y=class{constructor(t,r,o){this.field=t;this.options=r;this.context=o;this.iframe=null;this.listeners=new Set;this.status="pending";this.messageHandler=null;}mount(t){if(this.iframe)throw new n({type:"validation_error",code:"already_mounted",message:`Element ${this.field} is already mounted`,retryable:false});let r=typeof t=="string"?document.querySelector(t):t;if(!(r instanceof HTMLElement))throw new n({type:"validation_error",code:"mount_target_not_found",message:`mount target not found: ${String(t)}`,retryable:false});let o=document.createElement("iframe");o.src=`${this.context.iframeBase}/iframe/${this.field}`,o.style.cssText="border:0;width:100%;height:100%;display:block;",o.setAttribute("allow","payment"),o.setAttribute("data-arcpay-element",this.field),r.appendChild(o),this.iframe=o;let s=new URL(this.context.iframeBase).origin;this.messageHandler=a=>{var l;if(a.source!==((l=this.iframe)==null?void 0:l.contentWindow))return;let p=m(a,s);p&&this.handleMessage(p);},window.addEventListener("message",this.messageHandler),o.addEventListener("load",()=>{if(!this.iframe)return;let a={type:"arcpay:hello",origin:window.location.origin,publishableKey:this.context.publishableKey,channelId:this.context.channelId};u(this.iframe,a,s);},{once:true});}handleMessage(t){t.type==="arcpay:ready"?(this.status="ready",this.options.style&&this.send({type:"arcpay:style",payload:b(this.options.style)}),this.emit({type:"ready"})):t.type==="arcpay:rejected"?(this.status="error",this.emit({type:"error",reason:t.reason})):t.type==="arcpay:change"&&t.field===this.field&&this.emit({type:"change",isValid:t.isValid,brand:t.brand,lastFour:t.lastFour});}update(t){t.style&&this.send({type:"arcpay:style",payload:b(t.style)});}destroy(){this.iframe&&(this.iframe.remove(),this.iframe=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.listeners.clear(),this.status="pending";}on(t,r){return this.listeners.add(r),()=>this.listeners.delete(r)}focus(){this.send({type:"arcpay:focus"});}clear(){this.send({type:"arcpay:clear"});}isReady(){return this.status==="ready"}getIframeContentWindow(){var t,r;return (r=(t=this.iframe)==null?void 0:t.contentWindow)!=null?r:null}send(t){if(!this.iframe)throw new n({type:"validation_error",code:"not_mounted",message:`Element ${this.field} is not mounted`,retryable:false});u(this.iframe,t,new URL(this.context.iframeBase).origin);}emit(t){for(let r of this.listeners)r(t);}};var U="https://sdk.arcpay.space",V=()=>{var e;if(!((e=globalThis.crypto)!=null&&e.randomUUID))throw new n({type:"validation_error",code:"crypto_unavailable",message:"crypto.randomUUID is required for Hosted Fields",retryable:false});return globalThis.crypto.randomUUID()},d=class{constructor(t){this.elementMap=new Map;this.tokenizeInFlight=false;var r;this.publishableKey=t.publishableKey,this.iframeBase=(r=t.iframeBase)!=null?r:U,this.channelId=V();}create(t,r={}){if(this.elementMap.has(t))throw new n({type:"validation_error",code:"duplicate_element",message:`Element for ${t} already created`,retryable:false});let o={iframeBase:this.iframeBase,publishableKey:this.publishableKey,channelId:this.channelId},s=new y(t,r,o);return this.elementMap.set(t,s),s}async tokenize(t,r){if(this.tokenizeInFlight)throw new n({type:"validation_error",code:"tokenize_in_progress",message:"A tokenize() call is already in progress for this Elements instance",retryable:false});let o=this.elementMap.get("cardNumber"),s=this.elementMap.get("cardExpiry"),a=this.elementMap.get("cardCvv");if(!o||!s||!a)throw new n({type:"validation_error",code:"incomplete_elements",message:"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()",retryable:false});if(!o.isReady()||!s.isReady()||!a.isReady())throw new n({type:"validation_error",code:"elements_not_ready",message:"Wait for all elements to fire 'ready' event before tokenize()",retryable:false});this.tokenizeInFlight=true;try{return await this.doTokenize(o,t,r)}finally{this.tokenizeInFlight=false;}}doTokenize(t,r,o){let s=new URL(this.iframeBase).origin,a=t.getIframeContentWindow();return new Promise((p,l)=>{let x=window.setTimeout(()=>{window.removeEventListener("message",c),l(new n({type:"network_error",code:"tokenize_timeout",message:"tokenize() timed out after 30 seconds",retryable:true,paymentId:r}));},3e4),c=T=>{if(a!==null&&T.source!==a)return;let i=m(T,s);if(i){if(i.type==="arcpay:tokenize-result")clearTimeout(x),window.removeEventListener("message",c),p({cardTokenId:i.cardTokenId,cardMask:i.cardMask,cardScheme:i.cardScheme,cardBin:i.cardBin,expiresIn:i.expiresIn,expiresAt:i.expiresAt});else if(i.type==="arcpay:tokenize-error"){clearTimeout(x),window.removeEventListener("message",c);let F=i.errorType==="validation_error"||i.errorType==="api_error"?i.errorType:"api_error";l(new n({type:F,code:i.code,message:i.message,retryable:false,paymentId:r}));}}};window.addEventListener("message",c),t.send({type:"arcpay:tokenize",paymentId:r,idempotencyKey:o});})}destroy(){for(let t of this.elementMap.values())t.destroy();this.elementMap.clear();}};var j=S,_=new Map,Y=e=>(f(e)==="sandbox"&&P(),{publishableKey:e,environment:f(e),elements:()=>new d({publishableKey:e})});function X(e){try{j(e);}catch(s){return Promise.reject(s)}let t=e,r=_.get(t);if(r)return r;let o=Promise.resolve(Y(e));return _.set(t,o),o}var G=()=>{_.clear();},J={load:X,__resetForTests:G};var Q=[1,4,8,15,16,24,32,48],Z=e=>Q.includes(e)?e:24,ee=e=>e>=1e3?"05":e>=600?"04":e>=500?"03":e>=390?"02":"01",k=(e="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")=>{if(typeof window=="undefined"||typeof navigator=="undefined"||typeof screen=="undefined")throw new Error("collectBrowserInfo must be called in a browser environment");return {accept_header:e,language:navigator.language||"en",screen_width:screen.width,screen_height:screen.height,color_depth:Z(screen.colorDepth),timezone_offset_minutes:new Date().getTimezoneOffset(),java_enabled:false,user_agent:navigator.userAgent,window_size:ee(window.innerWidth||screen.width)}},v=e=>e!=null?e:null,E=e=>(e==null?void 0:e.type)==="three_ds_method"&&e.three_ds.phase==="method",A=e=>(e==null?void 0:e.type)==="three_ds_challenge"&&e.three_ds.phase==="challenge",h=e=>({action:e.three_ds.submit.url,method:e.three_ds.submit.method,target:e.three_ds.submit.target,fields:e.three_ds.submit.fields}),B=e=>{let t=v(e);return t?{kind:t.three_ds.phase,protocolVersion:t.three_ds.version,form:h(t),completionEndpoint:t.three_ds.completion_endpoint,threeDSServerTransId:t.three_ds.three_ds_server_trans_id}:null},z=(e,t="Y")=>{if(!E(e)||!e.three_ds.three_ds_server_trans_id)throw new Error("nextAction must be a three_ds_method action with three_ds_server_trans_id");return {completion_indicator:t,three_ds_server_trans_id:e.three_ds.three_ds_server_trans_id}},w=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;"),D=e=>{let t=h(e),r=t.target==="hidden_iframe"?"arcpay-three-ds-method":"_self",o=t.fields.map(a=>`<input type="hidden" name="${w(a.name)}" value="${w(a.value)}">`).join("");return `<!doctype html><html><head><meta charset="utf-8"></head><body>${t.target==="hidden_iframe"?'<iframe name="arcpay-three-ds-method" title="3-D Secure method" hidden></iframe>':""}<form method="POST" action="${w(t.action)}" target="${r}">${o}</form><script>document.forms[0].submit();</script></body></html>`};var xe="0.1.12";
2
+ exports.ArcPay=J;exports.ArcPayError=n;exports.Elements=d;exports.SDK_VERSION=xe;exports.buildThreeDSAutoSubmitHtml=D;exports.buildThreeDSBrowserForm=h;exports.buildThreeDSBrowserStep=B;exports.buildThreeDSMethodCompletion=z;exports.collectBrowserInfo=k;exports.getThreeDSAction=v;exports.isApiError=O;exports.isAuthenticationError=M;exports.isAuthorizationError=R;exports.isChallengeAborted=H;exports.isNetworkError=W;exports.isRateLimitError=N;exports.isStateError=L;exports.isThreeDSChallengeAction=A;exports.isThreeDSMethodAction=E;exports.isValidationError=C;return exports;})({});//# sourceMappingURL=arcpay.global.js.map
3
3
  //# sourceMappingURL=arcpay.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/errors.ts","../../src/core/env.ts","../../src/core/sandbox-banner.ts","../../src/elements/postmessage.ts","../../src/elements/style.ts","../../src/elements/element.ts","../../src/elements/elements.ts","../../src/core/arcpay.ts","../../src/three-ds/actions.ts","../../src/index.ts"],"names":["ArcPayError","init","isValidationError","isAuthenticationError","isAuthorizationError","isStateError","isRateLimitError","isApiError","isNetworkError","isChallengeAborted","detectEnvironment","publishableKey","validatePublishableKey","key","BANNER_ATTR","showSandboxBanner","bar","text","dismiss","ARCPAY_TYPE_PREFIX","isArcpayMessage","data","postToIframe","iframe","message","targetOrigin","parseIncoming","event","expectedOrigin","FORBIDDEN_PROPERTIES","sanitizeBlock","block","out","value","normalizedKey","sanitizeStyle","style","result","Element","field","options","context","target","container","_a","hello","_event","callback","_b","listener","DEFAULT_IFRAME_BASE","createChannelId","Elements","opts","ctx","element","paymentId","idempotencyKey","cardNumber","cardExpiry","cardCvv","iframeOrigin","cardIframeWindow","resolve","reject","timer","onMessage","errType","el","cache","buildInstance","load","err","existing","promise","resetForTests","ArcPay","supportedColorDepths","normalizeColorDepth","resolveWindowSize","width","collectBrowserInfo","acceptHeader","getThreeDSAction","nextAction","isThreeDSMethodAction","isThreeDSChallengeAction","buildThreeDSBrowserForm","htmlEscape","buildThreeDSAutoSubmitHtml","form","inputs","SDK_VERSION"],"mappings":"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","file":"arcpay.global.js","sourcesContent":["export type ArcPayErrorType =\n | \"validation_error\"\n | \"authentication_error\"\n | \"authorization_error\"\n | \"state_error\"\n | \"rate_limit_error\"\n | \"api_error\"\n | \"network_error\"\n | \"challenge_aborted\";\n\nexport interface ArcPayErrorInit {\n type: ArcPayErrorType;\n message: string;\n code?: string;\n param?: string;\n paymentId?: string;\n declineCode?: string;\n retryable: boolean;\n requestId?: string;\n}\n\nexport class ArcPayError extends Error {\n readonly type: ArcPayErrorType;\n readonly code?: string;\n readonly param?: string;\n readonly paymentId?: string;\n readonly declineCode?: string;\n readonly retryable: boolean;\n readonly requestId?: string;\n\n constructor(init: ArcPayErrorInit) {\n super(init.message);\n this.name = \"ArcPayError\";\n this.type = init.type;\n this.code = init.code;\n this.param = init.param;\n this.paymentId = init.paymentId;\n this.declineCode = init.declineCode;\n this.retryable = init.retryable;\n this.requestId = init.requestId;\n }\n}\n\nexport const isValidationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"validation_error\";\nexport const isAuthenticationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authentication_error\";\nexport const isAuthorizationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authorization_error\";\nexport const isStateError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"state_error\";\nexport const isRateLimitError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"rate_limit_error\";\nexport const isApiError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"api_error\";\nexport const isNetworkError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"network_error\";\nexport const isChallengeAborted = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"challenge_aborted\";\n","import { ArcPayError } from \"./errors\";\n\nexport type Environment = \"sandbox\" | \"live\";\n\nexport const detectEnvironment = (publishableKey: string): Environment =>\n publishableKey.startsWith(\"pk_test_\") ? \"sandbox\" : \"live\";\n\nexport const validatePublishableKey = (key: unknown): asserts key is string => {\n if (typeof key !== \"string\" || key.length === 0) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message: \"Publishable key must be a non-empty string\",\n retryable: false,\n });\n }\n if (!key.startsWith(\"pk_test_\") && !key.startsWith(\"pk_live_\")) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message:\n \"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.\",\n retryable: false,\n });\n }\n};\n","const BANNER_ATTR = \"data-arcpay-sandbox-banner\";\n\nexport const showSandboxBanner = (): void => {\n if (typeof document === \"undefined\") return;\n if (document.querySelector(`[${BANNER_ATTR}]`)) return;\n\n const bar = document.createElement(\"div\");\n bar.setAttribute(BANNER_ATTR, \"\");\n bar.style.cssText =\n \"position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);\";\n\n const text = document.createElement(\"span\");\n text.textContent = \"ARC PAY TEST MODE — payments are simulated\";\n bar.appendChild(text);\n\n const dismiss = document.createElement(\"button\");\n dismiss.type = \"button\";\n dismiss.setAttribute(\"data-arcpay-banner-dismiss\", \"\");\n dismiss.textContent = \"×\";\n dismiss.setAttribute(\"aria-label\", \"Dismiss test mode banner\");\n dismiss.style.cssText =\n \"margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;\";\n dismiss.addEventListener(\"click\", () => bar.remove());\n bar.appendChild(dismiss);\n\n document.body.appendChild(bar);\n};\n","import { ArcPayError } from \"../core/errors\";\n\nexport type FieldType = \"cardNumber\" | \"cardExpiry\" | \"cardCvv\";\n\n// Parent → iframe\nexport type ParentToIframe =\n | { type: \"arcpay:hello\"; origin: string; publishableKey: string; channelId: string }\n | { type: \"arcpay:style\"; payload: StyleSubset }\n | { type: \"arcpay:focus\" }\n | { type: \"arcpay:clear\" }\n | { type: \"arcpay:tokenize\"; paymentId: string; idempotencyKey: string };\n\n// iframe → parent\nexport type IframeToParent =\n | { type: \"arcpay:ready\" }\n | { type: \"arcpay:rejected\"; reason: string }\n | {\n type: \"arcpay:change\";\n field: FieldType;\n isValid: boolean;\n brand?: string;\n lastFour?: string;\n }\n | {\n type: \"arcpay:tokenize-result\";\n cardTokenId: string;\n cardMask: string;\n cardScheme: string;\n cardBin: string;\n expiresIn: number;\n expiresAt: string;\n }\n | { type: \"arcpay:tokenize-error\"; errorType: string; code?: string; message: string };\n\nexport interface StyleSubset {\n base: Record<string, string>;\n invalid?: Record<string, string>;\n focus?: Record<string, string>;\n}\n\nconst ARCPAY_TYPE_PREFIX = \"arcpay:\";\n\nconst isArcpayMessage = (data: unknown): data is { type: string } =>\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n typeof (data as { type: unknown }).type === \"string\" &&\n (data as { type: string }).type.startsWith(ARCPAY_TYPE_PREFIX);\n\nexport const postToIframe = (\n iframe: HTMLIFrameElement,\n message: ParentToIframe,\n targetOrigin: string,\n): void => {\n if (targetOrigin === \"*\") {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"wildcard_origin_forbidden\",\n message: \"postToIframe: targetOrigin cannot be '*'\",\n retryable: false,\n });\n }\n if (!iframe.contentWindow) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"iframe_not_loaded\",\n message: \"postToIframe: iframe.contentWindow is null (iframe not mounted)\",\n retryable: false,\n });\n }\n iframe.contentWindow.postMessage(message, targetOrigin);\n};\n\nexport const postToParent = (message: IframeToParent, targetOrigin: string): void => {\n if (targetOrigin === \"*\") {\n throw new Error(\"postToParent: targetOrigin cannot be '*'\");\n }\n window.parent.postMessage(message, targetOrigin);\n};\n\nexport const parseIncoming = <T extends { type: string }>(\n event: MessageEvent,\n expectedOrigin: string,\n): T | null => {\n if (event.origin !== expectedOrigin) return null;\n if (!isArcpayMessage(event.data)) return null;\n return event.data as T;\n};\n","import type { StyleSubset } from \"./postmessage\";\n\n// Spec calls out position:fixed, transform, pointer-events:none as forbidden.\n// We extend to cover the full clickjacking attack surface: any positioning\n// (fixed/absolute/sticky), transform, all pointer-events values, z-index, and\n// inset properties (top/left/right/bottom/inset). The legitimate use cases\n// for these in a 1-line input field are zero, so blanket drop.\nconst FORBIDDEN_PROPERTIES = new Set([\n \"position\",\n \"transform\",\n \"pointer-events\",\n \"z-index\",\n \"top\",\n \"left\",\n \"right\",\n \"bottom\",\n \"inset\",\n]);\n\nconst sanitizeBlock = (block: Record<string, string>): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(block)) {\n const normalizedKey = key.toLowerCase();\n if (FORBIDDEN_PROPERTIES.has(normalizedKey)) {\n // Defense against position/transform-based clickjacking. Silently drop.\n continue;\n }\n out[key] = value;\n }\n return out;\n};\n\nexport const sanitizeStyle = (style: StyleSubset): StyleSubset => {\n const result: StyleSubset = { base: sanitizeBlock(style.base) };\n if (style.invalid !== undefined) result.invalid = sanitizeBlock(style.invalid);\n if (style.focus !== undefined) result.focus = sanitizeBlock(style.focus);\n return result;\n};\n","import { ArcPayError } from \"../core/errors\";\nimport {\n type FieldType,\n type ParentToIframe,\n type IframeToParent,\n type StyleSubset,\n postToIframe,\n parseIncoming,\n} from \"./postmessage\";\nimport { sanitizeStyle } from \"./style\";\n\nexport interface ElementOptions {\n /** StyleSubset applied via arcpay:style postMessage. */\n style?: StyleSubset;\n placeholder?: string;\n}\n\nexport type ElementEvent =\n | { type: \"ready\" }\n | { type: \"change\"; isValid: boolean; brand?: string; lastFour?: string }\n | { type: \"error\"; reason: string };\n\ntype Listener = (event: ElementEvent) => void;\n\nexport interface ElementContext {\n iframeBase: string;\n publishableKey: string;\n channelId: string;\n}\n\nexport class Element {\n private iframe: HTMLIFrameElement | null = null;\n private readonly listeners = new Set<Listener>();\n private status: \"pending\" | \"ready\" | \"error\" = \"pending\";\n private messageHandler: ((e: MessageEvent) => void) | null = null;\n\n constructor(\n public readonly field: FieldType,\n private readonly options: ElementOptions,\n private readonly context: ElementContext,\n ) {}\n\n mount(target: string | HTMLElement): void {\n if (this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"already_mounted\",\n message: `Element ${this.field} is already mounted`,\n retryable: false,\n });\n }\n const container = typeof target === \"string\" ? document.querySelector(target) : target;\n if (!(container instanceof HTMLElement)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"mount_target_not_found\",\n message: `mount target not found: ${String(target)}`,\n retryable: false,\n });\n }\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${this.context.iframeBase}/iframe/${this.field}`;\n iframe.style.cssText = \"border:0;width:100%;height:100%;display:block;\";\n iframe.setAttribute(\"allow\", \"payment\");\n iframe.setAttribute(\"data-arcpay-element\", this.field);\n container.appendChild(iframe);\n this.iframe = iframe;\n\n const expectedOrigin = new URL(this.context.iframeBase).origin;\n\n this.messageHandler = (event: MessageEvent) => {\n // C1: source guard — only accept messages from this element's own iframe.\n // Without this, any iframe at the same origin (e.g. cardExpiry, cardCvv)\n // could trigger handlers on cardNumber and vice-versa.\n if (event.source !== this.iframe?.contentWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, expectedOrigin);\n if (!data) return;\n this.handleMessage(data);\n };\n window.addEventListener(\"message\", this.messageHandler);\n\n iframe.addEventListener(\n \"load\",\n () => {\n if (!this.iframe) return;\n const hello: ParentToIframe = {\n type: \"arcpay:hello\",\n origin: window.location.origin,\n publishableKey: this.context.publishableKey,\n channelId: this.context.channelId,\n };\n postToIframe(this.iframe, hello, expectedOrigin);\n },\n { once: true },\n );\n }\n\n private handleMessage(data: IframeToParent): void {\n if (data.type === \"arcpay:ready\") {\n this.status = \"ready\";\n // Apply initial style if provided at construction time.\n if (this.options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(this.options.style) });\n }\n this.emit({ type: \"ready\" });\n } else if (data.type === \"arcpay:rejected\") {\n this.status = \"error\";\n this.emit({ type: \"error\", reason: data.reason });\n } else if (data.type === \"arcpay:change\" && data.field === this.field) {\n this.emit({\n type: \"change\",\n isValid: data.isValid,\n brand: data.brand,\n lastFour: data.lastFour,\n });\n }\n // arcpay:tokenize-result / arcpay:tokenize-error handled by Elements factory (Task 9).\n }\n\n update(options: { style?: StyleSubset }): void {\n if (options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(options.style) });\n }\n }\n\n destroy(): void {\n if (this.iframe) {\n this.iframe.remove();\n this.iframe = null;\n }\n if (this.messageHandler) {\n window.removeEventListener(\"message\", this.messageHandler);\n this.messageHandler = null;\n }\n this.listeners.clear();\n this.status = \"pending\";\n }\n\n on(_event: \"ready\" | \"change\" | \"error\", callback: Listener): () => void {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n\n focus(): void {\n this.send({ type: \"arcpay:focus\" });\n }\n\n clear(): void {\n this.send({ type: \"arcpay:clear\" });\n }\n\n isReady(): boolean {\n return this.status === \"ready\";\n }\n\n /**\n * Internal: returns the iframe's contentWindow for source-filtering in\n * Elements.doTokenize(). Returns null when the iframe is not yet mounted\n * or when jsdom has not yet populated contentWindow (test environment).\n */\n getIframeContentWindow(): Window | null {\n return this.iframe?.contentWindow ?? null;\n }\n\n /** Internal: used by Elements factory to send tokenize commands. */\n send(message: ParentToIframe): void {\n if (!this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"not_mounted\",\n message: `Element ${this.field} is not mounted`,\n retryable: false,\n });\n }\n postToIframe(this.iframe, message, new URL(this.context.iframeBase).origin);\n }\n\n private emit(event: ElementEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n}\n","import { ArcPayError } from \"../core/errors\";\nimport { Element, type ElementContext, type ElementOptions } from \"./element\";\nimport type { FieldType, IframeToParent } from \"./postmessage\";\nimport { parseIncoming } from \"./postmessage\";\nimport type { TokenizeResult } from \"../tokenize/tokenize\";\n\nexport type { TokenizeResult };\n\nexport type ElementsOptions = Record<string, never>;\n\nconst DEFAULT_IFRAME_BASE = \"https://sdk.arcpay.space\";\n\nconst createChannelId = (): string => {\n if (!globalThis.crypto?.randomUUID) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"crypto_unavailable\",\n message: \"crypto.randomUUID is required for Hosted Fields\",\n retryable: false,\n });\n }\n return globalThis.crypto.randomUUID();\n};\n\nexport class Elements {\n private readonly elementMap = new Map<FieldType, Element>();\n private readonly iframeBase: string;\n private readonly publishableKey: string;\n private readonly channelId: string;\n private tokenizeInFlight = false;\n\n constructor(opts: { publishableKey: string; iframeBase?: string }) {\n this.publishableKey = opts.publishableKey;\n this.iframeBase = opts.iframeBase ?? DEFAULT_IFRAME_BASE;\n this.channelId = createChannelId();\n }\n\n create(field: FieldType, options: ElementOptions = {}): Element {\n if (this.elementMap.has(field)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"duplicate_element\",\n message: `Element for ${field} already created`,\n retryable: false,\n });\n }\n const ctx: ElementContext = {\n iframeBase: this.iframeBase,\n publishableKey: this.publishableKey,\n channelId: this.channelId,\n };\n const element = new Element(field, options, ctx);\n this.elementMap.set(field, element);\n return element;\n }\n\n async tokenize(paymentId: string, idempotencyKey: string): Promise<TokenizeResult> {\n // C2: concurrent-call guard — only one tokenize() may be in-flight at a time.\n if (this.tokenizeInFlight) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"tokenize_in_progress\",\n message: \"A tokenize() call is already in progress for this Elements instance\",\n retryable: false,\n });\n }\n\n const cardNumber = this.elementMap.get(\"cardNumber\");\n const cardExpiry = this.elementMap.get(\"cardExpiry\");\n const cardCvv = this.elementMap.get(\"cardCvv\");\n\n if (!cardNumber || !cardExpiry || !cardCvv) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"incomplete_elements\",\n message:\n \"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()\",\n retryable: false,\n });\n }\n if (!cardNumber.isReady() || !cardExpiry.isReady() || !cardCvv.isReady()) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"elements_not_ready\",\n message: \"Wait for all elements to fire 'ready' event before tokenize()\",\n retryable: false,\n });\n }\n\n this.tokenizeInFlight = true;\n try {\n return await this.doTokenize(cardNumber, paymentId, idempotencyKey);\n } finally {\n this.tokenizeInFlight = false;\n }\n }\n\n private doTokenize(\n cardNumber: Element,\n paymentId: string,\n idempotencyKey: string,\n ): Promise<TokenizeResult> {\n const iframeOrigin = new URL(this.iframeBase).origin;\n // C1: obtain reference to the cardNumber iframe's contentWindow before\n // registering the listener so we can filter by source.\n const cardIframeWindow = cardNumber.getIframeContentWindow();\n\n return new Promise<TokenizeResult>((resolve, reject) => {\n // C3: 30-second timeout — rejects and cleans up if no result arrives.\n const timer = window.setTimeout(() => {\n window.removeEventListener(\"message\", onMessage);\n reject(\n new ArcPayError({\n type: \"network_error\",\n code: \"tokenize_timeout\",\n message: \"tokenize() timed out after 30 seconds\",\n retryable: true,\n paymentId,\n }),\n );\n }, 30_000);\n\n const onMessage = (event: MessageEvent) => {\n // C1: source guard — only accept messages from the cardNumber iframe.\n if (cardIframeWindow !== null && event.source !== cardIframeWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, iframeOrigin);\n if (!data) return;\n\n if (data.type === \"arcpay:tokenize-result\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n resolve({\n cardTokenId: data.cardTokenId,\n cardMask: data.cardMask,\n cardScheme: data.cardScheme,\n cardBin: data.cardBin,\n expiresIn: data.expiresIn,\n expiresAt: data.expiresAt,\n });\n } else if (data.type === \"arcpay:tokenize-error\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n const errType =\n data.errorType === \"validation_error\" || data.errorType === \"api_error\"\n ? data.errorType\n : \"api_error\";\n reject(\n new ArcPayError({\n type: errType,\n code: data.code,\n message: data.message,\n retryable: false,\n paymentId,\n }),\n );\n }\n };\n\n window.addEventListener(\"message\", onMessage);\n cardNumber.send({ type: \"arcpay:tokenize\", paymentId, idempotencyKey });\n });\n }\n\n destroy(): void {\n for (const el of this.elementMap.values()) {\n el.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import {\n detectEnvironment,\n type Environment,\n validatePublishableKey as _validatePublishableKey,\n} from \"./env\";\nimport { showSandboxBanner } from \"./sandbox-banner\";\nimport { Elements, type ElementsOptions } from \"../elements/elements\";\n\nconst validatePublishableKey: (key: unknown) => asserts key is string = _validatePublishableKey;\n\nexport interface ArcPayLoadOptions {\n readonly _reserved?: never;\n}\n\nexport interface ArcPayInstance {\n readonly publishableKey: string;\n readonly environment: Environment;\n elements: (opts?: ElementsOptions) => Elements;\n}\n\nconst cache = new Map<string, Promise<ArcPayInstance>>();\n\nconst buildInstance = (publishableKey: string): ArcPayInstance => {\n if (detectEnvironment(publishableKey) === \"sandbox\") {\n showSandboxBanner();\n }\n return {\n publishableKey,\n environment: detectEnvironment(publishableKey),\n elements: () => new Elements({ publishableKey }),\n };\n};\n\nfunction load(publishableKey: string): Promise<ArcPayInstance> {\n try {\n validatePublishableKey(publishableKey);\n } catch (err) {\n return Promise.reject(err);\n }\n const key = publishableKey;\n const existing = cache.get(key);\n if (existing) return existing;\n const promise = Promise.resolve(buildInstance(publishableKey));\n cache.set(key, promise);\n return promise;\n}\n\nconst resetForTests = (): void => {\n cache.clear();\n};\n\nexport const ArcPay = {\n load,\n __resetForTests: resetForTests,\n};\n","import type { PaymentNextAction } from \"../server/types\";\nimport type { ExecutePaymentRequest } from \"../server/types\";\n\nexport type ThreeDSAction = PaymentNextAction;\nexport type BrowserInfo = ExecutePaymentRequest[\"browser_info\"];\n\nexport interface BrowserFormField {\n name: string;\n value: string;\n}\n\nexport interface BrowserPostForm {\n action: string;\n method: \"POST\";\n target: \"hidden_iframe\" | \"browser\";\n fields: BrowserFormField[];\n}\n\nconst supportedColorDepths = [1, 4, 8, 15, 16, 24, 32, 48] as const;\n\nconst normalizeColorDepth = (value: number): BrowserInfo[\"color_depth\"] =>\n supportedColorDepths.includes(value as BrowserInfo[\"color_depth\"])\n ? (value as BrowserInfo[\"color_depth\"])\n : 24;\n\nconst resolveWindowSize = (width: number): NonNullable<BrowserInfo[\"window_size\"]> => {\n if (width >= 1000) return \"05\";\n if (width >= 600) return \"04\";\n if (width >= 500) return \"03\";\n if (width >= 390) return \"02\";\n return \"01\";\n};\n\nexport const collectBrowserInfo = (\n acceptHeader = \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\",\n): BrowserInfo => {\n if (\n typeof window === \"undefined\" ||\n typeof navigator === \"undefined\" ||\n typeof screen === \"undefined\"\n ) {\n throw new Error(\"collectBrowserInfo must be called in a browser environment\");\n }\n return {\n accept_header: acceptHeader,\n language: navigator.language || \"en\",\n screen_width: screen.width,\n screen_height: screen.height,\n color_depth: normalizeColorDepth(screen.colorDepth),\n timezone_offset_minutes: new Date().getTimezoneOffset(),\n java_enabled: false,\n user_agent: navigator.userAgent,\n window_size: resolveWindowSize(window.innerWidth || screen.width),\n };\n};\n\nexport const getThreeDSAction = (nextAction?: PaymentNextAction): PaymentNextAction | null => {\n return nextAction ?? null;\n};\n\nexport const isThreeDSMethodAction = (nextAction?: PaymentNextAction): boolean => {\n return nextAction?.type === \"three_ds_method\" && nextAction.three_ds.phase === \"method\";\n};\n\nexport const isThreeDSChallengeAction = (nextAction?: PaymentNextAction): boolean => {\n return nextAction?.type === \"three_ds_challenge\" && nextAction.three_ds.phase === \"challenge\";\n};\n\nexport const buildThreeDSBrowserForm = (nextAction: PaymentNextAction): BrowserPostForm => ({\n action: nextAction.three_ds.submit.url,\n method: nextAction.three_ds.submit.method,\n target: nextAction.three_ds.submit.target,\n fields: nextAction.three_ds.submit.fields,\n});\n\nconst htmlEscape = (value: string): string =>\n value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n\nexport const buildThreeDSAutoSubmitHtml = (nextAction: PaymentNextAction): string => {\n const form = buildThreeDSBrowserForm(nextAction);\n const target = form.target === \"hidden_iframe\" ? \"arcpay-three-ds-method\" : \"_self\";\n const inputs = form.fields\n .map(\n (field) =>\n `<input type=\"hidden\" name=\"${htmlEscape(field.name)}\" value=\"${htmlEscape(field.value)}\">`,\n )\n .join(\"\");\n const iframe =\n form.target === \"hidden_iframe\"\n ? '<iframe name=\"arcpay-three-ds-method\" title=\"3-D Secure method\" hidden></iframe>'\n : \"\";\n return `<!doctype html><html><head><meta charset=\"utf-8\"></head><body>${iframe}<form method=\"POST\" action=\"${htmlEscape(form.action)}\" target=\"${target}\">${inputs}</form><script>document.forms[0].submit();</script></body></html>`;\n};\n","export { ArcPay } from \"./core/arcpay\";\nexport type { ArcPayInstance, ArcPayLoadOptions } from \"./core/arcpay\";\nexport {\n ArcPayError,\n isValidationError,\n isAuthenticationError,\n isAuthorizationError,\n isStateError,\n isRateLimitError,\n isApiError,\n isNetworkError,\n isChallengeAborted,\n} from \"./core/errors\";\nexport type { ArcPayErrorType } from \"./core/errors\";\nexport type { Environment } from \"./core/env\";\nexport type { TokenizeResult } from \"./tokenize/tokenize\";\nexport type { CardScheme } from \"./tokenize/scheme\";\nexport {\n buildThreeDSAutoSubmitHtml,\n buildThreeDSBrowserForm,\n collectBrowserInfo,\n getThreeDSAction,\n isThreeDSChallengeAction,\n isThreeDSMethodAction,\n} from \"./three-ds\";\nexport type { BrowserFormField, BrowserInfo, BrowserPostForm, ThreeDSAction } from \"./three-ds\";\nexport const SDK_VERSION = \"0.1.11\";\n\nexport type { FieldType } from \"./elements/postmessage\";\nexport type { ElementOptions, ElementEvent } from \"./elements/element\";\nexport { Elements } from \"./elements/elements\";\nexport type { ElementsOptions } from \"./elements/elements\";\n"]}
1
+ {"version":3,"sources":["../../src/core/errors.ts","../../src/core/env.ts","../../src/core/sandbox-banner.ts","../../src/elements/postmessage.ts","../../src/elements/style.ts","../../src/elements/element.ts","../../src/elements/elements.ts","../../src/core/arcpay.ts","../../src/three-ds/actions.ts","../../src/index.ts"],"names":["ArcPayError","init","isValidationError","isAuthenticationError","isAuthorizationError","isStateError","isRateLimitError","isApiError","isNetworkError","isChallengeAborted","detectEnvironment","publishableKey","validatePublishableKey","key","BANNER_ATTR","showSandboxBanner","bar","text","dismiss","ARCPAY_TYPE_PREFIX","isArcpayMessage","data","postToIframe","iframe","message","targetOrigin","parseIncoming","event","expectedOrigin","FORBIDDEN_PROPERTIES","sanitizeBlock","block","out","value","normalizedKey","sanitizeStyle","style","result","Element","field","options","context","target","container","_a","hello","_event","callback","_b","listener","DEFAULT_IFRAME_BASE","createChannelId","Elements","opts","ctx","element","paymentId","idempotencyKey","cardNumber","cardExpiry","cardCvv","iframeOrigin","cardIframeWindow","resolve","reject","timer","onMessage","errType","el","cache","buildInstance","load","err","existing","promise","resetForTests","ArcPay","supportedColorDepths","normalizeColorDepth","resolveWindowSize","width","collectBrowserInfo","acceptHeader","getThreeDSAction","nextAction","isThreeDSMethodAction","isThreeDSChallengeAction","buildThreeDSBrowserForm","buildThreeDSBrowserStep","action","buildThreeDSMethodCompletion","completionIndicator","htmlEscape","buildThreeDSAutoSubmitHtml","form","inputs","SDK_VERSION"],"mappings":"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","file":"arcpay.global.js","sourcesContent":["export type ArcPayErrorType =\n | \"validation_error\"\n | \"authentication_error\"\n | \"authorization_error\"\n | \"state_error\"\n | \"rate_limit_error\"\n | \"api_error\"\n | \"network_error\"\n | \"challenge_aborted\";\n\nexport interface ArcPayErrorInit {\n type: ArcPayErrorType;\n message: string;\n code?: string;\n param?: string;\n paymentId?: string;\n declineCode?: string;\n retryable: boolean;\n requestId?: string;\n}\n\nexport class ArcPayError extends Error {\n readonly type: ArcPayErrorType;\n readonly code?: string;\n readonly param?: string;\n readonly paymentId?: string;\n readonly declineCode?: string;\n readonly retryable: boolean;\n readonly requestId?: string;\n\n constructor(init: ArcPayErrorInit) {\n super(init.message);\n this.name = \"ArcPayError\";\n this.type = init.type;\n this.code = init.code;\n this.param = init.param;\n this.paymentId = init.paymentId;\n this.declineCode = init.declineCode;\n this.retryable = init.retryable;\n this.requestId = init.requestId;\n }\n}\n\nexport const isValidationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"validation_error\";\nexport const isAuthenticationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authentication_error\";\nexport const isAuthorizationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authorization_error\";\nexport const isStateError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"state_error\";\nexport const isRateLimitError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"rate_limit_error\";\nexport const isApiError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"api_error\";\nexport const isNetworkError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"network_error\";\nexport const isChallengeAborted = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"challenge_aborted\";\n","import { ArcPayError } from \"./errors\";\n\nexport type Environment = \"sandbox\" | \"live\";\n\nexport const detectEnvironment = (publishableKey: string): Environment =>\n publishableKey.startsWith(\"pk_test_\") ? \"sandbox\" : \"live\";\n\nexport const validatePublishableKey = (key: unknown): asserts key is string => {\n if (typeof key !== \"string\" || key.length === 0) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message: \"Publishable key must be a non-empty string\",\n retryable: false,\n });\n }\n if (!key.startsWith(\"pk_test_\") && !key.startsWith(\"pk_live_\")) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message:\n \"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.\",\n retryable: false,\n });\n }\n};\n","const BANNER_ATTR = \"data-arcpay-sandbox-banner\";\n\nexport const showSandboxBanner = (): void => {\n if (typeof document === \"undefined\") return;\n if (document.querySelector(`[${BANNER_ATTR}]`)) return;\n\n const bar = document.createElement(\"div\");\n bar.setAttribute(BANNER_ATTR, \"\");\n bar.style.cssText =\n \"position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);\";\n\n const text = document.createElement(\"span\");\n text.textContent = \"ARC PAY TEST MODE — payments are simulated\";\n bar.appendChild(text);\n\n const dismiss = document.createElement(\"button\");\n dismiss.type = \"button\";\n dismiss.setAttribute(\"data-arcpay-banner-dismiss\", \"\");\n dismiss.textContent = \"×\";\n dismiss.setAttribute(\"aria-label\", \"Dismiss test mode banner\");\n dismiss.style.cssText =\n \"margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;\";\n dismiss.addEventListener(\"click\", () => bar.remove());\n bar.appendChild(dismiss);\n\n document.body.appendChild(bar);\n};\n","import { ArcPayError } from \"../core/errors\";\n\nexport type FieldType = \"cardNumber\" | \"cardExpiry\" | \"cardCvv\";\n\n// Parent → iframe\nexport type ParentToIframe =\n | { type: \"arcpay:hello\"; origin: string; publishableKey: string; channelId: string }\n | { type: \"arcpay:style\"; payload: StyleSubset }\n | { type: \"arcpay:focus\" }\n | { type: \"arcpay:clear\" }\n | { type: \"arcpay:tokenize\"; paymentId: string; idempotencyKey: string };\n\n// iframe → parent\nexport type IframeToParent =\n | { type: \"arcpay:ready\" }\n | { type: \"arcpay:rejected\"; reason: string }\n | {\n type: \"arcpay:change\";\n field: FieldType;\n isValid: boolean;\n brand?: string;\n lastFour?: string;\n }\n | {\n type: \"arcpay:tokenize-result\";\n cardTokenId: string;\n cardMask: string;\n cardScheme: string;\n cardBin: string;\n expiresIn: number;\n expiresAt: string;\n }\n | { type: \"arcpay:tokenize-error\"; errorType: string; code?: string; message: string };\n\nexport interface StyleSubset {\n base: Record<string, string>;\n invalid?: Record<string, string>;\n focus?: Record<string, string>;\n}\n\nconst ARCPAY_TYPE_PREFIX = \"arcpay:\";\n\nconst isArcpayMessage = (data: unknown): data is { type: string } =>\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n typeof (data as { type: unknown }).type === \"string\" &&\n (data as { type: string }).type.startsWith(ARCPAY_TYPE_PREFIX);\n\nexport const postToIframe = (\n iframe: HTMLIFrameElement,\n message: ParentToIframe,\n targetOrigin: string,\n): void => {\n if (targetOrigin === \"*\") {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"wildcard_origin_forbidden\",\n message: \"postToIframe: targetOrigin cannot be '*'\",\n retryable: false,\n });\n }\n if (!iframe.contentWindow) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"iframe_not_loaded\",\n message: \"postToIframe: iframe.contentWindow is null (iframe not mounted)\",\n retryable: false,\n });\n }\n iframe.contentWindow.postMessage(message, targetOrigin);\n};\n\nexport const postToParent = (message: IframeToParent, targetOrigin: string): void => {\n if (targetOrigin === \"*\") {\n throw new Error(\"postToParent: targetOrigin cannot be '*'\");\n }\n window.parent.postMessage(message, targetOrigin);\n};\n\nexport const parseIncoming = <T extends { type: string }>(\n event: MessageEvent,\n expectedOrigin: string,\n): T | null => {\n if (event.origin !== expectedOrigin) return null;\n if (!isArcpayMessage(event.data)) return null;\n return event.data as T;\n};\n","import type { StyleSubset } from \"./postmessage\";\n\n// Spec calls out position:fixed, transform, pointer-events:none as forbidden.\n// We extend to cover the full clickjacking attack surface: any positioning\n// (fixed/absolute/sticky), transform, all pointer-events values, z-index, and\n// inset properties (top/left/right/bottom/inset). The legitimate use cases\n// for these in a 1-line input field are zero, so blanket drop.\nconst FORBIDDEN_PROPERTIES = new Set([\n \"position\",\n \"transform\",\n \"pointer-events\",\n \"z-index\",\n \"top\",\n \"left\",\n \"right\",\n \"bottom\",\n \"inset\",\n]);\n\nconst sanitizeBlock = (block: Record<string, string>): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(block)) {\n const normalizedKey = key.toLowerCase();\n if (FORBIDDEN_PROPERTIES.has(normalizedKey)) {\n // Defense against position/transform-based clickjacking. Silently drop.\n continue;\n }\n out[key] = value;\n }\n return out;\n};\n\nexport const sanitizeStyle = (style: StyleSubset): StyleSubset => {\n const result: StyleSubset = { base: sanitizeBlock(style.base) };\n if (style.invalid !== undefined) result.invalid = sanitizeBlock(style.invalid);\n if (style.focus !== undefined) result.focus = sanitizeBlock(style.focus);\n return result;\n};\n","import { ArcPayError } from \"../core/errors\";\nimport {\n type FieldType,\n type ParentToIframe,\n type IframeToParent,\n type StyleSubset,\n postToIframe,\n parseIncoming,\n} from \"./postmessage\";\nimport { sanitizeStyle } from \"./style\";\n\nexport interface ElementOptions {\n /** StyleSubset applied via arcpay:style postMessage. */\n style?: StyleSubset;\n placeholder?: string;\n}\n\nexport type ElementEvent =\n | { type: \"ready\" }\n | { type: \"change\"; isValid: boolean; brand?: string; lastFour?: string }\n | { type: \"error\"; reason: string };\n\ntype Listener = (event: ElementEvent) => void;\n\nexport interface ElementContext {\n iframeBase: string;\n publishableKey: string;\n channelId: string;\n}\n\nexport class Element {\n private iframe: HTMLIFrameElement | null = null;\n private readonly listeners = new Set<Listener>();\n private status: \"pending\" | \"ready\" | \"error\" = \"pending\";\n private messageHandler: ((e: MessageEvent) => void) | null = null;\n\n constructor(\n public readonly field: FieldType,\n private readonly options: ElementOptions,\n private readonly context: ElementContext,\n ) {}\n\n mount(target: string | HTMLElement): void {\n if (this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"already_mounted\",\n message: `Element ${this.field} is already mounted`,\n retryable: false,\n });\n }\n const container = typeof target === \"string\" ? document.querySelector(target) : target;\n if (!(container instanceof HTMLElement)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"mount_target_not_found\",\n message: `mount target not found: ${String(target)}`,\n retryable: false,\n });\n }\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${this.context.iframeBase}/iframe/${this.field}`;\n iframe.style.cssText = \"border:0;width:100%;height:100%;display:block;\";\n iframe.setAttribute(\"allow\", \"payment\");\n iframe.setAttribute(\"data-arcpay-element\", this.field);\n container.appendChild(iframe);\n this.iframe = iframe;\n\n const expectedOrigin = new URL(this.context.iframeBase).origin;\n\n this.messageHandler = (event: MessageEvent) => {\n // C1: source guard — only accept messages from this element's own iframe.\n // Without this, any iframe at the same origin (e.g. cardExpiry, cardCvv)\n // could trigger handlers on cardNumber and vice-versa.\n if (event.source !== this.iframe?.contentWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, expectedOrigin);\n if (!data) return;\n this.handleMessage(data);\n };\n window.addEventListener(\"message\", this.messageHandler);\n\n iframe.addEventListener(\n \"load\",\n () => {\n if (!this.iframe) return;\n const hello: ParentToIframe = {\n type: \"arcpay:hello\",\n origin: window.location.origin,\n publishableKey: this.context.publishableKey,\n channelId: this.context.channelId,\n };\n postToIframe(this.iframe, hello, expectedOrigin);\n },\n { once: true },\n );\n }\n\n private handleMessage(data: IframeToParent): void {\n if (data.type === \"arcpay:ready\") {\n this.status = \"ready\";\n // Apply initial style if provided at construction time.\n if (this.options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(this.options.style) });\n }\n this.emit({ type: \"ready\" });\n } else if (data.type === \"arcpay:rejected\") {\n this.status = \"error\";\n this.emit({ type: \"error\", reason: data.reason });\n } else if (data.type === \"arcpay:change\" && data.field === this.field) {\n this.emit({\n type: \"change\",\n isValid: data.isValid,\n brand: data.brand,\n lastFour: data.lastFour,\n });\n }\n // arcpay:tokenize-result / arcpay:tokenize-error handled by Elements factory (Task 9).\n }\n\n update(options: { style?: StyleSubset }): void {\n if (options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(options.style) });\n }\n }\n\n destroy(): void {\n if (this.iframe) {\n this.iframe.remove();\n this.iframe = null;\n }\n if (this.messageHandler) {\n window.removeEventListener(\"message\", this.messageHandler);\n this.messageHandler = null;\n }\n this.listeners.clear();\n this.status = \"pending\";\n }\n\n on(_event: \"ready\" | \"change\" | \"error\", callback: Listener): () => void {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n\n focus(): void {\n this.send({ type: \"arcpay:focus\" });\n }\n\n clear(): void {\n this.send({ type: \"arcpay:clear\" });\n }\n\n isReady(): boolean {\n return this.status === \"ready\";\n }\n\n /**\n * Internal: returns the iframe's contentWindow for source-filtering in\n * Elements.doTokenize(). Returns null when the iframe is not yet mounted\n * or when jsdom has not yet populated contentWindow (test environment).\n */\n getIframeContentWindow(): Window | null {\n return this.iframe?.contentWindow ?? null;\n }\n\n /** Internal: used by Elements factory to send tokenize commands. */\n send(message: ParentToIframe): void {\n if (!this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"not_mounted\",\n message: `Element ${this.field} is not mounted`,\n retryable: false,\n });\n }\n postToIframe(this.iframe, message, new URL(this.context.iframeBase).origin);\n }\n\n private emit(event: ElementEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n}\n","import { ArcPayError } from \"../core/errors\";\nimport { Element, type ElementContext, type ElementOptions } from \"./element\";\nimport type { FieldType, IframeToParent } from \"./postmessage\";\nimport { parseIncoming } from \"./postmessage\";\nimport type { TokenizeResult } from \"../tokenize/tokenize\";\n\nexport type { TokenizeResult };\n\nexport type ElementsOptions = Record<string, never>;\n\nconst DEFAULT_IFRAME_BASE = \"https://sdk.arcpay.space\";\n\nconst createChannelId = (): string => {\n if (!globalThis.crypto?.randomUUID) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"crypto_unavailable\",\n message: \"crypto.randomUUID is required for Hosted Fields\",\n retryable: false,\n });\n }\n return globalThis.crypto.randomUUID();\n};\n\nexport class Elements {\n private readonly elementMap = new Map<FieldType, Element>();\n private readonly iframeBase: string;\n private readonly publishableKey: string;\n private readonly channelId: string;\n private tokenizeInFlight = false;\n\n constructor(opts: { publishableKey: string; iframeBase?: string }) {\n this.publishableKey = opts.publishableKey;\n this.iframeBase = opts.iframeBase ?? DEFAULT_IFRAME_BASE;\n this.channelId = createChannelId();\n }\n\n create(field: FieldType, options: ElementOptions = {}): Element {\n if (this.elementMap.has(field)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"duplicate_element\",\n message: `Element for ${field} already created`,\n retryable: false,\n });\n }\n const ctx: ElementContext = {\n iframeBase: this.iframeBase,\n publishableKey: this.publishableKey,\n channelId: this.channelId,\n };\n const element = new Element(field, options, ctx);\n this.elementMap.set(field, element);\n return element;\n }\n\n async tokenize(paymentId: string, idempotencyKey: string): Promise<TokenizeResult> {\n // C2: concurrent-call guard — only one tokenize() may be in-flight at a time.\n if (this.tokenizeInFlight) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"tokenize_in_progress\",\n message: \"A tokenize() call is already in progress for this Elements instance\",\n retryable: false,\n });\n }\n\n const cardNumber = this.elementMap.get(\"cardNumber\");\n const cardExpiry = this.elementMap.get(\"cardExpiry\");\n const cardCvv = this.elementMap.get(\"cardCvv\");\n\n if (!cardNumber || !cardExpiry || !cardCvv) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"incomplete_elements\",\n message:\n \"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()\",\n retryable: false,\n });\n }\n if (!cardNumber.isReady() || !cardExpiry.isReady() || !cardCvv.isReady()) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"elements_not_ready\",\n message: \"Wait for all elements to fire 'ready' event before tokenize()\",\n retryable: false,\n });\n }\n\n this.tokenizeInFlight = true;\n try {\n return await this.doTokenize(cardNumber, paymentId, idempotencyKey);\n } finally {\n this.tokenizeInFlight = false;\n }\n }\n\n private doTokenize(\n cardNumber: Element,\n paymentId: string,\n idempotencyKey: string,\n ): Promise<TokenizeResult> {\n const iframeOrigin = new URL(this.iframeBase).origin;\n // C1: obtain reference to the cardNumber iframe's contentWindow before\n // registering the listener so we can filter by source.\n const cardIframeWindow = cardNumber.getIframeContentWindow();\n\n return new Promise<TokenizeResult>((resolve, reject) => {\n // C3: 30-second timeout — rejects and cleans up if no result arrives.\n const timer = window.setTimeout(() => {\n window.removeEventListener(\"message\", onMessage);\n reject(\n new ArcPayError({\n type: \"network_error\",\n code: \"tokenize_timeout\",\n message: \"tokenize() timed out after 30 seconds\",\n retryable: true,\n paymentId,\n }),\n );\n }, 30_000);\n\n const onMessage = (event: MessageEvent) => {\n // C1: source guard — only accept messages from the cardNumber iframe.\n if (cardIframeWindow !== null && event.source !== cardIframeWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, iframeOrigin);\n if (!data) return;\n\n if (data.type === \"arcpay:tokenize-result\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n resolve({\n cardTokenId: data.cardTokenId,\n cardMask: data.cardMask,\n cardScheme: data.cardScheme,\n cardBin: data.cardBin,\n expiresIn: data.expiresIn,\n expiresAt: data.expiresAt,\n });\n } else if (data.type === \"arcpay:tokenize-error\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n const errType =\n data.errorType === \"validation_error\" || data.errorType === \"api_error\"\n ? data.errorType\n : \"api_error\";\n reject(\n new ArcPayError({\n type: errType,\n code: data.code,\n message: data.message,\n retryable: false,\n paymentId,\n }),\n );\n }\n };\n\n window.addEventListener(\"message\", onMessage);\n cardNumber.send({ type: \"arcpay:tokenize\", paymentId, idempotencyKey });\n });\n }\n\n destroy(): void {\n for (const el of this.elementMap.values()) {\n el.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import {\n detectEnvironment,\n type Environment,\n validatePublishableKey as _validatePublishableKey,\n} from \"./env\";\nimport { showSandboxBanner } from \"./sandbox-banner\";\nimport { Elements, type ElementsOptions } from \"../elements/elements\";\n\nconst validatePublishableKey: (key: unknown) => asserts key is string = _validatePublishableKey;\n\nexport interface ArcPayLoadOptions {\n readonly _reserved?: never;\n}\n\nexport interface ArcPayInstance {\n readonly publishableKey: string;\n readonly environment: Environment;\n elements: (opts?: ElementsOptions) => Elements;\n}\n\nconst cache = new Map<string, Promise<ArcPayInstance>>();\n\nconst buildInstance = (publishableKey: string): ArcPayInstance => {\n if (detectEnvironment(publishableKey) === \"sandbox\") {\n showSandboxBanner();\n }\n return {\n publishableKey,\n environment: detectEnvironment(publishableKey),\n elements: () => new Elements({ publishableKey }),\n };\n};\n\nfunction load(publishableKey: string): Promise<ArcPayInstance> {\n try {\n validatePublishableKey(publishableKey);\n } catch (err) {\n return Promise.reject(err);\n }\n const key = publishableKey;\n const existing = cache.get(key);\n if (existing) return existing;\n const promise = Promise.resolve(buildInstance(publishableKey));\n cache.set(key, promise);\n return promise;\n}\n\nconst resetForTests = (): void => {\n cache.clear();\n};\n\nexport const ArcPay = {\n load,\n __resetForTests: resetForTests,\n};\n","import type { PaymentNextAction } from \"../server/types\";\nimport type { ExecutePaymentRequest } from \"../server/types\";\n\nexport type ThreeDSAction = PaymentNextAction;\nexport type BrowserInfo = ExecutePaymentRequest[\"browser_info\"];\n\nexport interface BrowserFormField {\n name: string;\n value: string;\n}\n\nexport interface BrowserPostForm {\n action: string;\n method: \"POST\";\n target: \"hidden_iframe\" | \"browser\";\n fields: BrowserFormField[];\n}\n\nexport interface ThreeDSBrowserStep {\n kind: \"method\" | \"challenge\";\n protocolVersion: \"1\" | \"2\";\n form: BrowserPostForm;\n completionEndpoint?: string;\n threeDSServerTransId?: string;\n}\n\nconst supportedColorDepths = [1, 4, 8, 15, 16, 24, 32, 48] as const;\n\nconst normalizeColorDepth = (value: number): BrowserInfo[\"color_depth\"] =>\n supportedColorDepths.includes(value as BrowserInfo[\"color_depth\"])\n ? (value as BrowserInfo[\"color_depth\"])\n : 24;\n\nconst resolveWindowSize = (width: number): NonNullable<BrowserInfo[\"window_size\"]> => {\n if (width >= 1000) return \"05\";\n if (width >= 600) return \"04\";\n if (width >= 500) return \"03\";\n if (width >= 390) return \"02\";\n return \"01\";\n};\n\nexport const collectBrowserInfo = (\n acceptHeader = \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\",\n): BrowserInfo => {\n if (\n typeof window === \"undefined\" ||\n typeof navigator === \"undefined\" ||\n typeof screen === \"undefined\"\n ) {\n throw new Error(\"collectBrowserInfo must be called in a browser environment\");\n }\n return {\n accept_header: acceptHeader,\n language: navigator.language || \"en\",\n screen_width: screen.width,\n screen_height: screen.height,\n color_depth: normalizeColorDepth(screen.colorDepth),\n timezone_offset_minutes: new Date().getTimezoneOffset(),\n java_enabled: false,\n user_agent: navigator.userAgent,\n window_size: resolveWindowSize(window.innerWidth || screen.width),\n };\n};\n\nexport const getThreeDSAction = (nextAction?: PaymentNextAction): PaymentNextAction | null => {\n return nextAction ?? null;\n};\n\nexport const isThreeDSMethodAction = (nextAction?: PaymentNextAction): boolean => {\n return nextAction?.type === \"three_ds_method\" && nextAction.three_ds.phase === \"method\";\n};\n\nexport const isThreeDSChallengeAction = (nextAction?: PaymentNextAction): boolean => {\n return nextAction?.type === \"three_ds_challenge\" && nextAction.three_ds.phase === \"challenge\";\n};\n\nexport const buildThreeDSBrowserForm = (nextAction: PaymentNextAction): BrowserPostForm => ({\n action: nextAction.three_ds.submit.url,\n method: nextAction.three_ds.submit.method,\n target: nextAction.three_ds.submit.target,\n fields: nextAction.three_ds.submit.fields,\n});\n\nexport const buildThreeDSBrowserStep = (\n nextAction?: PaymentNextAction,\n): ThreeDSBrowserStep | null => {\n const action = getThreeDSAction(nextAction);\n if (!action) return null;\n return {\n kind: action.three_ds.phase,\n protocolVersion: action.three_ds.version,\n form: buildThreeDSBrowserForm(action),\n completionEndpoint: action.three_ds.completion_endpoint,\n threeDSServerTransId: action.three_ds.three_ds_server_trans_id,\n };\n};\n\nexport const buildThreeDSMethodCompletion = (\n nextAction: PaymentNextAction,\n completionIndicator: \"Y\" | \"N\" | \"U\" = \"Y\",\n): { completion_indicator: \"Y\" | \"N\" | \"U\"; three_ds_server_trans_id: string } => {\n if (!isThreeDSMethodAction(nextAction) || !nextAction.three_ds.three_ds_server_trans_id) {\n throw new Error(\"nextAction must be a three_ds_method action with three_ds_server_trans_id\");\n }\n return {\n completion_indicator: completionIndicator,\n three_ds_server_trans_id: nextAction.three_ds.three_ds_server_trans_id,\n };\n};\n\nconst htmlEscape = (value: string): string =>\n value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n\nexport const buildThreeDSAutoSubmitHtml = (nextAction: PaymentNextAction): string => {\n const form = buildThreeDSBrowserForm(nextAction);\n const target = form.target === \"hidden_iframe\" ? \"arcpay-three-ds-method\" : \"_self\";\n const inputs = form.fields\n .map(\n (field) =>\n `<input type=\"hidden\" name=\"${htmlEscape(field.name)}\" value=\"${htmlEscape(field.value)}\">`,\n )\n .join(\"\");\n const iframe =\n form.target === \"hidden_iframe\"\n ? '<iframe name=\"arcpay-three-ds-method\" title=\"3-D Secure method\" hidden></iframe>'\n : \"\";\n return `<!doctype html><html><head><meta charset=\"utf-8\"></head><body>${iframe}<form method=\"POST\" action=\"${htmlEscape(form.action)}\" target=\"${target}\">${inputs}</form><script>document.forms[0].submit();</script></body></html>`;\n};\n","export { ArcPay } from \"./core/arcpay\";\nexport type { ArcPayInstance, ArcPayLoadOptions } from \"./core/arcpay\";\nexport {\n ArcPayError,\n isValidationError,\n isAuthenticationError,\n isAuthorizationError,\n isStateError,\n isRateLimitError,\n isApiError,\n isNetworkError,\n isChallengeAborted,\n} from \"./core/errors\";\nexport type { ArcPayErrorType } from \"./core/errors\";\nexport type { Environment } from \"./core/env\";\nexport type { TokenizeResult } from \"./tokenize/tokenize\";\nexport type { CardScheme } from \"./tokenize/scheme\";\nexport {\n buildThreeDSAutoSubmitHtml,\n buildThreeDSBrowserForm,\n buildThreeDSBrowserStep,\n buildThreeDSMethodCompletion,\n collectBrowserInfo,\n getThreeDSAction,\n isThreeDSChallengeAction,\n isThreeDSMethodAction,\n} from \"./three-ds\";\nexport type {\n BrowserFormField,\n BrowserInfo,\n BrowserPostForm,\n ThreeDSAction,\n ThreeDSBrowserStep,\n} from \"./three-ds\";\nexport const SDK_VERSION = \"0.1.12\";\n\nexport type { FieldType } from \"./elements/postmessage\";\nexport type { ElementOptions, ElementEvent } from \"./elements/element\";\nexport { Elements } from \"./elements/elements\";\nexport type { ElementsOptions } from \"./elements/elements\";\n"]}
package/dist/index.cjs CHANGED
@@ -470,6 +470,26 @@ var buildThreeDSBrowserForm = (nextAction) => ({
470
470
  target: nextAction.three_ds.submit.target,
471
471
  fields: nextAction.three_ds.submit.fields
472
472
  });
473
+ var buildThreeDSBrowserStep = (nextAction) => {
474
+ const action = getThreeDSAction(nextAction);
475
+ if (!action) return null;
476
+ return {
477
+ kind: action.three_ds.phase,
478
+ protocolVersion: action.three_ds.version,
479
+ form: buildThreeDSBrowserForm(action),
480
+ completionEndpoint: action.three_ds.completion_endpoint,
481
+ threeDSServerTransId: action.three_ds.three_ds_server_trans_id
482
+ };
483
+ };
484
+ var buildThreeDSMethodCompletion = (nextAction, completionIndicator = "Y") => {
485
+ if (!isThreeDSMethodAction(nextAction) || !nextAction.three_ds.three_ds_server_trans_id) {
486
+ throw new Error("nextAction must be a three_ds_method action with three_ds_server_trans_id");
487
+ }
488
+ return {
489
+ completion_indicator: completionIndicator,
490
+ three_ds_server_trans_id: nextAction.three_ds.three_ds_server_trans_id
491
+ };
492
+ };
473
493
  var htmlEscape = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
474
494
  var buildThreeDSAutoSubmitHtml = (nextAction) => {
475
495
  const form = buildThreeDSBrowserForm(nextAction);
@@ -482,7 +502,7 @@ var buildThreeDSAutoSubmitHtml = (nextAction) => {
482
502
  };
483
503
 
484
504
  // src/index.ts
485
- var SDK_VERSION = "0.1.11";
505
+ var SDK_VERSION = "0.1.12";
486
506
 
487
507
  exports.ArcPay = ArcPay;
488
508
  exports.ArcPayError = ArcPayError;
@@ -490,6 +510,8 @@ exports.Elements = Elements;
490
510
  exports.SDK_VERSION = SDK_VERSION;
491
511
  exports.buildThreeDSAutoSubmitHtml = buildThreeDSAutoSubmitHtml;
492
512
  exports.buildThreeDSBrowserForm = buildThreeDSBrowserForm;
513
+ exports.buildThreeDSBrowserStep = buildThreeDSBrowserStep;
514
+ exports.buildThreeDSMethodCompletion = buildThreeDSMethodCompletion;
493
515
  exports.collectBrowserInfo = collectBrowserInfo;
494
516
  exports.getThreeDSAction = getThreeDSAction;
495
517
  exports.isApiError = isApiError;