@dodopayments/convex 0.2.0 → 0.2.2
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 +62 -37
- package/dist/component/lib.js +1 -1
- package/dist/component/lib.js.map +1 -1
- package/dist/index.cjs +4192 -232
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4192 -232
- package/dist/index.js.map +1 -1
- package/dist/node_modules/zod/v3/ZodError.js +133 -0
- package/dist/node_modules/zod/v3/ZodError.js.map +1 -0
- package/dist/node_modules/zod/v3/errors.js +9 -0
- package/dist/node_modules/zod/v3/errors.js.map +1 -0
- package/dist/node_modules/zod/v3/helpers/errorUtil.js +9 -0
- package/dist/node_modules/zod/v3/helpers/errorUtil.js.map +1 -0
- package/dist/node_modules/zod/v3/helpers/parseUtil.js +112 -0
- package/dist/node_modules/zod/v3/helpers/parseUtil.js.map +1 -0
- package/dist/node_modules/zod/v3/helpers/util.js +136 -0
- package/dist/node_modules/zod/v3/helpers/util.js.map +1 -0
- package/dist/node_modules/zod/v3/locales/en.js +112 -0
- package/dist/node_modules/zod/v3/locales/en.js.map +1 -0
- package/dist/node_modules/zod/v3/types.js +3356 -0
- package/dist/node_modules/zod/v3/types.js.map +1 -0
- package/dist/{core → packages/core}/dist/checkout/checkout.js +88 -99
- package/dist/packages/core/dist/checkout/checkout.js.map +1 -0
- package/package.json +3 -3
- package/dist/core/dist/checkout/checkout.js.map +0 -1
package/README.md
CHANGED
|
@@ -22,7 +22,6 @@ npm install @dodopayments/convex
|
|
|
22
22
|
|
|
23
23
|
## Quick Start
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
### 1. Add Component to Convex Config
|
|
27
26
|
|
|
28
27
|
```typescript
|
|
@@ -46,6 +45,7 @@ DODO_PAYMENTS_API_KEY=your-dodo-payments-api-key
|
|
|
46
45
|
DODO_PAYMENTS_ENVIRONMENT=test_mode
|
|
47
46
|
DODO_PAYMENTS_WEBHOOK_SECRET=your-webhook-secret (if using webhooks)
|
|
48
47
|
```
|
|
48
|
+
|
|
49
49
|
```sh
|
|
50
50
|
npx convex dashboard
|
|
51
51
|
```
|
|
@@ -96,22 +96,24 @@ export const dodo = new DodoPayments(components.dodopayments, {
|
|
|
96
96
|
if (!identity) {
|
|
97
97
|
return null; // User is not logged in
|
|
98
98
|
}
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
// Use ctx.runQuery() to lookup user from your database
|
|
101
101
|
const user = await ctx.runQuery(internal.users.getByAuthId, {
|
|
102
102
|
authId: identity.subject,
|
|
103
103
|
});
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
if (!user) {
|
|
106
106
|
return null; // User not found in database
|
|
107
107
|
}
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
return {
|
|
110
110
|
dodoCustomerId: user.dodoCustomerId, // Replace user.dodoCustomerId with your field storing Dodo Payments customer ID
|
|
111
111
|
};
|
|
112
112
|
},
|
|
113
113
|
apiKey: process.env.DODO_PAYMENTS_API_KEY!,
|
|
114
|
-
environment: process.env.DODO_PAYMENTS_ENVIRONMENT as
|
|
114
|
+
environment: process.env.DODO_PAYMENTS_ENVIRONMENT as
|
|
115
|
+
| "test_mode"
|
|
116
|
+
| "live_mode",
|
|
115
117
|
});
|
|
116
118
|
|
|
117
119
|
// Export the API methods for use in your app
|
|
@@ -124,8 +126,8 @@ For handling Dodo Payments webhooks, create a file `convex/http.ts`:
|
|
|
124
126
|
|
|
125
127
|
```typescript
|
|
126
128
|
// convex/http.ts
|
|
127
|
-
import { httpRouter } from "convex/server";
|
|
128
129
|
import { createDodoWebhookHandler } from "@dodopayments/convex";
|
|
130
|
+
import { httpRouter } from "convex/server";
|
|
129
131
|
import { internal } from "./_generated/api";
|
|
130
132
|
|
|
131
133
|
const http = httpRouter();
|
|
@@ -134,23 +136,31 @@ http.route({
|
|
|
134
136
|
path: "/dodopayments-webhook",
|
|
135
137
|
method: "POST",
|
|
136
138
|
handler: createDodoWebhookHandler({
|
|
139
|
+
// Handle successful payments
|
|
137
140
|
onPaymentSucceeded: async (ctx, payload) => {
|
|
138
|
-
console.log("Payment
|
|
139
|
-
//
|
|
140
|
-
await ctx.runMutation(internal.
|
|
141
|
-
orderId: payload.data.metadata.orderId,
|
|
141
|
+
console.log("🎉 Payment Succeeded!");
|
|
142
|
+
// Use Convex context to persist payment data
|
|
143
|
+
await ctx.runMutation(internal.webhooks.createPayment, {
|
|
142
144
|
paymentId: payload.data.payment_id,
|
|
143
|
-
|
|
145
|
+
businessId: payload.business_id,
|
|
146
|
+
customerEmail: payload.data.customer.email,
|
|
147
|
+
amount: payload.data.total_amount,
|
|
148
|
+
currency: payload.data.currency,
|
|
149
|
+
status: payload.data.status,
|
|
150
|
+
webhookPayload: JSON.stringify(payload),
|
|
144
151
|
});
|
|
145
152
|
},
|
|
146
|
-
|
|
153
|
+
|
|
154
|
+
// Handle subscription activation
|
|
147
155
|
onSubscriptionActive: async (ctx, payload) => {
|
|
148
|
-
console.log("Subscription
|
|
149
|
-
//
|
|
150
|
-
await ctx.runMutation(internal.
|
|
156
|
+
console.log("🎉 Subscription Activated!");
|
|
157
|
+
// Use Convex context to persist subscription data
|
|
158
|
+
await ctx.runMutation(internal.webhooks.createSubscription, {
|
|
151
159
|
subscriptionId: payload.data.subscription_id,
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
businessId: payload.business_id,
|
|
161
|
+
customerEmail: payload.data.customer.email,
|
|
162
|
+
status: payload.data.status,
|
|
163
|
+
webhookPayload: JSON.stringify(payload),
|
|
154
164
|
});
|
|
155
165
|
},
|
|
156
166
|
// Add other event handlers as needed
|
|
@@ -160,6 +170,8 @@ http.route({
|
|
|
160
170
|
export default http;
|
|
161
171
|
```
|
|
162
172
|
|
|
173
|
+
**Important:** Make sure to define the corresponding database mutations in your Convex backend for each webhook event you want to handle. For example, create a `createPayment` mutation to record successful payments or a `createSubscription` mutation to manage subscription state.
|
|
174
|
+
|
|
163
175
|
**Important:** All webhook handlers receive the Convex `ActionCtx` as the first parameter, allowing you to use `ctx.runQuery()` and `ctx.runMutation()` to interact with your database.
|
|
164
176
|
|
|
165
177
|
Add your webhook secret in the Convex dashboard (**Settings** → **Environment Variables**):
|
|
@@ -175,11 +187,13 @@ import { v } from "convex/values";
|
|
|
175
187
|
import { checkout } from "./dodo";
|
|
176
188
|
|
|
177
189
|
export const createCheckout = action({
|
|
178
|
-
args: {
|
|
179
|
-
product_cart: v.array(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
190
|
+
args: {
|
|
191
|
+
product_cart: v.array(
|
|
192
|
+
v.object({
|
|
193
|
+
product_id: v.string(),
|
|
194
|
+
quantity: v.number(),
|
|
195
|
+
}),
|
|
196
|
+
),
|
|
183
197
|
returnUrl: v.optional(v.string()),
|
|
184
198
|
},
|
|
185
199
|
handler: async (ctx, args) => {
|
|
@@ -301,16 +315,16 @@ export const dodo = new DodoPayments(components.dodopayments, {
|
|
|
301
315
|
if (!identity) {
|
|
302
316
|
return null; // User is not logged in
|
|
303
317
|
}
|
|
304
|
-
|
|
318
|
+
|
|
305
319
|
// Use ctx.runQuery() to lookup user from your database
|
|
306
320
|
const user = await ctx.runQuery(internal.users.getByAuthId, {
|
|
307
321
|
authId: identity.subject,
|
|
308
322
|
});
|
|
309
|
-
|
|
323
|
+
|
|
310
324
|
if (!user) {
|
|
311
325
|
return null; // User not found in database
|
|
312
326
|
}
|
|
313
|
-
|
|
327
|
+
|
|
314
328
|
return {
|
|
315
329
|
dodoCustomerId: user.dodoCustomerId, // Replace user.dodoCustomerId with your field storing Dodo Payments customer ID
|
|
316
330
|
};
|
|
@@ -331,7 +345,7 @@ import { checkout } from "./dodo";
|
|
|
331
345
|
|
|
332
346
|
// Checkout session with full feature support
|
|
333
347
|
export const createCheckout = action({
|
|
334
|
-
args: {
|
|
348
|
+
args: {
|
|
335
349
|
product_cart: v.array(v.object({
|
|
336
350
|
product_id: v.string(),
|
|
337
351
|
quantity: v.number(),
|
|
@@ -447,8 +461,8 @@ Do not use .env files for backend functions; always set secrets in the Convex da
|
|
|
447
461
|
Step 2: Create a file `convex/http.ts`:
|
|
448
462
|
|
|
449
463
|
// convex/http.ts
|
|
450
|
-
import { httpRouter } from "convex/server";
|
|
451
464
|
import { createDodoWebhookHandler } from "@dodopayments/convex";
|
|
465
|
+
import { httpRouter } from "convex/server";
|
|
452
466
|
import { internal } from "./_generated/api";
|
|
453
467
|
|
|
454
468
|
const http = httpRouter();
|
|
@@ -457,21 +471,31 @@ http.route({
|
|
|
457
471
|
path: "/dodopayments-webhook",
|
|
458
472
|
method: "POST",
|
|
459
473
|
handler: createDodoWebhookHandler({
|
|
474
|
+
// Handle successful payments
|
|
460
475
|
onPaymentSucceeded: async (ctx, payload) => {
|
|
461
|
-
console.log("Payment
|
|
462
|
-
//
|
|
463
|
-
await ctx.runMutation(internal.
|
|
464
|
-
orderId: payload.data.metadata.orderId,
|
|
476
|
+
console.log("🎉 Payment Succeeded!");
|
|
477
|
+
// Use Convex context to persist payment data
|
|
478
|
+
await ctx.runMutation(internal.webhooks.createPayment, {
|
|
465
479
|
paymentId: payload.data.payment_id,
|
|
480
|
+
businessId: payload.business_id,
|
|
481
|
+
customerEmail: payload.data.customer.email,
|
|
482
|
+
amount: payload.data.total_amount,
|
|
483
|
+
currency: payload.data.currency,
|
|
484
|
+
status: payload.data.status,
|
|
485
|
+
webhookPayload: JSON.stringify(payload),
|
|
466
486
|
});
|
|
467
487
|
},
|
|
468
|
-
|
|
488
|
+
|
|
489
|
+
// Handle subscription activation
|
|
469
490
|
onSubscriptionActive: async (ctx, payload) => {
|
|
470
|
-
console.log("Subscription
|
|
471
|
-
// Use
|
|
472
|
-
await ctx.runMutation(internal.
|
|
491
|
+
console.log("🎉 Subscription Activated!");
|
|
492
|
+
// Use Convex context to persist subscription data
|
|
493
|
+
await ctx.runMutation(internal.webhooks.createSubscription, {
|
|
473
494
|
subscriptionId: payload.data.subscription_id,
|
|
474
|
-
|
|
495
|
+
businessId: payload.business_id,
|
|
496
|
+
customerEmail: payload.data.customer.email,
|
|
497
|
+
status: payload.data.status,
|
|
498
|
+
webhookPayload: JSON.stringify(payload),
|
|
475
499
|
});
|
|
476
500
|
},
|
|
477
501
|
// Add other event handlers as needed
|
|
@@ -480,6 +504,8 @@ http.route({
|
|
|
480
504
|
|
|
481
505
|
export default http;
|
|
482
506
|
|
|
507
|
+
Note: Make sure to define the corresponding database mutations in your Convex backend for each webhook event you want to handle. For example, create a `createPayment` mutation to record successful payments or a `createSubscription` mutation to manage subscription state.
|
|
508
|
+
|
|
483
509
|
Now, you can set the webhook endpoint URL in your Dodo Payments dashboard to `https://<your-convex-deployment-url>/dodopayments-webhook`.
|
|
484
510
|
|
|
485
511
|
Environment Variable Setup:
|
|
@@ -505,4 +531,3 @@ If the user needs assistance setting up environment variables or deployment, ask
|
|
|
505
531
|
|
|
506
532
|
Run `npx convex dev` after setting up the component to generate the necessary types.
|
|
507
533
|
```
|
|
508
|
-
|
package/dist/component/lib.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { action } from './_generated/server.js';
|
|
2
2
|
import { v } from 'convex/values';
|
|
3
|
-
import { buildCheckoutUrl } from '../core/dist/checkout/checkout.js';
|
|
3
|
+
import { buildCheckoutUrl } from '../packages/core/dist/checkout/checkout.js';
|
|
4
4
|
import DodoPayments from 'dodopayments';
|
|
5
5
|
|
|
6
6
|
const checkoutSessionPayloadValidator = v.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.js","sources":["../../src/component/lib.ts"],"sourcesContent":["import { action } from \"../component/_generated/server\";\nimport { v } from \"convex/values\";\nimport {
|
|
1
|
+
{"version":3,"file":"lib.js","sources":["../../src/component/lib.ts"],"sourcesContent":["import { action } from \"../component/_generated/server\";\nimport { v } from \"convex/values\";\nimport {\n buildCheckoutUrl,\n type CheckoutSessionPayload,\n} from \"@dodopayments/core/checkout\";\nimport DodoPayments from \"dodopayments\";\n\nconst checkoutSessionPayloadValidator = v.object({\n product_cart: v.array(\n v.object({\n product_id: v.string(),\n quantity: v.number(),\n }),\n ),\n customer: v.optional(\n v.object({\n email: v.optional(v.string()),\n name: v.optional(v.string()),\n phone_number: v.optional(v.string()),\n }),\n ),\n billing_address: v.optional(\n v.object({\n street: v.optional(v.string()),\n city: v.optional(v.string()),\n state: v.optional(v.string()),\n country: v.string(),\n zipcode: v.optional(v.string()),\n }),\n ),\n return_url: v.optional(v.string()),\n allowed_payment_method_types: v.optional(v.array(v.string())),\n billing_currency: v.optional(v.string()),\n show_saved_payment_methods: v.optional(v.boolean()),\n confirm: v.optional(v.boolean()),\n discount_code: v.optional(v.string()),\n metadata: v.optional(v.record(v.string(), v.string())),\n customization: v.optional(\n v.object({\n theme: v.optional(v.string()),\n show_order_details: v.optional(v.boolean()),\n show_on_demand_tag: v.optional(v.boolean()),\n }),\n ),\n feature_flags: v.optional(\n v.object({\n allow_currency_selection: v.optional(v.boolean()),\n allow_discount_code: v.optional(v.boolean()),\n allow_phone_number_collection: v.optional(v.boolean()),\n allow_tax_id: v.optional(v.boolean()),\n always_create_new_customer: v.optional(v.boolean()),\n }),\n ),\n subscription_data: v.optional(\n v.object({\n trial_period_days: v.optional(v.number()),\n }),\n ),\n});\n\nexport const checkout = action({\n args: {\n payload: checkoutSessionPayloadValidator,\n apiKey: v.string(),\n environment: v.union(v.literal(\"test_mode\"), v.literal(\"live_mode\")),\n },\n returns: v.object({ checkout_url: v.string() }),\n handler: async (\n _,\n { payload, apiKey, environment },\n ): Promise<{ checkout_url: string }> => {\n const checkoutUrl = await buildCheckoutUrl({\n sessionPayload: payload as CheckoutSessionPayload,\n bearerToken: apiKey,\n environment,\n type: \"session\",\n });\n return { checkout_url: checkoutUrl };\n },\n});\n\nexport const customerPortal = action({\n args: {\n dodoCustomerId: v.string(),\n send_email: v.optional(v.boolean()),\n apiKey: v.string(),\n environment: v.union(v.literal(\"test_mode\"), v.literal(\"live_mode\")),\n },\n returns: v.object({ portal_url: v.string() }),\n handler: async (\n _,\n { dodoCustomerId, send_email, apiKey, environment },\n ): Promise<{ portal_url: string }> => {\n if (!dodoCustomerId) {\n throw new Error(\"dodoCustomerId is required for customerPortal.\");\n }\n\n const dodopayments = new DodoPayments({\n bearerToken: apiKey,\n environment,\n });\n\n const params = {\n send_email: Boolean(send_email),\n };\n\n const session = await dodopayments.customers.customerPortal.create(\n dodoCustomerId,\n params,\n );\n return { portal_url: session.link };\n },\n});\n"],"names":[],"mappings":"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"}
|