@easypayment/medusa-paypal 0.6.2 → 0.6.4
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 +12 -15
- package/.medusa/server/src/admin/index.mjs +12 -15
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/payment-collections/[id]/payment-sessions/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/capture-order/route.js +1 -11
- package/.medusa/server/src/api/store/paypal/capture-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/create-order/route.js +0 -9
- package/.medusa/server/src/api/store/paypal/create-order/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal/webhook/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal/webhook/route.js +162 -115
- package/.medusa/server/src/api/store/paypal/webhook/route.js.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.d.ts.map +1 -1
- package/.medusa/server/src/api/store/paypal-complete/route.js +0 -6
- package/.medusa/server/src/api/store/paypal-complete/route.js.map +1 -1
- package/.medusa/server/src/jobs/paypal-webhook-retry.d.ts.map +1 -1
- package/.medusa/server/src/jobs/paypal-webhook-retry.js +97 -43
- package/.medusa/server/src/jobs/paypal-webhook-retry.js.map +1 -1
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts +6 -0
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.d.ts.map +1 -0
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js +20 -0
- package/.medusa/server/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.js.map +1 -0
- package/.medusa/server/src/modules/paypal/payment-provider/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/payment-provider/service.js +0 -42
- package/.medusa/server/src/modules/paypal/payment-provider/service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/service.d.ts +0 -8
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +6 -114
- package/.medusa/server/src/modules/paypal/service.js.map +1 -1
- package/.medusa/server/src/modules/paypal/types/config.d.ts +0 -2
- package/.medusa/server/src/modules/paypal/types/config.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/types/config.js +0 -9
- package/.medusa/server/src/modules/paypal/types/config.js.map +1 -1
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts +21 -17
- package/.medusa/server/src/modules/paypal/webhook-processor.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/webhook-processor.js +195 -99
- package/.medusa/server/src/modules/paypal/webhook-processor.js.map +1 -1
- package/README.md +156 -159
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/_components/Tabs.tsx +48 -52
- package/src/admin/routes/settings/paypal/paypal-settings/page.tsx +0 -23
- package/src/api/store/payment-collections/[id]/payment-sessions/route.ts +56 -65
- package/src/api/store/paypal/capture-order/route.ts +266 -276
- package/src/api/store/paypal/create-order/route.ts +0 -9
- package/src/api/store/paypal/webhook/route.ts +325 -246
- package/src/api/store/paypal-complete/route.ts +69 -75
- package/src/jobs/paypal-webhook-retry.ts +149 -85
- package/src/modules/paypal/migrations/20270201000000_add_webhook_dead_letter.ts +17 -0
- package/src/modules/paypal/payment-provider/service.ts +1079 -1121
- package/src/modules/paypal/service.ts +6 -127
- package/src/modules/paypal/types/config.ts +33 -47
- package/src/modules/paypal/webhook-processor.ts +377 -215
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts +0 -3
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.d.ts.map +0 -1
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js +0 -9
- package/.medusa/server/src/api/admin/paypal/rotate-credentials/route.js.map +0 -1
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts +0 -7
- package/.medusa/server/src/jobs/paypal-reconcile.d.ts.map +0 -1
- package/.medusa/server/src/jobs/paypal-reconcile.js +0 -109
- package/.medusa/server/src/jobs/paypal-reconcile.js.map +0 -1
- package/.medusa/server/src/modules/paypal/utils/crypto.d.ts +0 -4
- package/.medusa/server/src/modules/paypal/utils/crypto.d.ts.map +0 -1
- package/.medusa/server/src/modules/paypal/utils/crypto.js +0 -47
- package/.medusa/server/src/modules/paypal/utils/crypto.js.map +0 -1
- package/src/api/admin/paypal/rotate-credentials/route.ts +0 -8
- package/src/jobs/paypal-reconcile.ts +0 -113
- package/src/modules/paypal/utils/crypto.ts +0 -51
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.config = void 0;
|
|
4
|
-
exports.default = paypalReconcile;
|
|
5
|
-
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
-
const paypal_1 = require("../modules/paypal");
|
|
7
|
-
const provider_ids_1 = require("../modules/paypal/utils/provider-ids");
|
|
8
|
-
const STATUS_MAP = {
|
|
9
|
-
CREATED: "pending",
|
|
10
|
-
APPROVED: "authorized",
|
|
11
|
-
COMPLETED: "captured",
|
|
12
|
-
VOIDED: "canceled",
|
|
13
|
-
CANCELLED: "canceled",
|
|
14
|
-
};
|
|
15
|
-
async function paypalReconcile(container) {
|
|
16
|
-
// FIX 3a: was container.resolve("payment_session") as any
|
|
17
|
-
// Modules.PAYMENT is the official typed constant for the Medusa payment module.
|
|
18
|
-
// listPaymentSessions and updatePaymentSession are methods on the payment module service.
|
|
19
|
-
const paymentModule = container.resolve(utils_1.Modules.PAYMENT);
|
|
20
|
-
// FIX 3b: was container.resolve<PayPalModuleService>("paypal_onboarding")
|
|
21
|
-
// PAYPAL_MODULE is the exported constant from modules/paypal/index.ts
|
|
22
|
-
const paypal = container.resolve(paypal_1.PAYPAL_MODULE);
|
|
23
|
-
// FIX 3c: was ["pp_paypal_paypal", "pp_paypal_card_paypal_card"]
|
|
24
|
-
// PAYPAL_PROVIDER_IDS is the exported array from modules/paypal/utils/provider-ids.ts
|
|
25
|
-
// If the provider IDs ever change in one place, this file updates automatically.
|
|
26
|
-
const sessions = await paymentModule.listPaymentSessions({
|
|
27
|
-
provider_id: [...provider_ids_1.PAYPAL_PROVIDER_IDS],
|
|
28
|
-
status: ["pending", "authorized"],
|
|
29
|
-
});
|
|
30
|
-
for (const session of sessions || []) {
|
|
31
|
-
const data = (session?.data || {});
|
|
32
|
-
const paypalData = (data.paypal || {});
|
|
33
|
-
const orderId = String(paypalData.order_id || data.order_id || "");
|
|
34
|
-
if (!orderId) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
const order = await paypal.getOrderDetails(orderId);
|
|
39
|
-
const status = STATUS_MAP[String(order?.status || "").toUpperCase()];
|
|
40
|
-
if (!status) {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
const previousStatus = session?.status;
|
|
44
|
-
if (previousStatus && previousStatus !== status) {
|
|
45
|
-
await paypal.recordPaymentLog("reconcile_drift", {
|
|
46
|
-
session_id: session.id,
|
|
47
|
-
order_id: orderId,
|
|
48
|
-
previous_status: previousStatus,
|
|
49
|
-
next_status: status,
|
|
50
|
-
});
|
|
51
|
-
await paypal.recordMetric("reconcile_drift");
|
|
52
|
-
await paypal.sendAlert({
|
|
53
|
-
type: "reconcile_drift",
|
|
54
|
-
message: `PayPal reconciliation drift detected for order ${orderId}.`,
|
|
55
|
-
metadata: {
|
|
56
|
-
session_id: session.id,
|
|
57
|
-
previous_status: previousStatus,
|
|
58
|
-
next_status: status,
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
// FIX 3d: was paymentSessionService.update(session.id, { ... })
|
|
63
|
-
// updatePaymentSession is the correct method name on the payment module service.
|
|
64
|
-
await paymentModule.updatePaymentSession(session.id, {
|
|
65
|
-
status,
|
|
66
|
-
amount: session.amount,
|
|
67
|
-
data: {
|
|
68
|
-
...(session.data || {}),
|
|
69
|
-
paypal: {
|
|
70
|
-
...((session.data || {}).paypal || {}),
|
|
71
|
-
order,
|
|
72
|
-
reconciliation: {
|
|
73
|
-
last_reconciled_at: new Date().toISOString(),
|
|
74
|
-
last_status: status,
|
|
75
|
-
order_status: order?.status,
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
try {
|
|
81
|
-
await paypal.recordMetric("reconcile_success");
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
// ignore metrics failures
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
try {
|
|
89
|
-
await paypal.recordMetric("reconcile_failed");
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
// ignore metrics failures
|
|
93
|
-
}
|
|
94
|
-
await paypal.sendAlert({
|
|
95
|
-
type: "reconcile_failed",
|
|
96
|
-
message: `PayPal reconciliation failed for order ${orderId}.`,
|
|
97
|
-
metadata: {
|
|
98
|
-
session_id: session.id,
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
console.error("[PayPal] reconcile error", error);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
exports.config = {
|
|
106
|
-
name: "paypal-reconcile",
|
|
107
|
-
schedule: "*/15 * * * *",
|
|
108
|
-
};
|
|
109
|
-
//# sourceMappingURL=paypal-reconcile.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paypal-reconcile.js","sourceRoot":"","sources":["../../../../src/jobs/paypal-reconcile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../../../../../src/modules/paypal/utils/crypto.ts"],"names":[],"mappings":"AAUA,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,WAEtD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAgB1D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAkB1D"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isEncryptedSecret = isEncryptedSecret;
|
|
4
|
-
exports.encryptSecret = encryptSecret;
|
|
5
|
-
exports.decryptSecret = decryptSecret;
|
|
6
|
-
const crypto_1 = require("crypto");
|
|
7
|
-
const ENCRYPTED_PREFIX = "enc:";
|
|
8
|
-
const ALGORITHM = "aes-256-gcm";
|
|
9
|
-
const IV_LENGTH = 12;
|
|
10
|
-
function deriveKey(secret) {
|
|
11
|
-
return (0, crypto_1.createHash)("sha256").update(secret).digest();
|
|
12
|
-
}
|
|
13
|
-
function isEncryptedSecret(value) {
|
|
14
|
-
return typeof value === "string" && value.startsWith(ENCRYPTED_PREFIX);
|
|
15
|
-
}
|
|
16
|
-
function encryptSecret(value, secret) {
|
|
17
|
-
if (!value || isEncryptedSecret(value)) {
|
|
18
|
-
return value;
|
|
19
|
-
}
|
|
20
|
-
const iv = (0, crypto_1.randomBytes)(IV_LENGTH);
|
|
21
|
-
const cipher = (0, crypto_1.createCipheriv)(ALGORITHM, deriveKey(secret), iv);
|
|
22
|
-
const encrypted = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
|
|
23
|
-
const tag = cipher.getAuthTag();
|
|
24
|
-
return [
|
|
25
|
-
ENCRYPTED_PREFIX.slice(0, -1),
|
|
26
|
-
iv.toString("base64"),
|
|
27
|
-
tag.toString("base64"),
|
|
28
|
-
encrypted.toString("base64"),
|
|
29
|
-
].join(":");
|
|
30
|
-
}
|
|
31
|
-
function decryptSecret(value, secret) {
|
|
32
|
-
if (!isEncryptedSecret(value)) {
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
const [, ivBase64, tagBase64, payloadBase64] = value.split(":");
|
|
36
|
-
if (!ivBase64 || !tagBase64 || !payloadBase64) {
|
|
37
|
-
throw new Error("Invalid encrypted PayPal secret format.");
|
|
38
|
-
}
|
|
39
|
-
const iv = Buffer.from(ivBase64, "base64");
|
|
40
|
-
const tag = Buffer.from(tagBase64, "base64");
|
|
41
|
-
const payload = Buffer.from(payloadBase64, "base64");
|
|
42
|
-
const decipher = (0, crypto_1.createDecipheriv)(ALGORITHM, deriveKey(secret), iv);
|
|
43
|
-
decipher.setAuthTag(tag);
|
|
44
|
-
const decrypted = Buffer.concat([decipher.update(payload), decipher.final()]);
|
|
45
|
-
return decrypted.toString("utf8");
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=crypto.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../../../../src/modules/paypal/utils/crypto.ts"],"names":[],"mappings":";;AAUA,8CAEC;AAED,sCAgBC;AAED,sCAkBC;AAlDD,mCAAkF;AAElF,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAC/B,MAAM,SAAS,GAAG,aAAa,CAAA;AAC/B,MAAM,SAAS,GAAG,EAAE,CAAA;AAEpB,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAA;AACrD,CAAC;AAED,SAAgB,iBAAiB,CAAC,KAAqB;IACrD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;AACxE,CAAC;AAED,SAAgB,aAAa,CAAC,KAAa,EAAE,MAAc;IACzD,IAAI,CAAC,KAAK,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,EAAE,GAAG,IAAA,oBAAW,EAAC,SAAS,CAAC,CAAA;IACjC,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC/E,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,EAAE,CAAA;IAE/B,OAAO;QACL,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7B,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACrB,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACtB,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;KAC7B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACb,CAAC;AAED,SAAgB,aAAa,CAAC,KAAa,EAAE,MAAc;IACzD,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC/D,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,IAAI,CAAC,aAAa,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;IACpD,MAAM,QAAQ,GAAG,IAAA,yBAAgB,EAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;IACnE,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAE7E,OAAO,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AACnC,CAAC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
2
|
-
import type PayPalModuleService from "../../../../modules/paypal/service"
|
|
3
|
-
|
|
4
|
-
export async function POST(req: MedusaRequest, res: MedusaResponse) {
|
|
5
|
-
const paypal = req.scope.resolve<PayPalModuleService>("paypal_onboarding")
|
|
6
|
-
const result = await paypal.rotateCredentialEncryptionKey()
|
|
7
|
-
return res.json(result)
|
|
8
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import type { MedusaContainer } from "@medusajs/framework/types"
|
|
2
|
-
import { Modules } from "@medusajs/framework/utils"
|
|
3
|
-
import type PayPalModuleService from "../modules/paypal/service"
|
|
4
|
-
import { PAYPAL_MODULE } from "../modules/paypal"
|
|
5
|
-
import { PAYPAL_PROVIDER_IDS } from "../modules/paypal/utils/provider-ids"
|
|
6
|
-
|
|
7
|
-
const STATUS_MAP: Record<string, "pending" | "authorized" | "captured" | "canceled"> = {
|
|
8
|
-
CREATED: "pending",
|
|
9
|
-
APPROVED: "authorized",
|
|
10
|
-
COMPLETED: "captured",
|
|
11
|
-
VOIDED: "canceled",
|
|
12
|
-
CANCELLED: "canceled",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default async function paypalReconcile(container: MedusaContainer) {
|
|
16
|
-
// FIX 3a: was container.resolve("payment_session") as any
|
|
17
|
-
// Modules.PAYMENT is the official typed constant for the Medusa payment module.
|
|
18
|
-
// listPaymentSessions and updatePaymentSession are methods on the payment module service.
|
|
19
|
-
const paymentModule = container.resolve(Modules.PAYMENT) as any
|
|
20
|
-
|
|
21
|
-
// FIX 3b: was container.resolve<PayPalModuleService>("paypal_onboarding")
|
|
22
|
-
// PAYPAL_MODULE is the exported constant from modules/paypal/index.ts
|
|
23
|
-
const paypal = container.resolve<PayPalModuleService>(PAYPAL_MODULE)
|
|
24
|
-
|
|
25
|
-
// FIX 3c: was ["pp_paypal_paypal", "pp_paypal_card_paypal_card"]
|
|
26
|
-
// PAYPAL_PROVIDER_IDS is the exported array from modules/paypal/utils/provider-ids.ts
|
|
27
|
-
// If the provider IDs ever change in one place, this file updates automatically.
|
|
28
|
-
const sessions = await paymentModule.listPaymentSessions({
|
|
29
|
-
provider_id: [...PAYPAL_PROVIDER_IDS],
|
|
30
|
-
status: ["pending", "authorized"],
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
for (const session of sessions || []) {
|
|
35
|
-
const data = (session?.data || {}) as Record<string, any>
|
|
36
|
-
const paypalData = (data.paypal || {}) as Record<string, any>
|
|
37
|
-
const orderId = String(paypalData.order_id || data.order_id || "")
|
|
38
|
-
if (!orderId) {
|
|
39
|
-
continue
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const order = await paypal.getOrderDetails(orderId)
|
|
44
|
-
const status = STATUS_MAP[String(order?.status || "").toUpperCase()]
|
|
45
|
-
if (!status) {
|
|
46
|
-
continue
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const previousStatus = session?.status
|
|
50
|
-
if (previousStatus && previousStatus !== status) {
|
|
51
|
-
await paypal.recordPaymentLog("reconcile_drift", {
|
|
52
|
-
session_id: session.id,
|
|
53
|
-
order_id: orderId,
|
|
54
|
-
previous_status: previousStatus,
|
|
55
|
-
next_status: status,
|
|
56
|
-
})
|
|
57
|
-
await paypal.recordMetric("reconcile_drift")
|
|
58
|
-
await paypal.sendAlert({
|
|
59
|
-
type: "reconcile_drift",
|
|
60
|
-
message: `PayPal reconciliation drift detected for order ${orderId}.`,
|
|
61
|
-
metadata: {
|
|
62
|
-
session_id: session.id,
|
|
63
|
-
previous_status: previousStatus,
|
|
64
|
-
next_status: status,
|
|
65
|
-
},
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// FIX 3d: was paymentSessionService.update(session.id, { ... })
|
|
70
|
-
// updatePaymentSession is the correct method name on the payment module service.
|
|
71
|
-
await paymentModule.updatePaymentSession(session.id, {
|
|
72
|
-
status,
|
|
73
|
-
amount: session.amount,
|
|
74
|
-
data: {
|
|
75
|
-
...(session.data || {}),
|
|
76
|
-
paypal: {
|
|
77
|
-
...((session.data || {}).paypal || {}),
|
|
78
|
-
order,
|
|
79
|
-
reconciliation: {
|
|
80
|
-
last_reconciled_at: new Date().toISOString(),
|
|
81
|
-
last_status: status,
|
|
82
|
-
order_status: order?.status,
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
})
|
|
87
|
-
try {
|
|
88
|
-
await paypal.recordMetric("reconcile_success")
|
|
89
|
-
} catch {
|
|
90
|
-
// ignore metrics failures
|
|
91
|
-
}
|
|
92
|
-
} catch (error) {
|
|
93
|
-
try {
|
|
94
|
-
await paypal.recordMetric("reconcile_failed")
|
|
95
|
-
} catch {
|
|
96
|
-
// ignore metrics failures
|
|
97
|
-
}
|
|
98
|
-
await paypal.sendAlert({
|
|
99
|
-
type: "reconcile_failed",
|
|
100
|
-
message: `PayPal reconciliation failed for order ${orderId}.`,
|
|
101
|
-
metadata: {
|
|
102
|
-
session_id: session.id,
|
|
103
|
-
},
|
|
104
|
-
})
|
|
105
|
-
console.error("[PayPal] reconcile error", error)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export const config = {
|
|
111
|
-
name: "paypal-reconcile",
|
|
112
|
-
schedule: "*/15 * * * *",
|
|
113
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { createCipheriv, createDecipheriv, createHash, randomBytes } from "crypto"
|
|
2
|
-
|
|
3
|
-
const ENCRYPTED_PREFIX = "enc:"
|
|
4
|
-
const ALGORITHM = "aes-256-gcm"
|
|
5
|
-
const IV_LENGTH = 12
|
|
6
|
-
|
|
7
|
-
function deriveKey(secret: string) {
|
|
8
|
-
return createHash("sha256").update(secret).digest()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function isEncryptedSecret(value?: string | null) {
|
|
12
|
-
return typeof value === "string" && value.startsWith(ENCRYPTED_PREFIX)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function encryptSecret(value: string, secret: string) {
|
|
16
|
-
if (!value || isEncryptedSecret(value)) {
|
|
17
|
-
return value
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const iv = randomBytes(IV_LENGTH)
|
|
21
|
-
const cipher = createCipheriv(ALGORITHM, deriveKey(secret), iv)
|
|
22
|
-
const encrypted = Buffer.concat([cipher.update(value, "utf8"), cipher.final()])
|
|
23
|
-
const tag = cipher.getAuthTag()
|
|
24
|
-
|
|
25
|
-
return [
|
|
26
|
-
ENCRYPTED_PREFIX.slice(0, -1),
|
|
27
|
-
iv.toString("base64"),
|
|
28
|
-
tag.toString("base64"),
|
|
29
|
-
encrypted.toString("base64"),
|
|
30
|
-
].join(":")
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function decryptSecret(value: string, secret: string) {
|
|
34
|
-
if (!isEncryptedSecret(value)) {
|
|
35
|
-
return value
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const [, ivBase64, tagBase64, payloadBase64] = value.split(":")
|
|
39
|
-
if (!ivBase64 || !tagBase64 || !payloadBase64) {
|
|
40
|
-
throw new Error("Invalid encrypted PayPal secret format.")
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const iv = Buffer.from(ivBase64, "base64")
|
|
44
|
-
const tag = Buffer.from(tagBase64, "base64")
|
|
45
|
-
const payload = Buffer.from(payloadBase64, "base64")
|
|
46
|
-
const decipher = createDecipheriv(ALGORITHM, deriveKey(secret), iv)
|
|
47
|
-
decipher.setAuthTag(tag)
|
|
48
|
-
const decrypted = Buffer.concat([decipher.update(payload), decipher.final()])
|
|
49
|
-
|
|
50
|
-
return decrypted.toString("utf8")
|
|
51
|
-
}
|