@ozura/elements 0.1.0-beta.1
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/LICENSE +21 -0
- package/README.md +717 -0
- package/dist/frame/element-frame.html +22 -0
- package/dist/frame/element-frame.js +731 -0
- package/dist/frame/element-frame.js.map +1 -0
- package/dist/frame/tokenizer-frame.html +11 -0
- package/dist/frame/tokenizer-frame.js +328 -0
- package/dist/frame/tokenizer-frame.js.map +1 -0
- package/dist/oz-elements.esm.js +1190 -0
- package/dist/oz-elements.esm.js.map +1 -0
- package/dist/oz-elements.umd.js +1202 -0
- package/dist/oz-elements.umd.js.map +1 -0
- package/dist/react/frame/elementFrame.d.ts +8 -0
- package/dist/react/frame/tokenizerFrame.d.ts +13 -0
- package/dist/react/index.cjs.js +1407 -0
- package/dist/react/index.cjs.js.map +1 -0
- package/dist/react/index.esm.js +1400 -0
- package/dist/react/index.esm.js.map +1 -0
- package/dist/react/react/index.d.ts +214 -0
- package/dist/react/sdk/OzElement.d.ts +65 -0
- package/dist/react/sdk/OzVault.d.ts +106 -0
- package/dist/react/sdk/errors.d.ts +55 -0
- package/dist/react/sdk/index.d.ts +5 -0
- package/dist/react/server/index.d.ts +140 -0
- package/dist/react/types/index.d.ts +432 -0
- package/dist/react/utils/appearance.d.ts +13 -0
- package/dist/react/utils/billingUtils.d.ts +60 -0
- package/dist/react/utils/cardUtils.d.ts +37 -0
- package/dist/server/frame/elementFrame.d.ts +8 -0
- package/dist/server/frame/tokenizerFrame.d.ts +13 -0
- package/dist/server/index.cjs.js +294 -0
- package/dist/server/index.cjs.js.map +1 -0
- package/dist/server/index.esm.js +290 -0
- package/dist/server/index.esm.js.map +1 -0
- package/dist/server/sdk/OzElement.d.ts +65 -0
- package/dist/server/sdk/OzVault.d.ts +106 -0
- package/dist/server/sdk/errors.d.ts +55 -0
- package/dist/server/sdk/index.d.ts +5 -0
- package/dist/server/server/index.d.ts +140 -0
- package/dist/server/types/index.d.ts +432 -0
- package/dist/server/utils/appearance.d.ts +13 -0
- package/dist/server/utils/billingUtils.d.ts +60 -0
- package/dist/server/utils/cardUtils.d.ts +37 -0
- package/dist/types/frame/elementFrame.d.ts +8 -0
- package/dist/types/frame/tokenizerFrame.d.ts +13 -0
- package/dist/types/sdk/OzElement.d.ts +65 -0
- package/dist/types/sdk/OzVault.d.ts +106 -0
- package/dist/types/sdk/errors.d.ts +55 -0
- package/dist/types/sdk/index.d.ts +5 -0
- package/dist/types/server/index.d.ts +140 -0
- package/dist/types/types/index.d.ts +432 -0
- package/dist/types/utils/appearance.d.ts +13 -0
- package/dist/types/utils/billingUtils.d.ts +60 -0
- package/dist/types/utils/cardUtils.d.ts +37 -0
- package/package.json +97 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
export interface ElementStyle {
|
|
2
|
+
color?: string;
|
|
3
|
+
fontSize?: string;
|
|
4
|
+
fontFamily?: string;
|
|
5
|
+
fontWeight?: string;
|
|
6
|
+
fontStyle?: string;
|
|
7
|
+
fontVariant?: string;
|
|
8
|
+
letterSpacing?: string;
|
|
9
|
+
lineHeight?: string;
|
|
10
|
+
textAlign?: string;
|
|
11
|
+
textDecoration?: string;
|
|
12
|
+
textShadow?: string;
|
|
13
|
+
textTransform?: string;
|
|
14
|
+
padding?: string;
|
|
15
|
+
paddingTop?: string;
|
|
16
|
+
paddingRight?: string;
|
|
17
|
+
paddingBottom?: string;
|
|
18
|
+
paddingLeft?: string;
|
|
19
|
+
backgroundColor?: string;
|
|
20
|
+
opacity?: string;
|
|
21
|
+
border?: string;
|
|
22
|
+
borderColor?: string;
|
|
23
|
+
borderWidth?: string;
|
|
24
|
+
borderStyle?: string;
|
|
25
|
+
borderRadius?: string;
|
|
26
|
+
borderTop?: string;
|
|
27
|
+
borderRight?: string;
|
|
28
|
+
borderBottom?: string;
|
|
29
|
+
borderLeft?: string;
|
|
30
|
+
borderTopColor?: string;
|
|
31
|
+
borderRightColor?: string;
|
|
32
|
+
borderBottomColor?: string;
|
|
33
|
+
borderLeftColor?: string;
|
|
34
|
+
borderTopWidth?: string;
|
|
35
|
+
borderRightWidth?: string;
|
|
36
|
+
borderBottomWidth?: string;
|
|
37
|
+
borderLeftWidth?: string;
|
|
38
|
+
borderTopStyle?: string;
|
|
39
|
+
borderRightStyle?: string;
|
|
40
|
+
borderBottomStyle?: string;
|
|
41
|
+
borderLeftStyle?: string;
|
|
42
|
+
borderTopLeftRadius?: string;
|
|
43
|
+
borderTopRightRadius?: string;
|
|
44
|
+
borderBottomLeftRadius?: string;
|
|
45
|
+
borderBottomRightRadius?: string;
|
|
46
|
+
boxShadow?: string;
|
|
47
|
+
outline?: string;
|
|
48
|
+
outlineColor?: string;
|
|
49
|
+
outlineWidth?: string;
|
|
50
|
+
outlineStyle?: string;
|
|
51
|
+
outlineOffset?: string;
|
|
52
|
+
cursor?: string;
|
|
53
|
+
caretColor?: string;
|
|
54
|
+
height?: string;
|
|
55
|
+
minHeight?: string;
|
|
56
|
+
maxHeight?: string;
|
|
57
|
+
transition?: string;
|
|
58
|
+
/** Index signature for forward-compatibility with future CSS properties. */
|
|
59
|
+
[key: string]: string | undefined;
|
|
60
|
+
}
|
|
61
|
+
export interface ElementStyleConfig {
|
|
62
|
+
/** Default styles applied to the input. */
|
|
63
|
+
base?: ElementStyle;
|
|
64
|
+
/** Styles applied when the input is focused. Merges on top of `base`. */
|
|
65
|
+
focus?: ElementStyle;
|
|
66
|
+
/** Styles applied when the input contains an invalid value (on blur). Merges on top of `base`. */
|
|
67
|
+
invalid?: ElementStyle;
|
|
68
|
+
/** Styles applied when the input contains a valid, complete value (on blur). Merges on top of `base`. */
|
|
69
|
+
complete?: ElementStyle;
|
|
70
|
+
/** Styles applied to the input's placeholder text (::placeholder pseudo-element). */
|
|
71
|
+
placeholder?: ElementStyle;
|
|
72
|
+
}
|
|
73
|
+
export interface ElementOptions {
|
|
74
|
+
style?: ElementStyleConfig;
|
|
75
|
+
placeholder?: string;
|
|
76
|
+
disabled?: boolean;
|
|
77
|
+
/** How long to wait (ms) for the iframe to load before emitting `loaderror`. Default: 10 000. */
|
|
78
|
+
loadTimeoutMs?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface ElementChangeEvent {
|
|
81
|
+
empty: boolean;
|
|
82
|
+
complete: boolean;
|
|
83
|
+
valid: boolean;
|
|
84
|
+
/** Card brand — only present on cardNumber elements */
|
|
85
|
+
cardBrand?: string;
|
|
86
|
+
/** Parsed month (01-12) — only present on expirationDate elements */
|
|
87
|
+
month?: string;
|
|
88
|
+
/** Parsed 2-digit year — only present on expirationDate elements */
|
|
89
|
+
year?: string;
|
|
90
|
+
/** Human-readable error when valid is false and the field has been touched */
|
|
91
|
+
error?: string;
|
|
92
|
+
}
|
|
93
|
+
export type ElementType = 'cardNumber' | 'cvv' | 'expirationDate';
|
|
94
|
+
/** Bank account element types. */
|
|
95
|
+
export type BankElementType = 'accountNumber' | 'routingNumber';
|
|
96
|
+
/** Load a font from a CSS stylesheet URL (e.g. Google Fonts). Must be HTTPS. */
|
|
97
|
+
export interface CssFontSource {
|
|
98
|
+
cssSrc: string;
|
|
99
|
+
}
|
|
100
|
+
/** Load a custom font via @font-face. `src` must be a `url(https://...)` value. */
|
|
101
|
+
export interface CustomFontSource {
|
|
102
|
+
family: string;
|
|
103
|
+
src: string;
|
|
104
|
+
weight?: string;
|
|
105
|
+
style?: string;
|
|
106
|
+
display?: string;
|
|
107
|
+
unicodeRange?: string;
|
|
108
|
+
}
|
|
109
|
+
export type FontSource = CssFontSource | CustomFontSource;
|
|
110
|
+
export type OzTheme = 'default' | 'night' | 'flat';
|
|
111
|
+
/**
|
|
112
|
+
* CSS variable-style overrides. Each key maps to a specific style property
|
|
113
|
+
* across all style states, so merchants can theme with a single flat object
|
|
114
|
+
* instead of manually building full `ElementStyleConfig` objects.
|
|
115
|
+
*/
|
|
116
|
+
export interface AppearanceVariables {
|
|
117
|
+
/** Input text color. Maps to `base.color`. */
|
|
118
|
+
colorText?: string;
|
|
119
|
+
/** Input background color. Maps to `base.backgroundColor`. */
|
|
120
|
+
colorBackground?: string;
|
|
121
|
+
/** Primary accent color. Maps to `focus.caretColor` and `focus.color`. */
|
|
122
|
+
colorPrimary?: string;
|
|
123
|
+
/** Error/invalid state text color. Maps to `invalid.color`. */
|
|
124
|
+
colorDanger?: string;
|
|
125
|
+
/** Success/complete state text color. Maps to `complete.color`. */
|
|
126
|
+
colorSuccess?: string;
|
|
127
|
+
/** Placeholder text color. Maps to `placeholder.color`. */
|
|
128
|
+
colorPlaceholder?: string;
|
|
129
|
+
/** Font family. Maps to `base.fontFamily`. */
|
|
130
|
+
fontFamily?: string;
|
|
131
|
+
/** Font size. Maps to `base.fontSize`. */
|
|
132
|
+
fontSize?: string;
|
|
133
|
+
/** Font weight. Maps to `base.fontWeight`. */
|
|
134
|
+
fontWeight?: string;
|
|
135
|
+
/** Letter spacing. Maps to `base.letterSpacing`. */
|
|
136
|
+
letterSpacing?: string;
|
|
137
|
+
/** Line height. Maps to `base.lineHeight`. */
|
|
138
|
+
lineHeight?: string;
|
|
139
|
+
/** Inner padding. Maps to `base.padding`. */
|
|
140
|
+
padding?: string;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Global appearance configuration. Applied to all elements created by this vault.
|
|
144
|
+
* Per-element `style` overrides take precedence over appearance settings.
|
|
145
|
+
*/
|
|
146
|
+
export interface Appearance {
|
|
147
|
+
/** Preset theme. Applies a complete set of default styles. */
|
|
148
|
+
theme?: OzTheme;
|
|
149
|
+
/** Variable overrides. Merged on top of the theme defaults. */
|
|
150
|
+
variables?: AppearanceVariables;
|
|
151
|
+
}
|
|
152
|
+
export interface VaultOptions {
|
|
153
|
+
/** Base URL of the vault API. Defaults to the Ozura production vault. */
|
|
154
|
+
apiUrl?: string;
|
|
155
|
+
/** System pub key required for tokenization. Obtain from Ozura admin.
|
|
156
|
+
* Sent as the `X-Pub-Key` header on tokenize requests. */
|
|
157
|
+
pubKey: string;
|
|
158
|
+
/** Base URL where the Ozura frame HTML/JS assets are served from.
|
|
159
|
+
* Defaults to the production CDN. Override for local development. */
|
|
160
|
+
frameBaseUrl?: string;
|
|
161
|
+
/**
|
|
162
|
+
* Custom fonts to inject into element iframes. Accepts Google Fonts URLs
|
|
163
|
+
* or @font-face declarations. Fonts are loaded inside each iframe so they
|
|
164
|
+
* render in the card input fields.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* // Google Fonts
|
|
168
|
+
* fonts: [{ cssSrc: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap' }]
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* // Custom @font-face
|
|
172
|
+
* fonts: [{ family: 'MyFont', src: 'url(https://cdn.example.com/myfont.woff2)', weight: '400' }]
|
|
173
|
+
*/
|
|
174
|
+
fonts?: FontSource[];
|
|
175
|
+
/**
|
|
176
|
+
* Called if the tokenizer iframe fails to signal ready within `loadTimeoutMs`.
|
|
177
|
+
* Use this to show a fallback UI (e.g. "Unable to load payment fields").
|
|
178
|
+
*/
|
|
179
|
+
onLoadError?: () => void;
|
|
180
|
+
/** How long to wait (ms) for the tokenizer iframe before calling `onLoadError`. Default: 10 000. */
|
|
181
|
+
loadTimeoutMs?: number;
|
|
182
|
+
/**
|
|
183
|
+
* Global appearance configuration. Applies preset themes and/or variable
|
|
184
|
+
* overrides to all elements created by this vault. Per-element `style`
|
|
185
|
+
* overrides take precedence.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* appearance: { theme: 'night' }
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* appearance: {
|
|
192
|
+
* theme: 'flat',
|
|
193
|
+
* variables: { colorPrimary: '#6366f1', fontFamily: '"Inter", sans-serif' },
|
|
194
|
+
* }
|
|
195
|
+
*/
|
|
196
|
+
appearance?: Appearance;
|
|
197
|
+
}
|
|
198
|
+
/** Billing address. All string fields are validated to 1–50 characters. */
|
|
199
|
+
export interface BillingAddress {
|
|
200
|
+
line1: string;
|
|
201
|
+
/** Optional. Omitted entirely from cardSale if blank (schema enforces minLength 1 if present). */
|
|
202
|
+
line2?: string;
|
|
203
|
+
city: string;
|
|
204
|
+
/** For US and CA: normalized to the 2-letter abbreviation (e.g. "California" → "CA"). */
|
|
205
|
+
state: string;
|
|
206
|
+
zip: string;
|
|
207
|
+
/** ISO 3166-1 alpha-2, e.g. "US", "CA", "GB". */
|
|
208
|
+
country: string;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Cardholder billing details validated against the Ozura cardSale API schema.
|
|
212
|
+
* Mirrors the `billing_details` object in Stripe's createPaymentMethod API.
|
|
213
|
+
*
|
|
214
|
+
* Pass to `vault.createToken({ billing })` — the SDK validates all fields and
|
|
215
|
+
* returns normalized values in `TokenResponse.billing` ready for the cardSale call.
|
|
216
|
+
*/
|
|
217
|
+
export interface BillingDetails {
|
|
218
|
+
/** 1–50 characters. Required for cardSale. */
|
|
219
|
+
firstName: string;
|
|
220
|
+
/** 1–50 characters. Required for cardSale. Must be non-empty. */
|
|
221
|
+
lastName: string;
|
|
222
|
+
/** Valid email address, max 50 characters. */
|
|
223
|
+
email?: string;
|
|
224
|
+
/** E.164 format, e.g. "+15551234567". Max 50 characters. */
|
|
225
|
+
phone?: string;
|
|
226
|
+
address?: BillingAddress;
|
|
227
|
+
}
|
|
228
|
+
export interface TokenizeOptions {
|
|
229
|
+
/**
|
|
230
|
+
* Billing details — validated, normalized, and returned in TokenResponse.billing
|
|
231
|
+
* ready to be passed directly to the cardSale API.
|
|
232
|
+
*
|
|
233
|
+
* If provided, firstName and lastName inside billing take precedence over
|
|
234
|
+
* the top-level firstName/lastName params below.
|
|
235
|
+
*/
|
|
236
|
+
billing?: BillingDetails;
|
|
237
|
+
/** @deprecated Pass firstName inside `billing` instead. */
|
|
238
|
+
firstName?: string;
|
|
239
|
+
/** @deprecated Pass lastName inside `billing` instead. */
|
|
240
|
+
lastName?: string;
|
|
241
|
+
}
|
|
242
|
+
/** Options for `vault.createBankToken()`. */
|
|
243
|
+
export interface BankTokenizeOptions {
|
|
244
|
+
/** Account holder first name. Required. */
|
|
245
|
+
firstName: string;
|
|
246
|
+
/** Account holder last name. Required. */
|
|
247
|
+
lastName: string;
|
|
248
|
+
}
|
|
249
|
+
/** Non-sensitive bank account metadata returned alongside the token. */
|
|
250
|
+
export interface BankAccountMetadata {
|
|
251
|
+
/** Last 4 digits of the account number. */
|
|
252
|
+
last4: string;
|
|
253
|
+
/** US routing number (9 digits). */
|
|
254
|
+
routingNumber: string;
|
|
255
|
+
}
|
|
256
|
+
/** Non-sensitive card metadata returned alongside the token. */
|
|
257
|
+
export interface CardMetadata {
|
|
258
|
+
/** Last 4 digits of the card number. */
|
|
259
|
+
last4: string;
|
|
260
|
+
/** Detected card brand (e.g. "visa", "mastercard", "amex"). */
|
|
261
|
+
brand: string;
|
|
262
|
+
/** 2-digit expiry month (e.g. "09"). */
|
|
263
|
+
expMonth: string;
|
|
264
|
+
/** 4-digit expiry year (e.g. "2027"). */
|
|
265
|
+
expYear: string;
|
|
266
|
+
}
|
|
267
|
+
export interface TokenResponse {
|
|
268
|
+
token: string;
|
|
269
|
+
cvcSession?: string;
|
|
270
|
+
/** Non-sensitive card metadata — available immediately without a cardSale call. */
|
|
271
|
+
card?: CardMetadata;
|
|
272
|
+
/**
|
|
273
|
+
* Validated, normalized billing details — ready to spread into a cardSale request.
|
|
274
|
+
* Only present when billing was passed to createToken().
|
|
275
|
+
*/
|
|
276
|
+
billing?: BillingDetails;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Returned by `vault.createBankToken()` after successful ACH tokenization.
|
|
280
|
+
* The token can be passed to any ACH-capable payment processor.
|
|
281
|
+
* Note: OzuraPay does not currently support bank account payments.
|
|
282
|
+
*/
|
|
283
|
+
export interface BankTokenResponse {
|
|
284
|
+
/** Vault token representing the bank account. Use with your ACH processor. */
|
|
285
|
+
token: string;
|
|
286
|
+
/** Non-sensitive bank account metadata. */
|
|
287
|
+
bank?: BankAccountMetadata;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Full request body for the Ozura Pay API cardSale endpoint.
|
|
291
|
+
* All string fields are 1–50 characters. billingAddress2 is optional (omit if blank).
|
|
292
|
+
*
|
|
293
|
+
* Headers required:
|
|
294
|
+
* x-api-key: <merchantApiKey>
|
|
295
|
+
* vault-api-key: <vaultApiKey> (same key passed to OzVault)
|
|
296
|
+
*/
|
|
297
|
+
export interface CardSaleRequest {
|
|
298
|
+
/** Processor to use. If omitted, the Pay API auto-selects (Elavon → Nuvei → Worldpay). */
|
|
299
|
+
processor?: 'elavon' | 'nuvei' | 'worldpay';
|
|
300
|
+
merchantId: string;
|
|
301
|
+
/** Decimal string, e.g. "49.00". */
|
|
302
|
+
amount: string;
|
|
303
|
+
/** ISO 4217, e.g. "USD". */
|
|
304
|
+
currency: string;
|
|
305
|
+
/** From TokenResponse.token */
|
|
306
|
+
ozuraCardToken: string;
|
|
307
|
+
/** From TokenResponse.cvcSession */
|
|
308
|
+
ozuraCvcSession: string;
|
|
309
|
+
billingFirstName: string;
|
|
310
|
+
billingLastName: string;
|
|
311
|
+
billingEmail: string;
|
|
312
|
+
/** E.164 format, max 50 chars. */
|
|
313
|
+
billingPhone: string;
|
|
314
|
+
billingAddress1: string;
|
|
315
|
+
/** Omit entirely if blank — schema enforces minLength 1 if present. */
|
|
316
|
+
billingAddress2?: string;
|
|
317
|
+
billingCity: string;
|
|
318
|
+
/** 2-letter state/province code. */
|
|
319
|
+
billingState: string;
|
|
320
|
+
billingZipcode: string;
|
|
321
|
+
/** ISO 3166-1 alpha-2. */
|
|
322
|
+
billingCountry: string;
|
|
323
|
+
/** Fetch from your server — use an internal route, not api.ipify.org (ad-blockers block it). */
|
|
324
|
+
clientIpAddress: string;
|
|
325
|
+
salesTaxExempt: boolean;
|
|
326
|
+
/** Defaults to "0.00". Range 0–3. */
|
|
327
|
+
surchargePercent?: string;
|
|
328
|
+
/** Defaults to "0.00". */
|
|
329
|
+
tipAmount?: string;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The `data` object inside a successful cardSale API response.
|
|
333
|
+
*
|
|
334
|
+
* Store `transactionId` in your database immediately after receiving this —
|
|
335
|
+
* it is required for refunds and idempotency checks.
|
|
336
|
+
*/
|
|
337
|
+
export interface CardSaleResponseData {
|
|
338
|
+
/** Unique transaction reference — store this in your database. */
|
|
339
|
+
transactionId: string;
|
|
340
|
+
/** Amount charged, decimal string, e.g. "49.00". */
|
|
341
|
+
amount: string;
|
|
342
|
+
/** ISO 4217 currency code, e.g. "USD". */
|
|
343
|
+
currency: string;
|
|
344
|
+
/** Surcharge amount applied, e.g. "0.00". */
|
|
345
|
+
surchargeAmount: string;
|
|
346
|
+
/** Sales tax calculated by the Pay API based on billing address. */
|
|
347
|
+
salesTaxAmount?: string;
|
|
348
|
+
/** Tip amount applied, e.g. "0.00". */
|
|
349
|
+
tipAmount: string;
|
|
350
|
+
/** Last four digits of the card number. */
|
|
351
|
+
cardLastFour: string;
|
|
352
|
+
/** First six digits of the card number (BIN). */
|
|
353
|
+
cardBin?: string;
|
|
354
|
+
/** Expiry month as 2-digit string, e.g. "09". */
|
|
355
|
+
cardExpMonth: string;
|
|
356
|
+
/** Expiry year as 4-digit string, e.g. "2027". */
|
|
357
|
+
cardExpYear: string;
|
|
358
|
+
/** Card brand returned by processor, e.g. "visa", "mastercard", "amex". */
|
|
359
|
+
cardBrand: string;
|
|
360
|
+
/** Whether the card is a credit card (vs debit). */
|
|
361
|
+
isCreditCard?: boolean;
|
|
362
|
+
/** ISO 8601 transaction timestamp. */
|
|
363
|
+
transDate: string;
|
|
364
|
+
/** Merchant ID echoed back from the request. */
|
|
365
|
+
ozuraMerchantId: string;
|
|
366
|
+
/** Client IP address echoed back. */
|
|
367
|
+
clientIpAddress?: string;
|
|
368
|
+
/** Billing fields echoed back — useful for receipts. */
|
|
369
|
+
billingFirstName: string;
|
|
370
|
+
billingLastName: string;
|
|
371
|
+
billingEmail: string;
|
|
372
|
+
billingPhone: string;
|
|
373
|
+
billingAddress1: string;
|
|
374
|
+
billingAddress2?: string;
|
|
375
|
+
billingCity: string;
|
|
376
|
+
billingState: string;
|
|
377
|
+
billingZipcode: string;
|
|
378
|
+
billingCountry: string;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Full response envelope from the Ozura Pay API cardSale endpoint.
|
|
382
|
+
*
|
|
383
|
+
* On success: `{ success: true, data: CardSaleResponseData }`
|
|
384
|
+
* On failure: HTTP 4xx/5xx with `{ error: string }` — pass `error` to
|
|
385
|
+
* `normalizeCardSaleError()` to get a user-facing message.
|
|
386
|
+
*/
|
|
387
|
+
export interface CardSaleApiResponse {
|
|
388
|
+
success: boolean;
|
|
389
|
+
data: CardSaleResponseData;
|
|
390
|
+
}
|
|
391
|
+
/** Query params for GET /api/v1/transQuery. */
|
|
392
|
+
export interface TransactionQueryParams {
|
|
393
|
+
merchantId: string;
|
|
394
|
+
/** Fetch a specific transaction. */
|
|
395
|
+
transactionId?: string;
|
|
396
|
+
/** Date range start, format "YYYY-MM-DD HH:MM:SS". */
|
|
397
|
+
dateFrom?: string;
|
|
398
|
+
/** Date range end, format "YYYY-MM-DD HH:MM:SS". */
|
|
399
|
+
dateTo?: string;
|
|
400
|
+
/** Filter by type, e.g. "sale", "refund". */
|
|
401
|
+
transactionType?: string;
|
|
402
|
+
/** 1-based page number. Default: 1. */
|
|
403
|
+
page?: number;
|
|
404
|
+
/** Results per page. Default: 50, max: 100. */
|
|
405
|
+
limit?: number;
|
|
406
|
+
/** Comma-separated field names to return. */
|
|
407
|
+
fields?: string;
|
|
408
|
+
sortBy?: string;
|
|
409
|
+
sortOrder?: 'asc' | 'desc';
|
|
410
|
+
}
|
|
411
|
+
export interface TransactionQueryPagination {
|
|
412
|
+
currentPage: number;
|
|
413
|
+
totalPages: number;
|
|
414
|
+
totalCount: number;
|
|
415
|
+
limit: number;
|
|
416
|
+
hasNextPage: boolean;
|
|
417
|
+
hasPrevPage: boolean;
|
|
418
|
+
nextPage: number | null;
|
|
419
|
+
prevPage: number | null;
|
|
420
|
+
}
|
|
421
|
+
export interface TransactionQueryResponse {
|
|
422
|
+
success: boolean;
|
|
423
|
+
data: CardSaleResponseData[];
|
|
424
|
+
pagination: TransactionQueryPagination;
|
|
425
|
+
}
|
|
426
|
+
export type OzMessageType = 'OZ_FRAME_READY' | 'OZ_INIT' | 'OZ_UPDATE' | 'OZ_CLEAR' | 'OZ_CHANGE' | 'OZ_FOCUS' | 'OZ_BLUR' | 'OZ_RESIZE' | 'OZ_SET_TOKENIZER_NAME' | 'OZ_BEGIN_COLLECT' | 'OZ_FIELD_VALUE' | 'OZ_TOKENIZE' | 'OZ_TOKEN_RESULT' | 'OZ_TOKEN_ERROR' | 'OZ_FOCUS_REQUEST' | 'OZ_BLUR_REQUEST' | 'OZ_SET_CVV_LENGTH' | 'OZ_BANK_TOKENIZE' | 'OZ_BANK_TOKEN_RESULT';
|
|
427
|
+
export interface OzMessage {
|
|
428
|
+
__oz: true;
|
|
429
|
+
vaultId: string;
|
|
430
|
+
type: OzMessageType;
|
|
431
|
+
[key: string]: unknown;
|
|
432
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Appearance, ElementStyleConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves an `Appearance` config into a flat `ElementStyleConfig`.
|
|
4
|
+
* Resolution order: theme defaults → variable overrides.
|
|
5
|
+
* The returned config is then used as the "base appearance" that
|
|
6
|
+
* per-element `style` overrides merge on top of.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveAppearance(appearance?: Appearance): ElementStyleConfig | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Merges a resolved appearance with per-element style overrides.
|
|
11
|
+
* Element styles always win over appearance styles.
|
|
12
|
+
*/
|
|
13
|
+
export declare function mergeAppearanceWithElementStyle(appearance: ElementStyleConfig | undefined, elementStyle: ElementStyleConfig | undefined): ElementStyleConfig | undefined;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* billingUtils.ts — billing detail validation and normalization.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the validation in checkout/page.tsx (pre-flight checks before cardSale)
|
|
5
|
+
* so that billing data passed to createToken() is guaranteed schema-compliant and
|
|
6
|
+
* ready to forward directly to the Ozura Pay API cardSale endpoint.
|
|
7
|
+
*
|
|
8
|
+
* All string fields enforced to 1–50 characters (cardSale schema constraint).
|
|
9
|
+
* State is normalized to 2-letter abbreviation for US and CA.
|
|
10
|
+
* Phone must be E.164 format (matches checkout's formatPhoneForAPI output).
|
|
11
|
+
*/
|
|
12
|
+
import { BillingDetails } from '../types';
|
|
13
|
+
/** Returns true when the email is syntactically valid and ≤50 characters. */
|
|
14
|
+
export declare function validateEmail(email: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Validates E.164 phone format: starts with +, 1–3 digit country code,
|
|
17
|
+
* followed by 7–12 digits, total ≤50 characters.
|
|
18
|
+
*
|
|
19
|
+
* Matches the output of checkout's formatPhoneForAPI() function.
|
|
20
|
+
* Examples: "+15551234567", "+447911123456", "+61412345678"
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateE164Phone(phone: string): boolean;
|
|
23
|
+
/** Returns true when the string is non-empty and ≤50 characters (cardSale schema). */
|
|
24
|
+
export declare function isValidBillingField(value: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Converts a full US state or Canadian province name to its 2-letter abbreviation.
|
|
27
|
+
* If already a valid abbreviation (case-insensitive), returns it uppercased.
|
|
28
|
+
* For non-US/CA countries, returns the input uppercased unchanged.
|
|
29
|
+
*
|
|
30
|
+
* Matches checkout's convertStateToAbbreviation() behaviour exactly.
|
|
31
|
+
*/
|
|
32
|
+
export declare function normalizeState(state: string, country: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Validates a postal/ZIP code against country-specific format rules.
|
|
35
|
+
* For countries without a specific pattern, falls back to generic 1–50 char check.
|
|
36
|
+
*/
|
|
37
|
+
export declare function validatePostalCode(zip: string, country: string): {
|
|
38
|
+
valid: boolean;
|
|
39
|
+
error?: string;
|
|
40
|
+
};
|
|
41
|
+
export interface BillingValidationResult {
|
|
42
|
+
valid: boolean;
|
|
43
|
+
/** One entry per failing field, each suitable for display in a thrown OzError message. */
|
|
44
|
+
errors: string[];
|
|
45
|
+
/** Trimmed and normalized billing details — state converted, address2 omitted if blank. */
|
|
46
|
+
normalized: BillingDetails;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Validates and normalizes billing details against the Ozura cardSale API schema.
|
|
50
|
+
*
|
|
51
|
+
* Rules applied (same as checkout's pre-flight validation in page.tsx):
|
|
52
|
+
* - firstName, lastName: required, 1–50 chars
|
|
53
|
+
* - email: optional; if provided, must be valid format and ≤50 chars
|
|
54
|
+
* - phone: optional; if provided, must be E.164 and ≤50 chars
|
|
55
|
+
* - address fields: if address is provided, line1/city/state/zip/country are
|
|
56
|
+
* required (1–50 chars each); line2 is optional and omitted from normalized
|
|
57
|
+
* output if blank (cardSale schema: minLength 1 if present)
|
|
58
|
+
* - state: normalized to 2-letter abbreviation for US and CA
|
|
59
|
+
*/
|
|
60
|
+
export declare function validateBilling(billing: BillingDetails): BillingValidationResult;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cardUtils.ts — pure card validation and formatting helpers.
|
|
3
|
+
*
|
|
4
|
+
* These functions contain no DOM or browser dependencies and are shared
|
|
5
|
+
* between the element frame runtime and the test suite.
|
|
6
|
+
*/
|
|
7
|
+
/** Returns true when the digit string passes the Luhn checksum. */
|
|
8
|
+
export declare function luhn(digits: string): boolean;
|
|
9
|
+
export type CardBrand = 'visa' | 'mastercard' | 'amex' | 'dinersclub' | 'discover' | 'jcb' | 'unknown';
|
|
10
|
+
/** Detects the card brand from the leading digits. Returns 'unknown' for no match. */
|
|
11
|
+
export declare function detectBrand(num: string): CardBrand;
|
|
12
|
+
/** Maximum digit length allowed for a given brand. */
|
|
13
|
+
export declare function getCardMaxLength(brand: CardBrand | string): number;
|
|
14
|
+
/**
|
|
15
|
+
* Formats raw card digits into the display string for the given brand.
|
|
16
|
+
* Amex: 4-6-5 grouping. All others: groups of 4.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatCard(digits: string, brand: CardBrand | string): string;
|
|
19
|
+
export interface CardValidationResult {
|
|
20
|
+
complete: boolean;
|
|
21
|
+
valid: boolean;
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function validateCardNumber(digits: string, brand: CardBrand | string): CardValidationResult;
|
|
25
|
+
export interface ExpiryValidationResult {
|
|
26
|
+
complete: boolean;
|
|
27
|
+
valid: boolean;
|
|
28
|
+
month?: string;
|
|
29
|
+
year?: string;
|
|
30
|
+
error?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validates a raw 4-digit MMYY string (as stored by the element frame).
|
|
34
|
+
* Month is clamped to 01–12 at input time, so only past-date and
|
|
35
|
+
* incomplete checks are needed here.
|
|
36
|
+
*/
|
|
37
|
+
export declare function validateExpiry(rawMMYY: string): ExpiryValidationResult;
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ozura/elements",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "PCI-compliant card tokenization SDK for the Ozura Vault — collect card data in iframe-isolated fields and tokenize without PCI scope",
|
|
5
|
+
"main": "dist/oz-elements.umd.js",
|
|
6
|
+
"module": "dist/oz-elements.esm.js",
|
|
7
|
+
"types": "dist/types/sdk/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types/sdk/index.d.ts",
|
|
11
|
+
"import": "./dist/oz-elements.esm.js",
|
|
12
|
+
"require": "./dist/oz-elements.umd.js"
|
|
13
|
+
},
|
|
14
|
+
"./react": {
|
|
15
|
+
"types": "./dist/react/index.d.ts",
|
|
16
|
+
"import": "./dist/react/index.esm.js",
|
|
17
|
+
"require": "./dist/react/index.cjs.js"
|
|
18
|
+
},
|
|
19
|
+
"./server": {
|
|
20
|
+
"types": "./dist/server/index.d.ts",
|
|
21
|
+
"import": "./dist/server/index.esm.js",
|
|
22
|
+
"require": "./dist/server/index.cjs.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist/oz-elements.esm.js",
|
|
27
|
+
"dist/oz-elements.umd.js",
|
|
28
|
+
"dist/oz-elements.esm.js.map",
|
|
29
|
+
"dist/oz-elements.umd.js.map",
|
|
30
|
+
"dist/frame",
|
|
31
|
+
"dist/react",
|
|
32
|
+
"dist/server",
|
|
33
|
+
"dist/types"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && rollup -c rollup.config.mjs",
|
|
37
|
+
"dev": "npm run build && node dev-server.mjs",
|
|
38
|
+
"watch": "rollup -c rollup.config.mjs --watch",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"test:watch": "vitest",
|
|
41
|
+
"test:coverage": "vitest run --coverage",
|
|
42
|
+
"test:e2e": "playwright test --project=mock",
|
|
43
|
+
"test:e2e:live": "playwright test --project=live",
|
|
44
|
+
"prepublishOnly": "npm run build"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"react": ">=17",
|
|
48
|
+
"react-dom": ">=17"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"react": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"react-dom": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"keywords": [
|
|
59
|
+
"vault",
|
|
60
|
+
"tokenization",
|
|
61
|
+
"pci",
|
|
62
|
+
"card",
|
|
63
|
+
"iframe",
|
|
64
|
+
"ozura",
|
|
65
|
+
"pci-dss",
|
|
66
|
+
"saq-a"
|
|
67
|
+
],
|
|
68
|
+
"author": "Ozura",
|
|
69
|
+
"license": "MIT",
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "https://github.com/Ozura-Inc/pci-vault-elements"
|
|
73
|
+
},
|
|
74
|
+
"engines": {
|
|
75
|
+
"node": ">=18 <24"
|
|
76
|
+
},
|
|
77
|
+
"sideEffects": false,
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@playwright/test": "^1.58.2",
|
|
80
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
81
|
+
"@rollup/plugin-replace": "^6.0.3",
|
|
82
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
83
|
+
"@types/node": "^22.14.0",
|
|
84
|
+
"@types/react": "^19.2.14",
|
|
85
|
+
"@types/react-dom": "^19.2.3",
|
|
86
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
87
|
+
"cross-env": "^10.1.0",
|
|
88
|
+
"jsdom": "^28.1.0",
|
|
89
|
+
"react": "^19.2.4",
|
|
90
|
+
"react-dom": "^19.2.4",
|
|
91
|
+
"rollup": "^4.34.9",
|
|
92
|
+
"rollup-plugin-copy": "^3.5.0",
|
|
93
|
+
"tslib": "^2.8.1",
|
|
94
|
+
"typescript": "^5.8.3",
|
|
95
|
+
"vitest": "^4.0.18"
|
|
96
|
+
}
|
|
97
|
+
}
|