@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
|
@@ -4,7 +4,6 @@ import PayPalMetric from "./models/paypal_metric"
|
|
|
4
4
|
import PayPalSettings from "./models/paypal_settings"
|
|
5
5
|
import PayPalWebhookEvent from "./models/paypal_webhook_event"
|
|
6
6
|
import { getPayPalConfig } from "./types/config"
|
|
7
|
-
import { decryptSecret, encryptSecret, isEncryptedSecret } from "./utils/crypto"
|
|
8
7
|
import { normalizeCurrencyCode } from "./utils/currencies"
|
|
9
8
|
|
|
10
9
|
type Environment = "sandbox" | "live"
|
|
@@ -99,59 +98,6 @@ class PayPalModuleService extends MedusaService({
|
|
|
99
98
|
return (this.cfg.alertWebhookUrls || []).map((url) => url.trim()).filter(Boolean)
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
private getEncryptionKey() {
|
|
103
|
-
return (this.cfg.credentialsEncryptionKey || "").trim()
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
private getDecryptionKeys() {
|
|
107
|
-
const current = this.getEncryptionKey()
|
|
108
|
-
const previous = this.cfg.credentialsEncryptionKeyPrevious || []
|
|
109
|
-
const keys = [current, ...previous].map((key) => (key || "").trim()).filter(Boolean)
|
|
110
|
-
return Array.from(new Set(keys))
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
private decryptSecretWithKeys(secret: string, keys: string[]) {
|
|
114
|
-
let lastError: unknown
|
|
115
|
-
for (const key of keys) {
|
|
116
|
-
try {
|
|
117
|
-
return decryptSecret(secret, key)
|
|
118
|
-
} catch (err) {
|
|
119
|
-
lastError = err
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (lastError) {
|
|
123
|
-
throw lastError
|
|
124
|
-
}
|
|
125
|
-
return secret
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private maybeEncryptSecret(secret: string) {
|
|
129
|
-
const key = this.getEncryptionKey()
|
|
130
|
-
if (!key) {
|
|
131
|
-
return secret
|
|
132
|
-
}
|
|
133
|
-
return encryptSecret(secret, key)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
private maybeDecryptSecret(secret?: string | null) {
|
|
137
|
-
if (!secret) {
|
|
138
|
-
return ""
|
|
139
|
-
}
|
|
140
|
-
const keys = this.getDecryptionKeys()
|
|
141
|
-
if (keys.length === 0) {
|
|
142
|
-
if (isEncryptedSecret(secret)) {
|
|
143
|
-
throw new Error(
|
|
144
|
-
"PayPal client secret is encrypted. Set PAYPAL_CREDENTIALS_ENCRYPTION_KEY to decrypt."
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
return secret
|
|
148
|
-
}
|
|
149
|
-
if (!isEncryptedSecret(secret)) {
|
|
150
|
-
return secret
|
|
151
|
-
}
|
|
152
|
-
return this.decryptSecretWithKeys(secret, keys)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
101
|
private async getPartnerMerchantId(env: Environment) {
|
|
156
102
|
const { onboarding } = await this.ensureSettingsDefaults()
|
|
157
103
|
return env === "live" ? onboarding.partner_merchant_id_live : onboarding.partner_merchant_id_sandbox
|
|
@@ -619,7 +565,6 @@ class PayPalModuleService extends MedusaService({
|
|
|
619
565
|
}
|
|
620
566
|
}
|
|
621
567
|
|
|
622
|
-
// ✅ If PayPal returned an error object, surface it clearly.
|
|
623
568
|
// Typical error shape: { name, message, debug_id, details: [...], links: [...] }
|
|
624
569
|
if (json?.name && json?.message && (json?.debug_id || json?.details || json?.links)) {
|
|
625
570
|
const debug = json.debug_id ? ` debug_id=${json.debug_id}` : ""
|
|
@@ -871,7 +816,6 @@ class PayPalModuleService extends MedusaService({
|
|
|
871
816
|
const currentEnv = await this.getCurrentEnvironment()
|
|
872
817
|
const env = (input.environment || currentEnv) as Environment
|
|
873
818
|
|
|
874
|
-
const encryptedSecret = this.maybeEncryptSecret(input.clientSecret)
|
|
875
819
|
const existingCreds = row ? this.getEnvCreds(row, env) : {}
|
|
876
820
|
const nextSellerMerchantId =
|
|
877
821
|
(input.sellerMerchantId || "").trim() || existingCreds.sellerMerchantId || row?.seller_merchant_id || null
|
|
@@ -881,8 +825,8 @@ class PayPalModuleService extends MedusaService({
|
|
|
881
825
|
const nextCreds = {
|
|
882
826
|
client_id: input.clientId,
|
|
883
827
|
clientId: input.clientId,
|
|
884
|
-
client_secret:
|
|
885
|
-
clientSecret:
|
|
828
|
+
client_secret: input.clientSecret,
|
|
829
|
+
clientSecret: input.clientSecret,
|
|
886
830
|
merchantId: nextSellerMerchantId,
|
|
887
831
|
merchant_id: nextSellerMerchantId,
|
|
888
832
|
payer_id: nextSellerMerchantId,
|
|
@@ -897,7 +841,7 @@ class PayPalModuleService extends MedusaService({
|
|
|
897
841
|
environment: env,
|
|
898
842
|
status: "connected",
|
|
899
843
|
seller_client_id: input.clientId,
|
|
900
|
-
seller_client_secret:
|
|
844
|
+
seller_client_secret: input.clientSecret,
|
|
901
845
|
seller_merchant_id: nextSellerMerchantId,
|
|
902
846
|
seller_email: nextSellerEmail,
|
|
903
847
|
app_access_token: null,
|
|
@@ -928,7 +872,7 @@ class PayPalModuleService extends MedusaService({
|
|
|
928
872
|
id: row.id,
|
|
929
873
|
status: "connected",
|
|
930
874
|
seller_client_id: input.clientId,
|
|
931
|
-
seller_client_secret:
|
|
875
|
+
seller_client_secret: input.clientSecret,
|
|
932
876
|
seller_merchant_id: nextSellerMerchantId,
|
|
933
877
|
seller_email: nextSellerEmail,
|
|
934
878
|
app_access_token: null,
|
|
@@ -1111,62 +1055,6 @@ class PayPalModuleService extends MedusaService({
|
|
|
1111
1055
|
)}`
|
|
1112
1056
|
}
|
|
1113
1057
|
|
|
1114
|
-
async rotateCredentialEncryptionKey() {
|
|
1115
|
-
const currentKey = this.getEncryptionKey()
|
|
1116
|
-
if (!currentKey) {
|
|
1117
|
-
throw new Error("PAYPAL_CREDENTIALS_ENCRYPTION_KEY must be set to rotate credentials.")
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
const row = await this.getCurrentRow()
|
|
1121
|
-
if (!row) {
|
|
1122
|
-
return { rotated: 0 }
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
const meta = (row.metadata || {}) as any
|
|
1126
|
-
const credentials = { ...(meta.credentials || {}) }
|
|
1127
|
-
let rotated = 0
|
|
1128
|
-
|
|
1129
|
-
for (const [env, envCreds] of Object.entries(credentials)) {
|
|
1130
|
-
if (!envCreds || typeof envCreds !== "object") continue
|
|
1131
|
-
const clientSecret = (envCreds as any).client_secret
|
|
1132
|
-
if (!clientSecret) continue
|
|
1133
|
-
|
|
1134
|
-
const decrypted = this.maybeDecryptSecret(clientSecret)
|
|
1135
|
-
const reEncrypted = this.maybeEncryptSecret(decrypted)
|
|
1136
|
-
if (reEncrypted !== clientSecret) {
|
|
1137
|
-
credentials[env] = {
|
|
1138
|
-
...(envCreds as any),
|
|
1139
|
-
client_secret: reEncrypted,
|
|
1140
|
-
}
|
|
1141
|
-
rotated += 1
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
if (rotated === 0) {
|
|
1146
|
-
return { rotated: 0 }
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
await this.updatePayPalConnections({
|
|
1150
|
-
id: row.id,
|
|
1151
|
-
metadata: {
|
|
1152
|
-
...(row.metadata || {}),
|
|
1153
|
-
credentials,
|
|
1154
|
-
},
|
|
1155
|
-
seller_client_secret: credentials?.[row.environment as Environment]?.client_secret || null,
|
|
1156
|
-
})
|
|
1157
|
-
|
|
1158
|
-
const updated = await this.getCurrentRow()
|
|
1159
|
-
if (updated) {
|
|
1160
|
-
await this.syncRowFieldsFromMetadata(updated, (updated.environment as Environment) || "live")
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
await this.recordAuditEvent("credentials_rotated", {
|
|
1164
|
-
environments: Object.keys(credentials),
|
|
1165
|
-
})
|
|
1166
|
-
|
|
1167
|
-
return { rotated }
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
1058
|
async getStatus(envOverride?: Environment) {
|
|
1171
1059
|
const row = await this.getCurrentRow()
|
|
1172
1060
|
const env = envOverride ?? (await this.getCurrentEnvironment())
|
|
@@ -1179,14 +1067,6 @@ class PayPalModuleService extends MedusaService({
|
|
|
1179
1067
|
const hasCreds = !!(c.clientId && c.clientSecret)
|
|
1180
1068
|
let sellerEmail: string | null = c.sellerEmail || row.seller_email || null
|
|
1181
1069
|
let sellerMerchantId: string | null = c.sellerMerchantId || row.seller_merchant_id || null
|
|
1182
|
-
let decryptedSecret: string | null = null
|
|
1183
|
-
if (c.clientSecret) {
|
|
1184
|
-
try {
|
|
1185
|
-
decryptedSecret = this.maybeDecryptSecret(c.clientSecret)
|
|
1186
|
-
} catch (e: any) {
|
|
1187
|
-
console.warn("[PayPal] Unable to decrypt seller client secret for status sync:", e?.message || e)
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
1070
|
|
|
1191
1071
|
if (!sellerEmail && hasCreds) {
|
|
1192
1072
|
try {
|
|
@@ -1194,7 +1074,7 @@ class PayPalModuleService extends MedusaService({
|
|
|
1194
1074
|
if (hydrated.sellerEmail || hydrated.sellerMerchantId) {
|
|
1195
1075
|
await this.saveSellerCredentials({
|
|
1196
1076
|
clientId: c.clientId!,
|
|
1197
|
-
clientSecret:
|
|
1077
|
+
clientSecret: c.clientSecret!,
|
|
1198
1078
|
sellerMerchantId: hydrated.sellerMerchantId || sellerMerchantId,
|
|
1199
1079
|
sellerEmail: hydrated.sellerEmail || sellerEmail,
|
|
1200
1080
|
environment: env,
|
|
@@ -1410,7 +1290,7 @@ class PayPalModuleService extends MedusaService({
|
|
|
1410
1290
|
}
|
|
1411
1291
|
|
|
1412
1292
|
const c = this.getEnvCreds(row, env)
|
|
1413
|
-
const clientSecret =
|
|
1293
|
+
const clientSecret = c.clientSecret || ""
|
|
1414
1294
|
|
|
1415
1295
|
if (!c.clientId || !clientSecret) {
|
|
1416
1296
|
throw new Error(
|
|
@@ -1563,7 +1443,6 @@ class PayPalModuleService extends MedusaService({
|
|
|
1563
1443
|
metadata: metadata ?? {},
|
|
1564
1444
|
created_at: new Date().toISOString(),
|
|
1565
1445
|
}
|
|
1566
|
-
console.info("[PayPal] payment_event", payload)
|
|
1567
1446
|
return await this.recordAuditEvent(`payment_${eventType}`, metadata)
|
|
1568
1447
|
}
|
|
1569
1448
|
|
|
@@ -1,47 +1,33 @@
|
|
|
1
|
-
export type PayPalModuleConfig = {
|
|
2
|
-
partnerServiceUrl: string
|
|
3
|
-
partnerJsUrl: string
|
|
4
|
-
backendUrl: string
|
|
5
|
-
sellerNonce: string
|
|
6
|
-
bnCode?: string
|
|
7
|
-
partnerMerchantIdSandbox: string
|
|
8
|
-
partnerMerchantIdLive: string
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
...STATIC_CFG,
|
|
35
|
-
backendUrl: process.env.MEDUSA_BACKEND_URL || STATIC_CFG.backendUrl,
|
|
36
|
-
credentialsEncryptionKey:
|
|
37
|
-
process.env.PAYPAL_CREDENTIALS_ENCRYPTION_KEY ||
|
|
38
|
-
STATIC_CFG.credentialsEncryptionKey,
|
|
39
|
-
credentialsEncryptionKeyPrevious:
|
|
40
|
-
previousKeys.length > 0 ? previousKeys : STATIC_CFG.credentialsEncryptionKeyPrevious,
|
|
41
|
-
alertWebhookUrls:
|
|
42
|
-
(process.env.PAYPAL_ALERT_WEBHOOK_URLS || "")
|
|
43
|
-
.split(",")
|
|
44
|
-
.map((url) => url.trim())
|
|
45
|
-
.filter(Boolean) || STATIC_CFG.alertWebhookUrls,
|
|
46
|
-
}
|
|
47
|
-
}
|
|
1
|
+
export type PayPalModuleConfig = {
|
|
2
|
+
partnerServiceUrl: string
|
|
3
|
+
partnerJsUrl: string
|
|
4
|
+
backendUrl: string
|
|
5
|
+
sellerNonce: string
|
|
6
|
+
bnCode?: string
|
|
7
|
+
partnerMerchantIdSandbox: string
|
|
8
|
+
partnerMerchantIdLive: string
|
|
9
|
+
alertWebhookUrls?: string[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const STATIC_CFG: PayPalModuleConfig = {
|
|
13
|
+
partnerServiceUrl: "https://mbjtechnolabs.com/ppcp-seller-onboarding/seller-onboarding.php",
|
|
14
|
+
partnerJsUrl: "https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js",
|
|
15
|
+
backendUrl: "http://localhost:9000",
|
|
16
|
+
sellerNonce: "a1233wtergfsdt4365tzrshgfbaewa36AGa1233wtergfsdt4365tzrshgfbaewa36AG",
|
|
17
|
+
bnCode: "",
|
|
18
|
+
partnerMerchantIdSandbox: "K6QLN2LPGQRHL",
|
|
19
|
+
partnerMerchantIdLive: "GT5R877JNBPLL",
|
|
20
|
+
alertWebhookUrls: [],
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getPayPalConfig(): PayPalModuleConfig {
|
|
24
|
+
return {
|
|
25
|
+
...STATIC_CFG,
|
|
26
|
+
backendUrl: process.env.MEDUSA_BACKEND_URL || STATIC_CFG.backendUrl,
|
|
27
|
+
alertWebhookUrls:
|
|
28
|
+
(process.env.PAYPAL_ALERT_WEBHOOK_URLS || "")
|
|
29
|
+
.split(",")
|
|
30
|
+
.map((url) => url.trim())
|
|
31
|
+
.filter(Boolean) || STATIC_CFG.alertWebhookUrls,
|
|
32
|
+
}
|
|
33
|
+
}
|