mirror of
https://github.com/wasp-lang/open-saas.git
synced 2025-03-26 17:52:28 +01:00
Merge branch 'main' into fix-docs-links
This commit is contained in:
commit
4dd508df97
BIN
opensaas-sh/blog/public/stripe/switch-plans.png
Normal file
BIN
opensaas-sh/blog/public/stripe/switch-plans.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 188 KiB |
@ -70,7 +70,8 @@ To create a test product, go to the test products url [https://dashboard.stripe.
|
||||
- Make sure you select `Software as a service (SaaS)` as the product type.
|
||||
- For Subscription products, make sure you select `Recurring` as the billing type.
|
||||
- For One-time payment products, make sure you select `One-time` as the billing type.
|
||||
- If you want to add different price tiers for the same product, click the `Add another price` button at the buttom.
|
||||
- If you intend to let your users switch between two subscription plans, e.g. upgrade from hobby to pro, you'll need to create two separate products and with their own price IDs. The ability for users to swich plans can then be configured later in the [Customer Portal](#set-up-the-customer-portal).
|
||||
- If you want to add different price tiers for the same product (e.g. monthly and yearly), click the `Add another price` button at the buttom.
|
||||
|
||||

|
||||
|
||||
@ -89,7 +90,7 @@ To create a test customer, go to the test customers url [https://dashboard.strip
|
||||
When filling in the test customer email address, use an address you have access to and will use when logging into your SaaS app. This is important because the email address is used to identify the customer when creating a subscription and allows you to manage your test user's payments/subscriptions via the test customer portal
|
||||
:::
|
||||
|
||||
### Get your Customer Portal Link
|
||||
### Set up the Customer Portal
|
||||
|
||||
Go to https://dashboard.stripe.com/test/settings/billing/portal in the Stripe Dashboard and activate and copy the `Customer portal link`. Paste it in your `.env.server` file:
|
||||
|
||||
@ -97,6 +98,14 @@ Go to https://dashboard.stripe.com/test/settings/billing/portal in the Stripe Da
|
||||
STRIPE_CUSTOMER_PORTAL_URL=<your-test-customer-portal-link>
|
||||
```
|
||||
|
||||
If you'd like to give users the ability to switch between different plans, e.g. upgrade from a hobby to a pro subscription, go down to the `Subscriptions` dropdown and select `customers can switch plans`.
|
||||
|
||||

|
||||
|
||||
Then select the products you'd like them to be able to switch between.
|
||||
|
||||
Now, after your users have paid, they can click on `Manage Subscription` in the client and will be taken to the customer portal where they can update their current plan.
|
||||
|
||||
### Install the Stripe CLI
|
||||
|
||||
To install the Stripe CLI with homebrew, run the following command in your terminal:
|
||||
|
@ -29,11 +29,9 @@ export const lemonSqueezyPaymentProcessor: PaymentProcessor = {
|
||||
lemonSqueezyCustomerPortalUrl: true,
|
||||
},
|
||||
});
|
||||
if (!user.lemonSqueezyCustomerPortalUrl) {
|
||||
console.log(`User with ID ${args.userId} does not have a LemonSqueezy customer portal URL`);
|
||||
} else {
|
||||
return user.lemonSqueezyCustomerPortalUrl;
|
||||
}
|
||||
// Note that Lemon Squeezy assigns a unique URL to each user after the first successful payment.
|
||||
// This is handled in the Lemon Squeezy webhook.
|
||||
return user.lemonSqueezyCustomerPortalUrl;
|
||||
},
|
||||
webhook: lemonSqueezyWebhook,
|
||||
webhookMiddlewareConfigFn: lemonSqueezyMiddlewareConfigFn,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type { GenerateCheckoutSession, GetCustomerPortalUrl } from 'wasp/server/operations';
|
||||
import type { FetchCustomerPortalUrlArgs } from './paymentProcessor';
|
||||
import { PaymentPlanId, paymentPlans } from '../payment/plans';
|
||||
import { paymentProcessor } from './paymentProcessor';
|
||||
import { HttpError } from 'wasp/server';
|
||||
@ -39,7 +38,7 @@ export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, Che
|
||||
};
|
||||
};
|
||||
|
||||
export const getCustomerPortalUrl: GetCustomerPortalUrl<void, string | undefined> = async (_args, context) => {
|
||||
export const getCustomerPortalUrl: GetCustomerPortalUrl<void, string | null> = async (_args, context) => {
|
||||
if (!context.user) {
|
||||
throw new HttpError(401);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export interface FetchCustomerPortalUrlArgs {
|
||||
export interface PaymentProcessor {
|
||||
id: 'stripe' | 'lemonsqueezy';
|
||||
createCheckoutSession: (args: CreateCheckoutSessionArgs) => Promise<{ session: { id: string; url: string }; }>;
|
||||
fetchCustomerPortalUrl: (args: FetchCustomerPortalUrlArgs) => Promise<string | undefined>;
|
||||
fetchCustomerPortalUrl: (args: FetchCustomerPortalUrlArgs) => Promise<string | null>;
|
||||
webhook: PaymentsWebhook;
|
||||
webhookMiddlewareConfigFn: MiddlewareConfigFn;
|
||||
}
|
||||
|
@ -124,6 +124,8 @@ function CustomerPortalButton() {
|
||||
|
||||
if (customerPortalUrl) {
|
||||
window.open(customerPortalUrl, '_blank');
|
||||
} else {
|
||||
console.error('Customer portal URL is not available');
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user