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/cli.mjs
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
RemitaCheckoutClient,
|
|
4
|
+
__commonJS,
|
|
5
|
+
init_client
|
|
6
|
+
} from "./chunk-MGQQHIIZ.mjs";
|
|
7
|
+
|
|
8
|
+
// src/cli.ts
|
|
9
|
+
import { parseArgs } from "util";
|
|
10
|
+
var require_cli = __commonJS({
|
|
11
|
+
"src/cli.ts"() {
|
|
12
|
+
init_client();
|
|
13
|
+
function printUsage() {
|
|
14
|
+
console.log(`
|
|
15
|
+
remita-checkout <command> [options]
|
|
16
|
+
|
|
17
|
+
Commands:
|
|
18
|
+
pre Pre-payment initialization
|
|
19
|
+
fee Calculate channel fee
|
|
20
|
+
initiate Initiate a payment
|
|
21
|
+
authorize Submit authorization params to an actionUrl
|
|
22
|
+
validate Validate second-factor authorization (e.g. OTP)
|
|
23
|
+
verify Verify payment status by reference
|
|
24
|
+
stream Stream real-time status updates (SSE) for a transaction
|
|
25
|
+
banks List supported banks
|
|
26
|
+
ussd List USSD codes
|
|
27
|
+
wallets List wallet types
|
|
28
|
+
|
|
29
|
+
Global options:
|
|
30
|
+
--key <publicKey> Remita public key (required for most commands)
|
|
31
|
+
--env <qa|demo|production> Explicit environment (skips prefix detection)
|
|
32
|
+
--base-url <url> Override the resolved base URL entirely
|
|
33
|
+
--json Print raw JSON only, useful for piping
|
|
34
|
+
|
|
35
|
+
Command-specific options:
|
|
36
|
+
pre: --rrr <rrr> | --txn <transactionId> [--payload '<json>']
|
|
37
|
+
fee: --amount <amount> --channel <channel>
|
|
38
|
+
initiate: --amount <amount> --channel <channel> [--txn <transactionId>]
|
|
39
|
+
authorize: --action-url <url> --payload '<json>'
|
|
40
|
+
validate: --payload '<json>' [--action-url <url>] [--ref <paymentReference>] [--otp <otp>]
|
|
41
|
+
verify: --ref <paymentReference>
|
|
42
|
+
stream: --trx <trxRef>
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
remita-checkout pre --key QA-abc123 --rrr 123456789
|
|
46
|
+
remita-checkout initiate --key QA-abc123 --amount 5000 --channel card --json
|
|
47
|
+
remita-checkout stream --key QA-abc123 --trx TRX-001
|
|
48
|
+
`);
|
|
49
|
+
}
|
|
50
|
+
function buildClient(values) {
|
|
51
|
+
const key = values.key;
|
|
52
|
+
if (!key) throw new Error("--key is required.");
|
|
53
|
+
const baseUrl = values["base-url"];
|
|
54
|
+
return new RemitaCheckoutClient({
|
|
55
|
+
publicKey: key,
|
|
56
|
+
environment: values.env,
|
|
57
|
+
baseUrls: baseUrl ? { qa: baseUrl, demo: baseUrl, production: baseUrl } : void 0,
|
|
58
|
+
onEnvironmentDetectionFallback: (guessed) => {
|
|
59
|
+
if (!values.json) {
|
|
60
|
+
console.error(`(couldn't detect environment from key prefix, defaulting to "${guessed}")`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function output(values, label, data) {
|
|
66
|
+
if (values.json) {
|
|
67
|
+
console.log(JSON.stringify(data, null, 2));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log(`
|
|
71
|
+
${label}:`);
|
|
72
|
+
console.log(JSON.stringify(data, null, 2));
|
|
73
|
+
}
|
|
74
|
+
function parsePayload(raw) {
|
|
75
|
+
if (!raw) return {};
|
|
76
|
+
try {
|
|
77
|
+
return JSON.parse(raw);
|
|
78
|
+
} catch {
|
|
79
|
+
throw new Error(`--payload must be valid JSON, e.g. --payload '{"otp":"123456"}'`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function main() {
|
|
83
|
+
const { values, positionals } = parseArgs({
|
|
84
|
+
allowPositionals: true,
|
|
85
|
+
options: {
|
|
86
|
+
key: { type: "string" },
|
|
87
|
+
env: { type: "string" },
|
|
88
|
+
"base-url": { type: "string" },
|
|
89
|
+
json: { type: "boolean", default: false },
|
|
90
|
+
rrr: { type: "string" },
|
|
91
|
+
txn: { type: "string" },
|
|
92
|
+
amount: { type: "string" },
|
|
93
|
+
channel: { type: "string" },
|
|
94
|
+
"action-url": { type: "string" },
|
|
95
|
+
payload: { type: "string" },
|
|
96
|
+
ref: { type: "string" },
|
|
97
|
+
otp: { type: "string" },
|
|
98
|
+
trx: { type: "string" },
|
|
99
|
+
help: { type: "boolean", default: false }
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const command = positionals[0];
|
|
103
|
+
if (!command || values.help) {
|
|
104
|
+
printUsage();
|
|
105
|
+
process.exit(command ? 0 : 1);
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
switch (command) {
|
|
109
|
+
case "pre": {
|
|
110
|
+
const client = buildClient(values);
|
|
111
|
+
const result = await client.prePayment({
|
|
112
|
+
...parsePayload(values.payload),
|
|
113
|
+
publicKey: client.publicKey,
|
|
114
|
+
rrr: values.rrr,
|
|
115
|
+
transactionId: values.txn
|
|
116
|
+
});
|
|
117
|
+
output(values, "Pre-payment response", result);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case "fee": {
|
|
121
|
+
const client = buildClient(values);
|
|
122
|
+
if (!values.amount || !values.channel) {
|
|
123
|
+
throw new Error("fee requires --amount and --channel.");
|
|
124
|
+
}
|
|
125
|
+
const result = await client.calculateFee({
|
|
126
|
+
publicKey: client.publicKey,
|
|
127
|
+
amount: Number(values.amount),
|
|
128
|
+
channel: values.channel
|
|
129
|
+
});
|
|
130
|
+
output(values, "Fee response", result);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case "initiate": {
|
|
134
|
+
const client = buildClient(values);
|
|
135
|
+
if (!values.amount || !values.channel) {
|
|
136
|
+
throw new Error("initiate requires --amount and --channel.");
|
|
137
|
+
}
|
|
138
|
+
const result = await client.initiatePayment({
|
|
139
|
+
publicKey: client.publicKey,
|
|
140
|
+
amount: Number(values.amount),
|
|
141
|
+
channel: values.channel,
|
|
142
|
+
transactionId: values.txn
|
|
143
|
+
});
|
|
144
|
+
output(values, "Initiate response", result);
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
case "authorize": {
|
|
148
|
+
const client = buildClient(values);
|
|
149
|
+
const actionUrl = values["action-url"];
|
|
150
|
+
if (!actionUrl) throw new Error("authorize requires --action-url.");
|
|
151
|
+
const result = await client.authorize(
|
|
152
|
+
actionUrl,
|
|
153
|
+
parsePayload(values.payload)
|
|
154
|
+
);
|
|
155
|
+
output(values, "Authorize response", result);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case "validate": {
|
|
159
|
+
const client = buildClient(values);
|
|
160
|
+
const payload = parsePayload(values.payload);
|
|
161
|
+
const result = await client.validatePayment(
|
|
162
|
+
{
|
|
163
|
+
paymentReference: values.ref,
|
|
164
|
+
otp: values.otp,
|
|
165
|
+
...payload
|
|
166
|
+
},
|
|
167
|
+
values["action-url"]
|
|
168
|
+
);
|
|
169
|
+
output(values, "Validate response", result);
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case "verify": {
|
|
173
|
+
const client = buildClient(values);
|
|
174
|
+
const ref = values.ref;
|
|
175
|
+
if (!ref) throw new Error("verify requires --ref.");
|
|
176
|
+
const result = await client.verifyPayment(ref);
|
|
177
|
+
output(values, "Verify response", result);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case "stream": {
|
|
181
|
+
const client = buildClient(values);
|
|
182
|
+
const trx = values.trx;
|
|
183
|
+
if (!trx) throw new Error("stream requires --trx.");
|
|
184
|
+
console.error(`Streaming status for ${trx}. Ctrl+C to stop.`);
|
|
185
|
+
const handle = client.streamPaymentStatus(trx, {
|
|
186
|
+
onOpen: () => console.error("(stream open)"),
|
|
187
|
+
onMessage: (event) => console.log(JSON.stringify(event.data, null, 2)),
|
|
188
|
+
onError: (err) => {
|
|
189
|
+
console.error("Stream error:", err);
|
|
190
|
+
process.exitCode = 1;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
process.on("SIGINT", () => {
|
|
194
|
+
handle.close();
|
|
195
|
+
process.exit(0);
|
|
196
|
+
});
|
|
197
|
+
await new Promise(() => {
|
|
198
|
+
});
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
case "banks": {
|
|
202
|
+
const client = buildClient(values);
|
|
203
|
+
output(values, "Bank list", await client.getBankList());
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
case "ussd": {
|
|
207
|
+
const client = buildClient(values);
|
|
208
|
+
output(values, "USSD codes", await client.getUssdCodes());
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
case "wallets": {
|
|
212
|
+
const client = buildClient(values);
|
|
213
|
+
output(values, "Wallet types", await client.getWalletTypes());
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
default:
|
|
217
|
+
console.error(`Unknown command: ${command}
|
|
218
|
+
`);
|
|
219
|
+
printUsage();
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
} catch (err) {
|
|
223
|
+
console.error("Error:", err instanceof Error ? err.message : err);
|
|
224
|
+
process.exitCode = 1;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
main();
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
export default require_cli();
|
|
231
|
+
//# sourceMappingURL=cli.mjs.map
|
package/dist/cli.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n// Node.js provides this builtin at runtime; the project does not currently\n// include Node.js type definitions, so suppress only this module-resolution\n// diagnostic until @types/node is added.\n// @ts-ignore\nimport { parseArgs } from \"node:util\";\nimport { RemitaCheckoutClient } from \"./client\";\nimport type { RemitaEnvironment } from \"./environment\";\n\ndeclare const process: {\n exit(code?: number): never;\n exitCode?: number;\n on(signal: string, listener: () => void): void;\n};\n\nfunction printUsage(): void {\n console.log(`\nremita-checkout <command> [options]\n\nCommands:\n pre Pre-payment initialization\n fee Calculate channel fee\n initiate Initiate a payment\n authorize Submit authorization params to an actionUrl\n validate Validate second-factor authorization (e.g. OTP)\n verify Verify payment status by reference\n stream Stream real-time status updates (SSE) for a transaction\n banks List supported banks\n ussd List USSD codes\n wallets List wallet types\n\nGlobal options:\n --key <publicKey> Remita public key (required for most commands)\n --env <qa|demo|production> Explicit environment (skips prefix detection)\n --base-url <url> Override the resolved base URL entirely\n --json Print raw JSON only, useful for piping\n\nCommand-specific options:\n pre: --rrr <rrr> | --txn <transactionId> [--payload '<json>']\n fee: --amount <amount> --channel <channel>\n initiate: --amount <amount> --channel <channel> [--txn <transactionId>]\n authorize: --action-url <url> --payload '<json>'\n validate: --payload '<json>' [--action-url <url>] [--ref <paymentReference>] [--otp <otp>]\n verify: --ref <paymentReference>\n stream: --trx <trxRef>\n\nExamples:\n remita-checkout pre --key QA-abc123 --rrr 123456789\n remita-checkout initiate --key QA-abc123 --amount 5000 --channel card --json\n remita-checkout stream --key QA-abc123 --trx TRX-001\n`);\n}\n\ntype ParsedValues = Record<string, string | boolean | undefined>;\n\nfunction buildClient(values: ParsedValues): RemitaCheckoutClient {\n const key = values.key as string | undefined;\n if (!key) throw new Error(\"--key is required.\");\n\n const baseUrl = values[\"base-url\"] as string | undefined;\n\n return new RemitaCheckoutClient({\n publicKey: key,\n environment: values.env as RemitaEnvironment | undefined,\n baseUrls: baseUrl ? { qa: baseUrl, demo: baseUrl, production: baseUrl } : undefined,\n onEnvironmentDetectionFallback: (guessed) => {\n if (!values.json) {\n console.error(`(couldn't detect environment from key prefix, defaulting to \"${guessed}\")`);\n }\n },\n });\n}\n\nfunction output(values: ParsedValues, label: string, data: unknown): void {\n if (values.json) {\n console.log(JSON.stringify(data, null, 2));\n return;\n }\n console.log(`\\n${label}:`);\n console.log(JSON.stringify(data, null, 2));\n}\n\nfunction parsePayload(raw: string | undefined): Record<string, unknown> {\n if (!raw) return {};\n try {\n return JSON.parse(raw);\n } catch {\n throw new Error(`--payload must be valid JSON, e.g. --payload '{\"otp\":\"123456\"}'`);\n }\n}\n\nasync function main(): Promise<void> {\n const { values, positionals } = parseArgs({\n allowPositionals: true,\n options: {\n key: { type: \"string\" },\n env: { type: \"string\" },\n \"base-url\": { type: \"string\" },\n json: { type: \"boolean\", default: false },\n rrr: { type: \"string\" },\n txn: { type: \"string\" },\n amount: { type: \"string\" },\n channel: { type: \"string\" },\n \"action-url\": { type: \"string\" },\n payload: { type: \"string\" },\n ref: { type: \"string\" },\n otp: { type: \"string\" },\n trx: { type: \"string\" },\n help: { type: \"boolean\", default: false },\n },\n });\n\n const command = positionals[0];\n\n if (!command || values.help) {\n printUsage();\n process.exit(command ? 0 : 1);\n }\n\n try {\n switch (command) {\n case \"pre\": {\n const client = buildClient(values);\n const result = await client.prePayment({\n ...parsePayload(values.payload as string | undefined),\n publicKey: client.publicKey,\n rrr: values.rrr as string | undefined,\n transactionId: values.txn as string | undefined,\n } as unknown as Parameters<RemitaCheckoutClient[\"prePayment\"]>[0]);\n output(values, \"Pre-payment response\", result);\n break;\n }\n\n case \"fee\": {\n const client = buildClient(values);\n if (!values.amount || !values.channel) {\n throw new Error(\"fee requires --amount and --channel.\");\n }\n const result = await client.calculateFee({\n publicKey: client.publicKey,\n amount: Number(values.amount),\n channel: values.channel as string,\n });\n output(values, \"Fee response\", result);\n break;\n }\n\n case \"initiate\": {\n const client = buildClient(values);\n if (!values.amount || !values.channel) {\n throw new Error(\"initiate requires --amount and --channel.\");\n }\n const result = await client.initiatePayment({\n publicKey: client.publicKey,\n amount: Number(values.amount),\n channel: values.channel as string,\n transactionId: values.txn as string | undefined,\n });\n output(values, \"Initiate response\", result);\n break;\n }\n\n case \"authorize\": {\n const client = buildClient(values);\n const actionUrl = values[\"action-url\"] as string | undefined;\n if (!actionUrl) throw new Error(\"authorize requires --action-url.\");\n const result = await client.authorize(\n actionUrl,\n parsePayload(values.payload as string | undefined)\n );\n output(values, \"Authorize response\", result);\n break;\n }\n\n case \"validate\": {\n const client = buildClient(values);\n const payload = parsePayload(values.payload as string | undefined);\n const result = await client.validatePayment(\n {\n paymentReference: values.ref as string | undefined,\n otp: values.otp as string | undefined,\n ...payload,\n },\n values[\"action-url\"] as string | undefined\n );\n output(values, \"Validate response\", result);\n break;\n }\n\n case \"verify\": {\n const client = buildClient(values);\n const ref = values.ref as string | undefined;\n if (!ref) throw new Error(\"verify requires --ref.\");\n const result = await client.verifyPayment(ref);\n output(values, \"Verify response\", result);\n break;\n }\n\n case \"stream\": {\n const client = buildClient(values);\n const trx = values.trx as string | undefined;\n if (!trx) throw new Error(\"stream requires --trx.\");\n console.error(`Streaming status for ${trx}. Ctrl+C to stop.`);\n const handle = client.streamPaymentStatus(trx, {\n onOpen: () => console.error(\"(stream open)\"),\n onMessage: (event) => console.log(JSON.stringify(event.data, null, 2)),\n onError: (err) => {\n console.error(\"Stream error:\", err);\n process.exitCode = 1;\n },\n });\n process.on(\"SIGINT\", () => {\n handle.close();\n process.exit(0);\n });\n await new Promise(() => {}); // keep the process alive until Ctrl+C\n break;\n }\n\n case \"banks\": {\n const client = buildClient(values);\n output(values, \"Bank list\", await client.getBankList());\n break;\n }\n\n case \"ussd\": {\n const client = buildClient(values);\n output(values, \"USSD codes\", await client.getUssdCodes());\n break;\n }\n\n case \"wallets\": {\n const client = buildClient(values);\n output(values, \"Wallet types\", await client.getWalletTypes());\n break;\n }\n\n default:\n console.error(`Unknown command: ${command}\\n`);\n printUsage();\n process.exit(1);\n }\n } catch (err) {\n console.error(\"Error:\", err instanceof Error ? err.message : err);\n process.exitCode = 1;\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
type RemitaEnvironment = "qa" | "demo" | "production";
|
|
2
|
+
declare const ENVIRONMENT_BASE_URLS: Record<RemitaEnvironment, string>;
|
|
3
|
+
interface ResolveEnvironmentOptions {
|
|
4
|
+
/** Explicit override — always wins over prefix detection. */
|
|
5
|
+
environment?: RemitaEnvironment;
|
|
6
|
+
/** Custom base URLs, e.g. to point at a local/staging mirror. */
|
|
7
|
+
baseUrls?: Partial<Record<RemitaEnvironment, string>>;
|
|
8
|
+
}
|
|
9
|
+
interface ResolvedEnvironment {
|
|
10
|
+
environment: RemitaEnvironment;
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
/** False when detection couldn't confidently match a prefix and we fell back to a default. */
|
|
13
|
+
detected: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare function resolveEnvironment(publicKey: string, options?: ResolveEnvironmentOptions): ResolvedEnvironment;
|
|
16
|
+
|
|
17
|
+
interface ApiErrorPayload {
|
|
18
|
+
responseCode?: string;
|
|
19
|
+
responseMessage?: string;
|
|
20
|
+
message?: string;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
declare class RemitaApiError extends Error {
|
|
24
|
+
readonly status: number;
|
|
25
|
+
readonly payload: ApiErrorPayload | undefined;
|
|
26
|
+
constructor(message: string, status: number, payload?: ApiErrorPayload);
|
|
27
|
+
}
|
|
28
|
+
interface PrePaymentRequest {
|
|
29
|
+
firstName: string;
|
|
30
|
+
lastName: string;
|
|
31
|
+
email: string;
|
|
32
|
+
phoneNumber: string;
|
|
33
|
+
paymentIdentifier: string;
|
|
34
|
+
currency: string;
|
|
35
|
+
narration?: string;
|
|
36
|
+
amount: number;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
interface PaymentChannel {
|
|
40
|
+
code: string;
|
|
41
|
+
name: string;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
interface PrePaymentResponse {
|
|
45
|
+
merchantName?: string;
|
|
46
|
+
amount?: number | string;
|
|
47
|
+
currency?: string;
|
|
48
|
+
channels?: PaymentChannel[];
|
|
49
|
+
/** Forwarded from /payment/pre if the API echoes one. */
|
|
50
|
+
transactionId?: string;
|
|
51
|
+
paymentReference?: string;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
}
|
|
54
|
+
interface FeeChargeRequest {
|
|
55
|
+
amount: number;
|
|
56
|
+
channel: string;
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
}
|
|
59
|
+
interface FeeChargeResponse {
|
|
60
|
+
fee?: number | string;
|
|
61
|
+
totalAmount?: number | string;
|
|
62
|
+
[key: string]: unknown;
|
|
63
|
+
}
|
|
64
|
+
interface InitiatePaymentRequest {
|
|
65
|
+
channel: string;
|
|
66
|
+
amount: number;
|
|
67
|
+
transactionId?: string;
|
|
68
|
+
[key: string]: unknown;
|
|
69
|
+
}
|
|
70
|
+
interface InitiatePaymentResponse {
|
|
71
|
+
/** Where to POST the next-step authorization payload (OTP, PIN, 3DS fields, etc). */
|
|
72
|
+
actionUrl?: string;
|
|
73
|
+
paymentReference?: string;
|
|
74
|
+
transactionId?: string;
|
|
75
|
+
status?: string;
|
|
76
|
+
[key: string]: unknown;
|
|
77
|
+
}
|
|
78
|
+
type AuthorizePayload = Record<string, unknown>;
|
|
79
|
+
interface AuthorizeResponse {
|
|
80
|
+
status?: string;
|
|
81
|
+
requiresValidation?: boolean;
|
|
82
|
+
[key: string]: unknown;
|
|
83
|
+
}
|
|
84
|
+
interface ValidatePaymentRequest {
|
|
85
|
+
paymentReference?: string;
|
|
86
|
+
transactionId?: string;
|
|
87
|
+
otp?: string;
|
|
88
|
+
[key: string]: unknown;
|
|
89
|
+
}
|
|
90
|
+
interface ValidatePaymentResponse {
|
|
91
|
+
status?: string;
|
|
92
|
+
[key: string]: unknown;
|
|
93
|
+
}
|
|
94
|
+
type PaymentStatus = "APPROVED" | "PENDING" | "FAILED" | (string & {});
|
|
95
|
+
interface VerifyPaymentResponse {
|
|
96
|
+
status?: PaymentStatus;
|
|
97
|
+
paymentReference?: string;
|
|
98
|
+
amount?: number | string;
|
|
99
|
+
[key: string]: unknown;
|
|
100
|
+
}
|
|
101
|
+
interface Bank {
|
|
102
|
+
code: string;
|
|
103
|
+
name: string;
|
|
104
|
+
currency?: string;
|
|
105
|
+
[key: string]: unknown;
|
|
106
|
+
}
|
|
107
|
+
interface BankListResponse {
|
|
108
|
+
banks: Bank[];
|
|
109
|
+
[key: string]: unknown;
|
|
110
|
+
}
|
|
111
|
+
interface UssdCode {
|
|
112
|
+
bankCode: string;
|
|
113
|
+
ussdCode: string;
|
|
114
|
+
[key: string]: unknown;
|
|
115
|
+
}
|
|
116
|
+
interface UssdCodesResponse {
|
|
117
|
+
codes: UssdCode[];
|
|
118
|
+
[key: string]: unknown;
|
|
119
|
+
}
|
|
120
|
+
interface WalletType {
|
|
121
|
+
code: string;
|
|
122
|
+
name: string;
|
|
123
|
+
[key: string]: unknown;
|
|
124
|
+
}
|
|
125
|
+
interface WalletTypesResponse {
|
|
126
|
+
wallets: WalletType[];
|
|
127
|
+
[key: string]: unknown;
|
|
128
|
+
}
|
|
129
|
+
interface StatusStreamEvent {
|
|
130
|
+
status?: PaymentStatus;
|
|
131
|
+
[key: string]: unknown;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
interface StatusStreamOptions {
|
|
135
|
+
onMessage: (event: {
|
|
136
|
+
data: unknown;
|
|
137
|
+
raw: string;
|
|
138
|
+
}) => void;
|
|
139
|
+
onError?: (err: unknown) => void;
|
|
140
|
+
onOpen?: () => void;
|
|
141
|
+
fetchImpl?: typeof fetch;
|
|
142
|
+
/** Optional override; publicKey is sent as a query param by default. */
|
|
143
|
+
sendPublicKeyHeader?: boolean;
|
|
144
|
+
}
|
|
145
|
+
interface StatusStreamHandle {
|
|
146
|
+
close: () => void;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Opens the payment status SSE stream using a manual fetch + ReadableStream
|
|
150
|
+
* reader rather than the browser-only `EventSource` global, so this works
|
|
151
|
+
* identically in the browser and in Node 18+.
|
|
152
|
+
*/
|
|
153
|
+
declare function openStatusStream(baseUrl: string, trxRef: string, publicKey: string, options: StatusStreamOptions): StatusStreamHandle;
|
|
154
|
+
|
|
155
|
+
interface RemitaCheckoutClientOptions extends ResolveEnvironmentOptions {
|
|
156
|
+
publicKey: string;
|
|
157
|
+
fetchImpl?: typeof fetch;
|
|
158
|
+
timeoutMs?: number;
|
|
159
|
+
/** Extra headers merged after `publicKey` is set (so they can override). */
|
|
160
|
+
defaultHeaders?: Record<string, string>;
|
|
161
|
+
/** Called once if the environment couldn't be confidently detected from the key prefix (falls back to "qa"). */
|
|
162
|
+
onEnvironmentDetectionFallback?: (guessed: "qa") => void;
|
|
163
|
+
}
|
|
164
|
+
declare class RemitaCheckoutClient {
|
|
165
|
+
readonly publicKey: string;
|
|
166
|
+
readonly environment: string;
|
|
167
|
+
readonly baseUrl: string;
|
|
168
|
+
private readonly http;
|
|
169
|
+
constructor(options: RemitaCheckoutClientOptions);
|
|
170
|
+
prePayment(request: PrePaymentRequest): Promise<PrePaymentResponse>;
|
|
171
|
+
calculateFee(request: FeeChargeRequest): Promise<FeeChargeResponse>;
|
|
172
|
+
initiatePayment(request: InitiatePaymentRequest): Promise<InitiatePaymentResponse>;
|
|
173
|
+
/**
|
|
174
|
+
* Posts authorization params (OTP, PIN, 3DS form fields, etc) to the
|
|
175
|
+
* processor-provided actionUrl from initiatePayment().
|
|
176
|
+
*
|
|
177
|
+
* NOTE: CyberSource/Cardinal 3DS endpoints expect
|
|
178
|
+
* `application/x-www-form-urlencoded`. Pass `contentType` if the
|
|
179
|
+
* actionUrl is a 3DS processor endpoint.
|
|
180
|
+
*/
|
|
181
|
+
authorize(actionUrl: string, payload: AuthorizePayload, contentType?: string): Promise<AuthorizeResponse>;
|
|
182
|
+
/**
|
|
183
|
+
* Validates second-factor authorization (e.g. OTP). Per the endpoint docs
|
|
184
|
+
* this may go to a fixed /payment/validate endpoint OR to a dynamic
|
|
185
|
+
* actionUrl — pass `actionUrl` if the preceding step returned one.
|
|
186
|
+
*/
|
|
187
|
+
validatePayment(request: ValidatePaymentRequest, actionUrl?: string): Promise<ValidatePaymentResponse>;
|
|
188
|
+
verifyPayment(paymentRef: string): Promise<VerifyPaymentResponse>;
|
|
189
|
+
/** Opens an SSE stream for real-time status updates. Call the returned `close()` when done. */
|
|
190
|
+
streamPaymentStatus(trxRef: string, options: StatusStreamOptions): StatusStreamHandle;
|
|
191
|
+
getBankList(): Promise<BankListResponse>;
|
|
192
|
+
getUssdCodes(): Promise<UssdCodesResponse>;
|
|
193
|
+
getWalletTypes(): Promise<WalletTypesResponse>;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
type PaymentSessionStage = "idle" | "pre" | "fee" | "initiated" | "authorized" | "validated" | "verified" | "failed";
|
|
197
|
+
/**
|
|
198
|
+
* Sequences the multi-step payment flow (pre → fee → initiate → authorize →
|
|
199
|
+
* validate → verify) and tracks the refs each step hands to the next
|
|
200
|
+
* (paymentReference, transactionId, actionUrl), so callers don't have to
|
|
201
|
+
* thread that state through by hand.
|
|
202
|
+
*/
|
|
203
|
+
declare class PaymentSession {
|
|
204
|
+
private readonly client;
|
|
205
|
+
stage: PaymentSessionStage;
|
|
206
|
+
paymentReference?: string;
|
|
207
|
+
transactionId?: string;
|
|
208
|
+
/** URL returned by initiate() for the *authorize* step. */
|
|
209
|
+
private authorizeActionUrl?;
|
|
210
|
+
/** URL returned by authorize() for the *validate* step, if different. */
|
|
211
|
+
private validateActionUrl?;
|
|
212
|
+
constructor(client: RemitaCheckoutClient);
|
|
213
|
+
pre(request: PrePaymentRequest): Promise<PrePaymentResponse>;
|
|
214
|
+
fee(request: FeeChargeRequest): Promise<FeeChargeResponse>;
|
|
215
|
+
initiate(request: InitiatePaymentRequest): Promise<InitiatePaymentResponse>;
|
|
216
|
+
/**
|
|
217
|
+
* Uses the actionUrl captured from initiate() unless you pass one explicitly.
|
|
218
|
+
* Pass `contentType` for 3DS processor endpoints that require form-encoding.
|
|
219
|
+
*/
|
|
220
|
+
authorize(payload: AuthorizePayload, actionUrlOverride?: string, contentType?: string): Promise<AuthorizeResponse>;
|
|
221
|
+
validate(request: ValidatePaymentRequest, actionUrlOverride?: string): Promise<ValidatePaymentResponse>;
|
|
222
|
+
verify(paymentRefOverride?: string): Promise<VerifyPaymentResponse>;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export { type ApiErrorPayload, type AuthorizePayload, type AuthorizeResponse, type Bank, type BankListResponse, ENVIRONMENT_BASE_URLS, type FeeChargeRequest, type FeeChargeResponse, type InitiatePaymentRequest, type InitiatePaymentResponse, type PaymentChannel, PaymentSession, type PaymentSessionStage, type PaymentStatus, type PrePaymentRequest, type PrePaymentResponse, RemitaApiError, RemitaCheckoutClient, type RemitaCheckoutClientOptions, type RemitaEnvironment, type ResolveEnvironmentOptions, type ResolvedEnvironment, type StatusStreamEvent, type StatusStreamHandle, type StatusStreamOptions, type UssdCode, type UssdCodesResponse, type ValidatePaymentRequest, type ValidatePaymentResponse, type VerifyPaymentResponse, type WalletType, type WalletTypesResponse, openStatusStream, resolveEnvironment };
|