@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/dist/index.mjs
CHANGED
|
@@ -6355,6 +6355,9 @@ import {
|
|
|
6355
6355
|
CheckoutPaymentIntent,
|
|
6356
6356
|
OrderApplicationContextUserAction
|
|
6357
6357
|
} from "@paypal/paypal-server-sdk";
|
|
6358
|
+
import crypto3 from "crypto";
|
|
6359
|
+
import crc32 from "buffer-crc32";
|
|
6360
|
+
var certCache = /* @__PURE__ */ new Map();
|
|
6358
6361
|
function usePaypalService() {
|
|
6359
6362
|
const paypalClient = new Client({
|
|
6360
6363
|
clientCredentialsAuthCredentials: {
|
|
@@ -6396,66 +6399,47 @@ function usePaypalService() {
|
|
|
6396
6399
|
function captureOrder(id) {
|
|
6397
6400
|
return new OrdersController(paypalClient).captureOrder({ id });
|
|
6398
6401
|
}
|
|
6399
|
-
async function
|
|
6400
|
-
const
|
|
6401
|
-
|
|
6402
|
+
async function downloadAndCacheCert(url) {
|
|
6403
|
+
const cachedCert = certCache.get(url);
|
|
6404
|
+
if (cachedCert) {
|
|
6405
|
+
return cachedCert;
|
|
6406
|
+
}
|
|
6407
|
+
const response = await fetch(url);
|
|
6408
|
+
if (!response.ok) {
|
|
6409
|
+
throw new Error(
|
|
6410
|
+
`Failed to download PayPal certificate: ${response.statusText}`
|
|
6411
|
+
);
|
|
6412
|
+
}
|
|
6413
|
+
const certPem = await response.text();
|
|
6414
|
+
certCache.set(url, certPem);
|
|
6415
|
+
return certPem;
|
|
6416
|
+
}
|
|
6417
|
+
async function verifySignature(rawBody, headers, webhookId = PAYPAL_WEBHOOK_ID) {
|
|
6402
6418
|
const transmissionId = headers["paypal-transmission-id"];
|
|
6419
|
+
const timeStamp = headers["paypal-transmission-time"];
|
|
6420
|
+
const certUrl = headers["paypal-cert-url"];
|
|
6403
6421
|
const transmissionSig = headers["paypal-transmission-sig"];
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
return {
|
|
6407
|
-
verified: false,
|
|
6408
|
-
verificationStatus: "FAILURE"
|
|
6409
|
-
};
|
|
6422
|
+
if (!transmissionId || !timeStamp || !certUrl || !transmissionSig) {
|
|
6423
|
+
return false;
|
|
6410
6424
|
}
|
|
6411
|
-
const
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
throw new Error("Failed to obtain PayPal access token");
|
|
6424
|
-
}
|
|
6425
|
-
const tokenData = await tokenResponse.json();
|
|
6426
|
-
const accessToken = tokenData.access_token;
|
|
6427
|
-
const verifyResponse = await fetch(
|
|
6428
|
-
`${PAYPAL_API_URL}/v1/notifications/verify-webhook-signature`,
|
|
6429
|
-
{
|
|
6430
|
-
method: "POST",
|
|
6431
|
-
headers: {
|
|
6432
|
-
Authorization: `Bearer ${accessToken}`,
|
|
6433
|
-
"Content-Type": "application/json"
|
|
6434
|
-
},
|
|
6435
|
-
body: JSON.stringify({
|
|
6436
|
-
auth_algo: authAlgo,
|
|
6437
|
-
cert_url: certUrl,
|
|
6438
|
-
transmission_id: transmissionId,
|
|
6439
|
-
transmission_sig: transmissionSig,
|
|
6440
|
-
transmission_time: transmissionTime,
|
|
6441
|
-
webhook_id: webhookId,
|
|
6442
|
-
webhook_event: body
|
|
6443
|
-
})
|
|
6444
|
-
}
|
|
6445
|
-
);
|
|
6446
|
-
if (!verifyResponse.ok) {
|
|
6447
|
-
throw new Error("Failed to verify PayPal webhook signature");
|
|
6425
|
+
const eventBuffer = Buffer.isBuffer(rawBody) ? rawBody : Buffer.from(rawBody);
|
|
6426
|
+
const crcValue = parseInt("0x" + crc32(eventBuffer).toString("hex"));
|
|
6427
|
+
const message = `${transmissionId}|${timeStamp}|${webhookId}|${crcValue}`;
|
|
6428
|
+
try {
|
|
6429
|
+
const certPem = await downloadAndCacheCert(certUrl);
|
|
6430
|
+
const signatureBuffer = Buffer.from(transmissionSig, "base64");
|
|
6431
|
+
const verifier = crypto3.createVerify("SHA256");
|
|
6432
|
+
verifier.update(message);
|
|
6433
|
+
return verifier.verify(certPem, signatureBuffer);
|
|
6434
|
+
} catch (error) {
|
|
6435
|
+
console.error("PayPal webhook verification error:", error);
|
|
6436
|
+
throw new Error("Failed to verify PayPal webhook signature.");
|
|
6448
6437
|
}
|
|
6449
|
-
const verifyData = await verifyResponse.json();
|
|
6450
|
-
return {
|
|
6451
|
-
verified: verifyData.verification_status === "SUCCESS",
|
|
6452
|
-
verificationStatus: verifyData.verification_status
|
|
6453
|
-
};
|
|
6454
6438
|
}
|
|
6455
6439
|
return {
|
|
6456
6440
|
addOrder,
|
|
6457
6441
|
captureOrder,
|
|
6458
|
-
|
|
6442
|
+
verifySignature
|
|
6459
6443
|
};
|
|
6460
6444
|
}
|
|
6461
6445
|
|
|
@@ -9873,9 +9857,35 @@ function useUtilController() {
|
|
|
9873
9857
|
}
|
|
9874
9858
|
}
|
|
9875
9859
|
}
|
|
9860
|
+
const { verifySignature } = usePaypalService();
|
|
9876
9861
|
async function paypalWebhook(req, res, next) {
|
|
9877
|
-
|
|
9878
|
-
|
|
9862
|
+
try {
|
|
9863
|
+
const headers = req.headers;
|
|
9864
|
+
const event = req.body;
|
|
9865
|
+
const data = JSON.parse(event);
|
|
9866
|
+
console.log(`headers`, headers);
|
|
9867
|
+
console.log(`parsed json`, JSON.stringify(data, null, 2));
|
|
9868
|
+
console.log(`raw event: ${event}`);
|
|
9869
|
+
const isSignatureValid = await verifySignature(
|
|
9870
|
+
event,
|
|
9871
|
+
headers,
|
|
9872
|
+
PAYPAL_WEBHOOK_ID
|
|
9873
|
+
);
|
|
9874
|
+
if (isSignatureValid) {
|
|
9875
|
+
console.log("Signature is valid.");
|
|
9876
|
+
console.log(`Received event`, JSON.stringify(data, null, 2));
|
|
9877
|
+
} else {
|
|
9878
|
+
console.log(
|
|
9879
|
+
`Signature is not valid for ${data?.id} ${headers?.["correlation-id"]}`
|
|
9880
|
+
);
|
|
9881
|
+
}
|
|
9882
|
+
res.sendStatus(200);
|
|
9883
|
+
} catch (error) {
|
|
9884
|
+
logger28.log({
|
|
9885
|
+
level: "error",
|
|
9886
|
+
message: `${error}`
|
|
9887
|
+
});
|
|
9888
|
+
}
|
|
9879
9889
|
}
|
|
9880
9890
|
return {
|
|
9881
9891
|
healthCheck,
|