remita-checkout-client 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 +0 -0
- package/README.md +138 -0
- package/dist/chunk-MGQQHIIZ.mjs +275 -0
- package/dist/chunk-MGQQHIIZ.mjs.map +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +453 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +231 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +225 -0
- package/dist/index.d.ts +225 -0
- package/dist/index.js +347 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +102 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +58 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ENVIRONMENT_BASE_URLS,
|
|
3
|
+
RemitaCheckoutClient,
|
|
4
|
+
init_client,
|
|
5
|
+
init_environment,
|
|
6
|
+
init_stream,
|
|
7
|
+
openStatusStream,
|
|
8
|
+
resolveEnvironment
|
|
9
|
+
} from "./chunk-MGQQHIIZ.mjs";
|
|
10
|
+
|
|
11
|
+
// src/index.ts
|
|
12
|
+
init_client();
|
|
13
|
+
|
|
14
|
+
// src/session.ts
|
|
15
|
+
var PaymentSession = class {
|
|
16
|
+
constructor(client) {
|
|
17
|
+
this.client = client;
|
|
18
|
+
this.stage = "idle";
|
|
19
|
+
}
|
|
20
|
+
async pre(request) {
|
|
21
|
+
const response = await this.client.prePayment(request);
|
|
22
|
+
this.transactionId = response.transactionId ?? this.transactionId;
|
|
23
|
+
this.paymentReference = response.paymentReference ?? this.paymentReference;
|
|
24
|
+
this.stage = "pre";
|
|
25
|
+
return response;
|
|
26
|
+
}
|
|
27
|
+
async fee(request) {
|
|
28
|
+
const response = await this.client.calculateFee(request);
|
|
29
|
+
this.stage = "fee";
|
|
30
|
+
return response;
|
|
31
|
+
}
|
|
32
|
+
async initiate(request) {
|
|
33
|
+
const response = await this.client.initiatePayment(request);
|
|
34
|
+
this.authorizeActionUrl = response.actionUrl;
|
|
35
|
+
this.validateActionUrl = void 0;
|
|
36
|
+
this.paymentReference = response.paymentReference ?? this.paymentReference;
|
|
37
|
+
this.transactionId = response.transactionId ?? this.transactionId;
|
|
38
|
+
this.stage = "initiated";
|
|
39
|
+
return response;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Uses the actionUrl captured from initiate() unless you pass one explicitly.
|
|
43
|
+
* Pass `contentType` for 3DS processor endpoints that require form-encoding.
|
|
44
|
+
*/
|
|
45
|
+
async authorize(payload, actionUrlOverride, contentType) {
|
|
46
|
+
const url = actionUrlOverride ?? this.authorizeActionUrl;
|
|
47
|
+
if (!url) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
"No actionUrl available \u2014 call initiate() first, or pass actionUrlOverride explicitly."
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
const response = await this.client.authorize(url, payload, contentType);
|
|
53
|
+
const next = response.actionUrl;
|
|
54
|
+
if (next) this.validateActionUrl = next;
|
|
55
|
+
this.stage = "authorized";
|
|
56
|
+
return response;
|
|
57
|
+
}
|
|
58
|
+
async validate(request, actionUrlOverride) {
|
|
59
|
+
const url = actionUrlOverride ?? this.validateActionUrl;
|
|
60
|
+
const response = await this.client.validatePayment(request, url);
|
|
61
|
+
this.stage = "validated";
|
|
62
|
+
return response;
|
|
63
|
+
}
|
|
64
|
+
async verify(paymentRefOverride) {
|
|
65
|
+
const ref = paymentRefOverride ?? this.paymentReference ?? this.transactionId;
|
|
66
|
+
if (!ref) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
"No paymentReference or transactionId available \u2014 call initiate() first, or pass it explicitly."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const response = await this.client.verifyPayment(ref);
|
|
72
|
+
if (response.status === "APPROVED") {
|
|
73
|
+
this.stage = "verified";
|
|
74
|
+
} else if (response.status === "FAILED") {
|
|
75
|
+
this.stage = "failed";
|
|
76
|
+
}
|
|
77
|
+
return response;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// src/index.ts
|
|
82
|
+
init_environment();
|
|
83
|
+
init_stream();
|
|
84
|
+
|
|
85
|
+
// src/types.ts
|
|
86
|
+
var RemitaApiError = class extends Error {
|
|
87
|
+
constructor(message, status, payload) {
|
|
88
|
+
super(message);
|
|
89
|
+
this.name = "RemitaApiError";
|
|
90
|
+
this.status = status;
|
|
91
|
+
this.payload = payload;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
export {
|
|
95
|
+
ENVIRONMENT_BASE_URLS,
|
|
96
|
+
PaymentSession,
|
|
97
|
+
RemitaApiError,
|
|
98
|
+
RemitaCheckoutClient,
|
|
99
|
+
openStatusStream,
|
|
100
|
+
resolveEnvironment
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/session.ts","../src/types.ts"],"sourcesContent":["export { RemitaCheckoutClient } from \"./client\";\nexport type { RemitaCheckoutClientOptions } from \"./client\";\n\nexport { PaymentSession } from \"./session\";\nexport type { PaymentSessionStage } from \"./session\";\n\nexport {\n resolveEnvironment,\n ENVIRONMENT_BASE_URLS,\n} from \"./environment\";\nexport type {\n RemitaEnvironment,\n ResolveEnvironmentOptions,\n ResolvedEnvironment,\n} from \"./environment\";\n\nexport { openStatusStream } from \"./stream\";\nexport type { StatusStreamOptions, StatusStreamHandle } from \"./stream\";\n\nexport { RemitaApiError } from \"./types\";\nexport type {\n ApiErrorPayload,\n PrePaymentRequest,\n PrePaymentResponse,\n PaymentChannel,\n FeeChargeRequest,\n FeeChargeResponse,\n InitiatePaymentRequest,\n InitiatePaymentResponse,\n AuthorizePayload,\n AuthorizeResponse,\n ValidatePaymentRequest,\n ValidatePaymentResponse,\n PaymentStatus,\n VerifyPaymentResponse,\n Bank,\n BankListResponse,\n UssdCode,\n UssdCodesResponse,\n WalletType,\n WalletTypesResponse,\n StatusStreamEvent,\n} from \"./types\";\n","import type { RemitaCheckoutClient } from \"./client\";\nimport type {\n PrePaymentRequest,\n PrePaymentResponse,\n FeeChargeRequest,\n FeeChargeResponse,\n InitiatePaymentRequest,\n InitiatePaymentResponse,\n AuthorizePayload,\n AuthorizeResponse,\n ValidatePaymentRequest,\n ValidatePaymentResponse,\n VerifyPaymentResponse,\n} from \"./types\";\n\nexport type PaymentSessionStage =\n | \"idle\"\n | \"pre\"\n | \"fee\"\n | \"initiated\"\n | \"authorized\"\n | \"validated\"\n | \"verified\"\n | \"failed\";\n\n/**\n * Sequences the multi-step payment flow (pre → fee → initiate → authorize →\n * validate → verify) and tracks the refs each step hands to the next\n * (paymentReference, transactionId, actionUrl), so callers don't have to\n * thread that state through by hand.\n */\nexport class PaymentSession {\n stage: PaymentSessionStage = \"idle\";\n paymentReference?: string;\n transactionId?: string;\n\n /** URL returned by initiate() for the *authorize* step. */\n private authorizeActionUrl?: string;\n /** URL returned by authorize() for the *validate* step, if different. */\n private validateActionUrl?: string;\n\n constructor(private readonly client: RemitaCheckoutClient) {}\n\n async pre(request: PrePaymentRequest): Promise<PrePaymentResponse> {\n const response = await this.client.prePayment(request);\n // Read refs from the RESPONSE, not the request.\n this.transactionId = response.transactionId ?? this.transactionId;\n this.paymentReference = response.paymentReference ?? this.paymentReference;\n this.stage = \"pre\";\n return response;\n }\n\n async fee(request: FeeChargeRequest): Promise<FeeChargeResponse> {\n const response = await this.client.calculateFee(request);\n this.stage = \"fee\";\n return response;\n }\n\n async initiate(request: InitiatePaymentRequest): Promise<InitiatePaymentResponse> {\n const response = await this.client.initiatePayment(request);\n this.authorizeActionUrl = response.actionUrl;\n this.validateActionUrl = undefined; // reset until authorize tells us otherwise\n this.paymentReference = response.paymentReference ?? this.paymentReference;\n this.transactionId = response.transactionId ?? this.transactionId;\n this.stage = \"initiated\";\n return response;\n }\n\n /**\n * Uses the actionUrl captured from initiate() unless you pass one explicitly.\n * Pass `contentType` for 3DS processor endpoints that require form-encoding.\n */\n async authorize(\n payload: AuthorizePayload,\n actionUrlOverride?: string,\n contentType?: string\n ): Promise<AuthorizeResponse> {\n const url = actionUrlOverride ?? this.authorizeActionUrl;\n if (!url) {\n throw new Error(\n \"No actionUrl available — call initiate() first, or pass actionUrlOverride explicitly.\"\n );\n }\n const response = await this.client.authorize(url, payload, contentType);\n\n // If the processor told us where the next validation step lives, use it.\n const next = (response as { actionUrl?: string }).actionUrl;\n if (next) this.validateActionUrl = next;\n\n this.stage = \"authorized\";\n return response;\n }\n\n async validate(\n request: ValidatePaymentRequest,\n actionUrlOverride?: string\n ): Promise<ValidatePaymentResponse> {\n // Prefer an explicit override, then the URL authorize() handed us,\n // then fall through to /payment/validate.\n const url = actionUrlOverride ?? this.validateActionUrl;\n const response = await this.client.validatePayment(request, url);\n this.stage = \"validated\";\n return response;\n }\n\n async verify(paymentRefOverride?: string): Promise<VerifyPaymentResponse> {\n const ref = paymentRefOverride ?? this.paymentReference ?? this.transactionId;\n if (!ref) {\n throw new Error(\n \"No paymentReference or transactionId available — call initiate() first, or pass it explicitly.\"\n );\n }\n const response = await this.client.verifyPayment(ref);\n // Only APPROVED counts as verified. PENDING stays \"validated\".\n if (response.status === \"APPROVED\") {\n this.stage = \"verified\";\n } else if (response.status === \"FAILED\") {\n this.stage = \"failed\";\n }\n return response;\n }\n}","export interface ApiErrorPayload {\n responseCode?: string;\n responseMessage?: string;\n message?: string;\n [key: string]: unknown;\n}\n\nexport class RemitaApiError extends Error {\n readonly status: number;\n readonly payload: ApiErrorPayload | undefined;\n\n constructor(message: string, status: number, payload?: ApiErrorPayload) {\n super(message);\n this.name = \"RemitaApiError\";\n this.status = status;\n this.payload = payload;\n }\n}\n\n/* -------------------------------------------------------------------- *\n * NOTE ON THE TYPES BELOW\n *\n * Field names for PrePaymentRequest are verified against a working QA\n * cURL. The rest remain best-effort based on standard gateway\n * conventions and should be tightened as real DTOs are confirmed.\n *\n * `publicKey` is NEVER part of a request body — it is sent as a header\n * by RemitaCheckoutClient. Do not add it back to any request interface.\n * -------------------------------------------------------------------- */\n\nexport interface PrePaymentRequest {\n firstName: string;\n lastName: string;\n email: string;\n phoneNumber: string;\n paymentIdentifier: string;\n currency: string;\n narration?: string;\n amount: number;\n [key: string]: unknown;\n}\n\nexport interface PaymentChannel {\n code: string;\n name: string;\n [key: string]: unknown;\n}\n\nexport interface PrePaymentResponse {\n merchantName?: string;\n amount?: number | string;\n currency?: string;\n channels?: PaymentChannel[];\n /** Forwarded from /payment/pre if the API echoes one. */\n transactionId?: string;\n paymentReference?: string;\n [key: string]: unknown;\n}\n\nexport interface FeeChargeRequest {\n amount: number;\n channel: string;\n [key: string]: unknown;\n}\n\nexport interface FeeChargeResponse {\n fee?: number | string;\n totalAmount?: number | string;\n [key: string]: unknown;\n}\n\nexport interface InitiatePaymentRequest {\n channel: string;\n amount: number;\n transactionId?: string;\n [key: string]: unknown;\n}\n\nexport interface InitiatePaymentResponse {\n /** Where to POST the next-step authorization payload (OTP, PIN, 3DS fields, etc). */\n actionUrl?: string;\n paymentReference?: string;\n transactionId?: string;\n status?: string;\n [key: string]: unknown;\n}\n\nexport type AuthorizePayload = Record<string, unknown>;\n\nexport interface AuthorizeResponse {\n status?: string;\n requiresValidation?: boolean;\n [key: string]: unknown;\n}\n\nexport interface ValidatePaymentRequest {\n paymentReference?: string;\n transactionId?: string;\n otp?: string;\n [key: string]: unknown;\n}\n\nexport interface ValidatePaymentResponse {\n status?: string;\n [key: string]: unknown;\n}\n\nexport type PaymentStatus = \"APPROVED\" | \"PENDING\" | \"FAILED\" | (string & {});\n\nexport interface VerifyPaymentResponse {\n status?: PaymentStatus;\n paymentReference?: string;\n amount?: number | string;\n [key: string]: unknown;\n}\n\nexport interface Bank {\n code: string;\n name: string;\n currency?: string;\n [key: string]: unknown;\n}\n\nexport interface BankListResponse {\n banks: Bank[];\n [key: string]: unknown;\n}\n\nexport interface UssdCode {\n bankCode: string;\n ussdCode: string;\n [key: string]: unknown;\n}\n\nexport interface UssdCodesResponse {\n codes: UssdCode[];\n [key: string]: unknown;\n}\n\nexport interface WalletType {\n code: string;\n name: string;\n [key: string]: unknown;\n}\n\nexport interface WalletTypesResponse {\n wallets: WalletType[];\n [key: string]: unknown;\n}\n\nexport interface StatusStreamEvent {\n status?: PaymentStatus;\n [key: string]: unknown;\n}"],"mappings":";;;;;;;;;;;AAAA;;;AC+BO,IAAM,iBAAN,MAAqB;AAAA,EAU1B,YAA6B,QAA8B;AAA9B;AAT7B,iBAA6B;AAAA,EAS+B;AAAA,EAE5D,MAAM,IAAI,SAAyD;AACjE,UAAM,WAAW,MAAM,KAAK,OAAO,WAAW,OAAO;AAErD,SAAK,gBAAgB,SAAS,iBAAiB,KAAK;AACpD,SAAK,mBAAmB,SAAS,oBAAoB,KAAK;AAC1D,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,SAAuD;AAC/D,UAAM,WAAW,MAAM,KAAK,OAAO,aAAa,OAAO;AACvD,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,SAAmE;AAChF,UAAM,WAAW,MAAM,KAAK,OAAO,gBAAgB,OAAO;AAC1D,SAAK,qBAAqB,SAAS;AACnC,SAAK,oBAAoB;AACzB,SAAK,mBAAmB,SAAS,oBAAoB,KAAK;AAC1D,SAAK,gBAAgB,SAAS,iBAAiB,KAAK;AACpD,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UACJ,SACA,mBACA,aAC4B;AAC5B,UAAM,MAAM,qBAAqB,KAAK;AACtC,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,WAAW,MAAM,KAAK,OAAO,UAAU,KAAK,SAAS,WAAW;AAGtE,UAAM,OAAQ,SAAoC;AAClD,QAAI,KAAM,MAAK,oBAAoB;AAEnC,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SACJ,SACA,mBACkC;AAGlC,UAAM,MAAM,qBAAqB,KAAK;AACtC,UAAM,WAAW,MAAM,KAAK,OAAO,gBAAgB,SAAS,GAAG;AAC/D,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,oBAA6D;AACxE,UAAM,MAAM,sBAAsB,KAAK,oBAAoB,KAAK;AAChE,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,WAAW,MAAM,KAAK,OAAO,cAAc,GAAG;AAEpD,QAAI,SAAS,WAAW,YAAY;AAClC,WAAK,QAAQ;AAAA,IACf,WAAW,SAAS,WAAW,UAAU;AACvC,WAAK,QAAQ;AAAA,IACf;AACA,WAAO;AAAA,EACT;AACF;;;ADnHA;AAUA;;;AETO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAIxC,YAAY,SAAiB,QAAgB,SAA2B;AACtE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "remita-checkout-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Typed client for the Remita Checkout REST API (pre-payment, fee calc, initiate, authorize, validate, verify, SSE status, channel config).",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"bin": {
|
|
21
|
+
"remita-checkout": "dist/cli.js"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup src/index.ts src/cli.ts --format cjs,esm --dts --sourcemap --clean",
|
|
28
|
+
"dev": "tsup src/index.ts src/cli.ts --format cjs,esm --dts --watch",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"test": "vitest run --reporter=verbose",
|
|
31
|
+
"prepublishOnly": "npm run build && npm run typecheck"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"remita",
|
|
35
|
+
"payment",
|
|
36
|
+
"checkout",
|
|
37
|
+
"nigeria",
|
|
38
|
+
"fintech"
|
|
39
|
+
],
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/<you>/<repo>.git"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/<you>/<repo>#readme",
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/<you>/<repo>/issues"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^22.0.0",
|
|
51
|
+
"tsup": "^8.5.1",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"vitest": "^2.1.0"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"license": "^1.0.3"
|
|
57
|
+
}
|
|
58
|
+
}
|