@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/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 verifyWebhook(headers, body, webhookId = PAYPAL_WEBHOOK_ID) {
6400
- const authAlgo = headers["paypal-auth-algo"];
6401
- const certUrl = headers["paypal-cert-url"];
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
- const transmissionTime = headers["paypal-transmission-time"];
6405
- if (!authAlgo || !certUrl || !transmissionId || !transmissionSig || !transmissionTime) {
6406
- return {
6407
- verified: false,
6408
- verificationStatus: "FAILURE"
6409
- };
6422
+ if (!transmissionId || !timeStamp || !certUrl || !transmissionSig) {
6423
+ return false;
6410
6424
  }
6411
- const auth = Buffer.from(
6412
- `${PAYPAL_CLIENT_ID}:${PAYPAL_CLIENT_SECRET}`
6413
- ).toString("base64");
6414
- const tokenResponse = await fetch(`${PAYPAL_API_URL}/v1/oauth2/token`, {
6415
- method: "POST",
6416
- headers: {
6417
- Authorization: `Basic ${auth}`,
6418
- "Content-Type": "application/x-www-form-urlencoded"
6419
- },
6420
- body: "grant_type=client_credentials"
6421
- });
6422
- if (!tokenResponse.ok) {
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
- verifyWebhook
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
- console.log(req.body);
9878
- return res.status(200).send("OK");
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,