@ozura/elements 1.1.0 → 1.2.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/README.md +1340 -1338
- package/dist/frame/element-frame.html +22 -22
- package/dist/frame/element-frame.js +13 -2
- package/dist/frame/element-frame.js.map +1 -1
- package/dist/frame/tokenizer-frame.html +11 -11
- package/dist/oz-elements.esm.js +262 -243
- package/dist/oz-elements.esm.js.map +1 -1
- package/dist/oz-elements.umd.js +263 -243
- package/dist/oz-elements.umd.js.map +1 -1
- package/dist/react/index.cjs.js +138 -112
- package/dist/react/index.cjs.js.map +1 -1
- package/dist/react/index.esm.js +137 -112
- package/dist/react/index.esm.js.map +1 -1
- package/dist/react/react/index.d.ts +50 -29
- package/dist/react/sdk/OzVault.d.ts +6 -5
- package/dist/react/sdk/createSessionFetcher.d.ts +29 -0
- package/dist/react/sdk/index.d.ts +6 -26
- package/dist/react/server/index.d.ts +126 -74
- package/dist/react/types/index.d.ts +70 -41
- package/dist/server/index.cjs.js +186 -88
- package/dist/server/index.cjs.js.map +1 -1
- package/dist/server/index.esm.js +185 -89
- package/dist/server/index.esm.js.map +1 -1
- package/dist/server/sdk/OzVault.d.ts +6 -5
- package/dist/server/sdk/createSessionFetcher.d.ts +29 -0
- package/dist/server/sdk/index.d.ts +6 -26
- package/dist/server/server/index.d.ts +126 -74
- package/dist/server/types/index.d.ts +70 -41
- package/dist/types/sdk/OzVault.d.ts +6 -5
- package/dist/types/sdk/createSessionFetcher.d.ts +29 -0
- package/dist/types/sdk/index.d.ts +6 -26
- package/dist/types/server/index.d.ts +126 -74
- package/dist/types/types/index.d.ts +70 -41
- package/package.json +1 -1
package/dist/react/index.esm.js
CHANGED
|
@@ -838,6 +838,85 @@ function validateBilling(billing) {
|
|
|
838
838
|
*/
|
|
839
839
|
const PROTOCOL_VERSION = 1;
|
|
840
840
|
|
|
841
|
+
/**
|
|
842
|
+
* Creates a `getSessionKey` callback for `OzVault.create()` and `<OzElements>`.
|
|
843
|
+
*
|
|
844
|
+
* This is the recommended way to wire the SDK to your backend session endpoint.
|
|
845
|
+
* If you don't need custom headers or auth logic, pass `sessionUrl` directly to
|
|
846
|
+
* `OzVault.create()` or `<OzElements>` — it calls this helper internally.
|
|
847
|
+
*
|
|
848
|
+
* The callback POSTs `{ sessionId }` to `url` and reads `sessionKey` (or the
|
|
849
|
+
* legacy `waxKey`) from the JSON response, so it is compatible with both the
|
|
850
|
+
* new `createSessionMiddleware` and the old `createMintWaxMiddleware` backends.
|
|
851
|
+
*
|
|
852
|
+
* Each call enforces a **10-second timeout**. On pure network failures
|
|
853
|
+
* (offline, DNS, connection refused) the request is retried **once after 750ms**.
|
|
854
|
+
* HTTP 4xx/5xx errors are never retried — they indicate misconfiguration.
|
|
855
|
+
*
|
|
856
|
+
* @param url - Absolute or relative URL of your session endpoint, e.g. `'/api/oz-session'`.
|
|
857
|
+
*
|
|
858
|
+
* @example
|
|
859
|
+
* // Simplest — just pass sessionUrl, no need to call this directly
|
|
860
|
+
* const vault = await OzVault.create({ pubKey: 'pk_live_...', sessionUrl: '/api/oz-session' });
|
|
861
|
+
*
|
|
862
|
+
* @example
|
|
863
|
+
* // Manual — use when you need custom headers
|
|
864
|
+
* const vault = await OzVault.create({
|
|
865
|
+
* pubKey: 'pk_live_...',
|
|
866
|
+
* getSessionKey: createSessionFetcher('/api/oz-session'),
|
|
867
|
+
* });
|
|
868
|
+
*/
|
|
869
|
+
function createSessionFetcher(url) {
|
|
870
|
+
const TIMEOUT_MS = 10000;
|
|
871
|
+
// Each attempt gets its own AbortController so a timeout on attempt 1 does
|
|
872
|
+
// not bleed into the retry.
|
|
873
|
+
const attemptFetch = (sessionId) => {
|
|
874
|
+
const controller = new AbortController();
|
|
875
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
876
|
+
return fetch(url, {
|
|
877
|
+
method: 'POST',
|
|
878
|
+
headers: { 'Content-Type': 'application/json' },
|
|
879
|
+
body: JSON.stringify({ sessionId }),
|
|
880
|
+
signal: controller.signal,
|
|
881
|
+
}).finally(() => clearTimeout(timer));
|
|
882
|
+
};
|
|
883
|
+
return async (sessionId) => {
|
|
884
|
+
let res;
|
|
885
|
+
try {
|
|
886
|
+
res = await attemptFetch(sessionId);
|
|
887
|
+
}
|
|
888
|
+
catch (firstErr) {
|
|
889
|
+
// Timeout/abort — don't retry, we already waited the full duration.
|
|
890
|
+
if (firstErr instanceof Error && (firstErr.name === 'AbortError' || firstErr.name === 'TimeoutError')) {
|
|
891
|
+
throw new OzError(`Session endpoint timed out after ${TIMEOUT_MS / 1000}s (${url})`, undefined, 'timeout');
|
|
892
|
+
}
|
|
893
|
+
// Pure network error — retry once after a short pause.
|
|
894
|
+
await new Promise(resolve => setTimeout(resolve, 750));
|
|
895
|
+
try {
|
|
896
|
+
res = await attemptFetch(sessionId);
|
|
897
|
+
}
|
|
898
|
+
catch (retryErr) {
|
|
899
|
+
const msg = retryErr instanceof Error ? retryErr.message : 'Network error';
|
|
900
|
+
throw new OzError(`Could not reach session endpoint (${url}): ${msg}`, undefined, 'network');
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
const data = await res.json().catch(() => ({}));
|
|
904
|
+
if (!res.ok) {
|
|
905
|
+
throw new OzError(typeof data.error === 'string' && data.error
|
|
906
|
+
? data.error
|
|
907
|
+
: `Session endpoint returned HTTP ${res.status}`, undefined, res.status >= 500 ? 'server' : res.status === 401 || res.status === 403 ? 'auth' : 'validation');
|
|
908
|
+
}
|
|
909
|
+
// Accept both new `sessionKey` and legacy `waxKey` for backward compatibility
|
|
910
|
+
// with backends that haven't migrated to createSessionMiddleware yet.
|
|
911
|
+
const key = (typeof data.sessionKey === 'string' ? data.sessionKey : '') ||
|
|
912
|
+
(typeof data.waxKey === 'string' ? data.waxKey : '');
|
|
913
|
+
if (!key.trim()) {
|
|
914
|
+
throw new OzError('Session endpoint response is missing sessionKey. Check your /api/oz-session implementation.', undefined, 'validation');
|
|
915
|
+
}
|
|
916
|
+
return key;
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
|
|
841
920
|
function isCardMetadata(v) {
|
|
842
921
|
return !!v && typeof v === 'object' && typeof v.last4 === 'string';
|
|
843
922
|
}
|
|
@@ -877,7 +956,7 @@ class OzVault {
|
|
|
877
956
|
* @internal
|
|
878
957
|
*/
|
|
879
958
|
constructor(options, waxKey, tokenizationSessionId) {
|
|
880
|
-
var _a, _b, _c, _d;
|
|
959
|
+
var _a, _b, _c, _d, _e;
|
|
881
960
|
this.elements = new Map();
|
|
882
961
|
this.elementsByType = new Map();
|
|
883
962
|
this.bankElementsByType = new Map();
|
|
@@ -911,7 +990,12 @@ class OzVault {
|
|
|
911
990
|
this.fonts = (_a = options.fonts) !== null && _a !== void 0 ? _a : [];
|
|
912
991
|
this.resolvedAppearance = resolveAppearance(options.appearance);
|
|
913
992
|
this.vaultId = `vault-${uuid()}`;
|
|
914
|
-
|
|
993
|
+
// sessionLimit takes precedence over legacy maxTokenizeCalls.
|
|
994
|
+
// null means unlimited — use Infinity so the ">=" check never triggers.
|
|
995
|
+
const rawLimit = options.sessionLimit !== undefined
|
|
996
|
+
? options.sessionLimit
|
|
997
|
+
: ((_b = options.maxTokenizeCalls) !== null && _b !== void 0 ? _b : 3);
|
|
998
|
+
this._maxTokenizeCalls = rawLimit === null ? Infinity : rawLimit;
|
|
915
999
|
this._debug = (_c = options.debug) !== null && _c !== void 0 ? _c : false;
|
|
916
1000
|
this.boundHandleMessage = this.handleMessage.bind(this);
|
|
917
1001
|
window.addEventListener('message', this.boundHandleMessage);
|
|
@@ -927,7 +1011,8 @@ class OzVault {
|
|
|
927
1011
|
}
|
|
928
1012
|
}, timeout);
|
|
929
1013
|
}
|
|
930
|
-
|
|
1014
|
+
// onSessionRefresh takes precedence over legacy onWaxRefresh
|
|
1015
|
+
this._onWaxRefresh = (_e = options.onSessionRefresh) !== null && _e !== void 0 ? _e : options.onWaxRefresh;
|
|
931
1016
|
this._onReady = options.onReady;
|
|
932
1017
|
this.log('vault created', { vaultId: this.vaultId, frameBaseUrl: this.frameBaseUrl, maxTokenizeCalls: this._maxTokenizeCalls });
|
|
933
1018
|
}
|
|
@@ -935,51 +1020,63 @@ class OzVault {
|
|
|
935
1020
|
* Creates and returns a ready `OzVault` instance.
|
|
936
1021
|
*
|
|
937
1022
|
* Internally this:
|
|
938
|
-
* 1. Generates a
|
|
1023
|
+
* 1. Generates a session UUID.
|
|
939
1024
|
* 2. Starts loading the hidden tokenizer iframe immediately.
|
|
940
|
-
* 3.
|
|
941
|
-
*
|
|
942
|
-
*
|
|
1025
|
+
* 3. Fetches a session key from your backend concurrently — either via
|
|
1026
|
+
* `sessionUrl` (simplest), `getSessionKey` (custom headers/auth), or the
|
|
1027
|
+
* deprecated `fetchWaxKey` callback.
|
|
1028
|
+
* 4. Resolves with the vault instance once the session key is stored. The iframe
|
|
943
1029
|
* has been loading the whole time, so `isReady` may already be true or
|
|
944
1030
|
* will fire shortly after.
|
|
945
1031
|
*
|
|
946
1032
|
* The returned vault is ready to create elements immediately. `createToken()`
|
|
947
1033
|
* additionally requires `vault.isReady` (tokenizer iframe loaded).
|
|
948
1034
|
*
|
|
949
|
-
* @throws {OzError} if
|
|
1035
|
+
* @throws {OzError} if the session fetch fails, times out, or returns an empty string.
|
|
950
1036
|
*/
|
|
951
1037
|
static async create(options, signal) {
|
|
952
1038
|
if (!options.pubKey || !options.pubKey.trim()) {
|
|
953
1039
|
throw new OzError('pubKey is required in options. Obtain your public key from the Ozura admin.');
|
|
954
1040
|
}
|
|
955
|
-
|
|
956
|
-
|
|
1041
|
+
// Normalize the session callback. Priority: sessionUrl > getSessionKey > fetchWaxKey (deprecated).
|
|
1042
|
+
// This allows merchants to use the clean new API without touching legacy code.
|
|
1043
|
+
let resolvedFetchKey;
|
|
1044
|
+
if (options.sessionUrl) {
|
|
1045
|
+
resolvedFetchKey = createSessionFetcher(options.sessionUrl);
|
|
1046
|
+
}
|
|
1047
|
+
else if (typeof options.getSessionKey === 'function') {
|
|
1048
|
+
resolvedFetchKey = options.getSessionKey;
|
|
1049
|
+
}
|
|
1050
|
+
else if (typeof options.fetchWaxKey === 'function') {
|
|
1051
|
+
resolvedFetchKey = options.fetchWaxKey;
|
|
1052
|
+
}
|
|
1053
|
+
else {
|
|
1054
|
+
throw new OzError('A session URL or callback is required. Pass sessionUrl, getSessionKey, or fetchWaxKey to OzVault.create().');
|
|
957
1055
|
}
|
|
958
1056
|
const tokenizationSessionId = uuid();
|
|
959
1057
|
// Construct the vault immediately — this mounts the tokenizer iframe so it
|
|
960
|
-
// starts loading while
|
|
961
|
-
// empty and is set below before create() returns.
|
|
1058
|
+
// starts loading while the session fetch is in flight.
|
|
962
1059
|
const vault = new OzVault(options, '', tokenizationSessionId);
|
|
963
1060
|
// If the caller provides an AbortSignal (e.g. React useEffect cleanup),
|
|
964
1061
|
// destroy the vault immediately on abort so the tokenizer iframe and message
|
|
965
|
-
// listener are removed synchronously rather than waiting for
|
|
966
|
-
// settle. This eliminates the brief double-iframe window in React StrictMode.
|
|
1062
|
+
// listener are removed synchronously rather than waiting for the session fetch
|
|
1063
|
+
// to settle. This eliminates the brief double-iframe window in React StrictMode.
|
|
967
1064
|
const onAbort = () => vault.destroy();
|
|
968
1065
|
signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
|
|
969
1066
|
let waxKey;
|
|
970
1067
|
try {
|
|
971
|
-
waxKey = await
|
|
1068
|
+
waxKey = await resolvedFetchKey(tokenizationSessionId);
|
|
972
1069
|
}
|
|
973
1070
|
catch (err) {
|
|
974
1071
|
signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
|
|
975
1072
|
vault.destroy();
|
|
976
1073
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
977
1074
|
throw new OzError('OzVault.create() was cancelled.');
|
|
978
|
-
// Preserve errorCode/retryable from OzError (e.g. timeout/network from
|
|
1075
|
+
// Preserve errorCode/retryable from OzError (e.g. timeout/network from createSessionFetcher)
|
|
979
1076
|
// so callers can distinguish transient failures from config errors.
|
|
980
1077
|
const originalCode = err instanceof OzError ? err.errorCode : undefined;
|
|
981
1078
|
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
982
|
-
throw new OzError(`
|
|
1079
|
+
throw new OzError(`Session fetch threw an error: ${msg}`, undefined, originalCode);
|
|
983
1080
|
}
|
|
984
1081
|
signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
|
|
985
1082
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
@@ -988,11 +1085,11 @@ class OzVault {
|
|
|
988
1085
|
}
|
|
989
1086
|
if (typeof waxKey !== 'string' || !waxKey.trim()) {
|
|
990
1087
|
vault.destroy();
|
|
991
|
-
throw new OzError('
|
|
1088
|
+
throw new OzError('Session fetch returned an empty key. Check your session endpoint response — it must return { sessionKey: "..." }.');
|
|
992
1089
|
}
|
|
993
1090
|
// Static methods can access private fields of instances of the same class.
|
|
994
1091
|
vault.waxKey = waxKey;
|
|
995
|
-
vault._storedFetchWaxKey =
|
|
1092
|
+
vault._storedFetchWaxKey = resolvedFetchKey;
|
|
996
1093
|
// If the tokenizer iframe fired OZ_FRAME_READY before fetchWaxKey resolved,
|
|
997
1094
|
// the OZ_INIT sent at that point had an empty waxKey. Send a follow-up now
|
|
998
1095
|
// so the tokenizer has the key stored before any createToken() call.
|
|
@@ -1658,9 +1755,9 @@ class OzVault {
|
|
|
1658
1755
|
// key without waiting for a vault rejection.
|
|
1659
1756
|
this._tokenizeSuccessCount++;
|
|
1660
1757
|
if (this._tokenizeSuccessCount >= this._maxTokenizeCalls) {
|
|
1661
|
-
this.log('proactive
|
|
1758
|
+
this.log('proactive session key refresh triggered', { tokenizeSuccessCount: this._tokenizeSuccessCount, maxTokenizeCalls: this._maxTokenizeCalls });
|
|
1662
1759
|
this.refreshWaxKey().catch((err) => {
|
|
1663
|
-
console.warn('[OzVault] Post-budget
|
|
1760
|
+
console.warn('[OzVault] Post-budget session key refresh failed:', err instanceof Error ? err.message : err);
|
|
1664
1761
|
});
|
|
1665
1762
|
}
|
|
1666
1763
|
}
|
|
@@ -1818,9 +1915,9 @@ class OzVault {
|
|
|
1818
1915
|
// Same proactive refresh logic as card tokenization.
|
|
1819
1916
|
this._tokenizeSuccessCount++;
|
|
1820
1917
|
if (this._tokenizeSuccessCount >= this._maxTokenizeCalls) {
|
|
1821
|
-
this.log('proactive
|
|
1918
|
+
this.log('proactive session key refresh triggered', { tokenizeSuccessCount: this._tokenizeSuccessCount, maxTokenizeCalls: this._maxTokenizeCalls });
|
|
1822
1919
|
this.refreshWaxKey().catch((err) => {
|
|
1823
|
-
console.warn('[OzVault] Post-budget
|
|
1920
|
+
console.warn('[OzVault] Post-budget session key refresh failed:', err instanceof Error ? err.message : err);
|
|
1824
1921
|
});
|
|
1825
1922
|
}
|
|
1826
1923
|
}
|
|
@@ -1906,84 +2003,6 @@ class OzVault {
|
|
|
1906
2003
|
}
|
|
1907
2004
|
}
|
|
1908
2005
|
|
|
1909
|
-
/**
|
|
1910
|
-
* Creates a ready-to-use `fetchWaxKey` callback for `OzVault.create()` and `<OzElements>`.
|
|
1911
|
-
*
|
|
1912
|
-
* Calls your backend mint endpoint with `{ sessionId }` and returns the wax key string.
|
|
1913
|
-
* Throws on non-OK responses or a missing `waxKey` field so the vault can surface the
|
|
1914
|
-
* error through its normal error path.
|
|
1915
|
-
*
|
|
1916
|
-
* Each call enforces a 10-second per-attempt timeout. On a pure network-level
|
|
1917
|
-
* failure (connection refused, DNS failure, etc.) the call is retried once after
|
|
1918
|
-
* 750ms before throwing. HTTP errors (4xx/5xx) are never retried — they indicate
|
|
1919
|
-
* an endpoint misconfiguration or an invalid key, not a transient failure.
|
|
1920
|
-
*
|
|
1921
|
-
* The mint endpoint is typically the one-line `createMintWaxHandler` / `createMintWaxMiddleware`
|
|
1922
|
-
* from `@ozura/elements/server`.
|
|
1923
|
-
*
|
|
1924
|
-
* @param mintUrl - Absolute or relative URL of your wax-key mint endpoint, e.g. `'/api/mint-wax'`.
|
|
1925
|
-
*
|
|
1926
|
-
* @example
|
|
1927
|
-
* // Vanilla JS
|
|
1928
|
-
* const vault = await OzVault.create({
|
|
1929
|
-
* pubKey: 'pk_live_...',
|
|
1930
|
-
* fetchWaxKey: createFetchWaxKey('/api/mint-wax'),
|
|
1931
|
-
* });
|
|
1932
|
-
*
|
|
1933
|
-
* @example
|
|
1934
|
-
* // React
|
|
1935
|
-
* <OzElements pubKey="pk_live_..." fetchWaxKey={createFetchWaxKey('/api/mint-wax')}>
|
|
1936
|
-
*/
|
|
1937
|
-
function createFetchWaxKey(mintUrl) {
|
|
1938
|
-
const TIMEOUT_MS = 10000;
|
|
1939
|
-
// Each attempt gets its own AbortController so a timeout on attempt 1 does
|
|
1940
|
-
// not bleed into the retry. Uses AbortController + setTimeout instead of
|
|
1941
|
-
// AbortSignal.timeout() to support environments without that API.
|
|
1942
|
-
const attemptFetch = (sessionId) => {
|
|
1943
|
-
const controller = new AbortController();
|
|
1944
|
-
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
1945
|
-
return fetch(mintUrl, {
|
|
1946
|
-
method: 'POST',
|
|
1947
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1948
|
-
body: JSON.stringify({ sessionId }),
|
|
1949
|
-
signal: controller.signal,
|
|
1950
|
-
}).finally(() => clearTimeout(timer));
|
|
1951
|
-
};
|
|
1952
|
-
return async (sessionId) => {
|
|
1953
|
-
let res;
|
|
1954
|
-
try {
|
|
1955
|
-
res = await attemptFetch(sessionId);
|
|
1956
|
-
}
|
|
1957
|
-
catch (firstErr) {
|
|
1958
|
-
// Abort/timeout should not be retried — the server received nothing or
|
|
1959
|
-
// we already waited the full timeout duration.
|
|
1960
|
-
if (firstErr instanceof Error && (firstErr.name === 'AbortError' || firstErr.name === 'TimeoutError')) {
|
|
1961
|
-
throw new OzError(`Wax key mint timed out after ${TIMEOUT_MS / 1000}s (${mintUrl})`, undefined, 'timeout');
|
|
1962
|
-
}
|
|
1963
|
-
// Pure network error (offline, DNS, connection refused) — retry once
|
|
1964
|
-
// after a short pause in case of a transient blip.
|
|
1965
|
-
await new Promise(resolve => setTimeout(resolve, 750));
|
|
1966
|
-
try {
|
|
1967
|
-
res = await attemptFetch(sessionId);
|
|
1968
|
-
}
|
|
1969
|
-
catch (retryErr) {
|
|
1970
|
-
const msg = retryErr instanceof Error ? retryErr.message : 'Network error';
|
|
1971
|
-
throw new OzError(`Could not reach wax key mint endpoint (${mintUrl}): ${msg}`, undefined, 'network');
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
const data = await res.json().catch(() => ({}));
|
|
1975
|
-
if (!res.ok) {
|
|
1976
|
-
throw new OzError(typeof data.error === 'string' && data.error
|
|
1977
|
-
? data.error
|
|
1978
|
-
: `Wax key mint failed (HTTP ${res.status})`, undefined, res.status >= 500 ? 'server' : res.status === 401 || res.status === 403 ? 'auth' : 'validation');
|
|
1979
|
-
}
|
|
1980
|
-
if (typeof data.waxKey !== 'string' || !data.waxKey.trim()) {
|
|
1981
|
-
throw new OzError('Mint endpoint response is missing waxKey. Check your /api/mint-wax implementation.', undefined, 'validation');
|
|
1982
|
-
}
|
|
1983
|
-
return data.waxKey;
|
|
1984
|
-
};
|
|
1985
|
-
}
|
|
1986
|
-
|
|
1987
2006
|
const OzContext = createContext({
|
|
1988
2007
|
vault: null,
|
|
1989
2008
|
initError: null,
|
|
@@ -2000,7 +2019,7 @@ const OzContext = createContext({
|
|
|
2000
2019
|
* All `<OzCardNumber />`, `<OzExpiry />`, and `<OzCvv />` children must be
|
|
2001
2020
|
* rendered inside this provider.
|
|
2002
2021
|
*/
|
|
2003
|
-
function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loadTimeoutMs, onWaxRefresh, onReady, appearance, maxTokenizeCalls, debug, children }) {
|
|
2022
|
+
function OzElements({ sessionUrl, getSessionKey, fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loadTimeoutMs, onSessionRefresh, onWaxRefresh, onReady, appearance, sessionLimit, maxTokenizeCalls, debug, children }) {
|
|
2004
2023
|
const [vault, setVault] = useState(null);
|
|
2005
2024
|
const [initError, setInitError] = useState(null);
|
|
2006
2025
|
const [mountedCount, setMountedCount] = useState(0);
|
|
@@ -2008,13 +2027,14 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
|
|
|
2008
2027
|
const [tokenizeCount, setTokenizeCount] = useState(0);
|
|
2009
2028
|
const onLoadErrorRef = useRef(onLoadError);
|
|
2010
2029
|
onLoadErrorRef.current = onLoadError;
|
|
2011
|
-
const onWaxRefreshRef = useRef(onWaxRefresh);
|
|
2012
|
-
onWaxRefreshRef.current = onWaxRefresh;
|
|
2030
|
+
const onWaxRefreshRef = useRef(onSessionRefresh !== null && onSessionRefresh !== void 0 ? onSessionRefresh : onWaxRefresh);
|
|
2031
|
+
onWaxRefreshRef.current = onSessionRefresh !== null && onSessionRefresh !== void 0 ? onSessionRefresh : onWaxRefresh;
|
|
2013
2032
|
const onReadyRef = useRef(onReady);
|
|
2014
2033
|
onReadyRef.current = onReady;
|
|
2015
|
-
// Keep a ref to
|
|
2016
|
-
|
|
2017
|
-
|
|
2034
|
+
// Keep a ref to the session callback so changes don't trigger vault recreation.
|
|
2035
|
+
// Priority mirrors OzVault.create(): sessionUrl > getSessionKey > fetchWaxKey.
|
|
2036
|
+
const getSessionKeyRef = useRef(getSessionKey !== null && getSessionKey !== void 0 ? getSessionKey : fetchWaxKey);
|
|
2037
|
+
getSessionKeyRef.current = getSessionKey !== null && getSessionKey !== void 0 ? getSessionKey : fetchWaxKey;
|
|
2018
2038
|
const appearanceKey = useMemo(() => appearance ? JSON.stringify(appearance) : '', [appearance]);
|
|
2019
2039
|
const fontsKey = useMemo(() => fonts ? JSON.stringify(fonts) : '', [fonts]);
|
|
2020
2040
|
useEffect(() => {
|
|
@@ -2041,7 +2061,11 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
|
|
|
2041
2061
|
// synchronously rather than waiting for the promise to settle. Without this,
|
|
2042
2062
|
// two hidden iframes and two window listeners briefly coexist.
|
|
2043
2063
|
const abortController = new AbortController();
|
|
2044
|
-
OzVault.create(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(
|
|
2064
|
+
OzVault.create(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ pubKey }, (sessionUrl
|
|
2065
|
+
? { sessionUrl }
|
|
2066
|
+
: getSessionKeyRef.current
|
|
2067
|
+
? { getSessionKey: (sessionId) => getSessionKeyRef.current(sessionId) }
|
|
2068
|
+
: {})), (frameBaseUrl ? { frameBaseUrl } : {})), (parsedFonts ? { fonts: parsedFonts } : {})), (parsedAppearance ? { appearance: parsedAppearance } : {})), (onLoadErrorRef.current ? { onLoadError: fireLoadError, loadTimeoutMs } : {})), {
|
|
2045
2069
|
// Always install onWaxRefresh internally so we can reset tokenizeCount
|
|
2046
2070
|
// when any wax key refresh occurs (reactive TTL expiry, post-budget
|
|
2047
2071
|
// proactive, or visibility-change proactive). Without this the React
|
|
@@ -2063,11 +2087,12 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
|
|
|
2063
2087
|
// the retry tokenization completes (a full fetchWaxKey + tokenize round-
|
|
2064
2088
|
// trip separates them), so the count correctly resets to 0 then rises to
|
|
2065
2089
|
// 1 after the retry notifyTokenize fires.
|
|
2066
|
-
|
|
2090
|
+
onSessionRefresh: () => {
|
|
2067
2091
|
var _a;
|
|
2068
2092
|
Promise.resolve().then(() => setTokenizeCount(0));
|
|
2069
2093
|
(_a = onWaxRefreshRef.current) === null || _a === void 0 ? void 0 : _a.call(onWaxRefreshRef);
|
|
2070
|
-
}, onReady: () => { var _a; return (_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef); } }), (
|
|
2094
|
+
}, onReady: () => { var _a; return (_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef); } }), (sessionLimit !== undefined ? { sessionLimit }
|
|
2095
|
+
: maxTokenizeCalls !== undefined ? { maxTokenizeCalls } : {})), (debug ? { debug: true } : {})), abortController.signal).then(v => {
|
|
2071
2096
|
if (cancelled) {
|
|
2072
2097
|
v.destroy();
|
|
2073
2098
|
return;
|
|
@@ -2100,7 +2125,7 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
|
|
|
2100
2125
|
setVault(null);
|
|
2101
2126
|
setInitError(null);
|
|
2102
2127
|
};
|
|
2103
|
-
}, [pubKey, frameBaseUrl, loadTimeoutMs, appearanceKey, fontsKey, maxTokenizeCalls, debug]);
|
|
2128
|
+
}, [pubKey, sessionUrl, frameBaseUrl, loadTimeoutMs, appearanceKey, fontsKey, sessionLimit, maxTokenizeCalls, debug]);
|
|
2104
2129
|
const notifyMount = useCallback(() => setMountedCount(n => n + 1), []);
|
|
2105
2130
|
const notifyReady = useCallback(() => setReadyCount(n => n + 1), []);
|
|
2106
2131
|
const notifyUnmount = useCallback(() => {
|
|
@@ -2436,5 +2461,5 @@ function OzBankCard({ style, styles, classNames, labels, labelStyle, labelClassN
|
|
|
2436
2461
|
return (jsxs("div", { className: className, style: { width: '100%', display: 'flex', flexDirection: 'column', gap: gapStr }, children: [jsxs("div", { children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.accountNumber), jsx(OzBankAccountNumber, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.accountNumber), className: classNames === null || classNames === void 0 ? void 0 : classNames.accountNumber, placeholder: (_a = placeholders === null || placeholders === void 0 ? void 0 : placeholders.accountNumber) !== null && _a !== void 0 ? _a : 'Account number', disabled: disabled, onChange: (e) => { fieldState.current.accountNumber = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'accountNumber'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'accountNumber'); }, onReady: readyHandlers['accountNumber'] })] }), jsxs("div", { children: [renderLabel(labels === null || labels === void 0 ? void 0 : labels.routingNumber), jsx(OzBankRoutingNumber, { style: mergeStyles(style, styles === null || styles === void 0 ? void 0 : styles.routingNumber), className: classNames === null || classNames === void 0 ? void 0 : classNames.routingNumber, placeholder: (_b = placeholders === null || placeholders === void 0 ? void 0 : placeholders.routingNumber) !== null && _b !== void 0 ? _b : 'Routing number', disabled: disabled, onChange: (e) => { fieldState.current.routingNumber = e; emitChange(); }, onFocus: () => { var _a; return (_a = onFocusRef.current) === null || _a === void 0 ? void 0 : _a.call(onFocusRef, 'routingNumber'); }, onBlur: () => { var _a; return (_a = onBlurRef.current) === null || _a === void 0 ? void 0 : _a.call(onBlurRef, 'routingNumber'); }, onReady: readyHandlers['routingNumber'] })] }), errorNode] }));
|
|
2437
2462
|
}
|
|
2438
2463
|
|
|
2439
|
-
export { OzBankAccountNumber, OzBankCard, OzBankRoutingNumber, OzCard, OzCardNumber, OzCvv, OzElements, OzExpiry, createFetchWaxKey, useOzElements };
|
|
2464
|
+
export { OzBankAccountNumber, OzBankCard, OzBankRoutingNumber, OzCard, OzCardNumber, OzCvv, OzElements, OzExpiry, createSessionFetcher as createFetchWaxKey, createSessionFetcher, useOzElements };
|
|
2440
2465
|
//# sourceMappingURL=index.esm.js.map
|