medusa-paystack-plugin 0.1.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.
- package/.medusa/server/src/admin/index.js +135 -0
- package/.medusa/server/src/admin/index.mjs +134 -0
- package/.medusa/server/src/api/middlewares.js +9 -0
- package/.medusa/server/src/api/store/paystack/config/middlewares.js +13 -0
- package/.medusa/server/src/api/store/paystack/config/route.js +15 -0
- package/.medusa/server/src/api/store/paystack/validators.js +33 -0
- package/.medusa/server/src/api/store/paystack/webview/html.js +178 -0
- package/.medusa/server/src/api/store/paystack/webview/middlewares.js +13 -0
- package/.medusa/server/src/api/store/paystack/webview/route.js +27 -0
- package/.medusa/server/src/constants.js +9 -0
- package/.medusa/server/src/frontend.js +147 -0
- package/.medusa/server/src/lib/paystack-client.js +39 -0
- package/.medusa/server/src/lib/paystack-utils.js +59 -0
- package/.medusa/server/src/lib/plugin-config.js +56 -0
- package/.medusa/server/src/lib/store.js +36 -0
- package/.medusa/server/src/providers/paystack/index.js +11 -0
- package/.medusa/server/src/providers/paystack/service.js +150 -0
- package/.medusa/server/src/types.js +3 -0
- package/README.md +209 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Medusa Paystack Browser Plugin
|
|
2
|
+
|
|
3
|
+
Medusa v2 plugin for Paystack with:
|
|
4
|
+
|
|
5
|
+
- a per-store admin widget for the Paystack publishable key
|
|
6
|
+
- a public config route for storefronts and mobile apps
|
|
7
|
+
- a hosted webview checkout route that loads Paystack InlineJS v2
|
|
8
|
+
- a frontend helper export for browser checkout
|
|
9
|
+
- an optional verified Medusa payment provider for installs that also configure a Paystack secret key
|
|
10
|
+
|
|
11
|
+
## Modes
|
|
12
|
+
|
|
13
|
+
### Helper mode
|
|
14
|
+
|
|
15
|
+
Helper mode only needs the Paystack publishable key.
|
|
16
|
+
|
|
17
|
+
It gives you:
|
|
18
|
+
|
|
19
|
+
- `store.metadata.paystack_publishable_key`
|
|
20
|
+
- `GET /store/paystack/config`
|
|
21
|
+
- `GET /store/paystack/webview`
|
|
22
|
+
- `medusa-paystack-plugin/frontend` helper functions
|
|
23
|
+
|
|
24
|
+
In helper mode, the browser `onSuccess(transaction)` callback is only a UX signal. The plugin does not mark a Medusa order as paid from the client callback alone.
|
|
25
|
+
|
|
26
|
+
### Verified mode
|
|
27
|
+
|
|
28
|
+
Verified mode uses the same browser checkout flow, but also registers the optional payment provider with a Paystack `secret_key`.
|
|
29
|
+
|
|
30
|
+
In verified mode:
|
|
31
|
+
|
|
32
|
+
- the browser success callback triggers `sdk.store.cart.complete(cart.id)`
|
|
33
|
+
- the provider verifies the Paystack transaction reference server-side
|
|
34
|
+
- Medusa only completes the cart when verification succeeds
|
|
35
|
+
- refunds use the stored Paystack transaction id
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install medusa-paystack-plugin
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Register the plugin in your Medusa app:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
module.exports = defineConfig({
|
|
47
|
+
plugins: [
|
|
48
|
+
{
|
|
49
|
+
resolve: "medusa-paystack-plugin",
|
|
50
|
+
options: {},
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If you want verified Medusa payment completion, also register the provider:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
module.exports = defineConfig({
|
|
60
|
+
plugins: [
|
|
61
|
+
{
|
|
62
|
+
resolve: "medusa-paystack-plugin",
|
|
63
|
+
options: {
|
|
64
|
+
secret_key: process.env.PAYSTACK_SECRET_KEY,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
modules: [
|
|
69
|
+
{
|
|
70
|
+
resolve: "@medusajs/medusa/payment",
|
|
71
|
+
options: {
|
|
72
|
+
providers: [
|
|
73
|
+
{
|
|
74
|
+
resolve: "medusa-paystack-plugin/providers/paystack",
|
|
75
|
+
id: "paystack",
|
|
76
|
+
options: {
|
|
77
|
+
secret_key: process.env.PAYSTACK_SECRET_KEY,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Admin setup
|
|
88
|
+
|
|
89
|
+
After the plugin is installed, open the store details page in Medusa Admin. A `Paystack` widget is injected into `store.details.after`.
|
|
90
|
+
|
|
91
|
+
Save the store-specific publishable key there. The widget stores it in:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
store.metadata.paystack_publishable_key
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Store routes
|
|
98
|
+
|
|
99
|
+
### `GET /store/paystack/config`
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"store_id": "store_123",
|
|
106
|
+
"publishable_key": "pk_test_xxx",
|
|
107
|
+
"verified_mode_enabled": true
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
If your Medusa installation has more than one store, pass `store_id`.
|
|
112
|
+
|
|
113
|
+
### `GET /store/paystack/webview`
|
|
114
|
+
|
|
115
|
+
Returns a minimal HTML page that loads Paystack InlineJS and starts checkout inside a mobile webview or popup-style browser window.
|
|
116
|
+
|
|
117
|
+
Supported query params:
|
|
118
|
+
|
|
119
|
+
- `store_id`
|
|
120
|
+
- `email`
|
|
121
|
+
- `amount`
|
|
122
|
+
- `currency`
|
|
123
|
+
- `reference`
|
|
124
|
+
- `callback_url`
|
|
125
|
+
- `metadata`
|
|
126
|
+
- `channels`
|
|
127
|
+
- `first_name`
|
|
128
|
+
- `last_name`
|
|
129
|
+
- `phone`
|
|
130
|
+
|
|
131
|
+
On success, cancel, or error the page:
|
|
132
|
+
|
|
133
|
+
- posts a message with source `medusa-paystack-webview`
|
|
134
|
+
- redirects to `callback_url` when provided
|
|
135
|
+
|
|
136
|
+
## Frontend helper
|
|
137
|
+
|
|
138
|
+
Import the helper:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import {
|
|
142
|
+
buildPaystackReference,
|
|
143
|
+
buildPaystackWebviewUrl,
|
|
144
|
+
createPaystackSuccessHandler,
|
|
145
|
+
fetchPaystackConfig,
|
|
146
|
+
launchPaystackCheckout,
|
|
147
|
+
} from "medusa-paystack-plugin/frontend"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Storefront checkout example
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
const config = await fetchPaystackConfig({
|
|
154
|
+
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL,
|
|
155
|
+
storeId: "store_123",
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
const onSuccess = createPaystackSuccessHandler({
|
|
159
|
+
mode: config.verified_mode_enabled ? "verified" : "helper",
|
|
160
|
+
cartId: cart.id,
|
|
161
|
+
sdk,
|
|
162
|
+
redirectUrl: `${window.location.origin}/checkout/complete`,
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
await launchPaystackCheckout({
|
|
166
|
+
key: config.publishable_key,
|
|
167
|
+
email: cart.email!,
|
|
168
|
+
amount: paymentSession.amount,
|
|
169
|
+
currency: paymentSession.currency_code,
|
|
170
|
+
reference:
|
|
171
|
+
(paymentSession.data as { paystack_reference?: string })?.paystack_reference ??
|
|
172
|
+
buildPaystackReference(),
|
|
173
|
+
metadata: {
|
|
174
|
+
cart_id: cart.id,
|
|
175
|
+
},
|
|
176
|
+
successHandler: onSuccess,
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Mobile webview example
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
const webviewUrl = buildPaystackWebviewUrl({
|
|
184
|
+
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL,
|
|
185
|
+
callbackUrl: "myapp://checkout/complete",
|
|
186
|
+
currency: cart.currency_code,
|
|
187
|
+
email: cart.email!,
|
|
188
|
+
amount: cart.total,
|
|
189
|
+
metadata: {
|
|
190
|
+
cart_id: cart.id,
|
|
191
|
+
},
|
|
192
|
+
storeId: "store_123",
|
|
193
|
+
})
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Load that URL in your mobile webview and listen for the `medusa-paystack-webview` message payload or the redirect to your callback URL.
|
|
197
|
+
|
|
198
|
+
## Development
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
npm run typecheck
|
|
202
|
+
npm test
|
|
203
|
+
npm run build
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Notes
|
|
207
|
+
|
|
208
|
+
- This package uses the Medusa v2 plugin scaffold and exports `./providers/paystack` plus `./frontend`.
|
|
209
|
+
- If `npm run build` fails because your local Medusa CLI install is incomplete, reinstall dependencies cleanly and rerun the build.
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "medusa-paystack-plugin",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Medusa v2 Paystack plugin with per-store publishable key settings, storefront helpers, and an optional verified payment provider.",
|
|
5
|
+
"author": "Medusa plugin scaffold extended for Paystack",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"files": [
|
|
8
|
+
".medusa/server"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
"./workflows": "./.medusa/server/src/workflows/index.js",
|
|
13
|
+
"./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
14
|
+
"./modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
15
|
+
"./providers/*": "./.medusa/server/src/providers/*/index.js",
|
|
16
|
+
"./*": "./.medusa/server/src/*.js",
|
|
17
|
+
"./admin": {
|
|
18
|
+
"import": "./.medusa/server/src/admin/index.mjs",
|
|
19
|
+
"require": "./.medusa/server/src/admin/index.js",
|
|
20
|
+
"default": "./.medusa/server/src/admin/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"medusa",
|
|
25
|
+
"medusa-plugin",
|
|
26
|
+
"medusa-plugin-integration",
|
|
27
|
+
"medusa-plugin-payment",
|
|
28
|
+
"medusa-v2",
|
|
29
|
+
"paystack"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "node ./node_modules/@medusajs/cli/cli.js plugin:build",
|
|
33
|
+
"dev": "node ./node_modules/@medusajs/cli/cli.js plugin:develop",
|
|
34
|
+
"prepublishOnly": "node ./node_modules/@medusajs/cli/cli.js plugin:build",
|
|
35
|
+
"test": "node --test -r ts-node/register/transpile-only src/tests/**/*.spec.ts",
|
|
36
|
+
"typecheck": "tsc --noEmit"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"zod": "^3.25.76"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@medusajs/admin-sdk": "2.13.3",
|
|
43
|
+
"@medusajs/cli": "2.13.3",
|
|
44
|
+
"@medusajs/framework": "2.13.3",
|
|
45
|
+
"@medusajs/icons": "2.13.3",
|
|
46
|
+
"@medusajs/js-sdk": "2.13.3",
|
|
47
|
+
"@medusajs/medusa": "2.13.3",
|
|
48
|
+
"@medusajs/test-utils": "2.13.3",
|
|
49
|
+
"@medusajs/ui": "4.1.3",
|
|
50
|
+
"@swc/core": "^1.15.18",
|
|
51
|
+
"@tanstack/react-query": "5.64.2",
|
|
52
|
+
"@types/node": "^20.17.24",
|
|
53
|
+
"@types/react": "^18.3.20",
|
|
54
|
+
"@types/react-dom": "^18.3.6",
|
|
55
|
+
"react": "^18.3.1",
|
|
56
|
+
"react-dom": "^18.3.1",
|
|
57
|
+
"ts-node": "^10.9.2",
|
|
58
|
+
"typescript": "^5.8.2",
|
|
59
|
+
"vite": "^5.4.14",
|
|
60
|
+
"yalc": "^1.0.0-pre.53"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"@medusajs/admin-sdk": "2.13.3",
|
|
64
|
+
"@medusajs/cli": "2.13.3",
|
|
65
|
+
"@medusajs/framework": "2.13.3",
|
|
66
|
+
"@medusajs/icons": "2.13.3",
|
|
67
|
+
"@medusajs/medusa": "2.13.3",
|
|
68
|
+
"@medusajs/test-utils": "2.13.3",
|
|
69
|
+
"@medusajs/ui": "4.1.3"
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=20"
|
|
73
|
+
},
|
|
74
|
+
"packageManager": "npm@10.9.2"
|
|
75
|
+
}
|