payweave 0.0.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 +272 -0
- package/dist/_tsup-dts-rollup.d.ts +19470 -0
- package/dist/chunk-4R5OGOCC.js +94 -0
- package/dist/chunk-4R5OGOCC.js.map +1 -0
- package/dist/chunk-535Q3GUN.js +175 -0
- package/dist/chunk-535Q3GUN.js.map +1 -0
- package/dist/chunk-67NRYGRC.js +192 -0
- package/dist/chunk-67NRYGRC.js.map +1 -0
- package/dist/chunk-CGQ73I4I.js +568 -0
- package/dist/chunk-CGQ73I4I.js.map +1 -0
- package/dist/chunk-CJEYDHY6.js +18 -0
- package/dist/chunk-CJEYDHY6.js.map +1 -0
- package/dist/chunk-CR63JAAS.js +3 -0
- package/dist/chunk-CR63JAAS.js.map +1 -0
- package/dist/chunk-E633MKVX.js +1507 -0
- package/dist/chunk-E633MKVX.js.map +1 -0
- package/dist/chunk-FBPOCXRZ.js +1135 -0
- package/dist/chunk-FBPOCXRZ.js.map +1 -0
- package/dist/chunk-HTRGMZFH.js +267 -0
- package/dist/chunk-HTRGMZFH.js.map +1 -0
- package/dist/chunk-IUVGM3K7.js +765 -0
- package/dist/chunk-IUVGM3K7.js.map +1 -0
- package/dist/chunk-JD4OZHRI.js +326 -0
- package/dist/chunk-JD4OZHRI.js.map +1 -0
- package/dist/chunk-NV3MZF7L.js +139 -0
- package/dist/chunk-NV3MZF7L.js.map +1 -0
- package/dist/chunk-NXQBP35U.js +13 -0
- package/dist/chunk-NXQBP35U.js.map +1 -0
- package/dist/chunk-QJHXDZYC.js +412 -0
- package/dist/chunk-QJHXDZYC.js.map +1 -0
- package/dist/chunk-TWZK62TZ.js +83 -0
- package/dist/chunk-TWZK62TZ.js.map +1 -0
- package/dist/cli/index.js +35381 -0
- package/dist/core/index.d.ts +85 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/db/drizzle/index.d.ts +6 -0
- package/dist/db/drizzle/index.js +1532 -0
- package/dist/db/drizzle/index.js.map +1 -0
- package/dist/db/index.d.ts +43 -0
- package/dist/db/index.js +3 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/mongodb/index.d.ts +3 -0
- package/dist/db/mongodb/index.js +934 -0
- package/dist/db/mongodb/index.js.map +1 -0
- package/dist/db/mysql/index.d.ts +1 -0
- package/dist/db/mysql/index.js +12 -0
- package/dist/db/mysql/index.js.map +1 -0
- package/dist/db/postgres/index.d.ts +5 -0
- package/dist/db/postgres/index.js +791 -0
- package/dist/db/postgres/index.js.map +1 -0
- package/dist/db/prisma/index.d.ts +1 -0
- package/dist/db/prisma/index.js +12 -0
- package/dist/db/prisma/index.js.map +1 -0
- package/dist/db/sqlite/index.d.ts +5 -0
- package/dist/db/sqlite/index.js +750 -0
- package/dist/db/sqlite/index.js.map +1 -0
- package/dist/express/index.d.ts +1 -0
- package/dist/express/index.js +3 -0
- package/dist/express/index.js.map +1 -0
- package/dist/fastify/index.d.ts +1 -0
- package/dist/fastify/index.js +3 -0
- package/dist/fastify/index.js.map +1 -0
- package/dist/flutterwave/index.d.ts +27 -0
- package/dist/flutterwave/index.js +9 -0
- package/dist/flutterwave/index.js.map +1 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.js +3677 -0
- package/dist/index.js.map +1 -0
- package/dist/next/index.d.ts +1 -0
- package/dist/next/index.js +3 -0
- package/dist/next/index.js.map +1 -0
- package/dist/paystack/index.d.ts +33 -0
- package/dist/paystack/index.js +9 -0
- package/dist/paystack/index.js.map +1 -0
- package/dist/products/index.d.ts +22 -0
- package/dist/products/index.js +7 -0
- package/dist/products/index.js.map +1 -0
- package/dist/testing/index.d.ts +11 -0
- package/dist/testing/index.js +69 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/unified/index.d.ts +41 -0
- package/dist/unified/index.js +6 -0
- package/dist/unified/index.js.map +1 -0
- package/dist/webhooks/index.d.ts +8 -0
- package/dist/webhooks/index.js +8 -0
- package/dist/webhooks/index.js.map +1 -0
- package/package.json +164 -0
|
@@ -0,0 +1,1135 @@
|
|
|
1
|
+
import { defineProvider, FLW_V4_BASE_URL, FLW_V4_SANDBOX_URL, FLW_V3_BASE_URL, flutterwaveProviderConfigSchema, inferEnvironment, HttpClient, oauthClientCredentials, bearer, readHeader } from './chunk-IUVGM3K7.js';
|
|
2
|
+
import { verifyFlutterwaveV4, verifyFlutterwaveV3 } from './chunk-CJEYDHY6.js';
|
|
3
|
+
import { toUnifiedEventType } from './chunk-67NRYGRC.js';
|
|
4
|
+
import { PayweaveConfigError, PayweaveValidationError } from './chunk-HTRGMZFH.js';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { createCipheriv, createDecipheriv } from 'crypto';
|
|
7
|
+
|
|
8
|
+
function parseRequest(schema, input) {
|
|
9
|
+
try {
|
|
10
|
+
return schema.parse(input);
|
|
11
|
+
} catch (err) {
|
|
12
|
+
if (err instanceof z.ZodError) {
|
|
13
|
+
const detail = err.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
|
|
14
|
+
throw new PayweaveValidationError(`flutterwave request validation failed \u2014 ${detail}`, {
|
|
15
|
+
provider: "flutterwave",
|
|
16
|
+
cause: err
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
var flwEnvelope = (data) => z.looseObject({
|
|
23
|
+
status: z.string(),
|
|
24
|
+
message: z.string(),
|
|
25
|
+
data
|
|
26
|
+
});
|
|
27
|
+
var pageInfo = z.looseObject({
|
|
28
|
+
total: z.union([z.number(), z.string()]).optional(),
|
|
29
|
+
current_page: z.union([z.number(), z.string()]).optional(),
|
|
30
|
+
total_pages: z.union([z.number(), z.string()]).optional()
|
|
31
|
+
});
|
|
32
|
+
var listMeta = z.looseObject({
|
|
33
|
+
page_info: pageInfo.optional()
|
|
34
|
+
});
|
|
35
|
+
var flwListEnvelope = (item) => z.looseObject({
|
|
36
|
+
status: z.string(),
|
|
37
|
+
message: z.string(),
|
|
38
|
+
data: z.array(item),
|
|
39
|
+
meta: listMeta.optional()
|
|
40
|
+
});
|
|
41
|
+
var metaSchema = z.record(z.string(), z.unknown());
|
|
42
|
+
function metaNumber(value) {
|
|
43
|
+
if (typeof value === "number") return value;
|
|
44
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
45
|
+
const n = Number(value);
|
|
46
|
+
return Number.isFinite(n) ? n : void 0;
|
|
47
|
+
}
|
|
48
|
+
return void 0;
|
|
49
|
+
}
|
|
50
|
+
var paymentCustomer = z.object({
|
|
51
|
+
email: z.string(),
|
|
52
|
+
name: z.string().optional(),
|
|
53
|
+
phonenumber: z.string().optional()
|
|
54
|
+
});
|
|
55
|
+
var paymentCustomizations = z.object({
|
|
56
|
+
title: z.string().optional(),
|
|
57
|
+
description: z.string().optional(),
|
|
58
|
+
logo: z.string().optional()
|
|
59
|
+
});
|
|
60
|
+
var paymentSubaccount = z.looseObject({
|
|
61
|
+
id: z.string(),
|
|
62
|
+
transaction_split_ratio: z.number().optional(),
|
|
63
|
+
transaction_charge_type: z.string().optional(),
|
|
64
|
+
transaction_charge: z.number().optional()
|
|
65
|
+
});
|
|
66
|
+
var createPaymentReq = z.object({
|
|
67
|
+
/** Your unique transaction reference. Required. */
|
|
68
|
+
tx_ref: z.string(),
|
|
69
|
+
/** Amount in MAJOR units (e.g. 5000 = ₦5,000). Passed through unchanged. */
|
|
70
|
+
amount: z.union([z.number(), z.string()]),
|
|
71
|
+
/** ISO currency, e.g. "NGN". Defaults to NGN on Flutterwave's side if omitted. */
|
|
72
|
+
currency: z.string().optional(),
|
|
73
|
+
/** URL Flutterwave redirects to after payment. */
|
|
74
|
+
redirect_url: z.string().optional(),
|
|
75
|
+
customer: paymentCustomer,
|
|
76
|
+
/** Comma-separated payment methods, e.g. "card,banktransfer,ussd". */
|
|
77
|
+
payment_options: z.string().optional(),
|
|
78
|
+
customizations: paymentCustomizations.optional(),
|
|
79
|
+
/** Existing payment-plan id to subscribe the customer to. */
|
|
80
|
+
payment_plan: z.union([z.string(), z.number()]).optional(),
|
|
81
|
+
subaccounts: z.array(paymentSubaccount).optional(),
|
|
82
|
+
meta: metaSchema.optional(),
|
|
83
|
+
/** Checkout session lifetime in minutes. */
|
|
84
|
+
session_duration: z.number().optional(),
|
|
85
|
+
/** Max number of retries allowed on the checkout. */
|
|
86
|
+
max_retry_attempt: z.number().optional()
|
|
87
|
+
});
|
|
88
|
+
var paymentInitData = z.looseObject({
|
|
89
|
+
link: z.string()
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// src/flutterwave/v3/resources/payments.ts
|
|
93
|
+
var paymentInitRes = flwEnvelope(paymentInitData);
|
|
94
|
+
var Payments = class {
|
|
95
|
+
constructor(http) {
|
|
96
|
+
this.http = http;
|
|
97
|
+
}
|
|
98
|
+
http;
|
|
99
|
+
/**
|
|
100
|
+
* Create a Standard payment and get a hosted checkout link. `amount` is in
|
|
101
|
+
* MAJOR units (e.g. `5000` = ₦5,000) and is sent to Flutterwave unchanged
|
|
102
|
+
* (Surface A). The checkout URL is returned at `data.link`.
|
|
103
|
+
*
|
|
104
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/standard
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const res = await fw.flutterwave.payments.create({
|
|
108
|
+
* tx_ref: "pwv_tx_001",
|
|
109
|
+
* amount: 5000, // ₦5,000 in major units
|
|
110
|
+
* currency: "NGN",
|
|
111
|
+
* redirect_url: "https://example.com/callback",
|
|
112
|
+
* customer: { email: "buyer@example.com" },
|
|
113
|
+
* });
|
|
114
|
+
* console.log(res.data.link);
|
|
115
|
+
*/
|
|
116
|
+
async create(input) {
|
|
117
|
+
const body = parseRequest(createPaymentReq, input);
|
|
118
|
+
return this.http.request({
|
|
119
|
+
method: "POST",
|
|
120
|
+
path: "/payments",
|
|
121
|
+
body,
|
|
122
|
+
schema: paymentInitRes
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
var transaction = z.looseObject({
|
|
127
|
+
id: z.number(),
|
|
128
|
+
tx_ref: z.string().nullable().optional(),
|
|
129
|
+
flw_ref: z.string().nullable().optional(),
|
|
130
|
+
device_fingerprint: z.string().nullable().optional(),
|
|
131
|
+
amount: z.number().optional(),
|
|
132
|
+
currency: z.string().optional(),
|
|
133
|
+
charged_amount: z.number().optional(),
|
|
134
|
+
app_fee: z.number().optional(),
|
|
135
|
+
merchant_fee: z.number().optional(),
|
|
136
|
+
processor_response: z.string().nullable().optional(),
|
|
137
|
+
auth_model: z.string().nullable().optional(),
|
|
138
|
+
ip: z.string().nullable().optional(),
|
|
139
|
+
narration: z.string().nullable().optional(),
|
|
140
|
+
/** Flutterwave transaction status, e.g. "successful" | "failed" | "pending". */
|
|
141
|
+
status: z.string().optional(),
|
|
142
|
+
payment_type: z.string().nullable().optional(),
|
|
143
|
+
created_at: z.string().optional(),
|
|
144
|
+
account_id: z.number().optional(),
|
|
145
|
+
amount_settled: z.number().optional(),
|
|
146
|
+
customer: z.looseObject({}).optional(),
|
|
147
|
+
card: z.looseObject({}).optional(),
|
|
148
|
+
meta: z.unknown().optional()
|
|
149
|
+
});
|
|
150
|
+
var listQuery = z.object({
|
|
151
|
+
from: z.string().optional(),
|
|
152
|
+
to: z.string().optional(),
|
|
153
|
+
page: z.number().int().positive().optional(),
|
|
154
|
+
customer_email: z.string().optional(),
|
|
155
|
+
status: z.string().optional(),
|
|
156
|
+
tx_ref: z.string().optional(),
|
|
157
|
+
currency: z.string().optional(),
|
|
158
|
+
amount: z.union([z.number(), z.string()]).optional()
|
|
159
|
+
});
|
|
160
|
+
var feesQuery = z.object({
|
|
161
|
+
amount: z.union([z.number(), z.string()]),
|
|
162
|
+
currency: z.string().optional(),
|
|
163
|
+
/** e.g. "card", "account", "ussd" — the charge type the fee is quoted for. */
|
|
164
|
+
ptype: z.string().optional()
|
|
165
|
+
});
|
|
166
|
+
var feeData = z.looseObject({
|
|
167
|
+
charge_amount: z.number().optional(),
|
|
168
|
+
fee: z.number().optional(),
|
|
169
|
+
merchant_fee: z.number().optional(),
|
|
170
|
+
flutterwave_fee: z.number().optional(),
|
|
171
|
+
stamp_duty_fee: z.number().optional(),
|
|
172
|
+
currency: z.string().optional()
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// src/flutterwave/v3/resources/transactions.ts
|
|
176
|
+
var transactionRes = flwEnvelope(transaction);
|
|
177
|
+
var transactionListRes = flwListEnvelope(transaction);
|
|
178
|
+
var feeRes = flwEnvelope(feeData);
|
|
179
|
+
var Transactions = class {
|
|
180
|
+
constructor(http) {
|
|
181
|
+
this.http = http;
|
|
182
|
+
}
|
|
183
|
+
http;
|
|
184
|
+
/**
|
|
185
|
+
* Verify a transaction by its numeric Flutterwave id (NOT `tx_ref` — use
|
|
186
|
+
* {@link verifyByReference} for that). A 404 for an unknown id surfaces as
|
|
187
|
+
* {@link PayweaveNotFoundError}.
|
|
188
|
+
*
|
|
189
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/verify-transaction
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* const res = await fw.flutterwave.transactions.verify(288200108);
|
|
193
|
+
* if (res.data.status === "successful") { }
|
|
194
|
+
*/
|
|
195
|
+
async verify(id) {
|
|
196
|
+
return this.http.request({
|
|
197
|
+
method: "GET",
|
|
198
|
+
path: `/transactions/${encodeURIComponent(String(id))}/verify`,
|
|
199
|
+
schema: transactionRes
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Verify a transaction by your `tx_ref` (the reference you supplied at
|
|
204
|
+
* checkout). This is a distinct endpoint from verify-by-id.
|
|
205
|
+
*
|
|
206
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/verify-transaction-by-tx_ref
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* const res = await fw.flutterwave.transactions.verifyByReference("pwv_tx_001");
|
|
210
|
+
*/
|
|
211
|
+
async verifyByReference(txRef) {
|
|
212
|
+
const tx_ref = parseRequest(z.string().min(1), txRef);
|
|
213
|
+
return this.http.request({
|
|
214
|
+
method: "GET",
|
|
215
|
+
path: "/transactions/verify_by_reference",
|
|
216
|
+
query: { tx_ref },
|
|
217
|
+
schema: transactionRes
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* List transactions on the account.
|
|
222
|
+
*
|
|
223
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/list-transactions
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* const page = await fw.flutterwave.transactions.list({ status: "successful" });
|
|
227
|
+
*/
|
|
228
|
+
async list(query = {}) {
|
|
229
|
+
const q = parseRequest(listQuery, query);
|
|
230
|
+
return this.http.request({
|
|
231
|
+
method: "GET",
|
|
232
|
+
path: "/transactions",
|
|
233
|
+
query: q,
|
|
234
|
+
schema: transactionListRes
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Async iterator over ALL transactions matching `query`, transparently walking
|
|
239
|
+
* every page via `meta.page_info.total_pages`.
|
|
240
|
+
*
|
|
241
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/list-transactions
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* for await (const tx of fw.flutterwave.transactions.iterate({ status: "successful" })) {
|
|
245
|
+
* console.log(tx.id);
|
|
246
|
+
* }
|
|
247
|
+
*/
|
|
248
|
+
async *iterate(query = {}) {
|
|
249
|
+
const base = parseRequest(listQuery, query);
|
|
250
|
+
let page = base.page ?? 1;
|
|
251
|
+
for (; ; ) {
|
|
252
|
+
const res = await this.http.request({
|
|
253
|
+
method: "GET",
|
|
254
|
+
path: "/transactions",
|
|
255
|
+
query: { ...base, page },
|
|
256
|
+
schema: transactionListRes
|
|
257
|
+
});
|
|
258
|
+
for (const tx of res.data) yield tx;
|
|
259
|
+
const totalPages = metaNumber(res.meta?.page_info?.total_pages);
|
|
260
|
+
if (totalPages !== void 0) {
|
|
261
|
+
if (page >= totalPages) return;
|
|
262
|
+
} else if (res.data.length === 0) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
page += 1;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get the fee Flutterwave would charge for an amount. `amount` is MAJOR units.
|
|
270
|
+
*
|
|
271
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-transaction-fees
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* const res = await fw.flutterwave.transactions.fees({ amount: 5000, currency: "NGN" });
|
|
275
|
+
*/
|
|
276
|
+
async fees(query) {
|
|
277
|
+
const q = parseRequest(feesQuery, query);
|
|
278
|
+
return this.http.request({
|
|
279
|
+
method: "GET",
|
|
280
|
+
path: "/transactions/fee",
|
|
281
|
+
query: q,
|
|
282
|
+
schema: feeRes
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
var bank = z.looseObject({
|
|
287
|
+
id: z.number().optional(),
|
|
288
|
+
code: z.string().optional(),
|
|
289
|
+
name: z.string().optional()
|
|
290
|
+
});
|
|
291
|
+
var bankBranch = z.looseObject({
|
|
292
|
+
id: z.number().optional(),
|
|
293
|
+
branch_code: z.string().optional(),
|
|
294
|
+
branch_name: z.string().optional(),
|
|
295
|
+
swift_code: z.string().nullable().optional(),
|
|
296
|
+
bic: z.string().nullable().optional(),
|
|
297
|
+
bank_id: z.number().optional()
|
|
298
|
+
});
|
|
299
|
+
var resolveAccountReq = z.object({
|
|
300
|
+
account_number: z.string(),
|
|
301
|
+
/** The bank code (from `GET /banks/:country`). */
|
|
302
|
+
account_bank: z.string()
|
|
303
|
+
});
|
|
304
|
+
var resolvedAccount = z.looseObject({
|
|
305
|
+
account_number: z.string().optional(),
|
|
306
|
+
account_name: z.string().optional()
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// src/flutterwave/v3/resources/banks.ts
|
|
310
|
+
var bankListRes = flwEnvelope(z.array(bank));
|
|
311
|
+
var branchListRes = flwEnvelope(z.array(bankBranch));
|
|
312
|
+
var resolveRes = flwEnvelope(resolvedAccount);
|
|
313
|
+
var Banks = class {
|
|
314
|
+
constructor(http) {
|
|
315
|
+
this.http = http;
|
|
316
|
+
}
|
|
317
|
+
http;
|
|
318
|
+
/**
|
|
319
|
+
* List the banks Flutterwave supports for a country (ISO-2 code, e.g. "NG").
|
|
320
|
+
* `data` is a flat array (no pagination on this endpoint).
|
|
321
|
+
*
|
|
322
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-all-banks
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* const res = await fw.flutterwave.banks.list("NG");
|
|
326
|
+
* console.log(res.data[0].code);
|
|
327
|
+
*/
|
|
328
|
+
async list(country) {
|
|
329
|
+
const value = parseRequest(z.string().min(1), country);
|
|
330
|
+
return this.http.request({
|
|
331
|
+
method: "GET",
|
|
332
|
+
path: `/banks/${encodeURIComponent(value)}`,
|
|
333
|
+
schema: bankListRes
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* List branches for a bank by its Flutterwave bank id.
|
|
338
|
+
*
|
|
339
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-bank-branches
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* const res = await fw.flutterwave.banks.branches(280);
|
|
343
|
+
*/
|
|
344
|
+
async branches(bankId) {
|
|
345
|
+
return this.http.request({
|
|
346
|
+
method: "GET",
|
|
347
|
+
path: `/banks/${encodeURIComponent(String(bankId))}/branches`,
|
|
348
|
+
schema: branchListRes
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Resolve a bank account number to its account holder name.
|
|
353
|
+
*
|
|
354
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/resolve-account-details
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* const res = await fw.flutterwave.banks.resolveAccount({
|
|
358
|
+
* account_number: "0690000040",
|
|
359
|
+
* account_bank: "044",
|
|
360
|
+
* });
|
|
361
|
+
* console.log(res.data.account_name);
|
|
362
|
+
*/
|
|
363
|
+
async resolveAccount(input) {
|
|
364
|
+
const body = parseRequest(resolveAccountReq, input);
|
|
365
|
+
return this.http.request({
|
|
366
|
+
method: "POST",
|
|
367
|
+
path: "/accounts/resolve",
|
|
368
|
+
body,
|
|
369
|
+
schema: resolveRes
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
var createRefundReq = z.object({
|
|
374
|
+
/** Amount to refund in MAJOR units. Omit for a full refund. */
|
|
375
|
+
amount: z.union([z.number(), z.string()]).optional()
|
|
376
|
+
});
|
|
377
|
+
var listRefundsQuery = z.object({
|
|
378
|
+
from: z.string().optional(),
|
|
379
|
+
to: z.string().optional(),
|
|
380
|
+
page: z.number().int().positive().optional(),
|
|
381
|
+
status: z.string().optional()
|
|
382
|
+
});
|
|
383
|
+
var refund = z.looseObject({
|
|
384
|
+
id: z.number().optional(),
|
|
385
|
+
account_id: z.number().optional(),
|
|
386
|
+
tx_id: z.number().optional(),
|
|
387
|
+
flw_ref: z.string().nullable().optional(),
|
|
388
|
+
amount_refunded: z.number().optional(),
|
|
389
|
+
status: z.string().optional(),
|
|
390
|
+
destination: z.string().nullable().optional(),
|
|
391
|
+
meta: z.unknown().optional(),
|
|
392
|
+
created_at: z.string().optional()
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// src/flutterwave/v3/resources/refunds.ts
|
|
396
|
+
var refundRes = flwEnvelope(refund);
|
|
397
|
+
var refundListRes = flwListEnvelope(refund);
|
|
398
|
+
var Refunds = class {
|
|
399
|
+
constructor(http) {
|
|
400
|
+
this.http = http;
|
|
401
|
+
}
|
|
402
|
+
http;
|
|
403
|
+
/**
|
|
404
|
+
* Refund a transaction by its numeric id. Omit `amount` to refund in full;
|
|
405
|
+
* `amount` (when given) is MAJOR units, passed through unchanged.
|
|
406
|
+
*
|
|
407
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/refund-a-transaction
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* const res = await fw.flutterwave.refunds.create(288200108, { amount: 1000 });
|
|
411
|
+
*/
|
|
412
|
+
async create(transactionId, input = {}) {
|
|
413
|
+
const body = parseRequest(createRefundReq, input);
|
|
414
|
+
return this.http.request({
|
|
415
|
+
method: "POST",
|
|
416
|
+
path: `/transactions/${encodeURIComponent(String(transactionId))}/refund`,
|
|
417
|
+
body,
|
|
418
|
+
schema: refundRes
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* List refunds on the account.
|
|
423
|
+
*
|
|
424
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-all-refunds
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* const page = await fw.flutterwave.refunds.list({ status: "completed" });
|
|
428
|
+
*/
|
|
429
|
+
async list(query = {}) {
|
|
430
|
+
const q = parseRequest(listRefundsQuery, query);
|
|
431
|
+
return this.http.request({
|
|
432
|
+
method: "GET",
|
|
433
|
+
path: "/refunds",
|
|
434
|
+
query: q,
|
|
435
|
+
schema: refundListRes
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Async iterator over ALL refunds matching `query`, walking every page via
|
|
440
|
+
* `meta.page_info.total_pages`.
|
|
441
|
+
*
|
|
442
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-all-refunds
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* for await (const r of fw.flutterwave.refunds.iterate()) console.log(r.id);
|
|
446
|
+
*/
|
|
447
|
+
async *iterate(query = {}) {
|
|
448
|
+
const base = parseRequest(listRefundsQuery, query);
|
|
449
|
+
let page = base.page ?? 1;
|
|
450
|
+
for (; ; ) {
|
|
451
|
+
const res = await this.http.request({
|
|
452
|
+
method: "GET",
|
|
453
|
+
path: "/refunds",
|
|
454
|
+
query: { ...base, page },
|
|
455
|
+
schema: refundListRes
|
|
456
|
+
});
|
|
457
|
+
for (const r of res.data) yield r;
|
|
458
|
+
const totalPages = metaNumber(res.meta?.page_info?.total_pages);
|
|
459
|
+
if (totalPages !== void 0) {
|
|
460
|
+
if (page >= totalPages) return;
|
|
461
|
+
} else if (res.data.length === 0) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
page += 1;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Fetch a single refund by its id.
|
|
469
|
+
*
|
|
470
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-a-refund
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* const res = await fw.flutterwave.refunds.fetch(15221);
|
|
474
|
+
*/
|
|
475
|
+
async fetch(refundId) {
|
|
476
|
+
return this.http.request({
|
|
477
|
+
method: "GET",
|
|
478
|
+
path: `/refunds/${encodeURIComponent(String(refundId))}`,
|
|
479
|
+
schema: refundRes
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
function encryptCharge(encryptionKey, payload) {
|
|
484
|
+
const key = toKey(encryptionKey);
|
|
485
|
+
const plaintext = JSON.stringify(payload);
|
|
486
|
+
const cipher = createCipheriv("des-ede3", key, null);
|
|
487
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
488
|
+
return encrypted.toString("base64");
|
|
489
|
+
}
|
|
490
|
+
function decryptCharge(encryptionKey, ciphertext) {
|
|
491
|
+
const key = toKey(encryptionKey);
|
|
492
|
+
const decipher = createDecipheriv("des-ede3", key, null);
|
|
493
|
+
const decrypted = Buffer.concat([
|
|
494
|
+
decipher.update(Buffer.from(ciphertext, "base64")),
|
|
495
|
+
decipher.final()
|
|
496
|
+
]);
|
|
497
|
+
return JSON.parse(decrypted.toString("utf8"));
|
|
498
|
+
}
|
|
499
|
+
function toKey(encryptionKey) {
|
|
500
|
+
const key = Buffer.from(encryptionKey, "utf8");
|
|
501
|
+
if (key.length !== 24) {
|
|
502
|
+
throw new PayweaveConfigError(
|
|
503
|
+
"Flutterwave v3 encryptionKey must be the 24-character dashboard Encryption Key (3DES needs a 24-byte key).",
|
|
504
|
+
{ provider: "flutterwave" }
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
return key;
|
|
508
|
+
}
|
|
509
|
+
var cardChargeReq = z.object({
|
|
510
|
+
card_number: z.string(),
|
|
511
|
+
cvv: z.string(),
|
|
512
|
+
expiry_month: z.string(),
|
|
513
|
+
expiry_year: z.string(),
|
|
514
|
+
currency: z.string(),
|
|
515
|
+
/** Amount in MAJOR units. Passed through unchanged. */
|
|
516
|
+
amount: z.union([z.number(), z.string()]),
|
|
517
|
+
email: z.string(),
|
|
518
|
+
tx_ref: z.string(),
|
|
519
|
+
fullname: z.string().optional(),
|
|
520
|
+
phone_number: z.string().optional(),
|
|
521
|
+
/** Required only for the AVS/NoAuth authorization flows. */
|
|
522
|
+
redirect_url: z.string().optional(),
|
|
523
|
+
/** 3DS / AVS / PIN authorization sub-object (validated loosely). */
|
|
524
|
+
authorization: z.looseObject({}).optional(),
|
|
525
|
+
preauthorize: z.boolean().optional(),
|
|
526
|
+
meta: metaSchema.optional()
|
|
527
|
+
});
|
|
528
|
+
var bankTransferChargeReq = z.object({
|
|
529
|
+
tx_ref: z.string(),
|
|
530
|
+
amount: z.union([z.number(), z.string()]),
|
|
531
|
+
email: z.string(),
|
|
532
|
+
currency: z.string().optional(),
|
|
533
|
+
fullname: z.string().optional(),
|
|
534
|
+
phone_number: z.string().optional(),
|
|
535
|
+
/** Whether the generated account/number is reusable (permanent). */
|
|
536
|
+
is_permanent: z.boolean().optional(),
|
|
537
|
+
narration: z.string().optional(),
|
|
538
|
+
meta: metaSchema.optional()
|
|
539
|
+
});
|
|
540
|
+
var ussdChargeReq = z.object({
|
|
541
|
+
tx_ref: z.string(),
|
|
542
|
+
/** Bank code for the USSD-supported bank, e.g. "057". */
|
|
543
|
+
account_bank: z.string(),
|
|
544
|
+
amount: z.union([z.number(), z.string()]),
|
|
545
|
+
email: z.string(),
|
|
546
|
+
currency: z.string().optional(),
|
|
547
|
+
fullname: z.string().optional(),
|
|
548
|
+
phone_number: z.string().optional(),
|
|
549
|
+
meta: metaSchema.optional()
|
|
550
|
+
});
|
|
551
|
+
var ngAccountChargeReq = z.object({
|
|
552
|
+
tx_ref: z.string(),
|
|
553
|
+
amount: z.union([z.number(), z.string()]),
|
|
554
|
+
account_bank: z.string(),
|
|
555
|
+
account_number: z.string(),
|
|
556
|
+
email: z.string(),
|
|
557
|
+
currency: z.string().optional(),
|
|
558
|
+
fullname: z.string().optional(),
|
|
559
|
+
phone_number: z.string().optional(),
|
|
560
|
+
/** BVN — required by some banks for the NG account-debit flow. */
|
|
561
|
+
bvn: z.string().optional(),
|
|
562
|
+
meta: metaSchema.optional()
|
|
563
|
+
});
|
|
564
|
+
var validateChargeReq = z.object({
|
|
565
|
+
otp: z.string(),
|
|
566
|
+
/** The transaction's `flw_ref` from the initial charge response. */
|
|
567
|
+
flw_ref: z.string(),
|
|
568
|
+
type: z.string().optional()
|
|
569
|
+
});
|
|
570
|
+
var chargeData = z.looseObject({
|
|
571
|
+
id: z.number().optional(),
|
|
572
|
+
tx_ref: z.string().nullable().optional(),
|
|
573
|
+
flw_ref: z.string().nullable().optional(),
|
|
574
|
+
amount: z.number().optional(),
|
|
575
|
+
currency: z.string().optional(),
|
|
576
|
+
status: z.string().optional(),
|
|
577
|
+
payment_type: z.string().nullable().optional(),
|
|
578
|
+
processor_response: z.string().nullable().optional(),
|
|
579
|
+
auth_model: z.string().nullable().optional(),
|
|
580
|
+
created_at: z.string().optional(),
|
|
581
|
+
customer: z.looseObject({}).optional(),
|
|
582
|
+
meta: z.unknown().optional()
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
// src/flutterwave/v3/resources/charges.ts
|
|
586
|
+
var chargeRes = flwEnvelope(chargeData);
|
|
587
|
+
var Charges = class {
|
|
588
|
+
/**
|
|
589
|
+
* @param http - Shared HTTP client.
|
|
590
|
+
* @param encryptionKey - The account Encryption Key (from resolved config).
|
|
591
|
+
* May be `undefined` if not configured; `card()` then requires a per-call
|
|
592
|
+
* `encryptionKey` override or throws {@link PayweaveConfigError}.
|
|
593
|
+
*/
|
|
594
|
+
constructor(http, encryptionKey) {
|
|
595
|
+
this.http = http;
|
|
596
|
+
this.encryptionKey = encryptionKey;
|
|
597
|
+
}
|
|
598
|
+
http;
|
|
599
|
+
encryptionKey;
|
|
600
|
+
/**
|
|
601
|
+
* Charge a card. The payload is 3DES-EDE3-ECB encrypted with the account
|
|
602
|
+
* Encryption Key and sent as `{ client }` (provider-reference §5.3). `amount`
|
|
603
|
+
* is MAJOR units, passed through unchanged. A successful charge that needs
|
|
604
|
+
* OTP/PIN returns a `flw_ref` — pass it to {@link validate}.
|
|
605
|
+
*
|
|
606
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/initiate-a-card-charge
|
|
607
|
+
*
|
|
608
|
+
* @example
|
|
609
|
+
* const res = await fw.flutterwave.charges.card({
|
|
610
|
+
* card_number: "5531886652142950", cvv: "564",
|
|
611
|
+
* expiry_month: "09", expiry_year: "32", currency: "NGN",
|
|
612
|
+
* amount: 1000, email: "buyer@example.com", tx_ref: "pwv_tx_001",
|
|
613
|
+
* });
|
|
614
|
+
*/
|
|
615
|
+
async card(input, opts = {}) {
|
|
616
|
+
const payload = parseRequest(cardChargeReq, input);
|
|
617
|
+
const key = opts.encryptionKey ?? this.encryptionKey;
|
|
618
|
+
if (!key) {
|
|
619
|
+
throw new PayweaveConfigError(
|
|
620
|
+
"Flutterwave card charge requires an Encryption Key. Set `encryptionKey` in the SDK config or pass it as the second argument.",
|
|
621
|
+
{ provider: "flutterwave" }
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
const client = encryptCharge(key, payload);
|
|
625
|
+
return this.http.request({
|
|
626
|
+
method: "POST",
|
|
627
|
+
path: "/charges",
|
|
628
|
+
query: { type: "card" },
|
|
629
|
+
body: { client },
|
|
630
|
+
schema: chargeRes
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Initiate a bank-transfer (pay-with-transfer) charge. `amount` is MAJOR units.
|
|
635
|
+
*
|
|
636
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/initiate-a-bank-transfer-charge
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* const res = await fw.flutterwave.charges.bankTransfer({
|
|
640
|
+
* tx_ref: "pwv_tx_002", amount: 5000, email: "buyer@example.com", currency: "NGN",
|
|
641
|
+
* });
|
|
642
|
+
*/
|
|
643
|
+
async bankTransfer(input) {
|
|
644
|
+
const body = parseRequest(bankTransferChargeReq, input);
|
|
645
|
+
return this.http.request({
|
|
646
|
+
method: "POST",
|
|
647
|
+
path: "/charges",
|
|
648
|
+
query: { type: "bank_transfer" },
|
|
649
|
+
body,
|
|
650
|
+
schema: chargeRes
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Initiate a USSD charge. `amount` is MAJOR units.
|
|
655
|
+
*
|
|
656
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/initiate-a-ussd-charge
|
|
657
|
+
*
|
|
658
|
+
* @example
|
|
659
|
+
* const res = await fw.flutterwave.charges.ussd({
|
|
660
|
+
* tx_ref: "pwv_tx_003", account_bank: "057", amount: 1000,
|
|
661
|
+
* email: "buyer@example.com", currency: "NGN",
|
|
662
|
+
* });
|
|
663
|
+
*/
|
|
664
|
+
async ussd(input) {
|
|
665
|
+
const body = parseRequest(ussdChargeReq, input);
|
|
666
|
+
return this.http.request({
|
|
667
|
+
method: "POST",
|
|
668
|
+
path: "/charges",
|
|
669
|
+
query: { type: "ussd" },
|
|
670
|
+
body,
|
|
671
|
+
schema: chargeRes
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Initiate a Nigeria bank-account debit charge. `amount` is MAJOR units.
|
|
676
|
+
*
|
|
677
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/initiate-a-nigeria-bank-account-charge
|
|
678
|
+
*
|
|
679
|
+
* @example
|
|
680
|
+
* const res = await fw.flutterwave.charges.ngAccount({
|
|
681
|
+
* tx_ref: "pwv_tx_004", account_bank: "044", account_number: "0690000031",
|
|
682
|
+
* amount: 1000, email: "buyer@example.com", currency: "NGN",
|
|
683
|
+
* });
|
|
684
|
+
*/
|
|
685
|
+
async ngAccount(input) {
|
|
686
|
+
const body = parseRequest(ngAccountChargeReq, input);
|
|
687
|
+
return this.http.request({
|
|
688
|
+
method: "POST",
|
|
689
|
+
path: "/charges",
|
|
690
|
+
query: { type: "debit_ng_account" },
|
|
691
|
+
body,
|
|
692
|
+
schema: chargeRes
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Validate a charge with the OTP/PIN the customer received.
|
|
697
|
+
*
|
|
698
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/validate-a-charge
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* const res = await fw.flutterwave.charges.validate({
|
|
702
|
+
* otp: "12345", flw_ref: "FLW-MOCK-abc", type: "card",
|
|
703
|
+
* });
|
|
704
|
+
*/
|
|
705
|
+
async validate(input) {
|
|
706
|
+
const body = parseRequest(validateChargeReq, input);
|
|
707
|
+
return this.http.request({
|
|
708
|
+
method: "POST",
|
|
709
|
+
path: "/validate-charge",
|
|
710
|
+
body,
|
|
711
|
+
schema: chargeRes
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
var createTransferReq = z.object({
|
|
716
|
+
/** Recipient bank code. */
|
|
717
|
+
account_bank: z.string(),
|
|
718
|
+
account_number: z.string(),
|
|
719
|
+
/** Amount in MAJOR units. Passed through unchanged. */
|
|
720
|
+
amount: z.union([z.number(), z.string()]),
|
|
721
|
+
currency: z.string().optional(),
|
|
722
|
+
narration: z.string().optional(),
|
|
723
|
+
/** Your unique transfer reference. */
|
|
724
|
+
reference: z.string().optional(),
|
|
725
|
+
callback_url: z.string().optional(),
|
|
726
|
+
/** Currency to debit the balance in (for cross-currency transfers). */
|
|
727
|
+
debit_currency: z.string().optional(),
|
|
728
|
+
beneficiary_name: z.string().optional(),
|
|
729
|
+
/** Saved beneficiary id to transfer to instead of raw account details. */
|
|
730
|
+
beneficiary: z.number().optional(),
|
|
731
|
+
meta: metaSchema.optional()
|
|
732
|
+
});
|
|
733
|
+
var listTransfersQuery = z.object({
|
|
734
|
+
page: z.number().int().positive().optional(),
|
|
735
|
+
status: z.string().optional()
|
|
736
|
+
});
|
|
737
|
+
var transferFeeQuery = z.object({
|
|
738
|
+
amount: z.union([z.number(), z.string()]),
|
|
739
|
+
currency: z.string().optional(),
|
|
740
|
+
/** Fee category, e.g. "account" | "mobilemoney". */
|
|
741
|
+
type: z.string().optional()
|
|
742
|
+
});
|
|
743
|
+
var transfer = z.looseObject({
|
|
744
|
+
id: z.number().optional(),
|
|
745
|
+
account_number: z.string().optional(),
|
|
746
|
+
bank_code: z.string().optional(),
|
|
747
|
+
full_name: z.string().optional(),
|
|
748
|
+
created_at: z.string().optional(),
|
|
749
|
+
currency: z.string().optional(),
|
|
750
|
+
amount: z.number().optional(),
|
|
751
|
+
fee: z.number().optional(),
|
|
752
|
+
status: z.string().optional(),
|
|
753
|
+
reference: z.string().nullable().optional(),
|
|
754
|
+
narration: z.string().nullable().optional(),
|
|
755
|
+
complete_message: z.string().nullable().optional(),
|
|
756
|
+
bank_name: z.string().optional()
|
|
757
|
+
});
|
|
758
|
+
var transferFee = z.looseObject({
|
|
759
|
+
currency: z.string().optional(),
|
|
760
|
+
fee_type: z.string().optional(),
|
|
761
|
+
fee: z.number().optional()
|
|
762
|
+
});
|
|
763
|
+
var createBeneficiaryReq = z.object({
|
|
764
|
+
account_bank: z.string(),
|
|
765
|
+
account_number: z.string(),
|
|
766
|
+
beneficiary_name: z.string().optional(),
|
|
767
|
+
currency: z.string().optional(),
|
|
768
|
+
bank_name: z.string().optional()
|
|
769
|
+
});
|
|
770
|
+
var listBeneficiariesQuery = z.object({
|
|
771
|
+
page: z.number().int().positive().optional()
|
|
772
|
+
});
|
|
773
|
+
var beneficiary = z.looseObject({
|
|
774
|
+
id: z.number().optional(),
|
|
775
|
+
account_number: z.string().optional(),
|
|
776
|
+
account_name: z.string().optional(),
|
|
777
|
+
bank_name: z.string().optional(),
|
|
778
|
+
bank_code: z.string().optional(),
|
|
779
|
+
full_name: z.string().optional(),
|
|
780
|
+
created_at: z.string().optional()
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
// src/flutterwave/v3/resources/transfers.ts
|
|
784
|
+
var transferRes = flwEnvelope(transfer);
|
|
785
|
+
var transferListRes = flwListEnvelope(transfer);
|
|
786
|
+
var transferFeeRes = flwEnvelope(transferFee.array());
|
|
787
|
+
var Transfers = class {
|
|
788
|
+
constructor(http) {
|
|
789
|
+
this.http = http;
|
|
790
|
+
}
|
|
791
|
+
http;
|
|
792
|
+
/**
|
|
793
|
+
* Initiate a transfer (payout) to a bank account. `amount` is MAJOR units,
|
|
794
|
+
* passed through unchanged.
|
|
795
|
+
*
|
|
796
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/create-a-transfer
|
|
797
|
+
*
|
|
798
|
+
* @example
|
|
799
|
+
* const res = await fw.flutterwave.transfers.create({
|
|
800
|
+
* account_bank: "044", account_number: "0690000040",
|
|
801
|
+
* amount: 5000, currency: "NGN", narration: "Payout",
|
|
802
|
+
* });
|
|
803
|
+
*/
|
|
804
|
+
async create(input) {
|
|
805
|
+
const body = parseRequest(createTransferReq, input);
|
|
806
|
+
return this.http.request({
|
|
807
|
+
method: "POST",
|
|
808
|
+
path: "/transfers",
|
|
809
|
+
body,
|
|
810
|
+
schema: transferRes
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* List transfers on the account.
|
|
815
|
+
*
|
|
816
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/list-all-transfers
|
|
817
|
+
*
|
|
818
|
+
* @example
|
|
819
|
+
* const page = await fw.flutterwave.transfers.list({ status: "SUCCESSFUL" });
|
|
820
|
+
*/
|
|
821
|
+
async list(query = {}) {
|
|
822
|
+
const q = parseRequest(listTransfersQuery, query);
|
|
823
|
+
return this.http.request({
|
|
824
|
+
method: "GET",
|
|
825
|
+
path: "/transfers",
|
|
826
|
+
query: q,
|
|
827
|
+
schema: transferListRes
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Async iterator over ALL transfers matching `query`, walking every page via
|
|
832
|
+
* `meta.page_info.total_pages`.
|
|
833
|
+
*
|
|
834
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/list-all-transfers
|
|
835
|
+
*
|
|
836
|
+
* @example
|
|
837
|
+
* for await (const t of fw.flutterwave.transfers.iterate()) console.log(t.id);
|
|
838
|
+
*/
|
|
839
|
+
async *iterate(query = {}) {
|
|
840
|
+
const base = parseRequest(listTransfersQuery, query);
|
|
841
|
+
let page = base.page ?? 1;
|
|
842
|
+
for (; ; ) {
|
|
843
|
+
const res = await this.http.request({
|
|
844
|
+
method: "GET",
|
|
845
|
+
path: "/transfers",
|
|
846
|
+
query: { ...base, page },
|
|
847
|
+
schema: transferListRes
|
|
848
|
+
});
|
|
849
|
+
for (const t of res.data) yield t;
|
|
850
|
+
const totalPages = metaNumber(res.meta?.page_info?.total_pages);
|
|
851
|
+
if (totalPages !== void 0) {
|
|
852
|
+
if (page >= totalPages) return;
|
|
853
|
+
} else if (res.data.length === 0) {
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
page += 1;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Fetch a single transfer by its id.
|
|
861
|
+
*
|
|
862
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-a-transfer
|
|
863
|
+
*
|
|
864
|
+
* @example
|
|
865
|
+
* const res = await fw.flutterwave.transfers.fetch(27494);
|
|
866
|
+
*/
|
|
867
|
+
async fetch(id) {
|
|
868
|
+
return this.http.request({
|
|
869
|
+
method: "GET",
|
|
870
|
+
path: `/transfers/${encodeURIComponent(String(id))}`,
|
|
871
|
+
schema: transferRes
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Get the fee Flutterwave charges for a transfer of `amount` MAJOR units.
|
|
876
|
+
*
|
|
877
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/get-transfer-fee
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* const res = await fw.flutterwave.transfers.fees({ amount: 5000, currency: "NGN" });
|
|
881
|
+
*/
|
|
882
|
+
async fees(query) {
|
|
883
|
+
const q = parseRequest(transferFeeQuery, query);
|
|
884
|
+
return this.http.request({
|
|
885
|
+
method: "GET",
|
|
886
|
+
path: "/transfers/fee",
|
|
887
|
+
query: q,
|
|
888
|
+
schema: transferFeeRes
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
// src/flutterwave/v3/resources/beneficiaries.ts
|
|
894
|
+
var beneficiaryRes = flwEnvelope(beneficiary);
|
|
895
|
+
var beneficiaryListRes = flwListEnvelope(beneficiary);
|
|
896
|
+
var Beneficiaries = class {
|
|
897
|
+
constructor(http) {
|
|
898
|
+
this.http = http;
|
|
899
|
+
}
|
|
900
|
+
http;
|
|
901
|
+
/**
|
|
902
|
+
* Save a transfer beneficiary.
|
|
903
|
+
*
|
|
904
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/create-a-transfer-beneficiary
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* const res = await fw.flutterwave.beneficiaries.create({
|
|
908
|
+
* account_bank: "044", account_number: "0690000040", beneficiary_name: "Jane Doe",
|
|
909
|
+
* });
|
|
910
|
+
*/
|
|
911
|
+
async create(input) {
|
|
912
|
+
const body = parseRequest(createBeneficiaryReq, input);
|
|
913
|
+
return this.http.request({
|
|
914
|
+
method: "POST",
|
|
915
|
+
path: "/beneficiaries",
|
|
916
|
+
body,
|
|
917
|
+
schema: beneficiaryRes
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* List saved beneficiaries.
|
|
922
|
+
*
|
|
923
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/list-all-transfer-beneficiaries
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* const page = await fw.flutterwave.beneficiaries.list();
|
|
927
|
+
*/
|
|
928
|
+
async list(query = {}) {
|
|
929
|
+
const q = parseRequest(listBeneficiariesQuery, query);
|
|
930
|
+
return this.http.request({
|
|
931
|
+
method: "GET",
|
|
932
|
+
path: "/beneficiaries",
|
|
933
|
+
query: q,
|
|
934
|
+
schema: beneficiaryListRes
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Async iterator over ALL beneficiaries, walking every page via
|
|
939
|
+
* `meta.page_info.total_pages`.
|
|
940
|
+
*
|
|
941
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/list-all-transfer-beneficiaries
|
|
942
|
+
*
|
|
943
|
+
* @example
|
|
944
|
+
* for await (const b of fw.flutterwave.beneficiaries.iterate()) console.log(b.id);
|
|
945
|
+
*/
|
|
946
|
+
async *iterate(query = {}) {
|
|
947
|
+
const base = parseRequest(listBeneficiariesQuery, query);
|
|
948
|
+
let page = base.page ?? 1;
|
|
949
|
+
for (; ; ) {
|
|
950
|
+
const res = await this.http.request({
|
|
951
|
+
method: "GET",
|
|
952
|
+
path: "/beneficiaries",
|
|
953
|
+
query: { ...base, page },
|
|
954
|
+
schema: beneficiaryListRes
|
|
955
|
+
});
|
|
956
|
+
for (const b of res.data) yield b;
|
|
957
|
+
const totalPages = metaNumber(res.meta?.page_info?.total_pages);
|
|
958
|
+
if (totalPages !== void 0) {
|
|
959
|
+
if (page >= totalPages) return;
|
|
960
|
+
} else if (res.data.length === 0) {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
page += 1;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Fetch a single beneficiary by its id.
|
|
968
|
+
*
|
|
969
|
+
* Docs: https://developer.flutterwave.com/v3.0.0/reference/fetch-a-transfer-beneficiary
|
|
970
|
+
*
|
|
971
|
+
* @example
|
|
972
|
+
* const res = await fw.flutterwave.beneficiaries.fetch(5307);
|
|
973
|
+
*/
|
|
974
|
+
async fetch(id) {
|
|
975
|
+
return this.http.request({
|
|
976
|
+
method: "GET",
|
|
977
|
+
path: `/beneficiaries/${encodeURIComponent(String(id))}`,
|
|
978
|
+
schema: beneficiaryRes
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
};
|
|
982
|
+
|
|
983
|
+
// src/flutterwave/client.ts
|
|
984
|
+
var FlutterwaveClient = class {
|
|
985
|
+
/**
|
|
986
|
+
* Shared HTTP client. Resource classes receive THIS instance:
|
|
987
|
+
* `new Payments(this.http)`.
|
|
988
|
+
*/
|
|
989
|
+
http;
|
|
990
|
+
/** Configured API generation — decides which resource surface is mounted. */
|
|
991
|
+
version;
|
|
992
|
+
// ── v3 resources (mounted when version === "v3") ─────────────────────────────
|
|
993
|
+
/** Standard Payments: hosted checkout link (`data.link`). */
|
|
994
|
+
payments;
|
|
995
|
+
/** Transactions: verify by id / by tx_ref, list/iterate, fees. */
|
|
996
|
+
transactions;
|
|
997
|
+
/** Banks + account resolution: list banks by country, branches, resolve. */
|
|
998
|
+
banks;
|
|
999
|
+
/** Refunds: create, list/iterate, fetch. */
|
|
1000
|
+
refunds;
|
|
1001
|
+
/** Direct charges: card (3DES), bank transfer, USSD, NG account, validate. */
|
|
1002
|
+
charges;
|
|
1003
|
+
/** Transfers: create, list/iterate, fetch, fees. */
|
|
1004
|
+
transfers;
|
|
1005
|
+
/** Transfer beneficiaries: create, list/iterate, fetch. */
|
|
1006
|
+
beneficiaries;
|
|
1007
|
+
/**
|
|
1008
|
+
* @param http - Shared HTTP client every resource is built on.
|
|
1009
|
+
* @param version - `"v3"` mounts the v3 surface; `"v4"` is a later wave.
|
|
1010
|
+
* @param encryptionKey - The v3 dashboard Encryption Key (from resolved
|
|
1011
|
+
* config), consumed by `charges.card`. Optional so the facade can construct
|
|
1012
|
+
* the client without it; card charges then require a per-call override.
|
|
1013
|
+
*/
|
|
1014
|
+
constructor(http, version, encryptionKey) {
|
|
1015
|
+
this.http = http;
|
|
1016
|
+
this.version = version;
|
|
1017
|
+
if (version === "v3") {
|
|
1018
|
+
this.payments = new Payments(this.http);
|
|
1019
|
+
this.transactions = new Transactions(this.http);
|
|
1020
|
+
this.banks = new Banks(this.http);
|
|
1021
|
+
this.refunds = new Refunds(this.http);
|
|
1022
|
+
this.charges = new Charges(this.http, encryptionKey);
|
|
1023
|
+
this.transfers = new Transfers(this.http);
|
|
1024
|
+
this.beneficiaries = new Beneficiaries(this.http);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
function flutterwaveHttp(cfg) {
|
|
1029
|
+
if (cfg.version === "v4") {
|
|
1030
|
+
if (!cfg.clientId || !cfg.clientSecret || !cfg.tokenUrl) {
|
|
1031
|
+
throw new PayweaveConfigError(
|
|
1032
|
+
"Flutterwave v4 requires clientId, clientSecret, and a token URL.",
|
|
1033
|
+
{ provider: "flutterwave" }
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
return new HttpClient({
|
|
1037
|
+
baseUrl: cfg.baseUrl,
|
|
1038
|
+
auth: oauthClientCredentials({
|
|
1039
|
+
clientId: cfg.clientId,
|
|
1040
|
+
clientSecret: cfg.clientSecret,
|
|
1041
|
+
tokenUrl: cfg.tokenUrl,
|
|
1042
|
+
...cfg.fetch ? { fetch: cfg.fetch } : {},
|
|
1043
|
+
...cfg.logger ? { logger: cfg.logger } : {}
|
|
1044
|
+
}),
|
|
1045
|
+
provider: "flutterwave",
|
|
1046
|
+
version: "v4",
|
|
1047
|
+
timeoutMs: cfg.timeoutMs,
|
|
1048
|
+
maxRetries: cfg.maxRetries,
|
|
1049
|
+
fetch: cfg.fetch,
|
|
1050
|
+
logger: cfg.logger
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
if (!cfg.secretKey) {
|
|
1054
|
+
throw new PayweaveConfigError("Missing secret key for flutterwave.", { provider: "flutterwave" });
|
|
1055
|
+
}
|
|
1056
|
+
return new HttpClient({
|
|
1057
|
+
baseUrl: cfg.baseUrl,
|
|
1058
|
+
auth: bearer(cfg.secretKey),
|
|
1059
|
+
provider: "flutterwave",
|
|
1060
|
+
version: "v3",
|
|
1061
|
+
timeoutMs: cfg.timeoutMs,
|
|
1062
|
+
maxRetries: cfg.maxRetries,
|
|
1063
|
+
fetch: cfg.fetch,
|
|
1064
|
+
logger: cfg.logger
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
function flutterwaveWebhooks(version) {
|
|
1068
|
+
if (version === "v4") {
|
|
1069
|
+
return {
|
|
1070
|
+
signatureHeader: "flutterwave-signature",
|
|
1071
|
+
verify: ({ rawBody, headers, secret }) => verifyFlutterwaveV4(rawBody, readHeader(headers, "flutterwave-signature"), secret),
|
|
1072
|
+
parse: (rawBody) => {
|
|
1073
|
+
const root = JSON.parse(rawBody);
|
|
1074
|
+
return {
|
|
1075
|
+
type: typeof root.type === "string" ? root.type : "unknown",
|
|
1076
|
+
data: root.data,
|
|
1077
|
+
raw: root,
|
|
1078
|
+
...typeof root.id === "string" ? { id: root.id } : {}
|
|
1079
|
+
};
|
|
1080
|
+
},
|
|
1081
|
+
toUnified: (e) => ({
|
|
1082
|
+
provider: "flutterwave",
|
|
1083
|
+
type: e.type,
|
|
1084
|
+
unifiedType: toUnifiedEventType("flutterwave", "v4", e.type, e.data),
|
|
1085
|
+
data: e.data,
|
|
1086
|
+
raw: e.raw
|
|
1087
|
+
})
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
return {
|
|
1091
|
+
signatureHeader: "verif-hash",
|
|
1092
|
+
verify: ({ headers, secret }) => verifyFlutterwaveV3(readHeader(headers, "verif-hash"), secret),
|
|
1093
|
+
parse: (rawBody) => {
|
|
1094
|
+
const root = JSON.parse(rawBody);
|
|
1095
|
+
return {
|
|
1096
|
+
type: typeof root.event === "string" ? root.event : "unknown",
|
|
1097
|
+
data: root.data,
|
|
1098
|
+
raw: root
|
|
1099
|
+
};
|
|
1100
|
+
},
|
|
1101
|
+
toUnified: (e) => ({
|
|
1102
|
+
provider: "flutterwave",
|
|
1103
|
+
type: e.type,
|
|
1104
|
+
unifiedType: toUnifiedEventType("flutterwave", "v3", e.type, e.data),
|
|
1105
|
+
data: e.data,
|
|
1106
|
+
raw: e.raw
|
|
1107
|
+
})
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function createFlutterwaveAdapter(version = "v3") {
|
|
1111
|
+
return defineProvider({
|
|
1112
|
+
id: "flutterwave",
|
|
1113
|
+
configKey: "flutterwave",
|
|
1114
|
+
configSchema: flutterwaveProviderConfigSchema,
|
|
1115
|
+
environments: version === "v4" ? { test: { baseUrl: FLW_V4_SANDBOX_URL }, live: { baseUrl: FLW_V4_BASE_URL } } : (
|
|
1116
|
+
// v3: one host for both — environment is key-derived, not host-derived.
|
|
1117
|
+
{ test: { baseUrl: FLW_V3_BASE_URL }, live: { baseUrl: FLW_V3_BASE_URL } }
|
|
1118
|
+
),
|
|
1119
|
+
inferEnvironment: (secretKey) => {
|
|
1120
|
+
if (version === "v4") return null;
|
|
1121
|
+
try {
|
|
1122
|
+
return inferEnvironment("flutterwave", secretKey);
|
|
1123
|
+
} catch {
|
|
1124
|
+
return null;
|
|
1125
|
+
}
|
|
1126
|
+
},
|
|
1127
|
+
createHttp: flutterwaveHttp,
|
|
1128
|
+
webhooks: flutterwaveWebhooks(version)
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
createFlutterwaveAdapter("v3");
|
|
1132
|
+
|
|
1133
|
+
export { Banks, Beneficiaries, Charges, FlutterwaveClient, Payments, Refunds, Transactions, Transfers, decryptCharge, encryptCharge };
|
|
1134
|
+
//# sourceMappingURL=chunk-FBPOCXRZ.js.map
|
|
1135
|
+
//# sourceMappingURL=chunk-FBPOCXRZ.js.map
|