@agent-cards/sdk 0.23.9 → 0.23.10
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/CHANGELOG.md +40 -0
- package/PREFLIGHT.md +7 -5
- package/README.md +181 -92
- package/dist/aci.d.ts +7 -5
- package/dist/aci.generated.d.ts +2 -1
- package/dist/aci.generated.js +14 -4
- package/dist/aci.js +28 -7
- package/dist/amadeus-checkout.generated.js +2 -2
- package/dist/builtin-registry.generated.js +1 -1
- package/dist/card-fields.generated.js +163 -9
- package/dist/cdp.js +79 -34
- package/dist/client.d.ts +61 -31
- package/dist/client.js +99 -42
- package/dist/creditguard.generated.d.ts +1 -1
- package/dist/creditguard.generated.js +1 -3
- package/dist/cse-body.d.ts +7 -6
- package/dist/cse-body.js +8 -7
- package/dist/datatrans.generated.js +8 -5
- package/dist/elavon-converge.d.ts +1 -1
- package/dist/elavon-converge.generated.js +7 -4
- package/dist/elavon-converge.js +4 -3
- package/dist/fiserv.d.ts +9 -5
- package/dist/fiserv.generated.d.ts +3 -3
- package/dist/fiserv.generated.js +50 -20
- package/dist/fiserv.js +10 -6
- package/dist/payrails.d.ts +78 -18
- package/dist/payrails.generated.d.ts +12 -2
- package/dist/payrails.generated.js +213 -18
- package/dist/payrails.js +165 -44
- package/dist/pre-claim.js +51 -29
- package/dist/preflight-capabilities.generated.d.ts +0 -106
- package/dist/preflight-capabilities.generated.js +0 -153
- package/dist/preflight-catalog.json +61 -181
- package/dist/preflight-schemas.json +6 -6
- package/dist/preflight.generated.d.ts +0 -106
- package/dist/preflight.generated.js +27 -15
- package/dist/preparation.d.ts +2 -0
- package/dist/preparation.js +4 -2
- package/dist/prepared-processor.d.ts +19 -5
- package/dist/prepared-processor.js +21 -5
- package/dist/primer.generated.d.ts +5 -1
- package/dist/primer.generated.js +200 -33
- package/dist/registry.d.ts +18 -12
- package/dist/registry.js +11 -8
- package/dist/shiji-sts.d.ts +24 -22
- package/dist/shiji-sts.generated.d.ts +1 -1
- package/dist/shiji-sts.generated.js +12 -8
- package/dist/shiji-sts.js +49 -46
- package/dist/stripe-checkout.generated.js +146 -49
- package/dist/verifone.generated.js +192 -17
- package/dist/verifone.js +1 -1
- package/dist/wspay.d.ts +17 -16
- package/dist/wspay.generated.d.ts +6 -1
- package/dist/wspay.generated.js +13 -3
- package/dist/wspay.js +9 -11
- package/examples/preflight/kernel-native/README.md +1 -1
- package/examples/preflight/kernel-native/inventory.json +1 -19
- package/package.json +3 -3
package/dist/shiji-sts.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export declare const SHIJI_STS_CAPABILITY = "shiji_sts_pinned_key";
|
|
|
5
5
|
/**
|
|
6
6
|
* Why a Shiji STS request was refused, reported as the `reason` of the `unsupported_checkout` event
|
|
7
7
|
* and of the attachment's `unsupported` state:
|
|
8
|
-
* shiji_sts_keep_on_file a getTokenId in the proxy's shape while
|
|
9
|
-
*
|
|
8
|
+
* shiji_sts_keep_on_file a getTokenId in the proxy's shape while the card-on-file policy
|
|
9
|
+
* refuses (the kill switch): the hotel would keep the card
|
|
10
10
|
* unsupported_shiji_sts_request any other request to getTokenId or getCvvId: not the proxy's shape,
|
|
11
11
|
* a query, a port, or a body the classifier cannot read
|
|
12
12
|
* shiji_sts_foreign_key a card field encrypted under a key other than the pinned Shiji key
|
|
@@ -32,7 +32,7 @@ interface ShijiStsRequest {
|
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* The verdict on a request to an STS host that the registry recognized: 'pause' for the one prompt
|
|
35
|
-
* (a getTokenId in the proxy's shape
|
|
35
|
+
* (a getTokenId in the proxy's shape while the card-on-file policy asks), 'companion' for a
|
|
36
36
|
* getCvvId in the proxy's shape, and 'refuse' with a reason for everything else. A classifier that
|
|
37
37
|
* throws refuses.
|
|
38
38
|
*/
|
|
@@ -52,18 +52,19 @@ interface ServedSubstitutions {
|
|
|
52
52
|
export declare function isShijiStsServedSubstitution(sub: unknown): sub is ServedSubstitutions;
|
|
53
53
|
/**
|
|
54
54
|
* The page's reviewed getCvvId keys, as the API serves them beside an approved Shiji STS set
|
|
55
|
-
* (checkout.ts approvedShijiStsFields, `shiji_sts_companion`): the
|
|
56
|
-
* reviewed as the booking page's own getCvvId key (its SPS
|
|
55
|
+
* (checkout.ts approvedShijiStsFields, `shiji_sts_companion`): the SHA-256 (lowercase hex of its UTF-8
|
|
56
|
+
* bytes) of each keySequence Agentcard reviewed as the booking page's own getCvvId key (its SPS
|
|
57
|
+
* merchant's settings.client_key). Neither the API nor this SDK holds the key itself.
|
|
57
58
|
*/
|
|
58
59
|
export interface ShijiStsServedCompanion {
|
|
59
|
-
|
|
60
|
+
key_sequence_sha256: string[];
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
63
|
* Whether the API's `shiji_sts_companion` beside an approved Shiji STS set is one this SDK can bind
|
|
63
|
-
* the companion getCvvId to: exactly `{
|
|
64
|
-
*
|
|
65
|
-
* malformed and the getTokenId is not continued, so no card reaches Shiji while its
|
|
66
|
-
* reviewed key to go to.
|
|
64
|
+
* the companion getCvvId to: exactly `{ key_sequence_sha256 }`, 1 to 16 lowercase hex SHA-256 values.
|
|
65
|
+
* Anything else, an API that serves none or serves the keys themselves included, is not acted on: the
|
|
66
|
+
* approval reads as malformed and the getTokenId is not continued, so no card reaches Shiji while its
|
|
67
|
+
* CVV has no reviewed key to go to.
|
|
67
68
|
*/
|
|
68
69
|
export declare function isShijiStsServedCompanion(value: unknown): value is ShijiStsServedCompanion;
|
|
69
70
|
/** The paused request an approval was created from: the URL and body the API reviewed at create. */
|
|
@@ -75,9 +76,9 @@ export interface ShijiStsApprovedRequest {
|
|
|
75
76
|
* The continuation of an approved getTokenId: the paused body with the device's pan and expires
|
|
76
77
|
* written over the page's own at the body root (payment-core substituteShijiSts, which refuses a
|
|
77
78
|
* value that is not a ciphertext under the pinned key), the device's cvv, which this body does not
|
|
78
|
-
* carry and the runtime keeps in memory for the one companion getCvvId, and the
|
|
79
|
-
* keys that companion may carry it under (`companion`, the replay's
|
|
80
|
-
* client read from the API's shiji_sts_companion).
|
|
79
|
+
* carry and the runtime keeps in memory for the one companion getCvvId, and the SHA-256 of the
|
|
80
|
+
* reviewed getCvvId keys that companion may carry it under (`companion`, the replay's
|
|
81
|
+
* shijiStsCompanion, which the client read from the API's shiji_sts_companion).
|
|
81
82
|
*
|
|
82
83
|
* Only into `approved`, the paused getTokenId the approval was created from: `url` and `body` must
|
|
83
84
|
* equal it byte for byte, so the accessToken and keySequence are the ones the API reviewed at create
|
|
@@ -88,15 +89,15 @@ export interface ShijiStsApprovedRequest {
|
|
|
88
89
|
* Null when neither URL is on an STS host, so every other processor keeps the generic swap. Throws
|
|
89
90
|
* for any other body or URL, an STS URL that is not getTokenId, a substitution
|
|
90
91
|
* isShijiStsServedSubstitution refuses (`sub` is whatever the approval served, of any processor's
|
|
91
|
-
* shape), no reviewed getCvvId key to bind the companion to, and while the card-on-file
|
|
92
|
-
*
|
|
92
|
+
* shape), no reviewed getCvvId key to bind the companion to, and while the card-on-file policy
|
|
93
|
+
* refuses: in each case before anything continues.
|
|
93
94
|
*/
|
|
94
95
|
export declare function shijiStsTokenContinuation(url: string, body: string, sub: unknown, approved: ShijiStsApprovedRequest, companion?: {
|
|
95
|
-
|
|
96
|
+
keySequenceSha256: readonly string[];
|
|
96
97
|
}): {
|
|
97
98
|
body: string;
|
|
98
99
|
cvv: string;
|
|
99
|
-
|
|
100
|
+
cvvKeySequenceSha256: string[];
|
|
100
101
|
} | null;
|
|
101
102
|
/**
|
|
102
103
|
* One attachment's getCvvId companion: at most one binding, to the getTokenId it last continued with
|
|
@@ -113,12 +114,13 @@ export declare class ShijiStsCompanions {
|
|
|
113
114
|
/**
|
|
114
115
|
* Bind the companion of `tokenRequest` (the paused getTokenId: its URL, method and body) for the
|
|
115
116
|
* page `page` (the adapter's opaque id for the frame that sent it) and keep `cvv`, the device's
|
|
116
|
-
* CVV ciphertext, for it, to go only into a getCvvId whose keySequence
|
|
117
|
-
* (the reviewed getCvvId keys the approval served). Replaces any
|
|
118
|
-
* ShijiStsError for a request that is not a getTokenId in the proxy's shape,
|
|
119
|
-
* payment-core refuses (none, empty or malformed), and while the card-on-file
|
|
117
|
+
* CVV ciphertext, for it, to go only into a getCvvId whose keySequence hashes to one of
|
|
118
|
+
* `cvvKeySequenceSha256` (the SHA-256 of the reviewed getCvvId keys the approval served). Replaces any
|
|
119
|
+
* earlier binding. Throws ShijiStsError for a request that is not a getTokenId in the proxy's shape,
|
|
120
|
+
* a digest list payment-core refuses (none, empty or malformed), and while the card-on-file policy
|
|
121
|
+
* refuses.
|
|
120
122
|
*/
|
|
121
|
-
bind(tokenRequest: ShijiStsRequest, page: string, cvv: string,
|
|
123
|
+
bind(tokenRequest: ShijiStsRequest, page: string, cvv: string, cvvKeySequenceSha256: readonly string[], now?: number): void;
|
|
122
124
|
/** Drop the binding and the CVV ciphertext it holds. */
|
|
123
125
|
release(): void;
|
|
124
126
|
/**
|
|
@@ -61,7 +61,7 @@ declare function shijiStsSubstitutionsRefusal(template: any, substitutions: any)
|
|
|
61
61
|
code: string;
|
|
62
62
|
message: any;
|
|
63
63
|
} | null;
|
|
64
|
-
declare function createShijiStsCompanion(tokenRequest: any, { page, now,
|
|
64
|
+
declare function createShijiStsCompanion(tokenRequest: any, { page, now, cvvKeySequenceSha256 }?: {}): Readonly<{
|
|
65
65
|
claim: (request: any, context?: {}) => any;
|
|
66
66
|
}>;
|
|
67
67
|
declare function shijiStsResponseFacts(status: any, text: any): {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
-
// artifact-sha256:
|
|
3
|
+
// artifact-sha256: 98a535f4ba13e1ee4744fb725ae47c91fd9ca650dcb37fcd9eadd92b85bf6ce1
|
|
4
4
|
// src/sha256.js
|
|
5
5
|
var K = /* @__PURE__ */ new Uint32Array([
|
|
6
6
|
1116352408,
|
|
@@ -535,7 +535,7 @@ var SHIJI_STS_FIELDS = /* @__PURE__ */ Object.freeze({
|
|
|
535
535
|
token: Object.freeze(["pan", "expires"]),
|
|
536
536
|
cvv: Object.freeze(["cvv"])
|
|
537
537
|
});
|
|
538
|
-
var SHIJI_STS_KEEP_ON_FILE = "
|
|
538
|
+
var SHIJI_STS_KEEP_ON_FILE = "ask";
|
|
539
539
|
var SHIJI_STS_REFUSAL_REASONS = /* @__PURE__ */ Object.freeze([
|
|
540
540
|
"unsupported",
|
|
541
541
|
"foreign_key",
|
|
@@ -829,16 +829,19 @@ function shijiStsSubstitutionsRefusal(template, substitutions) {
|
|
|
829
829
|
}
|
|
830
830
|
var PAGE = /^[\x21-\x7e]{1,256}$/;
|
|
831
831
|
var instant = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
832
|
-
var
|
|
832
|
+
var REVIEWED_KEY_SEQUENCE_SHA256 = /^[0-9a-f]{64}$/;
|
|
833
833
|
var REVIEWED_KEY_SEQUENCES_LIMIT = 16;
|
|
834
|
-
function
|
|
834
|
+
function reviewedKeySequenceSha256(list) {
|
|
835
835
|
if (!Array.isArray(list) || list.length === 0 || list.length > REVIEWED_KEY_SEQUENCES_LIMIT)
|
|
836
836
|
return null;
|
|
837
|
-
if (!list.every((
|
|
837
|
+
if (!list.every((digest) => typeof digest === "string" && REVIEWED_KEY_SEQUENCE_SHA256.test(digest)))
|
|
838
838
|
return null;
|
|
839
839
|
return Object.freeze([...list]);
|
|
840
840
|
}
|
|
841
|
-
function
|
|
841
|
+
function keySequenceSha256(keySequence) {
|
|
842
|
+
return typeof keySequence === "string" && keySequence !== "" ? sha256Hex(keySequence) : null;
|
|
843
|
+
}
|
|
844
|
+
function createShijiStsCompanion(tokenRequest, { page, now, cvvKeySequenceSha256 } = {}) {
|
|
842
845
|
const policy = shijiStsKeepOnFileRefusal();
|
|
843
846
|
if (policy)
|
|
844
847
|
throw new ShijiStsError(policy);
|
|
@@ -849,7 +852,7 @@ function createShijiStsCompanion(tokenRequest, { page, now, cvvKeySequences } =
|
|
|
849
852
|
throw new ShijiStsError(token.reason);
|
|
850
853
|
if (typeof page !== "string" || !PAGE.test(page) || !instant(now))
|
|
851
854
|
throw new ShijiStsError("unsupported");
|
|
852
|
-
const reviewed =
|
|
855
|
+
const reviewed = reviewedKeySequenceSha256(cvvKeySequenceSha256);
|
|
853
856
|
if (!reviewed)
|
|
854
857
|
throw new ShijiStsError("unsupported");
|
|
855
858
|
const host = new URL(tokenRequest.url).hostname;
|
|
@@ -864,7 +867,8 @@ function createShijiStsCompanion(tokenRequest, { page, now, cvvKeySequences } =
|
|
|
864
867
|
return cvv.reason;
|
|
865
868
|
if (used)
|
|
866
869
|
return "companion_used";
|
|
867
|
-
|
|
870
|
+
const keyDigest = keySequenceSha256(cvv.keySequence);
|
|
871
|
+
if (new URL(request.url).hostname !== host || context.page !== boundPage || cvv.accessToken !== token.accessToken || keyDigest === null || !reviewed.includes(keyDigest))
|
|
868
872
|
return "companion_unbound";
|
|
869
873
|
if (!instant(context.now) || context.now < boundAt || context.now - boundAt > SHIJI_STS_COMPANION_WINDOW_MS)
|
|
870
874
|
return "companion_expired";
|
package/dist/shiji-sts.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// Shiji Payment Solutions STS, the card leg of the MyCheck Wallet V3 (Shiji Group), as the SDK sees it.
|
|
2
2
|
//
|
|
3
|
-
// La Quinta
|
|
4
|
-
// encrypts the typed card with RSAES-PKCS1-v1_5 under the
|
|
5
|
-
// fetch from the page:
|
|
3
|
+
// Wyndham's booking pages (every brand, La Quinta and Days Inn among them) load MyCheck's wallet,
|
|
4
|
+
// whose Shiji proxy (sts.proxy.v2.1.js) encrypts the typed card with RSAES-PKCS1-v1_5 under the
|
|
5
|
+
// RSA-1024 key it hardcodes and sends one fetch from the page:
|
|
6
6
|
// POST https://iframe.vault.eu.prod.shijipayment.com/v1/token/getTokenId (UAT: iframe.vault.eu.uat...)
|
|
7
|
-
// {"accessToken":"<STS token>","pan":"<b64>","expires":"<b64>"
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
7
|
+
// {"accessToken":"<STS token>","pan":"<b64>","expires":"<b64>"}
|
|
8
|
+
// (a wallet whose merchant has a clientKey adds it as "keySequence"; Wyndham's has none) and, after
|
|
9
|
+
// MyCheck's payment-methods call, the CVV the same way to /v1/token/getCvvId under the merchant's
|
|
10
|
+
// client_key. The agent's page encrypts the placeholder card. The cardholder's device encrypts the
|
|
11
|
+
// real one under the key payment-core pins (never a key from a row, a request or a page), and the
|
|
12
|
+
// runtime swaps those ciphertexts over the page's own, byte for byte, at the body root, so the
|
|
13
|
+
// accessToken, the keySequence and the origin stay the page's (mode cse).
|
|
13
14
|
//
|
|
14
15
|
// The registry entry ships dark (capability shiji_sts_pinned_key). This build declares the
|
|
15
16
|
// capability on syncRegistry, and the API serves the entry only to an org Agentcard enabled for
|
|
@@ -19,21 +20,22 @@
|
|
|
19
20
|
// For an org in the dark launch, a POST the registry recognizes on an STS host is judged by
|
|
20
21
|
// payment-core's classifier (shiji-sts.generated.ts classifyShijiStsRequest), the same rules the API
|
|
21
22
|
// runs at create and the device runs before it encrypts:
|
|
22
|
-
// - a getTokenId in the proxy's shape is the one prompt
|
|
23
|
-
//
|
|
24
|
-
// 'refuse' every one is refused in the browser
|
|
25
|
-
// prompt, and the page's card never reaches Shiji.
|
|
26
|
-
// into that paused request, byte for byte: if the
|
|
27
|
-
//
|
|
28
|
-
// same shape can name another Shiji merchant's
|
|
23
|
+
// - a getTokenId in the proxy's shape is the one prompt: the token Shiji mints guarantees a hotel
|
|
24
|
+
// stay, which the cardholder consents to on the approval screen while SHIJI_STS_KEEP_ON_FILE is
|
|
25
|
+
// 'ask'. Set back to 'refuse' (the kill switch), every one is refused in the browser
|
|
26
|
+
// (shiji_sts_keep_on_file) before any create or prompt, and the page's card never reaches Shiji.
|
|
27
|
+
// Once asked, the device's ciphertext goes only into that paused request, byte for byte: if the
|
|
28
|
+
// page abandons it, the approval is cancelled (merchant_request_aborted) and no later getTokenId
|
|
29
|
+
// is answered from it, because one of the same shape can name another Shiji merchant's
|
|
30
|
+
// accessToken and keySequence;
|
|
29
31
|
// - a getCvvId never prompts. It continues with the device's CVV ciphertext only when it is the
|
|
30
32
|
// companion of the getTokenId this attachment continued with the Vault's ciphertexts (same host,
|
|
31
|
-
// same page, same accessToken, a keySequence the API reviewed as that page's
|
|
32
|
-
// served with the approval, within 120 s, once), and is refused otherwise, so
|
|
33
|
-
// placeholder CVV never rides beside a real card and the real one goes to no
|
|
34
|
-
// binding, and the CVV ciphertext it holds, is dropped as soon as the
|
|
35
|
-
// use it: a cancel, the page, frame or target that sent the getTokenId
|
|
36
|
-
// committing a new document, which never obtained the approval;
|
|
33
|
+
// same page, same accessToken, a keySequence whose SHA-256 the API reviewed as that page's
|
|
34
|
+
// getCvvId key and served with the approval, within 120 s, once), and is refused otherwise, so
|
|
35
|
+
// the agent's placeholder CVV never rides beside a real card and the real one goes to no
|
|
36
|
+
// unreviewed key. The binding, and the CVV ciphertext it holds, is dropped as soon as the
|
|
37
|
+
// attachment can no longer use it: a cancel, the page, frame or target that sent the getTokenId
|
|
38
|
+
// going away, or that frame committing a new document, which never obtained the approval;
|
|
37
39
|
// - anything else on those two URLs is refused as an unsupported checkout.
|
|
38
40
|
// Autopilot never pays this processor: the API, the authority and the enclave refuse it.
|
|
39
41
|
import { SHIJI_STS_COMPANION_WINDOW_MS, SHIJI_STS_PSP, ShijiStsError, classifyShijiStsRequest, createShijiStsCompanion, isShijiStsCiphertext, isShijiStsHost, shijiStsEndpoint, substituteShijiSts, } from './shiji-sts.generated.js';
|
|
@@ -50,7 +52,7 @@ const REFUSED = Object.freeze({
|
|
|
50
52
|
});
|
|
51
53
|
/**
|
|
52
54
|
* The verdict on a request to an STS host that the registry recognized: 'pause' for the one prompt
|
|
53
|
-
* (a getTokenId in the proxy's shape
|
|
55
|
+
* (a getTokenId in the proxy's shape while the card-on-file policy asks), 'companion' for a
|
|
54
56
|
* getCvvId in the proxy's shape, and 'refuse' with a reason for everything else. A classifier that
|
|
55
57
|
* throws refuses.
|
|
56
58
|
*/
|
|
@@ -86,32 +88,32 @@ export function isShijiStsServedSubstitution(sub) {
|
|
|
86
88
|
return names.length === SERVED_FIELDS.length
|
|
87
89
|
&& SERVED_FIELDS.every((name) => isShijiStsCiphertext(fields[name]));
|
|
88
90
|
}
|
|
89
|
-
const
|
|
91
|
+
const SERVED_KEY_SEQUENCE_SHA256 = /^[0-9a-f]{64}$/;
|
|
90
92
|
const SERVED_KEY_SEQUENCES_LIMIT = 16;
|
|
91
93
|
/**
|
|
92
94
|
* Whether the API's `shiji_sts_companion` beside an approved Shiji STS set is one this SDK can bind
|
|
93
|
-
* the companion getCvvId to: exactly `{
|
|
94
|
-
*
|
|
95
|
-
* malformed and the getTokenId is not continued, so no card reaches Shiji while its
|
|
96
|
-
* reviewed key to go to.
|
|
95
|
+
* the companion getCvvId to: exactly `{ key_sequence_sha256 }`, 1 to 16 lowercase hex SHA-256 values.
|
|
96
|
+
* Anything else, an API that serves none or serves the keys themselves included, is not acted on: the
|
|
97
|
+
* approval reads as malformed and the getTokenId is not continued, so no card reaches Shiji while its
|
|
98
|
+
* CVV has no reviewed key to go to.
|
|
97
99
|
*/
|
|
98
100
|
export function isShijiStsServedCompanion(value) {
|
|
99
101
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
100
102
|
return false;
|
|
101
103
|
const names = Object.keys(value);
|
|
102
|
-
if (names.length !== 1 || names[0] !== '
|
|
104
|
+
if (names.length !== 1 || names[0] !== 'key_sequence_sha256')
|
|
103
105
|
return false;
|
|
104
|
-
const
|
|
105
|
-
return Array.isArray(
|
|
106
|
-
&&
|
|
106
|
+
const digests = value.key_sequence_sha256;
|
|
107
|
+
return Array.isArray(digests) && digests.length > 0 && digests.length <= SERVED_KEY_SEQUENCES_LIMIT
|
|
108
|
+
&& digests.every((digest) => typeof digest === 'string' && SERVED_KEY_SEQUENCE_SHA256.test(digest));
|
|
107
109
|
}
|
|
108
110
|
/**
|
|
109
111
|
* The continuation of an approved getTokenId: the paused body with the device's pan and expires
|
|
110
112
|
* written over the page's own at the body root (payment-core substituteShijiSts, which refuses a
|
|
111
113
|
* value that is not a ciphertext under the pinned key), the device's cvv, which this body does not
|
|
112
|
-
* carry and the runtime keeps in memory for the one companion getCvvId, and the
|
|
113
|
-
* keys that companion may carry it under (`companion`, the replay's
|
|
114
|
-
* client read from the API's shiji_sts_companion).
|
|
114
|
+
* carry and the runtime keeps in memory for the one companion getCvvId, and the SHA-256 of the
|
|
115
|
+
* reviewed getCvvId keys that companion may carry it under (`companion`, the replay's
|
|
116
|
+
* shijiStsCompanion, which the client read from the API's shiji_sts_companion).
|
|
115
117
|
*
|
|
116
118
|
* Only into `approved`, the paused getTokenId the approval was created from: `url` and `body` must
|
|
117
119
|
* equal it byte for byte, so the accessToken and keySequence are the ones the API reviewed at create
|
|
@@ -122,8 +124,8 @@ export function isShijiStsServedCompanion(value) {
|
|
|
122
124
|
* Null when neither URL is on an STS host, so every other processor keeps the generic swap. Throws
|
|
123
125
|
* for any other body or URL, an STS URL that is not getTokenId, a substitution
|
|
124
126
|
* isShijiStsServedSubstitution refuses (`sub` is whatever the approval served, of any processor's
|
|
125
|
-
* shape), no reviewed getCvvId key to bind the companion to, and while the card-on-file
|
|
126
|
-
*
|
|
127
|
+
* shape), no reviewed getCvvId key to bind the companion to, and while the card-on-file policy
|
|
128
|
+
* refuses: in each case before anything continues.
|
|
127
129
|
*/
|
|
128
130
|
export function shijiStsTokenContinuation(url, body, sub, approved, companion) {
|
|
129
131
|
if (!isShijiStsHost(url) && !isShijiStsHost(approved.url))
|
|
@@ -132,10 +134,10 @@ export function shijiStsTokenContinuation(url, body, sub, approved, companion) {
|
|
|
132
134
|
throw new ShijiStsError('unsupported');
|
|
133
135
|
if (shijiStsEndpoint(url, 'POST') !== 'token' || !isShijiStsServedSubstitution(sub))
|
|
134
136
|
throw new ShijiStsError('unsupported');
|
|
135
|
-
const
|
|
136
|
-
if (!
|
|
137
|
+
const digests = companion && Array.isArray(companion.keySequenceSha256) ? [...companion.keySequenceSha256] : null;
|
|
138
|
+
if (!digests || !isShijiStsServedCompanion({ key_sequence_sha256: digests }))
|
|
137
139
|
throw new ShijiStsError('unsupported');
|
|
138
|
-
return { body: substituteShijiSts(url, body, { pan: sub.fields.pan, expires: sub.fields.expires }), cvv: sub.fields.cvv,
|
|
140
|
+
return { body: substituteShijiSts(url, body, { pan: sub.fields.pan, expires: sub.fields.expires }), cvv: sub.fields.cvv, cvvKeySequenceSha256: digests };
|
|
139
141
|
}
|
|
140
142
|
/**
|
|
141
143
|
* One attachment's getCvvId companion: at most one binding, to the getTokenId it last continued with
|
|
@@ -152,16 +154,17 @@ export class ShijiStsCompanions {
|
|
|
152
154
|
/**
|
|
153
155
|
* Bind the companion of `tokenRequest` (the paused getTokenId: its URL, method and body) for the
|
|
154
156
|
* page `page` (the adapter's opaque id for the frame that sent it) and keep `cvv`, the device's
|
|
155
|
-
* CVV ciphertext, for it, to go only into a getCvvId whose keySequence
|
|
156
|
-
* (the reviewed getCvvId keys the approval served). Replaces any
|
|
157
|
-
* ShijiStsError for a request that is not a getTokenId in the proxy's shape,
|
|
158
|
-
* payment-core refuses (none, empty or malformed), and while the card-on-file
|
|
157
|
+
* CVV ciphertext, for it, to go only into a getCvvId whose keySequence hashes to one of
|
|
158
|
+
* `cvvKeySequenceSha256` (the SHA-256 of the reviewed getCvvId keys the approval served). Replaces any
|
|
159
|
+
* earlier binding. Throws ShijiStsError for a request that is not a getTokenId in the proxy's shape,
|
|
160
|
+
* a digest list payment-core refuses (none, empty or malformed), and while the card-on-file policy
|
|
161
|
+
* refuses.
|
|
159
162
|
*/
|
|
160
|
-
bind(tokenRequest, page, cvv,
|
|
163
|
+
bind(tokenRequest, page, cvv, cvvKeySequenceSha256, now = Date.now()) {
|
|
161
164
|
this.release();
|
|
162
165
|
if (!isShijiStsCiphertext(cvv))
|
|
163
166
|
throw new ShijiStsError('unsupported');
|
|
164
|
-
const companion = createShijiStsCompanion({ url: tokenRequest.url, method: tokenRequest.method.toUpperCase(), body: tokenRequest.body }, { page, now,
|
|
167
|
+
const companion = createShijiStsCompanion({ url: tokenRequest.url, method: tokenRequest.method.toUpperCase(), body: tokenRequest.body }, { page, now, cvvKeySequenceSha256: Array.isArray(cvvKeySequenceSha256) ? [...cvvKeySequenceSha256] : cvvKeySequenceSha256 });
|
|
165
168
|
const timer = setTimeout(() => { if (this.bound?.timer === timer)
|
|
166
169
|
this.bound = null; }, SHIJI_STS_COMPANION_WINDOW_MS + 1000);
|
|
167
170
|
timer.unref?.();
|