@atbas/m-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +364 -0
- package/dist/builder/transaction-builder.d.ts +53 -0
- package/dist/builder/transaction-builder.d.ts.map +1 -0
- package/dist/builder/transaction-builder.js +159 -0
- package/dist/builder/transaction-builder.js.map +1 -0
- package/dist/catalogue/default-catalogue.d.ts +18 -0
- package/dist/catalogue/default-catalogue.d.ts.map +1 -0
- package/dist/catalogue/default-catalogue.js +21 -0
- package/dist/catalogue/default-catalogue.js.map +1 -0
- package/dist/catalogue/endpoints.d.ts +22 -0
- package/dist/catalogue/endpoints.d.ts.map +1 -0
- package/dist/catalogue/endpoints.js +24 -0
- package/dist/catalogue/endpoints.js.map +1 -0
- package/dist/catalogue/flows.d.ts +32 -0
- package/dist/catalogue/flows.d.ts.map +1 -0
- package/dist/catalogue/flows.js +64 -0
- package/dist/catalogue/flows.js.map +1 -0
- package/dist/catalogue/hash-options.d.ts +112 -0
- package/dist/catalogue/hash-options.d.ts.map +1 -0
- package/dist/catalogue/hash-options.js +151 -0
- package/dist/catalogue/hash-options.js.map +1 -0
- package/dist/catalogue/types.d.ts +279 -0
- package/dist/catalogue/types.d.ts.map +1 -0
- package/dist/catalogue/types.js +360 -0
- package/dist/catalogue/types.js.map +1 -0
- package/dist/codegen/generate.d.ts +14 -0
- package/dist/codegen/generate.d.ts.map +1 -0
- package/dist/codegen/generate.js +490 -0
- package/dist/codegen/generate.js.map +1 -0
- package/dist/codegen/languages/node.d.ts +3 -0
- package/dist/codegen/languages/node.d.ts.map +1 -0
- package/dist/codegen/languages/node.js +32 -0
- package/dist/codegen/languages/node.js.map +1 -0
- package/dist/codegen/languages/php.d.ts +3 -0
- package/dist/codegen/languages/php.d.ts.map +1 -0
- package/dist/codegen/languages/php.js +27 -0
- package/dist/codegen/languages/php.js.map +1 -0
- package/dist/codegen/languages/python.d.ts +3 -0
- package/dist/codegen/languages/python.d.ts.map +1 -0
- package/dist/codegen/languages/python.js +27 -0
- package/dist/codegen/languages/python.js.map +1 -0
- package/dist/codegen/renderer.d.ts +24 -0
- package/dist/codegen/renderer.d.ts.map +1 -0
- package/dist/codegen/renderer.js +59 -0
- package/dist/codegen/renderer.js.map +1 -0
- package/dist/codegen/types.d.ts +50 -0
- package/dist/codegen/types.d.ts.map +1 -0
- package/dist/codegen/types.js +5 -0
- package/dist/codegen/types.js.map +1 -0
- package/dist/config/credentials.d.ts +64 -0
- package/dist/config/credentials.d.ts.map +1 -0
- package/dist/config/credentials.js +216 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/environment.d.ts +23 -0
- package/dist/config/environment.d.ts.map +1 -0
- package/dist/config/environment.js +54 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/core/dependencies.d.ts +43 -0
- package/dist/core/dependencies.d.ts.map +1 -0
- package/dist/core/dependencies.js +2 -0
- package/dist/core/dependencies.js.map +1 -0
- package/dist/core/registry.d.ts +33 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +13 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/server.d.ts +61 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +90 -0
- package/dist/core/server.js.map +1 -0
- package/dist/dependencies.d.ts +28 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +2 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/diagnostics/diagnose.d.ts +43 -0
- package/dist/diagnostics/diagnose.d.ts.map +1 -0
- package/dist/diagnostics/diagnose.js +121 -0
- package/dist/diagnostics/diagnose.js.map +1 -0
- package/dist/domain/amount.d.ts +157 -0
- package/dist/domain/amount.d.ts.map +1 -0
- package/dist/domain/amount.js +275 -0
- package/dist/domain/amount.js.map +1 -0
- package/dist/domain/datetime.d.ts +95 -0
- package/dist/domain/datetime.d.ts.map +1 -0
- package/dist/domain/datetime.js +211 -0
- package/dist/domain/datetime.js.map +1 -0
- package/dist/domain/response-codes.d.ts +116 -0
- package/dist/domain/response-codes.d.ts.map +1 -0
- package/dist/domain/response-codes.js +380 -0
- package/dist/domain/response-codes.js.map +1 -0
- package/dist/domain/secure-hash.d.ts +78 -0
- package/dist/domain/secure-hash.d.ts.map +1 -0
- package/dist/domain/secure-hash.js +69 -0
- package/dist/domain/secure-hash.js.map +1 -0
- package/dist/domain/signature/jazzcash.d.ts +56 -0
- package/dist/domain/signature/jazzcash.d.ts.map +1 -0
- package/dist/domain/signature/jazzcash.js +214 -0
- package/dist/domain/signature/jazzcash.js.map +1 -0
- package/dist/domain/signature/registry.d.ts +69 -0
- package/dist/domain/signature/registry.d.ts.map +1 -0
- package/dist/domain/signature/registry.js +92 -0
- package/dist/domain/signature/registry.js.map +1 -0
- package/dist/domain/signature/scheme.d.ts +349 -0
- package/dist/domain/signature/scheme.d.ts.map +1 -0
- package/dist/domain/signature/scheme.js +398 -0
- package/dist/domain/signature/scheme.js.map +1 -0
- package/dist/domain/txn-ref.d.ts +76 -0
- package/dist/domain/txn-ref.d.ts.map +1 -0
- package/dist/domain/txn-ref.js +126 -0
- package/dist/domain/txn-ref.js.map +1 -0
- package/dist/domain/types.d.ts +45 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/domain/types.js +70 -0
- package/dist/domain/types.js.map +1 -0
- package/dist/errors.d.ts +84 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +87 -0
- package/dist/errors.js.map +1 -0
- package/dist/gateway/checkout-form.d.ts +16 -0
- package/dist/gateway/checkout-form.d.ts.map +1 -0
- package/dist/gateway/checkout-form.js +103 -0
- package/dist/gateway/checkout-form.js.map +1 -0
- package/dist/gateway/checkout-output.d.ts +70 -0
- package/dist/gateway/checkout-output.d.ts.map +1 -0
- package/dist/gateway/checkout-output.js +199 -0
- package/dist/gateway/checkout-output.js.map +1 -0
- package/dist/gateway/guards.d.ts +37 -0
- package/dist/gateway/guards.d.ts.map +1 -0
- package/dist/gateway/guards.js +44 -0
- package/dist/gateway/guards.js.map +1 -0
- package/dist/gateway/http-client.d.ts +42 -0
- package/dist/gateway/http-client.d.ts.map +1 -0
- package/dist/gateway/http-client.js +153 -0
- package/dist/gateway/http-client.js.map +1 -0
- package/dist/gateway/rest-client.d.ts +42 -0
- package/dist/gateway/rest-client.d.ts.map +1 -0
- package/dist/gateway/rest-client.js +241 -0
- package/dist/gateway/rest-client.js.map +1 -0
- package/dist/gateway/transport.d.ts +31 -0
- package/dist/gateway/transport.d.ts.map +1 -0
- package/dist/gateway/transport.js +73 -0
- package/dist/gateway/transport.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -0
- package/dist/install/cli.d.ts +38 -0
- package/dist/install/cli.d.ts.map +1 -0
- package/dist/install/cli.js +274 -0
- package/dist/install/cli.js.map +1 -0
- package/dist/install/harnesses.d.ts +74 -0
- package/dist/install/harnesses.d.ts.map +1 -0
- package/dist/install/harnesses.js +263 -0
- package/dist/install/harnesses.js.map +1 -0
- package/dist/knowledge/corpus.d.ts +15 -0
- package/dist/knowledge/corpus.d.ts.map +1 -0
- package/dist/knowledge/corpus.js +129 -0
- package/dist/knowledge/corpus.js.map +1 -0
- package/dist/knowledge/search.d.ts +29 -0
- package/dist/knowledge/search.d.ts.map +1 -0
- package/dist/knowledge/search.js +181 -0
- package/dist/knowledge/search.js.map +1 -0
- package/dist/knowledge/source.d.ts +60 -0
- package/dist/knowledge/source.d.ts.map +1 -0
- package/dist/knowledge/source.js +91 -0
- package/dist/knowledge/source.js.map +1 -0
- package/dist/knowledge/types.d.ts +40 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +19 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/paths.d.ts +26 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +106 -0
- package/dist/paths.js.map +1 -0
- package/dist/prompts/integration-walkthrough.d.ts +11 -0
- package/dist/prompts/integration-walkthrough.d.ts.map +1 -0
- package/dist/prompts/integration-walkthrough.js +52 -0
- package/dist/prompts/integration-walkthrough.js.map +1 -0
- package/dist/prompts/register.d.ts +4 -0
- package/dist/prompts/register.d.ts.map +1 -0
- package/dist/prompts/register.js +4 -0
- package/dist/prompts/register.js.map +1 -0
- package/dist/registry.d.ts +14 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +2 -0
- package/dist/registry.js.map +1 -0
- package/dist/resources/knowledge-resources.d.ts +5 -0
- package/dist/resources/knowledge-resources.d.ts.map +1 -0
- package/dist/resources/knowledge-resources.js +121 -0
- package/dist/resources/knowledge-resources.js.map +1 -0
- package/dist/resources/register.d.ts +4 -0
- package/dist/resources/register.d.ts.map +1 -0
- package/dist/resources/register.js +8 -0
- package/dist/resources/register.js.map +1 -0
- package/dist/server.d.ts +40 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +56 -0
- package/dist/server.js.map +1 -0
- package/dist/telemetry/logger.d.ts +31 -0
- package/dist/telemetry/logger.d.ts.map +1 -0
- package/dist/telemetry/logger.js +67 -0
- package/dist/telemetry/logger.js.map +1 -0
- package/dist/telemetry/redaction.d.ts +88 -0
- package/dist/telemetry/redaction.d.ts.map +1 -0
- package/dist/telemetry/redaction.js +238 -0
- package/dist/telemetry/redaction.js.map +1 -0
- package/dist/tools/build-transaction-parameters.d.ts +10 -0
- package/dist/tools/build-transaction-parameters.d.ts.map +1 -0
- package/dist/tools/build-transaction-parameters.js +154 -0
- package/dist/tools/build-transaction-parameters.js.map +1 -0
- package/dist/tools/call-context.d.ts +47 -0
- package/dist/tools/call-context.d.ts.map +1 -0
- package/dist/tools/call-context.js +15 -0
- package/dist/tools/call-context.js.map +1 -0
- package/dist/tools/codegen-tools.d.ts +4 -0
- package/dist/tools/codegen-tools.d.ts.map +1 -0
- package/dist/tools/codegen-tools.js +131 -0
- package/dist/tools/codegen-tools.js.map +1 -0
- package/dist/tools/credential-tools.d.ts +32 -0
- package/dist/tools/credential-tools.d.ts.map +1 -0
- package/dist/tools/credential-tools.js +65 -0
- package/dist/tools/credential-tools.js.map +1 -0
- package/dist/tools/descriptor.d.ts +52 -0
- package/dist/tools/descriptor.d.ts.map +1 -0
- package/dist/tools/descriptor.js +2 -0
- package/dist/tools/descriptor.js.map +1 -0
- package/dist/tools/diagnostic-tools.d.ts +3 -0
- package/dist/tools/diagnostic-tools.d.ts.map +1 -0
- package/dist/tools/diagnostic-tools.js +128 -0
- package/dist/tools/diagnostic-tools.js.map +1 -0
- package/dist/tools/gateway-tools.d.ts +6 -0
- package/dist/tools/gateway-tools.d.ts.map +1 -0
- package/dist/tools/gateway-tools.js +381 -0
- package/dist/tools/gateway-tools.js.map +1 -0
- package/dist/tools/hash-tools.d.ts +5 -0
- package/dist/tools/hash-tools.d.ts.map +1 -0
- package/dist/tools/hash-tools.js +238 -0
- package/dist/tools/hash-tools.js.map +1 -0
- package/dist/tools/knowledge-tools.d.ts +7 -0
- package/dist/tools/knowledge-tools.d.ts.map +1 -0
- package/dist/tools/knowledge-tools.js +247 -0
- package/dist/tools/knowledge-tools.js.map +1 -0
- package/dist/tools/onboarding-checklist.d.ts +3 -0
- package/dist/tools/onboarding-checklist.d.ts.map +1 -0
- package/dist/tools/onboarding-checklist.js +141 -0
- package/dist/tools/onboarding-checklist.js.map +1 -0
- package/dist/tools/register.d.ts +60 -0
- package/dist/tools/register.d.ts.map +1 -0
- package/dist/tools/register.js +145 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/tools/tool-kit.d.ts +88 -0
- package/dist/tools/tool-kit.d.ts.map +1 -0
- package/dist/tools/tool-kit.js +297 -0
- package/dist/tools/tool-kit.js.map +1 -0
- package/dist/validation/payload-validator.d.ts +29 -0
- package/dist/validation/payload-validator.d.ts.map +1 -0
- package/dist/validation/payload-validator.js +79 -0
- package/dist/validation/payload-validator.js.map +1 -0
- package/dist/validation/rules/amount.d.ts +3 -0
- package/dist/validation/rules/amount.d.ts.map +1 -0
- package/dist/validation/rules/amount.js +77 -0
- package/dist/validation/rules/amount.js.map +1 -0
- package/dist/validation/rules/bill-reference.d.ts +10 -0
- package/dist/validation/rules/bill-reference.d.ts.map +1 -0
- package/dist/validation/rules/bill-reference.js +34 -0
- package/dist/validation/rules/bill-reference.js.map +1 -0
- package/dist/validation/rules/cnic.d.ts +3 -0
- package/dist/validation/rules/cnic.d.ts.map +1 -0
- package/dist/validation/rules/cnic.js +42 -0
- package/dist/validation/rules/cnic.js.map +1 -0
- package/dist/validation/rules/constants.d.ts +9 -0
- package/dist/validation/rules/constants.d.ts.map +1 -0
- package/dist/validation/rules/constants.js +28 -0
- package/dist/validation/rules/constants.js.map +1 -0
- package/dist/validation/rules/constraints.d.ts +3 -0
- package/dist/validation/rules/constraints.d.ts.map +1 -0
- package/dist/validation/rules/constraints.js +113 -0
- package/dist/validation/rules/constraints.js.map +1 -0
- package/dist/validation/rules/datetime.d.ts +3 -0
- package/dist/validation/rules/datetime.d.ts.map +1 -0
- package/dist/validation/rules/datetime.js +49 -0
- package/dist/validation/rules/datetime.js.map +1 -0
- package/dist/validation/rules/empty-string.d.ts +13 -0
- package/dist/validation/rules/empty-string.d.ts.map +1 -0
- package/dist/validation/rules/empty-string.js +32 -0
- package/dist/validation/rules/empty-string.js.map +1 -0
- package/dist/validation/rules/expiry.d.ts +3 -0
- package/dist/validation/rules/expiry.d.ts.map +1 -0
- package/dist/validation/rules/expiry.js +52 -0
- package/dist/validation/rules/expiry.js.map +1 -0
- package/dist/validation/rules/msisdn.d.ts +3 -0
- package/dist/validation/rules/msisdn.d.ts.map +1 -0
- package/dist/validation/rules/msisdn.js +45 -0
- package/dist/validation/rules/msisdn.js.map +1 -0
- package/dist/validation/rules/presence.d.ts +3 -0
- package/dist/validation/rules/presence.d.ts.map +1 -0
- package/dist/validation/rules/presence.js +90 -0
- package/dist/validation/rules/presence.js.map +1 -0
- package/dist/validation/rules/return-url.d.ts +14 -0
- package/dist/validation/rules/return-url.d.ts.map +1 -0
- package/dist/validation/rules/return-url.js +58 -0
- package/dist/validation/rules/return-url.js.map +1 -0
- package/dist/validation/rules/tool-argument.d.ts +16 -0
- package/dist/validation/rules/tool-argument.d.ts.map +1 -0
- package/dist/validation/rules/tool-argument.js +38 -0
- package/dist/validation/rules/tool-argument.js.map +1 -0
- package/dist/validation/rules/txn-ref.d.ts +3 -0
- package/dist/validation/rules/txn-ref.d.ts.map +1 -0
- package/dist/validation/rules/txn-ref.js +47 -0
- package/dist/validation/rules/txn-ref.js.map +1 -0
- package/dist/validation/rules/unknown-fields.d.ts +10 -0
- package/dist/validation/rules/unknown-fields.d.ts.map +1 -0
- package/dist/validation/rules/unknown-fields.js +29 -0
- package/dist/validation/rules/unknown-fields.js.map +1 -0
- package/dist/validation/types.d.ts +36 -0
- package/dist/validation/types.d.ts.map +1 -0
- package/dist/validation/types.js +12 -0
- package/dist/validation/types.js.map +1 -0
- package/dist/version.d.ts +23 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/knowledge/diagnostics/symptoms.json +321 -0
- package/knowledge/docs/bnpl-guide.md +77 -0
- package/knowledge/docs/card-page-redirection.md +67 -0
- package/knowledge/docs/card-refund.md +91 -0
- package/knowledge/docs/hmac-sha256-calculation.md +72 -0
- package/knowledge/docs/index.json +189 -0
- package/knowledge/docs/ipn-implementation.md +89 -0
- package/knowledge/docs/mwallet-recurring.md +117 -0
- package/knowledge/docs/mwallet-refund.md +65 -0
- package/knowledge/docs/mwallet-rest-v1-1.md +126 -0
- package/knowledge/docs/mwallet-rest-v2-0-cnic.md +113 -0
- package/knowledge/docs/portal-guide.md +45 -0
- package/knowledge/docs/shopify-guide.md +74 -0
- package/knowledge/docs/status-inquiry-2025-26.md +32 -0
- package/knowledge/docs/status-inquiry.md +111 -0
- package/knowledge/docs/wordpress-guide.md +49 -0
- package/knowledge/flow.schema.json +390 -0
- package/knowledge/flows/bnpl-page-redirection-v1.1.json +211 -0
- package/knowledge/flows/card-page-redirection-v1.1.json +211 -0
- package/knowledge/flows/mwallet-rest-v1.1.json +187 -0
- package/knowledge/flows/mwallet-rest-v2.0-cnic.json +197 -0
- package/knowledge/flows/mwallet-token-pay-v4.0.json +130 -0
- package/knowledge/flows/refund-bnpl.json +105 -0
- package/knowledge/flows/refund-card-v1.1.json +112 -0
- package/knowledge/flows/refund-card-v2.0.json +121 -0
- package/knowledge/flows/refund-mwallet-v1.1.json +106 -0
- package/knowledge/flows/status-inquiry-v1.1.json +102 -0
- package/knowledge/flows/status-inquiry-v2.0.json +103 -0
- package/knowledge/flows/token-delete-v1.json +85 -0
- package/knowledge/flows/token-inquiry-v1.json +85 -0
- package/knowledge/flows/wallet-linking-portal.json +103 -0
- package/knowledge/templates/node/checkout-redirect.tmpl +166 -0
- package/knowledge/templates/node/ipn-handler.tmpl +108 -0
- package/knowledge/templates/node/rest-client.tmpl +197 -0
- package/knowledge/templates/node/wallet-linking.tmpl +147 -0
- package/knowledge/templates/php/checkout-redirect.tmpl +149 -0
- package/knowledge/templates/php/ipn-handler.tmpl +105 -0
- package/knowledge/templates/php/rest-client.tmpl +191 -0
- package/knowledge/templates/php/wallet-linking.tmpl +137 -0
- package/knowledge/templates/python/checkout-redirect.tmpl +148 -0
- package/knowledge/templates/python/ipn-handler.tmpl +110 -0
- package/knowledge/templates/python/rest-client.tmpl +179 -0
- package/knowledge/templates/python/wallet-linking.tmpl +133 -0
- package/package.json +84 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { createHash, createHmac, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { SignatureError } from '../../errors.js';
|
|
3
|
+
import { compareParameterNames, normaliseParameters } from '../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The vocabulary a request signature is described in, and the engine that
|
|
6
|
+
* executes one.
|
|
7
|
+
*
|
|
8
|
+
* No two gateways sign the same way. JazzCash sorts the payload by field name,
|
|
9
|
+
* joins the non-empty values with `&`, prepends the Integrity Salt and HMACs
|
|
10
|
+
* the result.
|
|
11
|
+
*
|
|
12
|
+
* That is expressed here as a `SignaturePlan`: a recipe explicit enough that
|
|
13
|
+
* adding a gateway is a new plan rather than a new branch inside this file. The
|
|
14
|
+
* alternative — a second engine, or a second set of `if` statements — produces
|
|
15
|
+
* the failure this module exists to prevent. A forensic table written for one
|
|
16
|
+
* construction, replayed against a payload signed under another, reports that
|
|
17
|
+
* payload's CORRECT construction as a proven defect: several entries in the
|
|
18
|
+
* JazzCash table (a plain digest, the salt at the far end, empty components
|
|
19
|
+
* kept) are how other gateways legitimately sign.
|
|
20
|
+
*/
|
|
21
|
+
/** Every signature construction the server can produce and diagnose. */
|
|
22
|
+
export const SIGNATURE_SCHEME_IDS = ['jazzcash'];
|
|
23
|
+
/**
|
|
24
|
+
* Apply one delta to a plan.
|
|
25
|
+
*
|
|
26
|
+
* Exhaustive over `PlanDelta`, so a member added to the union fails to compile
|
|
27
|
+
* here rather than being silently dropped — a dropped delta is a variant that
|
|
28
|
+
* computes the correct signature under a wrong-construction label.
|
|
29
|
+
*/
|
|
30
|
+
function applyDelta(plan, delta) {
|
|
31
|
+
switch (delta.set) {
|
|
32
|
+
case 'ordering':
|
|
33
|
+
return { ...plan, ordering: delta.to };
|
|
34
|
+
case 'pairing':
|
|
35
|
+
return { ...plan, pairing: delta.to };
|
|
36
|
+
case 'valueTransform':
|
|
37
|
+
return { ...plan, valueTransform: delta.to };
|
|
38
|
+
case 'omitEmptyValues':
|
|
39
|
+
return { ...plan, omitEmptyValues: delta.to };
|
|
40
|
+
case 'separator':
|
|
41
|
+
return { ...plan, separator: delta.to };
|
|
42
|
+
case 'trailingSeparator':
|
|
43
|
+
return { ...plan, trailingSeparator: delta.to };
|
|
44
|
+
case 'secretPlacement':
|
|
45
|
+
return { ...plan, secretPlacement: delta.to };
|
|
46
|
+
case 'primitive':
|
|
47
|
+
return { ...plan, primitive: delta.to };
|
|
48
|
+
case 'digest':
|
|
49
|
+
return { ...plan, digest: delta.to };
|
|
50
|
+
case 'encoding':
|
|
51
|
+
return { ...plan, encoding: delta.to };
|
|
52
|
+
case 'excludeFields':
|
|
53
|
+
return { ...plan, selection: { ...plan.selection, excludeFields: delta.to } };
|
|
54
|
+
case 'includeFieldPrefixes':
|
|
55
|
+
return { ...plan, selection: { ...plan.selection, includeFieldPrefixes: delta.to } };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Read a value for a key that was enumerated from the same record.
|
|
60
|
+
*
|
|
61
|
+
* `noUncheckedIndexedAccess` requires a fallback that no current caller can
|
|
62
|
+
* take: every name reaching here comes from `Object.keys(parameters)`. It is
|
|
63
|
+
* kept rather than asserted away because a selection rule that names its own
|
|
64
|
+
* components — rather than filtering the payload's — would take it for a
|
|
65
|
+
* component the payload never carried, and an assertion would crash there
|
|
66
|
+
* instead of signing an empty slot.
|
|
67
|
+
*/
|
|
68
|
+
function valueOf(parameters, name) {
|
|
69
|
+
/* c8 ignore next -- unreachable while every selection filters Object.keys(parameters) */
|
|
70
|
+
return parameters[name] ?? '';
|
|
71
|
+
}
|
|
72
|
+
function isEmptyValue(value, treatWhitespaceOnlyAsEmpty) {
|
|
73
|
+
return treatWhitespaceOnlyAsEmpty ? value.trim() === '' : value === '';
|
|
74
|
+
}
|
|
75
|
+
function matchesAnyPrefix(name, prefixes) {
|
|
76
|
+
// An empty prefix list means "no prefix filtering".
|
|
77
|
+
return prefixes.length === 0 || prefixes.some((prefix) => name.startsWith(prefix));
|
|
78
|
+
}
|
|
79
|
+
function orderNames(names, ordering) {
|
|
80
|
+
switch (ordering) {
|
|
81
|
+
case 'name-ascending':
|
|
82
|
+
return [...names].sort(compareParameterNames);
|
|
83
|
+
case 'name-descending':
|
|
84
|
+
return [...names].sort(compareParameterNames).reverse();
|
|
85
|
+
case 'name-ascending-folded':
|
|
86
|
+
return [...names].sort((left, right) => compareParameterNames(left.toLowerCase(), right.toLowerCase()));
|
|
87
|
+
case 'as-listed':
|
|
88
|
+
return names;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function readValue(parameters, name, plan) {
|
|
92
|
+
return plan.valueTransform === 'trimmed' ? valueOf(parameters, name).trim() : valueOf(parameters, name);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Why this field cannot contribute, or `undefined` when it can.
|
|
96
|
+
*
|
|
97
|
+
* One function for every selection kind, so that a rule added for one is visibly
|
|
98
|
+
* either shared or conditional rather than duplicated into a second loop where
|
|
99
|
+
* it can quietly diverge.
|
|
100
|
+
*/
|
|
101
|
+
function exclusionReasonFor(name, value, plan) {
|
|
102
|
+
const selection = plan.selection;
|
|
103
|
+
if (selection.excludeFields.includes(name)) {
|
|
104
|
+
return 'excluded-field';
|
|
105
|
+
}
|
|
106
|
+
if (!matchesAnyPrefix(name, selection.includeFieldPrefixes)) {
|
|
107
|
+
return 'prefix-not-matched';
|
|
108
|
+
}
|
|
109
|
+
if (plan.omitEmptyValues && isEmptyValue(value, plan.treatWhitespaceOnlyAsEmpty)) {
|
|
110
|
+
return 'empty';
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
function selectFields(parameters, plan) {
|
|
115
|
+
// A prefix scheme reads the payload and filters it, so the candidates are
|
|
116
|
+
// whatever was transmitted. A selection rule that named its own components
|
|
117
|
+
// would supply them here instead, and would have to keep a slot for one the
|
|
118
|
+
// payload never carried — dropping it shifts every later component one place.
|
|
119
|
+
const candidates = Object.keys(parameters);
|
|
120
|
+
const components = [];
|
|
121
|
+
const excludedFields = [];
|
|
122
|
+
for (const name of orderNames(candidates, plan.ordering)) {
|
|
123
|
+
const value = readValue(parameters, name, plan);
|
|
124
|
+
const reason = exclusionReasonFor(name, value, plan);
|
|
125
|
+
if (reason === undefined) {
|
|
126
|
+
components.push({ name, value });
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
excludedFields.push({ name, reason });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { components, excludedFields };
|
|
133
|
+
}
|
|
134
|
+
function joinComponents(components, plan) {
|
|
135
|
+
const parts = plan.pairing === 'name-and-value'
|
|
136
|
+
? components.map((component) => `${component.name}=${component.value}`)
|
|
137
|
+
: components.map((component) => component.value);
|
|
138
|
+
return parts.join(plan.separator);
|
|
139
|
+
}
|
|
140
|
+
function placeSecret(plan, secret, joined, hasComponents) {
|
|
141
|
+
switch (plan.secretPlacement) {
|
|
142
|
+
case 'prepend':
|
|
143
|
+
return hasComponents ? `${secret}${plan.separator}${joined}` : secret;
|
|
144
|
+
case 'append':
|
|
145
|
+
return hasComponents ? `${joined}${plan.separator}${secret}` : secret;
|
|
146
|
+
case 'none':
|
|
147
|
+
return joined;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function assembleMessage(components, secret, plan) {
|
|
151
|
+
const message = placeSecret(plan, secret, joinComponents(components, plan), components.length > 0);
|
|
152
|
+
return plan.trailingSeparator ? `${message}${plan.separator}` : message;
|
|
153
|
+
}
|
|
154
|
+
function encodeDigest(message, secret, plan) {
|
|
155
|
+
const digest = plan.primitive === 'hmac'
|
|
156
|
+
? createHmac(plan.digest, secret).update(message, 'utf8').digest()
|
|
157
|
+
: createHash(plan.digest).update(message, 'utf8').digest();
|
|
158
|
+
return plan.encoding === 'base64' ? digest.toString('base64') : digest.toString('hex');
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Refuse a secret that carries no characters at all.
|
|
162
|
+
*
|
|
163
|
+
* A whitespace-only secret is as unusable as an empty one and far harder to
|
|
164
|
+
* spot: it survives a `!== ''` check, and every signature computed with it is
|
|
165
|
+
* then silently wrong, reaching the merchant only as an opaque gateway
|
|
166
|
+
* rejection. A secret that merely starts with whitespace is left exactly as
|
|
167
|
+
* supplied — it is signed material, so trimming it would produce the same wrong
|
|
168
|
+
* digest this guards against.
|
|
169
|
+
*/
|
|
170
|
+
function assertSecret(secret, description) {
|
|
171
|
+
if (secret.trim() !== '') {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const state = secret === '' ? 'is empty' : 'contains only whitespace';
|
|
175
|
+
throw new SignatureError(`The ${description.label} ${state}. ${description.role}`, {
|
|
176
|
+
docRefs: description.docRefs,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
function normaliseForComparison(signature, comparison) {
|
|
180
|
+
const trimmed = signature.trim();
|
|
181
|
+
return comparison === 'case-insensitive' ? trimmed.toLowerCase() : trimmed;
|
|
182
|
+
}
|
|
183
|
+
/** Constant-time signature comparison under a scheme's own case rule. */
|
|
184
|
+
export function signaturesMatch(left, right, comparison) {
|
|
185
|
+
const a = Buffer.from(normaliseForComparison(left, comparison), 'utf8');
|
|
186
|
+
const b = Buffer.from(normaliseForComparison(right, comparison), 'utf8');
|
|
187
|
+
if (a.length !== b.length) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
return timingSafeEqual(a, b);
|
|
191
|
+
}
|
|
192
|
+
function quoteAll(names, conjunction) {
|
|
193
|
+
return names.map((name) => `\`${name}\``).join(conjunction);
|
|
194
|
+
}
|
|
195
|
+
function describeSelection(selection) {
|
|
196
|
+
// An empty prefix list means no filtering, and the sentence has to say so
|
|
197
|
+
// rather than trail off after "prefixed" — which is what a merchant was
|
|
198
|
+
// handed for every flow whose prefixes are empty by construction.
|
|
199
|
+
return selection.includeFieldPrefixes.length === 0
|
|
200
|
+
? 'every field'
|
|
201
|
+
: `the fields prefixed ${quoteAll(selection.includeFieldPrefixes, ' or ')}`;
|
|
202
|
+
}
|
|
203
|
+
function describeOrdering(ordering) {
|
|
204
|
+
switch (ordering) {
|
|
205
|
+
case 'name-ascending':
|
|
206
|
+
return 'sorted by name (ASCII ascending)';
|
|
207
|
+
case 'name-descending':
|
|
208
|
+
return 'sorted by name (ASCII descending)';
|
|
209
|
+
case 'name-ascending-folded':
|
|
210
|
+
return 'sorted by lower-cased name';
|
|
211
|
+
case 'as-listed':
|
|
212
|
+
return 'in the order listed';
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function describeSecretPlacement(placement, secretLabel) {
|
|
216
|
+
switch (placement) {
|
|
217
|
+
case 'prepend':
|
|
218
|
+
return `prefixed by the ${secretLabel}`;
|
|
219
|
+
case 'append':
|
|
220
|
+
return `followed by the ${secretLabel}`;
|
|
221
|
+
case 'none':
|
|
222
|
+
return `with the ${secretLabel} nowhere in the signed string`;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* One sentence describing exactly how a plan builds the string it digests.
|
|
227
|
+
*
|
|
228
|
+
* Derived from the plan rather than written out per scheme, because a sentence
|
|
229
|
+
* written by hand describes the construction its author had in mind while the
|
|
230
|
+
* engine executes the one the flow configured — and a merchant implements the
|
|
231
|
+
* sentence, not the code. The two drift silently: nothing fails when a flow is
|
|
232
|
+
* described by a paragraph belonging to a different construction.
|
|
233
|
+
*/
|
|
234
|
+
export function describeConstruction(plan, secretLabel) {
|
|
235
|
+
// Spelled the way each is conventionally written, and the way this repository
|
|
236
|
+
// writes them elsewhere: `HMAC-SHA256`, but `SHA-512`.
|
|
237
|
+
const bits = plan.digest === 'sha256' ? '256' : '512';
|
|
238
|
+
const algorithm = plan.primitive === 'hmac' ? `HMAC-SHA${bits}` : `SHA-${bits}`;
|
|
239
|
+
const emptyRule = plan.omitEmptyValues ? 'non-empty ' : '';
|
|
240
|
+
const pairing = plan.pairing === 'name-and-value' ? 'name=value pairs' : 'values';
|
|
241
|
+
const transform = plan.valueTransform === 'trimmed' ? 'trimmed' : 'exactly as transmitted';
|
|
242
|
+
const joined = plan.separator === '' ? 'concatenated with no separator' : `joined with "${plan.separator}"`;
|
|
243
|
+
const trailing = plan.trailingSeparator ? ' and a trailing separator' : '';
|
|
244
|
+
// Stated only where it applies. It is not a default anywhere, no flow can
|
|
245
|
+
// declare it, and a merchant told their whitespace-only values are dropped
|
|
246
|
+
// when they are not would go looking for a difference that is not there.
|
|
247
|
+
const blanks = plan.omitEmptyValues && plan.treatWhitespaceOnlyAsEmpty ? ' (a whitespace-only value counts as empty)' : '';
|
|
248
|
+
// The secret appears twice in a keyed construction, which is the single most
|
|
249
|
+
// common JazzCash misreading: prepended AND used as the key, not either one.
|
|
250
|
+
const keying = plan.primitive === 'hmac' ? `, and keyed with the ${secretLabel}` : '';
|
|
251
|
+
return [
|
|
252
|
+
`${algorithm} over the ${emptyRule}${pairing} of ${describeSelection(plan.selection)}${blanks}`,
|
|
253
|
+
describeOrdering(plan.ordering),
|
|
254
|
+
`taken ${transform} and ${joined}${trailing}`,
|
|
255
|
+
`${describeSecretPlacement(plan.secretPlacement, secretLabel)}${keying}.`,
|
|
256
|
+
].join(', ');
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* One sentence naming the digest encoding and the comparison rule.
|
|
260
|
+
*
|
|
261
|
+
* Read from the plan for the same reason as the construction: a flow declaring
|
|
262
|
+
* base64 and case-sensitive comparison was told its output was lowercase hex
|
|
263
|
+
* compared case-insensitively, which is the advice that makes a correct
|
|
264
|
+
* signature look broken.
|
|
265
|
+
*/
|
|
266
|
+
export function describeEncoding(plan) {
|
|
267
|
+
const output = plan.encoding === 'base64' ? 'base64' : 'lowercase hex';
|
|
268
|
+
const comparison = plan.comparison === 'case-insensitive' ? 'case-insensitive' : 'case-sensitive';
|
|
269
|
+
return `Output is ${output}; comparison is ${comparison}.`;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Execute a plan, returning the reasoning as well as the signed string.
|
|
273
|
+
*
|
|
274
|
+
* Returning the breakdown rather than only the digest is the point: a merchant
|
|
275
|
+
* debugging a rejected signature needs to see which fields were used and in what
|
|
276
|
+
* order, which is precisely what no error message from a gateway tells them.
|
|
277
|
+
*/
|
|
278
|
+
function buildFromPlan(parameters, secret, plan) {
|
|
279
|
+
const { components, excludedFields } = selectFields(parameters, plan);
|
|
280
|
+
return {
|
|
281
|
+
includedFields: components.map((component) => component.name),
|
|
282
|
+
excludedFields,
|
|
283
|
+
hashString: assembleMessage(components, secret, plan),
|
|
284
|
+
values: components.map((component) => component.value),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/** Execute a plan and return only the encoded signature. */
|
|
288
|
+
function signFromPlan(parameters, secret, plan) {
|
|
289
|
+
return encodeDigest(buildFromPlan(parameters, secret, plan).hashString, secret, plan);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Bind a table of plan deltas to a scheme.
|
|
293
|
+
*
|
|
294
|
+
* Each variant re-resolves the scheme's plan from the merchant's own settings
|
|
295
|
+
* before applying its delta, so a flow that narrows the field selection is
|
|
296
|
+
* diagnosed against ITS construction rather than against the scheme default.
|
|
297
|
+
*/
|
|
298
|
+
export function defineVariants(plan, definitions) {
|
|
299
|
+
return definitions.map((definition) => ({
|
|
300
|
+
id: definition.id,
|
|
301
|
+
label: definition.label,
|
|
302
|
+
explanation: definition.explanation,
|
|
303
|
+
fix: definition.fix,
|
|
304
|
+
compute: (parameters, secret, settings) => signFromPlan(parameters, secret, applyDelta(plan(settings), definition.change)),
|
|
305
|
+
}));
|
|
306
|
+
}
|
|
307
|
+
/** Build the signed string for a payload under one scheme. */
|
|
308
|
+
export function buildSignature(scheme, parameters, secret, settings) {
|
|
309
|
+
assertSecret(secret, scheme.secret);
|
|
310
|
+
return buildFromPlan(normaliseParameters(parameters), secret, scheme.plan(settings));
|
|
311
|
+
}
|
|
312
|
+
/** Compute the signature for a payload under one scheme. */
|
|
313
|
+
export function computeSignature(scheme, parameters, secret, settings) {
|
|
314
|
+
assertSecret(secret, scheme.secret);
|
|
315
|
+
return signFromPlan(normaliseParameters(parameters), secret, scheme.plan(settings));
|
|
316
|
+
}
|
|
317
|
+
/** Verify a supplied signature against a freshly computed one. */
|
|
318
|
+
export function verifySignature(scheme, parameters, secret, providedSignature, settings) {
|
|
319
|
+
assertSecret(secret, scheme.secret);
|
|
320
|
+
const plan = scheme.plan(settings);
|
|
321
|
+
const breakdown = buildFromPlan(normaliseParameters(parameters), secret, plan);
|
|
322
|
+
const expectedHash = encodeDigest(breakdown.hashString, secret, plan);
|
|
323
|
+
return {
|
|
324
|
+
matches: signaturesMatch(expectedHash, providedSignature, plan.comparison),
|
|
325
|
+
expectedHash,
|
|
326
|
+
providedHash: normaliseForComparison(providedSignature, plan.comparison),
|
|
327
|
+
breakdown,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Summary for a mismatch judged under a construction nobody declared.
|
|
332
|
+
*
|
|
333
|
+
* Says what was assumed and offers no proven cause, rather than reusing the
|
|
334
|
+
* `unexplained` narrative — which would claim no known construction error
|
|
335
|
+
* reproduces the signature while one may well have done.
|
|
336
|
+
*/
|
|
337
|
+
function assumedSchemeSummary(label) {
|
|
338
|
+
return `The signature does not match. No flow named the construction, so it was assumed to be ${label}, and nothing is offered as a proven cause: a construction error identified under an assumed construction is just as likely to be another provider's correct one. Name the flow to diagnose the payload against the construction that flow declares.`;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Explain why a signature does not match, using one scheme's forensics only.
|
|
342
|
+
*
|
|
343
|
+
* Every variant of the scheme is executed against the merchant's own parameters.
|
|
344
|
+
* One that reproduces the signature they actually sent is reported as
|
|
345
|
+
* `confirmed`: that is not a guess, it is a demonstration of what their code
|
|
346
|
+
* did — provided the construction being varied is the one the payload was signed
|
|
347
|
+
* under. `provenance` is what says whether it is; see `SchemeProvenance`. Under
|
|
348
|
+
* an assumed construction no variant runs at all, and the scheme's ranked advice
|
|
349
|
+
* is offered as `possible` instead.
|
|
350
|
+
*
|
|
351
|
+
* A variant can only ever be its own scheme's plan with one field changed, which
|
|
352
|
+
* is what stops the table offering another provider's correct construction as a
|
|
353
|
+
* defect; see `PlanDelta`.
|
|
354
|
+
*/
|
|
355
|
+
export function diagnoseSignature(scheme, parameters, secret, providedSignature, settings, provenance) {
|
|
356
|
+
const verification = verifySignature(scheme, parameters, secret, providedSignature, settings);
|
|
357
|
+
if (verification.matches) {
|
|
358
|
+
return {
|
|
359
|
+
matches: true,
|
|
360
|
+
expectedHash: verification.expectedHash,
|
|
361
|
+
providedHash: verification.providedHash,
|
|
362
|
+
breakdown: verification.breakdown,
|
|
363
|
+
hypotheses: [],
|
|
364
|
+
summary: scheme.narrative.matched,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
const plan = scheme.plan(settings);
|
|
368
|
+
const normalised = normaliseParameters(parameters);
|
|
369
|
+
const confirmed = [];
|
|
370
|
+
if (provenance === 'declared') {
|
|
371
|
+
for (const variant of scheme.variants) {
|
|
372
|
+
if (signaturesMatch(variant.compute(normalised, secret, settings), providedSignature, plan.comparison)) {
|
|
373
|
+
confirmed.push({
|
|
374
|
+
id: variant.id,
|
|
375
|
+
label: variant.label,
|
|
376
|
+
explanation: variant.explanation,
|
|
377
|
+
fix: variant.fix,
|
|
378
|
+
confidence: 'confirmed',
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
const hypotheses = confirmed.length > 0 ? confirmed : scheme.advice.map((advice) => ({ ...advice, confidence: 'possible' }));
|
|
384
|
+
const summary = confirmed.length > 0
|
|
385
|
+
? `${scheme.narrative.reproducedPrefix}: ${confirmed.map((entry) => entry.label).join('; ')}.`
|
|
386
|
+
: provenance === 'declared'
|
|
387
|
+
? scheme.narrative.unexplained
|
|
388
|
+
: assumedSchemeSummary(scheme.label);
|
|
389
|
+
return {
|
|
390
|
+
matches: false,
|
|
391
|
+
expectedHash: verification.expectedHash,
|
|
392
|
+
providedHash: verification.providedHash,
|
|
393
|
+
breakdown: verification.breakdown,
|
|
394
|
+
hypotheses,
|
|
395
|
+
summary,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=scheme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheme.js","sourceRoot":"","sources":["../../../src/domain/signature/scheme.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transaction reference, bill reference and request identifier rules.
|
|
3
|
+
*
|
|
4
|
+
* From the MWallet guides:
|
|
5
|
+
* - `pp_TxnRefNo` must be unique for every transaction. The recommended format
|
|
6
|
+
* is the first three letters of the merchant's domain followed by the
|
|
7
|
+
* transaction date/time, e.g. `Goo20230208115409`. The v1.1 sample annotates
|
|
8
|
+
* the field as `[20AN]`, i.e. 20 alphanumeric characters.
|
|
9
|
+
* - `pp_BillReference` is mandatory, may repeat across transactions, and must
|
|
10
|
+
* contain only `A-Z`, `a-z` and `0-9`. Spaces and special characters are not
|
|
11
|
+
* allowed.
|
|
12
|
+
* - `pp_RequestID` (wallet linking, token inquiry, token delete) must be unique
|
|
13
|
+
* for every attempt.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MAX_TXN_REF_LENGTH = 20;
|
|
16
|
+
export declare const MAX_TXN_REF_PREFIX_LENGTH = 3;
|
|
17
|
+
export interface ReferenceCheck {
|
|
18
|
+
readonly valid: boolean;
|
|
19
|
+
readonly issues: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate `pp_TxnRefNo` against the documented rules.
|
|
23
|
+
*
|
|
24
|
+
* `maxLength` defaults to the documented 20 for callers with no flow to hand.
|
|
25
|
+
* The validation rule passes the flow's own declared limit instead, so a
|
|
26
|
+
* correction from JazzCash stays a data change rather than a code change.
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateTxnRefNo(value: string, maxLength?: number): ReferenceCheck;
|
|
29
|
+
/** Validate `pp_BillReference` against the documented rules. */
|
|
30
|
+
export declare function validateBillReference(value: string): ReferenceCheck;
|
|
31
|
+
/** Validate `pp_RequestID` used by the wallet linking and token APIs. */
|
|
32
|
+
export declare function validateRequestId(value: string, maxLength?: number): ReferenceCheck;
|
|
33
|
+
export interface ReferenceOptions {
|
|
34
|
+
/**
|
|
35
|
+
* Up to three alphanumeric characters. The guides recommend the first three
|
|
36
|
+
* letters of the merchant's domain, e.g. `Goo` for `google.com`.
|
|
37
|
+
*/
|
|
38
|
+
readonly prefix?: string;
|
|
39
|
+
readonly now?: Date;
|
|
40
|
+
/**
|
|
41
|
+
* Append random alphanumeric characters to disambiguate the reference.
|
|
42
|
+
*
|
|
43
|
+
* On by default: a second-resolution stamp collides whenever two orders are
|
|
44
|
+
* placed in the same second, which the gateway rejects as a duplicate
|
|
45
|
+
* reference. The suffix takes whatever room the prefix leaves inside the
|
|
46
|
+
* 20-character limit, so a shorter prefix buys more entropy.
|
|
47
|
+
*
|
|
48
|
+
* Turning it off yields exactly the documented `prefix + YYYYMMDDHHMMSS`
|
|
49
|
+
* shape, and with it the certainty that two references generated in the same
|
|
50
|
+
* second are identical. Only use it where the caller supplies uniqueness by
|
|
51
|
+
* some other means.
|
|
52
|
+
*/
|
|
53
|
+
readonly includeRandomSuffix?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generate a `pp_TxnRefNo`.
|
|
57
|
+
*
|
|
58
|
+
* Default shape is `T` + `YYYYMMDDHHMMSS` + five random alphanumeric characters,
|
|
59
|
+
* filling the 20-character limit. The documented three-letter merchant prefix
|
|
60
|
+
* leaves three random characters rather than five.
|
|
61
|
+
*
|
|
62
|
+
* Uniqueness is probabilistic, not guaranteed. The narrowest case is three
|
|
63
|
+
* random characters, 62³ ≈ 238,000 combinations within one second, so a given
|
|
64
|
+
* pair of references taken in that second collides with probability about one in
|
|
65
|
+
* 240,000 and a collision becomes likely only past roughly 600 references in the
|
|
66
|
+
* same second. A wall clock alone cannot do better: two builds in one
|
|
67
|
+
* millisecond, in one process or in two containers, produce the same stamp.
|
|
68
|
+
* Persist the reference you send, and treat the gateway's duplicate-reference
|
|
69
|
+
* rejection as a signal to regenerate rather than as a failed payment.
|
|
70
|
+
*/
|
|
71
|
+
export declare function generateTxnRefNo(options?: ReferenceOptions): string;
|
|
72
|
+
/** Generate a `pp_BillReference`. May repeat, but a unique value aids reconciliation. */
|
|
73
|
+
export declare function generateBillReference(options?: ReferenceOptions): string;
|
|
74
|
+
/** Generate a `pp_RequestID` for the wallet linking and token APIs. */
|
|
75
|
+
export declare function generateRequestId(options?: ReferenceOptions): string;
|
|
76
|
+
//# sourceMappingURL=txn-ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txn-ref.d.ts","sourceRoot":"","sources":["../../src/domain/txn-ref.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAa3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAsBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,MAA2B,GAAG,cAAc,CAEtG;AAED,gEAAgE;AAChE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAEnE;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,MAA2B,GAAG,cAAc,CAEvG;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACpB;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CACxC;AAkDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAEvE;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAE5E;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAExE"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { randomInt } from 'node:crypto';
|
|
2
|
+
import { JazzCashValidationError } from '../errors.js';
|
|
3
|
+
import { formatTxnDateTime } from './datetime.js';
|
|
4
|
+
/**
|
|
5
|
+
* Transaction reference, bill reference and request identifier rules.
|
|
6
|
+
*
|
|
7
|
+
* From the MWallet guides:
|
|
8
|
+
* - `pp_TxnRefNo` must be unique for every transaction. The recommended format
|
|
9
|
+
* is the first three letters of the merchant's domain followed by the
|
|
10
|
+
* transaction date/time, e.g. `Goo20230208115409`. The v1.1 sample annotates
|
|
11
|
+
* the field as `[20AN]`, i.e. 20 alphanumeric characters.
|
|
12
|
+
* - `pp_BillReference` is mandatory, may repeat across transactions, and must
|
|
13
|
+
* contain only `A-Z`, `a-z` and `0-9`. Spaces and special characters are not
|
|
14
|
+
* allowed.
|
|
15
|
+
* - `pp_RequestID` (wallet linking, token inquiry, token delete) must be unique
|
|
16
|
+
* for every attempt.
|
|
17
|
+
*/
|
|
18
|
+
export const MAX_TXN_REF_LENGTH = 20;
|
|
19
|
+
export const MAX_TXN_REF_PREFIX_LENGTH = 3;
|
|
20
|
+
const ALPHANUMERIC_PATTERN = /^[A-Za-z0-9]+$/;
|
|
21
|
+
/**
|
|
22
|
+
* The alphabet a generated reference's random suffix is drawn from.
|
|
23
|
+
*
|
|
24
|
+
* Restricted to `A-Z`, `a-z` and `0-9` because that is the whole character set
|
|
25
|
+
* the guides permit for a reference. 62 symbols per character is the most
|
|
26
|
+
* entropy available inside that rule.
|
|
27
|
+
*/
|
|
28
|
+
const SUFFIX_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
29
|
+
function checkAlphanumeric(fieldName, value, maxLength) {
|
|
30
|
+
const issues = [];
|
|
31
|
+
if (value === '') {
|
|
32
|
+
issues.push(`${fieldName} is mandatory and must not be empty.`);
|
|
33
|
+
return { valid: false, issues };
|
|
34
|
+
}
|
|
35
|
+
if (!ALPHANUMERIC_PATTERN.test(value)) {
|
|
36
|
+
const offending = [...new Set([...value].filter((character) => !ALPHANUMERIC_PATTERN.test(character)))];
|
|
37
|
+
issues.push(`${fieldName} must contain only letters and digits. Remove: ${offending.map((character) => (character === ' ' ? '(space)' : character)).join(' ')}`);
|
|
38
|
+
}
|
|
39
|
+
if (maxLength !== undefined && value.length > maxLength) {
|
|
40
|
+
issues.push(`${fieldName} is ${String(value.length)} characters; the documented maximum is ${String(maxLength)}.`);
|
|
41
|
+
}
|
|
42
|
+
return { valid: issues.length === 0, issues };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validate `pp_TxnRefNo` against the documented rules.
|
|
46
|
+
*
|
|
47
|
+
* `maxLength` defaults to the documented 20 for callers with no flow to hand.
|
|
48
|
+
* The validation rule passes the flow's own declared limit instead, so a
|
|
49
|
+
* correction from JazzCash stays a data change rather than a code change.
|
|
50
|
+
*/
|
|
51
|
+
export function validateTxnRefNo(value, maxLength = MAX_TXN_REF_LENGTH) {
|
|
52
|
+
return checkAlphanumeric('pp_TxnRefNo', value, maxLength);
|
|
53
|
+
}
|
|
54
|
+
/** Validate `pp_BillReference` against the documented rules. */
|
|
55
|
+
export function validateBillReference(value) {
|
|
56
|
+
return checkAlphanumeric('pp_BillReference', value, undefined);
|
|
57
|
+
}
|
|
58
|
+
/** Validate `pp_RequestID` used by the wallet linking and token APIs. */
|
|
59
|
+
export function validateRequestId(value, maxLength = MAX_TXN_REF_LENGTH) {
|
|
60
|
+
return checkAlphanumeric('pp_RequestID', value, maxLength);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Draw a random alphanumeric suffix.
|
|
64
|
+
*
|
|
65
|
+
* `node:crypto` rather than `Math.random`: a reference must be unpredictable to
|
|
66
|
+
* a third party who sees one of them, and `randomInt` rejection-samples so every
|
|
67
|
+
* character is uniform over the alphabet rather than biased towards its start.
|
|
68
|
+
*/
|
|
69
|
+
function randomSuffix(length) {
|
|
70
|
+
let suffix = '';
|
|
71
|
+
for (let index = 0; index < length; index += 1) {
|
|
72
|
+
suffix += SUFFIX_ALPHABET.charAt(randomInt(SUFFIX_ALPHABET.length));
|
|
73
|
+
}
|
|
74
|
+
return suffix;
|
|
75
|
+
}
|
|
76
|
+
function assertPrefix(prefix) {
|
|
77
|
+
if (prefix !== '' && !ALPHANUMERIC_PATTERN.test(prefix)) {
|
|
78
|
+
throw new JazzCashValidationError(`Reference prefix "${prefix}" must contain only letters and digits.`);
|
|
79
|
+
}
|
|
80
|
+
if (prefix.length > MAX_TXN_REF_PREFIX_LENGTH) {
|
|
81
|
+
throw new JazzCashValidationError(`Reference prefix "${prefix}" is longer than ${String(MAX_TXN_REF_PREFIX_LENGTH)} characters. The timestamp and its random suffix need the remaining room inside the ${String(MAX_TXN_REF_LENGTH)}-character limit.`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function buildReference(prefix, options) {
|
|
85
|
+
assertPrefix(prefix);
|
|
86
|
+
const now = options.now ?? new Date();
|
|
87
|
+
const stamp = formatTxnDateTime(now);
|
|
88
|
+
// assertPrefix caps the prefix at three characters, so the remaining room is
|
|
89
|
+
// at least three even for the longest permitted prefix.
|
|
90
|
+
const room = MAX_TXN_REF_LENGTH - prefix.length - stamp.length;
|
|
91
|
+
const suffix = options.includeRandomSuffix === false ? '' : randomSuffix(room);
|
|
92
|
+
const reference = `${prefix}${stamp}${suffix}`;
|
|
93
|
+
/* c8 ignore next 5 -- guarded by assertPrefix; retained as a defence in depth */
|
|
94
|
+
if (reference.length > MAX_TXN_REF_LENGTH) {
|
|
95
|
+
throw new JazzCashValidationError(`Generated reference "${reference}" exceeds the ${String(MAX_TXN_REF_LENGTH)}-character limit.`);
|
|
96
|
+
}
|
|
97
|
+
return reference;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Generate a `pp_TxnRefNo`.
|
|
101
|
+
*
|
|
102
|
+
* Default shape is `T` + `YYYYMMDDHHMMSS` + five random alphanumeric characters,
|
|
103
|
+
* filling the 20-character limit. The documented three-letter merchant prefix
|
|
104
|
+
* leaves three random characters rather than five.
|
|
105
|
+
*
|
|
106
|
+
* Uniqueness is probabilistic, not guaranteed. The narrowest case is three
|
|
107
|
+
* random characters, 62³ ≈ 238,000 combinations within one second, so a given
|
|
108
|
+
* pair of references taken in that second collides with probability about one in
|
|
109
|
+
* 240,000 and a collision becomes likely only past roughly 600 references in the
|
|
110
|
+
* same second. A wall clock alone cannot do better: two builds in one
|
|
111
|
+
* millisecond, in one process or in two containers, produce the same stamp.
|
|
112
|
+
* Persist the reference you send, and treat the gateway's duplicate-reference
|
|
113
|
+
* rejection as a signal to regenerate rather than as a failed payment.
|
|
114
|
+
*/
|
|
115
|
+
export function generateTxnRefNo(options = {}) {
|
|
116
|
+
return buildReference(options.prefix ?? 'T', options);
|
|
117
|
+
}
|
|
118
|
+
/** Generate a `pp_BillReference`. May repeat, but a unique value aids reconciliation. */
|
|
119
|
+
export function generateBillReference(options = {}) {
|
|
120
|
+
return buildReference(options.prefix ?? 'B', options);
|
|
121
|
+
}
|
|
122
|
+
/** Generate a `pp_RequestID` for the wallet linking and token APIs. */
|
|
123
|
+
export function generateRequestId(options = {}) {
|
|
124
|
+
return buildReference(options.prefix ?? 'R', options);
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=txn-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txn-ref.js","sourceRoot":"","sources":["../../src/domain/txn-ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,eAAe,GAAG,gEAAgE,CAAC;AAOzF,SAAS,iBAAiB,CAAC,SAAiB,EAAE,KAAa,EAAE,SAA6B;IACxF,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,sCAAsC,CAAC,CAAC;QAChE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAClC,CAAC;IACD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACxG,MAAM,CAAC,IAAI,CACT,GAAG,SAAS,kDAAkD,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACpJ,CAAC;IACJ,CAAC;IACD,IAAI,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,0CAA0C,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACrH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,YAAoB,kBAAkB;IACpF,OAAO,iBAAiB,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AAC5D,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,OAAO,iBAAiB,CAAC,kBAAkB,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AACjE,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,YAAoB,kBAAkB;IACrF,OAAO,iBAAiB,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AAC7D,CAAC;AAyBD;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,MAAM,KAAK,EAAE,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,uBAAuB,CAAC,qBAAqB,MAAM,yCAAyC,CAAC,CAAC;IAC1G,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,GAAG,yBAAyB,EAAE,CAAC;QAC9C,MAAM,IAAI,uBAAuB,CAC/B,qBAAqB,MAAM,oBAAoB,MAAM,CAAC,yBAAyB,CAAC,uFAAuF,MAAM,CAAC,kBAAkB,CAAC,mBAAmB,CACrN,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,OAAyB;IAC/D,YAAY,CAAC,MAAM,CAAC,CAAC;IAErB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACrC,6EAA6E;IAC7E,wDAAwD;IACxD,MAAM,IAAI,GAAG,kBAAkB,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,mBAAmB,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAE/E,MAAM,SAAS,GAAG,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,EAAE,CAAC;IAE/C,iFAAiF;IACjF,IAAI,SAAS,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QAC1C,MAAM,IAAI,uBAAuB,CAC/B,wBAAwB,SAAS,iBAAiB,MAAM,CAAC,kBAAkB,CAAC,mBAAmB,CAChG,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAA4B,EAAE;IAC7D,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,qBAAqB,CAAC,UAA4B,EAAE;IAClE,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,iBAAiB,CAAC,UAA4B,EAAE;IAC9D,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC"}
|