@easypayment/medusa-paypal 0.5.8 → 0.5.9
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 +14 -21
- package/.medusa/server/src/admin/index.mjs +14 -21
- package/.medusa/server/src/api/admin/paypal/save-credentials/route.d.ts.map +1 -1
- package/.medusa/server/src/api/admin/paypal/save-credentials/route.js +5 -1
- package/.medusa/server/src/api/admin/paypal/save-credentials/route.js.map +1 -1
- package/.medusa/server/src/modules/paypal/service.d.ts +31 -0
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +201 -22
- package/.medusa/server/src/modules/paypal/service.js.map +1 -1
- package/package.json +1 -1
- package/src/admin/routes/settings/paypal/connection/page.tsx +747 -754
- package/src/api/admin/paypal/save-credentials/route.ts +22 -14
- package/src/modules/paypal/service.ts +250 -22
|
@@ -325,9 +325,6 @@ function AdvancedCardPaymentsTab() {
|
|
|
325
325
|
function PayPalApplePayPage() {
|
|
326
326
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
327
327
|
}
|
|
328
|
-
function PayPalGooglePayPage() {
|
|
329
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
330
|
-
}
|
|
331
328
|
const config = adminSdk.defineRouteConfig({
|
|
332
329
|
label: "PayPal Connection",
|
|
333
330
|
hide: true
|
|
@@ -404,15 +401,6 @@ function PayPalConnectionPage() {
|
|
|
404
401
|
const canSaveManual = react.useMemo(() => {
|
|
405
402
|
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
406
403
|
}, [clientId, secret]);
|
|
407
|
-
const maskValue = react.useCallback((value, visibleChars = 4) => {
|
|
408
|
-
if (!value) return "";
|
|
409
|
-
if (value.length <= visibleChars) {
|
|
410
|
-
return "•".repeat(value.length);
|
|
411
|
-
}
|
|
412
|
-
return `${"•".repeat(Math.max(0, value.length - visibleChars))}${value.slice(
|
|
413
|
-
-visibleChars
|
|
414
|
-
)}`;
|
|
415
|
-
}, []);
|
|
416
404
|
const fetchFreshLink = react.useCallback(
|
|
417
405
|
(runId) => {
|
|
418
406
|
if (initLoaderRef.current) {
|
|
@@ -611,18 +599,20 @@ function PayPalConnectionPage() {
|
|
|
611
599
|
headers: { "content-type": "application/json" },
|
|
612
600
|
body: JSON.stringify({
|
|
613
601
|
clientId: clientId.trim(),
|
|
614
|
-
clientSecret: secret.trim()
|
|
602
|
+
clientSecret: secret.trim(),
|
|
603
|
+
environment: env
|
|
615
604
|
})
|
|
616
605
|
});
|
|
617
606
|
if (!res.ok) {
|
|
618
607
|
const txt = await res.text().catch(() => "");
|
|
619
608
|
throw new Error(txt || `Save credentials failed (${res.status})`);
|
|
620
609
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
seller_client_id_masked: maskValue(clientId.trim()),
|
|
624
|
-
seller_client_secret_masked: "••••••••"
|
|
610
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
611
|
+
method: "GET"
|
|
625
612
|
});
|
|
613
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
614
|
+
setConnState("connected");
|
|
615
|
+
setStatusInfo(refreshedStatus || null);
|
|
626
616
|
setShowManual(false);
|
|
627
617
|
try {
|
|
628
618
|
localStorage.removeItem(CACHE_KEY);
|
|
@@ -929,6 +919,9 @@ function PayPalConnectionPage() {
|
|
|
929
919
|
` })
|
|
930
920
|
] });
|
|
931
921
|
}
|
|
922
|
+
function PayPalGooglePayPage() {
|
|
923
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
924
|
+
}
|
|
932
925
|
function PayPalPayLaterMessagingPage() {
|
|
933
926
|
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
934
927
|
}
|
|
@@ -1224,14 +1217,14 @@ const routeModule = {
|
|
|
1224
1217
|
Component: PayPalApplePayPage,
|
|
1225
1218
|
path: "/settings/paypal/apple-pay"
|
|
1226
1219
|
},
|
|
1227
|
-
{
|
|
1228
|
-
Component: PayPalGooglePayPage,
|
|
1229
|
-
path: "/settings/paypal/google-pay"
|
|
1230
|
-
},
|
|
1231
1220
|
{
|
|
1232
1221
|
Component: PayPalConnectionPage,
|
|
1233
1222
|
path: "/settings/paypal/connection"
|
|
1234
1223
|
},
|
|
1224
|
+
{
|
|
1225
|
+
Component: PayPalGooglePayPage,
|
|
1226
|
+
path: "/settings/paypal/google-pay"
|
|
1227
|
+
},
|
|
1235
1228
|
{
|
|
1236
1229
|
Component: PayPalPayLaterMessagingPage,
|
|
1237
1230
|
path: "/settings/paypal/pay-later-messaging"
|
|
@@ -324,9 +324,6 @@ function AdvancedCardPaymentsTab() {
|
|
|
324
324
|
function PayPalApplePayPage() {
|
|
325
325
|
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
326
326
|
}
|
|
327
|
-
function PayPalGooglePayPage() {
|
|
328
|
-
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
329
|
-
}
|
|
330
327
|
const config = defineRouteConfig({
|
|
331
328
|
label: "PayPal Connection",
|
|
332
329
|
hide: true
|
|
@@ -403,15 +400,6 @@ function PayPalConnectionPage() {
|
|
|
403
400
|
const canSaveManual = useMemo(() => {
|
|
404
401
|
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
405
402
|
}, [clientId, secret]);
|
|
406
|
-
const maskValue = useCallback((value, visibleChars = 4) => {
|
|
407
|
-
if (!value) return "";
|
|
408
|
-
if (value.length <= visibleChars) {
|
|
409
|
-
return "•".repeat(value.length);
|
|
410
|
-
}
|
|
411
|
-
return `${"•".repeat(Math.max(0, value.length - visibleChars))}${value.slice(
|
|
412
|
-
-visibleChars
|
|
413
|
-
)}`;
|
|
414
|
-
}, []);
|
|
415
403
|
const fetchFreshLink = useCallback(
|
|
416
404
|
(runId) => {
|
|
417
405
|
if (initLoaderRef.current) {
|
|
@@ -610,18 +598,20 @@ function PayPalConnectionPage() {
|
|
|
610
598
|
headers: { "content-type": "application/json" },
|
|
611
599
|
body: JSON.stringify({
|
|
612
600
|
clientId: clientId.trim(),
|
|
613
|
-
clientSecret: secret.trim()
|
|
601
|
+
clientSecret: secret.trim(),
|
|
602
|
+
environment: env
|
|
614
603
|
})
|
|
615
604
|
});
|
|
616
605
|
if (!res.ok) {
|
|
617
606
|
const txt = await res.text().catch(() => "");
|
|
618
607
|
throw new Error(txt || `Save credentials failed (${res.status})`);
|
|
619
608
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
seller_client_id_masked: maskValue(clientId.trim()),
|
|
623
|
-
seller_client_secret_masked: "••••••••"
|
|
609
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
610
|
+
method: "GET"
|
|
624
611
|
});
|
|
612
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
613
|
+
setConnState("connected");
|
|
614
|
+
setStatusInfo(refreshedStatus || null);
|
|
625
615
|
setShowManual(false);
|
|
626
616
|
try {
|
|
627
617
|
localStorage.removeItem(CACHE_KEY);
|
|
@@ -928,6 +918,9 @@ function PayPalConnectionPage() {
|
|
|
928
918
|
` })
|
|
929
919
|
] });
|
|
930
920
|
}
|
|
921
|
+
function PayPalGooglePayPage() {
|
|
922
|
+
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
923
|
+
}
|
|
931
924
|
function PayPalPayLaterMessagingPage() {
|
|
932
925
|
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
933
926
|
}
|
|
@@ -1223,14 +1216,14 @@ const routeModule = {
|
|
|
1223
1216
|
Component: PayPalApplePayPage,
|
|
1224
1217
|
path: "/settings/paypal/apple-pay"
|
|
1225
1218
|
},
|
|
1226
|
-
{
|
|
1227
|
-
Component: PayPalGooglePayPage,
|
|
1228
|
-
path: "/settings/paypal/google-pay"
|
|
1229
|
-
},
|
|
1230
1219
|
{
|
|
1231
1220
|
Component: PayPalConnectionPage,
|
|
1232
1221
|
path: "/settings/paypal/connection"
|
|
1233
1222
|
},
|
|
1223
|
+
{
|
|
1224
|
+
Component: PayPalGooglePayPage,
|
|
1225
|
+
path: "/settings/paypal/google-pay"
|
|
1226
|
+
},
|
|
1234
1227
|
{
|
|
1235
1228
|
Component: PayPalPayLaterMessagingPage,
|
|
1236
1229
|
path: "/settings/paypal/pay-later-messaging"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/admin/paypal/save-credentials/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAG7E,wBAAsB,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/admin/paypal/save-credentials/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAG7E,wBAAsB,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,cAAc,2BAkBjE"}
|
|
@@ -7,7 +7,11 @@ async function POST(req, res) {
|
|
|
7
7
|
if (!body?.clientId || !body?.clientSecret) {
|
|
8
8
|
return res.status(400).json({ message: "Missing clientId/clientSecret" });
|
|
9
9
|
}
|
|
10
|
-
await paypal.
|
|
10
|
+
await paypal.saveAndHydrateSellerCredentials({
|
|
11
|
+
clientId: body.clientId,
|
|
12
|
+
clientSecret: body.clientSecret,
|
|
13
|
+
environment: body.environment,
|
|
14
|
+
});
|
|
11
15
|
return res.json({ ok: true });
|
|
12
16
|
}
|
|
13
17
|
//# sourceMappingURL=route.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/admin/paypal/save-credentials/route.ts"],"names":[],"mappings":";;AAGA,
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/admin/paypal/save-credentials/route.ts"],"names":[],"mappings":";;AAGA,oBAkBC;AAlBM,KAAK,UAAU,IAAI,CAAC,GAAkB,EAAE,GAAmB;IAChE,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAsB,mBAAmB,CAAC,CAAA;IAC1E,MAAM,IAAI,GAAG,GAAG,CAAC,IAIhB,CAAA;IAED,IAAI,CAAC,IAAI,EAAE,QAAQ,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;QAC3C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED,MAAM,MAAM,CAAC,+BAA+B,CAAC;QAC3C,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC,CAAA;IACF,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;AAC/B,CAAC"}
|
|
@@ -64,6 +64,9 @@ declare class PayPalModuleService extends PayPalModuleService_base {
|
|
|
64
64
|
private getEnvCreds;
|
|
65
65
|
private extractSellerEmail;
|
|
66
66
|
private fetchMerchantIntegrationDetails;
|
|
67
|
+
private getAppAccessTokenForCredentials;
|
|
68
|
+
private fetchSellerProfileFromDirectCredentials;
|
|
69
|
+
private hydrateSellerMetadataFromCredentials;
|
|
67
70
|
private syncRowFieldsFromMetadata;
|
|
68
71
|
/**
|
|
69
72
|
* Set environment based on admin UI selection (WooCommerce-style).
|
|
@@ -129,6 +132,7 @@ declare class PayPalModuleService extends PayPalModuleService_base {
|
|
|
129
132
|
clientSecret: string;
|
|
130
133
|
sellerMerchantId?: string | null;
|
|
131
134
|
sellerEmail?: string | null;
|
|
135
|
+
environment?: Environment;
|
|
132
136
|
}): Promise<{
|
|
133
137
|
id: string;
|
|
134
138
|
environment: string;
|
|
@@ -146,6 +150,33 @@ declare class PayPalModuleService extends PayPalModuleService_base {
|
|
|
146
150
|
updated_at: Date;
|
|
147
151
|
deleted_at: Date | null;
|
|
148
152
|
}>;
|
|
153
|
+
saveAndHydrateSellerCredentials(input: {
|
|
154
|
+
clientId: string;
|
|
155
|
+
clientSecret: string;
|
|
156
|
+
environment?: Environment;
|
|
157
|
+
}): Promise<{
|
|
158
|
+
environment: Environment;
|
|
159
|
+
status: Status;
|
|
160
|
+
seller_client_id_present: boolean;
|
|
161
|
+
shared_id?: undefined;
|
|
162
|
+
auth_code?: undefined;
|
|
163
|
+
seller_client_id_masked?: undefined;
|
|
164
|
+
seller_client_secret_masked?: undefined;
|
|
165
|
+
seller_merchant_id?: undefined;
|
|
166
|
+
seller_email?: undefined;
|
|
167
|
+
updated_at?: undefined;
|
|
168
|
+
} | {
|
|
169
|
+
environment: Environment;
|
|
170
|
+
status: Status;
|
|
171
|
+
shared_id: any;
|
|
172
|
+
auth_code: string | null;
|
|
173
|
+
seller_client_id_present: boolean;
|
|
174
|
+
seller_client_id_masked: string | null;
|
|
175
|
+
seller_client_secret_masked: string | null;
|
|
176
|
+
seller_merchant_id: string | null;
|
|
177
|
+
seller_email: string | null;
|
|
178
|
+
updated_at: any;
|
|
179
|
+
}>;
|
|
149
180
|
private resolveWebhookUrl;
|
|
150
181
|
private isLocalWebhookUrl;
|
|
151
182
|
private ensureWebhookRegistration;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../src/modules/paypal/service.ts"],"names":[],"mappings":"AASA,KAAK,WAAW,GAAG,SAAS,GAAG,MAAM,CAAA;AAErC,KAAK,MAAM,GACP,cAAc,GACd,SAAS,GACT,qBAAqB,GACrB,WAAW,GACX,SAAS,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEb,cAAM,mBAAoB,SAAQ,wBAKhC;IACA,SAAS,CAAC,GAAG,8CAAoB;YAEnB,eAAe;YAKf,sBAAsB;IA0D9B,aAAa;;;;IAQnB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;YAmBZ,oBAAoB;IAKlC;;;OAGG;YACW,aAAa;YAKb,qBAAqB;IAUnC,OAAO,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../src/modules/paypal/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -160,7 +160,12 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
160
160
|
return {
|
|
161
161
|
clientId: creds.client_id || creds.clientId || undefined,
|
|
162
162
|
clientSecret: creds.client_secret || creds.clientSecret || undefined,
|
|
163
|
-
sellerMerchantId: creds.seller_merchant_id ||
|
|
163
|
+
sellerMerchantId: creds.seller_merchant_id ||
|
|
164
|
+
creds.sellerMerchantId ||
|
|
165
|
+
creds.payer_id ||
|
|
166
|
+
creds.merchant_id ||
|
|
167
|
+
creds.merchantId ||
|
|
168
|
+
undefined,
|
|
164
169
|
sellerEmail: creds.seller_email || creds.sellerEmail || undefined,
|
|
165
170
|
};
|
|
166
171
|
}
|
|
@@ -239,6 +244,121 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
239
244
|
}
|
|
240
245
|
return json;
|
|
241
246
|
}
|
|
247
|
+
async getAppAccessTokenForCredentials(env, credentials) {
|
|
248
|
+
const baseUrl = env === "live" ? "https://api-m.paypal.com" : "https://api-m.sandbox.paypal.com";
|
|
249
|
+
const basic = Buffer.from(`${credentials.clientId}:${credentials.clientSecret}`).toString("base64");
|
|
250
|
+
const body = new URLSearchParams();
|
|
251
|
+
body.set("grant_type", "client_credentials");
|
|
252
|
+
const res = await fetch(`${baseUrl}/v1/oauth2/token`, {
|
|
253
|
+
method: "POST",
|
|
254
|
+
headers: {
|
|
255
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
256
|
+
Authorization: `Basic ${basic}`,
|
|
257
|
+
},
|
|
258
|
+
body,
|
|
259
|
+
});
|
|
260
|
+
const text = await res.text().catch(() => "");
|
|
261
|
+
let json = {};
|
|
262
|
+
try {
|
|
263
|
+
json = text ? JSON.parse(text) : {};
|
|
264
|
+
}
|
|
265
|
+
catch (e) {
|
|
266
|
+
console.warn("[PayPal] Failed to parse app token response JSON:", e?.message);
|
|
267
|
+
}
|
|
268
|
+
if (!res.ok) {
|
|
269
|
+
throw new Error(`PayPal client_credentials failed (${res.status}): ${text || JSON.stringify(json)}`);
|
|
270
|
+
}
|
|
271
|
+
const accessToken = String(json.access_token || "");
|
|
272
|
+
if (!accessToken) {
|
|
273
|
+
throw new Error("PayPal client_credentials succeeded but access_token is missing.");
|
|
274
|
+
}
|
|
275
|
+
return { accessToken, tokenPayload: json };
|
|
276
|
+
}
|
|
277
|
+
async fetchSellerProfileFromDirectCredentials(env, credentials) {
|
|
278
|
+
const baseUrl = env === "live" ? "https://api-m.paypal.com" : "https://api-m.sandbox.paypal.com";
|
|
279
|
+
const partnerMerchantId = await this.getPartnerMerchantId(env);
|
|
280
|
+
let tokenPayload = null;
|
|
281
|
+
let accessToken = "";
|
|
282
|
+
if (credentials) {
|
|
283
|
+
const tokenResp = await this.getAppAccessTokenForCredentials(env, {
|
|
284
|
+
clientId: credentials.clientId,
|
|
285
|
+
clientSecret: credentials.clientSecret,
|
|
286
|
+
});
|
|
287
|
+
accessToken = tokenResp.accessToken;
|
|
288
|
+
tokenPayload = tokenResp.tokenPayload;
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
accessToken = await this.getAppAccessToken();
|
|
292
|
+
}
|
|
293
|
+
let sellerEmail = this.extractSellerEmail(tokenPayload || undefined);
|
|
294
|
+
let sellerMerchantId = String(tokenPayload?.merchant_id || tokenPayload?.payer_id || tokenPayload?.account_id || "").trim() || null;
|
|
295
|
+
try {
|
|
296
|
+
const userInfoResp = await fetch(`${baseUrl}/v1/identity/oauth2/userinfo?schema=paypalv1`, {
|
|
297
|
+
method: "GET",
|
|
298
|
+
headers: {
|
|
299
|
+
Authorization: `Bearer ${accessToken}`,
|
|
300
|
+
"Content-Type": "application/json",
|
|
301
|
+
Accept: "application/json",
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
if (userInfoResp.ok) {
|
|
305
|
+
const userInfo = await userInfoResp.json().catch(() => ({}));
|
|
306
|
+
sellerEmail = sellerEmail || this.extractSellerEmail(userInfo);
|
|
307
|
+
sellerMerchantId =
|
|
308
|
+
sellerMerchantId ||
|
|
309
|
+
String(userInfo?.merchant_id || userInfo?.payer_id || userInfo?.user_id || userInfo?.sub || "").trim() ||
|
|
310
|
+
null;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (e) {
|
|
314
|
+
console.warn("[PayPal] userinfo lookup failed:", e?.message || e);
|
|
315
|
+
}
|
|
316
|
+
if (partnerMerchantId) {
|
|
317
|
+
try {
|
|
318
|
+
const credsResp = await fetch(`${baseUrl}/v1/customer/partners/${encodeURIComponent(partnerMerchantId)}/merchant-integrations/credentials/`, {
|
|
319
|
+
method: "GET",
|
|
320
|
+
headers: {
|
|
321
|
+
Authorization: `Bearer ${accessToken}`,
|
|
322
|
+
"Content-Type": "application/json",
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
if (credsResp.ok) {
|
|
326
|
+
const credsJson = await credsResp.json().catch(() => ({}));
|
|
327
|
+
sellerEmail = sellerEmail || this.extractSellerEmail(credsJson);
|
|
328
|
+
sellerMerchantId = sellerMerchantId || String(credsJson?.merchant_id || "").trim() || null;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch (e) {
|
|
332
|
+
console.warn("[PayPal] direct credential profile lookup failed:", e?.message || e);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const hydrated = await this.hydrateSellerMetadataFromCredentials(env, {
|
|
336
|
+
accessToken,
|
|
337
|
+
sellerMerchantId,
|
|
338
|
+
sellerEmail,
|
|
339
|
+
});
|
|
340
|
+
return {
|
|
341
|
+
sellerMerchantId: hydrated.sellerMerchantId,
|
|
342
|
+
sellerEmail: hydrated.sellerEmail,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
async hydrateSellerMetadataFromCredentials(env, input) {
|
|
346
|
+
let sellerMerchantId = (input.sellerMerchantId || "").trim() || null;
|
|
347
|
+
let sellerEmail = (input.sellerEmail || "").trim() || null;
|
|
348
|
+
if (!sellerEmail && input.metadataCandidates?.length) {
|
|
349
|
+
sellerEmail = this.extractSellerEmail(...input.metadataCandidates);
|
|
350
|
+
}
|
|
351
|
+
if (sellerMerchantId && !sellerEmail) {
|
|
352
|
+
try {
|
|
353
|
+
const details = await this.fetchMerchantIntegrationDetails(env, sellerMerchantId, input.accessToken);
|
|
354
|
+
sellerEmail = this.extractSellerEmail(details);
|
|
355
|
+
}
|
|
356
|
+
catch (e) {
|
|
357
|
+
console.warn("[PayPal] merchant integration lookup failed:", e?.message || e);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return { sellerMerchantId, sellerEmail };
|
|
361
|
+
}
|
|
242
362
|
async syncRowFieldsFromMetadata(row, env) {
|
|
243
363
|
const c = this.getEnvCreds(row, env);
|
|
244
364
|
await this.updatePayPalConnections({
|
|
@@ -531,19 +651,21 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
531
651
|
if (!credRes.ok) {
|
|
532
652
|
throw new Error(`PayPal credentials fetch failed (${credRes.status}): ${credText || JSON.stringify(credJson)}`);
|
|
533
653
|
}
|
|
534
|
-
const clientId = String(credJson.client_id || "");
|
|
535
|
-
const clientSecret = String(credJson.client_secret || "");
|
|
654
|
+
const clientId = String(credJson.client_id || credJson.clientId || "");
|
|
655
|
+
const clientSecret = String(credJson.client_secret || credJson.clientSecret || "");
|
|
536
656
|
if (!clientId || !clientSecret) {
|
|
537
657
|
throw new Error(`PayPal credentials response missing client_id/client_secret. Keys: ${Object.keys(credJson || {}).join(", ")}`);
|
|
538
658
|
}
|
|
539
659
|
let sellerEmail = this.extractSellerEmail(credJson, tokenJson);
|
|
540
|
-
let sellerMerchantId = String(credJson.
|
|
660
|
+
let sellerMerchantId = String(credJson.payer_id || credJson.merchant_id || tokenJson.payer_id || tokenJson.merchant_id || "").trim() ||
|
|
661
|
+
null;
|
|
541
662
|
if (!sellerEmail) {
|
|
542
663
|
// Use all available merchant/payer ID candidates from the token and credential responses
|
|
543
664
|
const merchantCandidates = [
|
|
665
|
+
String(credJson.payer_id || "").trim(),
|
|
544
666
|
String(credJson.merchant_id || "").trim(),
|
|
545
|
-
String(tokenJson.merchant_id || "").trim(),
|
|
546
667
|
String(tokenJson.payer_id || "").trim(),
|
|
668
|
+
String(tokenJson.merchant_id || "").trim(),
|
|
547
669
|
].filter(Boolean).filter((v, i, arr) => arr.indexOf(v) === i);
|
|
548
670
|
for (const merchantId of merchantCandidates) {
|
|
549
671
|
try {
|
|
@@ -586,13 +708,24 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
586
708
|
}
|
|
587
709
|
async saveSellerCredentials(input) {
|
|
588
710
|
const row = await this.getCurrentRow();
|
|
589
|
-
const
|
|
711
|
+
const currentEnv = await this.getCurrentEnvironment();
|
|
712
|
+
const env = (input.environment || currentEnv);
|
|
590
713
|
const encryptedSecret = this.maybeEncryptSecret(input.clientSecret);
|
|
714
|
+
const existingCreds = row ? this.getEnvCreds(row, env) : {};
|
|
715
|
+
const nextSellerMerchantId = (input.sellerMerchantId || "").trim() || existingCreds.sellerMerchantId || row?.seller_merchant_id || null;
|
|
716
|
+
const nextSellerEmail = (input.sellerEmail || "").trim() || existingCreds.sellerEmail || row?.seller_email || null;
|
|
591
717
|
const nextCreds = {
|
|
592
718
|
client_id: input.clientId,
|
|
719
|
+
clientId: input.clientId,
|
|
593
720
|
client_secret: encryptedSecret,
|
|
594
|
-
|
|
595
|
-
|
|
721
|
+
clientSecret: encryptedSecret,
|
|
722
|
+
merchantId: nextSellerMerchantId,
|
|
723
|
+
merchant_id: nextSellerMerchantId,
|
|
724
|
+
payer_id: nextSellerMerchantId,
|
|
725
|
+
seller_merchant_id: nextSellerMerchantId,
|
|
726
|
+
sellerMerchantId: nextSellerMerchantId,
|
|
727
|
+
seller_email: nextSellerEmail,
|
|
728
|
+
sellerEmail: nextSellerEmail,
|
|
596
729
|
};
|
|
597
730
|
if (!row) {
|
|
598
731
|
const created = await this.createPayPalConnections({
|
|
@@ -600,8 +733,8 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
600
733
|
status: "connected",
|
|
601
734
|
seller_client_id: input.clientId,
|
|
602
735
|
seller_client_secret: encryptedSecret,
|
|
603
|
-
seller_merchant_id:
|
|
604
|
-
seller_email:
|
|
736
|
+
seller_merchant_id: nextSellerMerchantId,
|
|
737
|
+
seller_email: nextSellerEmail,
|
|
605
738
|
app_access_token: null,
|
|
606
739
|
app_access_token_expires_at: null,
|
|
607
740
|
metadata: {
|
|
@@ -629,8 +762,8 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
629
762
|
status: "connected",
|
|
630
763
|
seller_client_id: input.clientId,
|
|
631
764
|
seller_client_secret: encryptedSecret,
|
|
632
|
-
seller_merchant_id:
|
|
633
|
-
seller_email:
|
|
765
|
+
seller_merchant_id: nextSellerMerchantId,
|
|
766
|
+
seller_email: nextSellerEmail,
|
|
634
767
|
app_access_token: null,
|
|
635
768
|
app_access_token_expires_at: null,
|
|
636
769
|
metadata: {
|
|
@@ -646,6 +779,37 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
646
779
|
await this.ensureWebhookRegistration();
|
|
647
780
|
return updated;
|
|
648
781
|
}
|
|
782
|
+
async saveAndHydrateSellerCredentials(input) {
|
|
783
|
+
const env = (input.environment || (await this.getCurrentEnvironment()));
|
|
784
|
+
await this.saveSellerCredentials({
|
|
785
|
+
clientId: input.clientId,
|
|
786
|
+
clientSecret: input.clientSecret,
|
|
787
|
+
environment: env,
|
|
788
|
+
});
|
|
789
|
+
try {
|
|
790
|
+
const hydrated = await this.fetchSellerProfileFromDirectCredentials(env, {
|
|
791
|
+
clientId: input.clientId,
|
|
792
|
+
clientSecret: input.clientSecret,
|
|
793
|
+
});
|
|
794
|
+
if (hydrated.sellerEmail || hydrated.sellerMerchantId) {
|
|
795
|
+
await this.saveSellerCredentials({
|
|
796
|
+
clientId: input.clientId,
|
|
797
|
+
clientSecret: input.clientSecret,
|
|
798
|
+
sellerMerchantId: hydrated.sellerMerchantId,
|
|
799
|
+
sellerEmail: hydrated.sellerEmail,
|
|
800
|
+
environment: env,
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
const refreshedRow = await this.getCurrentRow();
|
|
804
|
+
if (refreshedRow) {
|
|
805
|
+
await this.syncRowFieldsFromMetadata(refreshedRow, env);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
catch (e) {
|
|
809
|
+
console.warn("[PayPal] saveAndHydrateSellerCredentials lookup failed:", e?.message || e);
|
|
810
|
+
}
|
|
811
|
+
return await this.getStatus(env);
|
|
812
|
+
}
|
|
649
813
|
async resolveWebhookUrl() {
|
|
650
814
|
const { onboarding } = await this.ensureSettingsDefaults();
|
|
651
815
|
const base = String(onboarding.backend_url || "").replace(/\/$/, "");
|
|
@@ -807,23 +971,38 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
807
971
|
const c = this.getEnvCreds(row, env);
|
|
808
972
|
const hasCreds = !!(c.clientId && c.clientSecret);
|
|
809
973
|
let sellerEmail = c.sellerEmail || row.seller_email || null;
|
|
810
|
-
|
|
811
|
-
|
|
974
|
+
let sellerMerchantId = c.sellerMerchantId || row.seller_merchant_id || null;
|
|
975
|
+
let decryptedSecret = null;
|
|
976
|
+
if (c.clientSecret) {
|
|
977
|
+
try {
|
|
978
|
+
decryptedSecret = this.maybeDecryptSecret(c.clientSecret);
|
|
979
|
+
}
|
|
980
|
+
catch (e) {
|
|
981
|
+
console.warn("[PayPal] Unable to decrypt seller client secret for status sync:", e?.message || e);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
if (!sellerEmail && hasCreds) {
|
|
812
985
|
try {
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
if (fetchedEmail) {
|
|
816
|
-
sellerEmail = fetchedEmail;
|
|
986
|
+
const hydrated = await this.fetchSellerProfileFromDirectCredentials(env);
|
|
987
|
+
if (hydrated.sellerEmail || hydrated.sellerMerchantId) {
|
|
817
988
|
await this.saveSellerCredentials({
|
|
818
989
|
clientId: c.clientId,
|
|
819
|
-
clientSecret: c.clientSecret,
|
|
820
|
-
sellerMerchantId,
|
|
821
|
-
sellerEmail,
|
|
990
|
+
clientSecret: decryptedSecret || c.clientSecret,
|
|
991
|
+
sellerMerchantId: hydrated.sellerMerchantId || sellerMerchantId,
|
|
992
|
+
sellerEmail: hydrated.sellerEmail || sellerEmail,
|
|
993
|
+
environment: env,
|
|
822
994
|
});
|
|
995
|
+
const refreshedRow = await this.getCurrentRow();
|
|
996
|
+
if (refreshedRow) {
|
|
997
|
+
const refreshedCreds = this.getEnvCreds(refreshedRow, env);
|
|
998
|
+
sellerEmail = refreshedCreds.sellerEmail || refreshedRow.seller_email || sellerEmail;
|
|
999
|
+
sellerMerchantId =
|
|
1000
|
+
refreshedCreds.sellerMerchantId || refreshedRow.seller_merchant_id || sellerMerchantId;
|
|
1001
|
+
}
|
|
823
1002
|
}
|
|
824
1003
|
}
|
|
825
1004
|
catch (e) {
|
|
826
|
-
console.warn("[PayPal] status
|
|
1005
|
+
console.warn("[PayPal] status direct credential lookup failed:", e?.message || e);
|
|
827
1006
|
}
|
|
828
1007
|
}
|
|
829
1008
|
return {
|