@goweekdays/core 2.4.2 → 2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @goweekdays/core
2
2
 
3
+ ## 2.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 260c0c8: Paypal webhook verification implementation
8
+
9
+ ## 2.5.0
10
+
11
+ ### Minor Changes
12
+
13
+ - c861819: Initiate paypal service function
14
+
3
15
  ## 2.4.2
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -398,7 +398,10 @@ declare function useOrgRepo(): {
398
398
  declare function useOrgService(): {
399
399
  add: (value: TOrg & {
400
400
  seats: number;
401
- }) => Promise<string>;
401
+ }) => Promise<{
402
+ org: string;
403
+ paypalOrderLink: any;
404
+ }>;
402
405
  };
403
406
 
404
407
  declare function useOrgController(): {
@@ -627,6 +630,7 @@ declare function useGitHubService(): {
627
630
  declare function useUtilController(): {
628
631
  healthCheck: (req: Request, res: Response, next: NextFunction) => Promise<void>;
629
632
  setGitHubVariables: (req: Request, res: Response, next: NextFunction) => Promise<void>;
633
+ paypalWebhook: (req: Request, res: Response, next: NextFunction) => Promise<void>;
630
634
  };
631
635
 
632
636
  declare const transactionSchema: Joi.ObjectSchema<any>;
@@ -1026,8 +1030,10 @@ declare const SPACES_BUCKET: string;
1026
1030
  declare const PAYPAL_CLIENT_ID: string;
1027
1031
  declare const PAYPAL_CLIENT_SECRET: string;
1028
1032
  declare const PAYPAL_API_URL: string;
1033
+ declare const PAYPAL_WEBHOOK_ID: string;
1029
1034
  declare const XENDIT_SECRET_KEY: string;
1030
1035
  declare const XENDIT_BASE_URL: string;
1031
1036
  declare const DOMAIN: string;
1037
+ declare const APP_ORG: string;
1032
1038
 
1033
- export { ACCESS_TOKEN_EXPIRY, ACCESS_TOKEN_SECRET, APP_ACCOUNT, APP_MAIN, DEFAULT_USER_EMAIL, DEFAULT_USER_FIRST_NAME, DEFAULT_USER_LAST_NAME, DEFAULT_USER_PASSWORD, DOMAIN, MAILER_EMAIL, MAILER_PASSWORD, MAILER_TRANSPORT_HOST, MAILER_TRANSPORT_PORT, MAILER_TRANSPORT_SECURE, MBuilding, MBuildingUnit, MFile, MONGO_DB, MONGO_URI, PAYPAL_API_URL, PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PORT, REDIS_HOST, REDIS_PASSWORD, REDIS_PORT, REFRESH_TOKEN_EXPIRY, REFRESH_TOKEN_SECRET, SECRET_KEY, SPACES_ACCESS_KEY, SPACES_BUCKET, SPACES_ENDPOINT, SPACES_REGION, SPACES_SECRET_KEY, TApp, TBuilding, TBuildingUnit, TCounter, TFile, TMember, TOrg, TPermission, TPermissionGroup, TPlan, TPromo, TRole, TSubscription, TSubscriptionTransaction, TUser, TVerification, TVerificationMetadata, VERIFICATION_FORGET_PASSWORD_DURATION, VERIFICATION_USER_INVITE_DURATION, XENDIT_BASE_URL, XENDIT_SECRET_KEY, currencies, isDev, modelApp, modelMember, modelOrg, modelPermission, modelPermissionGroup, modelPlan, modelPromo, modelRole, modelSubscription, modelSubscriptionTransaction, modelUser, modelVerification, schemaApp, schemaAppUpdate, schemaBuilding, schemaBuildingUnit, schemaInviteMember, schemaMember, schemaMemberRole, schemaMemberStatus, schemaOrg, schemaOrgAdd, schemaOrgUpdate, schemaPermission, schemaPermissionGroup, schemaPermissionGroupUpdate, schemaPermissionUpdate, schemaPlan, schemaPromo, schemaRole, schemaRoleUpdate, schemaSubscription, schemaSubscriptionSeats, schemaSubscriptionTransaction, schemaSubscriptionUpdate, schemaUpdateOptions, schemaUser, schemaVerification, transactionSchema, useAppController, useAppRepo, useAppService, useAuthController, useAuthService, useBuildingController, useBuildingRepo, useBuildingService, useBuildingUnitController, useBuildingUnitRepo, useBuildingUnitService, useCounterModel, useCounterRepo, useFileController, useFileRepo, useFileService, useGitHubService, useMemberController, useMemberRepo, useOrgController, useOrgRepo, useOrgService, usePermissionController, usePermissionGroupController, usePermissionGroupRepo, usePermissionGroupService, usePermissionRepo, usePermissionService, usePlanController, usePlanRepo, usePlanService, usePromoRepo, useRoleController, useRoleRepo, useRoleService, useSubscriptionController, useSubscriptionRepo, useSubscriptionTransactionController, useSubscriptionTransactionRepo, useUserController, useUserRepo, useUserService, useUtilController, useVerificationController, useVerificationRepo, useVerificationService };
1039
+ export { ACCESS_TOKEN_EXPIRY, ACCESS_TOKEN_SECRET, APP_ACCOUNT, APP_MAIN, APP_ORG, DEFAULT_USER_EMAIL, DEFAULT_USER_FIRST_NAME, DEFAULT_USER_LAST_NAME, DEFAULT_USER_PASSWORD, DOMAIN, MAILER_EMAIL, MAILER_PASSWORD, MAILER_TRANSPORT_HOST, MAILER_TRANSPORT_PORT, MAILER_TRANSPORT_SECURE, MBuilding, MBuildingUnit, MFile, MONGO_DB, MONGO_URI, PAYPAL_API_URL, PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PAYPAL_WEBHOOK_ID, PORT, REDIS_HOST, REDIS_PASSWORD, REDIS_PORT, REFRESH_TOKEN_EXPIRY, REFRESH_TOKEN_SECRET, SECRET_KEY, SPACES_ACCESS_KEY, SPACES_BUCKET, SPACES_ENDPOINT, SPACES_REGION, SPACES_SECRET_KEY, TApp, TBuilding, TBuildingUnit, TCounter, TFile, TMember, TOrg, TPermission, TPermissionGroup, TPlan, TPromo, TRole, TSubscription, TSubscriptionTransaction, TUser, TVerification, TVerificationMetadata, VERIFICATION_FORGET_PASSWORD_DURATION, VERIFICATION_USER_INVITE_DURATION, XENDIT_BASE_URL, XENDIT_SECRET_KEY, currencies, isDev, modelApp, modelMember, modelOrg, modelPermission, modelPermissionGroup, modelPlan, modelPromo, modelRole, modelSubscription, modelSubscriptionTransaction, modelUser, modelVerification, schemaApp, schemaAppUpdate, schemaBuilding, schemaBuildingUnit, schemaInviteMember, schemaMember, schemaMemberRole, schemaMemberStatus, schemaOrg, schemaOrgAdd, schemaOrgUpdate, schemaPermission, schemaPermissionGroup, schemaPermissionGroupUpdate, schemaPermissionUpdate, schemaPlan, schemaPromo, schemaRole, schemaRoleUpdate, schemaSubscription, schemaSubscriptionSeats, schemaSubscriptionTransaction, schemaSubscriptionUpdate, schemaUpdateOptions, schemaUser, schemaVerification, transactionSchema, useAppController, useAppRepo, useAppService, useAuthController, useAuthService, useBuildingController, useBuildingRepo, useBuildingService, useBuildingUnitController, useBuildingUnitRepo, useBuildingUnitService, useCounterModel, useCounterRepo, useFileController, useFileRepo, useFileService, useGitHubService, useMemberController, useMemberRepo, useOrgController, useOrgRepo, useOrgService, usePermissionController, usePermissionGroupController, usePermissionGroupRepo, usePermissionGroupService, usePermissionRepo, usePermissionService, usePlanController, usePlanRepo, usePlanService, usePromoRepo, useRoleController, useRoleRepo, useRoleService, useSubscriptionController, useSubscriptionRepo, useSubscriptionTransactionController, useSubscriptionTransactionRepo, useUserController, useUserRepo, useUserService, useUtilController, useVerificationController, useVerificationRepo, useVerificationService };
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ __export(src_exports, {
34
34
  ACCESS_TOKEN_SECRET: () => ACCESS_TOKEN_SECRET,
35
35
  APP_ACCOUNT: () => APP_ACCOUNT,
36
36
  APP_MAIN: () => APP_MAIN,
37
+ APP_ORG: () => APP_ORG,
37
38
  DEFAULT_USER_EMAIL: () => DEFAULT_USER_EMAIL,
38
39
  DEFAULT_USER_FIRST_NAME: () => DEFAULT_USER_FIRST_NAME,
39
40
  DEFAULT_USER_LAST_NAME: () => DEFAULT_USER_LAST_NAME,
@@ -52,6 +53,7 @@ __export(src_exports, {
52
53
  PAYPAL_API_URL: () => PAYPAL_API_URL,
53
54
  PAYPAL_CLIENT_ID: () => PAYPAL_CLIENT_ID,
54
55
  PAYPAL_CLIENT_SECRET: () => PAYPAL_CLIENT_SECRET,
56
+ PAYPAL_WEBHOOK_ID: () => PAYPAL_WEBHOOK_ID,
55
57
  PORT: () => PORT,
56
58
  REDIS_HOST: () => REDIS_HOST,
57
59
  REDIS_PASSWORD: () => REDIS_PASSWORD,
@@ -1028,9 +1030,11 @@ var SPACES_BUCKET = process.env.SPACES_BUCKET;
1028
1030
  var PAYPAL_CLIENT_ID = process.env.PAYPAL_CLIENT_ID ?? "";
1029
1031
  var PAYPAL_CLIENT_SECRET = process.env.PAYPAL_CLIENT_SECRET ?? "";
1030
1032
  var PAYPAL_API_URL = process.env.PAYPAL_API_URL ?? "https://api-m.sandbox.paypal.com";
1033
+ var PAYPAL_WEBHOOK_ID = process.env.PAYPAL_WEBHOOK_ID ?? "";
1031
1034
  var XENDIT_SECRET_KEY = process.env.XENDIT_SECRET_KEY ?? "";
1032
1035
  var XENDIT_BASE_URL = process.env.XENDIT_BASE_URL ?? "https://api.xendit.co";
1033
1036
  var DOMAIN = process.env.DOMAIN || "localhost";
1037
+ var APP_ORG = process.env.APP_ORG || "http://localhost/organizations/create";
1034
1038
 
1035
1039
  // src/resources/user/user.service.ts
1036
1040
  var import_utils38 = require("@goweekdays/utils");
@@ -3555,6 +3559,11 @@ function useAppService() {
3555
3559
  code: "ride",
3556
3560
  name: "Ride",
3557
3561
  description: "Transportation and ride services."
3562
+ },
3563
+ {
3564
+ code: "job",
3565
+ name: "jobs",
3566
+ description: "Job listings and recruitment services."
3558
3567
  }
3559
3568
  ];
3560
3569
  const session = import_utils17.useAtlas.getClient()?.startSession();
@@ -6350,6 +6359,96 @@ function usePlanController() {
6350
6359
  };
6351
6360
  }
6352
6361
 
6362
+ // src/resources/utils/paypal.service.ts
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();
6367
+ function usePaypalService() {
6368
+ const paypalClient = new import_paypal_server_sdk.Client({
6369
+ clientCredentialsAuthCredentials: {
6370
+ oAuthClientId: PAYPAL_CLIENT_ID,
6371
+ oAuthClientSecret: PAYPAL_CLIENT_SECRET
6372
+ },
6373
+ timeout: 0,
6374
+ environment: isDev ? import_paypal_server_sdk.Environment.Sandbox : import_paypal_server_sdk.Environment.Production
6375
+ });
6376
+ function addOrder({
6377
+ amount = 0,
6378
+ currency = "PHP",
6379
+ customId = "",
6380
+ returnUrl = "",
6381
+ cancelUrl = "",
6382
+ action = "pay"
6383
+ } = {}) {
6384
+ return new import_paypal_server_sdk.OrdersController(paypalClient).createOrder({
6385
+ body: {
6386
+ intent: import_paypal_server_sdk.CheckoutPaymentIntent.Capture,
6387
+ purchaseUnits: [
6388
+ {
6389
+ amount: {
6390
+ currencyCode: currency,
6391
+ value: amount.toFixed(2)
6392
+ },
6393
+ customId
6394
+ }
6395
+ ],
6396
+ applicationContext: {
6397
+ returnUrl,
6398
+ cancelUrl,
6399
+ userAction: action === "pay" ? import_paypal_server_sdk.OrderApplicationContextUserAction.PayNow : action === "continue" ? import_paypal_server_sdk.OrderApplicationContextUserAction.Continue : void 0
6400
+ }
6401
+ },
6402
+ prefer: "return=minimal"
6403
+ });
6404
+ }
6405
+ function captureOrder(id) {
6406
+ return new import_paypal_server_sdk.OrdersController(paypalClient).captureOrder({ id });
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 verifyWebhook(rawBody, headers, webhookId = PAYPAL_WEBHOOK_ID) {
6424
+ const transmissionId = headers["paypal-transmission-id"];
6425
+ const timeStamp = headers["paypal-transmission-time"];
6426
+ const certUrl = headers["paypal-cert-url"];
6427
+ const transmissionSig = headers["paypal-transmission-sig"];
6428
+ if (!transmissionId || !timeStamp || !certUrl || !transmissionSig) {
6429
+ return false;
6430
+ }
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.");
6443
+ }
6444
+ }
6445
+ return {
6446
+ addOrder,
6447
+ captureOrder,
6448
+ verifyWebhook
6449
+ };
6450
+ }
6451
+
6353
6452
  // src/resources/organization/organization.service.ts
6354
6453
  function useOrgService() {
6355
6454
  const { add: addOrg } = useOrgRepo();
@@ -6360,6 +6459,7 @@ function useOrgService() {
6360
6459
  const { getDefault } = usePlanRepo();
6361
6460
  const { add: addSubscription } = useSubscriptionRepo();
6362
6461
  const { add: addSubscriptionTransaction } = useSubscriptionTransactionRepo();
6462
+ const { addOrder: addPaypalOrder } = usePaypalService();
6363
6463
  async function add(value) {
6364
6464
  const { error } = schemaOrgAdd.validate(value);
6365
6465
  if (error) {
@@ -6454,8 +6554,22 @@ function useOrgService() {
6454
6554
  },
6455
6555
  session
6456
6556
  );
6557
+ const order = await addPaypalOrder({
6558
+ amount,
6559
+ currency: plan.currency,
6560
+ customId: subscriptionId,
6561
+ returnUrl: `${APP_ORG}/organizations/success`,
6562
+ cancelUrl: `${APP_ORG}/organizations/cancel`,
6563
+ action: "pay"
6564
+ });
6457
6565
  await session?.commitTransaction();
6458
- return String(org);
6566
+ const paypalOrderLink = JSON.parse(order.body.toString()).links.find(
6567
+ (link) => link.rel === "approve"
6568
+ );
6569
+ return {
6570
+ org: String(org),
6571
+ paypalOrderLink: paypalOrderLink ? paypalOrderLink.href : ""
6572
+ };
6459
6573
  } catch (error2) {
6460
6574
  await session?.abortTransaction();
6461
6575
  throw error2;
@@ -6488,10 +6602,10 @@ function useOrgController() {
6488
6602
  return;
6489
6603
  }
6490
6604
  try {
6491
- const org = await _add(value);
6605
+ const data = await _add(value);
6492
6606
  res.json({
6493
6607
  message: "Organization created successfully.",
6494
- data: { org }
6608
+ data
6495
6609
  });
6496
6610
  return;
6497
6611
  } catch (error2) {
@@ -9709,9 +9823,26 @@ function useUtilController() {
9709
9823
  }
9710
9824
  }
9711
9825
  }
9826
+ const { verifyWebhook } = usePaypalService();
9827
+ async function paypalWebhook(req, res, next) {
9828
+ console.log(req);
9829
+ try {
9830
+ await verifyWebhook(req.body, req.headers, PAYPAL_WEBHOOK_ID);
9831
+ res.status(200).send("OK");
9832
+ return;
9833
+ } catch (error) {
9834
+ import_utils55.logger.log({
9835
+ level: "error",
9836
+ message: "PayPal webhook verification failed"
9837
+ });
9838
+ res.status(400).send("Invalid webhook");
9839
+ return;
9840
+ }
9841
+ }
9712
9842
  return {
9713
9843
  healthCheck,
9714
- setGitHubVariables
9844
+ setGitHubVariables,
9845
+ paypalWebhook
9715
9846
  };
9716
9847
  }
9717
9848
 
@@ -9974,6 +10105,7 @@ function useVerificationController() {
9974
10105
  ACCESS_TOKEN_SECRET,
9975
10106
  APP_ACCOUNT,
9976
10107
  APP_MAIN,
10108
+ APP_ORG,
9977
10109
  DEFAULT_USER_EMAIL,
9978
10110
  DEFAULT_USER_FIRST_NAME,
9979
10111
  DEFAULT_USER_LAST_NAME,
@@ -9992,6 +10124,7 @@ function useVerificationController() {
9992
10124
  PAYPAL_API_URL,
9993
10125
  PAYPAL_CLIENT_ID,
9994
10126
  PAYPAL_CLIENT_SECRET,
10127
+ PAYPAL_WEBHOOK_ID,
9995
10128
  PORT,
9996
10129
  REDIS_HOST,
9997
10130
  REDIS_PASSWORD,