finconnect 1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elisha Gerson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,328 @@
1
+ # FinConnect
2
+
3
+ <div align="center">
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
7
+ [![Node.js](https://img.shields.io/badge/Node.js-16+-green.svg)](https://nodejs.org/)
8
+
9
+ **A unified wrapper for East African fintech payment providers**
10
+
11
+ [Features](#features) • [Quick Start](#quick-start) • [Supported Providers](#supported-providers) • [Documentation](#documentation) • [Contributing](#contributing)
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ ## Overview
18
+
19
+ FinConnect is a lightweight, provider-agnostic integration wrapper that simplifies payment processing across multiple East African fintech platforms. Instead of managing different authentication flows, payload structures, and error handling for each provider, FinConnect provides a **single, unified API** for PesaPal, AzamPay, ClickPesa, and more.
20
+
21
+ ### The Problem We Solve
22
+
23
+ Integrating multiple payment providers typically requires:
24
+ - Learning different authentication flows (OAuth2 vs. JWT)
25
+ - Managing different payload structures per provider
26
+ - Implementing custom error handling for each API
27
+ - Maintaining complex provider-specific logic
28
+
29
+ FinConnect eliminates this complexity with a consistent, developer-friendly interface.
30
+
31
+ ---
32
+
33
+ ## ✨ Features
34
+
35
+ - 🔌 **Provider-Agnostic API** - Single interface for multiple payment providers
36
+ - 🔐 **Multi-Auth Support** - OAuth2, JWT, Bearer tokens handled transparently
37
+ - ⚡ **Type-Safe** - Full TypeScript support with complete type definitions
38
+ - 🌍 **Regional Coverage** - PesaPal (East Africa), AzamPay (Tanzania), ClickPesa (East Africa)
39
+ - 🛡️ **Error Handling** - Consistent error messages and status tracking
40
+ - 🔄 **Async/Await Ready** - Modern async patterns throughout
41
+ - 📝 **Well-Documented** - Comprehensive examples and API documentation
42
+
43
+ ---
44
+
45
+ ## 🚀 Quick Start
46
+
47
+ ### Prerequisites
48
+
49
+ - Node.js 16.x or later
50
+ - npm 7.x or later
51
+
52
+ ### Installation
53
+
54
+ ```bash
55
+ npm install finconnect
56
+ ```
57
+
58
+ Or from the repository source:
59
+
60
+ ```bash
61
+ # Clone the repository
62
+ git clone https://github.com/somebody1011/finconnect.git
63
+
64
+ # Navigate to project directory
65
+ cd finconnect
66
+
67
+ # Install dependencies
68
+ npm install
69
+ ```
70
+
71
+ ### Configuration
72
+
73
+ Create a `.env` file in your root directory with your provider credentials:
74
+
75
+ ```env
76
+ # PesaPal Configuration
77
+ PESAPAL_APP_KEY=your_key
78
+ PESAPAL_APP_SECRET=your_secret
79
+
80
+
81
+ # AzamPay Configuration
82
+ AZAMPAY_SECRET=your_secret
83
+
84
+ # ClickPesa Configuration
85
+ CLICKPESA_CLIENT_ID=your_id
86
+ CLICKPESA_API_KEY=your_api_key
87
+ ```
88
+
89
+ ### Basic Usage
90
+
91
+ ```typescript
92
+ import { FintechGateway } from './src/index';
93
+
94
+ // Initialize gateway for pesapal
95
+ const gateway = new FintechGateway('pesapal', {
96
+ apiKey: process.env.PESAPAL_CONSUMER_KEY,
97
+ apiSecret: process.env.PESAPAL_CONSUMER_SECRET,
98
+ shortCode: '174379',
99
+ environment: 'sandbox'
100
+ });
101
+
102
+ // Process a payment
103
+ async function processPayment() {
104
+ try {
105
+ const response = await gateway.processPayment({
106
+ amount: 1000,
107
+ phoneNumber: '255700000000',
108
+ reference: 'REF-99'
109
+ });
110
+
111
+ if (response.success) {
112
+ console.log(`✅ Payment successful! Transaction ID: ${response.transactionId}`);
113
+ } else {
114
+ console.error(`❌ Payment failed: ${response.message}`);
115
+ }
116
+ } catch (error) {
117
+ console.error('Error processing payment:', error);
118
+ }
119
+ }
120
+
121
+ processPayment();
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 🏗️ Supported Providers
127
+
128
+ | Provider | Status | Auth Method | Region(s) |
129
+ |----------|--------|-------------|-----------|
130
+ | **ClickPesa** |🚧🛠️ Onprogress | JWT | East Africa |
131
+ | **PesaPal** | 🚧🛠️ Onprogress| OAuth2 | East Africa |
132
+ | **AzamPay** | 📋 Planned | Bearer/Secret | Tanzania |
133
+
134
+
135
+ ---
136
+
137
+ ## 📚 API Reference
138
+
139
+ ### FintechGateway
140
+
141
+ #### Constructor
142
+
143
+ ```typescript
144
+ new FintechGateway(provider: string, config: ProviderConfig)
145
+ ```
146
+
147
+ **Parameters:**
148
+ - `provider` - The payment provider identifier ('pesapal', 'azampay', 'clickpesa')
149
+ - `config` - Provider-specific configuration object
150
+
151
+ #### Methods
152
+
153
+ ##### `processPayment()`
154
+
155
+ ```typescript
156
+ processPayment(params: PaymentParams): Promise<PaymentResponse>
157
+ ```
158
+
159
+ **Parameters:**
160
+ ```typescript
161
+ interface PaymentParams {
162
+ amount: number;
163
+ phoneNumber: string;
164
+ reference: string;
165
+ description?: string;
166
+ }
167
+ ```
168
+
169
+ **Returns:**
170
+ ```typescript
171
+ interface PaymentResponse {
172
+ success: boolean;
173
+ transactionId?: string;
174
+ message: string;
175
+ status: 'pending' | 'completed' | 'failed';
176
+ timestamp: Date;
177
+ }
178
+ ```
179
+
180
+ **Example:**
181
+ ```typescript
182
+ const result = await gateway.processPayment({
183
+ amount: 5000,
184
+ phoneNumber: '254712345678',
185
+ reference: 'ORD-2024-001',
186
+ description: 'Payment for order #123'
187
+ });
188
+ ```
189
+
190
+ ---
191
+
192
+ ## 📁 Project Structure
193
+
194
+ ```
195
+ finconnect/
196
+ ├── src/
197
+ │ ├── FintechGateway.ts # Main gateway class
198
+ │ ├── providers/
199
+ │ │ ├── BaseProvider.ts # Abstract base class
200
+ │ │ ├── MpesaProvider.ts # M-Pesa implementation
201
+ │ │ ├── AzampayProvider.ts # AzamPay implementation
202
+ │ │ └── ClickpesaProvider.ts # ClickPesa implementation
203
+ │ ├── types/
204
+ │ │ └── index.ts # TypeScript type definitions
205
+ │ └── utils/
206
+ │ └── errorHandler.ts # Error handling utilities
207
+ ├── tests/
208
+ │ ├── unit/
209
+ │ └── integration/
210
+ ├── .env.example
211
+ ├── package.json
212
+ ├── tsconfig.json
213
+ ├── jest.config.js
214
+ └── README.md
215
+ ```
216
+
217
+ ---
218
+
219
+ ## 🔒 Security Best Practices
220
+
221
+ 1. **Never commit credentials** - Use `.env` files and add them to `.gitignore`
222
+ 2. **Use environment variables** - Store sensitive keys outside version control
223
+ 3. **Validate inputs** - Always validate payment amounts and phone numbers
224
+ 4. **HTTPS only** - All API calls are made over HTTPS
225
+ 5. **Error messages** - Avoid exposing sensitive details in error responses
226
+
227
+ **Example:**
228
+ ```typescript
229
+ // ❌ DO NOT DO THIS
230
+ const gateway = new FintechGateway('mpesa', {
231
+ apiKey: 'your_actual_key_here'
232
+ });
233
+
234
+ // ✅ DO THIS
235
+ const gateway = new FintechGateway('pesapal', {
236
+ apiKey: process.env.PESAPAL_CONSUMER_KEY,
237
+ apiSecret: process.env.PESAPAL_CONSUMER_SECRET
238
+ });
239
+ ```
240
+
241
+ ---
242
+
243
+ ## 🗺️ Roadmap
244
+
245
+ - [x] ClickPesa integration
246
+ - [x] PesaPal integration
247
+ - [ ] AzamPay integration
248
+ - [ ] Add B2C (Business to Customer) support
249
+ - [ ] Implement automatic retry logic for failed API calls
250
+ - [ ] Add comprehensive unit tests using Jest
251
+ - [ ] Add rate limiting and throttling
252
+ - [ ] Support for transaction status polling
253
+ - [ ] Webhook integration for payment notifications
254
+ - [ ] SDK for React Native
255
+
256
+ ---
257
+
258
+ ## 🤝 Contributing
259
+
260
+ We welcome contributions! Here's how to get started:
261
+
262
+ 1. **Fork the repository** on GitHub
263
+ 2. **Create a feature branch** for your changes:
264
+ ```bash
265
+ git checkout -b feature/add-new-provider
266
+ ```
267
+ 3. **Add a new provider** (if applicable):
268
+ - Create a new file in `src/providers/` (e.g., `NewProviderName.ts`)
269
+ - Extend the `BaseProvider` class
270
+ - Implement required methods: `authenticate()`, `processPayment()`, `getTransactionStatus()`
271
+ 4. **Add tests** for your changes:
272
+ ```bash
273
+ npm test
274
+ ```
275
+ 5. **Commit your changes** with clear messages:
276
+ ```bash
277
+ git commit -m "Add support for XYZ provider"
278
+ ```
279
+ 6. **Push to your fork** and submit a Pull Request
280
+
281
+ ### Development Setup
282
+
283
+ ```bash
284
+ # Install dev dependencies
285
+ npm install --save-dev
286
+
287
+ # Run tests
288
+ npm test
289
+
290
+ # Build the project
291
+ npm run build
292
+
293
+ # Lint the code
294
+ npm run lint
295
+ ```
296
+
297
+ ---
298
+
299
+ ## 📝 License
300
+
301
+ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.
302
+
303
+ ---
304
+
305
+ ## 📞 Support & Contact
306
+
307
+ - **Issues** - Report bugs or request features via [GitHub Issues](https://github.com/somebody1011/finconnect/issues)
308
+ - **Discussions** - Join our community discussions [here](https://github.com/somebody1011/finconnect/discussions)
309
+ - **Author** - [@somebody1011](https://github.com/somebody1011)
310
+
311
+ ---
312
+
313
+ ## 🙏 Acknowledgments
314
+
315
+ - Built with ❤️ for the East African fintech community
316
+ - Inspired by Stripe's elegant API design
317
+ - Special thanks to all contributors and early users
318
+ - Thanks to the open-source community for amazing tools and libraries
319
+
320
+ ---
321
+
322
+ <div align="center">
323
+
324
+ Made with ❤️ by [somebody1011](https://github.com/somebody1011)
325
+
326
+ ⭐ Star us on GitHub! [somebody1011/finconnect](https://github.com/somebody1011/finconnect)
327
+
328
+ </div>
@@ -0,0 +1,21 @@
1
+ export declare const ProviderType: {
2
+ readonly clickpesa: "clickpesa";
3
+ readonly pesapal: "pesapal";
4
+ readonly azampay: "azampay";
5
+ };
6
+ export type ProviderType = typeof ProviderType[keyof typeof ProviderType];
7
+ export declare class FintechSDK {
8
+ private gateway;
9
+ constructor(options: {
10
+ provider: ProviderType | string;
11
+ config: any;
12
+ });
13
+ registerIpn(ipnUrl: string, ipnNotificationType?: "GET" | "POST"): Promise<any>;
14
+ pay(data: any, ipnId?: string): Promise<any>;
15
+ checkPaymentStatus(transactionId: string): Promise<any>;
16
+ handleCallback(callbackData: any): Promise<{
17
+ isValid: boolean;
18
+ data: any;
19
+ }>;
20
+ }
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAuC1E,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,EAAE;QAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAA;KAAE;IAK/D,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAE,KAAK,GAAG,MAAc;IAKvE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,MAAM;IAc7B,kBAAkB,CAAC,aAAa,EAAE,MAAM;IAIxC,cAAc,CAAC,YAAY,EAAE,GAAG;;;;CAMvC"}
package/dist/index.js ADDED
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FintechSDK = exports.ProviderType = void 0;
4
+ const ClickpesaProvider_js_1 = require("./providers/ClickpesaProvider.js");
5
+ const PesapalProvider_js_1 = require("./providers/PesapalProvider.js");
6
+ const AzampayProvider_js_1 = require("./providers/AzampayProvider.js");
7
+ exports.ProviderType = {
8
+ clickpesa: 'clickpesa',
9
+ pesapal: 'pesapal',
10
+ azampay: 'azampay',
11
+ };
12
+ class ProviderFactory {
13
+ /**
14
+ * Factory method to create a specific provider instance.
15
+ *
16
+ * Security Considerations:
17
+ * 1. Validates the provider type against an allowed list via a switch statement,
18
+ * preventing prototype pollution or instantiation of arbitrary objects.
19
+ * 2. Throws an explicit error for unsupported providers, avoiding silent failures.
20
+ * 3. Validates that essential configuration parameters are present before instantiating.
21
+ */
22
+ static createProvider(provider, config) {
23
+ switch (String(provider).toLowerCase()) {
24
+ case exports.ProviderType.clickpesa:
25
+ if (!config || !config.baseUrl || !config.CLICKPESA_CLIENT_ID || !config.CLICKPESA_API_KEY) {
26
+ throw new Error("Invalid configuration: Missing required fields for Clickpesa.");
27
+ }
28
+ return new ClickpesaProvider_js_1.ClickpesaProvider(config);
29
+ case exports.ProviderType.pesapal:
30
+ if (!config || !config.baseUrl || !config.PESAPAL_CONSUMER_KEY || !config.PESAPAL_CONSUMER_SECRET) {
31
+ throw new Error("Invalid configuration: Missing required fields for Pesapal.");
32
+ }
33
+ return new PesapalProvider_js_1.PesapalProvider(config);
34
+ case exports.ProviderType.azampay:
35
+ if (!config || !config.baseUrl || !config.AZAMPAY_APP_NAME || !config.AZAMPAY_CONSUMER_KEY || !config.AZAMPAY_CONSUMER_SECRET) {
36
+ throw new Error("Invalid configuration: Missing required fields for Azampay.");
37
+ }
38
+ return new AzampayProvider_js_1.AzampayProvider(config);
39
+ default:
40
+ // Security: Fail securely if an unknown provider is requested.
41
+ throw new Error(`Unsupported provider type: ${String(provider)}`);
42
+ }
43
+ }
44
+ }
45
+ class FintechSDK {
46
+ gateway;
47
+ constructor(options) {
48
+ // Utilize the secure ProviderFactory to instantiate the gateway
49
+ this.gateway = ProviderFactory.createProvider(options.provider, options.config);
50
+ }
51
+ async registerIpn(ipnUrl, ipnNotificationType = "GET") {
52
+ // Allows the user to register an IPN and retrieve an ipnId
53
+ return this.gateway.registerIpn(ipnUrl, ipnNotificationType);
54
+ }
55
+ async pay(data, ipnId) {
56
+ // Normalizes the data structure depending on what the underlying provider expects.
57
+ if (this.gateway instanceof PesapalProvider_js_1.PesapalProvider) {
58
+ // Pesapal expects an object with payload and ipnId
59
+ return this.gateway.initiateUssdPushRequest({ payload: data, ipnId });
60
+ }
61
+ else if (this.gateway instanceof AzampayProvider_js_1.AzampayProvider) {
62
+ // Azampay expects an object with payload
63
+ return this.gateway.initiateUssdPushRequest({ payload: data });
64
+ }
65
+ else {
66
+ // Clickpesa and others expect the raw payload directly
67
+ return this.gateway.initiateUssdPushRequest(data);
68
+ }
69
+ }
70
+ async checkPaymentStatus(transactionId) {
71
+ return this.gateway.checkPaymentStatus({ transactionId });
72
+ }
73
+ async handleCallback(callbackData) {
74
+ if (this.gateway instanceof AzampayProvider_js_1.AzampayProvider) {
75
+ return this.gateway.handleCallback(callbackData);
76
+ }
77
+ throw new Error(`Callback handling is not supported for provider ${this.gateway.constructor.name}`);
78
+ }
79
+ }
80
+ exports.FintechSDK = FintechSDK;
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { baseProvider } from "./BaseProvider.js";
2
+ export declare class AzampayProvider extends baseProvider {
3
+ constructor(config: any);
4
+ authenticate(): Promise<string>;
5
+ initiateUssdPushRequest({ payload }: {
6
+ payload: any;
7
+ }): Promise<any>;
8
+ checkPaymentStatus(params: {
9
+ transactionId: string;
10
+ }): Promise<any>;
11
+ getPublicKey(): Promise<string>;
12
+ verifyCallbackSignature(utilityRef: string, externalReference: string, transactionStatus: string, operatorName: string, signatureBase64: string, publicKeyPem: string): boolean;
13
+ handleCallback(callbackData: any): Promise<{
14
+ isValid: boolean;
15
+ data: any;
16
+ }>;
17
+ }
18
+ //# sourceMappingURL=AzampayProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AzampayProvider.d.ts","sourceRoot":"","sources":["../../src/providers/AzampayProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAM/C,qBAAa,eAAgB,SAAQ,YAAY;gBACjC,MAAM,EAAE,GAAG;IAIjB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IA2B/B,uBAAuB,CAAC,EAAE,OAAO,EAAE,EAAE;QAAE,OAAO,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA4BpE,kBAAkB,CAAC,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAKnE,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAcrC,uBAAuB,CACnB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,EACzB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,GACrB,OAAO;IAQJ,cAAc,CAAC,YAAY,EAAE,GAAG,GAAG,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAC,CAAC;CAkBlF"}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.AzampayProvider = void 0;
40
+ const BaseProvider_js_1 = require("./BaseProvider.js");
41
+ const dotenv = __importStar(require("dotenv"));
42
+ dotenv.config();
43
+ const axios_1 = __importDefault(require("axios"));
44
+ const crypto = __importStar(require("crypto"));
45
+ class AzampayProvider extends BaseProvider_js_1.baseProvider {
46
+ constructor(config) {
47
+ super(config);
48
+ }
49
+ async authenticate() {
50
+ try {
51
+ const response = await axios_1.default.post(` https://authenticator-sandbox.azampay.co.tz/AppRegistration/GenerateToken`, {
52
+ 'appName': this.config.AZAMPAY_APP_NAME,
53
+ 'clientId': this.config.AZAMPAY_CONSUMER_KEY,
54
+ 'clientSecret': this.config.AZAMPAY_CONSUMER_SECRET,
55
+ }, {
56
+ headers: {
57
+ 'Content-Type': 'application/json',
58
+ }
59
+ });
60
+ return response.data.data.accessToken;
61
+ }
62
+ catch (error) {
63
+ if (error.response) {
64
+ console.error('Authentication Error Response:', error.response.data);
65
+ throw new Error(`Authentication failed: ${error.response.data.message || error.message}`);
66
+ }
67
+ throw new Error(`Authentication failed: ${error}`);
68
+ }
69
+ }
70
+ async initiateUssdPushRequest({ payload }) {
71
+ try {
72
+ const token = await this.authenticate();
73
+ // console.log('Obtained Auth Token:', token); // Debug log for token
74
+ const response = await axios_1.default.post(`${this.config.baseUrl}/azampay/mno/checkout`, payload, {
75
+ headers: {
76
+ 'Content-Type': 'application/json',
77
+ 'Authorization': `Bearer ${token}`,
78
+ }
79
+ });
80
+ return response.data.transactionId;
81
+ }
82
+ catch (error) {
83
+ if (error.response) {
84
+ console.error('USSD Push Request Error Response:', error.response.data);
85
+ throw new Error(`Payment request failed: ${error.response.data.message || error.message}`);
86
+ }
87
+ throw new Error(`Payment request failed: ${error.message || error}`);
88
+ }
89
+ }
90
+ // Check Transaction Status (Unsupported in Tanzania Sandbox)
91
+ async checkPaymentStatus(params) {
92
+ throw new Error("AzamPay Tanzania does not support polling for payment status. Please use the Webhook Callback (handleCallback) strategy instead.");
93
+ }
94
+ // Handle Payment Callback with Signature Verification
95
+ async getPublicKey() {
96
+ try {
97
+ const token = await this.authenticate();
98
+ const response = await axios_1.default.get(`${this.config.baseUrl}/azampay/v1/public-key?format=Pem`, {
99
+ headers: {
100
+ 'Authorization': `Bearer ${token}`
101
+ }
102
+ });
103
+ return response.data.publicKey;
104
+ }
105
+ catch (error) {
106
+ throw new Error(`Failed to fetch public key: ${error.message}`);
107
+ }
108
+ }
109
+ verifyCallbackSignature(utilityRef, externalReference, transactionStatus, operatorName, signatureBase64, publicKeyPem) {
110
+ const dataToVerify = `${utilityRef}${externalReference}${transactionStatus}${operatorName}`;
111
+ const verifier = crypto.createVerify('SHA256');
112
+ verifier.update(dataToVerify, 'utf8');
113
+ verifier.end();
114
+ return verifier.verify(publicKeyPem, signatureBase64, 'base64');
115
+ }
116
+ async handleCallback(callbackData) {
117
+ try {
118
+ const publicKeyPem = await this.getPublicKey();
119
+ const isValid = this.verifyCallbackSignature(callbackData.utilityref || '', callbackData.externalreference || '', callbackData.transactionstatus || '', callbackData.operator || '', callbackData.signature || '', publicKeyPem);
120
+ return { isValid, data: callbackData };
121
+ }
122
+ catch (error) {
123
+ throw new Error(`Callback handling failed: ${error.message}`);
124
+ }
125
+ }
126
+ }
127
+ exports.AzampayProvider = AzampayProvider;
128
+ // async function testAzampay() {
129
+ // const azampay = new AzampayProvider({baseUrl:process.env.AZAMPAY_BASE_URL,AZAMPAY_APP_NAME:process.env.AZAMPAY_APP_NAME, AZAMPAY_CONSUMER_KEY:process.env.AZAMPAY_CLIENT_ID, AZAMPAY_CONSUMER_SECRET:process.env.AZAMPAY_API_KEY});
130
+ // const auth = await azampay.authenticate();
131
+ // console.log('Auth token:', auth);
132
+ // }
133
+ // testAzampay()
134
+ //# sourceMappingURL=AzampayProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AzampayProvider.js","sourceRoot":"","sources":["../../src/providers/AzampayProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare abstract class baseProvider {
2
+ protected config: any;
3
+ constructor(config: any);
4
+ abstract authenticate(): Promise<string>;
5
+ abstract initiateUssdPushRequest(params: {
6
+ payload: any;
7
+ ipnId?: string;
8
+ }): Promise<any>;
9
+ abstract checkPaymentStatus(params: {
10
+ transactionId: string;
11
+ }): Promise<any>;
12
+ registerIpn(_ipnUrl: string, _ipnNotificationType: "GET" | "POST"): Promise<any>;
13
+ }
14
+ //# sourceMappingURL=BaseProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseProvider.d.ts","sourceRoot":"","sources":["../../src/providers/BaseProvider.ts"],"names":[],"mappings":"AACA,8BAAsB,YAAY;IAChC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC;gBACV,MAAM,EAAE,GAAG;IAGvB,QAAQ,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IACxC,QAAQ,CAAC,uBAAuB,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,GAAG,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IACxF,QAAQ,CAAC,kBAAkB,CAAC,MAAM,EAAC;QAAC,aAAa,EAAC,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAClE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAGvF"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.baseProvider = void 0;
4
+ // Add 'export' right here
5
+ class baseProvider {
6
+ config;
7
+ constructor(config) {
8
+ this.config = config;
9
+ }
10
+ async registerIpn(_ipnUrl, _ipnNotificationType) {
11
+ throw new Error("IPN registration not supported by this provider");
12
+ }
13
+ }
14
+ exports.baseProvider = baseProvider;
15
+ //# sourceMappingURL=BaseProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseProvider.js","sourceRoot":"","sources":["../../src/providers/BaseProvider.ts"],"names":[],"mappings":";;;AAAA,0BAA0B;AAC1B,MAAsB,YAAY;IACtB,MAAM,CAAM;IACtB,YAAY,MAAW;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAID,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,oBAAoC;QACrE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;CACF;AAXD,oCAWC"}
@@ -0,0 +1,10 @@
1
+ import { baseProvider } from "./BaseProvider.js";
2
+ export declare class ClickpesaProvider extends baseProvider {
3
+ constructor(config: any);
4
+ authenticate(): Promise<string>;
5
+ initiateUssdPushRequest(payload: any): Promise<any>;
6
+ checkPaymentStatus(params: {
7
+ transactionId: string;
8
+ }): Promise<any>;
9
+ }
10
+ //# sourceMappingURL=ClickpesaProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClickpesaProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ClickpesaProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMjD,qBAAa,iBAAkB,SAAQ,YAAY;gBACrC,MAAM,EAAE,GAAG;IAIjB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAkB/B,uBAAuB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAoBnD,kBAAkB,CAAC,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;CAkB1E"}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ClickpesaProvider = void 0;
40
+ const BaseProvider_js_1 = require("./BaseProvider.js");
41
+ const axios_1 = __importDefault(require("axios"));
42
+ const dotenv = __importStar(require("dotenv"));
43
+ dotenv.config();
44
+ class ClickpesaProvider extends BaseProvider_js_1.baseProvider {
45
+ constructor(config) {
46
+ super(config);
47
+ }
48
+ async authenticate() {
49
+ try {
50
+ const response = await axios_1.default.post(`${this.config.baseUrl}/third-parties/generate-token`, {
51
+ headers: {
52
+ 'client-id': this.config.CLICKPESA_CLIENT_ID,
53
+ 'api-key': this.config.CLICKPESA_API_KEY,
54
+ "Content-Type": "application/json",
55
+ },
56
+ });
57
+ return response.data?.token || response.data;
58
+ }
59
+ catch (error) {
60
+ throw new Error(`Authentication failed: ${error}`);
61
+ }
62
+ }
63
+ async initiateUssdPushRequest(payload) {
64
+ try {
65
+ const token = await this.authenticate();
66
+ const response = await axios_1.default.post(`${this.config.baseUrl}/third-parties/payments/initiate-ussd-push-request`, // Added /third-parties/
67
+ payload, {
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ "Authorization": token,
71
+ },
72
+ });
73
+ return response.data;
74
+ }
75
+ catch (error) {
76
+ console.error('USSD Push Error:', error.response?.data || error.message);
77
+ throw new Error(`Payment request failed: ${error.response?.data?.message || error.message}`);
78
+ }
79
+ }
80
+ async checkPaymentStatus(params) {
81
+ try {
82
+ const token = await this.authenticate();
83
+ const response = await axios_1.default.get(`${this.config.baseUrl}/third-parties/payments/${params.transactionId}`, // Added /third-parties/
84
+ {
85
+ headers: {
86
+ 'Accept': 'application/json',
87
+ 'Content-Type': 'application/json',
88
+ 'Authorization': token,
89
+ }
90
+ });
91
+ return response.data;
92
+ }
93
+ catch (error) {
94
+ throw new Error(`Payment status check failed: ${error}`);
95
+ }
96
+ }
97
+ }
98
+ exports.ClickpesaProvider = ClickpesaProvider;
99
+ //# sourceMappingURL=ClickpesaProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClickpesaProvider.js","sourceRoot":"","sources":["../../src/providers/ClickpesaProvider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uDAAiD;AACjD,kDAA0B;AAC1B,+CAAiC;AAEjC,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAa,iBAAkB,SAAQ,8BAAY;IACjD,YAAY,MAAW;QACrB,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAC/B,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,+BAA+B,EACrD;gBACE,OAAO,EAAE;oBACP,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB;oBAC5C,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,iBAAiB;oBACxC,cAAc,EAAE,kBAAkB;iBACnC;aACF,CACF,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,EAAE,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,OAAY;QACxC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAC/B,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,oDAAoD,EAAE,wBAAwB;YACpG,OAAO,EACP;gBACE,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,KAAK;iBACvB;aACF,CACF,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;YACzE,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,MAAiC;QACxD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAC9B,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,2BAA2B,MAAM,CAAC,aAAa,EAAE,EAAE,wBAAwB;YACjG;gBACE,OAAO,EAAE;oBACP,QAAQ,EAAE,kBAAkB;oBAC5B,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,KAAK;iBACvB;aACF,CACF,CAAC;YACF,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF;AA7DD,8CA6DC"}
@@ -0,0 +1,14 @@
1
+ import { baseProvider } from './BaseProvider.js';
2
+ export declare class PesapalProvider extends baseProvider {
3
+ constructor(config: any);
4
+ authenticate(): Promise<string>;
5
+ registerIpn(ipnUrl: string, ipnNotificationType: "GET" | "POST"): Promise<any>;
6
+ initiateUssdPushRequest({ payload, ipnId }: {
7
+ payload: any;
8
+ ipnId?: string;
9
+ }): Promise<any>;
10
+ checkPaymentStatus(params: {
11
+ transactionId: string;
12
+ }): Promise<any>;
13
+ }
14
+ //# sourceMappingURL=PesapalProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PesapalProvider.d.ts","sourceRoot":"","sources":["../../src/providers/PesapalProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAG/C,qBAAa,eAAgB,SAAQ,YAAY;gBACjC,MAAM,EAAE,GAAG;IAIjB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAqBnC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAwB1E,uBAAuB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAAE,OAAO,EAAE,GAAG,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAwB3F,kBAAkB,CAAC,MAAM,EAAC;QAAC,aAAa,EAAC,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,GAAG,CAAC;CAmBxE"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PesapalProvider = void 0;
7
+ const BaseProvider_js_1 = require("./BaseProvider.js");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ class PesapalProvider extends BaseProvider_js_1.baseProvider {
10
+ constructor(config) {
11
+ super(config);
12
+ }
13
+ async authenticate() {
14
+ try {
15
+ const response = await axios_1.default.post(`${this.config.baseUrl}/api/Auth/RequestToken`, {
16
+ consumer_key: this.config.PESAPAL_CONSUMER_KEY,
17
+ consumer_secret: this.config.PESAPAL_CONSUMER_SECRET,
18
+ }, {
19
+ headers: {
20
+ 'Accept': 'application/json',
21
+ 'Content-Type': 'application/json',
22
+ }
23
+ });
24
+ return response.data.token;
25
+ }
26
+ catch (error) {
27
+ throw new Error(`Authentication failed: ${error}`);
28
+ }
29
+ }
30
+ async registerIpn(ipnUrl, ipnNotificationType) {
31
+ try {
32
+ const token = await this.authenticate();
33
+ const response = await axios_1.default.post(`${this.config.baseUrl}/api/URLSetup/RegisterIPN`, // sandbox path
34
+ {
35
+ url: ipnUrl,
36
+ ipn_notification_type: ipnNotificationType
37
+ }, {
38
+ headers: {
39
+ 'Accept': 'application/json',
40
+ 'Content-Type': 'application/json',
41
+ 'Authorization': `Bearer ${token}`,
42
+ }
43
+ });
44
+ return response.data.ipn_id;
45
+ }
46
+ catch (error) {
47
+ throw new Error(`IPN registration failed: ${error}`);
48
+ }
49
+ }
50
+ async initiateUssdPushRequest({ payload, ipnId }) {
51
+ try {
52
+ const token = await this.authenticate();
53
+ const finalPayload = {
54
+ ...payload,
55
+ notification_id: ipnId
56
+ };
57
+ const response = await axios_1.default.post(`${this.config.baseUrl}/api/Transactions/SubmitOrderRequest`, finalPayload, {
58
+ headers: {
59
+ 'Accept': 'application/json',
60
+ 'Content-Type': 'application/json',
61
+ 'Authorization': `Bearer ${token}`,
62
+ }
63
+ });
64
+ return response.data;
65
+ }
66
+ catch (error) {
67
+ throw new Error(`Payment request failed: ${error}`);
68
+ }
69
+ }
70
+ async checkPaymentStatus(params) {
71
+ try {
72
+ const token = await this.authenticate();
73
+ const response = await axios_1.default.get(`${this.config.baseUrl}/api/Transactions/GetTransactionStatus?orderTrackingId=${params.transactionId}`, {
74
+ headers: {
75
+ 'Accept': 'application/json',
76
+ 'Content-Type': 'application/json',
77
+ 'Authorization': `Bearer ${token}`,
78
+ }
79
+ });
80
+ return response.data;
81
+ }
82
+ catch (error) {
83
+ throw new Error(`Payment status check failed: ${error}`);
84
+ }
85
+ }
86
+ }
87
+ exports.PesapalProvider = PesapalProvider;
88
+ //# sourceMappingURL=PesapalProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PesapalProvider.js","sourceRoot":"","sources":["../../src/providers/PesapalProvider.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "finconnect",
3
+ "version": "1.0.0",
4
+ "description": "A lightweight, provider-agnostic integration wrapper for East African Fintech APIs.",
5
+ "homepage": "https://github.com/somebody1011/finconnect#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/somebody1011/finconnect/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/somebody1011/finconnect.git"
12
+ },
13
+ "license": "MIT",
14
+ "author": "elisha gerson",
15
+ "type": "commonjs",
16
+ "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "require": "./dist/index.js",
22
+ "default": "./dist/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "directories": {
31
+ "example": "examples",
32
+ "test": "test"
33
+ },
34
+ "keywords": [
35
+ "fintech",
36
+ "payments",
37
+ "azampay",
38
+ "pesapal",
39
+ "clickpesa",
40
+ "typescript",
41
+ "node"
42
+ ],
43
+ "engines": {
44
+ "node": ">=16"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc",
48
+ "test": "jest --runInBand",
49
+ "dev": "ts-node scripts/server.ts",
50
+ "dev-tool": "tsx scripts/dev-tool.ts",
51
+ "provider-test": "tsx src/providers/ClickpesaProvider.ts",
52
+ "prepublishOnly": "npm run build && npm test"
53
+ },
54
+ "dependencies": {
55
+ "axios": "^1.15.2",
56
+ "dotenv": "^17.4.2",
57
+ "express": "^5.2.1"
58
+ },
59
+ "devDependencies": {
60
+ "@types/express": "^5.0.6",
61
+ "@types/jest": "^30.0.0",
62
+ "@types/node": "^25.6.0",
63
+ "axios-mock-adapter": "^2.1.0",
64
+ "jest": "^30.3.0",
65
+ "ts-jest": "^29.4.9",
66
+ "ts-node": "^10.9.2",
67
+ "tsx": "^4.21.0",
68
+ "typescript": "^6.0.3"
69
+ },
70
+ "publishConfig": {
71
+ "access": "public"
72
+ }
73
+ }