@ozura/elements 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/frame/element-frame.html +1 -1
- package/dist/frame/element-frame.js +7 -4
- package/dist/frame/tokenizer-frame.html +1 -1
- package/dist/frame/tokenizer-frame.js +5 -6
- package/dist/oz-elements.esm.js +70 -22
- package/dist/oz-elements.umd.js +70 -22
- package/dist/react/index.cjs.js +114 -38
- package/dist/react/index.esm.js +114 -38
- package/dist/react/react/index.d.ts +29 -1
- package/dist/react/sdk/OzVault.d.ts +33 -0
- package/dist/react/types/index.d.ts +30 -5
- package/dist/react/vue/index.d.ts +56 -1
- package/dist/server/sdk/OzVault.d.ts +33 -0
- package/dist/server/types/index.d.ts +30 -5
- package/dist/server/vue/index.d.ts +56 -1
- package/dist/types/sdk/OzVault.d.ts +33 -0
- package/dist/types/types/index.d.ts +30 -5
- package/dist/types/vue/index.d.ts +56 -1
- package/dist/vue/index.cjs.js +135 -35
- package/dist/vue/index.esm.js +135 -35
- package/dist/vue/sdk/OzVault.d.ts +33 -0
- package/dist/vue/types/index.d.ts +30 -5
- package/dist/vue/vue/index.d.ts +56 -1
- package/package.json +1 -1
- package/dist/react/index.cjs.js.map +0 -1
- package/dist/react/index.esm.js.map +0 -1
- package/dist/vue/index.cjs.js.map +0 -1
- package/dist/vue/index.esm.js.map +0 -1
package/dist/react/index.esm.js
CHANGED
|
@@ -1115,7 +1115,7 @@ class OzVault {
|
|
|
1115
1115
|
this.loadErrorTimeoutId = setTimeout(() => {
|
|
1116
1116
|
this.loadErrorTimeoutId = null;
|
|
1117
1117
|
if (!this._destroyed && !this.tokenizerReady) {
|
|
1118
|
-
options.onLoadError();
|
|
1118
|
+
options.onLoadError({ source: 'tokenizer' });
|
|
1119
1119
|
}
|
|
1120
1120
|
}, timeout);
|
|
1121
1121
|
}
|
|
@@ -1248,6 +1248,49 @@ class OzVault {
|
|
|
1248
1248
|
get tokenizeCount() {
|
|
1249
1249
|
return this._tokenizeSuccessCount;
|
|
1250
1250
|
}
|
|
1251
|
+
/**
|
|
1252
|
+
* `true` when every mounted field has reported `complete && valid` via its
|
|
1253
|
+
* last `change` event. `false` if no fields have been created, or if any
|
|
1254
|
+
* field is incomplete or invalid.
|
|
1255
|
+
*
|
|
1256
|
+
* Use this to gate the pay button in vanilla JS integrations without having
|
|
1257
|
+
* to wire up individual `change` event listeners:
|
|
1258
|
+
*
|
|
1259
|
+
* @example
|
|
1260
|
+
* vault.getElement('cardNumber')!.on('change', () => {
|
|
1261
|
+
* payBtn.disabled = !vault.isComplete;
|
|
1262
|
+
* });
|
|
1263
|
+
*/
|
|
1264
|
+
get isComplete() {
|
|
1265
|
+
return this.allComplete([...this.elementsByType.values()]);
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Like {@link isComplete}, but for bank-account elements created via
|
|
1269
|
+
* {@link createBankElement}. Card and bank fields are tracked separately so a
|
|
1270
|
+
* card-only checkout is never gated on bank fields (and vice versa), matching
|
|
1271
|
+
* the `createToken()` / `createBankToken()` split. A vault with both card and
|
|
1272
|
+
* bank elements exposes each completion state independently.
|
|
1273
|
+
*/
|
|
1274
|
+
get isBankComplete() {
|
|
1275
|
+
return this.allComplete([...this.bankElementsByType.values()]);
|
|
1276
|
+
}
|
|
1277
|
+
/** True iff the set is non-empty and every element has reported complete-and-valid. */
|
|
1278
|
+
allComplete(els) {
|
|
1279
|
+
if (els.length === 0)
|
|
1280
|
+
return false;
|
|
1281
|
+
return els.every(el => this.completionState.get(el.frameId) === true);
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* `true` while a `createToken()` or `createBankToken()` call is in progress
|
|
1285
|
+
* (including the transparent wax-key refresh phase). Use this to keep the pay
|
|
1286
|
+
* button disabled during tokenization to prevent double-submission.
|
|
1287
|
+
*
|
|
1288
|
+
* @example
|
|
1289
|
+
* payBtn.disabled = vault.isTokenizing;
|
|
1290
|
+
*/
|
|
1291
|
+
get isTokenizing() {
|
|
1292
|
+
return this._tokenizing !== null;
|
|
1293
|
+
}
|
|
1251
1294
|
/**
|
|
1252
1295
|
* Creates a new OzElement of the given type. Call `.mount(selector)` on the
|
|
1253
1296
|
* returned element to attach it to the DOM.
|
|
@@ -1330,17 +1373,29 @@ class OzVault {
|
|
|
1330
1373
|
? 'A card tokenization is already in progress. Wait for it to complete before calling createBankToken().'
|
|
1331
1374
|
: 'A bank tokenization is already in progress. Wait for it to complete before calling createBankToken() again.');
|
|
1332
1375
|
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1376
|
+
// Validate billing details if provided — billing.firstName/lastName take
|
|
1377
|
+
// precedence over the top-level params (mirrors createToken() behaviour).
|
|
1378
|
+
let normalizedBankBilling;
|
|
1379
|
+
let bankFirstName = ((_a = options.firstName) !== null && _a !== void 0 ? _a : '').trim();
|
|
1380
|
+
let bankLastName = ((_b = options.lastName) !== null && _b !== void 0 ? _b : '').trim();
|
|
1381
|
+
if (options.billing) {
|
|
1382
|
+
const result = validateBilling(options.billing);
|
|
1383
|
+
if (!result.valid) {
|
|
1384
|
+
throw new OzError(`Invalid billing details: ${result.errors.join('; ')}`);
|
|
1385
|
+
}
|
|
1386
|
+
normalizedBankBilling = result.normalized;
|
|
1387
|
+
bankFirstName = normalizedBankBilling.firstName;
|
|
1388
|
+
bankLastName = normalizedBankBilling.lastName;
|
|
1341
1389
|
}
|
|
1342
|
-
|
|
1343
|
-
|
|
1390
|
+
else {
|
|
1391
|
+
if (!bankFirstName)
|
|
1392
|
+
throw new OzError('firstName is required for bank account tokenization.');
|
|
1393
|
+
if (!bankLastName)
|
|
1394
|
+
throw new OzError('lastName is required for bank account tokenization.');
|
|
1395
|
+
if (bankFirstName.length > 50)
|
|
1396
|
+
throw new OzError('firstName must be 50 characters or fewer.');
|
|
1397
|
+
if (bankLastName.length > 50)
|
|
1398
|
+
throw new OzError('lastName must be 50 characters or fewer.');
|
|
1344
1399
|
}
|
|
1345
1400
|
const accountEl = this.bankElementsByType.get('accountNumber');
|
|
1346
1401
|
const routingEl = this.bankElementsByType.get('routingNumber');
|
|
@@ -1366,14 +1421,7 @@ class OzVault {
|
|
|
1366
1421
|
if (this._resetCount === resetCountAtStart)
|
|
1367
1422
|
this._tokenizing = null;
|
|
1368
1423
|
};
|
|
1369
|
-
this.bankTokenizeResolvers.set(requestId, {
|
|
1370
|
-
resolve: (v) => { cleanup(); resolve(v); },
|
|
1371
|
-
reject: (e) => { cleanup(); reject(e); },
|
|
1372
|
-
firstName: options.firstName.trim(),
|
|
1373
|
-
lastName: options.lastName.trim(),
|
|
1374
|
-
readyElements: readyBankElements,
|
|
1375
|
-
fieldCount: readyBankElements.length,
|
|
1376
|
-
});
|
|
1424
|
+
this.bankTokenizeResolvers.set(requestId, Object.assign(Object.assign({ resolve: (v) => { cleanup(); resolve(v); }, reject: (e) => { cleanup(); reject(e); }, firstName: bankFirstName, lastName: bankLastName }, (normalizedBankBilling ? { billing: normalizedBankBilling } : {})), { readyElements: readyBankElements, fieldCount: readyBankElements.length }));
|
|
1377
1425
|
try {
|
|
1378
1426
|
const bankChannels = readyBankElements.map(() => new MessageChannel());
|
|
1379
1427
|
const bankTokenizeStartMs = Date.now();
|
|
@@ -1382,8 +1430,8 @@ class OzVault {
|
|
|
1382
1430
|
requestId,
|
|
1383
1431
|
tokenizationSessionId: this.tokenizationSessionId,
|
|
1384
1432
|
pubKey: (_a = this.pubKey) !== null && _a !== void 0 ? _a : '',
|
|
1385
|
-
firstName:
|
|
1386
|
-
lastName:
|
|
1433
|
+
firstName: bankFirstName,
|
|
1434
|
+
lastName: bankLastName,
|
|
1387
1435
|
fieldCount: readyBankElements.length,
|
|
1388
1436
|
}, bankChannels.map(ch => ch.port1));
|
|
1389
1437
|
this.log('OZ_BANK_TOKENIZE sent', { requestIdPrefix: `${requestId.slice(0, 12)}...`, fieldCount: readyBankElements.length });
|
|
@@ -2105,7 +2153,7 @@ class OzVault {
|
|
|
2105
2153
|
break;
|
|
2106
2154
|
}
|
|
2107
2155
|
const bank = isBankAccountMetadata(msg.bank) ? msg.bank : undefined;
|
|
2108
|
-
pending.resolve(Object.assign({ token }, (bank ? { bank } : {})));
|
|
2156
|
+
pending.resolve(Object.assign(Object.assign({ token }, (bank ? { bank } : {})), (pending.billing ? { billing: pending.billing } : {})));
|
|
2109
2157
|
this.log('bank token received', {
|
|
2110
2158
|
elapsedMs: pending.tokenizeStartMs != null ? Date.now() - pending.tokenizeStartMs : null,
|
|
2111
2159
|
tokenPresent: true,
|
|
@@ -2235,9 +2283,11 @@ const OzContext = createContext({
|
|
|
2235
2283
|
notifyUnmount: () => { },
|
|
2236
2284
|
notifyMount: () => { },
|
|
2237
2285
|
notifyTokenize: () => { },
|
|
2286
|
+
notifyChange: () => { },
|
|
2238
2287
|
mountedCount: 0,
|
|
2239
2288
|
readyCount: 0,
|
|
2240
2289
|
tokenizeCount: 0,
|
|
2290
|
+
changeTick: 0,
|
|
2241
2291
|
});
|
|
2242
2292
|
/**
|
|
2243
2293
|
* Creates and owns an OzVault instance for the lifetime of this component.
|
|
@@ -2250,6 +2300,7 @@ function OzElements({ sessionUrl, getSessionKey, fetchWaxKey, pubKey, frameBaseU
|
|
|
2250
2300
|
const [mountedCount, setMountedCount] = useState(0);
|
|
2251
2301
|
const [readyCount, setReadyCount] = useState(0);
|
|
2252
2302
|
const [tokenizeCount, setTokenizeCount] = useState(0);
|
|
2303
|
+
const [changeTick, setChangeTick] = useState(0);
|
|
2253
2304
|
const onLoadErrorRef = useRef(onLoadError);
|
|
2254
2305
|
onLoadErrorRef.current = onLoadError;
|
|
2255
2306
|
const onWaxRefreshRef = useRef(onSessionRefresh !== null && onSessionRefresh !== void 0 ? onSessionRefresh : onWaxRefresh);
|
|
@@ -2288,7 +2339,7 @@ function OzElements({ sessionUrl, getSessionKey, fetchWaxKey, pubKey, frameBaseU
|
|
|
2288
2339
|
if (loadErrorFired)
|
|
2289
2340
|
return;
|
|
2290
2341
|
loadErrorFired = true;
|
|
2291
|
-
(_a = onLoadErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onLoadErrorRef);
|
|
2342
|
+
(_a = onLoadErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onLoadErrorRef, { source: 'tokenizer' });
|
|
2292
2343
|
};
|
|
2293
2344
|
// AbortController passed to create() so that if this effect's cleanup runs
|
|
2294
2345
|
// while fetchWaxKey is still in-flight (React StrictMode double-invoke or
|
|
@@ -2372,7 +2423,8 @@ function OzElements({ sessionUrl, getSessionKey, fetchWaxKey, pubKey, frameBaseU
|
|
|
2372
2423
|
setReadyCount(n => Math.max(0, n - 1));
|
|
2373
2424
|
}, []);
|
|
2374
2425
|
const notifyTokenize = useCallback(() => setTokenizeCount(n => n + 1), []);
|
|
2375
|
-
const
|
|
2426
|
+
const notifyChange = useCallback(() => setChangeTick(n => n + 1), []);
|
|
2427
|
+
const value = useMemo(() => ({ vault, initError, notifyMount, notifyReady, notifyUnmount, notifyTokenize, notifyChange, mountedCount, readyCount, tokenizeCount, changeTick }), [vault, initError, notifyMount, notifyReady, notifyUnmount, notifyTokenize, notifyChange, mountedCount, readyCount, tokenizeCount, changeTick]);
|
|
2376
2428
|
return jsx(OzContext.Provider, { value: value, children: children });
|
|
2377
2429
|
}
|
|
2378
2430
|
/**
|
|
@@ -2380,28 +2432,53 @@ function OzElements({ sessionUrl, getSessionKey, fetchWaxKey, pubKey, frameBaseU
|
|
|
2380
2432
|
* an `<OzElements>` provider tree.
|
|
2381
2433
|
*/
|
|
2382
2434
|
function useOzElements() {
|
|
2383
|
-
|
|
2435
|
+
var _a, _b, _c;
|
|
2436
|
+
const { vault, initError, mountedCount, readyCount, notifyTokenize, notifyChange, tokenizeCount } = useContext(OzContext);
|
|
2384
2437
|
const createToken = useCallback(async (options) => {
|
|
2385
2438
|
if (!vault) {
|
|
2386
2439
|
return Promise.reject(new OzError('useOzElements must be called inside an <OzElements> provider.'));
|
|
2387
2440
|
}
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2441
|
+
// Start the call so vault._tokenizing flips synchronously, then notify so
|
|
2442
|
+
// `isTokenizing` re-renders as `true`. Notify again on settle so it returns
|
|
2443
|
+
// to `false`. (vault.isTokenizing is a plain getter — nothing else would
|
|
2444
|
+
// trigger a render while the call is in flight.)
|
|
2445
|
+
const promise = vault.createToken(options);
|
|
2446
|
+
notifyChange();
|
|
2447
|
+
try {
|
|
2448
|
+
const result = await promise;
|
|
2449
|
+
notifyTokenize();
|
|
2450
|
+
return result;
|
|
2451
|
+
}
|
|
2452
|
+
finally {
|
|
2453
|
+
notifyChange();
|
|
2454
|
+
}
|
|
2455
|
+
}, [vault, notifyTokenize, notifyChange]);
|
|
2392
2456
|
const createBankToken = useCallback(async (options) => {
|
|
2393
2457
|
if (!vault) {
|
|
2394
2458
|
return Promise.reject(new OzError('useOzElements must be called inside an <OzElements> provider.'));
|
|
2395
2459
|
}
|
|
2396
|
-
const
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2460
|
+
const promise = vault.createBankToken(options);
|
|
2461
|
+
notifyChange();
|
|
2462
|
+
try {
|
|
2463
|
+
const result = await promise;
|
|
2464
|
+
notifyTokenize();
|
|
2465
|
+
return result;
|
|
2466
|
+
}
|
|
2467
|
+
finally {
|
|
2468
|
+
notifyChange();
|
|
2469
|
+
}
|
|
2470
|
+
}, [vault, notifyTokenize, notifyChange]);
|
|
2400
2471
|
const reset = useCallback(() => {
|
|
2401
2472
|
vault === null || vault === void 0 ? void 0 : vault.reset();
|
|
2402
|
-
|
|
2473
|
+
// reset() clears completion state and cancels any in-flight tokenization, so
|
|
2474
|
+
// re-render to refresh the derived isComplete / isTokenizing getters below.
|
|
2475
|
+
notifyChange();
|
|
2476
|
+
}, [vault, notifyChange]);
|
|
2403
2477
|
const ready = vault !== null && vault.isReady && mountedCount > 0 && readyCount >= mountedCount;
|
|
2404
|
-
|
|
2478
|
+
const isComplete = (_a = vault === null || vault === void 0 ? void 0 : vault.isComplete) !== null && _a !== void 0 ? _a : false;
|
|
2479
|
+
const isBankComplete = (_b = vault === null || vault === void 0 ? void 0 : vault.isBankComplete) !== null && _b !== void 0 ? _b : false;
|
|
2480
|
+
const isTokenizing = (_c = vault === null || vault === void 0 ? void 0 : vault.isTokenizing) !== null && _c !== void 0 ? _c : false;
|
|
2481
|
+
return { createToken, createBankToken, reset, ready, initError, tokenizeCount, isComplete, isBankComplete, isTokenizing };
|
|
2405
2482
|
}
|
|
2406
2483
|
const SKELETON_STYLE = {
|
|
2407
2484
|
height: 46,
|
|
@@ -2436,7 +2513,7 @@ function OzFieldBase({ type, variant, style, placeholder, disabled, loadTimeoutM
|
|
|
2436
2513
|
const elementRef = useRef(null);
|
|
2437
2514
|
const [loaded, setLoaded] = useState(false);
|
|
2438
2515
|
const [loadError, setLoadError] = useState(null);
|
|
2439
|
-
const { vault, notifyMount, notifyReady, notifyUnmount } = useContext(OzContext);
|
|
2516
|
+
const { vault, notifyMount, notifyReady, notifyUnmount, notifyChange } = useContext(OzContext);
|
|
2440
2517
|
const onChangeRef = useRef(onChange);
|
|
2441
2518
|
const onFocusRef = useRef(onFocus);
|
|
2442
2519
|
const onBlurRef = useRef(onBlur);
|
|
@@ -2468,7 +2545,7 @@ function OzFieldBase({ type, variant, style, placeholder, disabled, loadTimeoutM
|
|
|
2468
2545
|
notifyReady();
|
|
2469
2546
|
(_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef);
|
|
2470
2547
|
});
|
|
2471
|
-
element.on('change', (e) => { var _a;
|
|
2548
|
+
element.on('change', (e) => { var _a; (_a = onChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onChangeRef, e); notifyChange(); });
|
|
2472
2549
|
element.on('focus', () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef); });
|
|
2473
2550
|
element.on('blur', () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef); });
|
|
2474
2551
|
element.on('loaderror', (e) => {
|
|
@@ -2701,4 +2778,3 @@ function OzBankCard({ style, styles, classNames, labels, labelStyle, labelClassN
|
|
|
2701
2778
|
}
|
|
2702
2779
|
|
|
2703
2780
|
export { OzBankAccountNumber, OzBankCard, OzBankRoutingNumber, OzCard, OzCardNumber, OzCvv, OzElements, OzExpiry, createSessionFetcher as createFetchWaxKey, createSessionFetcher, useOzElements };
|
|
2704
|
-
//# sourceMappingURL=index.esm.js.map
|
|
@@ -93,7 +93,9 @@ export interface OzElementsProps {
|
|
|
93
93
|
*/
|
|
94
94
|
fonts?: FontSource[];
|
|
95
95
|
/** Called if the tokenizer iframe fails to load within `loadTimeoutMs`. */
|
|
96
|
-
onLoadError?: (
|
|
96
|
+
onLoadError?: (info?: {
|
|
97
|
+
source: 'tokenizer';
|
|
98
|
+
}) => void;
|
|
97
99
|
/** How long to wait (ms) for the tokenizer iframe before calling `onLoadError`. Default: 10 000. */
|
|
98
100
|
loadTimeoutMs?: number;
|
|
99
101
|
/**
|
|
@@ -223,6 +225,32 @@ export interface UseOzElementsReturn {
|
|
|
223
225
|
* if (attemptsLeft === 1) <p>Last payment attempt available.</p>;
|
|
224
226
|
*/
|
|
225
227
|
tokenizeCount: number;
|
|
228
|
+
/**
|
|
229
|
+
* `true` when every mounted field has reported `complete && valid`.
|
|
230
|
+
* Use this to gate the pay button without wiring individual `onChange`
|
|
231
|
+
* listeners — reacts in real time as the customer fills in fields.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* const { ready, isComplete, createToken } = useOzElements();
|
|
235
|
+
* <button disabled={!ready || !isComplete} onClick={() => createToken()}>Pay</button>
|
|
236
|
+
*/
|
|
237
|
+
isComplete: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Like `isComplete`, but for bank-account fields (`OzBankCard` /
|
|
240
|
+
* `createBankElement`). Card and bank completion are tracked independently, so
|
|
241
|
+
* a card-only form isn't gated on bank fields and vice versa.
|
|
242
|
+
*/
|
|
243
|
+
isBankComplete: boolean;
|
|
244
|
+
/**
|
|
245
|
+
* `true` while `createToken()` or `createBankToken()` is in progress,
|
|
246
|
+
* including the transparent wax-key refresh phase. Use this to keep the
|
|
247
|
+
* pay button disabled and prevent double-submission.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* const { isTokenizing, createToken } = useOzElements();
|
|
251
|
+
* <button disabled={isTokenizing} onClick={() => createToken()}>Pay</button>
|
|
252
|
+
*/
|
|
253
|
+
isTokenizing: boolean;
|
|
226
254
|
}
|
|
227
255
|
/**
|
|
228
256
|
* Returns `createToken` and the `ready` flag. Must be called from inside
|
|
@@ -107,6 +107,39 @@ export declare class OzVault {
|
|
|
107
107
|
* payButton.textContent = remaining > 0 ? `Pay (${remaining} attempts left)` : 'Pay';
|
|
108
108
|
*/
|
|
109
109
|
get tokenizeCount(): number;
|
|
110
|
+
/**
|
|
111
|
+
* `true` when every mounted field has reported `complete && valid` via its
|
|
112
|
+
* last `change` event. `false` if no fields have been created, or if any
|
|
113
|
+
* field is incomplete or invalid.
|
|
114
|
+
*
|
|
115
|
+
* Use this to gate the pay button in vanilla JS integrations without having
|
|
116
|
+
* to wire up individual `change` event listeners:
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* vault.getElement('cardNumber')!.on('change', () => {
|
|
120
|
+
* payBtn.disabled = !vault.isComplete;
|
|
121
|
+
* });
|
|
122
|
+
*/
|
|
123
|
+
get isComplete(): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Like {@link isComplete}, but for bank-account elements created via
|
|
126
|
+
* {@link createBankElement}. Card and bank fields are tracked separately so a
|
|
127
|
+
* card-only checkout is never gated on bank fields (and vice versa), matching
|
|
128
|
+
* the `createToken()` / `createBankToken()` split. A vault with both card and
|
|
129
|
+
* bank elements exposes each completion state independently.
|
|
130
|
+
*/
|
|
131
|
+
get isBankComplete(): boolean;
|
|
132
|
+
/** True iff the set is non-empty and every element has reported complete-and-valid. */
|
|
133
|
+
private allComplete;
|
|
134
|
+
/**
|
|
135
|
+
* `true` while a `createToken()` or `createBankToken()` call is in progress
|
|
136
|
+
* (including the transparent wax-key refresh phase). Use this to keep the pay
|
|
137
|
+
* button disabled during tokenization to prevent double-submission.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* payBtn.disabled = vault.isTokenizing;
|
|
141
|
+
*/
|
|
142
|
+
get isTokenizing(): boolean;
|
|
110
143
|
/**
|
|
111
144
|
* Creates a new OzElement of the given type. Call `.mount(selector)` on the
|
|
112
145
|
* returned element to attach it to the DOM.
|
|
@@ -223,8 +223,14 @@ export interface VaultOptions {
|
|
|
223
223
|
/**
|
|
224
224
|
* Called if the tokenizer iframe fails to signal ready within `loadTimeoutMs`.
|
|
225
225
|
* Use this to show a fallback UI (e.g. "Unable to load payment fields").
|
|
226
|
+
*
|
|
227
|
+
* Receives an optional `info` object with a `source` field identifying which
|
|
228
|
+
* iframe timed out. Currently always `'tokenizer'` — element-level load errors
|
|
229
|
+
* fire the `loaderror` event on the individual element instead.
|
|
226
230
|
*/
|
|
227
|
-
onLoadError?: (
|
|
231
|
+
onLoadError?: (info?: {
|
|
232
|
+
source: 'tokenizer';
|
|
233
|
+
}) => void;
|
|
228
234
|
/** How long to wait (ms) for the tokenizer iframe before calling `onLoadError`. Default: 10 000.
|
|
229
235
|
* Only takes effect when `onLoadError` is also provided — setting this without `onLoadError` has no effect. */
|
|
230
236
|
loadTimeoutMs?: number;
|
|
@@ -350,10 +356,24 @@ export interface TokenizeOptions {
|
|
|
350
356
|
}
|
|
351
357
|
/** Options for `vault.createBankToken()`. */
|
|
352
358
|
export interface BankTokenizeOptions {
|
|
353
|
-
/**
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
359
|
+
/**
|
|
360
|
+
* Account holder first name.
|
|
361
|
+
* Required when `billing` is not provided.
|
|
362
|
+
* @deprecated Pass firstName inside `billing` instead.
|
|
363
|
+
*/
|
|
364
|
+
firstName?: string;
|
|
365
|
+
/**
|
|
366
|
+
* Account holder last name.
|
|
367
|
+
* Required when `billing` is not provided.
|
|
368
|
+
* @deprecated Pass lastName inside `billing` instead.
|
|
369
|
+
*/
|
|
370
|
+
lastName?: string;
|
|
371
|
+
/**
|
|
372
|
+
* Billing details for the account holder. When provided, `billing.firstName`
|
|
373
|
+
* and `billing.lastName` take precedence over the top-level fields.
|
|
374
|
+
* The normalized details are echoed back in `BankTokenResponse.billing`.
|
|
375
|
+
*/
|
|
376
|
+
billing?: BillingDetails;
|
|
357
377
|
}
|
|
358
378
|
/** Non-sensitive bank account metadata returned alongside the token. */
|
|
359
379
|
export interface BankAccountMetadata {
|
|
@@ -406,6 +426,11 @@ export interface BankTokenResponse {
|
|
|
406
426
|
token: string;
|
|
407
427
|
/** Non-sensitive bank account metadata. */
|
|
408
428
|
bank?: BankAccountMetadata;
|
|
429
|
+
/**
|
|
430
|
+
* Validated, normalized billing details — echoed back when billing was
|
|
431
|
+
* passed to createBankToken(). Ready to spread into your ACH processor request.
|
|
432
|
+
*/
|
|
433
|
+
billing?: BillingDetails;
|
|
409
434
|
}
|
|
410
435
|
/**
|
|
411
436
|
* Full request body for the Ozura Pay API cardSale endpoint.
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
import { type Ref, type PropType, type ComputedRef } from 'vue';
|
|
27
|
-
import type { TokenizeOptions, TokenResponse, BankTokenizeOptions, BankTokenResponse, FontSource, Appearance } from '../types';
|
|
27
|
+
import type { ElementOptions, TokenizeOptions, TokenResponse, BankTokenizeOptions, BankTokenResponse, FontSource, Appearance } from '../types';
|
|
28
28
|
export interface OzElementsProps {
|
|
29
29
|
/** Omit when using a test vault key from a Test project at ozuravault.com.
|
|
30
30
|
* Required for production vault keys. */
|
|
@@ -40,6 +40,14 @@ export interface OzElementsProps {
|
|
|
40
40
|
onSessionRefresh?: () => void;
|
|
41
41
|
/** Called once when the vault tokenizer and all mounted field iframes are ready. */
|
|
42
42
|
onReady?: () => void;
|
|
43
|
+
/**
|
|
44
|
+
* Called if the tokenizer iframe fails to signal ready within `loadTimeoutMs`.
|
|
45
|
+
* Use this to show a fallback UI (e.g. "Payment fields failed to load").
|
|
46
|
+
* Receives an optional info object with `source: 'tokenizer'`.
|
|
47
|
+
*/
|
|
48
|
+
onLoadError?: (info?: {
|
|
49
|
+
source: 'tokenizer';
|
|
50
|
+
}) => void;
|
|
43
51
|
/**
|
|
44
52
|
* Maximum number of tokenize calls before the vault proactively refreshes the session.
|
|
45
53
|
* Must match the `sessionLimit` passed to `createSession()` on your server.
|
|
@@ -94,6 +102,12 @@ export declare const OzElements: import("vue").DefineComponent<import("vue").Ext
|
|
|
94
102
|
type: PropType<() => void>;
|
|
95
103
|
default: undefined;
|
|
96
104
|
};
|
|
105
|
+
onLoadError: {
|
|
106
|
+
type: PropType<(info?: {
|
|
107
|
+
source: "tokenizer";
|
|
108
|
+
}) => void>;
|
|
109
|
+
default: undefined;
|
|
110
|
+
};
|
|
97
111
|
sessionLimit: {
|
|
98
112
|
type: PropType<number | null>;
|
|
99
113
|
default: undefined;
|
|
@@ -145,6 +159,12 @@ export declare const OzElements: import("vue").DefineComponent<import("vue").Ext
|
|
|
145
159
|
type: PropType<() => void>;
|
|
146
160
|
default: undefined;
|
|
147
161
|
};
|
|
162
|
+
onLoadError: {
|
|
163
|
+
type: PropType<(info?: {
|
|
164
|
+
source: "tokenizer";
|
|
165
|
+
}) => void>;
|
|
166
|
+
default: undefined;
|
|
167
|
+
};
|
|
148
168
|
sessionLimit: {
|
|
149
169
|
type: PropType<number | null>;
|
|
150
170
|
default: undefined;
|
|
@@ -164,6 +184,9 @@ export declare const OzElements: import("vue").DefineComponent<import("vue").Ext
|
|
|
164
184
|
maxTokenizeCalls: number;
|
|
165
185
|
sessionUrl: string;
|
|
166
186
|
getSessionKey: (sessionId: string) => Promise<string>;
|
|
187
|
+
onLoadError: (info?: {
|
|
188
|
+
source: "tokenizer";
|
|
189
|
+
}) => void;
|
|
167
190
|
onSessionRefresh: () => void;
|
|
168
191
|
onReady: () => void;
|
|
169
192
|
appearance: Appearance;
|
|
@@ -196,6 +219,32 @@ export interface UseOzElementsReturn {
|
|
|
196
219
|
* Clears all mounted element fields without destroying the vault.
|
|
197
220
|
*/
|
|
198
221
|
reset: () => void;
|
|
222
|
+
/**
|
|
223
|
+
* `true` when every mounted field has reported `complete && valid`.
|
|
224
|
+
* Use this to gate the pay button without wiring individual `@change`
|
|
225
|
+
* listeners — reacts in real time as the customer fills in fields.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* const { ready, isComplete, createToken } = useOzElements();
|
|
229
|
+
* // <button :disabled="!ready || !isComplete" @click="createToken()">Pay</button>
|
|
230
|
+
*/
|
|
231
|
+
isComplete: ComputedRef<boolean>;
|
|
232
|
+
/**
|
|
233
|
+
* Like `isComplete`, but for bank-account fields (`createBankElement`). Card
|
|
234
|
+
* and bank completion are tracked independently, so a card-only form isn't
|
|
235
|
+
* gated on bank fields and vice versa.
|
|
236
|
+
*/
|
|
237
|
+
isBankComplete: ComputedRef<boolean>;
|
|
238
|
+
/**
|
|
239
|
+
* `true` while `createToken()` or `createBankToken()` is in progress,
|
|
240
|
+
* including the transparent wax-key refresh phase. Use this to keep the
|
|
241
|
+
* pay button disabled and prevent double-submission.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* const { isTokenizing, createToken } = useOzElements();
|
|
245
|
+
* // <button :disabled="isTokenizing" @click="createToken()">Pay</button>
|
|
246
|
+
*/
|
|
247
|
+
isTokenizing: ComputedRef<boolean>;
|
|
199
248
|
}
|
|
200
249
|
/**
|
|
201
250
|
* Returns createToken, createBankToken, ready, initError, tokenizeCount, and reset.
|
|
@@ -204,6 +253,12 @@ export interface UseOzElementsReturn {
|
|
|
204
253
|
* @throws {Error} if called outside an <OzElements> provider
|
|
205
254
|
*/
|
|
206
255
|
export declare function useOzElements(): UseOzElementsReturn;
|
|
256
|
+
/** Props accepted by all individual field components (OzCardNumber, OzExpiry, OzCvv, etc.). */
|
|
257
|
+
export interface OzFieldProps {
|
|
258
|
+
placeholder?: string;
|
|
259
|
+
disabled?: boolean;
|
|
260
|
+
style?: ElementOptions['style'];
|
|
261
|
+
}
|
|
207
262
|
/** Card number field. Emits `change` (ElementChangeEvent), `focus`, `blur`. */
|
|
208
263
|
export declare const OzCardNumber: import("vue").DefineComponent<{
|
|
209
264
|
placeholder?: string | undefined;
|
|
@@ -107,6 +107,39 @@ export declare class OzVault {
|
|
|
107
107
|
* payButton.textContent = remaining > 0 ? `Pay (${remaining} attempts left)` : 'Pay';
|
|
108
108
|
*/
|
|
109
109
|
get tokenizeCount(): number;
|
|
110
|
+
/**
|
|
111
|
+
* `true` when every mounted field has reported `complete && valid` via its
|
|
112
|
+
* last `change` event. `false` if no fields have been created, or if any
|
|
113
|
+
* field is incomplete or invalid.
|
|
114
|
+
*
|
|
115
|
+
* Use this to gate the pay button in vanilla JS integrations without having
|
|
116
|
+
* to wire up individual `change` event listeners:
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* vault.getElement('cardNumber')!.on('change', () => {
|
|
120
|
+
* payBtn.disabled = !vault.isComplete;
|
|
121
|
+
* });
|
|
122
|
+
*/
|
|
123
|
+
get isComplete(): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Like {@link isComplete}, but for bank-account elements created via
|
|
126
|
+
* {@link createBankElement}. Card and bank fields are tracked separately so a
|
|
127
|
+
* card-only checkout is never gated on bank fields (and vice versa), matching
|
|
128
|
+
* the `createToken()` / `createBankToken()` split. A vault with both card and
|
|
129
|
+
* bank elements exposes each completion state independently.
|
|
130
|
+
*/
|
|
131
|
+
get isBankComplete(): boolean;
|
|
132
|
+
/** True iff the set is non-empty and every element has reported complete-and-valid. */
|
|
133
|
+
private allComplete;
|
|
134
|
+
/**
|
|
135
|
+
* `true` while a `createToken()` or `createBankToken()` call is in progress
|
|
136
|
+
* (including the transparent wax-key refresh phase). Use this to keep the pay
|
|
137
|
+
* button disabled during tokenization to prevent double-submission.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* payBtn.disabled = vault.isTokenizing;
|
|
141
|
+
*/
|
|
142
|
+
get isTokenizing(): boolean;
|
|
110
143
|
/**
|
|
111
144
|
* Creates a new OzElement of the given type. Call `.mount(selector)` on the
|
|
112
145
|
* returned element to attach it to the DOM.
|
|
@@ -223,8 +223,14 @@ export interface VaultOptions {
|
|
|
223
223
|
/**
|
|
224
224
|
* Called if the tokenizer iframe fails to signal ready within `loadTimeoutMs`.
|
|
225
225
|
* Use this to show a fallback UI (e.g. "Unable to load payment fields").
|
|
226
|
+
*
|
|
227
|
+
* Receives an optional `info` object with a `source` field identifying which
|
|
228
|
+
* iframe timed out. Currently always `'tokenizer'` — element-level load errors
|
|
229
|
+
* fire the `loaderror` event on the individual element instead.
|
|
226
230
|
*/
|
|
227
|
-
onLoadError?: (
|
|
231
|
+
onLoadError?: (info?: {
|
|
232
|
+
source: 'tokenizer';
|
|
233
|
+
}) => void;
|
|
228
234
|
/** How long to wait (ms) for the tokenizer iframe before calling `onLoadError`. Default: 10 000.
|
|
229
235
|
* Only takes effect when `onLoadError` is also provided — setting this without `onLoadError` has no effect. */
|
|
230
236
|
loadTimeoutMs?: number;
|
|
@@ -350,10 +356,24 @@ export interface TokenizeOptions {
|
|
|
350
356
|
}
|
|
351
357
|
/** Options for `vault.createBankToken()`. */
|
|
352
358
|
export interface BankTokenizeOptions {
|
|
353
|
-
/**
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
359
|
+
/**
|
|
360
|
+
* Account holder first name.
|
|
361
|
+
* Required when `billing` is not provided.
|
|
362
|
+
* @deprecated Pass firstName inside `billing` instead.
|
|
363
|
+
*/
|
|
364
|
+
firstName?: string;
|
|
365
|
+
/**
|
|
366
|
+
* Account holder last name.
|
|
367
|
+
* Required when `billing` is not provided.
|
|
368
|
+
* @deprecated Pass lastName inside `billing` instead.
|
|
369
|
+
*/
|
|
370
|
+
lastName?: string;
|
|
371
|
+
/**
|
|
372
|
+
* Billing details for the account holder. When provided, `billing.firstName`
|
|
373
|
+
* and `billing.lastName` take precedence over the top-level fields.
|
|
374
|
+
* The normalized details are echoed back in `BankTokenResponse.billing`.
|
|
375
|
+
*/
|
|
376
|
+
billing?: BillingDetails;
|
|
357
377
|
}
|
|
358
378
|
/** Non-sensitive bank account metadata returned alongside the token. */
|
|
359
379
|
export interface BankAccountMetadata {
|
|
@@ -406,6 +426,11 @@ export interface BankTokenResponse {
|
|
|
406
426
|
token: string;
|
|
407
427
|
/** Non-sensitive bank account metadata. */
|
|
408
428
|
bank?: BankAccountMetadata;
|
|
429
|
+
/**
|
|
430
|
+
* Validated, normalized billing details — echoed back when billing was
|
|
431
|
+
* passed to createBankToken(). Ready to spread into your ACH processor request.
|
|
432
|
+
*/
|
|
433
|
+
billing?: BillingDetails;
|
|
409
434
|
}
|
|
410
435
|
/**
|
|
411
436
|
* Full request body for the Ozura Pay API cardSale endpoint.
|