@easypayment/medusa-paypal 0.5.8 → 0.6.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/admin/index.js +9 -16
- package/.medusa/server/src/admin/index.mjs +9 -16
- 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 +4 -6
- 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
|
@@ -404,15 +404,6 @@ function PayPalConnectionPage() {
|
|
|
404
404
|
const canSaveManual = react.useMemo(() => {
|
|
405
405
|
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
406
406
|
}, [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
407
|
const fetchFreshLink = react.useCallback(
|
|
417
408
|
(runId) => {
|
|
418
409
|
if (initLoaderRef.current) {
|
|
@@ -611,18 +602,20 @@ function PayPalConnectionPage() {
|
|
|
611
602
|
headers: { "content-type": "application/json" },
|
|
612
603
|
body: JSON.stringify({
|
|
613
604
|
clientId: clientId.trim(),
|
|
614
|
-
clientSecret: secret.trim()
|
|
605
|
+
clientSecret: secret.trim(),
|
|
606
|
+
environment: env
|
|
615
607
|
})
|
|
616
608
|
});
|
|
617
609
|
if (!res.ok) {
|
|
618
610
|
const txt = await res.text().catch(() => "");
|
|
619
611
|
throw new Error(txt || `Save credentials failed (${res.status})`);
|
|
620
612
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
seller_client_id_masked: maskValue(clientId.trim()),
|
|
624
|
-
seller_client_secret_masked: "••••••••"
|
|
613
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
614
|
+
method: "GET"
|
|
625
615
|
});
|
|
616
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
617
|
+
setConnState("connected");
|
|
618
|
+
setStatusInfo(refreshedStatus || null);
|
|
626
619
|
setShowManual(false);
|
|
627
620
|
try {
|
|
628
621
|
localStorage.removeItem(CACHE_KEY);
|
|
@@ -693,7 +686,7 @@ function PayPalConnectionPage() {
|
|
|
693
686
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
694
687
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold", children: "PayPal Gateway By Easy Payment" }),
|
|
695
688
|
/* @__PURE__ */ jsxRuntime.jsx(PayPalTabs, {}),
|
|
696
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-
|
|
689
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-y-6 p-4 md:grid-cols-[260px_1fr] md:items-start", children: [
|
|
697
690
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium pt-2", children: "Environment" }),
|
|
698
691
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-xl", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
699
692
|
"select",
|
|
@@ -767,7 +760,7 @@ function PayPalConnectionPage() {
|
|
|
767
760
|
href: finalUrl || "#",
|
|
768
761
|
"data-paypal-onboard-complete": "onboardingCallback",
|
|
769
762
|
onClick: handleConnectClick,
|
|
770
|
-
className: "inline-flex items-center justify-center rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-
|
|
763
|
+
className: "inline-flex items-center justify-center rounded-md border border-ui-border-base bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-base no-underline shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ui-border-interactive disabled:opacity-60",
|
|
771
764
|
style: {
|
|
772
765
|
cursor: onboardingInProgress ? "not-allowed" : "pointer",
|
|
773
766
|
opacity: onboardingInProgress ? 0.6 : 1,
|
|
@@ -403,15 +403,6 @@ function PayPalConnectionPage() {
|
|
|
403
403
|
const canSaveManual = useMemo(() => {
|
|
404
404
|
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
405
405
|
}, [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
406
|
const fetchFreshLink = useCallback(
|
|
416
407
|
(runId) => {
|
|
417
408
|
if (initLoaderRef.current) {
|
|
@@ -610,18 +601,20 @@ function PayPalConnectionPage() {
|
|
|
610
601
|
headers: { "content-type": "application/json" },
|
|
611
602
|
body: JSON.stringify({
|
|
612
603
|
clientId: clientId.trim(),
|
|
613
|
-
clientSecret: secret.trim()
|
|
604
|
+
clientSecret: secret.trim(),
|
|
605
|
+
environment: env
|
|
614
606
|
})
|
|
615
607
|
});
|
|
616
608
|
if (!res.ok) {
|
|
617
609
|
const txt = await res.text().catch(() => "");
|
|
618
610
|
throw new Error(txt || `Save credentials failed (${res.status})`);
|
|
619
611
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
seller_client_id_masked: maskValue(clientId.trim()),
|
|
623
|
-
seller_client_secret_masked: "••••••••"
|
|
612
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
613
|
+
method: "GET"
|
|
624
614
|
});
|
|
615
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
616
|
+
setConnState("connected");
|
|
617
|
+
setStatusInfo(refreshedStatus || null);
|
|
625
618
|
setShowManual(false);
|
|
626
619
|
try {
|
|
627
620
|
localStorage.removeItem(CACHE_KEY);
|
|
@@ -692,7 +685,7 @@ function PayPalConnectionPage() {
|
|
|
692
685
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
693
686
|
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold", children: "PayPal Gateway By Easy Payment" }),
|
|
694
687
|
/* @__PURE__ */ jsx(PayPalTabs, {}),
|
|
695
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-
|
|
688
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-xl border border-ui-border-base bg-ui-bg-base shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-y-6 p-4 md:grid-cols-[260px_1fr] md:items-start", children: [
|
|
696
689
|
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium pt-2", children: "Environment" }),
|
|
697
690
|
/* @__PURE__ */ jsx("div", { className: "max-w-xl", children: /* @__PURE__ */ jsxs(
|
|
698
691
|
"select",
|
|
@@ -766,7 +759,7 @@ function PayPalConnectionPage() {
|
|
|
766
759
|
href: finalUrl || "#",
|
|
767
760
|
"data-paypal-onboard-complete": "onboardingCallback",
|
|
768
761
|
onClick: handleConnectClick,
|
|
769
|
-
className: "inline-flex items-center justify-center rounded-md bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-
|
|
762
|
+
className: "inline-flex items-center justify-center rounded-md border border-ui-border-base bg-ui-button-neutral px-4 py-2 text-sm font-medium text-ui-fg-base no-underline shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ui-border-interactive disabled:opacity-60",
|
|
770
763
|
style: {
|
|
771
764
|
cursor: onboardingInProgress ? "not-allowed" : "pointer",
|
|
772
765
|
opacity: onboardingInProgress ? 0.6 : 1,
|
|
@@ -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 {
|