@thavguard/arc-pay 0.1.22 → 0.1.24
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 +52 -0
- package/dist/{arcpay-DIPpoeDw.d.cts → arcpay-OKf8cplO.d.cts} +37 -5
- package/dist/{arcpay-DIPpoeDw.d.ts → arcpay-OKf8cplO.d.ts} +37 -5
- package/dist/cdn/arcpay.global.js +2 -2
- package/dist/cdn/arcpay.global.js.map +1 -1
- package/dist/index.cjs +124 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +124 -21
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.cjs +124 -21
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.mjs +124 -21
- package/dist/react/index.mjs.map +1 -1
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -54,6 +54,58 @@ with `Authorization: Bearer <pk_...>`, `Content-Type`, optional
|
|
|
54
54
|
may use either `Authorization: Bearer <pk_...>` or `X-Api-Key: pk_...` for
|
|
55
55
|
`/payments/{id}/tokenize`.
|
|
56
56
|
|
|
57
|
+
### Hosted Fields appearance
|
|
58
|
+
|
|
59
|
+
Hosted Fields are secure iframe inputs. The merchant page owns layout and
|
|
60
|
+
container styling: labels, wrappers, spacing, borders, shadows, error text, and
|
|
61
|
+
the submit button should be regular merchant CSS. Arc Pay only styles the input
|
|
62
|
+
text inside each iframe through a typed, allowlisted `appearance` contract.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const elements = arcpay.elements({
|
|
66
|
+
appearance: {
|
|
67
|
+
variables: {
|
|
68
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
69
|
+
fontSize: "16px",
|
|
70
|
+
lineHeight: "24px",
|
|
71
|
+
colorText: "#111827",
|
|
72
|
+
colorPlaceholder: "#9ca3af",
|
|
73
|
+
colorDanger: "#dc2626",
|
|
74
|
+
caretColor: "#111827",
|
|
75
|
+
},
|
|
76
|
+
rules: {
|
|
77
|
+
focus: { "font-weight": "600" },
|
|
78
|
+
invalid: { color: "#dc2626" },
|
|
79
|
+
complete: { color: "#047857" },
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const number = elements.create("cardNumber", {
|
|
85
|
+
placeholder: "1234 1234 1234 1234",
|
|
86
|
+
});
|
|
87
|
+
const expiry = elements.create("cardExpiry");
|
|
88
|
+
const cvc = elements.create("cardCvv", {
|
|
89
|
+
appearance: {
|
|
90
|
+
rules: {
|
|
91
|
+
base: { "text-align": "center" },
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
number.mount("#card-number");
|
|
97
|
+
expiry.mount("#card-expiry");
|
|
98
|
+
cvc.mount("#card-cvv");
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`appearance.theme` defaults to `"none"` so Arc Pay branding is not imposed on
|
|
102
|
+
merchant checkout pages. `theme: "arcpay"` is available for demos and quick
|
|
103
|
+
starts. Supported iframe properties are limited to text, color, caret,
|
|
104
|
+
placeholder, opacity, and `background-color`; container CSS such as border,
|
|
105
|
+
padding, margin, shadow, position, transform, and z-index is intentionally
|
|
106
|
+
dropped. Use element `change` events (`isEmpty`, `isComplete`, `isValid`,
|
|
107
|
+
`brand`, `lastFour`) to style your own wrappers.
|
|
108
|
+
|
|
57
109
|
`@thavguard/arc-pay/server` intentionally does not expose `tokenizeCard()`.
|
|
58
110
|
Tokenization belongs to Hosted Fields. Direct browser calls with a publishable
|
|
59
111
|
key are only for explicitly approved raw-card forms; those forms handle
|
|
@@ -26,11 +26,36 @@ interface StyleSubset {
|
|
|
26
26
|
base: Record<string, string>;
|
|
27
27
|
invalid?: Record<string, string>;
|
|
28
28
|
focus?: Record<string, string>;
|
|
29
|
+
complete?: Record<string, string>;
|
|
30
|
+
empty?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type HostedFieldsTheme = "none" | "arcpay";
|
|
34
|
+
interface HostedFieldsAppearanceVariables {
|
|
35
|
+
fontFamily?: string;
|
|
36
|
+
fontSize?: string;
|
|
37
|
+
fontWeight?: string;
|
|
38
|
+
fontStyle?: string;
|
|
39
|
+
lineHeight?: string;
|
|
40
|
+
letterSpacing?: string;
|
|
41
|
+
textAlign?: string;
|
|
42
|
+
colorText?: string;
|
|
43
|
+
colorPlaceholder?: string;
|
|
44
|
+
colorDanger?: string;
|
|
45
|
+
colorSuccess?: string;
|
|
46
|
+
colorBackground?: string;
|
|
47
|
+
caretColor?: string;
|
|
48
|
+
}
|
|
49
|
+
type HostedFieldsAppearanceRule = "base" | "focus" | "invalid" | "complete" | "empty";
|
|
50
|
+
interface HostedFieldsAppearance {
|
|
51
|
+
theme?: HostedFieldsTheme;
|
|
52
|
+
variables?: HostedFieldsAppearanceVariables;
|
|
53
|
+
rules?: Partial<Record<HostedFieldsAppearanceRule, Record<string, string>>>;
|
|
29
54
|
}
|
|
30
55
|
|
|
31
56
|
interface ElementOptions {
|
|
32
|
-
/**
|
|
33
|
-
|
|
57
|
+
/** Iframe-safe input appearance. Container layout remains merchant-owned CSS. */
|
|
58
|
+
appearance?: HostedFieldsAppearance;
|
|
34
59
|
placeholder?: string;
|
|
35
60
|
}
|
|
36
61
|
type ElementEvent = {
|
|
@@ -38,6 +63,8 @@ type ElementEvent = {
|
|
|
38
63
|
} | {
|
|
39
64
|
type: "change";
|
|
40
65
|
isValid: boolean;
|
|
66
|
+
isEmpty: boolean;
|
|
67
|
+
isComplete: boolean;
|
|
41
68
|
brand?: string;
|
|
42
69
|
lastFour?: string;
|
|
43
70
|
} | {
|
|
@@ -63,7 +90,7 @@ declare class Element {
|
|
|
63
90
|
mount(target: string | HTMLElement): void;
|
|
64
91
|
private handleMessage;
|
|
65
92
|
update(options: {
|
|
66
|
-
|
|
93
|
+
appearance?: HostedFieldsAppearance;
|
|
67
94
|
placeholder?: string;
|
|
68
95
|
}): void;
|
|
69
96
|
destroy(): void;
|
|
@@ -91,16 +118,21 @@ interface TokenizeResult {
|
|
|
91
118
|
expiresAt: string;
|
|
92
119
|
}
|
|
93
120
|
|
|
94
|
-
|
|
121
|
+
interface ElementsOptions {
|
|
122
|
+
/** Default iframe-safe input appearance applied to elements created by this factory. */
|
|
123
|
+
appearance?: HostedFieldsAppearance;
|
|
124
|
+
}
|
|
95
125
|
declare class Elements {
|
|
96
126
|
private readonly elementMap;
|
|
97
127
|
private readonly iframeBase;
|
|
98
128
|
private readonly publishableKey;
|
|
99
129
|
private readonly channelId;
|
|
100
130
|
private tokenizeInFlight;
|
|
131
|
+
private readonly appearance?;
|
|
101
132
|
constructor(opts: {
|
|
102
133
|
publishableKey: string;
|
|
103
134
|
iframeBase?: string;
|
|
135
|
+
appearance?: HostedFieldsAppearance;
|
|
104
136
|
});
|
|
105
137
|
create(field: FieldType, options?: ElementOptions): Element;
|
|
106
138
|
tokenize(paymentId: string, idempotencyKey: string): Promise<TokenizeResult>;
|
|
@@ -122,4 +154,4 @@ declare const ArcPay: {
|
|
|
122
154
|
__resetForTests: () => void;
|
|
123
155
|
};
|
|
124
156
|
|
|
125
|
-
export { ArcPay as A, type ElementEvent as E, type FieldType as F, type TokenizeResult as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementOptions as c, Elements as d, type ElementsOptions as e, type Environment as f };
|
|
157
|
+
export { ArcPay as A, type ElementEvent as E, type FieldType as F, type HostedFieldsAppearance as H, type TokenizeResult as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementOptions as c, Elements as d, type ElementsOptions as e, type Environment as f, type HostedFieldsAppearanceRule as g, type HostedFieldsAppearanceVariables as h, type HostedFieldsTheme as i };
|
|
@@ -26,11 +26,36 @@ interface StyleSubset {
|
|
|
26
26
|
base: Record<string, string>;
|
|
27
27
|
invalid?: Record<string, string>;
|
|
28
28
|
focus?: Record<string, string>;
|
|
29
|
+
complete?: Record<string, string>;
|
|
30
|
+
empty?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type HostedFieldsTheme = "none" | "arcpay";
|
|
34
|
+
interface HostedFieldsAppearanceVariables {
|
|
35
|
+
fontFamily?: string;
|
|
36
|
+
fontSize?: string;
|
|
37
|
+
fontWeight?: string;
|
|
38
|
+
fontStyle?: string;
|
|
39
|
+
lineHeight?: string;
|
|
40
|
+
letterSpacing?: string;
|
|
41
|
+
textAlign?: string;
|
|
42
|
+
colorText?: string;
|
|
43
|
+
colorPlaceholder?: string;
|
|
44
|
+
colorDanger?: string;
|
|
45
|
+
colorSuccess?: string;
|
|
46
|
+
colorBackground?: string;
|
|
47
|
+
caretColor?: string;
|
|
48
|
+
}
|
|
49
|
+
type HostedFieldsAppearanceRule = "base" | "focus" | "invalid" | "complete" | "empty";
|
|
50
|
+
interface HostedFieldsAppearance {
|
|
51
|
+
theme?: HostedFieldsTheme;
|
|
52
|
+
variables?: HostedFieldsAppearanceVariables;
|
|
53
|
+
rules?: Partial<Record<HostedFieldsAppearanceRule, Record<string, string>>>;
|
|
29
54
|
}
|
|
30
55
|
|
|
31
56
|
interface ElementOptions {
|
|
32
|
-
/**
|
|
33
|
-
|
|
57
|
+
/** Iframe-safe input appearance. Container layout remains merchant-owned CSS. */
|
|
58
|
+
appearance?: HostedFieldsAppearance;
|
|
34
59
|
placeholder?: string;
|
|
35
60
|
}
|
|
36
61
|
type ElementEvent = {
|
|
@@ -38,6 +63,8 @@ type ElementEvent = {
|
|
|
38
63
|
} | {
|
|
39
64
|
type: "change";
|
|
40
65
|
isValid: boolean;
|
|
66
|
+
isEmpty: boolean;
|
|
67
|
+
isComplete: boolean;
|
|
41
68
|
brand?: string;
|
|
42
69
|
lastFour?: string;
|
|
43
70
|
} | {
|
|
@@ -63,7 +90,7 @@ declare class Element {
|
|
|
63
90
|
mount(target: string | HTMLElement): void;
|
|
64
91
|
private handleMessage;
|
|
65
92
|
update(options: {
|
|
66
|
-
|
|
93
|
+
appearance?: HostedFieldsAppearance;
|
|
67
94
|
placeholder?: string;
|
|
68
95
|
}): void;
|
|
69
96
|
destroy(): void;
|
|
@@ -91,16 +118,21 @@ interface TokenizeResult {
|
|
|
91
118
|
expiresAt: string;
|
|
92
119
|
}
|
|
93
120
|
|
|
94
|
-
|
|
121
|
+
interface ElementsOptions {
|
|
122
|
+
/** Default iframe-safe input appearance applied to elements created by this factory. */
|
|
123
|
+
appearance?: HostedFieldsAppearance;
|
|
124
|
+
}
|
|
95
125
|
declare class Elements {
|
|
96
126
|
private readonly elementMap;
|
|
97
127
|
private readonly iframeBase;
|
|
98
128
|
private readonly publishableKey;
|
|
99
129
|
private readonly channelId;
|
|
100
130
|
private tokenizeInFlight;
|
|
131
|
+
private readonly appearance?;
|
|
101
132
|
constructor(opts: {
|
|
102
133
|
publishableKey: string;
|
|
103
134
|
iframeBase?: string;
|
|
135
|
+
appearance?: HostedFieldsAppearance;
|
|
104
136
|
});
|
|
105
137
|
create(field: FieldType, options?: ElementOptions): Element;
|
|
106
138
|
tokenize(paymentId: string, idempotencyKey: string): Promise<TokenizeResult>;
|
|
@@ -122,4 +154,4 @@ declare const ArcPay: {
|
|
|
122
154
|
__resetForTests: () => void;
|
|
123
155
|
};
|
|
124
156
|
|
|
125
|
-
export { ArcPay as A, type ElementEvent as E, type FieldType as F, type TokenizeResult as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementOptions as c, Elements as d, type ElementsOptions as e, type Environment as f };
|
|
157
|
+
export { ArcPay as A, type ElementEvent as E, type FieldType as F, type HostedFieldsAppearance as H, type TokenizeResult as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementOptions as c, Elements as d, type ElementsOptions as e, type Environment as f, type HostedFieldsAppearanceRule as g, type HostedFieldsAppearanceVariables as h, type HostedFieldsTheme as i };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var ArcPay=(function(exports){'use strict';var s=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;}},L=e=>e instanceof s&&e.type==="validation_error";var C=e=>e instanceof s&&e.type==="authentication_error",O=e=>e instanceof s&&e.type==="authorization_error",N=e=>e instanceof s&&e.type==="state_error",H=e=>e instanceof s&&e.type==="rate_limit_error",U=e=>e instanceof s&&e.type==="api_error",W=e=>e instanceof s&&e.type==="network_error",$=e=>e instanceof s&&e.type==="challenge_aborted";var T=e=>e.startsWith("pk_test_")?"sandbox":"live",D=e=>{if(typeof e!="string"||e.length===0)throw new s({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 s({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 k="data-arcpay-sandbox-banner",A=()=>{if(typeof document=="undefined"||document.querySelector(`[${k}]`))return;let e=document.createElement("div");e.setAttribute(k,""),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:",q=e=>typeof e=="object"&&e!==null&&"type"in e&&typeof e.type=="string"&&e.type.startsWith(K),E=(e,t,r)=>{if(r==="*")throw new s({type:"validation_error",code:"wildcard_origin_forbidden",message:"postToIframe: targetOrigin cannot be '*'",retryable:false});if(!e.contentWindow)throw new s({type:"validation_error",code:"iframe_not_loaded",message:"postToIframe: iframe.contentWindow is null (iframe not mounted)",retryable:false});e.contentWindow.postMessage(t,r);};var f=(e,t)=>e.origin!==t||!q(e.data)?null:e.data;var V=new Set(["position","transform","pointer-events","pointerevents","z-index","zindex","top","left","right","bottom","inset"]),v=e=>{let t={};for(let[r,o]of Object.entries(e)){let i=r.toLowerCase();V.has(i)||(t[r]=o);}return t},S=e=>{let t={base:v(e.base)};return e.invalid!==void 0&&(t.invalid=v(e.invalid)),e.focus!==void 0&&(t.focus=v(e.focus)),t};var g=class{constructor(t,r,o){this.field=t;this.options=r;this.context=o;this.iframe=null;this.listeners={ready:new Set,change:new Set,error:new Set};this.status="pending";this.messageHandler=null;}mount(t){if(this.iframe)throw new s({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 s({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 i=new URL(this.context.iframeBase).origin;this.messageHandler=n=>{var l;if(n.source!==((l=this.iframe)==null?void 0:l.contentWindow))return;let d=f(n,i);d&&this.handleMessage(d);},window.addEventListener("message",this.messageHandler),o.addEventListener("load",()=>{if(!this.iframe)return;let n={type:"arcpay:hello",origin:window.location.origin,publishableKey:this.context.publishableKey,channelId:this.context.channelId};E(this.iframe,n,i);},{once:true});}handleMessage(t){t.type==="arcpay:ready"?(this.status="ready",this.options.style&&this.send({type:"arcpay:style",payload:S(this.options.style)}),this.options.placeholder&&this.send({type:"arcpay:placeholder",field:this.field,placeholder:this.options.placeholder}),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:S(t.style)}),t.placeholder&&this.send({type:"arcpay:placeholder",field:this.field,placeholder:t.placeholder});}destroy(){this.iframe&&(this.iframe.remove(),this.iframe=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null);for(let t of Object.values(this.listeners))t.clear();this.status="pending";}on(t,r){return this.listeners[t].add(r),()=>this.listeners[t].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 s({type:"validation_error",code:"not_mounted",message:`Element ${this.field} is not mounted`,retryable:false});E(this.iframe,t,new URL(this.context.iframeBase).origin);}emit(t){for(let r of this.listeners[t.type])r(t);}};var Y="https://sdk.arcpay.space",j=()=>{var e;if(!((e=globalThis.crypto)!=null&&e.randomUUID))throw new s({type:"validation_error",code:"crypto_unavailable",message:"crypto.randomUUID is required for Hosted Fields",retryable:false});return globalThis.crypto.randomUUID()},h=class{constructor(t){this.elementMap=new Map;this.tokenizeInFlight=false;var r;this.publishableKey=t.publishableKey,this.iframeBase=(r=t.iframeBase)!=null?r:Y,this.channelId=j();}create(t,r={}){if(this.elementMap.has(t))throw new s({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},i=new g(t,r,o);return this.elementMap.set(t,i),i}async tokenize(t,r){if(this.tokenizeInFlight)throw new s({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"),i=this.elementMap.get("cardExpiry"),n=this.elementMap.get("cardCvv");if(!o||!i||!n)throw new s({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()||!i.isReady()||!n.isReady())throw new s({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 i=new URL(this.iframeBase).origin,n=t.getIframeContentWindow();return new Promise((d,l)=>{let p=window.setTimeout(()=>{window.removeEventListener("message",c),l(new s({type:"network_error",code:"tokenize_timeout",message:"tokenize() timed out after 30 seconds",retryable:true,paymentId:r}));},3e4),c=m=>{if(n!==null&&m.source!==n)return;let a=f(m,i);a&&(a.type==="arcpay:tokenize-result"?(clearTimeout(p),window.removeEventListener("message",c),d({cardTokenId:a.cardTokenId,cardMask:a.cardMask,cardScheme:a.cardScheme,cardBin:a.cardBin,expiresIn:a.expiresIn,expiresAt:a.expiresAt})):a.type==="arcpay:tokenize-error"&&(clearTimeout(p),window.removeEventListener("message",c),l(new s({type:a.errorType==="validation_error"||a.errorType==="configuration_error"||a.errorType==="network_error"||a.errorType==="api_error"?a.errorType:"api_error",code:a.code,message:a.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 X=D,x=new Map,G=e=>(T(e)==="sandbox"&&A(),{publishableKey:e,environment:T(e),elements:()=>new h({publishableKey:e})});function J(e){try{X(e);}catch(i){return Promise.reject(i)}let t=e,r=x.get(t);if(r)return r;let o=Promise.resolve(G(e));return x.set(t,o),o}var Q=()=>{x.clear();},Z={load:J,__resetForTests:Q};var ee=[1,4,8,15,16,24,32,48],te=e=>ee.includes(e)?e:24,re=e=>e>=1e3?"05":e>=600?"04":e>=500?"03":e>=390?"02":"01",F=(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:te(screen.colorDepth),timezone_offset_minutes:new Date().getTimezoneOffset(),java_enabled:false,user_agent:navigator.userAgent,window_size:re(window.innerWidth||screen.width)}},b=e=>e!=null?e:null,_=e=>(e==null?void 0:e.type)==="three_ds_method"&&e.three_ds.phase==="method",w=e=>(e==null?void 0:e.type)==="three_ds_challenge"&&e.three_ds.phase==="challenge",y=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;try{t=new URL(e);}catch(r){throw new Error("3DS form action must be an absolute HTTPS URL")}if(t.protocol!=="https:")throw new Error("3DS form action must use HTTPS")},M=e=>{let t=b(e);return t?{kind:t.three_ds.phase,protocolVersion:t.three_ds.version,form:y(t),completionEndpoint:t.three_ds.completion_endpoint,threeDSServerTransId:t.three_ds.three_ds_server_trans_id}:null},I=(e,t="Y")=>{if(!_(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}},oe=e=>{if(e)return e;if(typeof document=="undefined")throw new Error("3DS browser helpers must be called in a browser environment");return document},ne=e=>{e.submit();},u=(e,t={})=>{var p,c;let r=oe(t.document),o=(p=t.container)!=null?p:r.body,i=y(e);B(i.action);let n=r.createElement("form"),d=i.target==="hidden_iframe"?`arcpay-three-ds-method-${crypto.randomUUID()}`:(c=t.challengeTarget)!=null?c:"_self",l;n.method=i.method,n.action=i.action,n.target=d,n.hidden=true;for(let m of i.fields){let a=r.createElement("input");a.type="hidden",a.name=m.name,a.value=m.value,n.append(a);}return i.target==="hidden_iframe"&&(l=r.createElement("iframe"),l.name=d,l.title="3-D Secure method",l.hidden=true,o.append(l)),o.append(n),{form:n,iframe:l,submit:()=>{var m;return ((m=t.submitter)!=null?m:ne)(n)},remove:()=>{n.remove(),l==null||l.remove();}}},se=(e,t,r)=>new Promise((o,i)=>{if(!e.iframe){o("loaded");return}if(r!=null&&r.aborted){i(new DOMException("The operation was aborted","AbortError"));return}let n=false,d=()=>{var a;(a=e.iframe)==null||a.removeEventListener("load",p),r==null||r.removeEventListener("abort",c),clearTimeout(m);},l=a=>{n||(n=true,d(),o(a));},p=()=>l("loaded"),c=()=>{n||(n=true,d(),i(new DOMException("The operation was aborted","AbortError")));},m=setTimeout(()=>l("timeout"),t);e.iframe.addEventListener("load",p,{once:true}),r==null||r.addEventListener("abort",c,{once:true});}),R=async(e,t)=>{var i,n;if(!e)return {status:"no_action"};if(w(e)){let d=u(e,t);return d.submit(),{status:"challenge_submitted",action:e,mounted:d}}if(!_(e))return {status:"no_action"};let r=t.completeThreeDSMethod;if(!r)throw new Error("completeThreeDSMethod is required for 3DS Method actions");let o=u(e,t);try{o.submit();let d=await se(o,(i=t.methodTimeoutMs)!=null?i:1e4,t.signal),l=(n=t.methodCompletionIndicator)!=null?n:d==="loaded"?"Y":"N",p=await r(I(e,l),e),c=b(p.next_action);if(c&&w(c)){let m=u(c,t);return m.submit(),{status:"challenge_submitted",action:c,response:p,mounted:m,methodResult:d}}return {status:"method_completed",response:p,methodResult:d}}finally{o.remove();}},P=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),z=e=>{let t=y(e);B(t.action);let r=t.target==="hidden_iframe"?"arcpay-three-ds-method":"_self",o=t.fields.map(n=>`<input type="hidden" name="${P(n.name)}" value="${P(n.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="${P(t.action)}" target="${r}">${o}</form><script>document.forms[0].submit();</script></body></html>`};var De="0.1.22";
|
|
2
|
-
exports.ArcPay=
|
|
1
|
+
var ArcPay=(function(exports){'use strict';var i=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;}},O=e=>e instanceof i&&e.type==="validation_error";var N=e=>e instanceof i&&e.type==="authentication_error",U=e=>e instanceof i&&e.type==="authorization_error",W=e=>e instanceof i&&e.type==="state_error",$=e=>e instanceof i&&e.type==="rate_limit_error",K=e=>e instanceof i&&e.type==="api_error",q=e=>e instanceof i&&e.type==="network_error",V=e=>e instanceof i&&e.type==="challenge_aborted";var S=e=>e.startsWith("pk_test_")?"sandbox":"live",D=e=>{if(typeof e!="string"||e.length===0)throw new i({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 i({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 k="data-arcpay-sandbox-banner",B=()=>{if(typeof document=="undefined"||document.querySelector(`[${k}]`))return;let e=document.createElement("div");e.setAttribute(k,""),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 Y="arcpay:",j=e=>typeof e=="object"&&e!==null&&"type"in e&&typeof e.type=="string"&&e.type.startsWith(Y),x=(e,t,r)=>{if(r==="*")throw new i({type:"validation_error",code:"wildcard_origin_forbidden",message:"postToIframe: targetOrigin cannot be '*'",retryable:false});if(!e.contentWindow)throw new i({type:"validation_error",code:"iframe_not_loaded",message:"postToIframe: iframe.contentWindow is null (iframe not mounted)",retryable:false});e.contentWindow.postMessage(t,r);};var w=(e,t)=>e.origin!==t||!j(e.data)?null:e.data;var X=new Set(["--arcpay-placeholder-color","background-color","caret-color","color","font-family","font-size","font-style","font-weight","letter-spacing","line-height","opacity","text-align","text-decoration","text-transform"]),G={base:{"font-family":'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',"font-size":"16px","line-height":"24px",color:"#111827","--arcpay-placeholder-color":"#9ca3af","caret-color":"#111827"},focus:{color:"#111827"},invalid:{color:"#dc2626"},complete:{color:"#111827"},empty:{color:"#111827"}},u=(e,t)=>{if(!(!e&&!t))return {...e!=null?e:{},...t!=null?t:{}}},y=(e,t,r)=>{r!==void 0&&(e[t]=r);},h=e=>{let t={};for(let[r,o]of Object.entries(e)){let n=r.toLowerCase();X.has(n)&&(t[n]=o);}return t},J=e=>{let t={base:h(e.base)};return e.invalid!==void 0&&(t.invalid=h(e.invalid)),e.focus!==void 0&&(t.focus=h(e.focus)),e.complete!==void 0&&(t.complete=h(e.complete)),e.empty!==void 0&&(t.empty=h(e.empty)),t},P=e=>{var p;let t=(e==null?void 0:e.theme)==="arcpay"?G:{base:{}},r={base:{}},o=e==null?void 0:e.variables;o&&(y(r.base,"font-family",o.fontFamily),y(r.base,"font-size",o.fontSize),y(r.base,"font-weight",o.fontWeight),y(r.base,"font-style",o.fontStyle),y(r.base,"line-height",o.lineHeight),y(r.base,"letter-spacing",o.letterSpacing),y(r.base,"text-align",o.textAlign),y(r.base,"color",o.colorText),y(r.base,"--arcpay-placeholder-color",o.colorPlaceholder),y(r.base,"background-color",o.colorBackground),y(r.base,"caret-color",o.caretColor),o.colorDanger!==void 0&&(r.invalid={color:o.colorDanger}),o.colorSuccess!==void 0&&(r.complete={color:o.colorSuccess}));let n=e==null?void 0:e.rules,s={base:{...t.base,...r.base,...(p=n==null?void 0:n.base)!=null?p:{}}},d=u(u(t.focus,r.focus),n==null?void 0:n.focus),l=u(u(t.invalid,r.invalid),n==null?void 0:n.invalid),m=u(u(t.complete,r.complete),n==null?void 0:n.complete),c=u(u(t.empty,r.empty),n==null?void 0:n.empty);return d!==void 0&&(s.focus=d),l!==void 0&&(s.invalid=l),m!==void 0&&(s.complete=m),c!==void 0&&(s.empty=c),J(s)};var M={cardNumber:"Arc Pay card number",cardExpiry:"Arc Pay card expiration date",cardCvv:"Arc Pay card security code"},T=class{constructor(t,r,o){this.field=t;this.options=r;this.context=o;this.iframe=null;this.listeners={ready:new Set,change:new Set,error:new Set};this.status="pending";this.messageHandler=null;}mount(t){if(this.iframe)throw new i({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 i({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),o.setAttribute("title",M[this.field]),o.setAttribute("aria-label",M[this.field]),r.appendChild(o),this.iframe=o;let n=new URL(this.context.iframeBase).origin;this.messageHandler=s=>{var l;if(s.source!==((l=this.iframe)==null?void 0:l.contentWindow))return;let d=w(s,n);d&&this.handleMessage(d);},window.addEventListener("message",this.messageHandler),o.addEventListener("load",()=>{if(!this.iframe)return;let s={type:"arcpay:hello",origin:window.location.origin,publishableKey:this.context.publishableKey,channelId:this.context.channelId};x(this.iframe,s,n);},{once:true});}handleMessage(t){t.type==="arcpay:ready"?(this.status="ready",this.options.appearance&&this.send({type:"arcpay:style",payload:P(this.options.appearance)}),this.options.placeholder&&this.send({type:"arcpay:placeholder",field:this.field,placeholder:this.options.placeholder}),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,isEmpty:t.isEmpty,isComplete:t.isComplete,brand:t.brand,lastFour:t.lastFour});}update(t){t.appearance&&this.send({type:"arcpay:style",payload:P(t.appearance)}),t.placeholder&&this.send({type:"arcpay:placeholder",field:this.field,placeholder:t.placeholder});}destroy(){this.iframe&&(this.iframe.remove(),this.iframe=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null);for(let t of Object.values(this.listeners))t.clear();this.status="pending";}on(t,r){return this.listeners[t].add(r),()=>this.listeners[t].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 i({type:"validation_error",code:"not_mounted",message:`Element ${this.field} is not mounted`,retryable:false});x(this.iframe,t,new URL(this.context.iframeBase).origin);}emit(t){for(let r of this.listeners[t.type])r(t);}};var Q="https://sdk.arcpay.space",Z=()=>{var e;if(!((e=globalThis.crypto)!=null&&e.randomUUID))throw new i({type:"validation_error",code:"crypto_unavailable",message:"crypto.randomUUID is required for Hosted Fields",retryable:false});return globalThis.crypto.randomUUID()},f=class{constructor(t){this.elementMap=new Map;this.tokenizeInFlight=false;var r;this.publishableKey=t.publishableKey,this.iframeBase=(r=t.iframeBase)!=null?r:Q,this.channelId=Z(),this.appearance=t.appearance;}create(t,r={}){var s;if(this.elementMap.has(t))throw new i({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},n=new T(t,{...r,appearance:(s=r.appearance)!=null?s:this.appearance},o);return this.elementMap.set(t,n),n}async tokenize(t,r){if(this.tokenizeInFlight)throw new i({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"),n=this.elementMap.get("cardExpiry"),s=this.elementMap.get("cardCvv");if(!o||!n||!s)throw new i({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()||!n.isReady()||!s.isReady())throw new i({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 n=new URL(this.iframeBase).origin,s=t.getIframeContentWindow();return new Promise((d,l)=>{let m=window.setTimeout(()=>{window.removeEventListener("message",c),l(new i({type:"network_error",code:"tokenize_timeout",message:"tokenize() timed out after 30 seconds",retryable:true,paymentId:r}));},3e4),c=p=>{if(s!==null&&p.source!==s)return;let a=w(p,n);a&&(a.type==="arcpay:tokenize-result"?(clearTimeout(m),window.removeEventListener("message",c),d({cardTokenId:a.cardTokenId,cardMask:a.cardMask,cardScheme:a.cardScheme,cardBin:a.cardBin,expiresIn:a.expiresIn,expiresAt:a.expiresAt})):a.type==="arcpay:tokenize-error"&&(clearTimeout(m),window.removeEventListener("message",c),l(new i({type:a.errorType==="validation_error"||a.errorType==="configuration_error"||a.errorType==="network_error"||a.errorType==="api_error"?a.errorType:"api_error",code:a.code,message:a.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 ee=D,A=new Map,te=e=>(S(e)==="sandbox"&&B(),{publishableKey:e,environment:S(e),elements:(t={})=>new f({publishableKey:e,...t})});function re(e){try{ee(e);}catch(n){return Promise.reject(n)}let t=e,r=A.get(t);if(r)return r;let o=Promise.resolve(te(e));return A.set(t,o),o}var oe=()=>{A.clear();},ne={load:re,__resetForTests:oe};var se=[1,4,8,15,16,24,32,48],ie=e=>se.includes(e)?e:24,ae=e=>e>=1e3?"05":e>=600?"04":e>=500?"03":e>=390?"02":"01",R=(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:ie(screen.colorDepth),timezone_offset_minutes:new Date().getTimezoneOffset(),java_enabled:false,user_agent:navigator.userAgent,window_size:ae(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",_=e=>(e==null?void 0:e.type)==="three_ds_challenge"&&e.three_ds.phase==="challenge",b=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}),z=e=>{let t;try{t=new URL(e);}catch(r){throw new Error("3DS form action must be an absolute HTTPS URL")}if(t.protocol!=="https:")throw new Error("3DS form action must use HTTPS")},C=e=>{let t=v(e);return t?{kind:t.three_ds.phase,protocolVersion:t.three_ds.version,form:b(t),completionEndpoint:t.three_ds.completion_endpoint,threeDSServerTransId:t.three_ds.three_ds_server_trans_id}:null},I=(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}},le=e=>{if(e)return e;if(typeof document=="undefined")throw new Error("3DS browser helpers must be called in a browser environment");return document},de=e=>{e.submit();},g=(e,t={})=>{var m,c;let r=le(t.document),o=(m=t.container)!=null?m:r.body,n=b(e);z(n.action);let s=r.createElement("form"),d=n.target==="hidden_iframe"?`arcpay-three-ds-method-${crypto.randomUUID()}`:(c=t.challengeTarget)!=null?c:"_self",l;s.method=n.method,s.action=n.action,s.target=d,s.hidden=true;for(let p of n.fields){let a=r.createElement("input");a.type="hidden",a.name=p.name,a.value=p.value,s.append(a);}return n.target==="hidden_iframe"&&(l=r.createElement("iframe"),l.name=d,l.title="3-D Secure method",l.hidden=true,o.append(l)),o.append(s),{form:s,iframe:l,submit:()=>{var p;return ((p=t.submitter)!=null?p:de)(s)},remove:()=>{s.remove(),l==null||l.remove();}}},ce=(e,t,r)=>new Promise((o,n)=>{if(!e.iframe){o("loaded");return}if(r!=null&&r.aborted){n(new DOMException("The operation was aborted","AbortError"));return}let s=false,d=()=>{var a;(a=e.iframe)==null||a.removeEventListener("load",m),r==null||r.removeEventListener("abort",c),clearTimeout(p);},l=a=>{s||(s=true,d(),o(a));},m=()=>l("loaded"),c=()=>{s||(s=true,d(),n(new DOMException("The operation was aborted","AbortError")));},p=setTimeout(()=>l("timeout"),t);e.iframe.addEventListener("load",m,{once:true}),r==null||r.addEventListener("abort",c,{once:true});}),L=async(e,t)=>{var n,s;if(!e)return {status:"no_action"};if(_(e)){let d=g(e,t);return d.submit(),{status:"challenge_submitted",action:e,mounted:d}}if(!E(e))return {status:"no_action"};let r=t.completeThreeDSMethod;if(!r)throw new Error("completeThreeDSMethod is required for 3DS Method actions");let o=g(e,t);try{o.submit();let d=await ce(o,(n=t.methodTimeoutMs)!=null?n:1e4,t.signal),l=(s=t.methodCompletionIndicator)!=null?s:d==="loaded"?"Y":"N",m=await r(I(e,l),e),c=v(m.next_action);if(c&&_(c)){let p=g(c,t);return p.submit(),{status:"challenge_submitted",action:c,response:m,mounted:p,methodResult:d}}return {status:"method_completed",response:m,methodResult:d}}finally{o.remove();}},F=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),H=e=>{let t=b(e);z(t.action);let r=t.target==="hidden_iframe"?"arcpay-three-ds-method":"_self",o=t.fields.map(s=>`<input type="hidden" name="${F(s.name)}" value="${F(s.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="${F(t.action)}" target="${r}">${o}</form><script>document.forms[0].submit();</script></body></html>`};var Me="0.1.24";
|
|
2
|
+
exports.ArcPay=ne;exports.ArcPayError=i;exports.Elements=f;exports.SDK_VERSION=Me;exports.buildThreeDSAutoSubmitHtml=H;exports.buildThreeDSBrowserForm=b;exports.buildThreeDSBrowserStep=C;exports.buildThreeDSMethodCompletion=I;exports.collectBrowserInfo=R;exports.getThreeDSAction=v;exports.isApiError=K;exports.isAuthenticationError=N;exports.isAuthorizationError=U;exports.isChallengeAborted=V;exports.isNetworkError=q;exports.isRateLimitError=$;exports.isStateError=W;exports.isThreeDSChallengeAction=_;exports.isThreeDSMethodAction=E;exports.isValidationError=O;exports.mountThreeDSBrowserForm=g;exports.runThreeDSBrowserFlow=L;return exports;})({});//# sourceMappingURL=arcpay.global.js.map
|
|
3
3
|
//# sourceMappingURL=arcpay.global.js.map
|