medusa-paystack 0.1.0 → 0.2.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/.medusa/server/src/providers/paystack/index.d.ts +2 -0
- package/.medusa/server/src/providers/paystack/index.js +10 -5
- package/.medusa/server/src/providers/paystack/lib.d.ts +68 -0
- package/.medusa/server/src/providers/paystack/lib.js +18 -10
- package/.medusa/server/src/providers/paystack/service.d.ts +35 -0
- package/.medusa/server/src/providers/paystack/service.js +37 -15
- package/AGENTS.md +10 -0
- package/README.md +27 -0
- package/package.json +15 -3
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
7
|
+
const service_1 = __importDefault(require("./service"));
|
|
8
|
+
exports.default = (0, utils_1.ModuleProvider)(utils_1.Modules.PAYMENT, {
|
|
9
|
+
services: [service_1.default],
|
|
5
10
|
});
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3BheXN0YWNrL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscURBQW9FO0FBQ3BFLHdEQUFnRDtBQUVoRCxrQkFBZSxJQUFBLHNCQUFjLEVBQUMsZUFBTyxDQUFDLE9BQU8sRUFBRTtJQUM3QyxRQUFRLEVBQUUsQ0FBQyxpQkFBdUIsQ0FBQztDQUNwQyxDQUFDLENBQUMifQ==
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export declare function verifyPaystackSignature(rawBody: string, signature: string, secret: string): boolean;
|
|
2
|
+
export type WebhookEventData = {
|
|
3
|
+
reference?: string;
|
|
4
|
+
amount?: number;
|
|
5
|
+
metadata?: {
|
|
6
|
+
session_id?: string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export type WebhookActionOutput = {
|
|
10
|
+
action: "captured";
|
|
11
|
+
data: {
|
|
12
|
+
session_id: string;
|
|
13
|
+
amount: number;
|
|
14
|
+
};
|
|
15
|
+
} | {
|
|
16
|
+
action: "not_supported";
|
|
17
|
+
};
|
|
18
|
+
export declare function webhookAction(eventName: string | undefined, eventData: WebhookEventData, signatureValid: boolean): WebhookActionOutput;
|
|
19
|
+
export declare function assertChargeMatches(args: {
|
|
20
|
+
status: string;
|
|
21
|
+
amount: number;
|
|
22
|
+
currency: string;
|
|
23
|
+
expectedAmount: number;
|
|
24
|
+
expectedCurrency: string;
|
|
25
|
+
}): {
|
|
26
|
+
ok: true;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
reason: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function makeReference(seed: string, prefix?: string): string;
|
|
32
|
+
export declare function buildInitializePayload(args: {
|
|
33
|
+
amount: number;
|
|
34
|
+
currencyCode: string;
|
|
35
|
+
email: string;
|
|
36
|
+
reference: string;
|
|
37
|
+
sessionId?: string;
|
|
38
|
+
}): {
|
|
39
|
+
email: string;
|
|
40
|
+
amount: number;
|
|
41
|
+
currency: string;
|
|
42
|
+
reference: string;
|
|
43
|
+
metadata: {
|
|
44
|
+
session_id?: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export declare function buildRefundPayload(reference: string, amount: number): {
|
|
48
|
+
transaction: string;
|
|
49
|
+
amount: number;
|
|
50
|
+
};
|
|
51
|
+
export type PaystackInitResponse = {
|
|
52
|
+
status: boolean;
|
|
53
|
+
message: string;
|
|
54
|
+
data?: {
|
|
55
|
+
access_code: string;
|
|
56
|
+
reference: string;
|
|
57
|
+
authorization_url: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export type PaystackVerifyResponse = {
|
|
61
|
+
status: boolean;
|
|
62
|
+
data?: {
|
|
63
|
+
status: string;
|
|
64
|
+
amount: number;
|
|
65
|
+
currency: string;
|
|
66
|
+
reference: string;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyPaystackSignature = verifyPaystackSignature;
|
|
4
|
+
exports.webhookAction = webhookAction;
|
|
5
|
+
exports.assertChargeMatches = assertChargeMatches;
|
|
6
|
+
exports.makeReference = makeReference;
|
|
7
|
+
exports.buildInitializePayload = buildInitializePayload;
|
|
8
|
+
exports.buildRefundPayload = buildRefundPayload;
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
function verifyPaystackSignature(rawBody, signature, secret) {
|
|
11
|
+
const expected = (0, crypto_1.createHmac)("sha512", secret).update(rawBody, "utf8").digest("hex");
|
|
4
12
|
if (expected.length !== signature.length)
|
|
5
13
|
return false;
|
|
6
14
|
try {
|
|
7
|
-
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
|
|
15
|
+
return (0, crypto_1.timingSafeEqual)(Buffer.from(expected), Buffer.from(signature));
|
|
8
16
|
}
|
|
9
17
|
catch {
|
|
10
18
|
return false;
|
|
11
19
|
}
|
|
12
20
|
}
|
|
13
|
-
|
|
21
|
+
function webhookAction(eventName, eventData, signatureValid) {
|
|
14
22
|
if (!signatureValid)
|
|
15
23
|
return { action: "not_supported" };
|
|
16
24
|
if (eventName === "charge.success") {
|
|
@@ -24,7 +32,7 @@ export function webhookAction(eventName, eventData, signatureValid) {
|
|
|
24
32
|
}
|
|
25
33
|
return { action: "not_supported" };
|
|
26
34
|
}
|
|
27
|
-
|
|
35
|
+
function assertChargeMatches(args) {
|
|
28
36
|
if (args.status !== "success")
|
|
29
37
|
return { ok: false, reason: `status ${args.status}` };
|
|
30
38
|
if (args.currency.toUpperCase() !== args.expectedCurrency.toUpperCase())
|
|
@@ -33,10 +41,10 @@ export function assertChargeMatches(args) {
|
|
|
33
41
|
return { ok: false, reason: `amount ${args.amount} != ${args.expectedAmount}` };
|
|
34
42
|
return { ok: true };
|
|
35
43
|
}
|
|
36
|
-
|
|
44
|
+
function makeReference(seed, prefix = "") {
|
|
37
45
|
return `${prefix}${seed}`;
|
|
38
46
|
}
|
|
39
|
-
|
|
47
|
+
function buildInitializePayload(args) {
|
|
40
48
|
return {
|
|
41
49
|
email: args.email,
|
|
42
50
|
amount: Math.round(args.amount * 100),
|
|
@@ -45,7 +53,7 @@ export function buildInitializePayload(args) {
|
|
|
45
53
|
metadata: { session_id: args.sessionId },
|
|
46
54
|
};
|
|
47
55
|
}
|
|
48
|
-
|
|
56
|
+
function buildRefundPayload(reference, amount) {
|
|
49
57
|
return { transaction: reference, amount: Math.round(amount * 100) };
|
|
50
58
|
}
|
|
51
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy9wYXlzdGFjay9saWIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSwwREFZQztBQVlELHNDQWlCQztBQUVELGtEQWFDO0FBRUQsc0NBRUM7QUFFRCx3REFvQkM7QUFFRCxnREFLQztBQTNGRCxtQ0FBcUQ7QUFFckQsU0FBZ0IsdUJBQXVCLENBQ3JDLE9BQWUsRUFDZixTQUFpQixFQUNqQixNQUFjO0lBRWQsTUFBTSxRQUFRLEdBQUcsSUFBQSxtQkFBVSxFQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNwRixJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQztJQUN2RCxJQUFJLENBQUM7UUFDSCxPQUFPLElBQUEsd0JBQWUsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0FBQ0gsQ0FBQztBQVlELFNBQWdCLGFBQWEsQ0FDM0IsU0FBNkIsRUFDN0IsU0FBMkIsRUFDM0IsY0FBdUI7SUFFdkIsSUFBSSxDQUFDLGNBQWM7UUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxDQUFDO0lBRXhELElBQUksU0FBUyxLQUFLLGdCQUFnQixFQUFFLENBQUM7UUFDbkMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUM7UUFDM0MsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxDQUFDO1FBQzdDLE9BQU87WUFDTCxNQUFNLEVBQUUsVUFBVTtZQUNsQixJQUFJLEVBQUUsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLEdBQUcsR0FBRyxFQUFFO1NBQ2pFLENBQUM7SUFDSixDQUFDO0lBRUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsQ0FBQztBQUNyQyxDQUFDO0FBRUQsU0FBZ0IsbUJBQW1CLENBQUMsSUFNbkM7SUFDQyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUztRQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxVQUFVLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO0lBQ3JGLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsS0FBSyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFO1FBQ3JFLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO0lBQzVELElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsY0FBYztRQUNyQyxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsVUFBVSxJQUFJLENBQUMsTUFBTSxPQUFPLElBQUksQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDO0lBQ2xGLE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFDdEIsQ0FBQztBQUVELFNBQWdCLGFBQWEsQ0FBQyxJQUFZLEVBQUUsTUFBTSxHQUFHLEVBQUU7SUFDckQsT0FBTyxHQUFHLE1BQU0sR0FBRyxJQUFJLEVBQUUsQ0FBQztBQUM1QixDQUFDO0FBRUQsU0FBZ0Isc0JBQXNCLENBQUMsSUFNdEM7SUFPQyxPQUFPO1FBQ0wsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO1FBQ2pCLE1BQU0sRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO1FBQ3JDLFFBQVEsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRTtRQUN6QyxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7UUFDekIsUUFBUSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUU7S0FDekMsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFnQixrQkFBa0IsQ0FDaEMsU0FBaUIsRUFDakIsTUFBYztJQUVkLE9BQU8sRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDO0FBQ3RFLENBQUMifQ==
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AuthorizePaymentInput, AuthorizePaymentOutput, CancelPaymentInput, CancelPaymentOutput, CapturePaymentInput, CapturePaymentOutput, DeletePaymentInput, DeletePaymentOutput, GetPaymentStatusInput, GetPaymentStatusOutput, InitiatePaymentInput, InitiatePaymentOutput, ProviderWebhookPayload, RefundPaymentInput, RefundPaymentOutput, RetrievePaymentInput, RetrievePaymentOutput, UpdatePaymentInput, UpdatePaymentOutput, WebhookActionResult } from "@medusajs/framework/types";
|
|
2
|
+
import { AbstractPaymentProvider } from "@medusajs/framework/utils";
|
|
3
|
+
type PaystackOptions = {
|
|
4
|
+
secret_key?: string;
|
|
5
|
+
reference_prefix?: string;
|
|
6
|
+
};
|
|
7
|
+
declare class PaystackProviderService extends AbstractPaymentProvider<PaystackOptions> {
|
|
8
|
+
static identifier: string;
|
|
9
|
+
protected options_: PaystackOptions;
|
|
10
|
+
protected readonly container_: Record<string, unknown>;
|
|
11
|
+
constructor(cradle: Record<string, unknown>, options: PaystackOptions);
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the amount + currency actually charged at Paystack for a cart.
|
|
14
|
+
* Default: charge the cart's own amount and currency. Override in a subclass
|
|
15
|
+
* to settle in a different currency (e.g. convert every cart to GHS).
|
|
16
|
+
*/
|
|
17
|
+
protected resolveCharge(amount: number, currency_code: string): Promise<{
|
|
18
|
+
amount: number;
|
|
19
|
+
currency: string;
|
|
20
|
+
}>;
|
|
21
|
+
private get secretKey();
|
|
22
|
+
private authHeader;
|
|
23
|
+
initiatePayment(input: InitiatePaymentInput): Promise<InitiatePaymentOutput>;
|
|
24
|
+
authorizePayment(input: AuthorizePaymentInput): Promise<AuthorizePaymentOutput>;
|
|
25
|
+
capturePayment(input: CapturePaymentInput): Promise<CapturePaymentOutput>;
|
|
26
|
+
getPaymentStatus(input: GetPaymentStatusInput): Promise<GetPaymentStatusOutput>;
|
|
27
|
+
refundPayment(input: RefundPaymentInput): Promise<RefundPaymentOutput>;
|
|
28
|
+
cancelPayment(input: CancelPaymentInput): Promise<CancelPaymentOutput>;
|
|
29
|
+
deletePayment(input: DeletePaymentInput): Promise<DeletePaymentOutput>;
|
|
30
|
+
retrievePayment(input: RetrievePaymentInput): Promise<RetrievePaymentOutput>;
|
|
31
|
+
updatePayment(input: UpdatePaymentInput): Promise<UpdatePaymentOutput>;
|
|
32
|
+
getWebhookActionAndData(payload: ProviderWebhookPayload["payload"]): Promise<WebhookActionResult>;
|
|
33
|
+
}
|
|
34
|
+
export { PaystackProviderService };
|
|
35
|
+
export default PaystackProviderService;
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PaystackProviderService = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const lib_1 = require("./lib");
|
|
3
6
|
const PAYSTACK_API = "https://api.paystack.co";
|
|
4
|
-
class PaystackProviderService extends AbstractPaymentProvider {
|
|
7
|
+
class PaystackProviderService extends utils_1.AbstractPaymentProvider {
|
|
5
8
|
constructor(cradle, options) {
|
|
6
9
|
super(cradle, options);
|
|
7
10
|
this.options_ = options ?? {};
|
|
11
|
+
this.container_ = cradle;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the amount + currency actually charged at Paystack for a cart.
|
|
15
|
+
* Default: charge the cart's own amount and currency. Override in a subclass
|
|
16
|
+
* to settle in a different currency (e.g. convert every cart to GHS).
|
|
17
|
+
*/
|
|
18
|
+
async resolveCharge(amount, currency_code) {
|
|
19
|
+
return { amount, currency: currency_code.toUpperCase() };
|
|
8
20
|
}
|
|
9
21
|
get secretKey() {
|
|
10
22
|
return this.options_?.secret_key ?? process.env.PAYSTACK_SECRET_KEY ?? "";
|
|
@@ -23,11 +35,12 @@ class PaystackProviderService extends AbstractPaymentProvider {
|
|
|
23
35
|
if (!email) {
|
|
24
36
|
throw new Error("Paystack: a customer email is required to initiate payment");
|
|
25
37
|
}
|
|
38
|
+
const { amount: chargeAmount, currency: chargeCurrency } = await this.resolveCharge(Number(amount), currency_code);
|
|
26
39
|
const seed = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
27
|
-
const reference = makeReference(seed, this.options_.reference_prefix);
|
|
28
|
-
const payload = buildInitializePayload({
|
|
29
|
-
amount:
|
|
30
|
-
currencyCode:
|
|
40
|
+
const reference = (0, lib_1.makeReference)(seed, this.options_.reference_prefix);
|
|
41
|
+
const payload = (0, lib_1.buildInitializePayload)({
|
|
42
|
+
amount: chargeAmount,
|
|
43
|
+
currencyCode: chargeCurrency,
|
|
31
44
|
email,
|
|
32
45
|
reference,
|
|
33
46
|
sessionId: data?.session_id,
|
|
@@ -50,6 +63,8 @@ class PaystackProviderService extends AbstractPaymentProvider {
|
|
|
50
63
|
authorization_url,
|
|
51
64
|
amount: Number(amount),
|
|
52
65
|
currency: currency_code.toUpperCase(),
|
|
66
|
+
charge_amount: chargeAmount,
|
|
67
|
+
charge_currency: chargeCurrency,
|
|
53
68
|
},
|
|
54
69
|
};
|
|
55
70
|
}
|
|
@@ -63,9 +78,9 @@ class PaystackProviderService extends AbstractPaymentProvider {
|
|
|
63
78
|
if (!json.status || !json.data)
|
|
64
79
|
return { status: "error", data };
|
|
65
80
|
const { status, currency, amount } = json.data;
|
|
66
|
-
const expectedAmount = Math.round(Number(data.amount ?? 0) * 100);
|
|
67
|
-
const expectedCurrency = String(data.currency ?? "").toUpperCase();
|
|
68
|
-
const check = assertChargeMatches({
|
|
81
|
+
const expectedAmount = Math.round(Number(data.charge_amount ?? data.amount ?? 0) * 100);
|
|
82
|
+
const expectedCurrency = String(data.charge_currency ?? data.currency ?? "").toUpperCase();
|
|
83
|
+
const check = (0, lib_1.assertChargeMatches)({
|
|
69
84
|
status,
|
|
70
85
|
currency,
|
|
71
86
|
amount,
|
|
@@ -105,10 +120,16 @@ class PaystackProviderService extends AbstractPaymentProvider {
|
|
|
105
120
|
async refundPayment(input) {
|
|
106
121
|
const data = input.data ?? {};
|
|
107
122
|
const reference = data.reference;
|
|
123
|
+
// Refund in the charge currency. For carts settled in another currency the
|
|
124
|
+
// ratio scales the requested (original-currency) refund into the charged
|
|
125
|
+
// amount; for same-currency carts the ratio is 1.
|
|
126
|
+
const ratio = data.amount && data.charge_amount
|
|
127
|
+
? Number(data.charge_amount) / Number(data.amount)
|
|
128
|
+
: 1;
|
|
108
129
|
const res = await fetch(`${PAYSTACK_API}/refund`, {
|
|
109
130
|
method: "POST",
|
|
110
131
|
headers: this.authHeader(),
|
|
111
|
-
body: JSON.stringify(buildRefundPayload(reference, Number(input.amount))),
|
|
132
|
+
body: JSON.stringify((0, lib_1.buildRefundPayload)(reference, Number(input.amount) * ratio)),
|
|
112
133
|
});
|
|
113
134
|
const json = (await res.json());
|
|
114
135
|
if (!res.ok || !json.status) {
|
|
@@ -149,12 +170,13 @@ class PaystackProviderService extends AbstractPaymentProvider {
|
|
|
149
170
|
const { data, rawData, headers } = payload;
|
|
150
171
|
const signature = headers["x-paystack-signature"] ?? "";
|
|
151
172
|
const raw = Buffer.isBuffer(rawData) ? rawData.toString("utf8") : String(rawData);
|
|
152
|
-
const signatureValid = verifyPaystackSignature(raw, signature, this.secretKey);
|
|
173
|
+
const signatureValid = (0, lib_1.verifyPaystackSignature)(raw, signature, this.secretKey);
|
|
153
174
|
const event = data;
|
|
154
175
|
const eventData = (event.data ?? {});
|
|
155
|
-
return webhookAction(event.event, eventData, signatureValid);
|
|
176
|
+
return (0, lib_1.webhookAction)(event.event, eventData, signatureValid);
|
|
156
177
|
}
|
|
157
178
|
}
|
|
179
|
+
exports.PaystackProviderService = PaystackProviderService;
|
|
158
180
|
PaystackProviderService.identifier = "paystack";
|
|
159
|
-
|
|
160
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
181
|
+
exports.default = PaystackProviderService;
|
|
182
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvcGF5c3RhY2svc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFzQkEscURBQW9FO0FBQ3BFLCtCQVNlO0FBT2YsTUFBTSxZQUFZLEdBQUcseUJBQXlCLENBQUM7QUFFL0MsTUFBTSx1QkFBd0IsU0FBUSwrQkFBd0M7SUFNNUUsWUFBWSxNQUErQixFQUFFLE9BQXdCO1FBQ25FLEtBQUssQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDdkIsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7OztPQUlHO0lBQ08sS0FBSyxDQUFDLGFBQWEsQ0FDM0IsTUFBYyxFQUNkLGFBQXFCO1FBRXJCLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLGFBQWEsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO0lBQzNELENBQUM7SUFFRCxJQUFZLFNBQVM7UUFDbkIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLFVBQVUsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixJQUFJLEVBQUUsQ0FBQztJQUM1RSxDQUFDO0lBRU8sVUFBVTtRQUNoQixPQUFPO1lBQ0wsYUFBYSxFQUFFLFVBQVUsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUN6QyxjQUFjLEVBQUUsa0JBQWtCO1NBQ25DLENBQUM7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLGVBQWUsQ0FBQyxLQUEyQjtRQUMvQyxNQUFNLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUM7UUFDakQsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQTJDLENBQUM7UUFFL0QsTUFBTSxLQUFLLEdBQ1QsT0FBTyxFQUFFLFFB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
|
package/AGENTS.md
CHANGED
|
@@ -138,6 +138,16 @@ Add **Paystack** as a payment provider to each region that should accept it: Adm
|
|
|
138
138
|
| `secret_key` | yes | `process.env.PAYSTACK_SECRET_KEY` | server API calls + webhook signature verification |
|
|
139
139
|
| `reference_prefix` | no | `""` | prepended to generated transaction references |
|
|
140
140
|
|
|
141
|
+
## Custom settlement currency
|
|
142
|
+
|
|
143
|
+
If the merchant's Paystack account settles one currency (e.g. GHS) but the store sells
|
|
144
|
+
in others, do NOT fork the provider. Subclass it and override the protected
|
|
145
|
+
`resolveCharge(amount, currency_code)` hook (default returns the cart currency
|
|
146
|
+
unchanged) to return the converted `{ amount, currency }`. Import the class from
|
|
147
|
+
`medusa-paystack/providers/paystack/service`, keep `static identifier = "paystack"`,
|
|
148
|
+
and register the subclass as the app's payment provider. See the README's
|
|
149
|
+
"Custom settlement currency (subclassing)" section.
|
|
150
|
+
|
|
141
151
|
## Provider methods (reference)
|
|
142
152
|
|
|
143
153
|
`initiatePayment` (creates the Paystack transaction), `authorizePayment` (verifies
|
package/README.md
CHANGED
|
@@ -180,6 +180,33 @@ return to your callback page call `sdk.store.cart.complete(cartId)`.
|
|
|
180
180
|
> with Paystack before the order is created. Never treat the client `onSuccess` as
|
|
181
181
|
> proof of payment on its own.
|
|
182
182
|
|
|
183
|
+
## Custom settlement currency (subclassing)
|
|
184
|
+
|
|
185
|
+
By default the provider charges in the cart's own `currency_code`. If your Paystack
|
|
186
|
+
account settles a single currency but your store prices carts in others, subclass the
|
|
187
|
+
provider and override `resolveCharge` to convert. The base class records both the
|
|
188
|
+
original (`amount`/`currency`) and the charged (`charge_amount`/`charge_currency`)
|
|
189
|
+
values, and verifies the captured charge against the latter.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
// src/modules/paystack/service.ts (in your Medusa app)
|
|
193
|
+
import PaystackProviderService from "medusa-paystack/providers/paystack/service";
|
|
194
|
+
|
|
195
|
+
class MyPaystackService extends PaystackProviderService {
|
|
196
|
+
static identifier = "paystack";
|
|
197
|
+
|
|
198
|
+
protected async resolveCharge(amount: number, currency_code: string) {
|
|
199
|
+
if (currency_code.toLowerCase() === "ghs") return { amount, currency: "GHS" };
|
|
200
|
+
const rate = await myFxLookup(currency_code); // your conversion source
|
|
201
|
+
return { amount: amount * rate, currency: "GHS" };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export default MyPaystackService;
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Register it as a normal in-app payment provider (`resolve: "./src/modules/paystack"`).
|
|
209
|
+
|
|
183
210
|
## Webhook
|
|
184
211
|
|
|
185
212
|
Create a webhook in your Paystack dashboard pointing at your Medusa server's payment
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medusa-paystack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Paystack payment provider for Medusa v2",
|
|
5
5
|
"author": "nuette",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/champ3oy/medusa-paystack.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/champ3oy/medusa-paystack/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/champ3oy/medusa-paystack#readme",
|
|
7
15
|
"keywords": [
|
|
8
16
|
"medusa-plugin",
|
|
9
17
|
"medusa-plugin-payment",
|
|
@@ -19,14 +27,18 @@
|
|
|
19
27
|
"LICENSE"
|
|
20
28
|
],
|
|
21
29
|
"scripts": {
|
|
22
|
-
"build": "medusa plugin:build",
|
|
30
|
+
"build": "medusa plugin:build && tsc --emitDeclarationOnly --declaration --outDir .medusa/server",
|
|
23
31
|
"dev": "medusa plugin:develop",
|
|
24
32
|
"typecheck": "tsc --noEmit",
|
|
25
33
|
"test": "jest",
|
|
26
|
-
"prepublishOnly": "
|
|
34
|
+
"prepublishOnly": "npm run build"
|
|
27
35
|
},
|
|
28
36
|
"exports": {
|
|
29
37
|
"./package.json": "./package.json",
|
|
38
|
+
"./providers/paystack/service": {
|
|
39
|
+
"types": "./.medusa/server/src/providers/paystack/service.d.ts",
|
|
40
|
+
"default": "./.medusa/server/src/providers/paystack/service.js"
|
|
41
|
+
},
|
|
30
42
|
"./providers/*": "./.medusa/server/src/providers/*/index.js",
|
|
31
43
|
"./*": "./.medusa/server/src/*.js"
|
|
32
44
|
},
|