nomkit 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.txt +21 -0
- package/dist/_virtual/_rolldown/runtime.js +27 -0
- package/dist/adapters/index.d.ts +15 -0
- package/dist/adapters/index.js +6 -0
- package/dist/cli/commands/push.d.ts +6 -0
- package/dist/cli/commands/push.js +143 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/lib/collection_sync.d.ts +107 -0
- package/dist/cli/lib/collection_sync.js +158 -0
- package/dist/cli/lib/config_loader.d.ts +15 -0
- package/dist/cli/lib/config_loader.js +43 -0
- package/dist/cli/lib/hash.d.ts +22 -0
- package/dist/cli/lib/hash.js +63 -0
- package/dist/cli/lib/migrations.d.ts +6 -0
- package/dist/cli/lib/migrations.js +17 -0
- package/dist/client/index.d.ts +13 -0
- package/dist/client/index.js +34 -0
- package/dist/core/nomba_api/banks.d.ts +14 -0
- package/dist/core/nomba_api/banks.js +0 -0
- package/dist/core/nomba_api/charge-tokenized-card.d.ts +33 -0
- package/dist/core/nomba_api/charge-tokenized-card.js +0 -0
- package/dist/core/nomba_api/checkout.d.ts +44 -0
- package/dist/core/nomba_api/checkout.js +0 -0
- package/dist/core/nomba_api/get_checkout.d.ts +57 -0
- package/dist/core/nomba_api/get_checkout.js +0 -0
- package/dist/core/nomba_api/index.d.ts +313 -0
- package/dist/core/nomba_api/index.js +179 -0
- package/dist/core/nomba_api/lib/utils.d.ts +235 -0
- package/dist/core/nomba_api/lib/utils.js +313 -0
- package/dist/core/nomba_api/list-tokenized-cards.d.ts +24 -0
- package/dist/core/nomba_api/list-tokenized-cards.js +0 -0
- package/dist/core/nomba_api/token-manager/index.d.ts +51 -0
- package/dist/core/nomba_api/token-manager/index.js +109 -0
- package/dist/core/pg_db/index.d.ts +108 -0
- package/dist/core/pg_db/index.js +76 -0
- package/dist/core/pg_db/migrations/20260703085901_wealthy_blacklash/migration.sql +120 -0
- package/dist/core/pg_db/migrations/20260703085901_wealthy_blacklash/snapshot.json +1616 -0
- package/dist/core/pg_db/relations.d.ts +46 -0
- package/dist/core/pg_db/relations.js +83 -0
- package/dist/core/pg_db/schema.d.ts +1138 -0
- package/dist/core/pg_db/schema.js +124 -0
- package/dist/endpoints/customers/api.js +51 -0
- package/dist/endpoints/entitlements/api.js +42 -0
- package/dist/endpoints/routes.d.ts +15 -0
- package/dist/endpoints/routes.js +15 -0
- package/dist/endpoints/subscriptions/api.js +263 -0
- package/dist/endpoints/subscriptions/utils.js +105 -0
- package/dist/endpoints/webhooks/invoice/api.js +28 -0
- package/dist/endpoints/webhooks/nomba/api.js +76 -0
- package/dist/endpoints/webhooks/nomba/utils.js +36 -0
- package/dist/index.d.ts +204 -0
- package/dist/index.js +175 -0
- package/dist/lib/utils.d.ts +21 -0
- package/dist/lib/utils.js +41 -0
- package/dist/node_modules/.pnpm/@better-fetch_fetch@1.3.1/node_modules/@better-fetch/fetch/dist/index.js +475 -0
- package/dist/package.js +4 -0
- package/dist/queue/backends/pglite/backend.d.ts +43 -0
- package/dist/queue/backends/pglite/backend.js +33 -0
- package/dist/queue/backends/pglite/index.d.ts +4 -0
- package/dist/queue/backends/pglite/index.js +4 -0
- package/dist/queue/backends/pglite/migrations/schema.d.ts +4 -0
- package/dist/queue/backends/pglite/migrations/schema.js +37 -0
- package/dist/queue/backends/pglite/notification-channel.d.ts +17 -0
- package/dist/queue/backends/pglite/notification-channel.js +61 -0
- package/dist/queue/backends/pglite/repository.d.ts +38 -0
- package/dist/queue/backends/pglite/repository.js +299 -0
- package/dist/queue/backends/redis/index.d.ts +7 -0
- package/dist/queue/backends/redis/index.js +1 -0
- package/dist/queue/client/index.d.ts +12 -0
- package/dist/queue/client/index.js +31 -0
- package/dist/queue/endpoints/api.d.ts +53 -0
- package/dist/queue/endpoints/api.js +45 -0
- package/dist/queue/endpoints/routes.d.ts +32 -0
- package/dist/queue/endpoints/routes.js +5 -0
- package/dist/queue/init.d.ts +27 -0
- package/dist/queue/init.js +31 -0
- package/dist/queue/lib/billing.d.ts +25 -0
- package/dist/queue/lib/billing.js +87 -0
- package/dist/queue/lib/utils.d.ts +30 -0
- package/dist/queue/lib/utils.js +35 -0
- package/package.json +71 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region client/index.d.ts
|
|
2
|
+
interface NomKitClientOptions {
|
|
3
|
+
baseURL?: string;
|
|
4
|
+
}
|
|
5
|
+
declare function createNomKitClient<TServer extends Record<string, any>>(options?: NomKitClientOptions): InferClientAPI<ExtractAPI<TServer>>;
|
|
6
|
+
type AnyFn = (...args: any[]) => any;
|
|
7
|
+
type AwaitedReturn<T extends AnyFn> = Awaited<ReturnType<T>>;
|
|
8
|
+
type ExtractAPI<T> = T extends {
|
|
9
|
+
api: infer TApi;
|
|
10
|
+
} ? TApi : never;
|
|
11
|
+
type InferClientAPI<T> = { [K in keyof T]: T[K] extends AnyFn ? (...args: Parameters<T[K]>) => Promise<AwaitedReturn<T[K]>> : T[K] extends object ? InferClientAPI<T[K]> : never };
|
|
12
|
+
//#endregion
|
|
13
|
+
export { NomKitClientOptions, createNomKitClient };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createFetch } from "../node_modules/.pnpm/@better-fetch_fetch@1.3.1/node_modules/@better-fetch/fetch/dist/index.js";
|
|
2
|
+
//#region client/index.ts
|
|
3
|
+
function createNomKitClient(options) {
|
|
4
|
+
const baseUrl = (options?.baseURL ?? "/nomkit").replace(/\/+$/, "");
|
|
5
|
+
let apiUrl;
|
|
6
|
+
if (baseUrl === "") apiUrl = "/nomkit";
|
|
7
|
+
else if (baseUrl.endsWith("/nomkit")) apiUrl = baseUrl;
|
|
8
|
+
else apiUrl = `${baseUrl}/nomkit`;
|
|
9
|
+
const supportsCredentials = typeof globalThis.Request !== "undefined" && "credentials" in Request.prototype;
|
|
10
|
+
const $fetch = createFetch({
|
|
11
|
+
baseURL: apiUrl,
|
|
12
|
+
throw: true,
|
|
13
|
+
...supportsCredentials ? { credentials: "include" } : {}
|
|
14
|
+
});
|
|
15
|
+
const createProxy = (path = []) => new Proxy(() => {}, {
|
|
16
|
+
get(_, prop) {
|
|
17
|
+
if (typeof prop !== "string") return;
|
|
18
|
+
if (prop === "then" || prop === "catch" || prop === "finally") return;
|
|
19
|
+
return createProxy([...path, prop]);
|
|
20
|
+
},
|
|
21
|
+
async apply(_, __, args) {
|
|
22
|
+
const routePath = "/" + path.map((segment) => segment.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)).join("/");
|
|
23
|
+
const body = args[0] ?? {};
|
|
24
|
+
console.log("Nomkit client: ", routePath);
|
|
25
|
+
return $fetch(routePath, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
body
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return createProxy();
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { createNomKitClient };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region core/nomba_api/banks.d.ts
|
|
2
|
+
interface GetBanksResponse {
|
|
3
|
+
code: string;
|
|
4
|
+
description: string;
|
|
5
|
+
data: {
|
|
6
|
+
results: Result[];
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
type Result = {
|
|
10
|
+
code: string;
|
|
11
|
+
name: string;
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { GetBanksResponse, Result };
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region core/nomba_api/charge-tokenized-card.d.ts
|
|
2
|
+
interface TokenizedCardChargeRequest {
|
|
3
|
+
tokenKey: string;
|
|
4
|
+
order?: TokenizedCardOrder;
|
|
5
|
+
}
|
|
6
|
+
interface TokenizedCardOrder {
|
|
7
|
+
orderReference?: string;
|
|
8
|
+
customerId?: string;
|
|
9
|
+
callbackUrl?: string;
|
|
10
|
+
customerEmail?: string;
|
|
11
|
+
amount?: string;
|
|
12
|
+
currency?: string;
|
|
13
|
+
accountId?: string;
|
|
14
|
+
splitRequest?: SplitRequest;
|
|
15
|
+
}
|
|
16
|
+
interface SplitRequest {
|
|
17
|
+
splitType: "PERCENTAGE" | "AMOUNT";
|
|
18
|
+
splitList: SplitRecipient[];
|
|
19
|
+
}
|
|
20
|
+
interface SplitRecipient {
|
|
21
|
+
accountId: string;
|
|
22
|
+
value: string;
|
|
23
|
+
}
|
|
24
|
+
interface TokenizedCardChargeResponse {
|
|
25
|
+
"code": "00";
|
|
26
|
+
"description": string;
|
|
27
|
+
"data": {
|
|
28
|
+
"status": string;
|
|
29
|
+
"message": string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { SplitRecipient, SplitRequest, TokenizedCardChargeRequest, TokenizedCardChargeResponse, TokenizedCardOrder };
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region core/nomba_api/checkout.d.ts
|
|
2
|
+
interface CreateCheckoutRequest {
|
|
3
|
+
order: Checkout;
|
|
4
|
+
/**
|
|
5
|
+
* Note: we require this for subscriptions to be able to headlessly
|
|
6
|
+
* charge their card without triggering another checkout flow
|
|
7
|
+
* @default true
|
|
8
|
+
*/
|
|
9
|
+
tokenizeCard: boolean;
|
|
10
|
+
}
|
|
11
|
+
type Metadata = "nomkit.order_reference" | "nomkit.subscription.id" | "nomkit.subscription.customer_id" | "nomkit.subscription.customer_email" | "nomkit.subscription.internalPlanId";
|
|
12
|
+
type NonRequiredMetadata = "nomkit.subscription.kind" | "nomkit.subscription.previous_subscription_id" | "nomkit.subscription.previous_internalPlanId" | "nomkit.subscription.prorated_credit_applied";
|
|
13
|
+
type CheckoutMetadata = Record<Metadata, string> & Partial<Record<NonRequiredMetadata, string>>;
|
|
14
|
+
interface Checkout {
|
|
15
|
+
amount: string;
|
|
16
|
+
currency: string;
|
|
17
|
+
orderReference?: string;
|
|
18
|
+
callbackUrl?: string;
|
|
19
|
+
customerEmail?: string;
|
|
20
|
+
customerId?: string;
|
|
21
|
+
accountId?: string;
|
|
22
|
+
allowedPaymentMethods?: PaymentMethod[];
|
|
23
|
+
splitRequest?: SplitRequest;
|
|
24
|
+
orderMetaData?: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
interface SplitRequest {
|
|
27
|
+
splitType: "PERCENTAGE" | "AMOUNT";
|
|
28
|
+
splitList: SplitRecipient[];
|
|
29
|
+
}
|
|
30
|
+
interface SplitRecipient {
|
|
31
|
+
accountId: string;
|
|
32
|
+
value: string;
|
|
33
|
+
}
|
|
34
|
+
type PaymentMethod = "Card" | "Transfer" | "Nomba QR" | "USSD" | "Buy Now Pay Later" | "MOMO" | "Intl Card" | "Apple Pay";
|
|
35
|
+
interface CreateCheckoutResponse {
|
|
36
|
+
code: string;
|
|
37
|
+
description: string;
|
|
38
|
+
data: {
|
|
39
|
+
checkoutLink: string;
|
|
40
|
+
orderReference: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { Checkout, CheckoutMetadata, CreateCheckoutRequest, CreateCheckoutResponse, Metadata, NonRequiredMetadata, PaymentMethod, SplitRecipient, SplitRequest };
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CheckoutMetadata } from "./checkout.js";
|
|
2
|
+
|
|
3
|
+
//#region core/nomba_api/get_checkout.d.ts
|
|
4
|
+
interface FetchCheckoutResponse {
|
|
5
|
+
code: string;
|
|
6
|
+
description: string;
|
|
7
|
+
data: {
|
|
8
|
+
success: boolean;
|
|
9
|
+
message: string;
|
|
10
|
+
order: CheckoutOrder;
|
|
11
|
+
transactionDetails: TransactionDetails;
|
|
12
|
+
transferDetails: TransferDetails;
|
|
13
|
+
/**
|
|
14
|
+
* Will be null if the user paid by Bank Transfer
|
|
15
|
+
*/
|
|
16
|
+
cardDetails: CardDetails | null;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
interface CheckoutOrder {
|
|
20
|
+
orderId: string;
|
|
21
|
+
orderReference: string;
|
|
22
|
+
customerId: string;
|
|
23
|
+
accountId: string;
|
|
24
|
+
callbackUrl: string;
|
|
25
|
+
customerEmail: string;
|
|
26
|
+
amount: string;
|
|
27
|
+
currency: string;
|
|
28
|
+
orderMetaData: CheckoutMetadata;
|
|
29
|
+
}
|
|
30
|
+
interface TransactionDetails {
|
|
31
|
+
transactionDate: string;
|
|
32
|
+
paymentReference: string;
|
|
33
|
+
paymentVendorReference: string;
|
|
34
|
+
/**
|
|
35
|
+
* Will be false if the user paid by transfer
|
|
36
|
+
*/
|
|
37
|
+
tokenizedCardPayment: boolean;
|
|
38
|
+
statusCode: string;
|
|
39
|
+
}
|
|
40
|
+
interface TransferDetails {
|
|
41
|
+
sessionId: string;
|
|
42
|
+
beneficiaryAccountName: string;
|
|
43
|
+
beneficiaryAccountNumber: string;
|
|
44
|
+
originatorAccountName: string;
|
|
45
|
+
originatorAccountNumber: string;
|
|
46
|
+
narration: string;
|
|
47
|
+
destinationInstitutionCode: string;
|
|
48
|
+
paymentReference: string;
|
|
49
|
+
}
|
|
50
|
+
interface CardDetails {
|
|
51
|
+
cardPan: string;
|
|
52
|
+
cardType: string;
|
|
53
|
+
cardCurrency: string;
|
|
54
|
+
cardBank: string;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { CardDetails, CheckoutOrder, FetchCheckoutResponse, TransactionDetails, TransferDetails };
|
|
File without changes
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { CheckoutMetadata } from "./checkout.js";
|
|
2
|
+
import { CardDetails, CheckoutOrder, TransactionDetails, TransferDetails } from "./get_checkout.js";
|
|
3
|
+
import { CardDataList } from "./list-tokenized-cards.js";
|
|
4
|
+
|
|
5
|
+
//#region core/nomba_api/index.d.ts
|
|
6
|
+
type Environment = "production" | "sandbox";
|
|
7
|
+
declare class NombaAPI {
|
|
8
|
+
private environment;
|
|
9
|
+
private accountId;
|
|
10
|
+
private clientId;
|
|
11
|
+
private clientSecret;
|
|
12
|
+
private endpoint;
|
|
13
|
+
private webhookSecret;
|
|
14
|
+
private tokenManager;
|
|
15
|
+
constructor(args: {
|
|
16
|
+
accountId: string;
|
|
17
|
+
clientId: string;
|
|
18
|
+
clientSecret: string;
|
|
19
|
+
webhookSecret: string;
|
|
20
|
+
environment?: Environment;
|
|
21
|
+
});
|
|
22
|
+
init(): Promise<void>;
|
|
23
|
+
checkOut(args: {
|
|
24
|
+
successURL: string;
|
|
25
|
+
customerEmail: string;
|
|
26
|
+
amount: string;
|
|
27
|
+
reference: string;
|
|
28
|
+
metadata: CheckoutMetadata;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
checkoutLink: string;
|
|
31
|
+
orderReference: string;
|
|
32
|
+
}>;
|
|
33
|
+
getCheckOut(args: {
|
|
34
|
+
reference?: string;
|
|
35
|
+
orderId?: string;
|
|
36
|
+
}): Promise<{
|
|
37
|
+
success: boolean;
|
|
38
|
+
message: string;
|
|
39
|
+
order: CheckoutOrder;
|
|
40
|
+
transactionDetails: TransactionDetails;
|
|
41
|
+
transferDetails: TransferDetails;
|
|
42
|
+
cardDetails: CardDetails | null;
|
|
43
|
+
}>;
|
|
44
|
+
chargeCard(args: {
|
|
45
|
+
orderReference: string;
|
|
46
|
+
amount: string;
|
|
47
|
+
tokenKey: string;
|
|
48
|
+
customerEmail: string;
|
|
49
|
+
successURL: string;
|
|
50
|
+
}): Promise<{
|
|
51
|
+
status: string;
|
|
52
|
+
message: string;
|
|
53
|
+
}>;
|
|
54
|
+
listCards(args: {
|
|
55
|
+
customerEmail: string;
|
|
56
|
+
}): Promise<{
|
|
57
|
+
nextPage: number;
|
|
58
|
+
tokenizedCardDataList: CardDataList[];
|
|
59
|
+
}>;
|
|
60
|
+
getBanks(): Promise<readonly [{
|
|
61
|
+
readonly name: "Access Bank";
|
|
62
|
+
readonly code: "044";
|
|
63
|
+
}, {
|
|
64
|
+
readonly name: "Addosser Microfinance Bank";
|
|
65
|
+
readonly code: "090160";
|
|
66
|
+
}, {
|
|
67
|
+
readonly name: "AB Microfinance Bank";
|
|
68
|
+
readonly code: "090270";
|
|
69
|
+
}, {
|
|
70
|
+
readonly name: "Citibank Nigeria Limited";
|
|
71
|
+
readonly code: "023";
|
|
72
|
+
}, {
|
|
73
|
+
readonly name: "Diamond Bank";
|
|
74
|
+
readonly code: "063";
|
|
75
|
+
}, {
|
|
76
|
+
readonly name: "Ecobank Nigeria";
|
|
77
|
+
readonly code: "050";
|
|
78
|
+
}, {
|
|
79
|
+
readonly name: "Enterprise Bank";
|
|
80
|
+
readonly code: "084";
|
|
81
|
+
}, {
|
|
82
|
+
readonly name: "eTranzact";
|
|
83
|
+
readonly code: "306";
|
|
84
|
+
}, {
|
|
85
|
+
readonly name: "Fidelity Bank";
|
|
86
|
+
readonly code: "070";
|
|
87
|
+
}, {
|
|
88
|
+
readonly name: "First Bank of Nigeria";
|
|
89
|
+
readonly code: "011";
|
|
90
|
+
}, {
|
|
91
|
+
readonly name: "First City Monument Bank";
|
|
92
|
+
readonly code: "214";
|
|
93
|
+
}, {
|
|
94
|
+
readonly name: "First Monnie Wallet";
|
|
95
|
+
readonly code: "309";
|
|
96
|
+
}, {
|
|
97
|
+
readonly name: "Globus Bank";
|
|
98
|
+
readonly code: "000027";
|
|
99
|
+
}, {
|
|
100
|
+
readonly name: "Guaranty Trust Bank";
|
|
101
|
+
readonly code: "058";
|
|
102
|
+
}, {
|
|
103
|
+
readonly name: "Heritage Bank";
|
|
104
|
+
readonly code: "030";
|
|
105
|
+
}, {
|
|
106
|
+
readonly name: "Hackman Microfinance Bank";
|
|
107
|
+
readonly code: "090147";
|
|
108
|
+
}, {
|
|
109
|
+
readonly name: "Ibile Microfinance Bank";
|
|
110
|
+
readonly code: "090118";
|
|
111
|
+
}, {
|
|
112
|
+
readonly name: "Jaiz Bank";
|
|
113
|
+
readonly code: "301";
|
|
114
|
+
}, {
|
|
115
|
+
readonly name: "Key Stone Bank";
|
|
116
|
+
readonly code: "082";
|
|
117
|
+
}, {
|
|
118
|
+
readonly name: "Kuda Microfinance Bank";
|
|
119
|
+
readonly code: "090267";
|
|
120
|
+
}, {
|
|
121
|
+
readonly name: "Paycom (Opay)";
|
|
122
|
+
readonly code: "305";
|
|
123
|
+
}, {
|
|
124
|
+
readonly name: "Paga";
|
|
125
|
+
readonly code: "327";
|
|
126
|
+
}, {
|
|
127
|
+
readonly name: "PayAttitude Online";
|
|
128
|
+
readonly code: "329";
|
|
129
|
+
}, {
|
|
130
|
+
readonly name: "Providus Bank";
|
|
131
|
+
readonly code: "101";
|
|
132
|
+
}, {
|
|
133
|
+
readonly name: "RenMoney Microfinance Bank";
|
|
134
|
+
readonly code: "090198";
|
|
135
|
+
}, {
|
|
136
|
+
readonly name: "Royal Exchange Microfinance Bank";
|
|
137
|
+
readonly code: "090138";
|
|
138
|
+
}, {
|
|
139
|
+
readonly name: "Polaris Bank";
|
|
140
|
+
readonly code: "076";
|
|
141
|
+
}, {
|
|
142
|
+
readonly name: "Stanbic IBTC Bank";
|
|
143
|
+
readonly code: "039";
|
|
144
|
+
}, {
|
|
145
|
+
readonly name: "Standard Chartered Bank Nigeria";
|
|
146
|
+
readonly code: "068";
|
|
147
|
+
}, {
|
|
148
|
+
readonly name: "Sterling Bank Plc";
|
|
149
|
+
readonly code: "232";
|
|
150
|
+
}, {
|
|
151
|
+
readonly name: "SunTrust Bank Nigeria Limited";
|
|
152
|
+
readonly code: "100";
|
|
153
|
+
}, {
|
|
154
|
+
readonly name: "Taj Bank";
|
|
155
|
+
readonly code: "000026";
|
|
156
|
+
}, {
|
|
157
|
+
readonly name: "Titan Trust Bank";
|
|
158
|
+
readonly code: "000025";
|
|
159
|
+
}, {
|
|
160
|
+
readonly name: "Union Bank of Nigeria";
|
|
161
|
+
readonly code: "032";
|
|
162
|
+
}, {
|
|
163
|
+
readonly name: "United Bank for Africa";
|
|
164
|
+
readonly code: "033";
|
|
165
|
+
}, {
|
|
166
|
+
readonly name: "Unity Bank";
|
|
167
|
+
readonly code: "215";
|
|
168
|
+
}, {
|
|
169
|
+
readonly name: "Wema Bank";
|
|
170
|
+
readonly code: "035";
|
|
171
|
+
}, {
|
|
172
|
+
readonly name: "Zenith Bank";
|
|
173
|
+
readonly code: "057";
|
|
174
|
+
}, {
|
|
175
|
+
readonly name: "Parallex MF Bank";
|
|
176
|
+
readonly code: "526";
|
|
177
|
+
}, {
|
|
178
|
+
readonly name: "Nirsal MFB";
|
|
179
|
+
readonly code: "090194";
|
|
180
|
+
}, {
|
|
181
|
+
readonly name: "Moniepoint Microfinance Bank";
|
|
182
|
+
readonly code: "090405";
|
|
183
|
+
}, {
|
|
184
|
+
readonly name: "VFD Microfinance Bank Limited";
|
|
185
|
+
readonly code: "566";
|
|
186
|
+
}, {
|
|
187
|
+
readonly name: "Palmpay";
|
|
188
|
+
readonly code: "100033";
|
|
189
|
+
}, {
|
|
190
|
+
readonly name: "Good News Microfinance Bank";
|
|
191
|
+
readonly code: "090495";
|
|
192
|
+
}, {
|
|
193
|
+
readonly name: "Lapo Microfinance Bank";
|
|
194
|
+
readonly code: "090177";
|
|
195
|
+
}, {
|
|
196
|
+
readonly name: "Accion Microfinance Bank";
|
|
197
|
+
readonly code: "090134";
|
|
198
|
+
}, {
|
|
199
|
+
readonly name: "Hala Credit Microfinance Bank";
|
|
200
|
+
readonly code: "090291";
|
|
201
|
+
}, {
|
|
202
|
+
readonly name: "Page Financials";
|
|
203
|
+
readonly code: "070008";
|
|
204
|
+
}, {
|
|
205
|
+
readonly name: "Pristine Divitis Microfinance Bank";
|
|
206
|
+
readonly code: "090499";
|
|
207
|
+
}, {
|
|
208
|
+
readonly name: "Mainstreet Microfinance Bank";
|
|
209
|
+
readonly code: "090171";
|
|
210
|
+
}, {
|
|
211
|
+
readonly name: "Shalom Microfinance Bank";
|
|
212
|
+
readonly code: "090502";
|
|
213
|
+
}, {
|
|
214
|
+
readonly name: "Projetcs Microfinance Bank";
|
|
215
|
+
readonly code: "090503";
|
|
216
|
+
}, {
|
|
217
|
+
readonly name: "Zikora Microfinance Bank";
|
|
218
|
+
readonly code: "090504";
|
|
219
|
+
}, {
|
|
220
|
+
readonly name: "Enrich Microfinance Bank";
|
|
221
|
+
readonly code: "090539";
|
|
222
|
+
}, {
|
|
223
|
+
readonly name: "Ampersand Microfinance Bank";
|
|
224
|
+
readonly code: "090529";
|
|
225
|
+
}, {
|
|
226
|
+
readonly name: "Randalpha Microfinance Bank";
|
|
227
|
+
readonly code: "090496";
|
|
228
|
+
}, {
|
|
229
|
+
readonly name: "OAU Microfinance Bank";
|
|
230
|
+
readonly code: "090345";
|
|
231
|
+
}, {
|
|
232
|
+
readonly name: "Hope Payment Service Bank";
|
|
233
|
+
readonly code: "120002";
|
|
234
|
+
}, {
|
|
235
|
+
readonly name: "Fairmoney Microfinance Bank";
|
|
236
|
+
readonly code: "090551";
|
|
237
|
+
}, {
|
|
238
|
+
readonly name: "Access Yellow";
|
|
239
|
+
readonly code: "100052";
|
|
240
|
+
}, {
|
|
241
|
+
readonly name: "Contec Global Infotech Limited";
|
|
242
|
+
readonly code: "100032";
|
|
243
|
+
}, {
|
|
244
|
+
readonly name: "Lotus Bank";
|
|
245
|
+
readonly code: "000029";
|
|
246
|
+
}, {
|
|
247
|
+
readonly name: "Mkobo Microfinance Bank";
|
|
248
|
+
readonly code: "090455";
|
|
249
|
+
}, {
|
|
250
|
+
readonly name: "Momo Payment Service Bank";
|
|
251
|
+
readonly code: "120003";
|
|
252
|
+
}, {
|
|
253
|
+
readonly name: "Letshego Microfinance Bank";
|
|
254
|
+
readonly code: "090420";
|
|
255
|
+
}, {
|
|
256
|
+
readonly name: "Carbon";
|
|
257
|
+
readonly code: "100026";
|
|
258
|
+
}, {
|
|
259
|
+
readonly name: "Sparkle";
|
|
260
|
+
readonly code: "090325";
|
|
261
|
+
}, {
|
|
262
|
+
readonly name: "Kredi Microfinance Bank";
|
|
263
|
+
readonly code: "090380";
|
|
264
|
+
}, {
|
|
265
|
+
readonly name: "Renmoney Microfinance Bank";
|
|
266
|
+
readonly code: "090198";
|
|
267
|
+
}, {
|
|
268
|
+
readonly name: "Ekondo Microfinance Bank";
|
|
269
|
+
readonly code: "090097";
|
|
270
|
+
}, {
|
|
271
|
+
readonly name: "Premium Trust Bank";
|
|
272
|
+
readonly code: "000031";
|
|
273
|
+
}, {
|
|
274
|
+
readonly name: "Auchi Microfinance Bank";
|
|
275
|
+
readonly code: "090264";
|
|
276
|
+
}, {
|
|
277
|
+
readonly name: "AMJU Microfinance Bank";
|
|
278
|
+
readonly code: "090180";
|
|
279
|
+
}, {
|
|
280
|
+
readonly name: "Kenechukwu Microfinance Bank";
|
|
281
|
+
readonly code: "090602";
|
|
282
|
+
}, {
|
|
283
|
+
readonly name: "UNN Microfinance Bank";
|
|
284
|
+
readonly code: "090251";
|
|
285
|
+
}, {
|
|
286
|
+
readonly name: "AMUCHA Microfinance Bank";
|
|
287
|
+
readonly code: "090645";
|
|
288
|
+
}, {
|
|
289
|
+
readonly name: "9PSB";
|
|
290
|
+
readonly code: "120001";
|
|
291
|
+
}]>;
|
|
292
|
+
getClientSecret(): string;
|
|
293
|
+
getWebhookSecret(): string;
|
|
294
|
+
private getHeaders;
|
|
295
|
+
}
|
|
296
|
+
declare class BillingError extends Error {
|
|
297
|
+
private response;
|
|
298
|
+
constructor(message: string, args?: {
|
|
299
|
+
response: any;
|
|
300
|
+
});
|
|
301
|
+
getResponse<T>(): T;
|
|
302
|
+
}
|
|
303
|
+
declare function hashPayload({
|
|
304
|
+
payload,
|
|
305
|
+
secretKey,
|
|
306
|
+
timestamp
|
|
307
|
+
}: {
|
|
308
|
+
payload: any;
|
|
309
|
+
secretKey: string;
|
|
310
|
+
timestamp: string | number;
|
|
311
|
+
}): Promise<string>;
|
|
312
|
+
//#endregion
|
|
313
|
+
export { BillingError, NombaAPI, hashPayload };
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { banks } from "./lib/utils.js";
|
|
2
|
+
import { TokenManager } from "./token-manager/index.js";
|
|
3
|
+
//#region core/nomba_api/index.ts
|
|
4
|
+
const BASEURL = {
|
|
5
|
+
production: "https://api.nomba.com",
|
|
6
|
+
sandbox: "https://sandbox.nomba.com"
|
|
7
|
+
};
|
|
8
|
+
var NombaAPI = class {
|
|
9
|
+
environment = "production";
|
|
10
|
+
accountId;
|
|
11
|
+
clientId;
|
|
12
|
+
clientSecret;
|
|
13
|
+
endpoint;
|
|
14
|
+
webhookSecret;
|
|
15
|
+
tokenManager;
|
|
16
|
+
constructor(args) {
|
|
17
|
+
this.accountId = args.accountId;
|
|
18
|
+
this.clientId = args.clientId;
|
|
19
|
+
this.clientSecret = args.clientSecret;
|
|
20
|
+
this.webhookSecret = args.webhookSecret;
|
|
21
|
+
this.environment = args.environment ?? "production";
|
|
22
|
+
const baseUrl = BASEURL?.[this.environment] ?? BASEURL.production;
|
|
23
|
+
this.endpoint = baseUrl;
|
|
24
|
+
if (!this.clientId) throw new Error("Nomba clientId is required");
|
|
25
|
+
if (!this.clientSecret) throw new Error("Nomba clientSecret is required");
|
|
26
|
+
this.tokenManager = new TokenManager({
|
|
27
|
+
baseUrl,
|
|
28
|
+
accountId: args.accountId,
|
|
29
|
+
clientId: args.clientId,
|
|
30
|
+
clientSecret: args.clientSecret
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async init() {
|
|
34
|
+
await this.tokenManager.initialize();
|
|
35
|
+
}
|
|
36
|
+
async checkOut(args) {
|
|
37
|
+
const request = {
|
|
38
|
+
order: {
|
|
39
|
+
amount: args.amount,
|
|
40
|
+
currency: "NGN",
|
|
41
|
+
callbackUrl: args.successURL,
|
|
42
|
+
customerEmail: args.customerEmail,
|
|
43
|
+
orderReference: args.reference,
|
|
44
|
+
allowedPaymentMethods: ["Card", "Transfer"],
|
|
45
|
+
orderMetaData: args.metadata
|
|
46
|
+
},
|
|
47
|
+
tokenizeCard: true
|
|
48
|
+
};
|
|
49
|
+
const req = await fetch(`${this.endpoint}/v1/checkout/order`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
body: JSON.stringify(request),
|
|
52
|
+
headers: await this.getHeaders()
|
|
53
|
+
});
|
|
54
|
+
if (!req.ok) throw new Error("Failed to initialize checkout");
|
|
55
|
+
if (req.status !== 200) throw new Error("Failed to initialize checkout, bad request");
|
|
56
|
+
const response = await req.json();
|
|
57
|
+
if (isInvalid(response)) throw new BillingError("Checkout error: unable to checkout", { response });
|
|
58
|
+
return response.data;
|
|
59
|
+
}
|
|
60
|
+
async getCheckOut(args) {
|
|
61
|
+
if (!args.reference && !args.orderId) throw new Error("Either reference or orderId must be provided");
|
|
62
|
+
const url = new URL(`${this.endpoint}/v1/checkout/transaction`);
|
|
63
|
+
if (args.orderId) {
|
|
64
|
+
url.searchParams.set("id", args.orderId);
|
|
65
|
+
url.searchParams.set("idType", "ORDER_ID");
|
|
66
|
+
} else if (args.reference) {
|
|
67
|
+
url.searchParams.set("id", args.reference);
|
|
68
|
+
url.searchParams.set("idType", "ORDER_REFERENCE");
|
|
69
|
+
}
|
|
70
|
+
const req = await fetch(url, {
|
|
71
|
+
method: "GET",
|
|
72
|
+
headers: await this.getHeaders()
|
|
73
|
+
});
|
|
74
|
+
if (!req.ok) throw new Error("Failed to fetch checkout transaction");
|
|
75
|
+
if (req.status !== 200) throw new Error(`Failed to fetch checkout transaction, status ${req.status}`);
|
|
76
|
+
const response = await req.json();
|
|
77
|
+
if (isInvalid(response)) throw new BillingError("Checkout error: unable to fetch transaction", { response });
|
|
78
|
+
return response.data;
|
|
79
|
+
}
|
|
80
|
+
async chargeCard(args) {
|
|
81
|
+
const request = {
|
|
82
|
+
tokenKey: args.tokenKey,
|
|
83
|
+
order: {
|
|
84
|
+
orderReference: args.orderReference,
|
|
85
|
+
amount: args.amount,
|
|
86
|
+
currency: "NGN",
|
|
87
|
+
customerEmail: args.customerEmail,
|
|
88
|
+
callbackUrl: args.successURL
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const req = await fetch(`${this.endpoint}/v1/checkout/tokenized-card-payment`, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
body: JSON.stringify(request),
|
|
94
|
+
headers: await this.getHeaders()
|
|
95
|
+
});
|
|
96
|
+
if (!req.ok) throw new BillingError("API error: unable to charge card bad request");
|
|
97
|
+
if (req.status !== 200) throw new BillingError("API error: unable to charge card response error");
|
|
98
|
+
const response = await req.json();
|
|
99
|
+
if (isInvalid(response)) throw new BillingError("Charge error: unable to charge card", { response });
|
|
100
|
+
return response.data;
|
|
101
|
+
}
|
|
102
|
+
async listCards(args) {
|
|
103
|
+
const request = {
|
|
104
|
+
customerEmail: args.customerEmail,
|
|
105
|
+
page: 0
|
|
106
|
+
};
|
|
107
|
+
const req = await fetch(`${this.endpoint}/v1/checkout/tokenized-card-data`, {
|
|
108
|
+
method: "GET",
|
|
109
|
+
body: JSON.stringify(request),
|
|
110
|
+
headers: await this.getHeaders()
|
|
111
|
+
});
|
|
112
|
+
if (!req.ok) throw new Error("Failed to charge card");
|
|
113
|
+
if (req.status !== 200) throw new Error("Failed to charge card, bad request");
|
|
114
|
+
const response = await req.json();
|
|
115
|
+
if (isInvalid(response)) throw new BillingError("Card error: unable to list cards", { response });
|
|
116
|
+
return response.data;
|
|
117
|
+
}
|
|
118
|
+
async getBanks() {
|
|
119
|
+
return banks;
|
|
120
|
+
}
|
|
121
|
+
getClientSecret() {
|
|
122
|
+
return this.clientSecret;
|
|
123
|
+
}
|
|
124
|
+
getWebhookSecret() {
|
|
125
|
+
return this.webhookSecret;
|
|
126
|
+
}
|
|
127
|
+
async getHeaders() {
|
|
128
|
+
const token = await this.tokenManager.getAccessToken();
|
|
129
|
+
return new Headers({
|
|
130
|
+
"Content-Type": "application/json",
|
|
131
|
+
accountId: this.accountId,
|
|
132
|
+
Authorization: `Bearer ${token}`
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const errors = {
|
|
137
|
+
SUCCESS: "00",
|
|
138
|
+
GENERIC_ERROR: "01",
|
|
139
|
+
VALIDATION_ERROR: "02",
|
|
140
|
+
TRANSACTION_DENIED: "05",
|
|
141
|
+
ERROR_NO_RETRY: "06"
|
|
142
|
+
};
|
|
143
|
+
const isInvalid = (response) => {
|
|
144
|
+
return !("data" in response) || "code" in response && response.code !== errors.SUCCESS;
|
|
145
|
+
};
|
|
146
|
+
var BillingError = class extends Error {
|
|
147
|
+
response;
|
|
148
|
+
constructor(message, args) {
|
|
149
|
+
super(message);
|
|
150
|
+
this.response = args?.response;
|
|
151
|
+
}
|
|
152
|
+
getResponse() {
|
|
153
|
+
return this.response;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
async function hashPayload({ payload, secretKey, timestamp }) {
|
|
157
|
+
const data = payload.data || {};
|
|
158
|
+
const merchant = data.merchant || {};
|
|
159
|
+
const transaction = data.transaction || {};
|
|
160
|
+
const eventType = payload.event_type || "";
|
|
161
|
+
const requestId = payload.requestId || "";
|
|
162
|
+
const userId = merchant.userId || "";
|
|
163
|
+
const walletId = merchant.walletId || "";
|
|
164
|
+
const transactionId = transaction.transactionId || "";
|
|
165
|
+
const transactionType = transaction.type || "";
|
|
166
|
+
const transactionTime = transaction.time || "";
|
|
167
|
+
let transactionResponseCode = transaction.responseCode || "";
|
|
168
|
+
if (transactionResponseCode === "null") transactionResponseCode = "";
|
|
169
|
+
const hashingPayload = `${eventType}:${requestId}:${userId}:${walletId}:${transactionId}:${transactionType}:${transactionTime}:${transactionResponseCode}:${timestamp}`;
|
|
170
|
+
const encoder = new TextEncoder();
|
|
171
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secretKey), {
|
|
172
|
+
name: "HMAC",
|
|
173
|
+
hash: "SHA-256"
|
|
174
|
+
}, false, ["sign"]);
|
|
175
|
+
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(hashingPayload));
|
|
176
|
+
return Buffer.from(signature).toString("base64");
|
|
177
|
+
}
|
|
178
|
+
//#endregion
|
|
179
|
+
export { BillingError, NombaAPI, hashPayload };
|