feat(subscriptions): added polar as payment provider for subscriptions
* feature(dashboard): add polar / subscription * wip(payments): manage subscription * wip(payments): add free product, faq and some other improvements * fix(root): change node to bundler in tsconfig * wip(payments): display current subscription * feat(dashboard): schedule project for deletion * wip(payments): support custom products/subscriptions * wip(payments): fix polar scripts * wip(payments): add json package to dockerfiles
This commit is contained in:
committed by
GitHub
parent
86bf9dd064
commit
168ebc3430
112
packages/payments/src/polar.ts
Normal file
112
packages/payments/src/polar.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
// src/polar.ts
|
||||
import { Polar } from '@polar-sh/sdk';
|
||||
export {
|
||||
validateEvent as validatePolarEvent,
|
||||
WebhookVerificationError as PolarWebhookVerificationError,
|
||||
} from '@polar-sh/sdk/webhooks';
|
||||
|
||||
export type IPolarProduct = Awaited<ReturnType<typeof getProduct>>;
|
||||
export type IPolarPrice = IPolarProduct['prices'][number];
|
||||
|
||||
export const polar = new Polar({
|
||||
accessToken: process.env.POLAR_ACCESS_TOKEN!,
|
||||
server: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
|
||||
});
|
||||
|
||||
export const getSuccessUrl = (
|
||||
baseUrl: string,
|
||||
organizationId: string,
|
||||
projectId?: string,
|
||||
) =>
|
||||
projectId
|
||||
? `${baseUrl}/${organizationId}/${projectId}/settings?tab=billing`
|
||||
: `${baseUrl}/${organizationId}`;
|
||||
|
||||
export async function getProducts() {
|
||||
const products = await polar.products.list({
|
||||
limit: 100,
|
||||
isArchived: false,
|
||||
sorting: ['price_amount'],
|
||||
});
|
||||
return products.result.items.filter((product) => {
|
||||
return product.metadata.custom !== true;
|
||||
});
|
||||
}
|
||||
|
||||
export async function getProduct(id: string) {
|
||||
return polar.products.get({ id });
|
||||
}
|
||||
|
||||
export async function createPortal({
|
||||
customerId,
|
||||
}: {
|
||||
customerId: string;
|
||||
}) {
|
||||
return polar.customerSessions.create({
|
||||
customerId,
|
||||
});
|
||||
}
|
||||
|
||||
export async function createCheckout({
|
||||
priceId,
|
||||
organizationId,
|
||||
projectId,
|
||||
user,
|
||||
ipAddress,
|
||||
}: {
|
||||
priceId: string;
|
||||
organizationId: string;
|
||||
projectId?: string;
|
||||
user: {
|
||||
id: string;
|
||||
firstName: string | null;
|
||||
lastName: string | null;
|
||||
email: string;
|
||||
};
|
||||
ipAddress: string;
|
||||
}) {
|
||||
return polar.checkouts.create({
|
||||
productPriceId: priceId,
|
||||
successUrl: getSuccessUrl(
|
||||
process.env.NEXT_PUBLIC_DASHBOARD_URL!,
|
||||
organizationId,
|
||||
projectId,
|
||||
),
|
||||
customerEmail: user.email,
|
||||
customerName: [user.firstName, user.lastName].filter(Boolean).join(' '),
|
||||
customerIpAddress: ipAddress,
|
||||
metadata: {
|
||||
organizationId,
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function cancelSubscription(subscriptionId: string) {
|
||||
return polar.subscriptions.update({
|
||||
id: subscriptionId,
|
||||
subscriptionUpdate: {
|
||||
cancelAtPeriodEnd: true,
|
||||
revoke: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reactivateSubscription(subscriptionId: string) {
|
||||
return polar.subscriptions.update({
|
||||
id: subscriptionId,
|
||||
subscriptionUpdate: {
|
||||
cancelAtPeriodEnd: false,
|
||||
revoke: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function changeSubscription(subscriptionId: string, productId: string) {
|
||||
return polar.subscriptions.update({
|
||||
id: subscriptionId,
|
||||
subscriptionUpdate: {
|
||||
productId,
|
||||
},
|
||||
});
|
||||
}
|
||||
18
packages/payments/src/prices.ts
Normal file
18
packages/payments/src/prices.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export type IPrice = {
|
||||
price: number;
|
||||
events: number;
|
||||
};
|
||||
|
||||
export const PRICING: IPrice[] = [
|
||||
{ price: 0, events: 5_000 },
|
||||
{ price: 5, events: 10_000 },
|
||||
{ price: 20, events: 100_000 },
|
||||
{ price: 30, events: 250_000 },
|
||||
{ price: 50, events: 500_000 },
|
||||
{ price: 90, events: 1_000_000 },
|
||||
{ price: 180, events: 2_500_000 },
|
||||
{ price: 250, events: 5_000_000 },
|
||||
{ price: 400, events: 10_000_000 },
|
||||
// { price: 650, events: 20_000_000 },
|
||||
// { price: 900, events: 30_000_000 },
|
||||
];
|
||||
Reference in New Issue
Block a user