@erulabs-tech/medusa-plugin-wonyapay 0.0.1

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.
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ const i18nTranslations0 = {};
3
+ const widgetModule = { widgets: [] };
4
+ const routeModule = {
5
+ routes: []
6
+ };
7
+ const menuItemModule = {
8
+ menuItems: []
9
+ };
10
+ const formModule = { customFields: {} };
11
+ const displayModule = {
12
+ displays: {}
13
+ };
14
+ const i18nModule = { resources: i18nTranslations0 };
15
+ const plugin = {
16
+ widgetModule,
17
+ routeModule,
18
+ menuItemModule,
19
+ formModule,
20
+ displayModule,
21
+ i18nModule
22
+ };
23
+ module.exports = plugin;
@@ -0,0 +1,24 @@
1
+ const i18nTranslations0 = {};
2
+ const widgetModule = { widgets: [] };
3
+ const routeModule = {
4
+ routes: []
5
+ };
6
+ const menuItemModule = {
7
+ menuItems: []
8
+ };
9
+ const formModule = { customFields: {} };
10
+ const displayModule = {
11
+ displays: {}
12
+ };
13
+ const i18nModule = { resources: i18nTranslations0 };
14
+ const plugin = {
15
+ widgetModule,
16
+ routeModule,
17
+ menuItemModule,
18
+ formModule,
19
+ displayModule,
20
+ i18nModule
21
+ };
22
+ export {
23
+ plugin as default
24
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = GET;
4
+ async function GET(req, res) {
5
+ res.sendStatus(200);
6
+ }
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3BsdWdpbi9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLGtCQUtDO0FBTE0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBa0IsRUFDbEIsR0FBbUI7SUFFbkIsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN0QixDQUFDIn0=
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ const GET = async (req, res) => {
5
+ res.status(200).json({ message: "Pay with MoMo with Partner" });
6
+ };
7
+ exports.GET = GET;
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL3N0b3JlL3VzZS13b255YS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFTyxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDbkUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsQ0FBQyxDQUFDO0FBQ2xFLENBQUMsQ0FBQztBQUZXLFFBQUEsR0FBRyxPQUVkIn0=
@@ -0,0 +1,26 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ const utils_1 = require("@medusajs/framework/utils");
21
+ const service_1 = __importDefault(require("./service"));
22
+ __exportStar(require("./types"), exports);
23
+ exports.default = (0, utils_1.ModuleProvider)(utils_1.Modules.PAYMENT, {
24
+ services: [service_1.default],
25
+ });
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3dvbnlhcGF5L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxREFBb0U7QUFDcEUsd0RBQWdEO0FBRWhELDBDQUF3QjtBQUV4QixrQkFBZSxJQUFBLHNCQUFjLEVBQUMsZUFBTyxDQUFDLE9BQU8sRUFBRTtJQUM3QyxRQUFRLEVBQUUsQ0FBQyxpQkFBdUIsQ0FBQztDQUNwQyxDQUFDLENBQUMifQ==
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@medusajs/framework/utils");
4
+ const utils_2 = require("./utils");
5
+ const BASE_API_URL = "https://app-api.wonyasoft.com";
6
+ class WonyaPayProviderService extends utils_1.AbstractPaymentProvider {
7
+ constructor(deps, options) {
8
+ super(deps, options);
9
+ this.deps = deps;
10
+ this.options = options;
11
+ this.options = options;
12
+ }
13
+ static validateOptions(options) {
14
+ if (!options.apiKey) {
15
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Missing API Key");
16
+ }
17
+ if (!options.refPartner) {
18
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Missing Partner ID");
19
+ }
20
+ }
21
+ async authorizePayment(input) {
22
+ // TODO: Authorize payment
23
+ this.deps.logger.info("Authorize payment");
24
+ const paymentId = (0, utils_2.generateTransactionId)();
25
+ const response = await fetch(`${BASE_API_URL}/payment`, {
26
+ method: "POST",
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ Authorization: `Bearer ${this.options.apiKey}`,
30
+ },
31
+ body: JSON.stringify({
32
+ RefPartenaire: this.options.refPartner,
33
+ RefTransa: paymentId,
34
+ Montant: 100,
35
+ Devise: "CDF" /*|| (input.data?.currency_code as string).toUpperCase()*/,
36
+ Action: (input.data?.action).toUpperCase(),
37
+ mobileMoney: input.data?.mobileMoney,
38
+ }),
39
+ });
40
+ this.deps.logger.info("Waiting for transaction response");
41
+ if (!response.ok) {
42
+ return { data: {}, status: "error" };
43
+ }
44
+ const transactionData = await response.json();
45
+ console.log(transactionData);
46
+ const refTransa = transactionData.data.RefTransa;
47
+ // Poll to check if status has changed
48
+ await (0, utils_2.sleep)(10000);
49
+ let status = await this.getPaymentStatus({ data: { id: refTransa } });
50
+ console.log("First status");
51
+ console.log(status);
52
+ if (status.status === "authorized")
53
+ return {
54
+ status: "authorized",
55
+ };
56
+ else if (status.status === "canceled")
57
+ return { status: "canceled" };
58
+ else if (status.status === "error")
59
+ return { status: "error" };
60
+ // Second poll
61
+ await (0, utils_2.sleep)(10000);
62
+ status = await this.getPaymentStatus({ data: { id: refTransa } });
63
+ console.log("Second status");
64
+ console.log(status);
65
+ if (status.status === "authorized")
66
+ return {
67
+ status: "authorized",
68
+ };
69
+ else if (status.status === "canceled")
70
+ return { status: "canceled" };
71
+ else if (status.status === "error")
72
+ return { status: "error" };
73
+ // Third poll
74
+ await (0, utils_2.sleep)(10000);
75
+ status = await this.getPaymentStatus({ data: { id: refTransa } });
76
+ console.log("Third status");
77
+ console.log(status);
78
+ if (status.status === "authorized")
79
+ return {
80
+ status: "authorized",
81
+ };
82
+ else if (status.status === "canceled")
83
+ return { status: "canceled" };
84
+ else if (status.status === "error")
85
+ return { status: "error" };
86
+ // All polls failed
87
+ return {
88
+ data: {},
89
+ status: "pending",
90
+ };
91
+ }
92
+ async cancelPayment(input) {
93
+ // TODO: Cancel payment
94
+ this.deps.logger.info("Cancel payment");
95
+ return {
96
+ data: {},
97
+ };
98
+ }
99
+ async capturePayment(input) {
100
+ // TODO: Capture payment
101
+ this.deps.logger.info("Capture payment");
102
+ return { data: {} };
103
+ }
104
+ async getPaymentStatus(input) {
105
+ // TODO: Get payment status
106
+ this.deps.logger.info(`Get payment status`);
107
+ const transactionId = input.data?.id;
108
+ console.log(`Transaction ID ${transactionId}`);
109
+ const response = await fetch(`${BASE_API_URL}/transactionStatus/status/${transactionId}`, {
110
+ method: "GET",
111
+ headers: {
112
+ "Content-Type": "application/json",
113
+ Authorization: `Bearer ${this.options.apiKey}`,
114
+ },
115
+ });
116
+ if (!response.ok) {
117
+ console.log("An error from the response");
118
+ return { status: "error" };
119
+ }
120
+ const data = (await response.json());
121
+ console.log("Status data");
122
+ console.log(data);
123
+ switch (data.data.StatutWonya) {
124
+ case "Echec":
125
+ return { status: "canceled" };
126
+ case "pending":
127
+ case "Attente":
128
+ return { status: "pending" };
129
+ case "Reçu":
130
+ case "Succes":
131
+ return { status: "authorized" };
132
+ default:
133
+ return { status: "error" };
134
+ }
135
+ }
136
+ async initiatePayment(input) {
137
+ // TODO: Initiate payment session
138
+ this.deps.logger.info("Initiate payment");
139
+ const { amount, currency_code, data: customerDetails } = input;
140
+ console.log(input);
141
+ return { id: "", data: { amount, currency_code, customerDetails } };
142
+ }
143
+ async refundPayment(input) {
144
+ // TODO: Initiate refund payment
145
+ this.deps.logger.info("Initiate refund");
146
+ return { data: {} };
147
+ }
148
+ async retrievePayment(input) {
149
+ // TODO: Retrieve payment
150
+ this.deps.logger.info("Retrieve payment");
151
+ return { data: {} };
152
+ }
153
+ async getWebhookActionAndData(data) {
154
+ // TODO: Get webhook action and data
155
+ this.deps.logger.info("Get webhook action and data");
156
+ return { action: "authorized" };
157
+ }
158
+ async updatePayment(input) {
159
+ // TODO: Update payment
160
+ this.deps.logger.info("Update payment");
161
+ return {};
162
+ }
163
+ async deletePayment(input) {
164
+ // TODO: Delete payment
165
+ this.deps.logger.info("Delete payment");
166
+ return {};
167
+ }
168
+ }
169
+ WonyaPayProviderService.identifier = "payment-wonyapay";
170
+ exports.default = WonyaPayProviderService;
171
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvd29ueWFwYXkvc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHFEQUFpRjtBQXdCakYsbUNBQXVEO0FBRXZELE1BQU0sWUFBWSxHQUFHLCtCQUErQixDQUFDO0FBRXJELE1BQU0sdUJBQXdCLFNBQVEsK0JBQWdDO0lBR3BFLFlBQ1UsSUFBMEIsRUFDMUIsT0FBZ0I7UUFFeEIsS0FBSyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUhiLFNBQUksR0FBSixJQUFJLENBQXNCO1FBQzFCLFlBQU8sR0FBUCxPQUFPLENBQVM7UUFJeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztJQUVELE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBeUI7UUFDOUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksbUJBQVcsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUMzRSxDQUFDO1FBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksbUJBQVcsQ0FBQyxtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztRQUM5RSxDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxLQUE0QjtRQUNqRCwwQkFBMEI7UUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDM0MsTUFBTSxTQUFTLEdBQUcsSUFBQSw2QkFBcUIsR0FBRSxDQUFDO1FBRTFDLE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsWUFBWSxVQUFVLEVBQUU7WUFD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
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3dvbnlhcGF5L3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sleep = void 0;
4
+ exports.generateTransactionId = generateTransactionId;
5
+ const CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
6
+ function generateTransactionId(length = 20) {
7
+ const array = new Uint8Array(length);
8
+ crypto.getRandomValues(array);
9
+ return Array.from(array, (byte) => CHARS[byte % CHARS.length]).join("");
10
+ }
11
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
12
+ exports.sleep = sleep;
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3dvbnlhcGF5L3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLHNEQUtDO0FBUEQsTUFBTSxLQUFLLEdBQUcsc0NBQXNDLENBQUM7QUFFckQsU0FBZ0IscUJBQXFCLENBQUMsU0FBaUIsRUFBRTtJQUN2RCxNQUFNLEtBQUssR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNyQyxNQUFNLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTlCLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzFFLENBQUM7QUFFTSxNQUFNLEtBQUssR0FBRyxDQUFDLEVBQVUsRUFBRSxFQUFFLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUExRSxRQUFBLEtBQUssU0FBcUUifQ==
package/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # WonYaSoft Payment Plugin for Medusa
2
+
3
+ <div align="center">
4
+
5
+ [![npm version][npm-version]][npm-version-url]
6
+ [![License][license]][license-url]
7
+ [![Medusa v2][medusa-badge]][medusa-url]
8
+ [![Node.js >=20][node-badge]][node-url]
9
+ [![Under Active Development][dev-badge]][dev-badge]
10
+ [![TypeScript][typescript-badge]][typescript-url]
11
+ [![WonYaSoft Payment][wonyapay-badge]][wonyapay-url]
12
+
13
+ </div>
14
+
15
+ > :warning: **Under Active Development** - This plugin is currently being developed and is not yet production-ready.
16
+
17
+ A Medusa v2 payment plugin for WonYaSoft (WonyaPay) - Mobile Money payment solutions for the Democratic Republic of Congo.
18
+
19
+ ---
20
+
21
+ ## Table of Contents
22
+
23
+ - [Features](#features)
24
+ - [Requirements](#requirements)
25
+ - [Installation](#installation)
26
+ - [Configuration](#configuration)
27
+ - [Payment Flow](#payment-flow)
28
+ - [API Usage](#api-usage)
29
+ - [Supported Providers](#supported-providers)
30
+ - [Development](#development)
31
+ - [Known Limitations](#known-limitations)
32
+ - [Troubleshooting](#troubleshooting)
33
+ - [Support](#support)
34
+ - [License](#license)
35
+
36
+ ---
37
+
38
+ ## Features
39
+
40
+ - **Mobile Money Support**: M-Pesa, Airtel Money, Orange Money, AfriMoney
41
+ - **Currency Support**: CDF (Congolese Franc) and USD
42
+ - **C2B Payments**: Collect payments from customers via Mobile Money
43
+ - **B2C Payments**: Process refunds to customer Mobile Money accounts
44
+ - **Automatic Authorization**: Built-in polling for payment confirmation
45
+ - **Transaction Status**: Real-time status checking
46
+
47
+ ## Requirements
48
+
49
+ | Requirement | Version |
50
+ |------------|---------|
51
+ | Medusa | v2.x |
52
+ | Node.js | >= 20 |
53
+ | Medusa CLI | 2.x |
54
+
55
+ ## Installation
56
+
57
+ ```bash
58
+ npm install @erulabs-tech/medusa-plugin-wonyapay
59
+ # or
60
+ pnpm add @erulabs-tech/medusa-plugin-wonyapay
61
+ ```
62
+
63
+ ## Configuration
64
+
65
+ ### 1. Add to `medusa-config.ts`
66
+
67
+ ```typescript
68
+ module.exports = defineConfig({
69
+ // ... other config
70
+ modules: [
71
+ {
72
+ resolve: "@medusajs/medusa/payment",
73
+ options: {
74
+ providers: [
75
+ {
76
+ resolve: "@erulabs-tech/medusa-plugin-wonyapay/providers/wonyapay",
77
+ id: "payment-wonyapay",
78
+ options: {
79
+ apiKey: process.env.WONYAPAY_API_KEY,
80
+ defaultReceiverID: process.env.WONYAPAY_DEFAULT_RECEIVER_ID,
81
+ baseUrl: process.env.WONYAPAY_BASE_URL,
82
+ },
83
+ },
84
+ ],
85
+ },
86
+ },
87
+ ],
88
+ });
89
+ ```
90
+
91
+ ### 2. Environment Variables
92
+
93
+ Create a `.env` file with:
94
+
95
+ ```env
96
+ # WonYaSoft Payment Configuration
97
+ WONYAPAY_API_KEY=your_api_key_here
98
+ WONYAPAY_DEFAULT_RECEIVER_ID=your_receiver_id_here
99
+ WONYAPAY_BASE_URL=https://app-api.wonyasoft.com
100
+ ```
101
+
102
+ ## Environment Variables Reference
103
+
104
+ | Variable | Required | Description | Default |
105
+ |----------|----------|-------------|---------|
106
+ | `WONYAPAY_API_KEY` | Yes | Your WonYaSoft API key (Bearer token) | - |
107
+ | `WONYAPAY_DEFAULT_RECEIVER_ID` | Yes | Your merchant receiver ID | - |
108
+ | `WONYAPAY_BASE_URL` | No | WonYaSoft API base URL | `https://app-api.wonyasoft.com` |
109
+
110
+ ## Payment Flow
111
+
112
+ ```
113
+ ┌─────────────────────────────────────────────────────────────────┐
114
+ │ Payment Flow │
115
+ ├─────────────────────────────────────────────────────────────────┤
116
+ │ │
117
+ │ 1. Customer selects "Mobile Money" at checkout │
118
+ │ │
119
+ │ 2. Customer enters: │
120
+ │ - Phone number (Mobile Money account) │
121
+ │ - Provider (M-Pesa, Airtel, Orange, AfriMoney) │
122
+ │ │
123
+ │ 3. initiatePayment() → POST /payment │
124
+ │ - Creates transaction │
125
+ │ - Sends USSD prompt to customer phone │
126
+ │ │
127
+ │ 4. authorizePayment() → Polls for confirmation │
128
+ │ ┌─────────────────────────────────────────────────────────┐ │
129
+ │ │ Poll 1: 60 seconds after initiatePayment │ │
130
+ │ │ Poll 2: 30 seconds after Poll 1 │ │
131
+ │ │ Poll 3: 30 seconds after Poll 2 │ │
132
+ │ │ Max wait: 2 minutes │ │
133
+ │ └─────────────────────────────────────────────────────────┘ │
134
+ │ │
135
+ │ 5. Customer confirms payment on phone (enters PIN) │
136
+ │ │
137
+ │ 6. Payment authorized → Order completed │
138
+ │ │
139
+ │ 7. If polls exhausted without confirmation → Payment failed │
140
+ │ │
141
+ └─────────────────────────────────────────────────────────────────┘
142
+ ```
143
+
144
+ ## API Usage
145
+
146
+ ### Create Payment Session
147
+
148
+ ```bash
149
+ POST /store/payment-collections/:id/payment-sessions
150
+ Content-Type: application/json
151
+ x-publishable-api-key: pk_...
152
+
153
+ {
154
+ "provider_id": "payment-wonyapay",
155
+ "data": {
156
+ "senderPhone": "+243851858485",
157
+ "mobileProvider": "mpesa"
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Request Body Parameters
163
+
164
+ | Parameter | Type | Required | Description |
165
+ |-----------|------|----------|-------------|
166
+ | `senderPhone` | string | Yes | Customer's Mobile Money phone number |
167
+ | `mobileProvider` | string | No | Provider: `mpesa`, `airtel`, `orange`, `afrimoney` |
168
+
169
+ ### Using Medusa JS SDK
170
+
171
+ ```typescript
172
+ // Create payment session with Mobile Money details
173
+ await sdk.store.paymentCollection.createPaymentSession(
174
+ paymentCollectionId,
175
+ {
176
+ provider_id: "payment-wonyapay",
177
+ data: {
178
+ senderPhone: "+243851858485",
179
+ mobileProvider: "mpesa",
180
+ },
181
+ }
182
+ );
183
+
184
+ // Complete payment (triggers authorizePayment)
185
+ await sdk.store.cart.complete(cartId);
186
+ ```
187
+
188
+ ### cURL Example
189
+
190
+ ```bash
191
+ curl -X POST http://localhost:9000/store/payment-collections/paycol_123/payment-sessions \
192
+ -H "Content-Type: application/json" \
193
+ -H "x-publishable-api-key: pk_your_key" \
194
+ -d '{
195
+ "provider_id": "payment-wonyapay",
196
+ "data": {
197
+ "senderPhone": "+243851858485",
198
+ "mobileProvider": "mpesa"
199
+ }
200
+ }'
201
+ ```
202
+
203
+ ## Supported Providers
204
+
205
+ | Provider | Code | Status |
206
+ |----------|------|--------|
207
+ | M-Pesa | `mpesa` | :white_check_mark: Supported |
208
+ | Airtel Money | `airtel` | :white_check_mark: Supported |
209
+ | Orange Money | `orange` | :white_check_mark: Supported |
210
+ | AfriMoney | `afrimoney` | :white_check_mark: Supported |
211
+
212
+ ## Supported Currencies
213
+
214
+ | Currency | Code | Description |
215
+ |----------|------|-------------|
216
+ | Congolese Franc | `CDF` | Default currency |
217
+ | US Dollar | `USD` | Supported |
218
+
219
+ ## WonYaSoft API Endpoints
220
+
221
+ | Endpoint | Method | Description |
222
+ |----------|--------|-------------|
223
+ | `/payment` | POST | Initiate payment (C2B/B2C) |
224
+ | `/transactionStatus/status/:ref` | GET | Check transaction status |
225
+
226
+ ## Error Handling
227
+
228
+ ### Payment Status Mapping
229
+
230
+ | WonYaSoft Status | Medusa Status | Description |
231
+ |------------------|---------------|-------------|
232
+ | `success` | `authorized` | Payment confirmed |
233
+ | `pending` | `pending` | Awaiting confirmation |
234
+ | `failed` | `error` | Payment failed |
235
+ | `cancelled` | `canceled` | Customer cancelled |
236
+
237
+ ### Error Scenarios
238
+
239
+ | Scenario | Result | Action |
240
+ |----------|--------|--------|
241
+ | Customer doesn't confirm within 2 minutes | `error` | Customer must retry |
242
+ | Invalid phone number | `error` | Check and retry |
243
+ | Insufficient funds | `error` | Customer must add funds |
244
+ | API failure | `error` | Check API credentials |
245
+
246
+ ## Development
247
+
248
+ ### Prerequisites
249
+
250
+ - Node.js >= 20
251
+ - Medusa v2.x
252
+ - WonYaSoft API credentials
253
+
254
+ ### Build
255
+
256
+ ```bash
257
+ npm run build
258
+ ```
259
+
260
+ ### Watch Mode
261
+
262
+ ```bash
263
+ npm run dev
264
+ ```
265
+
266
+ ### Testing
267
+
268
+ ```bash
269
+ npm run test
270
+ ```
271
+
272
+ ## Known Limitations
273
+
274
+ > :warning: **Under Active Development** - The following features are planned:
275
+
276
+ - [ ] Webhook support for instant notifications
277
+ - [ ] Admin dashboard configuration
278
+ - [ ] Payment retry mechanism
279
+ - [ ] Transaction history in admin
280
+ - [ ] SMS notifications for payment status
281
+ - [ ] Multiple receiver ID support
282
+
283
+ ## Troubleshooting
284
+
285
+ ### Payment stuck in "pending"
286
+
287
+ The customer may not have confirmed the payment on their phone. The payment will auto-fail after 2 minutes.
288
+
289
+ ### "Invalid phone number" error
290
+
291
+ Ensure the phone number:
292
+ - Starts with country code (e.g., `+243` for DRC)
293
+ - Is registered with a Mobile Money provider
294
+ - Has sufficient funds
295
+
296
+ ### API connection errors
297
+
298
+ 1. Verify `WONYAPAY_API_KEY` is correct
299
+ 2. Verify `WONYAPAY_DEFAULT_RECEIVER_ID` is correct
300
+ 3. Check network connectivity to WonYaSoft API
301
+
302
+ ## Support
303
+
304
+ - **Email**: contact@wonso.cd
305
+ - **Phone**: +243 892 672 472
306
+ - **Website**: https://wonyasoft.com
307
+
308
+ ## License
309
+
310
+ This project is licensed under the MIT License.
311
+
312
+ ---
313
+
314
+ <!-- Badges -->
315
+ [npm-version]: https://img.shields.io/npm/v/@erulabs-tech/medusa-plugin-wonyapay?style=flat
316
+ [npm-version-url]: https://www.npmjs.com/package/@erulabs-tech/medusa-plugin-wonyapay
317
+ [license]: https://img.shields.io/badge/license-MIT-green?style=flat
318
+ [license-url]: https://opensource.org/licenses/MIT
319
+ [medusa-badge]: https://img.shields.io/badge/Medusa-v2-blue?style=flat
320
+ [medusa-url]: https://medusajs.com
321
+ [node-badge]: https://img.shields.io/badge/node-%3E%3D20-brightgreen?style=flat
322
+ [node-url]: https://nodejs.org
323
+ [dev-badge]: https://img.shields.io/badge/development-active-orange?style=flat
324
+ [typescript-badge]: https://img.shields.io/badge/TypeScript-blue?style=flat
325
+ [typescript-url]: https://www.typescriptlang.org
326
+ [wonyapay-badge]: https://img.shields.io/badge/WonYaPay-Mobile%20Money-red?style=flat
327
+ [wonyapay-url]: https://wonyasoft.com
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@erulabs-tech/medusa-plugin-wonyapay",
3
+ "version": "0.0.1",
4
+ "description": "A starter for Medusa plugins.",
5
+ "keywords": [
6
+ "medusa",
7
+ "medusa-plugin",
8
+ "medusa-plugin-other",
9
+ "medusa-v2",
10
+ "plugin"
11
+ ],
12
+ "license": "MIT",
13
+ "author": "Medusa (https://medusajs.com)",
14
+ "files": [
15
+ ".medusa/server"
16
+ ],
17
+ "exports": {
18
+ "./package.json": "./package.json",
19
+ "./workflows": "./.medusa/server/src/workflows/index.js",
20
+ "./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
21
+ "./modules/*": "./.medusa/server/src/modules/*/index.js",
22
+ "./providers/*": "./.medusa/server/src/providers/*/index.js",
23
+ "./*": "./.medusa/server/src/*.js",
24
+ "./admin": {
25
+ "import": "./.medusa/server/src/admin/index.mjs",
26
+ "require": "./.medusa/server/src/admin/index.js",
27
+ "default": "./.medusa/server/src/admin/index.js"
28
+ }
29
+ },
30
+ "devDependencies": {
31
+ "@medusajs/admin-sdk": "2.12.4",
32
+ "@medusajs/cli": "2.12.4",
33
+ "@medusajs/framework": "2.12.4",
34
+ "@medusajs/icons": "2.12.4",
35
+ "@medusajs/medusa": "2.12.4",
36
+ "@medusajs/test-utils": "2.12.4",
37
+ "@medusajs/ui": "4.0.25",
38
+ "@swc/core": "^1.7.28",
39
+ "@types/node": "^20.0.0",
40
+ "@types/react": "^18.3.2",
41
+ "@types/react-dom": "^18.2.25",
42
+ "prop-types": "^15.8.1",
43
+ "react": "^18.2.0",
44
+ "react-dom": "^18.2.0",
45
+ "ts-node": "^10.9.2",
46
+ "typescript": "^5.6.2",
47
+ "vite": "^5.2.11",
48
+ "yalc": "^1.0.0-pre.53"
49
+ },
50
+ "peerDependencies": {
51
+ "@medusajs/admin-sdk": "2.12.4",
52
+ "@medusajs/cli": "2.12.4",
53
+ "@medusajs/framework": "2.12.4",
54
+ "@medusajs/icons": "2.12.4",
55
+ "@medusajs/medusa": "2.12.4",
56
+ "@medusajs/test-utils": "2.12.4",
57
+ "@medusajs/ui": "4.0.25"
58
+ },
59
+ "engines": {
60
+ "node": ">=20"
61
+ },
62
+ "scripts": {
63
+ "build": "medusa plugin:build",
64
+ "dev": "medusa plugin:develop"
65
+ }
66
+ }