@nexo-labs/payload-stripe-inventory 1.6.10 → 1.6.12
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-BFzOtUiG.d.mts +72 -0
- package/dist/index-BFzOtUiG.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/server/index.d.mts +187 -30
- package/dist/server/index.d.mts.map +1 -1
- package/dist/server/index.mjs +338 -164
- package/dist/server/index.mjs.map +1 -1
- package/package.json +4 -4
- package/dist/index-D-NQPUJO.d.mts +0 -892
- package/dist/index-D-NQPUJO.d.mts.map +0 -1
package/dist/server/index.mjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { S as generateUserInventory, _ as PricingType, a as getPermissionsSlugs, b as permissionSlugs, d as COLLECTION_SLUG_PRICES, f as COLLECTION_SLUG_PRODUCTS, g as PricingPlanInterval, m as MAX_UNLOCKS_PER_WEEK, n as countWeeklyUnlocksQuery, p as COLLECTION_SLUG_USER, r as checkIfUserCanUnlockQuery, u as COLLECTION_SLUG_CUSTOMERS, x as generateCustomerInventory, y as formatOptions } from "../src-BmlQoR4x.mjs";
|
|
2
|
+
import { stripePlugin } from "@payloadcms/plugin-stripe";
|
|
2
3
|
import Stripe from "stripe";
|
|
3
|
-
import { headers } from "next/headers.js";
|
|
4
|
-
import { NextResponse } from "next/server.js";
|
|
5
4
|
import { COLLECTION_SLUG_TAXONOMY, buildTaxonomyRelationship } from "@nexo-labs/payload-taxonomies";
|
|
6
|
-
import { stripePlugin } from "@payloadcms/plugin-stripe";
|
|
7
5
|
|
|
8
6
|
//#region src/server/utils/payload/upsert.ts
|
|
9
7
|
const payloadUpsert = async ({ payload, collection, data, where }) => {
|
|
@@ -42,7 +40,7 @@ const updatePrices = async (payload) => {
|
|
|
42
40
|
limit: 100,
|
|
43
41
|
active: true
|
|
44
42
|
})).data.map((price) => priceUpsert(price, payload));
|
|
45
|
-
const pricesByProductId = (await Promise.all(promises)).
|
|
43
|
+
const pricesByProductId = (await Promise.all(promises)).filter((p) => p !== null).reduce((acc, { productId, priceId }) => {
|
|
46
44
|
if (!acc[productId]) acc[productId] = [];
|
|
47
45
|
acc[productId].push(priceId);
|
|
48
46
|
return acc;
|
|
@@ -468,13 +466,6 @@ const customerDeleted = async (customer, payload) => {
|
|
|
468
466
|
}
|
|
469
467
|
};
|
|
470
468
|
|
|
471
|
-
//#endregion
|
|
472
|
-
//#region src/server/access/get-current-user-query.ts
|
|
473
|
-
async function getCurrentUserQuery(payload) {
|
|
474
|
-
const headers$1 = await headers();
|
|
475
|
-
return (await payload.auth({ headers: headers$1 })).user;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
469
|
//#endregion
|
|
479
470
|
//#region src/server/actions/unlock-item-for-user-action.ts
|
|
480
471
|
const addUniqueUnlock = (unlocks, collection, contentId) => {
|
|
@@ -485,9 +476,16 @@ const addUniqueUnlock = (unlocks, collection, contentId) => {
|
|
|
485
476
|
dateUnlocked: /* @__PURE__ */ new Date()
|
|
486
477
|
}];
|
|
487
478
|
};
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
479
|
+
/**
|
|
480
|
+
* Unlocks an item for a user, adding it to their inventory.
|
|
481
|
+
*
|
|
482
|
+
* @param payload - The Payload instance
|
|
483
|
+
* @param user - The authenticated user
|
|
484
|
+
* @param collection - The collection slug of the item to unlock
|
|
485
|
+
* @param contentId - The ID of the item to unlock
|
|
486
|
+
* @returns Result indicating success or error message
|
|
487
|
+
*/
|
|
488
|
+
const unlockItemForUser = async (payload, user, collection, contentId) => {
|
|
491
489
|
if (!user || !user.id) return { error: "Usuario no válido" };
|
|
492
490
|
const item = await payload.findByID({
|
|
493
491
|
collection,
|
|
@@ -549,148 +547,336 @@ async function getCustomerFromStripeOrCreate(email, name) {
|
|
|
549
547
|
}
|
|
550
548
|
|
|
551
549
|
//#endregion
|
|
552
|
-
//#region src/server/
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
550
|
+
//#region src/server/endpoints/validators/request-validator.ts
|
|
551
|
+
/**
|
|
552
|
+
* Creates a JSON response using Web API Response
|
|
553
|
+
*/
|
|
554
|
+
function jsonResponse(data, options) {
|
|
555
|
+
return new Response(JSON.stringify(data), {
|
|
556
|
+
headers: { "Content-Type": "application/json" },
|
|
557
|
+
...options
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Creates a redirect response using Web API Response
|
|
562
|
+
* @param url - The URL to redirect to
|
|
563
|
+
* @param status - HTTP status code (default: 303 See Other)
|
|
564
|
+
*/
|
|
565
|
+
function redirectResponse(url, status = 303) {
|
|
566
|
+
return new Response(null, {
|
|
567
|
+
status,
|
|
568
|
+
headers: { Location: url }
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Creates an error response
|
|
573
|
+
*/
|
|
574
|
+
function errorResponse(message, status = 400) {
|
|
575
|
+
return jsonResponse({ error: message }, { status });
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Validates that the request has an authenticated user
|
|
579
|
+
* Uses the config's resolveUser if provided, otherwise uses request.user
|
|
580
|
+
*/
|
|
581
|
+
async function validateAuthenticatedRequest(request, config) {
|
|
582
|
+
if (config.checkPermissions) {
|
|
583
|
+
if (!await config.checkPermissions(request)) return {
|
|
584
|
+
success: false,
|
|
585
|
+
error: errorResponse("Permission denied", 403)
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
let user = null;
|
|
589
|
+
if (config.resolveUser) user = await config.resolveUser(request);
|
|
590
|
+
else user = request.user;
|
|
591
|
+
if (!user) return {
|
|
592
|
+
success: false,
|
|
593
|
+
error: errorResponse("You must be logged in to access this endpoint", 401)
|
|
594
|
+
};
|
|
595
|
+
if (!user.email) return {
|
|
596
|
+
success: false,
|
|
597
|
+
error: errorResponse("User email is required", 400)
|
|
598
|
+
};
|
|
599
|
+
return {
|
|
600
|
+
success: true,
|
|
601
|
+
user,
|
|
602
|
+
payload: request.payload
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
//#endregion
|
|
607
|
+
//#region src/server/endpoints/handlers/checkout-handler.ts
|
|
608
|
+
/**
|
|
609
|
+
* Creates a handler for Stripe checkout sessions (subscriptions)
|
|
610
|
+
*
|
|
611
|
+
* @param config - Endpoint configuration
|
|
612
|
+
* @returns PayloadHandler for checkout endpoint
|
|
613
|
+
*/
|
|
614
|
+
function createCheckoutHandler(config) {
|
|
615
|
+
return async (request) => {
|
|
616
|
+
try {
|
|
617
|
+
const validated = await validateAuthenticatedRequest(request, config);
|
|
618
|
+
if (!validated.success) return validated.error;
|
|
619
|
+
const { user, payload } = validated;
|
|
620
|
+
const priceId = new URL(request.url || "").searchParams.get("priceId");
|
|
621
|
+
if (!priceId) return errorResponse("priceId is required", 400);
|
|
622
|
+
const stripe = stripeBuilder();
|
|
623
|
+
const customerId = await getCustomerFromStripeOrCreate(user.email, user.name);
|
|
624
|
+
await upsertCustomerInventoryAndSyncWithUser(payload, user.customer?.inventory, user.email, customerId);
|
|
625
|
+
const metadata = { type: "subscription" };
|
|
626
|
+
const checkoutResult = await stripe.checkout.sessions.create({
|
|
627
|
+
success_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?success=${Date.now()}`,
|
|
628
|
+
cancel_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}?error=${Date.now()}`,
|
|
629
|
+
mode: "subscription",
|
|
630
|
+
customer: customerId,
|
|
631
|
+
client_reference_id: String(user.id),
|
|
632
|
+
line_items: [{
|
|
633
|
+
price: priceId,
|
|
634
|
+
quantity: 1
|
|
635
|
+
}],
|
|
636
|
+
metadata,
|
|
637
|
+
tax_id_collection: { enabled: true },
|
|
638
|
+
customer_update: {
|
|
639
|
+
name: "auto",
|
|
640
|
+
address: "auto",
|
|
641
|
+
shipping: "auto"
|
|
574
642
|
},
|
|
575
|
-
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
metadata,
|
|
583
|
-
payment_intent_data: { metadata },
|
|
584
|
-
invoice_creation: {
|
|
585
|
-
enabled: true,
|
|
586
|
-
invoice_data: { metadata }
|
|
643
|
+
subscription_data: { metadata }
|
|
644
|
+
});
|
|
645
|
+
if (checkoutResult.url) return redirectResponse(checkoutResult.url, 303);
|
|
646
|
+
return errorResponse("Failed to create checkout URL", 406);
|
|
647
|
+
} catch (error) {
|
|
648
|
+
console.error("[Stripe Checkout Error]", error);
|
|
649
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
|
|
587
650
|
}
|
|
588
|
-
}
|
|
589
|
-
return NextResponse.json({ url: session.url });
|
|
651
|
+
};
|
|
590
652
|
}
|
|
591
653
|
|
|
592
654
|
//#endregion
|
|
593
|
-
//#region src/server/
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
655
|
+
//#region src/server/endpoints/handlers/donation-handler.ts
|
|
656
|
+
/**
|
|
657
|
+
* Creates a handler for one-time donation payments
|
|
658
|
+
*
|
|
659
|
+
* @param config - Endpoint configuration
|
|
660
|
+
* @returns PayloadHandler for donation endpoint
|
|
661
|
+
*/
|
|
662
|
+
function createDonationHandler(config) {
|
|
663
|
+
return async (request) => {
|
|
664
|
+
try {
|
|
665
|
+
const validated = await validateAuthenticatedRequest(request, config);
|
|
666
|
+
if (!validated.success) return validated.error;
|
|
667
|
+
const { user, payload } = validated;
|
|
668
|
+
const amountParam = new URL(request.url || "").searchParams.get("amount");
|
|
669
|
+
if (!amountParam) return errorResponse("amount is required", 400);
|
|
670
|
+
const amount = parseInt(amountParam, 10);
|
|
671
|
+
if (isNaN(amount) || amount < 100) return errorResponse("Minimum donation amount is 1 EUR (100 cents)", 400);
|
|
672
|
+
const stripe = stripeBuilder();
|
|
673
|
+
const customerId = await getCustomerFromStripeOrCreate(user.email, user.name);
|
|
674
|
+
await upsertCustomerInventoryAndSyncWithUser(payload, user.customer?.inventory, user.email, customerId);
|
|
675
|
+
const donationPageHref = config.routes.donationPageHref || config.routes.subscriptionPageHref;
|
|
676
|
+
const metadata = { type: "donation" };
|
|
677
|
+
return jsonResponse({ url: (await stripe.checkout.sessions.create({
|
|
678
|
+
customer: customerId,
|
|
679
|
+
payment_method_types: ["card"],
|
|
680
|
+
line_items: [{
|
|
681
|
+
price_data: {
|
|
682
|
+
currency: "eur",
|
|
683
|
+
product_data: {
|
|
684
|
+
name: "Donation",
|
|
685
|
+
description: "One-time donation"
|
|
686
|
+
},
|
|
687
|
+
unit_amount: amount
|
|
688
|
+
},
|
|
689
|
+
quantity: 1
|
|
690
|
+
}],
|
|
691
|
+
mode: "payment",
|
|
692
|
+
success_url: `${process.env.DOMAIN}${donationPageHref}?success=donation`,
|
|
693
|
+
cancel_url: `${process.env.DOMAIN}${donationPageHref}?error=donation_cancelled`,
|
|
694
|
+
metadata,
|
|
695
|
+
payment_intent_data: { metadata },
|
|
696
|
+
invoice_creation: {
|
|
697
|
+
enabled: true,
|
|
698
|
+
invoice_data: { metadata }
|
|
699
|
+
}
|
|
700
|
+
})).url });
|
|
701
|
+
} catch (error) {
|
|
702
|
+
console.error("[Stripe Donation Error]", error);
|
|
703
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
|
|
704
|
+
}
|
|
705
|
+
};
|
|
610
706
|
}
|
|
611
707
|
|
|
612
708
|
//#endregion
|
|
613
|
-
//#region src/server/
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
709
|
+
//#region src/server/endpoints/handlers/portal-handler.ts
|
|
710
|
+
/**
|
|
711
|
+
* Creates a handler for Stripe Billing Portal access
|
|
712
|
+
*
|
|
713
|
+
* @param config - Endpoint configuration
|
|
714
|
+
* @returns PayloadHandler for portal endpoint
|
|
715
|
+
*/
|
|
716
|
+
function createPortalHandler(config) {
|
|
717
|
+
return async (request) => {
|
|
718
|
+
try {
|
|
719
|
+
const validated = await validateAuthenticatedRequest(request, config);
|
|
720
|
+
if (!validated.success) return validated.error;
|
|
721
|
+
const { user, payload } = validated;
|
|
722
|
+
const url = new URL(request.url || "");
|
|
723
|
+
const cancelSubscriptionId = url.searchParams.get("cancelSubscriptionId");
|
|
724
|
+
const updateSubscriptionId = url.searchParams.get("updateSubscriptionId");
|
|
725
|
+
let flowData;
|
|
726
|
+
if (cancelSubscriptionId) flowData = {
|
|
727
|
+
type: "subscription_cancel",
|
|
728
|
+
subscription_cancel: { subscription: cancelSubscriptionId }
|
|
729
|
+
};
|
|
730
|
+
else if (updateSubscriptionId) flowData = {
|
|
731
|
+
type: "subscription_update",
|
|
732
|
+
subscription_update: { subscription: updateSubscriptionId }
|
|
733
|
+
};
|
|
734
|
+
const stripe = stripeBuilder();
|
|
735
|
+
const customerId = await getCustomerFromStripeOrCreate(user.email, user.name);
|
|
736
|
+
await upsertCustomerInventoryAndSyncWithUser(payload, user.customer?.inventory, user.email, customerId);
|
|
737
|
+
return redirectResponse((await stripe.billingPortal.sessions.create({
|
|
738
|
+
flow_data: flowData,
|
|
739
|
+
customer: customerId,
|
|
740
|
+
return_url: `${process.env.DOMAIN}${config.routes.subscriptionPageHref}`
|
|
741
|
+
})).url, 303);
|
|
742
|
+
} catch (error) {
|
|
743
|
+
console.error("[Stripe Portal Error]", error);
|
|
744
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
|
|
745
|
+
}
|
|
625
746
|
};
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
//#endregion
|
|
750
|
+
//#region src/server/endpoints/handlers/update-handler.ts
|
|
751
|
+
/**
|
|
752
|
+
* Creates a handler for updating Stripe subscriptions (cancel at period end)
|
|
753
|
+
*
|
|
754
|
+
* @param config - Endpoint configuration
|
|
755
|
+
* @returns PayloadHandler for update endpoint
|
|
756
|
+
*/
|
|
757
|
+
function createUpdateHandler(config) {
|
|
758
|
+
return async (request) => {
|
|
759
|
+
try {
|
|
760
|
+
const validated = await validateAuthenticatedRequest(request, config);
|
|
761
|
+
if (!validated.success) return validated.error;
|
|
762
|
+
const { user, payload } = validated;
|
|
763
|
+
const url = new URL(request.url || "");
|
|
764
|
+
const subscriptionId = url.searchParams.get("subscriptionId");
|
|
765
|
+
const cancelAtPeriodEnd = url.searchParams.get("cancelAtPeriodEnd") === "true";
|
|
766
|
+
if (!subscriptionId) return errorResponse("subscriptionId is required", 400);
|
|
767
|
+
await stripeBuilder().subscriptions.update(subscriptionId, { cancel_at_period_end: cancelAtPeriodEnd });
|
|
768
|
+
const customer = user.customer;
|
|
769
|
+
const inventory = customer?.inventory;
|
|
770
|
+
if (inventory?.subscriptions?.[subscriptionId]) inventory.subscriptions[subscriptionId].cancel_at_period_end = cancelAtPeriodEnd;
|
|
771
|
+
if (customer?.email) await upsertCustomerInventoryAndSyncWithUser(payload, inventory, customer.email);
|
|
772
|
+
return redirectResponse(`${process.env.DOMAIN}${config.routes.subscriptionPageHref}?refresh=${Date.now()}`, 303);
|
|
773
|
+
} catch (error) {
|
|
774
|
+
console.error("[Stripe Update Error]", error);
|
|
775
|
+
return errorResponse(error instanceof Error ? error.message : "Unknown error occurred", 500);
|
|
776
|
+
}
|
|
629
777
|
};
|
|
630
|
-
const stripe = stripeBuilder();
|
|
631
|
-
const routes = getRoutes();
|
|
632
|
-
const customerId = await getCustomerFromStripeOrCreate(payloadUser.email, payloadUser.name);
|
|
633
|
-
await upsertCustomerInventoryAndSyncWithUser(payload, payloadUser.customer?.inventory, payloadUser.email, customerId);
|
|
634
|
-
const session = await stripe.billingPortal.sessions.create({
|
|
635
|
-
flow_data: flowData,
|
|
636
|
-
customer: customerId,
|
|
637
|
-
return_url: `${process.env.DOMAIN}${routes.nextJS.subscriptionPageHref}`
|
|
638
|
-
});
|
|
639
|
-
return NextResponse.redirect(session.url, 303);
|
|
640
778
|
}
|
|
641
779
|
|
|
642
780
|
//#endregion
|
|
643
|
-
//#region src/server/
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
shipping: "auto"
|
|
781
|
+
//#region src/server/endpoints/index.ts
|
|
782
|
+
/**
|
|
783
|
+
* Creates all Stripe inventory endpoints
|
|
784
|
+
*
|
|
785
|
+
* @param config - Endpoint configuration
|
|
786
|
+
* @param basePath - Base path for endpoints (default: '/stripe')
|
|
787
|
+
* @returns Array of Payload endpoints
|
|
788
|
+
*
|
|
789
|
+
* @example
|
|
790
|
+
* ```typescript
|
|
791
|
+
* const endpoints = createStripeEndpoints({
|
|
792
|
+
* routes: { subscriptionPageHref: '/account/subscription' },
|
|
793
|
+
* });
|
|
794
|
+
* // Endpoints:
|
|
795
|
+
* // GET /api/stripe/checkout?priceId={id}
|
|
796
|
+
* // GET /api/stripe/portal
|
|
797
|
+
* // GET /api/stripe/update?subscriptionId={id}&cancelAtPeriodEnd={bool}
|
|
798
|
+
* // GET /api/stripe/donation?amount={cents}
|
|
799
|
+
* ```
|
|
800
|
+
*/
|
|
801
|
+
function createStripeEndpoints(config, basePath = "/stripe") {
|
|
802
|
+
return [
|
|
803
|
+
{
|
|
804
|
+
path: `${basePath}/checkout`,
|
|
805
|
+
method: "get",
|
|
806
|
+
handler: createCheckoutHandler(config)
|
|
670
807
|
},
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
808
|
+
{
|
|
809
|
+
path: `${basePath}/portal`,
|
|
810
|
+
method: "get",
|
|
811
|
+
handler: createPortalHandler(config)
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
path: `${basePath}/update`,
|
|
815
|
+
method: "get",
|
|
816
|
+
handler: createUpdateHandler(config)
|
|
817
|
+
},
|
|
818
|
+
{
|
|
819
|
+
path: `${basePath}/donation`,
|
|
820
|
+
method: "get",
|
|
821
|
+
handler: createDonationHandler(config)
|
|
822
|
+
}
|
|
823
|
+
];
|
|
675
824
|
}
|
|
676
825
|
|
|
677
826
|
//#endregion
|
|
678
|
-
//#region src/server/
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
827
|
+
//#region src/server/plugin/create-stripe-inventory-plugin.ts
|
|
828
|
+
/**
|
|
829
|
+
* Creates the Stripe Inventory plugin for Payload CMS
|
|
830
|
+
*
|
|
831
|
+
* This plugin:
|
|
832
|
+
* - Registers REST endpoints for checkout, portal, update, and donation
|
|
833
|
+
* - Sets up Stripe webhook handlers for subscription and payment events
|
|
834
|
+
* - Syncs customer data between Stripe and Payload
|
|
835
|
+
*
|
|
836
|
+
* @param config - Plugin configuration
|
|
837
|
+
* @returns A Payload plugin function
|
|
838
|
+
*
|
|
839
|
+
* Endpoints registered:
|
|
840
|
+
* - GET /api{basePath}/checkout?priceId={id} - Redirect to Stripe Checkout
|
|
841
|
+
* - GET /api{basePath}/portal - Redirect to Stripe Billing Portal
|
|
842
|
+
* - GET /api{basePath}/update?subscriptionId={id}&cancelAtPeriodEnd={bool} - Update subscription
|
|
843
|
+
* - GET /api{basePath}/donation?amount={cents} - Returns JSON with checkout URL
|
|
844
|
+
*/
|
|
845
|
+
function createStripeInventoryPlugin(config) {
|
|
846
|
+
const basePath = config.basePath || "/stripe";
|
|
847
|
+
const endpointConfig = {
|
|
848
|
+
routes: config.routes,
|
|
849
|
+
checkPermissions: config.checkPermissions,
|
|
850
|
+
resolveUser: config.resolveUser
|
|
851
|
+
};
|
|
852
|
+
const onSubscriptionUpdate = config.onSubscriptionUpdate || (async () => {});
|
|
853
|
+
return (incomingConfig) => {
|
|
854
|
+
const stripeEndpoints = createStripeEndpoints(endpointConfig, basePath);
|
|
855
|
+
const configWithEndpoints = {
|
|
856
|
+
...incomingConfig,
|
|
857
|
+
endpoints: [...incomingConfig.endpoints || [], ...stripeEndpoints]
|
|
858
|
+
};
|
|
859
|
+
return stripePlugin({
|
|
860
|
+
isTestKey: process.env.STRIPE_SECRET_KEY?.includes("sk_test"),
|
|
861
|
+
stripeSecretKey: process.env.STRIPE_SECRET_KEY || "",
|
|
862
|
+
stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOK_SECRET,
|
|
863
|
+
webhooks: {
|
|
864
|
+
"price.deleted": async ({ event, payload }) => await priceDeleted(event.data.object, payload),
|
|
865
|
+
"customer.subscription.created": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
|
|
866
|
+
"customer.subscription.paused": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
|
|
867
|
+
"customer.subscription.updated": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
|
|
868
|
+
"customer.subscription.deleted": async ({ event, payload }) => await subscriptionDeleted(event.data.object, payload, onSubscriptionUpdate),
|
|
869
|
+
"customer.deleted": async ({ event, payload }) => await customerDeleted(event.data.object, payload),
|
|
870
|
+
"product.deleted": async ({ event, payload }) => await productDeleted(event.data.object, payload),
|
|
871
|
+
"payment_intent.succeeded": async ({ event, payload }) => {
|
|
872
|
+
await paymentSucceeded(event.data.object, payload);
|
|
873
|
+
},
|
|
874
|
+
"invoice.paid": async ({ event, payload }) => {
|
|
875
|
+
await invoiceSucceeded(event.data.object, payload);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
})(configWithEndpoints);
|
|
685
879
|
};
|
|
686
|
-
}
|
|
687
|
-
function createRouteHandlers(getPayload, getRoutes) {
|
|
688
|
-
return { GET: async (request, { params }) => {
|
|
689
|
-
const path = (await params).stripe[0];
|
|
690
|
-
const handlers = createStripeInventoryHandlers(getPayload, getRoutes);
|
|
691
|
-
if (path === "checkout" || path === "portal" || path === "update" || path === "donation") return handlers[path].GET(request);
|
|
692
|
-
return NextResponse.json({ error: "Route not found" }, { status: 404 });
|
|
693
|
-
} };
|
|
694
880
|
}
|
|
695
881
|
|
|
696
882
|
//#endregion
|
|
@@ -723,6 +909,19 @@ const loggedInOrPublished = ({ req: { user } }) => {
|
|
|
723
909
|
return { _status: { equals: "published" } };
|
|
724
910
|
};
|
|
725
911
|
|
|
912
|
+
//#endregion
|
|
913
|
+
//#region src/server/access/get-user-from-request.ts
|
|
914
|
+
/**
|
|
915
|
+
* Gets the current user from a PayloadRequest without depending on next/headers.
|
|
916
|
+
* This is the recommended way to get the user in Payload endpoint handlers.
|
|
917
|
+
*
|
|
918
|
+
* @param request - The PayloadRequest object
|
|
919
|
+
* @returns The user object or null if not authenticated
|
|
920
|
+
*/
|
|
921
|
+
function getUserFromRequest(request) {
|
|
922
|
+
return request.user;
|
|
923
|
+
}
|
|
924
|
+
|
|
726
925
|
//#endregion
|
|
727
926
|
//#region src/server/collections/customers.ts
|
|
728
927
|
const customers = {
|
|
@@ -1002,30 +1201,5 @@ const products = {
|
|
|
1002
1201
|
};
|
|
1003
1202
|
|
|
1004
1203
|
//#endregion
|
|
1005
|
-
|
|
1006
|
-
const plugin = (onSubscriptionUpdate) => {
|
|
1007
|
-
return stripePlugin({
|
|
1008
|
-
isTestKey: process.env.STRIPE_SECRET_KEY?.includes("sk_test"),
|
|
1009
|
-
stripeSecretKey: process.env.STRIPE_SECRET_KEY || "",
|
|
1010
|
-
stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOK_SECRET,
|
|
1011
|
-
webhooks: {
|
|
1012
|
-
"price.deleted": async ({ event, payload }) => await priceDeleted(event.data.object, payload),
|
|
1013
|
-
"customer.subscription.created": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
|
|
1014
|
-
"customer.subscription.paused": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
|
|
1015
|
-
"customer.subscription.updated": async ({ event, payload }) => await subscriptionUpsert(event.data.object, payload, onSubscriptionUpdate),
|
|
1016
|
-
"customer.subscription.deleted": async ({ event, payload }) => await subscriptionDeleted(event.data.object, payload, onSubscriptionUpdate),
|
|
1017
|
-
"customer.deleted": async ({ event, payload }) => await customerDeleted(event.data.object, payload),
|
|
1018
|
-
"product.deleted": async ({ event, payload }) => await productDeleted(event.data.object, payload),
|
|
1019
|
-
"payment_intent.succeeded": async ({ event, payload }) => {
|
|
1020
|
-
await paymentSucceeded(event.data.object, payload);
|
|
1021
|
-
},
|
|
1022
|
-
"invoice.paid": async ({ event, payload }) => {
|
|
1023
|
-
await invoiceSucceeded(event.data.object, payload);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
});
|
|
1027
|
-
};
|
|
1028
|
-
|
|
1029
|
-
//#endregion
|
|
1030
|
-
export { createCustomerAtStripe, createRouteHandlers, createStripeInventoryHandlers, customerDeleted, customers, getCustomer, getCustomerFromStripeOrCreate, invoiceSucceeded, isAdmin, isAdminOrCurrentUser, isAdminOrPublished, isAdminOrStripeActive, isAdminOrUserFieldMatchingCurrentUser, isAnyone, loggedInOrPublished, payloadUpsert, paymentSucceeded, permissionEvaluationField, plugin, priceDeleted, priceUpsert, prices, productDeleted, productSync, products, resolveStripeCustomer, stripeBuilder, subscriptionDeleted, subscriptionUpsert, syncCustomerByEmail, unlockItemForUser, updatePrices, updateProducts, updateProductsAndPrices, upsertCustomerInventoryAndSyncWithUser };
|
|
1204
|
+
export { createCheckoutHandler, createCustomerAtStripe, createDonationHandler, createPortalHandler, createStripeEndpoints, createStripeInventoryPlugin, createUpdateHandler, customerDeleted, customers, errorResponse, getCustomer, getUserFromRequest, invoiceSucceeded, isAdmin, isAdminOrCurrentUser, isAdminOrPublished, isAdminOrStripeActive, isAdminOrUserFieldMatchingCurrentUser, isAnyone, jsonResponse, loggedInOrPublished, payloadUpsert, paymentSucceeded, permissionEvaluationField, priceDeleted, priceUpsert, prices, productDeleted, productSync, products, redirectResponse, resolveStripeCustomer, stripeBuilder, subscriptionDeleted, subscriptionUpsert, syncCustomerByEmail, unlockItemForUser, updatePrices, updateProducts, updateProductsAndPrices, upsertCustomerInventoryAndSyncWithUser, validateAuthenticatedRequest };
|
|
1031
1205
|
//# sourceMappingURL=index.mjs.map
|