@dodopayments/convex 0.1.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/README.md ADDED
@@ -0,0 +1,443 @@
1
+ # `@dodopayments/convex`
2
+
3
+ A TypeScript library that provides a Convex component for seamless integration of Dodo Payments into your Convex applications.
4
+
5
+ > **AI Agent Integration Guide:** See the AI Agent Prompt section below for detailed instructions and guidance for AI assistants.
6
+
7
+ ## Documentation
8
+
9
+ Detailed documentation can be found at [Dodo Payments Convex Component](https://docs.dodopayments.com/developer-resources/convex-component)
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @dodopayments/convex
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ### 1. Add Component to Convex Config
20
+
21
+ ```typescript
22
+ // convex/convex.config.ts
23
+ import { defineApp } from "convex/server";
24
+ import dodopayments from "@dodopayments/convex/convex.config";
25
+
26
+ const app = defineApp();
27
+ app.use(dodopayments);
28
+ export default app;
29
+ ```
30
+
31
+ ### 2. Set Up Environment Variables
32
+
33
+ Add your environment variables in the Convex dashboard (**Settings** → **Environment Variables**). You can open the dashboard by running:
34
+
35
+ ```sh
36
+ npx convex dashboard
37
+ ```
38
+
39
+ Set the following variables:
40
+
41
+ - `DODO_PAYMENTS_API_KEY=your-api-key`
42
+ - `DODO_PAYMENTS_ENVIRONMENT=test_mode`
43
+ - `DODO_PAYMENTS_WEBHOOK_SECRET=your-webhook-secret` (if using webhooks)
44
+
45
+ > **Note:** Convex backend functions only read environment variables set in the Convex dashboard. `.env` files are ignored. Always set secrets in the Convex dashboard for both production and development.
46
+
47
+ ### 3. Create Payment Functions
48
+
49
+ ```typescript
50
+ // convex/dodo.ts
51
+ import { DodoPayments } from "@dodopayments/convex";
52
+ import { components } from "./_generated/api";
53
+
54
+ export const dodo = new DodoPayments(components.dodopayments, {
55
+ // This function maps your Convex user to a Dodo Payments customer
56
+ // Customize it based on your authentication provider and/or user database
57
+ identify: async (ctx) => {
58
+ const identity = await ctx.auth.getUserIdentity();
59
+ if (!identity) {
60
+ return null; // User is not logged in
61
+ }
62
+
63
+ // Lookup user from your database
64
+ const user = await ctx.db.query("users")
65
+ .withIndex("by_auth_id", (q) => q.eq("authId", identity.subject))
66
+ .first();
67
+ if (!user) {
68
+ return null; // User not found in database
69
+ }
70
+
71
+ return {
72
+ dodoCustomerId: user.dodoCustomerId, // Use stored dodoCustomerId
73
+ customerData: {
74
+ name: user.name,
75
+ email: user.email,
76
+ },
77
+ };
78
+ },
79
+ apiKey: process.env.DODO_PAYMENTS_API_KEY!,
80
+ environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode",
81
+ });
82
+
83
+ // Export the API methods for use in your app
84
+ export const { checkout, customerPortal } = dodo.api();
85
+ ```
86
+
87
+ ### 4. Set Up Webhooks (Optional)
88
+
89
+ For handling Dodo Payments webhooks, create a file `convex/http.ts`:
90
+
91
+ ```typescript
92
+ // convex/http.ts
93
+ import { httpRouter } from "convex/server";
94
+ import { createDodoWebhookHandler } from "@dodopayments/convex";
95
+
96
+ const http = httpRouter();
97
+
98
+ http.route({
99
+ path: "/dodopayments-webhook",
100
+ method: "POST",
101
+ handler: createDodoWebhookHandler({
102
+ onPaymentSucceeded: async (payload) => {
103
+ console.log("Payment succeeded:", payload.data.payment_id);
104
+ // Add your logic here to handle the successful payment
105
+ },
106
+ onSubscriptionActive: async (payload) => {
107
+ console.log("Subscription activated:", payload.data.subscription_id);
108
+ // Add your logic here
109
+ },
110
+ // Add other event handlers as needed
111
+ }),
112
+ });
113
+
114
+ export default http;
115
+ ```
116
+
117
+ Add your webhook secret in the Convex dashboard (**Settings** → **Environment Variables**):
118
+
119
+ - `DODO_PAYMENTS_WEBHOOK_SECRET=your-webhook-secret`
120
+
121
+ ### 5. Define Payment Actions
122
+
123
+ ```typescript
124
+ // convex/payments.ts
125
+ import { action } from "./_generated/server";
126
+ import { v } from "convex/values";
127
+ import { checkout } from "./dodo";
128
+
129
+ export const createCheckout = action({
130
+ args: {
131
+ product_cart: v.array(v.object({
132
+ product_id: v.string(),
133
+ quantity: v.number(),
134
+ })),
135
+ returnUrl: v.optional(v.string()),
136
+ },
137
+ handler: async (ctx, args) => {
138
+ return await checkout(ctx, {
139
+ payload: {
140
+ product_cart: args.product_cart,
141
+ return_url: args.returnUrl,
142
+ billing_currency: "USD",
143
+ feature_flags: {
144
+ allow_discount_code: true,
145
+ },
146
+ },
147
+ });
148
+ },
149
+ });
150
+ ```
151
+
152
+ ### 6. Frontend Usage
153
+
154
+ ```tsx
155
+ import { useAction } from "convex/react";
156
+ import { api } from "../convex/_generated/api";
157
+
158
+ export function CheckoutButton() {
159
+ const createCheckout = useAction(api.payments.createCheckout);
160
+
161
+ const handleCheckout = async () => {
162
+ const { checkout_url } = await createCheckout({
163
+ product_cart: [{ product_id: "prod_123", quantity: 1 }],
164
+ });
165
+ window.location.href = checkout_url;
166
+ };
167
+
168
+ return <button onClick={handleCheckout}>Buy Now</button>;
169
+ }
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Prompt for LLM
175
+
176
+ ```text
177
+ You are an expert Convex developer assistant. Your task is to guide a user through integrating the @dodopayments/convex component into their existing Convex application.
178
+
179
+ The @dodopayments/convex adapter provides a Convex component for Dodo Payments' Checkout, Customer Portal, and Webhook functionalities, built using the official Convex component architecture pattern.
180
+
181
+ First, install the necessary package:
182
+
183
+ npm install @dodopayments/convex
184
+
185
+ Here's how you should structure your response:
186
+
187
+ 1. Ask the user which functionalities they want to integrate.
188
+
189
+ "Which parts of the @dodopayments/convex component would you like to integrate into your project? You can choose one or more of the following:
190
+
191
+ - Checkout Function (for handling product checkouts)
192
+ - Customer Portal Function (for managing customer subscriptions/details)
193
+ - Webhook Handler (for receiving Dodo Payments webhook events)
194
+ - All (integrate all three)"
195
+
196
+ 2. Based on the user's selection, provide detailed integration steps for each chosen functionality.
197
+
198
+ If Checkout Function is selected:
199
+
200
+ Purpose: This function handles different types of checkout flows and returns checkout URLs for programmatic handling.
201
+
202
+ Integration Steps:
203
+
204
+ Step 1: Add the component to your Convex configuration.
205
+
206
+ // convex/convex.config.ts
207
+ import { defineApp } from "convex/server";
208
+ import dodopayments from "@dodopayments/convex/convex.config";
209
+
210
+ const app = defineApp();
211
+ app.use(dodopayments);
212
+ export default app;
213
+
214
+ Step 2: Guide the user to set up environment variables in the Convex dashboard. Instruct them to open the dashboard by running:
215
+
216
+ npx convex dashboard
217
+
218
+ Then add the required environment variables (e.g., DODO_PAYMENTS_API_KEY, DODO_PAYMENTS_ENVIRONMENT, DODO_PAYMENTS_WEBHOOK_SECRET) in **Settings → Environment Variables**. Do not use .env files for backend functions.
219
+
220
+ DODO_PAYMENTS_API_KEY=your-api-key
221
+ DODO_PAYMENTS_ENVIRONMENT=test_mode
222
+
223
+ Step 3: Create your payment functions file.
224
+
225
+ // convex/dodo.ts
226
+ import { DodoPayments } from "@dodopayments/convex";
227
+ import { components } from "./_generated/api";
228
+
229
+ export const dodo = new DodoPayments(components.dodopayments, {
230
+ // This function maps your Convex user to a Dodo Payments customer
231
+ // Customize it based on your authentication provider
232
+ identify: async (ctx) => {
233
+ const identity = await ctx.auth.getUserIdentity();
234
+ if (!identity) {
235
+ return null; // User is not logged in
236
+ }
237
+
238
+ // Option 1: Use identity data directly
239
+ return {
240
+ dodoCustomerId: identity.subject, // Use a stable identifier for the customer ID
241
+ customerData: { // Optional: additional customer information
242
+ name: identity.name,
243
+ email: identity.email,
244
+ },
245
+ };
246
+
247
+ // Lookup user from your database
248
+ const user = await ctx.db.query("users")
249
+ .withIndex("by_auth_id", (q) => q.eq("authId", identity.subject))
250
+ .first();
251
+ if (!user) {
252
+ return null; // User not found in database
253
+ }
254
+
255
+ return {
256
+ dodoCustomerId: user.dodoCustomerId, // Use stored dodoCustomerId
257
+ customerData: {
258
+ name: user.name,
259
+ email: user.email,
260
+ },
261
+ };
262
+ },
263
+ apiKey: process.env.DODO_PAYMENTS_API_KEY!,
264
+ environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode",
265
+ });
266
+
267
+ // Export the API methods for use in your app
268
+ export const { checkout, customerPortal } = dodo.api();
269
+
270
+ Step 4: Create actions that use the checkout function.
271
+
272
+ // convex/payments.ts
273
+ import { action } from "./_generated/server";
274
+ import { v } from "convex/values";
275
+ import { checkout } from "./dodo";
276
+
277
+ // Checkout session with full feature support
278
+ export const createCheckout = action({
279
+ args: {
280
+ product_cart: v.array(v.object({
281
+ product_id: v.string(),
282
+ quantity: v.number(),
283
+ })),
284
+ returnUrl: v.optional(v.string()),
285
+ },
286
+ handler: async (ctx, args) => {
287
+ return await checkout(ctx, {
288
+ payload: {
289
+ product_cart: args.product_cart,
290
+ return_url: args.returnUrl,
291
+ billing_currency: "USD",
292
+ feature_flags: {
293
+ allow_discount_code: true,
294
+ },
295
+ },
296
+ });
297
+ },
298
+ });
299
+
300
+ Step 5: Use in your frontend.
301
+
302
+ // Your frontend component
303
+ import { useAction } from "convex/react";
304
+ import { api } from "../convex/_generated/api";
305
+
306
+ export function CheckoutButton() {
307
+ const createCheckout = useAction(api.payments.createCheckout);
308
+
309
+ const handleCheckout = async () => {
310
+ const { checkout_url } = await createCheckout({
311
+ product_cart: [{ product_id: "prod_123", quantity: 1 }],
312
+ });
313
+ window.location.href = checkout_url;
314
+ };
315
+
316
+ return <button onClick={handleCheckout}>Buy Now</button>;
317
+ }
318
+
319
+ Configuration Details:
320
+
321
+ - `checkout()`: Checkout session with full feature support using session checkout.
322
+ - Returns: `{"checkout_url": "https://checkout.dodopayments.com/..."}`
323
+
324
+ For complete API documentation, refer to:
325
+ - Checkout Sessions: https://docs.dodopayments.com/developer-resources/checkout-session
326
+ - One-time Payments: https://docs.dodopayments.com/api-reference/payments/post-payments
327
+ - Subscriptions: https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions
328
+
329
+ If Customer Portal Function is selected:
330
+
331
+ Purpose: This function allows customers to manage their subscriptions and payment methods.
332
+
333
+ Integration Steps:
334
+
335
+ Follow Steps 1-3 from the Checkout Function section, then:
336
+
337
+ Step 4: Create a customer portal action.
338
+
339
+ // convex/payments.ts (add to existing file)
340
+ import { action } from "./_generated/server";
341
+ import { v } from "convex/values";
342
+ import { customerPortal } from "./dodo";
343
+
344
+ export const getCustomerPortal = action({
345
+ args: {
346
+ send_email: v.optional(v.boolean()),
347
+ },
348
+ handler: async (ctx, args) => {
349
+ return await customerPortal(ctx, args);
350
+ },
351
+ });
352
+
353
+ Step 5: Use in your frontend.
354
+
355
+ // Your frontend component
356
+ import { useAction } from "convex/react";
357
+ import { api } from "../convex/_generated/api";
358
+
359
+ export function CustomerPortalButton() {
360
+ const getPortal = useAction(api.payments.getCustomerPortal);
361
+
362
+ const handlePortal = async () => {
363
+ const { portal_url } = await getPortal({ send_email: false });
364
+ window.location.href = portal_url;
365
+ };
366
+
367
+ return <button onClick={handlePortal}>Manage Subscription</button>;
368
+ }
369
+
370
+ Configuration Details:
371
+ - Requires authenticated user (via `identify` function).
372
+ - `send_email`: Optional boolean to send portal link via email.
373
+
374
+ If Webhook Handler is selected:
375
+
376
+ Purpose: This handler processes incoming webhook events from Dodo Payments, allowing your application to react to events like successful payments or subscription changes.
377
+
378
+ Integration Steps:
379
+
380
+ Step 1: Add the webhook secret to your environment variables in the Convex dashboard. You can open the dashboard by running:
381
+
382
+ Guide the user to open the Convex dashboard by running:
383
+
384
+ npx convex dashboard
385
+
386
+ In the dashboard, go to **Settings → Environment Variables** and add:
387
+
388
+ - `DODO_PAYMENTS_WEBHOOK_SECRET=whsec_...`
389
+
390
+ Do not use .env files for backend functions; always set secrets in the Convex dashboard.
391
+
392
+ Step 2: Create a file `convex/http.ts`:
393
+
394
+ // convex/http.ts
395
+ import { httpRouter } from "convex/server";
396
+ import { createDodoWebhookHandler } from "@dodopayments/convex";
397
+
398
+ const http = httpRouter();
399
+
400
+ http.route({
401
+ path: "/dodopayments-webhook",
402
+ method: "POST",
403
+ handler: createDodoWebhookHandler({
404
+ onPaymentSucceeded: async (payload) => {
405
+ console.log("Payment succeeded:", payload.data.payment_id);
406
+ // Add your logic here to handle the successful payment
407
+ },
408
+ onSubscriptionActive: async (payload) => {
409
+ console.log("Subscription activated:", payload.data.subscription_id);
410
+ // Add your logic here
411
+ },
412
+ // Add other event handlers as needed
413
+ }),
414
+ });
415
+
416
+ export default http;
417
+
418
+ Now, you can set the webhook endpoint URL in your Dodo Payments dashboard to `https://<your-convex-deployment-url>/dodopayments-webhook`.
419
+
420
+ Environment Variable Setup:
421
+
422
+ Set up the following environment variables in your Convex dashboard (Settings → Environment Variables). You can open the dashboard by running:
423
+
424
+ npx convex dashboard
425
+
426
+ Set:
427
+
428
+ - `DODO_PAYMENTS_API_KEY=your-api-key`
429
+ - `DODO_PAYMENTS_ENVIRONMENT=test_mode`
430
+ - `DODO_PAYMENTS_WEBHOOK_SECRET=your-webhook-secret`
431
+
432
+ Usage in your component configuration:
433
+
434
+ apiKey: process.env.DODO_PAYMENTS_API_KEY!
435
+ environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode"
436
+
437
+ Important: Never commit sensitive environment variables directly into your code. Always use Convex environment variables for all sensitive information.
438
+
439
+ If the user needs assistance setting up environment variables or deployment, ask them about their specific setup and provide guidance accordingly.
440
+
441
+ Run `npx convex dev` after setting up the component to generate the necessary types.
442
+ ```
443
+
@@ -0,0 +1,42 @@
1
+ import type { CheckoutSessionPayload } from "@dodopayments/core/checkout";
2
+ import { GenericActionCtx } from "convex/server";
3
+ type CustomerPortalArgs = {
4
+ send_email?: boolean;
5
+ };
6
+ export interface DodoPaymentsComponent {
7
+ lib: {
8
+ checkout: any;
9
+ customerPortal: any;
10
+ };
11
+ }
12
+ export type DodoPaymentsClientConfig = {
13
+ identify: (ctx: GenericActionCtx<any>) => Promise<{
14
+ dodoCustomerId: string;
15
+ customerData?: any;
16
+ } | null>;
17
+ apiKey: string;
18
+ environment: "test_mode" | "live_mode";
19
+ };
20
+ export declare class DodoPayments {
21
+ component: DodoPaymentsComponent;
22
+ private config;
23
+ constructor(component: DodoPaymentsComponent, config: DodoPaymentsClientConfig);
24
+ /**
25
+ * Returns the public API methods for the Dodo Payments client.
26
+ */
27
+ api(): {
28
+ /**
29
+ * Creates a Dodo Payments checkout session.
30
+ * Uses session checkout with full feature support.
31
+ */
32
+ checkout: (ctx: any, args: {
33
+ payload: CheckoutSessionPayload;
34
+ }) => Promise<any>;
35
+ /**
36
+ * Retrieves a URL for the customer portal.
37
+ * This function is designed to be called from a public Convex query in your app.
38
+ */
39
+ customerPortal: (ctx: any, args?: CustomerPortalArgs) => Promise<any>;
40
+ };
41
+ }
42
+ export {};
@@ -0,0 +1,28 @@
1
+ import { actionGeneric } from 'convex/server';
2
+
3
+ /* eslint-disable */
4
+ /**
5
+ * Generated utilities for implementing server-side Convex query and mutation functions.
6
+ *
7
+ * THIS CODE IS AUTOMATICALLY GENERATED.
8
+ *
9
+ * To regenerate, run `npx convex dev`.
10
+ * @module
11
+ */
12
+
13
+
14
+ /**
15
+ * Define an action in this Convex app's public API.
16
+ *
17
+ * An action is a function which can execute any JavaScript code, including non-deterministic
18
+ * code and code with side-effects, like calling third-party services.
19
+ * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
20
+ * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
21
+ *
22
+ * @param func - The action. It receives an {@link ActionCtx} as its first argument.
23
+ * @returns The wrapped action. Include this as an `export` to name it and make it accessible.
24
+ */
25
+ const action = actionGeneric;
26
+
27
+ export { action };
28
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sources":["../../../src/component/_generated/server.js"],"sourcesContent":["/* eslint-disable */\n/**\n * Generated utilities for implementing server-side Convex query and mutation functions.\n *\n * THIS CODE IS AUTOMATICALLY GENERATED.\n *\n * To regenerate, run `npx convex dev`.\n * @module\n */\n\nimport {\n actionGeneric,\n httpActionGeneric,\n queryGeneric,\n mutationGeneric,\n internalActionGeneric,\n internalMutationGeneric,\n internalQueryGeneric,\n} from \"convex/server\";\n\n/**\n * Define a query in this Convex app's public API.\n *\n * This function will be allowed to read your Convex database and will be accessible from the client.\n *\n * @param func - The query function. It receives a {@link QueryCtx} as its first argument.\n * @returns The wrapped query. Include this as an `export` to name it and make it accessible.\n */\nexport const query = queryGeneric;\n\n/**\n * Define a query that is only accessible from other Convex functions (but not from the client).\n *\n * This function will be allowed to read from your Convex database. It will not be accessible from the client.\n *\n * @param func - The query function. It receives a {@link QueryCtx} as its first argument.\n * @returns The wrapped query. Include this as an `export` to name it and make it accessible.\n */\nexport const internalQuery = internalQueryGeneric;\n\n/**\n * Define a mutation in this Convex app's public API.\n *\n * This function will be allowed to modify your Convex database and will be accessible from the client.\n *\n * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.\n * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.\n */\nexport const mutation = mutationGeneric;\n\n/**\n * Define a mutation that is only accessible from other Convex functions (but not from the client).\n *\n * This function will be allowed to modify your Convex database. It will not be accessible from the client.\n *\n * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.\n * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.\n */\nexport const internalMutation = internalMutationGeneric;\n\n/**\n * Define an action in this Convex app's public API.\n *\n * An action is a function which can execute any JavaScript code, including non-deterministic\n * code and code with side-effects, like calling third-party services.\n * They can be run in Convex's JavaScript environment or in Node.js using the \"use node\" directive.\n * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.\n *\n * @param func - The action. It receives an {@link ActionCtx} as its first argument.\n * @returns The wrapped action. Include this as an `export` to name it and make it accessible.\n */\nexport const action = actionGeneric;\n\n/**\n * Define an action that is only accessible from other Convex functions (but not from the client).\n *\n * @param func - The function. It receives an {@link ActionCtx} as its first argument.\n * @returns The wrapped function. Include this as an `export` to name it and make it accessible.\n */\nexport const internalAction = internalActionGeneric;\n\n/**\n * Define a Convex HTTP action.\n *\n * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object\n * as its second.\n * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.\n */\nexport const httpAction = httpActionGeneric;\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAoDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,MAAM,GAAG;;;;"}
@@ -0,0 +1,2 @@
1
+ declare const _default: import("convex/server").ComponentDefinition<any>;
2
+ export default _default;
@@ -0,0 +1,6 @@
1
+ import { defineComponent } from 'convex/server';
2
+
3
+ var convex_config = defineComponent("dodopayments");
4
+
5
+ export { convex_config as default };
6
+ //# sourceMappingURL=convex.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convex.config.js","sources":["../../src/component/convex.config.ts"],"sourcesContent":["import { defineComponent } from \"convex/server\";\n\nexport default defineComponent(\"dodopayments\");\n"],"names":[],"mappings":";;AAEA,oBAAe,eAAe,CAAC,cAAc,CAAC;;;;"}
@@ -0,0 +1,54 @@
1
+ export declare const checkout: import("convex/server").RegisteredAction<"public", {
2
+ payload: {
3
+ customer?: {
4
+ email?: string | undefined;
5
+ name?: string | undefined;
6
+ phone_number?: string | undefined;
7
+ } | undefined;
8
+ billing_address?: {
9
+ street?: string | undefined;
10
+ city?: string | undefined;
11
+ state?: string | undefined;
12
+ zipcode?: string | undefined;
13
+ country: string;
14
+ } | undefined;
15
+ return_url?: string | undefined;
16
+ allowed_payment_method_types?: string[] | undefined;
17
+ billing_currency?: string | undefined;
18
+ show_saved_payment_methods?: boolean | undefined;
19
+ confirm?: boolean | undefined;
20
+ discount_code?: string | undefined;
21
+ metadata?: Record<string, string> | undefined;
22
+ customization?: {
23
+ theme?: string | undefined;
24
+ show_order_details?: boolean | undefined;
25
+ show_on_demand_tag?: boolean | undefined;
26
+ } | undefined;
27
+ feature_flags?: {
28
+ allow_currency_selection?: boolean | undefined;
29
+ allow_discount_code?: boolean | undefined;
30
+ allow_phone_number_collection?: boolean | undefined;
31
+ allow_tax_id?: boolean | undefined;
32
+ always_create_new_customer?: boolean | undefined;
33
+ } | undefined;
34
+ subscription_data?: {
35
+ trial_period_days?: number | undefined;
36
+ } | undefined;
37
+ product_cart: {
38
+ product_id: string;
39
+ quantity: number;
40
+ }[];
41
+ };
42
+ apiKey: string;
43
+ environment: "test_mode" | "live_mode";
44
+ }, Promise<{
45
+ checkout_url: string;
46
+ }>>;
47
+ export declare const customerPortal: import("convex/server").RegisteredAction<"public", {
48
+ send_email?: boolean | undefined;
49
+ apiKey: string;
50
+ environment: "test_mode" | "live_mode";
51
+ dodoCustomerId: string;
52
+ }, Promise<{
53
+ portal_url: string;
54
+ }>>;
@@ -0,0 +1,88 @@
1
+ import { action } from './_generated/server.js';
2
+ import { v } from 'convex/values';
3
+ import { buildCheckoutUrl } from '../core/dist/checkout/checkout.js';
4
+ import DodoPayments from 'dodopayments';
5
+
6
+ const checkoutSessionPayloadValidator = v.object({
7
+ product_cart: v.array(v.object({
8
+ product_id: v.string(),
9
+ quantity: v.number(),
10
+ })),
11
+ customer: v.optional(v.object({
12
+ email: v.optional(v.string()),
13
+ name: v.optional(v.string()),
14
+ phone_number: v.optional(v.string()),
15
+ })),
16
+ billing_address: v.optional(v.object({
17
+ street: v.optional(v.string()),
18
+ city: v.optional(v.string()),
19
+ state: v.optional(v.string()),
20
+ country: v.string(),
21
+ zipcode: v.optional(v.string()),
22
+ })),
23
+ return_url: v.optional(v.string()),
24
+ allowed_payment_method_types: v.optional(v.array(v.string())),
25
+ billing_currency: v.optional(v.string()),
26
+ show_saved_payment_methods: v.optional(v.boolean()),
27
+ confirm: v.optional(v.boolean()),
28
+ discount_code: v.optional(v.string()),
29
+ metadata: v.optional(v.record(v.string(), v.string())),
30
+ customization: v.optional(v.object({
31
+ theme: v.optional(v.string()),
32
+ show_order_details: v.optional(v.boolean()),
33
+ show_on_demand_tag: v.optional(v.boolean()),
34
+ })),
35
+ feature_flags: v.optional(v.object({
36
+ allow_currency_selection: v.optional(v.boolean()),
37
+ allow_discount_code: v.optional(v.boolean()),
38
+ allow_phone_number_collection: v.optional(v.boolean()),
39
+ allow_tax_id: v.optional(v.boolean()),
40
+ always_create_new_customer: v.optional(v.boolean()),
41
+ })),
42
+ subscription_data: v.optional(v.object({
43
+ trial_period_days: v.optional(v.number()),
44
+ })),
45
+ });
46
+ const checkout = action({
47
+ args: {
48
+ payload: checkoutSessionPayloadValidator,
49
+ apiKey: v.string(),
50
+ environment: v.union(v.literal("test_mode"), v.literal("live_mode")),
51
+ },
52
+ returns: v.object({ checkout_url: v.string() }),
53
+ handler: async (_, { payload, apiKey, environment }) => {
54
+ const checkoutUrl = await buildCheckoutUrl({
55
+ sessionPayload: payload,
56
+ bearerToken: apiKey,
57
+ environment,
58
+ type: "session",
59
+ });
60
+ return { checkout_url: checkoutUrl };
61
+ },
62
+ });
63
+ const customerPortal = action({
64
+ args: {
65
+ dodoCustomerId: v.string(),
66
+ send_email: v.optional(v.boolean()),
67
+ apiKey: v.string(),
68
+ environment: v.union(v.literal("test_mode"), v.literal("live_mode")),
69
+ },
70
+ returns: v.object({ portal_url: v.string() }),
71
+ handler: async (_, { dodoCustomerId, send_email, apiKey, environment }) => {
72
+ if (!dodoCustomerId) {
73
+ throw new Error("dodoCustomerId is required for customerPortal.");
74
+ }
75
+ const dodopayments = new DodoPayments({
76
+ bearerToken: apiKey,
77
+ environment,
78
+ });
79
+ const params = {
80
+ send_email: Boolean(send_email),
81
+ };
82
+ const session = await dodopayments.customers.customerPortal.create(dodoCustomerId, params);
83
+ return { portal_url: session.link };
84
+ },
85
+ });
86
+
87
+ export { checkout, customerPortal };
88
+ //# sourceMappingURL=lib.js.map