@easypayment/medusa-paypal 0.5.7 → 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 +33 -0
- package/.medusa/server/src/modules/paypal/service.d.ts.map +1 -1
- package/.medusa/server/src/modules/paypal/service.js +229 -46
- 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 +279 -48
|
@@ -183,9 +183,6 @@ function AdditionalSettingsTab() {
|
|
|
183
183
|
)
|
|
184
184
|
] }) });
|
|
185
185
|
}
|
|
186
|
-
function PayPalApplePayPage() {
|
|
187
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
188
|
-
}
|
|
189
186
|
async function adminFetch$1(path, opts = {}) {
|
|
190
187
|
var _a;
|
|
191
188
|
const { method = "GET", body, query } = opts;
|
|
@@ -325,6 +322,9 @@ function AdvancedCardPaymentsTab() {
|
|
|
325
322
|
)
|
|
326
323
|
] }) });
|
|
327
324
|
}
|
|
325
|
+
function PayPalApplePayPage() {
|
|
326
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
327
|
+
}
|
|
328
328
|
const config = adminSdk.defineRouteConfig({
|
|
329
329
|
label: "PayPal Connection",
|
|
330
330
|
hide: true
|
|
@@ -401,15 +401,6 @@ function PayPalConnectionPage() {
|
|
|
401
401
|
const canSaveManual = react.useMemo(() => {
|
|
402
402
|
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
403
403
|
}, [clientId, secret]);
|
|
404
|
-
const maskValue = react.useCallback((value, visibleChars = 4) => {
|
|
405
|
-
if (!value) return "";
|
|
406
|
-
if (value.length <= visibleChars) {
|
|
407
|
-
return "•".repeat(value.length);
|
|
408
|
-
}
|
|
409
|
-
return `${"•".repeat(Math.max(0, value.length - visibleChars))}${value.slice(
|
|
410
|
-
-visibleChars
|
|
411
|
-
)}`;
|
|
412
|
-
}, []);
|
|
413
404
|
const fetchFreshLink = react.useCallback(
|
|
414
405
|
(runId) => {
|
|
415
406
|
if (initLoaderRef.current) {
|
|
@@ -608,18 +599,20 @@ function PayPalConnectionPage() {
|
|
|
608
599
|
headers: { "content-type": "application/json" },
|
|
609
600
|
body: JSON.stringify({
|
|
610
601
|
clientId: clientId.trim(),
|
|
611
|
-
clientSecret: secret.trim()
|
|
602
|
+
clientSecret: secret.trim(),
|
|
603
|
+
environment: env
|
|
612
604
|
})
|
|
613
605
|
});
|
|
614
606
|
if (!res.ok) {
|
|
615
607
|
const txt = await res.text().catch(() => "");
|
|
616
608
|
throw new Error(txt || `Save credentials failed (${res.status})`);
|
|
617
609
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
seller_client_id_masked: maskValue(clientId.trim()),
|
|
621
|
-
seller_client_secret_masked: "••••••••"
|
|
610
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
611
|
+
method: "GET"
|
|
622
612
|
});
|
|
613
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
614
|
+
setConnState("connected");
|
|
615
|
+
setStatusInfo(refreshedStatus || null);
|
|
623
616
|
setShowManual(false);
|
|
624
617
|
try {
|
|
625
618
|
localStorage.removeItem(CACHE_KEY);
|
|
@@ -1216,14 +1209,14 @@ const routeModule = {
|
|
|
1216
1209
|
Component: AdditionalSettingsTab,
|
|
1217
1210
|
path: "/settings/paypal/additional-settings"
|
|
1218
1211
|
},
|
|
1219
|
-
{
|
|
1220
|
-
Component: PayPalApplePayPage,
|
|
1221
|
-
path: "/settings/paypal/apple-pay"
|
|
1222
|
-
},
|
|
1223
1212
|
{
|
|
1224
1213
|
Component: AdvancedCardPaymentsTab,
|
|
1225
1214
|
path: "/settings/paypal/advanced-card-payments"
|
|
1226
1215
|
},
|
|
1216
|
+
{
|
|
1217
|
+
Component: PayPalApplePayPage,
|
|
1218
|
+
path: "/settings/paypal/apple-pay"
|
|
1219
|
+
},
|
|
1227
1220
|
{
|
|
1228
1221
|
Component: PayPalConnectionPage,
|
|
1229
1222
|
path: "/settings/paypal/connection"
|
|
@@ -182,9 +182,6 @@ function AdditionalSettingsTab() {
|
|
|
182
182
|
)
|
|
183
183
|
] }) });
|
|
184
184
|
}
|
|
185
|
-
function PayPalApplePayPage() {
|
|
186
|
-
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
187
|
-
}
|
|
188
185
|
async function adminFetch$1(path, opts = {}) {
|
|
189
186
|
var _a;
|
|
190
187
|
const { method = "GET", body, query } = opts;
|
|
@@ -324,6 +321,9 @@ function AdvancedCardPaymentsTab() {
|
|
|
324
321
|
)
|
|
325
322
|
] }) });
|
|
326
323
|
}
|
|
324
|
+
function PayPalApplePayPage() {
|
|
325
|
+
return /* @__PURE__ */ jsx(Navigate, { to: "/settings/paypal/connection", replace: true });
|
|
326
|
+
}
|
|
327
327
|
const config = defineRouteConfig({
|
|
328
328
|
label: "PayPal Connection",
|
|
329
329
|
hide: true
|
|
@@ -400,15 +400,6 @@ function PayPalConnectionPage() {
|
|
|
400
400
|
const canSaveManual = useMemo(() => {
|
|
401
401
|
return clientId.trim().length > 0 && secret.trim().length > 0;
|
|
402
402
|
}, [clientId, secret]);
|
|
403
|
-
const maskValue = useCallback((value, visibleChars = 4) => {
|
|
404
|
-
if (!value) return "";
|
|
405
|
-
if (value.length <= visibleChars) {
|
|
406
|
-
return "•".repeat(value.length);
|
|
407
|
-
}
|
|
408
|
-
return `${"•".repeat(Math.max(0, value.length - visibleChars))}${value.slice(
|
|
409
|
-
-visibleChars
|
|
410
|
-
)}`;
|
|
411
|
-
}, []);
|
|
412
403
|
const fetchFreshLink = useCallback(
|
|
413
404
|
(runId) => {
|
|
414
405
|
if (initLoaderRef.current) {
|
|
@@ -607,18 +598,20 @@ function PayPalConnectionPage() {
|
|
|
607
598
|
headers: { "content-type": "application/json" },
|
|
608
599
|
body: JSON.stringify({
|
|
609
600
|
clientId: clientId.trim(),
|
|
610
|
-
clientSecret: secret.trim()
|
|
601
|
+
clientSecret: secret.trim(),
|
|
602
|
+
environment: env
|
|
611
603
|
})
|
|
612
604
|
});
|
|
613
605
|
if (!res.ok) {
|
|
614
606
|
const txt = await res.text().catch(() => "");
|
|
615
607
|
throw new Error(txt || `Save credentials failed (${res.status})`);
|
|
616
608
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
seller_client_id_masked: maskValue(clientId.trim()),
|
|
620
|
-
seller_client_secret_masked: "••••••••"
|
|
609
|
+
const statusRes = await fetch(`${STATUS_ENDPOINT}?environment=${env}`, {
|
|
610
|
+
method: "GET"
|
|
621
611
|
});
|
|
612
|
+
const refreshedStatus = await statusRes.json().catch(() => ({}));
|
|
613
|
+
setConnState("connected");
|
|
614
|
+
setStatusInfo(refreshedStatus || null);
|
|
622
615
|
setShowManual(false);
|
|
623
616
|
try {
|
|
624
617
|
localStorage.removeItem(CACHE_KEY);
|
|
@@ -1215,14 +1208,14 @@ const routeModule = {
|
|
|
1215
1208
|
Component: AdditionalSettingsTab,
|
|
1216
1209
|
path: "/settings/paypal/additional-settings"
|
|
1217
1210
|
},
|
|
1218
|
-
{
|
|
1219
|
-
Component: PayPalApplePayPage,
|
|
1220
|
-
path: "/settings/paypal/apple-pay"
|
|
1221
|
-
},
|
|
1222
1211
|
{
|
|
1223
1212
|
Component: AdvancedCardPaymentsTab,
|
|
1224
1213
|
path: "/settings/paypal/advanced-card-payments"
|
|
1225
1214
|
},
|
|
1215
|
+
{
|
|
1216
|
+
Component: PayPalApplePayPage,
|
|
1217
|
+
path: "/settings/paypal/apple-pay"
|
|
1218
|
+
},
|
|
1226
1219
|
{
|
|
1227
1220
|
Component: PayPalConnectionPage,
|
|
1228
1221
|
path: "/settings/paypal/connection"
|
|
@@ -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;
|
|
@@ -161,6 +192,7 @@ declare class PayPalModuleService extends PayPalModuleService_base {
|
|
|
161
192
|
auth_code?: undefined;
|
|
162
193
|
seller_client_id_masked?: undefined;
|
|
163
194
|
seller_client_secret_masked?: undefined;
|
|
195
|
+
seller_merchant_id?: undefined;
|
|
164
196
|
seller_email?: undefined;
|
|
165
197
|
updated_at?: undefined;
|
|
166
198
|
} | {
|
|
@@ -171,6 +203,7 @@ declare class PayPalModuleService extends PayPalModuleService_base {
|
|
|
171
203
|
seller_client_id_present: boolean;
|
|
172
204
|
seller_client_id_masked: string | null;
|
|
173
205
|
seller_client_secret_masked: string | null;
|
|
206
|
+
seller_merchant_id: string | null;
|
|
174
207
|
seller_email: string | null;
|
|
175
208
|
updated_at: any;
|
|
176
209
|
}>;
|
|
@@ -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
|
}
|
|
@@ -191,14 +196,21 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
191
196
|
obj.email_address,
|
|
192
197
|
obj.account_email,
|
|
193
198
|
obj.contact_email,
|
|
199
|
+
obj.value,
|
|
200
|
+
obj.address,
|
|
194
201
|
];
|
|
195
202
|
queue.push(...prioritized);
|
|
196
203
|
for (const [k, v] of Object.entries(obj)) {
|
|
197
204
|
const key = String(k).toLowerCase();
|
|
198
|
-
if (key.includes("email")) {
|
|
205
|
+
if (key.includes("email") || key.includes("address")) {
|
|
199
206
|
queue.push(v);
|
|
200
207
|
}
|
|
201
208
|
}
|
|
209
|
+
// Fallback: traverse nested values so shapes like
|
|
210
|
+
// { email_address: { value: "seller@example.com" } }
|
|
211
|
+
// or { email: { address: "seller@example.com" } }
|
|
212
|
+
// are still detected.
|
|
213
|
+
queue.push(...Object.values(obj));
|
|
202
214
|
}
|
|
203
215
|
}
|
|
204
216
|
return null;
|
|
@@ -232,6 +244,121 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
232
244
|
}
|
|
233
245
|
return json;
|
|
234
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
|
+
}
|
|
235
362
|
async syncRowFieldsFromMetadata(row, env) {
|
|
236
363
|
const c = this.getEnvCreds(row, env);
|
|
237
364
|
await this.updatePayPalConnections({
|
|
@@ -524,19 +651,21 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
524
651
|
if (!credRes.ok) {
|
|
525
652
|
throw new Error(`PayPal credentials fetch failed (${credRes.status}): ${credText || JSON.stringify(credJson)}`);
|
|
526
653
|
}
|
|
527
|
-
const clientId = String(credJson.client_id || "");
|
|
528
|
-
const clientSecret = String(credJson.client_secret || "");
|
|
654
|
+
const clientId = String(credJson.client_id || credJson.clientId || "");
|
|
655
|
+
const clientSecret = String(credJson.client_secret || credJson.clientSecret || "");
|
|
529
656
|
if (!clientId || !clientSecret) {
|
|
530
657
|
throw new Error(`PayPal credentials response missing client_id/client_secret. Keys: ${Object.keys(credJson || {}).join(", ")}`);
|
|
531
658
|
}
|
|
532
659
|
let sellerEmail = this.extractSellerEmail(credJson, tokenJson);
|
|
533
|
-
let sellerMerchantId = String(credJson.
|
|
660
|
+
let sellerMerchantId = String(credJson.payer_id || credJson.merchant_id || tokenJson.payer_id || tokenJson.merchant_id || "").trim() ||
|
|
661
|
+
null;
|
|
534
662
|
if (!sellerEmail) {
|
|
535
663
|
// Use all available merchant/payer ID candidates from the token and credential responses
|
|
536
664
|
const merchantCandidates = [
|
|
665
|
+
String(credJson.payer_id || "").trim(),
|
|
537
666
|
String(credJson.merchant_id || "").trim(),
|
|
538
|
-
String(tokenJson.merchant_id || "").trim(),
|
|
539
667
|
String(tokenJson.payer_id || "").trim(),
|
|
668
|
+
String(tokenJson.merchant_id || "").trim(),
|
|
540
669
|
].filter(Boolean).filter((v, i, arr) => arr.indexOf(v) === i);
|
|
541
670
|
for (const merchantId of merchantCandidates) {
|
|
542
671
|
try {
|
|
@@ -560,55 +689,43 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
560
689
|
sellerMerchantId,
|
|
561
690
|
sellerEmail,
|
|
562
691
|
});
|
|
563
|
-
// 5) Post-save email lookup via
|
|
564
|
-
//
|
|
565
|
-
//
|
|
566
|
-
|
|
567
|
-
if (!sellerEmail && input.sharedId) {
|
|
692
|
+
// 5) Post-save email lookup via merchant_id.
|
|
693
|
+
// Some partner accounts do not have permission to query by tracking_id,
|
|
694
|
+
// so we only rely on merchant integration detail lookup.
|
|
695
|
+
if (!sellerEmail && sellerMerchantId) {
|
|
568
696
|
try {
|
|
569
697
|
const appAccessToken = await this.getAppAccessToken();
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
"Content-Type": "application/json",
|
|
575
|
-
Authorization: `Bearer ${appAccessToken}`,
|
|
576
|
-
...(onboardingCfg.bn_code ? { "PayPal-Partner-Attribution-Id": onboardingCfg.bn_code } : {}),
|
|
577
|
-
},
|
|
578
|
-
});
|
|
579
|
-
if (trackingRes.ok) {
|
|
580
|
-
const trackingJson = await trackingRes.json().catch(() => ({}));
|
|
581
|
-
sellerEmail = this.extractSellerEmail(trackingJson);
|
|
582
|
-
const foundMerchantId = String(trackingJson.merchant_id || "").trim();
|
|
583
|
-
if (foundMerchantId) {
|
|
584
|
-
sellerMerchantId = sellerMerchantId || foundMerchantId;
|
|
585
|
-
}
|
|
586
|
-
if (!sellerEmail && foundMerchantId) {
|
|
587
|
-
const details = await this.fetchMerchantIntegrationDetails(env, foundMerchantId, appAccessToken);
|
|
588
|
-
sellerEmail = this.extractSellerEmail(details);
|
|
589
|
-
}
|
|
590
|
-
if (sellerEmail || sellerMerchantId) {
|
|
591
|
-
await this.saveSellerCredentials({ clientId, clientSecret, sellerMerchantId, sellerEmail });
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
else {
|
|
595
|
-
console.warn(`[PayPal] tracking_id lookup failed (${trackingRes.status})`);
|
|
698
|
+
const details = await this.fetchMerchantIntegrationDetails(env, sellerMerchantId, appAccessToken);
|
|
699
|
+
sellerEmail = this.extractSellerEmail(details);
|
|
700
|
+
if (sellerEmail) {
|
|
701
|
+
await this.saveSellerCredentials({ clientId, clientSecret, sellerMerchantId, sellerEmail });
|
|
596
702
|
}
|
|
597
703
|
}
|
|
598
704
|
catch (e) {
|
|
599
|
-
console.warn("[PayPal] Post-save
|
|
705
|
+
console.warn("[PayPal] Post-save merchant_id email lookup failed:", e?.message || e);
|
|
600
706
|
}
|
|
601
707
|
}
|
|
602
708
|
}
|
|
603
709
|
async saveSellerCredentials(input) {
|
|
604
710
|
const row = await this.getCurrentRow();
|
|
605
|
-
const
|
|
711
|
+
const currentEnv = await this.getCurrentEnvironment();
|
|
712
|
+
const env = (input.environment || currentEnv);
|
|
606
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;
|
|
607
717
|
const nextCreds = {
|
|
608
718
|
client_id: input.clientId,
|
|
719
|
+
clientId: input.clientId,
|
|
609
720
|
client_secret: encryptedSecret,
|
|
610
|
-
|
|
611
|
-
|
|
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,
|
|
612
729
|
};
|
|
613
730
|
if (!row) {
|
|
614
731
|
const created = await this.createPayPalConnections({
|
|
@@ -616,8 +733,8 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
616
733
|
status: "connected",
|
|
617
734
|
seller_client_id: input.clientId,
|
|
618
735
|
seller_client_secret: encryptedSecret,
|
|
619
|
-
seller_merchant_id:
|
|
620
|
-
seller_email:
|
|
736
|
+
seller_merchant_id: nextSellerMerchantId,
|
|
737
|
+
seller_email: nextSellerEmail,
|
|
621
738
|
app_access_token: null,
|
|
622
739
|
app_access_token_expires_at: null,
|
|
623
740
|
metadata: {
|
|
@@ -645,8 +762,8 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
645
762
|
status: "connected",
|
|
646
763
|
seller_client_id: input.clientId,
|
|
647
764
|
seller_client_secret: encryptedSecret,
|
|
648
|
-
seller_merchant_id:
|
|
649
|
-
seller_email:
|
|
765
|
+
seller_merchant_id: nextSellerMerchantId,
|
|
766
|
+
seller_email: nextSellerEmail,
|
|
650
767
|
app_access_token: null,
|
|
651
768
|
app_access_token_expires_at: null,
|
|
652
769
|
metadata: {
|
|
@@ -662,6 +779,37 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
662
779
|
await this.ensureWebhookRegistration();
|
|
663
780
|
return updated;
|
|
664
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
|
+
}
|
|
665
813
|
async resolveWebhookUrl() {
|
|
666
814
|
const { onboarding } = await this.ensureSettingsDefaults();
|
|
667
815
|
const base = String(onboarding.backend_url || "").replace(/\/$/, "");
|
|
@@ -822,7 +970,41 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
822
970
|
}
|
|
823
971
|
const c = this.getEnvCreds(row, env);
|
|
824
972
|
const hasCreds = !!(c.clientId && c.clientSecret);
|
|
825
|
-
|
|
973
|
+
let sellerEmail = c.sellerEmail || row.seller_email || null;
|
|
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) {
|
|
985
|
+
try {
|
|
986
|
+
const hydrated = await this.fetchSellerProfileFromDirectCredentials(env);
|
|
987
|
+
if (hydrated.sellerEmail || hydrated.sellerMerchantId) {
|
|
988
|
+
await this.saveSellerCredentials({
|
|
989
|
+
clientId: c.clientId,
|
|
990
|
+
clientSecret: decryptedSecret || c.clientSecret,
|
|
991
|
+
sellerMerchantId: hydrated.sellerMerchantId || sellerMerchantId,
|
|
992
|
+
sellerEmail: hydrated.sellerEmail || sellerEmail,
|
|
993
|
+
environment: env,
|
|
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
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
catch (e) {
|
|
1005
|
+
console.warn("[PayPal] status direct credential lookup failed:", e?.message || e);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
826
1008
|
return {
|
|
827
1009
|
environment: env,
|
|
828
1010
|
status: (hasCreds ? "connected" : "disconnected"),
|
|
@@ -831,6 +1013,7 @@ class PayPalModuleService extends (0, utils_1.MedusaService)({
|
|
|
831
1013
|
seller_client_id_present: hasCreds,
|
|
832
1014
|
seller_client_id_masked: this.maskValue(c.clientId),
|
|
833
1015
|
seller_client_secret_masked: c.clientSecret ? "••••••••" : null,
|
|
1016
|
+
seller_merchant_id: sellerMerchantId,
|
|
834
1017
|
seller_email: sellerEmail,
|
|
835
1018
|
updated_at: row.updated_at?.toISOString?.() ?? null,
|
|
836
1019
|
};
|