@goweekdays/core 2.5.0 → 2.6.1
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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +64 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +64 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -630,7 +630,7 @@ declare function useGitHubService(): {
|
|
|
630
630
|
declare function useUtilController(): {
|
|
631
631
|
healthCheck: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
632
632
|
setGitHubVariables: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
633
|
-
paypalWebhook: (req: Request, res: Response, next: NextFunction) => Promise<
|
|
633
|
+
paypalWebhook: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
634
634
|
};
|
|
635
635
|
|
|
636
636
|
declare const transactionSchema: Joi.ObjectSchema<any>;
|
package/dist/index.js
CHANGED
|
@@ -6361,6 +6361,9 @@ function usePlanController() {
|
|
|
6361
6361
|
|
|
6362
6362
|
// src/resources/utils/paypal.service.ts
|
|
6363
6363
|
var import_paypal_server_sdk = require("@paypal/paypal-server-sdk");
|
|
6364
|
+
var import_crypto3 = __toESM(require("crypto"));
|
|
6365
|
+
var import_buffer_crc32 = __toESM(require("buffer-crc32"));
|
|
6366
|
+
var certCache = /* @__PURE__ */ new Map();
|
|
6364
6367
|
function usePaypalService() {
|
|
6365
6368
|
const paypalClient = new import_paypal_server_sdk.Client({
|
|
6366
6369
|
clientCredentialsAuthCredentials: {
|
|
@@ -6402,66 +6405,47 @@ function usePaypalService() {
|
|
|
6402
6405
|
function captureOrder(id) {
|
|
6403
6406
|
return new import_paypal_server_sdk.OrdersController(paypalClient).captureOrder({ id });
|
|
6404
6407
|
}
|
|
6405
|
-
async function
|
|
6406
|
-
const
|
|
6407
|
-
|
|
6408
|
+
async function downloadAndCacheCert(url) {
|
|
6409
|
+
const cachedCert = certCache.get(url);
|
|
6410
|
+
if (cachedCert) {
|
|
6411
|
+
return cachedCert;
|
|
6412
|
+
}
|
|
6413
|
+
const response = await fetch(url);
|
|
6414
|
+
if (!response.ok) {
|
|
6415
|
+
throw new Error(
|
|
6416
|
+
`Failed to download PayPal certificate: ${response.statusText}`
|
|
6417
|
+
);
|
|
6418
|
+
}
|
|
6419
|
+
const certPem = await response.text();
|
|
6420
|
+
certCache.set(url, certPem);
|
|
6421
|
+
return certPem;
|
|
6422
|
+
}
|
|
6423
|
+
async function verifySignature(rawBody, headers, webhookId = PAYPAL_WEBHOOK_ID) {
|
|
6408
6424
|
const transmissionId = headers["paypal-transmission-id"];
|
|
6425
|
+
const timeStamp = headers["paypal-transmission-time"];
|
|
6426
|
+
const certUrl = headers["paypal-cert-url"];
|
|
6409
6427
|
const transmissionSig = headers["paypal-transmission-sig"];
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
return {
|
|
6413
|
-
verified: false,
|
|
6414
|
-
verificationStatus: "FAILURE"
|
|
6415
|
-
};
|
|
6428
|
+
if (!transmissionId || !timeStamp || !certUrl || !transmissionSig) {
|
|
6429
|
+
return false;
|
|
6416
6430
|
}
|
|
6417
|
-
const
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
throw new Error("Failed to obtain PayPal access token");
|
|
6430
|
-
}
|
|
6431
|
-
const tokenData = await tokenResponse.json();
|
|
6432
|
-
const accessToken = tokenData.access_token;
|
|
6433
|
-
const verifyResponse = await fetch(
|
|
6434
|
-
`${PAYPAL_API_URL}/v1/notifications/verify-webhook-signature`,
|
|
6435
|
-
{
|
|
6436
|
-
method: "POST",
|
|
6437
|
-
headers: {
|
|
6438
|
-
Authorization: `Bearer ${accessToken}`,
|
|
6439
|
-
"Content-Type": "application/json"
|
|
6440
|
-
},
|
|
6441
|
-
body: JSON.stringify({
|
|
6442
|
-
auth_algo: authAlgo,
|
|
6443
|
-
cert_url: certUrl,
|
|
6444
|
-
transmission_id: transmissionId,
|
|
6445
|
-
transmission_sig: transmissionSig,
|
|
6446
|
-
transmission_time: transmissionTime,
|
|
6447
|
-
webhook_id: webhookId,
|
|
6448
|
-
webhook_event: body
|
|
6449
|
-
})
|
|
6450
|
-
}
|
|
6451
|
-
);
|
|
6452
|
-
if (!verifyResponse.ok) {
|
|
6453
|
-
throw new Error("Failed to verify PayPal webhook signature");
|
|
6431
|
+
const eventBuffer = Buffer.isBuffer(rawBody) ? rawBody : Buffer.from(rawBody);
|
|
6432
|
+
const crcValue = parseInt("0x" + (0, import_buffer_crc32.default)(eventBuffer).toString("hex"));
|
|
6433
|
+
const message = `${transmissionId}|${timeStamp}|${webhookId}|${crcValue}`;
|
|
6434
|
+
try {
|
|
6435
|
+
const certPem = await downloadAndCacheCert(certUrl);
|
|
6436
|
+
const signatureBuffer = Buffer.from(transmissionSig, "base64");
|
|
6437
|
+
const verifier = import_crypto3.default.createVerify("SHA256");
|
|
6438
|
+
verifier.update(message);
|
|
6439
|
+
return verifier.verify(certPem, signatureBuffer);
|
|
6440
|
+
} catch (error) {
|
|
6441
|
+
console.error("PayPal webhook verification error:", error);
|
|
6442
|
+
throw new Error("Failed to verify PayPal webhook signature.");
|
|
6454
6443
|
}
|
|
6455
|
-
const verifyData = await verifyResponse.json();
|
|
6456
|
-
return {
|
|
6457
|
-
verified: verifyData.verification_status === "SUCCESS",
|
|
6458
|
-
verificationStatus: verifyData.verification_status
|
|
6459
|
-
};
|
|
6460
6444
|
}
|
|
6461
6445
|
return {
|
|
6462
6446
|
addOrder,
|
|
6463
6447
|
captureOrder,
|
|
6464
|
-
|
|
6448
|
+
verifySignature
|
|
6465
6449
|
};
|
|
6466
6450
|
}
|
|
6467
6451
|
|
|
@@ -9839,9 +9823,35 @@ function useUtilController() {
|
|
|
9839
9823
|
}
|
|
9840
9824
|
}
|
|
9841
9825
|
}
|
|
9826
|
+
const { verifySignature } = usePaypalService();
|
|
9842
9827
|
async function paypalWebhook(req, res, next) {
|
|
9843
|
-
|
|
9844
|
-
|
|
9828
|
+
try {
|
|
9829
|
+
const headers = req.headers;
|
|
9830
|
+
const event = req.body;
|
|
9831
|
+
const data = JSON.parse(event);
|
|
9832
|
+
console.log(`headers`, headers);
|
|
9833
|
+
console.log(`parsed json`, JSON.stringify(data, null, 2));
|
|
9834
|
+
console.log(`raw event: ${event}`);
|
|
9835
|
+
const isSignatureValid = await verifySignature(
|
|
9836
|
+
event,
|
|
9837
|
+
headers,
|
|
9838
|
+
PAYPAL_WEBHOOK_ID
|
|
9839
|
+
);
|
|
9840
|
+
if (isSignatureValid) {
|
|
9841
|
+
console.log("Signature is valid.");
|
|
9842
|
+
console.log(`Received event`, JSON.stringify(data, null, 2));
|
|
9843
|
+
} else {
|
|
9844
|
+
console.log(
|
|
9845
|
+
`Signature is not valid for ${data?.id} ${headers?.["correlation-id"]}`
|
|
9846
|
+
);
|
|
9847
|
+
}
|
|
9848
|
+
res.sendStatus(200);
|
|
9849
|
+
} catch (error) {
|
|
9850
|
+
import_utils55.logger.log({
|
|
9851
|
+
level: "error",
|
|
9852
|
+
message: `${error}`
|
|
9853
|
+
});
|
|
9854
|
+
}
|
|
9845
9855
|
}
|
|
9846
9856
|
return {
|
|
9847
9857
|
healthCheck,
|