@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/aci.generated.js
CHANGED
|
@@ -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: 624ca03645e28d72156188c850b3650fd0f5162b0366475e6a124657120f7f11
|
|
4
4
|
// src/aci.js
|
|
5
5
|
var ACI_HOSTS = Object.freeze(["eu-prod.oppwa.com", "oppwa.com", "eu-test.oppwa.com", "test.oppwa.com"]);
|
|
6
6
|
var ACI_TEST_HOSTS = Object.freeze(["eu-test.oppwa.com", "test.oppwa.com"]);
|
|
@@ -22,6 +22,9 @@ var ACI_ABSORBED_FIELDS = Object.freeze(["card.cvv", "card.expiryMonth", "card.e
|
|
|
22
22
|
var ACI_PASSED_FIELDS = Object.freeze(["card.holder"]);
|
|
23
23
|
var ACI_SIBLING_KEYS = Object.freeze(["customParameters[SHOPPER_EndToEndIdentity]"]);
|
|
24
24
|
var ACI_REMOVED_ON_CONTINUATION = Object.freeze(["card.expiryMonth", "card.expiryYear"]);
|
|
25
|
+
var ACI_FINGERPRINT_FIELD = "customer.browserFingerprint.value";
|
|
26
|
+
var FINGERPRINT_LENGTH = 4096;
|
|
27
|
+
var LEG_BODY_LIMIT = 16384;
|
|
25
28
|
var END_TO_END = ACI_SIBLING_KEYS[0];
|
|
26
29
|
var CHECKOUT_ID = /^[0-9A-F]{32}\.[a-z0-9]{1,16}-vm-tx[0-9]{1,3}$/i;
|
|
27
30
|
var ENDPOINT_PATH = /^\/v1\/checkouts\/([^/]+?)(\/payment|\/registration)?$/;
|
|
@@ -76,7 +79,8 @@ function readAciForm(body, limit = 8192) {
|
|
|
76
79
|
catch {
|
|
77
80
|
return null;
|
|
78
81
|
}
|
|
79
|
-
|
|
82
|
+
const longest = key === ACI_FINGERPRINT_FIELD ? FINGERPRINT_LENGTH : 2048;
|
|
83
|
+
if (!key || key.length > 128 || CONTROL.test(key) || CONTROL.test(value) || value.length > longest || seen.has(key))
|
|
80
84
|
return null;
|
|
81
85
|
seen.add(key);
|
|
82
86
|
pairs.push({ key, value, raw });
|
|
@@ -117,11 +121,13 @@ function classifyAciRequest(request) {
|
|
|
117
121
|
return refuse(ACI_CARD_ON_FILE_REFUSED);
|
|
118
122
|
if (endpoint.kind === "payment")
|
|
119
123
|
return { leg: "continuation", ...at };
|
|
120
|
-
const pairs = readAciForm(request.body);
|
|
124
|
+
const pairs = readAciForm(request.body, LEG_BODY_LIMIT);
|
|
121
125
|
if (!pairs)
|
|
122
126
|
return refuse(ACI_UNSUPPORTED_REQUEST);
|
|
123
127
|
if (pairs.some(({ key }) => isAciCardOnFileKey(key)))
|
|
124
128
|
return refuse(ACI_CARD_ON_FILE_REFUSED);
|
|
129
|
+
if (pairs.length === 1 && pairs[0].key === ACI_FINGERPRINT_FIELD)
|
|
130
|
+
return { leg: "pass", ...at };
|
|
125
131
|
if (!pairs.every(({ key, value }) => validField(key, value)))
|
|
126
132
|
return refuse(ACI_UNSUPPORTED_REQUEST);
|
|
127
133
|
const own = pairs.map(({ key }) => key).filter((key) => key !== END_TO_END);
|
|
@@ -199,6 +205,7 @@ function aciPlaceholderBrandRefusal(templateBody, card) {
|
|
|
199
205
|
var CONTINUATION_KEYS = /* @__PURE__ */ new Set([
|
|
200
206
|
"paymentBrand",
|
|
201
207
|
"shopperResultUrl",
|
|
208
|
+
"shopperResultTarget",
|
|
202
209
|
"shopOrigin",
|
|
203
210
|
"forceUtf8",
|
|
204
211
|
"card.holder",
|
|
@@ -250,6 +257,9 @@ function prepareAciContinuation(request, context) {
|
|
|
250
257
|
if (!pairs.every(({ key }) => continuationKey(key)))
|
|
251
258
|
return refuse(ACI_UNSUPPORTED_REQUEST);
|
|
252
259
|
const value = (key) => pairs.find((pair) => pair.key === key)?.value;
|
|
260
|
+
const target = value("shopperResultTarget");
|
|
261
|
+
if (target !== void 0 && target !== "_top")
|
|
262
|
+
return refuse(ACI_UNSUPPORTED_REQUEST);
|
|
253
263
|
if (typeof brand !== "string" || !/^[A-Z]{2,16}$/.test(brand) || value("paymentBrand") !== brand)
|
|
254
264
|
return refuse(ACI_BRAND_MISMATCH);
|
|
255
265
|
if (!onOrigin(value("shopperResultUrl"), merchantOrigin))
|
|
@@ -303,4 +313,4 @@ function sanitizeAciResponse(text) {
|
|
|
303
313
|
throw new Error("Refusing to store an unconfirmed ACI answer.");
|
|
304
314
|
return JSON.stringify({ result: { code: ACI_CHECKOUT_UPDATED, description: "successfully updated checkout" } });
|
|
305
315
|
}
|
|
306
|
-
export { ACI_ABSORBED_FIELDS, ACI_BRAND_MISMATCH, ACI_CARD_FIELD, ACI_CARD_ON_FILE_REFUSED, ACI_CHECKOUT_UPDATED, ACI_EXPIRY_UNSTRIPPABLE, ACI_HOSTS, ACI_PASSED_FIELDS, ACI_REMOVED_ON_CONTINUATION, ACI_RESULT_URL_REFUSED, ACI_SIBLING_KEYS, ACI_TEST_HOSTS, ACI_TEST_PANS, ACI_UNSUPPORTED_REQUEST, aciBrandForNetwork, aciBrandOfCardLeg, aciCardBrand, aciEndpoint, aciEnvironment, aciFacts, aciHostEnvironment, aciPlaceholderBrandRefusal, aciResponseOutcome, classifyAciRequest, injectAciCard, isAciCardOnFileKey, isAciCardRequest, isPreparedAciRequest, prepareAciContinuation, readAciForm, sanitizeAciResponse };
|
|
316
|
+
export { ACI_ABSORBED_FIELDS, ACI_BRAND_MISMATCH, ACI_CARD_FIELD, ACI_CARD_ON_FILE_REFUSED, ACI_CHECKOUT_UPDATED, ACI_EXPIRY_UNSTRIPPABLE, ACI_FINGERPRINT_FIELD, ACI_HOSTS, ACI_PASSED_FIELDS, ACI_REMOVED_ON_CONTINUATION, ACI_RESULT_URL_REFUSED, ACI_SIBLING_KEYS, ACI_TEST_HOSTS, ACI_TEST_PANS, ACI_UNSUPPORTED_REQUEST, aciBrandForNetwork, aciBrandOfCardLeg, aciCardBrand, aciEndpoint, aciEnvironment, aciFacts, aciHostEnvironment, aciPlaceholderBrandRefusal, aciResponseOutcome, classifyAciRequest, injectAciCard, isAciCardOnFileKey, isAciCardRequest, isPreparedAciRequest, prepareAciContinuation, readAciForm, sanitizeAciResponse };
|
package/dist/aci.js
CHANGED
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
// - the page's own CVC and expiry requests carry the agent's placeholder values: they are held
|
|
13
13
|
// and answered with the card-number request's answer once it lands, never forwarded, and
|
|
14
14
|
// failed when it does not (or when no card-number request for their checkout ever begins);
|
|
15
|
-
// - the holder request
|
|
15
|
+
// - the holder request and the ReD Shield device fingerprint the widget posts on load carry
|
|
16
|
+
// nothing secret and continue;
|
|
17
|
+
// - a refused request fails the checkout's waiting CVC and expiry requests only when it is that
|
|
18
|
+
// checkout's card-number request: a refusal that names no card number leaves them waiting;
|
|
16
19
|
// - a second card-number request on a checkout whose first one is running or was answered here
|
|
17
20
|
// is refused: that answer put the real card on the checkout and may already have let /payment
|
|
18
21
|
// through, and ACI warns that one checkout id reused can carry a second transaction;
|
|
@@ -22,7 +25,7 @@
|
|
|
22
25
|
// It continues only as a frame navigation, which is how the widget's form posts it into its
|
|
23
26
|
// hidden iframe, and a classic-mode body only on a browser shown to send the body the SDK
|
|
24
27
|
// replaced on a navigation (Chromium; see playwrightReplacesNavigationBody).
|
|
25
|
-
import { aciBrandOfCardLeg as brandOfCardLeg, aciEndpoint, classifyAciRequest, prepareAciContinuation, sanitizeAciResponse, } from './aci.generated.js';
|
|
28
|
+
import { ACI_CARD_FIELD, aciBrandOfCardLeg as brandOfCardLeg, aciEndpoint, classifyAciRequest, prepareAciContinuation, sanitizeAciResponse, } from './aci.generated.js';
|
|
26
29
|
const classifyLeg = classifyAciRequest;
|
|
27
30
|
const judgePayment = prepareAciContinuation;
|
|
28
31
|
/** The processor id, as the registry and the API name it. */
|
|
@@ -164,6 +167,20 @@ export async function playwrightReplacesNavigationBody(page, probeMs = ACI_ENGIN
|
|
|
164
167
|
}
|
|
165
168
|
}
|
|
166
169
|
const groupKey = (leg) => `${leg.host}/${leg.checkoutId}`;
|
|
170
|
+
/** Whether a form body has a card.number key, whatever else it carries and however it broke the rules. */
|
|
171
|
+
function namesCardNumber(body) {
|
|
172
|
+
if (typeof body !== 'string')
|
|
173
|
+
return false;
|
|
174
|
+
return body.split('&').some((pair) => {
|
|
175
|
+
const eq = pair.indexOf('=');
|
|
176
|
+
try {
|
|
177
|
+
return decodeURIComponent((eq < 0 ? pair : pair.slice(0, eq)).replace(/\+/g, ' ')) === ACI_CARD_FIELD;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
167
184
|
/**
|
|
168
185
|
* One attachment's ACI state, keyed by checkout (host and checkout id). Every sibling and every
|
|
169
186
|
* /payment submission is matched against a card-number request this attachment itself paused and
|
|
@@ -280,12 +297,16 @@ export class AciGate {
|
|
|
280
297
|
this.prune();
|
|
281
298
|
}
|
|
282
299
|
/**
|
|
283
|
-
* A request on this checkout was refused
|
|
284
|
-
*
|
|
285
|
-
* one fail now, and so does every later sibling
|
|
286
|
-
*
|
|
300
|
+
* A request on this checkout was refused. When it names the card number (a card-number request
|
|
301
|
+
* that asks ACI to keep the card, or carries a field the widget never sends with it) and no
|
|
302
|
+
* card-number request began, the siblings waiting for one fail now, and so does every later sibling
|
|
303
|
+
* until a card-number request begins. A refused request that names no card number, such as a
|
|
304
|
+
* fingerprint longer than ACI takes, says nothing about the card-number request a later Pay sends,
|
|
305
|
+
* so its siblings keep waiting for it. A running or answered card-number request keeps its siblings.
|
|
287
306
|
*/
|
|
288
|
-
refused(leg) {
|
|
307
|
+
refused(leg, body) {
|
|
308
|
+
if (!namesCardNumber(body))
|
|
309
|
+
return;
|
|
289
310
|
const key = groupKey(leg);
|
|
290
311
|
const known = this.groups.get(key);
|
|
291
312
|
if (known && known.state !== 'failed')
|
|
@@ -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: d537d04a5cd64f34af196a0f6cec7a7f5319bb396d94824131857a04632aab0a
|
|
4
4
|
// src/amadeus-body.js
|
|
5
5
|
var AMADEUS_CARD_MOPID = /^creditcard[0-9]*$/;
|
|
6
6
|
var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -44,7 +44,7 @@ var AMADEUS_CARD_URLS = Object.freeze({
|
|
|
44
44
|
})
|
|
45
45
|
});
|
|
46
46
|
var AMADEUS_MERCHANT_EXPIRY_POLICIES = Object.freeze(["refuse", "fill"]);
|
|
47
|
-
var AMADEUS_MERCHANT_EXPIRY_POLICY = "
|
|
47
|
+
var AMADEUS_MERCHANT_EXPIRY_POLICY = "fill";
|
|
48
48
|
var AMADEUS_REFUSAL_REASONS = Object.freeze([
|
|
49
49
|
"unsupported",
|
|
50
50
|
"card_on_file",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const BUILTIN_REGISTRY = [{ "psp": "spreedly", "match": /core\.spreedly\.com\/v1\/payment_methods\/restricted\.json/i, "hosts": ["^core\\.spreedly\\.com$"], "encoding": "json", "passthroughHeaders": [/^spreedly-environment-key$/i] }, { "psp": "shopify", "match": /(checkout\.pci\.shopifyinc\.com|deposit\.[a-z0-9-]+\.shopifycs\.com)\/sessions/i, "hosts": ["^checkout\\.pci\\.shopifyinc\\.com$", "^deposit\\.[a-z0-9-]+\\.shopifycs\\.com$"], "encoding": "json", "passthroughHeaders": [/^shopify-identification-signature$/i] }, { "psp": "stripe", "match": /api\.stripe\.com\/v1\/(payment_methods|tokens|sources|confirmation_tokens|setup_intents\/seti_\w+\/confirm|payment_intents\/pi_\w+\/confirm|payment_pages\/cs_(?:test|live)_\w+\/confirm)/i, "hosts": ["^api\\.stripe\\.com$"], "encoding": "form", "passthroughHeaders": [/^authorization$/i, /^stripe-version$/i, /^x-stripe-client-user-agent$/i], "cardFields": ["card[number]", "payment_method_data[card][number]"], "passWithoutCard": "api\\.stripe\\.com/v1/(sources|confirmation_tokens|payment_pages/cs_(?:test|live)_\\w+/confirm)" }, { "psp": "braintree", "match": /payments(\.sandbox)?\.braintree-api\.com\/graphql/i, "hosts": ["^payments\\.braintree-api\\.com$", "^payments\\.sandbox\\.braintree-api\\.com$"], "sandboxHosts": ["^payments\\.sandbox\\.braintree-api\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^braintree-version$/i] }, { "psp": "checkout_com", "match": /(api|card-acquisition-gateway)(\.sandbox)?\.checkout\.com\/tokens/i, "hosts": ["^api\\.checkout\\.com$", "^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "sandboxHosts": ["^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "adyen", "match": /(checkoutshopper-(test|live(-[a-z]+)?)\.adyen\.com|([a-z0-9-]+\.)*adyenpayments\.com)\/checkoutshopper\/v1\/sessions\/[A-Za-z0-9_-]+\/payments/i, "hosts": ["^checkoutshopper-(test|live(-[a-z]+)?)\\.adyen\\.com$", "^([a-z0-9-]+\\.)*adyenpayments\\.com$"], "sandboxHosts": ["^checkoutshopper-test\\.adyen\\.com$"], "encoding": "json", "passthroughHeaders": [], "clientSideEncrypted": true, "mode": "cse" }, { "psp": "tranzila", "match": /(direct\.tranzila\.com\/process\/n\/|directng\.tranzila\.com\/process\/?)/i, "hosts": ["^direct\\.tranzila\\.com$", "^directng\\.tranzila\\.com$"], "encoding": "form", "passthroughHeaders": [], "mode": "hosted_form" }, { "psp": "square", "match": /pci-connect\.squareup(?:sandbox)?\.com\/v2\/card-nonce/i, "hosts": ["^pci-connect\\.squareup\\.com$", "^pci-connect\\.squareupsandbox\\.com$"], "sandboxHosts": ["^pci-connect\\.squareupsandbox\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "authorize_net", "match": /(api2|apitest)\.authorize\.net\/xml\/v1\/request\.api/i, "hosts": ["^api2\\.authorize\\.net$", "^apitest\\.authorize\\.net$"], "sandboxHosts": ["^apitest\\.authorize\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "worldpay", "match": /(try\.)?access\.worldpay\.com\/(sessions\/card|verifiedTokens\/sessions)/i, "hosts": ["^access\\.worldpay\\.com$", "^try\\.access\\.worldpay\\.com$"], "sandboxHosts": ["^try\\.access\\.worldpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^accept$/i] }, { "psp": "nuvei", "match": /(secure|ppp-test)\.safecharge\.com\/ppp\/api\/v1\/(?:cardTokenization|clientPayment|websdk\/initPaymentWithCardTokenization)\.do/i, "hosts": ["^secure\\.safecharge\\.com$", "^ppp-test\\.safecharge\\.com$"], "sandboxHosts": ["^ppp-test\\.safecharge\\.com$"], "encoding": "json", "passthroughHeaders": [], "jsonCardFields": [["paymentOption", "card", "cardNumber"], ["cardData", "cardNumber"]], "passWithoutCard": "(?:secure|ppp-test)\\.safecharge\\.com/ppp/api/v1/(?:clientPayment|websdk/initPaymentWithCardTokenization)\\.do" }, { "psp": "airwallex", "match": /(checkout(\.sandbox)?\.airwallex\.com|pci-api(\.sandbox)?\.airwallex\.com)\/api\/v1\/pa\/(payment_intents\/[^/?#]+\/confirm|payment_consents\/[^/?#]+\/verify|payment_methods\/create)(\?|$)/i, "hosts": ["^checkout\\.airwallex\\.com$", "^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "sandboxHosts": ["^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "encoding": "json", "passthroughHeaders": [/^client-secret$/i, /^authorization$/i, /^x-auth-token$/i, /^x-on-behalf-of$/i, /^x-api-version$/i] }, { "psp": "rapyd", "match": /(api|sandboxapi)\.rapyd\.net\/v1\/(?:hosted\/collect\/card\/[^/?#]+\/payment_method|checkout\/checkout_[A-Za-z0-9]+)(?:[?#]|$)/i, "hosts": ["^api\\.rapyd\\.net$", "^sandboxapi\\.rapyd\\.net$"], "sandboxHosts": ["^sandboxapi\\.rapyd\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "dlocal", "match": /ppmcc(-sandbox)?\.dlocal\.com\/cvault\/credit-card\/temporal/i, "hosts": ["^ppmcc\\.dlocal\\.com$", "^ppmcc-sandbox\\.dlocal\\.com$"], "sandboxHosts": ["^ppmcc-sandbox\\.dlocal\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-fields-api-key$/i, /^x-uow$/i, /^x-dlocal-infrav2$/i] }, { "psp": "ebanx", "match": /(?:(?:customer-frontier|customer|api-local-latam|api|sandbox-local-latam|sandbox)\.ebanx\.com|(?:api-diamond|api|sandbox)\.ebanxpay\.com)\/ws\/token/i, "hosts": ["^customer\\.ebanx\\.com$", "^customer-frontier\\.ebanx\\.com$", "^api\\.ebanx\\.com$", "^sandbox\\.ebanx\\.com$", "^api-local-latam\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^api-diamond\\.ebanxpay\\.com$", "^api\\.ebanxpay\\.com$", "^sandbox\\.ebanxpay\\.com$"], "sandboxHosts": ["^sandbox\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^sandbox\\.ebanxpay\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "mercado_pago", "match": /api\.mercadopago\.com\/v1\/card_tokens(?![\w/-])/i, "hosts": ["^api\\.mercadopago\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-product-id$/i] }, { "psp": "payu", "match": /(secure\.payu\.com|(merch-prod|secure)\.snd\.payu\.com)\/api\/front\/tokens/i, "hosts": ["^secure\\.payu\\.com$", "^(merch-prod|secure)\\.snd\\.payu\\.com$"], "sandboxHosts": ["^(merch-prod|secure)\\.snd\\.payu\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "razorpay", "match": /api\.razorpay\.com\/v1\/(?:standard_checkout\/)?payments\/create\/(?:ajax|checkout|fees)/i, "hosts": ["^api\\.razorpay\\.com$"], "encoding": "form", "passthroughHeaders": [/^x-razorpay-sessionid$/i, /^x-customer-access-token$/i] }, { "psp": "mollie", "match": /api\.cc\.mollie\.com\/v1\/card-tokens/i, "hosts": ["^api\\.cc\\.mollie\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "paysafe", "match": /(?:api(\.test)?\.paysafe\.com\/(?:paymenthub\/v1\/singleusepaymenthandles|js\/api\/v1\/tokenize)|hosted(\.test)?\.paysafe\.com\/checkout\/api\/v1\/tokenize)(?![\w/-])/i, "hosts": ["^api\\.paysafe\\.com$", "^api\\.test\\.paysafe\\.com$", "^hosted\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "sandboxHosts": ["^api\\.test\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-paysafe-credentials$/i, /^correlationid$/i] }, { "psp": "recurly", "match": /api(\.eu)?\.recurly\.com\/js\/v1\/token(?![\w-])/i, "hosts": ["^api\\.recurly\\.com$", "^api\\.eu\\.recurly\\.com$"], "encoding": "form", "passthroughHeaders": [/^recurly-credential-checkout-hostname$/i] }, { "psp": "
|
|
1
|
+
export const BUILTIN_REGISTRY = [{ "psp": "spreedly", "match": /core\.spreedly\.com\/v1\/payment_methods\/restricted\.json/i, "hosts": ["^core\\.spreedly\\.com$"], "encoding": "json", "passthroughHeaders": [/^spreedly-environment-key$/i] }, { "psp": "shopify", "match": /(checkout\.pci\.shopifyinc\.com|deposit\.[a-z0-9-]+\.shopifycs\.com)\/sessions/i, "hosts": ["^checkout\\.pci\\.shopifyinc\\.com$", "^deposit\\.[a-z0-9-]+\\.shopifycs\\.com$"], "encoding": "json", "passthroughHeaders": [/^shopify-identification-signature$/i] }, { "psp": "stripe", "match": /api\.stripe\.com\/v1\/(payment_methods|tokens|sources|confirmation_tokens|setup_intents\/seti_\w+\/confirm|payment_intents\/pi_\w+\/confirm|payment_pages\/cs_(?:test|live)_\w+\/confirm)/i, "hosts": ["^api\\.stripe\\.com$"], "encoding": "form", "passthroughHeaders": [/^authorization$/i, /^stripe-version$/i, /^x-stripe-client-user-agent$/i], "cardFields": ["card[number]", "payment_method_data[card][number]"], "passWithoutCard": "api\\.stripe\\.com/v1/(sources|confirmation_tokens|payment_pages/cs_(?:test|live)_\\w+/confirm)" }, { "psp": "braintree", "match": /payments(\.sandbox)?\.braintree-api\.com\/graphql/i, "hosts": ["^payments\\.braintree-api\\.com$", "^payments\\.sandbox\\.braintree-api\\.com$"], "sandboxHosts": ["^payments\\.sandbox\\.braintree-api\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^braintree-version$/i] }, { "psp": "checkout_com", "match": /(api|card-acquisition-gateway)(\.sandbox)?\.checkout\.com\/tokens/i, "hosts": ["^api\\.checkout\\.com$", "^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "sandboxHosts": ["^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "adyen", "match": /(checkoutshopper-(test|live(-[a-z]+)?)\.adyen\.com|([a-z0-9-]+\.)*adyenpayments\.com)\/checkoutshopper\/v1\/sessions\/[A-Za-z0-9_-]+\/payments/i, "hosts": ["^checkoutshopper-(test|live(-[a-z]+)?)\\.adyen\\.com$", "^([a-z0-9-]+\\.)*adyenpayments\\.com$"], "sandboxHosts": ["^checkoutshopper-test\\.adyen\\.com$"], "encoding": "json", "passthroughHeaders": [], "clientSideEncrypted": true, "mode": "cse" }, { "psp": "tranzila", "match": /(direct\.tranzila\.com\/process\/n\/|directng\.tranzila\.com\/process\/?)/i, "hosts": ["^direct\\.tranzila\\.com$", "^directng\\.tranzila\\.com$"], "encoding": "form", "passthroughHeaders": [], "mode": "hosted_form" }, { "psp": "square", "match": /pci-connect\.squareup(?:sandbox)?\.com\/v2\/card-nonce/i, "hosts": ["^pci-connect\\.squareup\\.com$", "^pci-connect\\.squareupsandbox\\.com$"], "sandboxHosts": ["^pci-connect\\.squareupsandbox\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "authorize_net", "match": /(api2|apitest)\.authorize\.net\/xml\/v1\/request\.api/i, "hosts": ["^api2\\.authorize\\.net$", "^apitest\\.authorize\\.net$"], "sandboxHosts": ["^apitest\\.authorize\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "worldpay", "match": /(try\.)?access\.worldpay\.com\/(sessions\/card|verifiedTokens\/sessions)/i, "hosts": ["^access\\.worldpay\\.com$", "^try\\.access\\.worldpay\\.com$"], "sandboxHosts": ["^try\\.access\\.worldpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^accept$/i] }, { "psp": "nuvei", "match": /(secure|ppp-test)\.safecharge\.com\/ppp\/api\/v1\/(?:cardTokenization|clientPayment|websdk\/initPaymentWithCardTokenization)\.do/i, "hosts": ["^secure\\.safecharge\\.com$", "^ppp-test\\.safecharge\\.com$"], "sandboxHosts": ["^ppp-test\\.safecharge\\.com$"], "encoding": "json", "passthroughHeaders": [], "jsonCardFields": [["paymentOption", "card", "cardNumber"], ["cardData", "cardNumber"]], "passWithoutCard": "(?:secure|ppp-test)\\.safecharge\\.com/ppp/api/v1/(?:clientPayment|websdk/initPaymentWithCardTokenization)\\.do" }, { "psp": "airwallex", "match": /(checkout(\.sandbox)?\.airwallex\.com|pci-api(\.sandbox)?\.airwallex\.com)\/api\/v1\/pa\/(payment_intents\/[^/?#]+\/confirm|payment_consents\/[^/?#]+\/verify|payment_methods\/create)(\?|$)/i, "hosts": ["^checkout\\.airwallex\\.com$", "^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "sandboxHosts": ["^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "encoding": "json", "passthroughHeaders": [/^client-secret$/i, /^authorization$/i, /^x-auth-token$/i, /^x-on-behalf-of$/i, /^x-api-version$/i] }, { "psp": "rapyd", "match": /(api|sandboxapi)\.rapyd\.net\/v1\/(?:hosted\/collect\/card\/[^/?#]+\/payment_method|checkout\/checkout_[A-Za-z0-9]+)(?:[?#]|$)/i, "hosts": ["^api\\.rapyd\\.net$", "^sandboxapi\\.rapyd\\.net$"], "sandboxHosts": ["^sandboxapi\\.rapyd\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "dlocal", "match": /ppmcc(-sandbox)?\.dlocal\.com\/cvault\/credit-card\/temporal/i, "hosts": ["^ppmcc\\.dlocal\\.com$", "^ppmcc-sandbox\\.dlocal\\.com$"], "sandboxHosts": ["^ppmcc-sandbox\\.dlocal\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-fields-api-key$/i, /^x-uow$/i, /^x-dlocal-infrav2$/i] }, { "psp": "ebanx", "match": /(?:(?:customer-frontier|customer|api-local-latam|api|sandbox-local-latam|sandbox)\.ebanx\.com|(?:api-diamond|api|sandbox)\.ebanxpay\.com)\/ws\/token/i, "hosts": ["^customer\\.ebanx\\.com$", "^customer-frontier\\.ebanx\\.com$", "^api\\.ebanx\\.com$", "^sandbox\\.ebanx\\.com$", "^api-local-latam\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^api-diamond\\.ebanxpay\\.com$", "^api\\.ebanxpay\\.com$", "^sandbox\\.ebanxpay\\.com$"], "sandboxHosts": ["^sandbox\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^sandbox\\.ebanxpay\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "mercado_pago", "match": /api\.mercadopago\.com\/v1\/card_tokens(?![\w/-])/i, "hosts": ["^api\\.mercadopago\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-product-id$/i] }, { "psp": "payu", "match": /(secure\.payu\.com|(merch-prod|secure)\.snd\.payu\.com)\/api\/front\/tokens/i, "hosts": ["^secure\\.payu\\.com$", "^(merch-prod|secure)\\.snd\\.payu\\.com$"], "sandboxHosts": ["^(merch-prod|secure)\\.snd\\.payu\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "razorpay", "match": /api\.razorpay\.com\/v1\/(?:standard_checkout\/)?payments\/create\/(?:ajax|checkout|fees)/i, "hosts": ["^api\\.razorpay\\.com$"], "encoding": "form", "passthroughHeaders": [/^x-razorpay-sessionid$/i, /^x-customer-access-token$/i] }, { "psp": "mollie", "match": /api\.cc\.mollie\.com\/v1\/card-tokens/i, "hosts": ["^api\\.cc\\.mollie\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "paysafe", "match": /(?:api(\.test)?\.paysafe\.com\/(?:paymenthub\/v1\/singleusepaymenthandles|js\/api\/v1\/tokenize)|hosted(\.test)?\.paysafe\.com\/checkout\/api\/v1\/tokenize)(?![\w/-])/i, "hosts": ["^api\\.paysafe\\.com$", "^api\\.test\\.paysafe\\.com$", "^hosted\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "sandboxHosts": ["^api\\.test\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-paysafe-credentials$/i, /^correlationid$/i] }, { "psp": "recurly", "match": /api(\.eu)?\.recurly\.com\/js\/v1\/token(?![\w-])/i, "hosts": ["^api\\.recurly\\.com$", "^api\\.eu\\.recurly\\.com$"], "encoding": "form", "passthroughHeaders": [/^recurly-credential-checkout-hostname$/i] }, { "psp": "bambora", "match": /(api\.na\.bambora\.com|api\.bam\.shift4api\.net)\/scripts\/tokenization\/tokens/i, "hosts": ["^api\\.na\\.bambora\\.com$", "^api\\.bam\\.shift4api\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "global_payments", "match": /(?:api\.heartlandportico\.com\/SecureSubmit\.v1\/api\/token|cert\.api2\.heartlandportico\.com\/Hps\.Exchange\.PosGateway\.Hpf\.v1\/api\/token|apis(?:\.sandbox)?(?:\.eu)?\.globalpay\.com\/ucp\/(?:merchants\/[^/]+\/)?payment-methods)/i, "hosts": ["^api\\.heartlandportico\\.com$", "^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.globalpay\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.eu\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "sandboxHosts": ["^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-gp-version$/i] }];
|
|
@@ -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: 6a0cf6104aac41a93fb4788532c63075d6831419127b76b87228dd7839c2a106
|
|
4
4
|
// src/card-number-key.js
|
|
5
5
|
var CARD_NUMBER_KEY = /^(number|card_number|cardnumber|cardNum|card_num|pan)$/i;
|
|
6
6
|
// src/json-path.js
|
|
@@ -29,7 +29,8 @@ function jsonAt(root, path) {
|
|
|
29
29
|
// src/elavon-converge.js
|
|
30
30
|
var CONVERGE_PROCESS_URLS = /* @__PURE__ */ Object.freeze([
|
|
31
31
|
"https://api.convergepay.com/hosted-payments/service/payment/hpp/process",
|
|
32
|
-
"https://api.demo.convergepay.com/hosted-payments/service/payment/hpp/process"
|
|
32
|
+
"https://api.demo.convergepay.com/hosted-payments/service/payment/hpp/process",
|
|
33
|
+
"https://www.convergepay.com/hosted-payments/service/payment/hpp/process"
|
|
33
34
|
]);
|
|
34
35
|
var TOP_LEVEL_KEYS = /* @__PURE__ */ Object.freeze(["paymentType", "paymentData", "context", "captchaToken", "shippingSameAsBilling"]);
|
|
35
36
|
var WALLET_FIELDS = /* @__PURE__ */ Object.freeze([
|
|
@@ -70,6 +71,7 @@ var RECURRING_FIELDS = /* @__PURE__ */ Object.freeze([
|
|
|
70
71
|
"ssl_recurring_batch_count",
|
|
71
72
|
"ssl_installment_id"
|
|
72
73
|
]);
|
|
74
|
+
var ONE_TIME_RECURRING_FLAG = "false";
|
|
73
75
|
var CARD_SAVING_FLAGS = /* @__PURE__ */ Object.freeze(["ssl_get_token", "ssl_add_token"]);
|
|
74
76
|
var CREDENTIAL_FIELDS = /* @__PURE__ */ Object.freeze(["ssl_account_id", "ssl_merchant_id", "ssl_user_id", "ssl_pin", "ssl_vendor_id"]);
|
|
75
77
|
var AMOUNT_ADD_ON_FIELDS = /* @__PURE__ */ Object.freeze(["ssl_tip_amount", "ssl_cashback_amount"]);
|
|
@@ -79,6 +81,7 @@ var CVC = /^\d{3,4}$/;
|
|
|
79
81
|
var AMOUNT = /^(\d{1,13})(?:\.(\d{1,2}))?$/;
|
|
80
82
|
var isRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
81
83
|
var owns = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
84
|
+
var recurringRequested = (data) => RECURRING_FIELDS.some((key) => owns(data, key) && !(key === "recurring" && data[key] === ONE_TIME_RECURRING_FLAG));
|
|
82
85
|
var refuse = (code) => Object.freeze({ verdict: "refuse", code });
|
|
83
86
|
var CARD = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
84
87
|
var CONTINUE = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
@@ -140,7 +143,7 @@ function convergeBodyVerdict(body) {
|
|
|
140
143
|
if (owns(data, "ssl_token") || CARD_SAVING_FLAGS.some((key) => owns(data, key) && !(typeof data[key] === "string" && /^n$/i.test(data[key])))) {
|
|
141
144
|
return refuse("converge_card_saving_refused");
|
|
142
145
|
}
|
|
143
|
-
if (
|
|
146
|
+
if (recurringRequested(data))
|
|
144
147
|
return refuse("converge_recurring_refused");
|
|
145
148
|
if (owns(data, "ssl_transaction_currency") && !(typeof data.ssl_transaction_currency === "string" && /^usd$/i.test(data.ssl_transaction_currency))) {
|
|
146
149
|
return refuse("converge_currency_refused");
|
|
@@ -169,11 +172,155 @@ function isConvergeProcessUrl(url) {
|
|
|
169
172
|
}
|
|
170
173
|
return parsed.href === url && CONVERGE_PROCESS_URLS.includes(parsed.href);
|
|
171
174
|
}
|
|
172
|
-
// src/
|
|
173
|
-
var
|
|
175
|
+
// src/gravy.js
|
|
176
|
+
var GRAVY_PSP = "gravy";
|
|
177
|
+
var BODY_LIMIT = 4096;
|
|
178
|
+
var CARD_KEYS = /* @__PURE__ */ Object.freeze(["method", "number", "expiration_date", "security_code"]);
|
|
179
|
+
var ROOT_KEYS = /* @__PURE__ */ Object.freeze(["payment_method", "postal_code"]);
|
|
180
|
+
var CARD_NUMBER2 = /^[0-9]{12,19}$/;
|
|
181
|
+
var EXPIRY = /^(?:0[1-9]|1[0-2])\/[0-9]{2}$/;
|
|
182
|
+
var SECURITY_CODE = /^[0-9]{3,4}$/;
|
|
183
|
+
var POSTAL_CODE = /^[A-Za-z0-9 -]{0,16}$/;
|
|
184
|
+
var PAN_LIKE = /(?:[0-9][ _.:-]*){12,}/;
|
|
185
|
+
var EXPIRY_OR_CODE = /^(?:expiration_?date|expiry(?:_?date)?|exp_?date|card_?expiry|security_?code|cvc|cvc2|cvv|cvv2|cvd|card_?cvv|card_?cvc|verification_?value)$/i;
|
|
174
186
|
var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
175
187
|
var owns2 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
176
|
-
|
|
188
|
+
function cardNamed(key) {
|
|
189
|
+
const name = key.slice(key.lastIndexOf(".") + 1);
|
|
190
|
+
return CARD_NUMBER_KEY.test(name) || /cardnumber$/i.test(name) || EXPIRY_OR_CODE.test(name);
|
|
191
|
+
}
|
|
192
|
+
function cardOutside(root) {
|
|
193
|
+
const pending = [];
|
|
194
|
+
for (const key of Object.keys(root)) {
|
|
195
|
+
const value = root[key];
|
|
196
|
+
if (key === "payment_method" && record(value)) {
|
|
197
|
+
for (const inner of Object.keys(value))
|
|
198
|
+
if (!CARD_KEYS.includes(inner))
|
|
199
|
+
pending.push([inner, value[inner]]);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
pending.push([key, value]);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
while (pending.length > 0) {
|
|
206
|
+
const [key, value] = pending.pop();
|
|
207
|
+
if (key !== null && cardNamed(key))
|
|
208
|
+
return true;
|
|
209
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
210
|
+
if (PAN_LIKE.test(String(value)))
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
else if (Array.isArray(value)) {
|
|
214
|
+
for (const item of value)
|
|
215
|
+
pending.push([null, item]);
|
|
216
|
+
}
|
|
217
|
+
else if (record(value)) {
|
|
218
|
+
for (const inner of Object.keys(value))
|
|
219
|
+
pending.push([inner, value[inner]]);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
function readBody(body) {
|
|
225
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT)
|
|
226
|
+
return null;
|
|
227
|
+
let value;
|
|
228
|
+
try {
|
|
229
|
+
value = JSON.parse(body);
|
|
230
|
+
if (!record(value) || JSON.stringify(value) !== body)
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
var refuse2 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
239
|
+
var CARD2 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
240
|
+
function gravyBodyVerdict(body) {
|
|
241
|
+
const value = readBody(body);
|
|
242
|
+
if (value === null)
|
|
243
|
+
return refuse2("gravy_body_unsupported");
|
|
244
|
+
if (cardOutside(value))
|
|
245
|
+
return refuse2("gravy_card_outside_payment_method");
|
|
246
|
+
const card = value.payment_method;
|
|
247
|
+
if (!record(card) || card.method !== "card" || !CARD_KEYS.every((key) => owns2(card, key)))
|
|
248
|
+
return refuse2("gravy_new_card_missing");
|
|
249
|
+
if (!Object.keys(value).every((key) => ROOT_KEYS.includes(key)) || !Object.keys(card).every((key) => CARD_KEYS.includes(key)) || typeof card.number !== "string" || !CARD_NUMBER2.test(card.number) || typeof card.expiration_date !== "string" || !EXPIRY.test(card.expiration_date) || typeof card.security_code !== "string" || !SECURITY_CODE.test(card.security_code) || owns2(value, "postal_code") && (typeof value.postal_code !== "string" || !POSTAL_CODE.test(value.postal_code))) {
|
|
250
|
+
return refuse2("gravy_body_unsupported");
|
|
251
|
+
}
|
|
252
|
+
return CARD2;
|
|
253
|
+
}
|
|
254
|
+
// src/moneris.js
|
|
255
|
+
var MONERIS_PSP = "moneris";
|
|
256
|
+
var CARD_KEYS2 = /* @__PURE__ */ Object.freeze(["input_data", "input_exp", "input_cvd", "hpt_id", "hpt_ticket", "doTokenize"]);
|
|
257
|
+
var PARTIAL_KEYS = /* @__PURE__ */ Object.freeze([
|
|
258
|
+
["input_data", "hpt_id", "hpt_ticket", "doTokenize"],
|
|
259
|
+
["input_data", "input_exp", "hpt_id", "hpt_ticket", "doTokenize"],
|
|
260
|
+
["input_data", "input_cvd", "hpt_id", "hpt_ticket", "doTokenize"]
|
|
261
|
+
]);
|
|
262
|
+
var CARD_NUMBER3 = /^\d{12,19}$/;
|
|
263
|
+
var GROUPED_DIGITS = /^\d+(?: \d+)*$/;
|
|
264
|
+
var EXPIRY_MMYY2 = /^(0[1-9]|1[0-2])\d{2}$/;
|
|
265
|
+
var CVD = /^\d{3,4}$/;
|
|
266
|
+
var PROFILE_ID = /^ht[A-Za-z0-9]{1,64}$/;
|
|
267
|
+
var TICKET = /^tt[A-Za-z0-9]{1,128}$/;
|
|
268
|
+
var refuse3 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
269
|
+
var CARD3 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
270
|
+
function readPairs(body) {
|
|
271
|
+
if (typeof body !== "string" || body === "" || body.length > 4096)
|
|
272
|
+
return null;
|
|
273
|
+
const pairs = [];
|
|
274
|
+
for (const chunk of body.split("&")) {
|
|
275
|
+
const eq = chunk.indexOf("=");
|
|
276
|
+
if (eq <= 0)
|
|
277
|
+
return null;
|
|
278
|
+
pairs.push([chunk.slice(0, eq), chunk.slice(eq + 1)]);
|
|
279
|
+
}
|
|
280
|
+
return pairs;
|
|
281
|
+
}
|
|
282
|
+
var hasKeys = (pairs, keys) => pairs.length === keys.length && pairs.every(([key], at) => key === keys[at]);
|
|
283
|
+
function monerisBodyVerdict(body) {
|
|
284
|
+
const pairs = readPairs(body);
|
|
285
|
+
if (pairs === null)
|
|
286
|
+
return refuse3("moneris_body_malformed");
|
|
287
|
+
if (PARTIAL_KEYS.some((keys) => hasKeys(pairs, keys)))
|
|
288
|
+
return refuse3("moneris_partial_card");
|
|
289
|
+
if (!hasKeys(pairs, CARD_KEYS2))
|
|
290
|
+
return refuse3("moneris_body_malformed");
|
|
291
|
+
const [[, number], [, expiry], [, cvd], [, profile], [, ticket], [, tokenize]] = pairs;
|
|
292
|
+
if (!GROUPED_DIGITS.test(number) || !CARD_NUMBER3.test(number.replace(/ /g, "")) || !EXPIRY_MMYY2.test(expiry) || !CVD.test(cvd) || !PROFILE_ID.test(profile) || !TICKET.test(ticket) || tokenize !== "true")
|
|
293
|
+
return refuse3("moneris_body_malformed");
|
|
294
|
+
return CARD3;
|
|
295
|
+
}
|
|
296
|
+
var MONERIS_TOKENIZE_HOSTS = /* @__PURE__ */ Object.freeze({
|
|
297
|
+
production: Object.freeze(["www3.moneris.com", "gateway.moneris.com"]),
|
|
298
|
+
sandbox: Object.freeze(["esqa.moneris.com"])
|
|
299
|
+
});
|
|
300
|
+
var MONERIS_TOKENIZE_PATH = "/HPPtoken/request.php";
|
|
301
|
+
function monerisTokenizeEnvironment(url) {
|
|
302
|
+
if (typeof url !== "string")
|
|
303
|
+
return null;
|
|
304
|
+
for (const environment of
|
|
305
|
+
/** @type {const} */
|
|
306
|
+
["production", "sandbox"]) {
|
|
307
|
+
if (MONERIS_TOKENIZE_HOSTS[environment].some((host) => url === `https://${host}${MONERIS_TOKENIZE_PATH}`))
|
|
308
|
+
return environment;
|
|
309
|
+
}
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
function isMonerisTokenizeUrl(url) {
|
|
313
|
+
return monerisTokenizeEnvironment(url) !== null;
|
|
314
|
+
}
|
|
315
|
+
var pin = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fields.origins]), profileIds: Object.freeze([...fields.profileIds]) });
|
|
316
|
+
var MONERIS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
317
|
+
pin({ id: "jack_org_raisin", merchant: "Jack.org", origins: ["https://jack.akaraisin.com"], profileIds: ["htL7TR9H7ICYN2B"] })
|
|
318
|
+
]);
|
|
319
|
+
// src/amadeus-body.js
|
|
320
|
+
var AMADEUS_CARD_MOPID = /^creditcard[0-9]*$/;
|
|
321
|
+
var record2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
322
|
+
var owns3 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
323
|
+
var holdsPan = (mopdata) => record2(mopdata) && owns3(mopdata, "pan") && mopdata.pan !== null && mopdata.pan !== "";
|
|
177
324
|
function amadeusBodyKind(body) {
|
|
178
325
|
let value;
|
|
179
326
|
try {
|
|
@@ -182,18 +329,25 @@ function amadeusBodyKind(body) {
|
|
|
182
329
|
catch {
|
|
183
330
|
return "card";
|
|
184
331
|
}
|
|
185
|
-
if (!
|
|
332
|
+
if (!record2(value))
|
|
186
333
|
return "card";
|
|
187
334
|
if (value.action === "add") {
|
|
188
335
|
const entries = Array.isArray(value.data) ? value.data : [value.data];
|
|
189
|
-
return entries.some((entry) =>
|
|
336
|
+
return entries.some((entry) => record2(entry) && typeof entry.mopid === "string" && AMADEUS_CARD_MOPID.test(entry.mopid) && holdsPan(entry.mopdata)) ? "card" : "other";
|
|
190
337
|
}
|
|
191
338
|
if (value.action === "store")
|
|
192
|
-
return
|
|
339
|
+
return record2(value.data) && holdsPan(value.data.mopdata) ? "card" : "other";
|
|
193
340
|
return "other";
|
|
194
341
|
}
|
|
195
342
|
// src/card-fields.js
|
|
196
343
|
function processorGate(recognizer, url, body) {
|
|
344
|
+
if (recognizer && recognizer.psp === GRAVY_PSP)
|
|
345
|
+
return gravyBodyVerdict(body);
|
|
346
|
+
if (recognizer && recognizer.psp === MONERIS_PSP) {
|
|
347
|
+
if (url !== void 0 && !isMonerisTokenizeUrl(url))
|
|
348
|
+
return { verdict: "refuse", code: "moneris_url_refused" };
|
|
349
|
+
return monerisBodyVerdict(body);
|
|
350
|
+
}
|
|
197
351
|
if (!recognizer || recognizer.psp !== "elavon_converge")
|
|
198
352
|
return null;
|
|
199
353
|
if (url !== void 0 && !isConvergeProcessUrl(url))
|