@alexasomba/better-auth-paystack 1.2.0 → 1.2.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/client.d.mts +3 -4
- package/dist/client.d.mts.map +1 -1
- package/dist/client.mjs +15 -14
- package/dist/client.mjs.map +1 -1
- package/dist/{types-BOpjdQrr.d.mts → index-DoMJ9OLF.d.mts} +99 -6
- package/dist/index-DoMJ9OLF.d.mts.map +1 -0
- package/dist/index.d.mts +2 -623
- package/dist/index.mjs +152 -169
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/dist/index.d.mts.map +0 -1
- package/dist/types-BOpjdQrr.d.mts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,6 @@ import { HIDE_METADATA, logger } from "better-auth";
|
|
|
5
5
|
import { APIError, getSessionFromCtx, originCheck, sessionMiddleware } from "better-auth/api";
|
|
6
6
|
import * as z from "zod/v4";
|
|
7
7
|
import { mergeSchema } from "better-auth/db";
|
|
8
|
-
|
|
9
8
|
//#region src/paystack-sdk.ts
|
|
10
9
|
function isOpenApiFetchResponse(value) {
|
|
11
10
|
return value !== null && value !== void 0 && typeof value === "object" && ("data" in value || "error" in value || "response" in value);
|
|
@@ -117,7 +116,6 @@ function getPaystackOps(paystackClient) {
|
|
|
117
116
|
}
|
|
118
117
|
};
|
|
119
118
|
}
|
|
120
|
-
|
|
121
119
|
//#endregion
|
|
122
120
|
//#region src/utils.ts
|
|
123
121
|
async function getPlans(subscriptionOptions) {
|
|
@@ -190,8 +188,8 @@ async function syncProductQuantityFromPaystack(ctx, productName, paystackClient)
|
|
|
190
188
|
value: productName.toLowerCase().replace(/\s+/g, "-")
|
|
191
189
|
}]
|
|
192
190
|
});
|
|
193
|
-
if (localProduct?.paystackId === void 0 || localProduct
|
|
194
|
-
if (localProduct && localProduct.unlimited !== true && localProduct.quantity
|
|
191
|
+
if (localProduct?.paystackId === void 0 || localProduct.paystackId === null || localProduct.paystackId === "") {
|
|
192
|
+
if (localProduct !== null && localProduct.unlimited !== true && typeof localProduct.quantity === "number" && localProduct.quantity > 0) await ctx.context.adapter.update({
|
|
195
193
|
model: "paystackProduct",
|
|
196
194
|
update: {
|
|
197
195
|
quantity: localProduct.quantity - 1,
|
|
@@ -218,7 +216,7 @@ async function syncProductQuantityFromPaystack(ctx, productName, paystackClient)
|
|
|
218
216
|
}]
|
|
219
217
|
});
|
|
220
218
|
} catch {
|
|
221
|
-
if (localProduct.unlimited !== true && localProduct.quantity
|
|
219
|
+
if (localProduct !== null && localProduct.unlimited !== true && typeof localProduct.quantity === "number" && localProduct.quantity > 0) await ctx.context.adapter.update({
|
|
222
220
|
model: "paystackProduct",
|
|
223
221
|
update: {
|
|
224
222
|
quantity: localProduct.quantity - 1,
|
|
@@ -233,7 +231,7 @@ async function syncProductQuantityFromPaystack(ctx, productName, paystackClient)
|
|
|
233
231
|
}
|
|
234
232
|
async function syncSubscriptionSeats(ctx, organizationId, options) {
|
|
235
233
|
if (options.subscription?.enabled !== true) return;
|
|
236
|
-
const adapter = ctx.context
|
|
234
|
+
const adapter = ctx.context.adapter;
|
|
237
235
|
const subscription = await adapter.findOne({
|
|
238
236
|
model: "subscription",
|
|
239
237
|
where: [{
|
|
@@ -241,7 +239,7 @@ async function syncSubscriptionSeats(ctx, organizationId, options) {
|
|
|
241
239
|
value: organizationId
|
|
242
240
|
}]
|
|
243
241
|
});
|
|
244
|
-
if (subscription ===
|
|
242
|
+
if (subscription?.paystackSubscriptionCode === void 0 || subscription.paystackSubscriptionCode === null || subscription.paystackSubscriptionCode === "") return;
|
|
245
243
|
const plan = await getPlanByName(options, subscription.plan);
|
|
246
244
|
if (plan === null) return;
|
|
247
245
|
if (plan.seatAmount === void 0 && plan.seatPlanCode === void 0) return;
|
|
@@ -253,7 +251,7 @@ async function syncSubscriptionSeats(ctx, organizationId, options) {
|
|
|
253
251
|
}]
|
|
254
252
|
})).length;
|
|
255
253
|
let totalAmount = plan.amount ?? 0;
|
|
256
|
-
if (plan.seatAmount !== void 0 && plan.seatAmount !== null) totalAmount += quantity * plan.seatAmount;
|
|
254
|
+
if (plan.seatAmount !== void 0 && plan.seatAmount !== null && typeof plan.seatAmount === "number") totalAmount += quantity * plan.seatAmount;
|
|
257
255
|
const ops = getPaystackOps(options.paystackClient);
|
|
258
256
|
try {
|
|
259
257
|
await ops.subscriptionUpdate({
|
|
@@ -272,11 +270,10 @@ async function syncSubscriptionSeats(ctx, organizationId, options) {
|
|
|
272
270
|
}
|
|
273
271
|
});
|
|
274
272
|
} catch (e) {
|
|
275
|
-
const log = ctx.context
|
|
273
|
+
const log = ctx.context.logger;
|
|
276
274
|
if (log !== void 0 && log !== null) log.error("Failed to sync subscription seats with Paystack", e);
|
|
277
275
|
}
|
|
278
276
|
}
|
|
279
|
-
|
|
280
277
|
//#endregion
|
|
281
278
|
//#region src/middleware.ts
|
|
282
279
|
const referenceMiddleware = (options, action) => createAuthMiddleware(async (ctx) => {
|
|
@@ -315,7 +312,6 @@ const referenceMiddleware = (options, action) => createAuthMiddleware(async (ctx
|
|
|
315
312
|
logger.error(`Passing referenceId into a subscription action isn't allowed if subscription.authorizeReference isn't defined in your paystack plugin config and matches no organization membership.`);
|
|
316
313
|
throw new APIError("BAD_REQUEST", { message: "Passing referenceId isn't allowed without subscription.authorizeReference or valid organization membership." });
|
|
317
314
|
});
|
|
318
|
-
|
|
319
315
|
//#endregion
|
|
320
316
|
//#region src/limits.ts
|
|
321
317
|
const getOrganizationSubscription = async (ctx, organizationId) => {
|
|
@@ -350,7 +346,6 @@ const checkTeamLimit = async (ctx, organizationId, maxTeams) => {
|
|
|
350
346
|
})).length >= maxTeams) throw new APIError("FORBIDDEN", { message: `Organization team limit reached. Max teams: ${maxTeams}` });
|
|
351
347
|
return true;
|
|
352
348
|
};
|
|
353
|
-
|
|
354
349
|
//#endregion
|
|
355
350
|
//#region src/routes.ts
|
|
356
351
|
const PAYSTACK_ERROR_CODES = defineErrorCodes({
|
|
@@ -391,7 +386,7 @@ const paystackWebhook = (options) => {
|
|
|
391
386
|
disableBody: true
|
|
392
387
|
}, async (ctx) => {
|
|
393
388
|
const request = ctx.requestClone ?? ctx.request;
|
|
394
|
-
if (
|
|
389
|
+
if (request === void 0 || request === null) throw new APIError("BAD_REQUEST", { message: "Request object is missing from context" });
|
|
395
390
|
const payload = await request.text();
|
|
396
391
|
const signature = (ctx.headers ?? ctx.request?.headers)?.get("x-paystack-signature");
|
|
397
392
|
if (signature === void 0 || signature === null || signature === "") throw new APIError("UNAUTHORIZED", {
|
|
@@ -433,7 +428,7 @@ const paystackWebhook = (options) => {
|
|
|
433
428
|
value: reference
|
|
434
429
|
}]
|
|
435
430
|
});
|
|
436
|
-
if (transaction?.product) await syncProductQuantityFromPaystack(ctx, transaction.product, options.paystackClient);
|
|
431
|
+
if (transaction?.product !== void 0 && transaction.product !== null && transaction.product !== "") await syncProductQuantityFromPaystack(ctx, transaction.product, options.paystackClient);
|
|
437
432
|
} catch (e) {
|
|
438
433
|
ctx.context.logger.warn("Failed to sync product quantity", e);
|
|
439
434
|
}
|
|
@@ -489,11 +484,10 @@ const paystackWebhook = (options) => {
|
|
|
489
484
|
value: planName
|
|
490
485
|
});
|
|
491
486
|
if (where.length > 0) {
|
|
492
|
-
const
|
|
487
|
+
const subscription = (await ctx.context.adapter.findMany({
|
|
493
488
|
model: "subscription",
|
|
494
489
|
where
|
|
495
|
-
});
|
|
496
|
-
const subscription = matches !== void 0 && matches !== null ? matches[0] : void 0;
|
|
490
|
+
}))?.[0];
|
|
497
491
|
if (subscription !== void 0 && subscription !== null) {
|
|
498
492
|
await ctx.context.adapter.update({
|
|
499
493
|
model: "subscription",
|
|
@@ -501,7 +495,7 @@ const paystackWebhook = (options) => {
|
|
|
501
495
|
paystackSubscriptionCode: subscriptionCode,
|
|
502
496
|
status: "active",
|
|
503
497
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
504
|
-
periodEnd: payloadData?.next_payment_date !== void 0 && payloadData
|
|
498
|
+
periodEnd: payloadData?.next_payment_date !== void 0 && payloadData.next_payment_date !== null && payloadData.next_payment_date !== "" ? new Date(payloadData.next_payment_date) : void 0
|
|
505
499
|
},
|
|
506
500
|
where: [{
|
|
507
501
|
field: "id",
|
|
@@ -546,8 +540,8 @@ const paystackWebhook = (options) => {
|
|
|
546
540
|
});
|
|
547
541
|
let newStatus = "canceled";
|
|
548
542
|
const nextPaymentDate = data?.next_payment_date;
|
|
549
|
-
const periodEnd = nextPaymentDate ? new Date(nextPaymentDate) : existing?.periodEnd ? new Date(existing.periodEnd) : void 0;
|
|
550
|
-
if (periodEnd && periodEnd > /* @__PURE__ */ new Date()) newStatus = "active";
|
|
543
|
+
const periodEnd = nextPaymentDate !== void 0 && nextPaymentDate !== null && nextPaymentDate !== "" ? new Date(nextPaymentDate) : existing?.periodEnd !== void 0 ? new Date(existing.periodEnd) : void 0;
|
|
544
|
+
if (periodEnd !== void 0 && periodEnd > /* @__PURE__ */ new Date()) newStatus = "active";
|
|
551
545
|
await ctx.context.adapter.update({
|
|
552
546
|
model: "subscription",
|
|
553
547
|
update: {
|
|
@@ -561,7 +555,7 @@ const paystackWebhook = (options) => {
|
|
|
561
555
|
value: subscriptionCode
|
|
562
556
|
}]
|
|
563
557
|
});
|
|
564
|
-
if (existing) await options.subscription.onSubscriptionCancel?.({
|
|
558
|
+
if (existing !== void 0 && existing !== null) await options.subscription.onSubscriptionCancel?.({
|
|
565
559
|
event,
|
|
566
560
|
subscription: {
|
|
567
561
|
...existing,
|
|
@@ -573,7 +567,7 @@ const paystackWebhook = (options) => {
|
|
|
573
567
|
if (eventName === "charge.success" || eventName === "invoice.update") {
|
|
574
568
|
const payloadData = data;
|
|
575
569
|
const subscriptionCode = payloadData?.subscription?.subscription_code ?? payloadData?.subscription_code;
|
|
576
|
-
if (subscriptionCode) {
|
|
570
|
+
if (subscriptionCode !== void 0 && subscriptionCode !== null && subscriptionCode !== "") {
|
|
577
571
|
const existingSub = await ctx.context.adapter.findOne({
|
|
578
572
|
model: "subscription",
|
|
579
573
|
where: [{
|
|
@@ -581,7 +575,7 @@ const paystackWebhook = (options) => {
|
|
|
581
575
|
value: subscriptionCode
|
|
582
576
|
}]
|
|
583
577
|
});
|
|
584
|
-
if (existingSub?.pendingPlan) await ctx.context.adapter.update({
|
|
578
|
+
if (existingSub?.pendingPlan !== void 0 && existingSub.pendingPlan !== null && existingSub.pendingPlan !== "") await ctx.context.adapter.update({
|
|
585
579
|
model: "subscription",
|
|
586
580
|
update: {
|
|
587
581
|
plan: existingSub.pendingPlan,
|
|
@@ -632,7 +626,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
632
626
|
if (callbackURL !== void 0 && callbackURL !== null && callbackURL !== "") {
|
|
633
627
|
const checkTrusted = () => {
|
|
634
628
|
try {
|
|
635
|
-
if (
|
|
629
|
+
if (callbackURL === void 0 || callbackURL === null || callbackURL === "") return false;
|
|
636
630
|
if (callbackURL.startsWith("/")) return true;
|
|
637
631
|
const baseUrl = ctx.context?.baseURL ?? ctx.request?.url ?? "";
|
|
638
632
|
if (!baseUrl) return false;
|
|
@@ -642,7 +636,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
642
636
|
return false;
|
|
643
637
|
}
|
|
644
638
|
};
|
|
645
|
-
if (
|
|
639
|
+
if (checkTrusted() !== true) throw new APIError("FORBIDDEN", {
|
|
646
640
|
message: "callbackURL is not a trusted origin.",
|
|
647
641
|
status: 403
|
|
648
642
|
});
|
|
@@ -650,7 +644,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
650
644
|
const session = await getSessionFromCtx(ctx);
|
|
651
645
|
if (!session) throw new APIError("UNAUTHORIZED");
|
|
652
646
|
const user = session.user;
|
|
653
|
-
if (subscriptionOptions?.enabled === true && subscriptionOptions.requireEmailVerification === true &&
|
|
647
|
+
if (subscriptionOptions?.enabled === true && subscriptionOptions.requireEmailVerification === true && user.emailVerified !== true) throw new APIError("BAD_REQUEST", {
|
|
654
648
|
code: "EMAIL_VERIFICATION_REQUIRED",
|
|
655
649
|
message: PAYSTACK_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED.message
|
|
656
650
|
});
|
|
@@ -659,7 +653,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
659
653
|
if (planName !== void 0 && planName !== null && planName !== "") {
|
|
660
654
|
if (subscriptionOptions?.enabled !== true) throw new APIError("BAD_REQUEST", { message: "Subscriptions are not enabled." });
|
|
661
655
|
plan = await getPlanByName(options, planName) ?? void 0;
|
|
662
|
-
if (
|
|
656
|
+
if (plan === null || plan === void 0) {
|
|
663
657
|
const nativePlan = await ctx.context.adapter.findOne({
|
|
664
658
|
model: "paystackPlan",
|
|
665
659
|
where: [{
|
|
@@ -667,7 +661,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
667
661
|
value: planName
|
|
668
662
|
}]
|
|
669
663
|
});
|
|
670
|
-
if (nativePlan) plan = nativePlan;
|
|
664
|
+
if (nativePlan !== void 0 && nativePlan !== null) plan = nativePlan;
|
|
671
665
|
else plan = await ctx.context.adapter.findOne({
|
|
672
666
|
model: "paystackPlan",
|
|
673
667
|
where: [{
|
|
@@ -676,7 +670,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
676
670
|
}]
|
|
677
671
|
}) ?? void 0;
|
|
678
672
|
}
|
|
679
|
-
if (
|
|
673
|
+
if (plan === null || plan === void 0) throw new APIError("BAD_REQUEST", {
|
|
680
674
|
code: "SUBSCRIPTION_PLAN_NOT_FOUND",
|
|
681
675
|
message: PAYSTACK_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND.message,
|
|
682
676
|
status: 400
|
|
@@ -692,7 +686,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
692
686
|
}]
|
|
693
687
|
}) ?? void 0;
|
|
694
688
|
}
|
|
695
|
-
if (
|
|
689
|
+
if (product === null || product === void 0) throw new APIError("BAD_REQUEST", {
|
|
696
690
|
message: `Product '${productName}' not found.`,
|
|
697
691
|
status: 400
|
|
698
692
|
});
|
|
@@ -746,7 +740,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
746
740
|
});
|
|
747
741
|
}
|
|
748
742
|
}
|
|
749
|
-
if (plan &&
|
|
743
|
+
if (plan !== null && plan !== void 0 && (plan.seatAmount !== void 0 || "seatPriceId" in plan)) {
|
|
750
744
|
const members = await ctx.context.adapter.findMany({
|
|
751
745
|
model: "member",
|
|
752
746
|
where: [{
|
|
@@ -764,13 +758,13 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
764
758
|
let trialStart;
|
|
765
759
|
let trialEnd;
|
|
766
760
|
if (plan?.freeTrial?.days !== void 0 && plan.freeTrial.days !== null && plan.freeTrial.days > 0) {
|
|
767
|
-
if (
|
|
761
|
+
if ((await ctx.context.adapter.findMany({
|
|
768
762
|
model: "subscription",
|
|
769
763
|
where: [{
|
|
770
764
|
field: "referenceId",
|
|
771
765
|
value: referenceId
|
|
772
766
|
}]
|
|
773
|
-
}))?.some((sub) => sub.trialStart !== void 0 && sub.trialStart !== null || sub.trialEnd !== void 0 && sub.trialEnd !== null || sub.status === "trialing")) {
|
|
767
|
+
}))?.some((sub) => sub.trialStart !== void 0 && sub.trialStart !== null || sub.trialEnd !== void 0 && sub.trialEnd !== null || sub.status === "trialing") !== true) {
|
|
774
768
|
trialStart = /* @__PURE__ */ new Date();
|
|
775
769
|
trialEnd = /* @__PURE__ */ new Date();
|
|
776
770
|
trialEnd.setDate(trialEnd.getDate() + plan.freeTrial.days);
|
|
@@ -801,7 +795,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
801
795
|
value: "owner"
|
|
802
796
|
}]
|
|
803
797
|
});
|
|
804
|
-
if (ownerMember) {
|
|
798
|
+
if (ownerMember !== void 0 && ownerMember !== null) {
|
|
805
799
|
const ownerUser = await ctx.context.adapter.findOne({
|
|
806
800
|
model: "user",
|
|
807
801
|
where: [{
|
|
@@ -819,7 +813,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
819
813
|
userId: user.id,
|
|
820
814
|
plan: plan?.name.toLowerCase(),
|
|
821
815
|
product: product?.name.toLowerCase(),
|
|
822
|
-
isTrial:
|
|
816
|
+
isTrial: trialStart !== void 0 && trialStart !== null,
|
|
823
817
|
trialEnd: trialEnd?.toISOString(),
|
|
824
818
|
...extraMetadata
|
|
825
819
|
});
|
|
@@ -834,7 +828,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
834
828
|
const ops = getPaystackOps(options.paystackClient);
|
|
835
829
|
if (initBody.email !== void 0 && initBody.email !== null && initBody.email !== "") await ops.customerUpdate(paystackCustomerCode, { email: initBody.email });
|
|
836
830
|
} catch (_e) {}
|
|
837
|
-
if (plan && prorateAndCharge === true) {
|
|
831
|
+
if (plan !== void 0 && plan !== null && prorateAndCharge === true) {
|
|
838
832
|
const existingSub = await getOrganizationSubscription(ctx, referenceId);
|
|
839
833
|
if (existingSub?.status === "active" && existingSub.paystackAuthorizationCode !== null && existingSub.paystackAuthorizationCode !== void 0 && existingSub.paystackSubscriptionCode !== null && existingSub.paystackSubscriptionCode !== void 0) {
|
|
840
834
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -843,7 +837,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
843
837
|
const totalDays = Math.max(1, Math.ceil((periodEndLocal.getTime() - periodStartLocal.getTime()) / (1e3 * 60 * 60 * 24)));
|
|
844
838
|
const remainingDays = Math.max(0, Math.ceil((periodEndLocal.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24)));
|
|
845
839
|
let oldAmount = 0;
|
|
846
|
-
if (existingSub.plan) {
|
|
840
|
+
if (existingSub.plan !== void 0 && existingSub.plan !== null && existingSub.plan !== "") {
|
|
847
841
|
const oldPlan = await getPlanByName(options, existingSub.plan) ?? await ctx.context.adapter.findOne({
|
|
848
842
|
model: "paystackPlan",
|
|
849
843
|
where: [{
|
|
@@ -851,7 +845,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
851
845
|
value: existingSub.plan
|
|
852
846
|
}]
|
|
853
847
|
});
|
|
854
|
-
if (oldPlan) {
|
|
848
|
+
if (oldPlan !== null && oldPlan !== void 0) {
|
|
855
849
|
const oldSeatCount = existingSub.seats ?? 1;
|
|
856
850
|
oldAmount = (oldPlan.amount ?? 0) + oldSeatCount * (oldPlan.seatAmount ?? oldPlan.seatPriceId ?? 0);
|
|
857
851
|
}
|
|
@@ -873,7 +867,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
873
867
|
if (costDifference > 0 && remainingDays > 0) {
|
|
874
868
|
const proratedAmount = Math.round(costDifference / totalDays * remainingDays);
|
|
875
869
|
if (proratedAmount >= 5e3) {
|
|
876
|
-
|
|
870
|
+
if (unwrapSdkResult(await getPaystackOps(options.paystackClient).transactionChargeAuthorization({
|
|
877
871
|
email: targetEmail,
|
|
878
872
|
amount: proratedAmount,
|
|
879
873
|
authorization_code: existingSub.paystackAuthorizationCode,
|
|
@@ -885,8 +879,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
885
879
|
oldPlan: existingSub.plan,
|
|
886
880
|
remainingDays
|
|
887
881
|
}
|
|
888
|
-
}));
|
|
889
|
-
if ((chargeData?.data?.status ?? chargeData?.status) !== "success") throw new APIError("BAD_REQUEST", { message: "Failed to process prorated charge via saved authorization." });
|
|
882
|
+
}))?.status !== "success") throw new APIError("BAD_REQUEST", { message: "Failed to process prorated charge via saved authorization." });
|
|
890
883
|
}
|
|
891
884
|
}
|
|
892
885
|
await getPaystackOps(options.paystackClient).subscriptionUpdate({
|
|
@@ -913,7 +906,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
913
906
|
});
|
|
914
907
|
}
|
|
915
908
|
}
|
|
916
|
-
if (plan) if (trialStart) initBody.amount = 5e3;
|
|
909
|
+
if (plan !== void 0 && plan !== null) if (trialStart !== void 0 && trialStart !== null) initBody.amount = 5e3;
|
|
917
910
|
else {
|
|
918
911
|
initBody.plan = plan.planCode;
|
|
919
912
|
initBody.invoice_limit = plan.invoiceLimit;
|
|
@@ -921,19 +914,17 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
921
914
|
if (amount !== void 0 && amount !== null) {
|
|
922
915
|
finalAmount = amount;
|
|
923
916
|
initBody.quantity = 1;
|
|
924
|
-
} else finalAmount = (plan.amount ??
|
|
925
|
-
initBody.amount = Math.max(Math.round(finalAmount),
|
|
917
|
+
} else finalAmount = (plan.amount ?? 0) * (quantity ?? 1);
|
|
918
|
+
initBody.amount = Math.max(Math.round(finalAmount), 5e3);
|
|
926
919
|
}
|
|
927
920
|
else {
|
|
928
921
|
if (amount === void 0 || amount === null || amount === 0) throw new APIError("BAD_REQUEST", { message: "Amount is required for one-time payments" });
|
|
929
922
|
initBody.amount = Math.round(amount);
|
|
930
923
|
}
|
|
931
|
-
const
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
reference = data?.reference;
|
|
936
|
-
accessCode = data?.access_code;
|
|
924
|
+
const sdkRes = unwrapSdkResult(await paystack.transactionInitialize(initBody));
|
|
925
|
+
url = sdkRes?.authorization_url ?? sdkRes?.data?.authorization_url;
|
|
926
|
+
reference = sdkRes?.reference ?? sdkRes?.data?.reference;
|
|
927
|
+
accessCode = sdkRes?.access_code ?? sdkRes?.data?.access_code;
|
|
937
928
|
} catch (error) {
|
|
938
929
|
ctx.context.logger.error("Failed to initialize Paystack transaction", error);
|
|
939
930
|
throw new APIError("BAD_REQUEST", {
|
|
@@ -952,7 +943,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
952
943
|
status: "pending",
|
|
953
944
|
plan: plan?.name.toLowerCase(),
|
|
954
945
|
product: product?.name.toLowerCase(),
|
|
955
|
-
metadata: extraMetadata !== void 0 && extraMetadata !== null ? JSON.stringify(extraMetadata) : void 0,
|
|
946
|
+
metadata: extraMetadata !== void 0 && extraMetadata !== null && Object.keys(extraMetadata).length > 0 ? JSON.stringify(extraMetadata) : void 0,
|
|
956
947
|
createdAt: /* @__PURE__ */ new Date(),
|
|
957
948
|
updatedAt: /* @__PURE__ */ new Date()
|
|
958
949
|
}
|
|
@@ -967,7 +958,7 @@ const initializeTransaction = (options, path = "/paystack/initialize-transaction
|
|
|
967
958
|
value: referenceId
|
|
968
959
|
}]
|
|
969
960
|
});
|
|
970
|
-
if (org?.paystackCustomerCode !== void 0 && org
|
|
961
|
+
if (org?.paystackCustomerCode !== void 0 && org.paystackCustomerCode !== null && org.paystackCustomerCode !== "") storedCustomerCode = org.paystackCustomerCode;
|
|
971
962
|
}
|
|
972
963
|
const newSubscription = await ctx.context.adapter.create({
|
|
973
964
|
model: "subscription",
|
|
@@ -1023,7 +1014,8 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1023
1014
|
message: error?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_VERIFY_TRANSACTION.message
|
|
1024
1015
|
});
|
|
1025
1016
|
}
|
|
1026
|
-
const
|
|
1017
|
+
const dataRaw = unwrapSdkResult(verifyRes);
|
|
1018
|
+
const data = dataRaw?.data ?? dataRaw;
|
|
1027
1019
|
const status = data?.status;
|
|
1028
1020
|
const reference = data?.reference ?? ctx.body.reference;
|
|
1029
1021
|
const paystackId = data?.id !== void 0 && data?.id !== null ? String(data.id) : void 0;
|
|
@@ -1040,24 +1032,26 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1040
1032
|
if (session !== null && session !== void 0 && referenceId !== session.user.id) {
|
|
1041
1033
|
const authRef = subscriptionOptions?.authorizeReference;
|
|
1042
1034
|
let authorized = false;
|
|
1043
|
-
if (authRef !== void 0
|
|
1035
|
+
if (authRef !== void 0) authorized = await authRef({
|
|
1044
1036
|
user: session.user,
|
|
1045
1037
|
session,
|
|
1046
1038
|
referenceId,
|
|
1047
1039
|
action: "verify-transaction"
|
|
1048
1040
|
}, ctx);
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1041
|
+
if (authorized !== true) {
|
|
1042
|
+
if (options.organization?.enabled === true) {
|
|
1043
|
+
const member = await ctx.context.adapter.findOne({
|
|
1044
|
+
model: "member",
|
|
1045
|
+
where: [{
|
|
1046
|
+
field: "userId",
|
|
1047
|
+
value: session.user.id
|
|
1048
|
+
}, {
|
|
1049
|
+
field: "organizationId",
|
|
1050
|
+
value: referenceId
|
|
1051
|
+
}]
|
|
1052
|
+
});
|
|
1053
|
+
if (member !== void 0 && member !== null) authorized = true;
|
|
1054
|
+
}
|
|
1061
1055
|
}
|
|
1062
1056
|
if (!authorized) throw new APIError("UNAUTHORIZED");
|
|
1063
1057
|
}
|
|
@@ -1068,7 +1062,7 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1068
1062
|
status: "success",
|
|
1069
1063
|
paystackId,
|
|
1070
1064
|
...data?.amount !== void 0 && data?.amount !== null ? { amount: data.amount } : {},
|
|
1071
|
-
...data?.currency !== void 0 && data?.currency !== null ? { currency: data.currency } : {},
|
|
1065
|
+
...data?.currency !== void 0 && data?.currency !== null && data?.currency !== "" ? { currency: data.currency } : {},
|
|
1072
1066
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1073
1067
|
},
|
|
1074
1068
|
where: [{
|
|
@@ -1078,28 +1072,35 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1078
1072
|
});
|
|
1079
1073
|
const customer = data?.customer;
|
|
1080
1074
|
const paystackCustomerCodeFromPaystack = customer !== void 0 && customer !== null && typeof customer === "object" ? customer.customer_code : void 0;
|
|
1081
|
-
if (paystackCustomerCodeFromPaystack !== void 0 && paystackCustomerCodeFromPaystack !== null && paystackCustomerCodeFromPaystack !== "" && referenceId !== void 0 && referenceId !== null && referenceId !== "")
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1075
|
+
if (paystackCustomerCodeFromPaystack !== void 0 && paystackCustomerCodeFromPaystack !== null && paystackCustomerCodeFromPaystack !== "" && referenceId !== void 0 && referenceId !== null && referenceId !== "") {
|
|
1076
|
+
let isOrg = options.organization?.enabled === true && typeof referenceId === "string" && referenceId.startsWith("org_");
|
|
1077
|
+
if (!isOrg && options.organization?.enabled === true) {
|
|
1078
|
+
const org = await ctx.context.adapter.findOne({
|
|
1079
|
+
model: "organization",
|
|
1080
|
+
where: [{
|
|
1081
|
+
field: "id",
|
|
1082
|
+
value: referenceId
|
|
1083
|
+
}]
|
|
1084
|
+
});
|
|
1085
|
+
isOrg = org !== null && org !== void 0;
|
|
1086
|
+
}
|
|
1087
|
+
if (isOrg === true) await ctx.context.adapter.update({
|
|
1088
|
+
model: "organization",
|
|
1089
|
+
update: { paystackCustomerCode: paystackCustomerCodeFromPaystack },
|
|
1090
|
+
where: [{
|
|
1091
|
+
field: "id",
|
|
1092
|
+
value: referenceId
|
|
1093
|
+
}]
|
|
1094
|
+
});
|
|
1095
|
+
else await ctx.context.adapter.update({
|
|
1096
|
+
model: "user",
|
|
1097
|
+
update: { paystackCustomerCode: paystackCustomerCodeFromPaystack },
|
|
1098
|
+
where: [{
|
|
1099
|
+
field: "id",
|
|
1100
|
+
value: referenceId
|
|
1101
|
+
}]
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1103
1104
|
const transaction = await ctx.context.adapter.findOne({
|
|
1104
1105
|
model: "paystackTransaction",
|
|
1105
1106
|
where: [{
|
|
@@ -1107,7 +1108,7 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1107
1108
|
value: reference
|
|
1108
1109
|
}]
|
|
1109
1110
|
});
|
|
1110
|
-
if (transaction?.product) await syncProductQuantityFromPaystack(ctx, transaction.product, options.paystackClient);
|
|
1111
|
+
if (transaction?.product !== void 0 && transaction?.product !== null && transaction?.product !== "") await syncProductQuantityFromPaystack(ctx, transaction.product, options.paystackClient);
|
|
1111
1112
|
let isTrial = false;
|
|
1112
1113
|
let trialEnd;
|
|
1113
1114
|
let targetPlan;
|
|
@@ -1120,17 +1121,17 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1120
1121
|
}
|
|
1121
1122
|
let paystackSubscriptionCode;
|
|
1122
1123
|
if (isTrial === true && targetPlan !== void 0 && targetPlan !== null && targetPlan !== "" && trialEnd !== void 0 && trialEnd !== null && trialEnd !== "") {
|
|
1123
|
-
const email =
|
|
1124
|
+
const email = data.customer?.email;
|
|
1124
1125
|
const planConfig = (await getPlans(subscriptionOptions)).find((p) => p.name.toLowerCase() === targetPlan?.toLowerCase());
|
|
1125
|
-
if (planConfig !== void 0 && (planConfig.planCode === void 0 || planConfig.planCode === null || planConfig.planCode === "")) paystackSubscriptionCode = `LOC_${reference}`;
|
|
1126
|
-
if (authorizationCode !== void 0 && authorizationCode !== null && authorizationCode !== "" && email !== void 0 && email !== null && email !== "" && planConfig?.planCode !== void 0 && planConfig
|
|
1127
|
-
const
|
|
1126
|
+
if (planConfig !== void 0 && planConfig !== null && (planConfig.planCode === void 0 || planConfig.planCode === null || planConfig.planCode === "")) paystackSubscriptionCode = `LOC_${reference}`;
|
|
1127
|
+
if (authorizationCode !== void 0 && authorizationCode !== null && authorizationCode !== "" && email !== void 0 && email !== null && email !== "" && planConfig?.planCode !== void 0 && planConfig.planCode !== null && planConfig.planCode !== "") {
|
|
1128
|
+
const subRes = unwrapSdkResult(await paystack.subscriptionCreate({
|
|
1128
1129
|
customer: email,
|
|
1129
1130
|
plan: planConfig.planCode,
|
|
1130
1131
|
authorization: authorizationCode,
|
|
1131
1132
|
start_date: trialEnd
|
|
1132
1133
|
}));
|
|
1133
|
-
paystackSubscriptionCode = (
|
|
1134
|
+
paystackSubscriptionCode = (subRes?.data ?? subRes)?.subscription_code;
|
|
1134
1135
|
}
|
|
1135
1136
|
} else if (isTrial !== true) {
|
|
1136
1137
|
const planCodeFromPaystack = (data?.plan)?.plan_code;
|
|
@@ -1145,15 +1146,15 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1145
1146
|
}]
|
|
1146
1147
|
});
|
|
1147
1148
|
let targetSub;
|
|
1148
|
-
if (existingSubs && existingSubs.length > 0) targetSub = existingSubs.find((s) =>
|
|
1149
|
+
if (existingSubs !== null && existingSubs !== void 0 && existingSubs.length > 0) targetSub = existingSubs.find((s) => referenceId === void 0 || referenceId === null || referenceId === "" || s.referenceId === referenceId);
|
|
1149
1150
|
let updatedSubscription = null;
|
|
1150
1151
|
if (targetSub !== void 0 && targetSub !== null) updatedSubscription = await ctx.context.adapter.update({
|
|
1151
1152
|
model: "subscription",
|
|
1152
1153
|
update: {
|
|
1153
|
-
status: isTrial
|
|
1154
|
+
status: isTrial ? "trialing" : "active",
|
|
1154
1155
|
periodStart: /* @__PURE__ */ new Date(),
|
|
1155
1156
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
1156
|
-
...isTrial === true && trialEnd !== void 0 && trialEnd !== null
|
|
1157
|
+
...isTrial === true && trialEnd !== void 0 && trialEnd !== null ? {
|
|
1157
1158
|
trialStart: /* @__PURE__ */ new Date(),
|
|
1158
1159
|
trialEnd: new Date(trialEnd),
|
|
1159
1160
|
periodEnd: new Date(trialEnd)
|
|
@@ -1177,20 +1178,6 @@ const verifyTransaction = (options, path = "/paystack/verify-transaction") => {
|
|
|
1177
1178
|
} catch (e) {
|
|
1178
1179
|
ctx.context.logger.error("Failed to update transaction/subscription after verification", e);
|
|
1179
1180
|
}
|
|
1180
|
-
} else if (status === "failed" || status === "abandoned") try {
|
|
1181
|
-
await ctx.context.adapter.update({
|
|
1182
|
-
model: "paystackTransaction",
|
|
1183
|
-
update: {
|
|
1184
|
-
status,
|
|
1185
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1186
|
-
},
|
|
1187
|
-
where: [{
|
|
1188
|
-
field: "reference",
|
|
1189
|
-
value: reference
|
|
1190
|
-
}]
|
|
1191
|
-
});
|
|
1192
|
-
} catch (e) {
|
|
1193
|
-
ctx.context.logger.error("Failed to update transaction status", e);
|
|
1194
1181
|
}
|
|
1195
1182
|
return ctx.json({
|
|
1196
1183
|
status,
|
|
@@ -1216,7 +1203,7 @@ const listSubscriptions = (options) => {
|
|
|
1216
1203
|
if (!session) throw new APIError("UNAUTHORIZED");
|
|
1217
1204
|
const referenceIdPart = ctx.context.referenceId;
|
|
1218
1205
|
const queryRefId = ctx.query?.referenceId;
|
|
1219
|
-
const referenceId = referenceIdPart
|
|
1206
|
+
const referenceId = referenceIdPart ?? queryRefId ?? session.user.id;
|
|
1220
1207
|
const res = await ctx.context.adapter.findMany({
|
|
1221
1208
|
model: "subscription",
|
|
1222
1209
|
where: [{
|
|
@@ -1296,7 +1283,7 @@ const disablePaystackSubscription = (options, path = "/paystack/disable-subscrip
|
|
|
1296
1283
|
value: subscriptionCode
|
|
1297
1284
|
}]
|
|
1298
1285
|
});
|
|
1299
|
-
if (sub) {
|
|
1286
|
+
if (sub !== null && sub !== void 0) {
|
|
1300
1287
|
await ctx.context.adapter.update({
|
|
1301
1288
|
model: "subscription",
|
|
1302
1289
|
update: {
|
|
@@ -1317,15 +1304,15 @@ const disablePaystackSubscription = (options, path = "/paystack/disable-subscrip
|
|
|
1317
1304
|
let nextPaymentDate;
|
|
1318
1305
|
try {
|
|
1319
1306
|
const fetchRes = unwrapSdkResult(await paystack.subscriptionFetch(subscriptionCode));
|
|
1320
|
-
const data = fetchRes
|
|
1307
|
+
const data = fetchRes?.data ?? fetchRes;
|
|
1321
1308
|
if (emailToken === void 0 || emailToken === null || emailToken === "") emailToken = data?.email_token;
|
|
1322
1309
|
nextPaymentDate = data?.next_payment_date;
|
|
1323
1310
|
} catch {}
|
|
1324
1311
|
if (emailToken === void 0 || emailToken === null || emailToken === "") try {
|
|
1325
1312
|
const linkRes = unwrapSdkResult(await paystack.subscriptionManageLink(subscriptionCode));
|
|
1326
|
-
const data = linkRes
|
|
1327
|
-
const link = typeof data === "string" ? data : data
|
|
1328
|
-
if (
|
|
1313
|
+
const data = linkRes?.data ?? linkRes;
|
|
1314
|
+
const link = typeof data === "string" ? data : data.link;
|
|
1315
|
+
if (typeof link === "string" && link !== "") emailToken = tryGetEmailTokenFromSubscriptionManageLink(link);
|
|
1329
1316
|
} catch {}
|
|
1330
1317
|
if (emailToken === void 0 || emailToken === null || emailToken === "") throw new Error("Could not retrieve email_token for subscription disable.");
|
|
1331
1318
|
await paystack.subscriptionDisable({
|
|
@@ -1340,7 +1327,7 @@ const disablePaystackSubscription = (options, path = "/paystack/disable-subscrip
|
|
|
1340
1327
|
value: subscriptionCode
|
|
1341
1328
|
}]
|
|
1342
1329
|
});
|
|
1343
|
-
if (sub) await ctx.context.adapter.update({
|
|
1330
|
+
if (sub !== void 0 && sub !== null) await ctx.context.adapter.update({
|
|
1344
1331
|
model: "subscription",
|
|
1345
1332
|
update: {
|
|
1346
1333
|
status: atPeriodEnd === false ? "canceled" : "active",
|
|
@@ -1380,13 +1367,13 @@ const enablePaystackSubscription = (options, path = "/paystack/enable-subscripti
|
|
|
1380
1367
|
let emailToken = ctx.body.emailToken;
|
|
1381
1368
|
if (emailToken === void 0 || emailToken === null || emailToken === "") try {
|
|
1382
1369
|
const fetchRes = unwrapSdkResult(await paystack.subscriptionFetch(subscriptionCode));
|
|
1383
|
-
emailToken = (fetchRes
|
|
1370
|
+
emailToken = (fetchRes?.data ?? fetchRes)?.email_token;
|
|
1384
1371
|
} catch {}
|
|
1385
1372
|
if (emailToken === void 0 || emailToken === null || emailToken === "") try {
|
|
1386
1373
|
const linkRes = unwrapSdkResult(await paystack.subscriptionManageLink(subscriptionCode));
|
|
1387
|
-
const data = linkRes
|
|
1388
|
-
const link = typeof data === "string" ? data : data
|
|
1389
|
-
if (
|
|
1374
|
+
const data = linkRes?.data ?? linkRes;
|
|
1375
|
+
const link = typeof data === "string" ? data : data.link;
|
|
1376
|
+
if (typeof link === "string" && link !== "") emailToken = tryGetEmailTokenFromSubscriptionManageLink(link);
|
|
1390
1377
|
} catch {}
|
|
1391
1378
|
if (emailToken === void 0 || emailToken === null || emailToken === "") throw new APIError("BAD_REQUEST", { message: "Could not retrieve email_token for subscription enable." });
|
|
1392
1379
|
await paystack.subscriptionEnable({
|
|
@@ -1430,9 +1417,9 @@ const getSubscriptionManageLink = (options, path = "/paystack/get-subscription-m
|
|
|
1430
1417
|
const paystack = getPaystackOps(options.paystackClient);
|
|
1431
1418
|
try {
|
|
1432
1419
|
const res = unwrapSdkResult(await paystack.subscriptionManageLink(subscriptionCode));
|
|
1433
|
-
const data = res
|
|
1434
|
-
const link = typeof data === "string" ? data : data
|
|
1435
|
-
return ctx.json({ link });
|
|
1420
|
+
const data = res?.data ?? res;
|
|
1421
|
+
const link = typeof data === "string" ? data : data.link;
|
|
1422
|
+
return ctx.json({ link: typeof link === "string" ? link : null });
|
|
1436
1423
|
} catch (error) {
|
|
1437
1424
|
ctx.context.logger.error("Failed to get subscription manage link", error);
|
|
1438
1425
|
throw new APIError("BAD_REQUEST", { message: error?.message ?? "Failed to get subscription manage link" });
|
|
@@ -1451,16 +1438,14 @@ const syncProducts = (options) => {
|
|
|
1451
1438
|
disableBody: true,
|
|
1452
1439
|
use: [sessionMiddleware]
|
|
1453
1440
|
}, async (ctx) => {
|
|
1454
|
-
console.error("DEBUG: syncProducts endpoint hit!");
|
|
1455
1441
|
const paystack = getPaystackOps(options.paystackClient);
|
|
1456
1442
|
try {
|
|
1457
|
-
const
|
|
1458
|
-
const
|
|
1459
|
-
if (!Array.isArray(
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
for (const product of productsData) {
|
|
1443
|
+
const dataRaw = unwrapSdkResult(await paystack.productList());
|
|
1444
|
+
const productsDataRaw = dataRaw?.data ?? dataRaw;
|
|
1445
|
+
if (!Array.isArray(productsDataRaw)) return ctx.json({ products: [] });
|
|
1446
|
+
const productsData = productsDataRaw;
|
|
1447
|
+
for (const productRaw of productsData) {
|
|
1448
|
+
const product = productRaw;
|
|
1464
1449
|
const paystackId = String(product.id);
|
|
1465
1450
|
const existing = await ctx.context.adapter.findOne({
|
|
1466
1451
|
model: "paystackProduct",
|
|
@@ -1469,21 +1454,21 @@ const syncProducts = (options) => {
|
|
|
1469
1454
|
value: paystackId
|
|
1470
1455
|
}]
|
|
1471
1456
|
});
|
|
1472
|
-
const
|
|
1473
|
-
name: product.name,
|
|
1474
|
-
description: product.description,
|
|
1475
|
-
price: product.price,
|
|
1476
|
-
currency: product.currency,
|
|
1477
|
-
quantity: product.quantity,
|
|
1478
|
-
unlimited: product.unlimited,
|
|
1457
|
+
const productFields = {
|
|
1458
|
+
name: typeof product.name === "string" ? product.name : "",
|
|
1459
|
+
description: typeof product.description === "string" ? product.description : "",
|
|
1460
|
+
price: typeof product.price === "number" ? product.price : 0,
|
|
1461
|
+
currency: typeof product.currency === "string" ? product.currency : "",
|
|
1462
|
+
quantity: typeof product.quantity === "number" ? product.quantity : 0,
|
|
1463
|
+
unlimited: product.unlimited === true,
|
|
1479
1464
|
paystackId,
|
|
1480
|
-
slug: product.slug
|
|
1481
|
-
metadata: product.metadata ? JSON.stringify(product.metadata) : void 0,
|
|
1465
|
+
slug: typeof product.slug === "string" && product.slug !== "" ? product.slug : typeof product.name === "string" ? product.name.toLowerCase().replace(/\s+/g, "-") : "",
|
|
1466
|
+
metadata: product.metadata !== void 0 && product.metadata !== null ? JSON.stringify(product.metadata) : void 0,
|
|
1482
1467
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1483
1468
|
};
|
|
1484
|
-
if (existing) await ctx.context.adapter.update({
|
|
1469
|
+
if (existing !== null && existing !== void 0) await ctx.context.adapter.update({
|
|
1485
1470
|
model: "paystackProduct",
|
|
1486
|
-
update:
|
|
1471
|
+
update: productFields,
|
|
1487
1472
|
where: [{
|
|
1488
1473
|
field: "id",
|
|
1489
1474
|
value: existing.id
|
|
@@ -1492,7 +1477,7 @@ const syncProducts = (options) => {
|
|
|
1492
1477
|
else await ctx.context.adapter.create({
|
|
1493
1478
|
model: "paystackProduct",
|
|
1494
1479
|
data: {
|
|
1495
|
-
...
|
|
1480
|
+
...productFields,
|
|
1496
1481
|
createdAt: /* @__PURE__ */ new Date()
|
|
1497
1482
|
}
|
|
1498
1483
|
});
|
|
@@ -1526,7 +1511,7 @@ const syncPlans = (options) => {
|
|
|
1526
1511
|
const paystack = getPaystackOps(options.paystackClient);
|
|
1527
1512
|
try {
|
|
1528
1513
|
const res = unwrapSdkResult(await paystack.planList());
|
|
1529
|
-
const plansData = res
|
|
1514
|
+
const plansData = res?.data ?? res;
|
|
1530
1515
|
if (!Array.isArray(plansData)) return ctx.json({
|
|
1531
1516
|
status: "success",
|
|
1532
1517
|
count: 0
|
|
@@ -1548,10 +1533,10 @@ const syncPlans = (options) => {
|
|
|
1548
1533
|
interval: plan.interval,
|
|
1549
1534
|
planCode: plan.plan_code,
|
|
1550
1535
|
paystackId,
|
|
1551
|
-
metadata: plan.metadata ? JSON.stringify(plan.metadata) : void 0,
|
|
1536
|
+
metadata: plan.metadata !== void 0 && plan.metadata !== null ? JSON.stringify(plan.metadata) : void 0,
|
|
1552
1537
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1553
1538
|
};
|
|
1554
|
-
if (existing) await ctx.context.adapter.update({
|
|
1539
|
+
if (existing !== void 0 && existing !== null) await ctx.context.adapter.update({
|
|
1555
1540
|
model: "paystackPlan",
|
|
1556
1541
|
update: planData,
|
|
1557
1542
|
where: [{
|
|
@@ -1621,10 +1606,10 @@ const chargeRecurringSubscription = (options) => {
|
|
|
1621
1606
|
value: subscriptionId
|
|
1622
1607
|
}]
|
|
1623
1608
|
});
|
|
1624
|
-
if (subscription ===
|
|
1609
|
+
if (subscription === void 0 || subscription === null) throw new APIError("NOT_FOUND", { message: "Subscription not found" });
|
|
1625
1610
|
if (subscription.paystackAuthorizationCode === void 0 || subscription.paystackAuthorizationCode === null || subscription.paystackAuthorizationCode === "") throw new APIError("BAD_REQUEST", { message: "No authorization code found for this subscription" });
|
|
1626
1611
|
const plan = (await getPlans(options.subscription)).find((p) => p.name.toLowerCase() === subscription.plan.toLowerCase());
|
|
1627
|
-
if (plan
|
|
1612
|
+
if (!plan) throw new APIError("NOT_FOUND", { message: "Plan not found" });
|
|
1628
1613
|
const amount = bodyAmount ?? plan.amount;
|
|
1629
1614
|
if (amount === void 0 || amount === null) throw new APIError("BAD_REQUEST", { message: "Plan amount is not defined" });
|
|
1630
1615
|
let email;
|
|
@@ -1663,7 +1648,7 @@ const chargeRecurringSubscription = (options) => {
|
|
|
1663
1648
|
message: `Amount ${amount} is less than the minimum required for ${finalCurrency}.`,
|
|
1664
1649
|
status: 400
|
|
1665
1650
|
});
|
|
1666
|
-
const
|
|
1651
|
+
const dataRaw = unwrapSdkResult(await getPaystackOps(options.paystackClient).transactionChargeAuthorization({
|
|
1667
1652
|
email,
|
|
1668
1653
|
amount,
|
|
1669
1654
|
authorization_code: subscription.paystackAuthorizationCode,
|
|
@@ -1674,8 +1659,8 @@ const chargeRecurringSubscription = (options) => {
|
|
|
1674
1659
|
plan: plan.name
|
|
1675
1660
|
}
|
|
1676
1661
|
}));
|
|
1677
|
-
const chargeData =
|
|
1678
|
-
if (chargeData?.status === "success") {
|
|
1662
|
+
const chargeData = dataRaw?.data ?? dataRaw;
|
|
1663
|
+
if (chargeData?.status === "success" || dataRaw?.status === "success") {
|
|
1679
1664
|
const now = /* @__PURE__ */ new Date();
|
|
1680
1665
|
const nextPeriodEnd = getNextPeriodEnd(now, plan.interval ?? "monthly");
|
|
1681
1666
|
await ctx.context.adapter.update({
|
|
@@ -1684,7 +1669,7 @@ const chargeRecurringSubscription = (options) => {
|
|
|
1684
1669
|
periodStart: now,
|
|
1685
1670
|
periodEnd: nextPeriodEnd,
|
|
1686
1671
|
updatedAt: now,
|
|
1687
|
-
paystackTransactionReference: chargeData
|
|
1672
|
+
paystackTransactionReference: chargeData?.reference ?? dataRaw?.reference
|
|
1688
1673
|
},
|
|
1689
1674
|
where: [{
|
|
1690
1675
|
field: "id",
|
|
@@ -1702,7 +1687,6 @@ const chargeRecurringSubscription = (options) => {
|
|
|
1702
1687
|
}, { status: 400 });
|
|
1703
1688
|
});
|
|
1704
1689
|
};
|
|
1705
|
-
|
|
1706
1690
|
//#endregion
|
|
1707
1691
|
//#region src/schema.ts
|
|
1708
1692
|
const transactions = { paystackTransaction: { fields: {
|
|
@@ -1965,7 +1949,6 @@ const getSchema = (options) => {
|
|
|
1965
1949
|
}
|
|
1966
1950
|
return mergeSchema(baseSchema, options.schema);
|
|
1967
1951
|
};
|
|
1968
|
-
|
|
1969
1952
|
//#endregion
|
|
1970
1953
|
//#region src/index.ts
|
|
1971
1954
|
const INTERNAL_ERROR_CODES = defineErrorCodes({ ...Object.fromEntries(Object.entries(PAYSTACK_ERROR_CODES).map(([key, value]) => [key, typeof value === "string" ? value : value.message])) });
|
|
@@ -1999,14 +1982,14 @@ const paystack = (options) => {
|
|
|
1999
1982
|
return { options: {
|
|
2000
1983
|
databaseHooks: {
|
|
2001
1984
|
user: { create: { async after(user, hookCtx) {
|
|
2002
|
-
if (hookCtx
|
|
1985
|
+
if (!hookCtx || options.createCustomerOnSignUp !== true || user.email === null || user.email === void 0 || user.email === "") return;
|
|
2003
1986
|
const sdkRes = unwrapSdkResult(await getPaystackOps(options.paystackClient).customerCreate({
|
|
2004
1987
|
email: user.email,
|
|
2005
1988
|
first_name: user.name ?? void 0,
|
|
2006
1989
|
metadata: { userId: user.id }
|
|
2007
1990
|
}));
|
|
2008
1991
|
const customerCode = sdkRes?.customer_code ?? (sdkRes?.data)?.customer_code;
|
|
2009
|
-
if (customerCode ===
|
|
1992
|
+
if (customerCode === "" || customerCode === null || customerCode === void 0) return;
|
|
2010
1993
|
await ctx.adapter.update({
|
|
2011
1994
|
model: "user",
|
|
2012
1995
|
where: [{
|
|
@@ -2031,7 +2014,7 @@ const paystack = (options) => {
|
|
|
2031
2014
|
value: "owner"
|
|
2032
2015
|
}]
|
|
2033
2016
|
});
|
|
2034
|
-
if (ownerMember
|
|
2017
|
+
if (ownerMember) targetEmail = (await ctx.adapter.findOne({
|
|
2035
2018
|
model: "user",
|
|
2036
2019
|
where: [{
|
|
2037
2020
|
field: "id",
|
|
@@ -2047,7 +2030,7 @@ const paystack = (options) => {
|
|
|
2047
2030
|
}, extraCreateParams);
|
|
2048
2031
|
const sdkRes = unwrapSdkResult(await getPaystackOps(options.paystackClient).customerCreate(params));
|
|
2049
2032
|
const customerCode = sdkRes?.customer_code ?? (sdkRes?.data)?.customer_code;
|
|
2050
|
-
if (customerCode === void 0 ||
|
|
2033
|
+
if (customerCode === "" || customerCode === null || customerCode === void 0 || sdkRes === null || sdkRes === void 0) return;
|
|
2051
2034
|
await ctx.internalAdapter.updateOrganization(org.id, { paystackCustomerCode: customerCode });
|
|
2052
2035
|
await options.organization?.onCustomerCreate?.({
|
|
2053
2036
|
paystackCustomer: sdkRes,
|
|
@@ -2067,11 +2050,11 @@ const paystack = (options) => {
|
|
|
2067
2050
|
if (options.subscription?.enabled === true && member.organizationId && ctx !== null && ctx !== void 0) await checkSeatLimit(ctx, member.organizationId);
|
|
2068
2051
|
},
|
|
2069
2052
|
after: async (member, ctx) => {
|
|
2070
|
-
if (options.subscription?.enabled === true &&
|
|
2053
|
+
if (options.subscription?.enabled === true && typeof member?.organizationId === "string" && ctx) await syncSubscriptionSeats(ctx, member.organizationId, routeOptions);
|
|
2071
2054
|
}
|
|
2072
2055
|
},
|
|
2073
2056
|
delete: { after: async (member, ctx) => {
|
|
2074
|
-
if (options.subscription?.enabled === true &&
|
|
2057
|
+
if (options.subscription?.enabled === true && typeof member?.organizationId === "string" && ctx) await syncSubscriptionSeats(ctx, member.organizationId, routeOptions);
|
|
2075
2058
|
} }
|
|
2076
2059
|
},
|
|
2077
2060
|
invitation: {
|
|
@@ -2080,18 +2063,18 @@ const paystack = (options) => {
|
|
|
2080
2063
|
if (options.subscription?.enabled === true && invitation.organizationId && ctx !== null && ctx !== void 0) await checkSeatLimit(ctx, invitation.organizationId);
|
|
2081
2064
|
},
|
|
2082
2065
|
after: async (invitation, ctx) => {
|
|
2083
|
-
if (options.subscription?.enabled === true &&
|
|
2066
|
+
if (options.subscription?.enabled === true && typeof invitation?.organizationId === "string" && ctx) await syncSubscriptionSeats(ctx, invitation.organizationId, routeOptions);
|
|
2084
2067
|
}
|
|
2085
2068
|
},
|
|
2086
2069
|
delete: { after: async (invitation, ctx) => {
|
|
2087
|
-
if (options.subscription?.enabled === true &&
|
|
2070
|
+
if (options.subscription?.enabled === true && typeof invitation?.organizationId === "string" && ctx) await syncSubscriptionSeats(ctx, invitation.organizationId, routeOptions);
|
|
2088
2071
|
} }
|
|
2089
2072
|
},
|
|
2090
2073
|
team: { create: { before: async (team, ctx) => {
|
|
2091
|
-
if (options.subscription?.enabled === true && team.organizationId && ctx
|
|
2074
|
+
if (options.subscription?.enabled === true && team.organizationId && ctx) {
|
|
2092
2075
|
const subscription = await getOrganizationSubscription(ctx, team.organizationId);
|
|
2093
|
-
if (subscription
|
|
2094
|
-
const maxTeams = ((await getPlanByName(
|
|
2076
|
+
if (subscription) {
|
|
2077
|
+
const maxTeams = ((await getPlanByName(routeOptions, subscription.plan))?.limits)?.teams;
|
|
2095
2078
|
if (typeof maxTeams === "number") await checkTeamLimit(ctx, team.organizationId, maxTeams);
|
|
2096
2079
|
}
|
|
2097
2080
|
}
|
|
@@ -2101,7 +2084,7 @@ const paystack = (options) => {
|
|
|
2101
2084
|
$ERROR_CODES: INTERNAL_ERROR_CODES
|
|
2102
2085
|
};
|
|
2103
2086
|
};
|
|
2104
|
-
|
|
2105
2087
|
//#endregion
|
|
2106
2088
|
export { paystack };
|
|
2089
|
+
|
|
2107
2090
|
//# sourceMappingURL=index.mjs.map
|