@deiondz/better-auth-razorpay 2.0.12 → 2.0.14
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 +17 -2
- package/dist/client/hooks.d.ts +3 -3
- package/dist/client.d.ts +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +126 -19
- package/dist/index.js.map +1 -1
- package/dist/{types-VZW_XCzQ.d.ts → types-3dNrA0qB.d.ts} +21 -1
- package/dist/{types-BGWv0IJy.d.ts → types-CKR2ILS1.d.ts} +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -219,6 +219,7 @@ interface RazorpayPluginOptions {
|
|
|
219
219
|
razorpayKeySecret?: string // Optional: Razorpay API key secret; required when razorpayClient is not provided; when set, enables POST /razorpay/verify-payment
|
|
220
220
|
razorpayWebhookSecret?: string // Optional: Webhook secret for signature verification
|
|
221
221
|
createCustomerOnSignUp?: boolean // Optional: Create Razorpay customer on user sign-up (default: false)
|
|
222
|
+
trialOnSignUp?: { days: number; planName?: string } // Optional: When set with createCustomerOnSignUp, creates an app-level trial subscription at sign-up. Omit for no sign-up trial.
|
|
222
223
|
onCustomerCreate?: (args) => Promise<void>
|
|
223
224
|
getCustomerCreateParams?: (args) => Promise<{ params?: Record<string, unknown> }>
|
|
224
225
|
subscription?: SubscriptionOptions // Optional: { enabled, plans, callbacks, authorizeReference, ... }
|
|
@@ -227,6 +228,17 @@ interface RazorpayPluginOptions {
|
|
|
227
228
|
}
|
|
228
229
|
```
|
|
229
230
|
|
|
231
|
+
### Optional: Trial on sign-up
|
|
232
|
+
|
|
233
|
+
When you want new users to get a **free trial** without adding a payment method first (e.g. 14 days, then they must subscribe):
|
|
234
|
+
|
|
235
|
+
- Set **both** `createCustomerOnSignUp: true` and `trialOnSignUp: { days: 14, planName: 'Trial' }` (or any `days` and display `planName`).
|
|
236
|
+
- On sign-up, the plugin creates a Razorpay customer and **one local subscription** with `status: 'trialing'`, `trialStart` / `trialEnd`, and no `razorpaySubscriptionId` (no Razorpay subscription until they subscribe).
|
|
237
|
+
- **Subscription list** returns this record; your app can show "Free trial — ends <trialEnd>" and gate features when `trialEnd < now`.
|
|
238
|
+
- The user can **subscribe anytime** via create-or-update (choose a plan, get checkout URL); the same record is updated to a paid subscription (plan, `razorpaySubscriptionId`, status from Razorpay).
|
|
239
|
+
|
|
240
|
+
**Configurable:** Omit `trialOnSignUp` for products that do not want sign-up trials (e.g. checkout-first or plan-based trial only). If `trialOnSignUp` is not set, behavior is unchanged.
|
|
241
|
+
|
|
230
242
|
### Callback functions
|
|
231
243
|
|
|
232
244
|
The plugin supports the same callback hooks as the [community plugin](https://github.com/iamjasonkendrick/better-auth-razorpay). You can use them for emails, analytics, external systems, or custom logic.
|
|
@@ -254,6 +266,7 @@ razorpayPlugin({
|
|
|
254
266
|
razorpayWebhookSecret: process.env.RAZORPAY_WEBHOOK_SECRET,
|
|
255
267
|
razorpayKeySecret: process.env.RAZORPAY_KEY_SECRET, // optional: enables verify-payment endpoint
|
|
256
268
|
createCustomerOnSignUp: true,
|
|
269
|
+
trialOnSignUp: { days: 14, planName: 'Trial' }, // optional: app-level trial at sign-up
|
|
257
270
|
onCustomerCreate: async ({ user, razorpayCustomer }) => {
|
|
258
271
|
console.log(`Razorpay customer created for user ${user.id}: ${razorpayCustomer.id}`)
|
|
259
272
|
},
|
|
@@ -341,7 +354,7 @@ All endpoints are prefixed with `/api/auth/razorpay/` (or your configured `baseP
|
|
|
341
354
|
| Cancel | `POST` | `subscription/cancel` | Cancel by local subscription ID. Body: `subscriptionId`, `immediately?`. |
|
|
342
355
|
| Restore | `POST` | `subscription/restore` | Restore a subscription scheduled to cancel. Body: `subscriptionId`. |
|
|
343
356
|
| List | `GET` | `subscription/list` | List active/trialing subscriptions. Query: `referenceId?` (default: current user). |
|
|
344
|
-
| Get plans | `GET` | `get-plans` | Return configured plans (name, monthlyPlanId, annualPlanId, limits, freeTrial). |
|
|
357
|
+
| Get plans | `GET` | `get-plans` | Return configured plans with price details (name, monthlyPlanId, annualPlanId, limits, freeTrial, monthly/annual amount, currency, period from Razorpay). |
|
|
345
358
|
| Webhook | `POST` | `webhook` | Razorpay webhook URL; configure in Razorpay Dashboard. |
|
|
346
359
|
|
|
347
360
|
### 1. Get Plans
|
|
@@ -350,6 +363,8 @@ Retrieve all configured subscription plans (from plugin config; no Razorpay API
|
|
|
350
363
|
|
|
351
364
|
**Endpoint:** `GET /api/auth/razorpay/get-plans`
|
|
352
365
|
|
|
366
|
+
Each plan in the response includes optional **price details** (`monthly`, `annual`) when available from Razorpay: `amount` (smallest currency unit, e.g. paise/cents), `currency`, `period` (e.g. monthly, yearly), and `interval`. Omitted if the plan fetch fails or the variant is not configured.
|
|
367
|
+
|
|
353
368
|
**Authentication:** Not required (public endpoint)
|
|
354
369
|
|
|
355
370
|
**Response:**
|
|
@@ -357,7 +372,7 @@ Retrieve all configured subscription plans (from plugin config; no Razorpay API
|
|
|
357
372
|
```typescript
|
|
358
373
|
{
|
|
359
374
|
success: true,
|
|
360
|
-
data: Array<{ name: string; monthlyPlanId: string; annualPlanId?: string; limits?: Record<string, number>; freeTrial?: { days: number } }>
|
|
375
|
+
data: Array<{ name: string; monthlyPlanId: string; annualPlanId?: string; limits?: Record<string, number>; freeTrial?: { days: number }; monthly?: { amount: number; currency: string; period: string; interval?: number }; annual?: { amount: number; currency: string; period: string; interval?: number } }>
|
|
361
376
|
}
|
|
362
377
|
```
|
|
363
378
|
|
package/dist/client/hooks.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { S as SubscriptionRecord } from '../types-
|
|
1
|
+
import { S as SubscriptionRecord } from '../types-3dNrA0qB.js';
|
|
2
2
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
3
3
|
import { UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
|
|
4
4
|
import * as react from 'react';
|
|
5
5
|
import { ReactNode } from 'react';
|
|
6
|
-
import { c as RazorpayAuthClient, d as CancelSubscriptionResponse, a as CancelSubscriptionInput, e as CreateOrUpdateSubscriptionResponse, C as CreateOrUpdateSubscriptionInput, P as PlanSummary, f as RestoreSubscriptionResponse, b as RestoreSubscriptionInput, g as ListSubscriptionsResponse, h as VerifyPaymentResponse, V as VerifyPaymentInput, L as ListSubscriptionsInput } from '../types-
|
|
7
|
-
export { G as GetPlansResponse, i as RazorpayApiError, R as RazorpayApiResult, j as RazorpayClientActions } from '../types-
|
|
6
|
+
import { c as RazorpayAuthClient, d as CancelSubscriptionResponse, a as CancelSubscriptionInput, e as CreateOrUpdateSubscriptionResponse, C as CreateOrUpdateSubscriptionInput, P as PlanSummary, f as RestoreSubscriptionResponse, b as RestoreSubscriptionInput, g as ListSubscriptionsResponse, h as VerifyPaymentResponse, V as VerifyPaymentInput, L as ListSubscriptionsInput } from '../types-CKR2ILS1.js';
|
|
7
|
+
export { G as GetPlansResponse, i as RazorpayApiError, R as RazorpayApiResult, j as RazorpayClientActions } from '../types-CKR2ILS1.js';
|
|
8
8
|
import 'razorpay';
|
|
9
9
|
|
|
10
10
|
/**
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S as SubscriptionRecord } from './types-
|
|
1
|
+
import { S as SubscriptionRecord } from './types-3dNrA0qB.js';
|
|
2
2
|
import { razorpayPlugin } from './index.js';
|
|
3
|
-
import { R as RazorpayApiResult, P as PlanSummary, L as ListSubscriptionsInput, C as CreateOrUpdateSubscriptionInput, a as CancelSubscriptionInput, b as RestoreSubscriptionInput, V as VerifyPaymentInput } from './types-
|
|
3
|
+
import { R as RazorpayApiResult, P as PlanSummary, L as ListSubscriptionsInput, C as CreateOrUpdateSubscriptionInput, a as CancelSubscriptionInput, b as RestoreSubscriptionInput, V as VerifyPaymentInput } from './types-CKR2ILS1.js';
|
|
4
4
|
import 'razorpay';
|
|
5
5
|
import 'better-auth';
|
|
6
6
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BetterAuthPlugin } from 'better-auth';
|
|
2
|
-
import { R as RazorpayPluginOptions } from './types-
|
|
3
|
-
export { O as OnWebhookEventCallback, a as RazorpayApiResponse, b as RazorpayErrorResponse, c as RazorpayPlan, d as RazorpaySubscription, e as RazorpaySuccessResponse, f as RazorpayUserRecord, g as RazorpayWebhookContext, h as RazorpayWebhookEvent, i as RazorpayWebhookPayload, S as SubscriptionRecord, j as SubscriptionStatus } from './types-
|
|
2
|
+
import { R as RazorpayPluginOptions } from './types-3dNrA0qB.js';
|
|
3
|
+
export { O as OnWebhookEventCallback, a as RazorpayApiResponse, b as RazorpayErrorResponse, c as RazorpayPlan, d as RazorpaySubscription, e as RazorpaySuccessResponse, f as RazorpayUserRecord, g as RazorpayWebhookContext, h as RazorpayWebhookEvent, i as RazorpayWebhookPayload, S as SubscriptionRecord, j as SubscriptionStatus } from './types-3dNrA0qB.js';
|
|
4
4
|
import 'razorpay';
|
|
5
5
|
|
|
6
6
|
interface WebhookResult {
|
|
@@ -23,6 +23,7 @@ interface WebhookResult {
|
|
|
23
23
|
* @param options.razorpayKeySecret - Razorpay API key secret (required when razorpayClient is not provided; when set, also enables POST /razorpay/verify-payment)
|
|
24
24
|
* @param options.razorpayWebhookSecret - Webhook secret for signature verification
|
|
25
25
|
* @param options.createCustomerOnSignUp - Create Razorpay customer when user signs up (default: false)
|
|
26
|
+
* @param options.trialOnSignUp - Optional. When set with createCustomerOnSignUp, creates an app-level trial subscription at sign-up. { days, planName? }. Omit for no sign-up trial.
|
|
26
27
|
* @param options.onCustomerCreate - Callback after customer is created
|
|
27
28
|
* @param options.getCustomerCreateParams - Custom params when creating customer
|
|
28
29
|
* @param options.subscription - Subscription config (enabled, plans, callbacks, authorizeReference)
|
package/dist/index.js
CHANGED
|
@@ -4334,8 +4334,15 @@ var createOrUpdateSubscription = (razorpay, options) => createAuthEndpoint2(
|
|
|
4334
4334
|
"created",
|
|
4335
4335
|
"halted"
|
|
4336
4336
|
];
|
|
4337
|
-
const
|
|
4338
|
-
|
|
4337
|
+
const subs = existingSubs ?? [];
|
|
4338
|
+
const activePaidSubs = subs.filter(
|
|
4339
|
+
(s) => activeStatuses.includes(s.status) && s.razorpaySubscriptionId
|
|
4340
|
+
);
|
|
4341
|
+
const appTrialSubs = subs.filter(
|
|
4342
|
+
(s) => s.status === "trialing" && !s.razorpaySubscriptionId
|
|
4343
|
+
);
|
|
4344
|
+
const appTrialSub = appTrialSubs.length === 1 ? appTrialSubs[0] : null;
|
|
4345
|
+
if (activePaidSubs.length > 0) {
|
|
4339
4346
|
return {
|
|
4340
4347
|
success: false,
|
|
4341
4348
|
error: {
|
|
@@ -4354,7 +4361,7 @@ var createOrUpdateSubscription = (razorpay, options) => createAuthEndpoint2(
|
|
|
4354
4361
|
};
|
|
4355
4362
|
if (subOpts.getSubscriptionCreateParams) {
|
|
4356
4363
|
const tempSub = {
|
|
4357
|
-
id: "",
|
|
4364
|
+
id: appTrialSub?.id ?? "",
|
|
4358
4365
|
plan: plan.name,
|
|
4359
4366
|
referenceId: userId,
|
|
4360
4367
|
status: "created",
|
|
@@ -4379,17 +4386,64 @@ var createOrUpdateSubscription = (razorpay, options) => createAuthEndpoint2(
|
|
|
4379
4386
|
const rpSubscription = await razorpay.subscriptions.create(
|
|
4380
4387
|
subscriptionPayload
|
|
4381
4388
|
);
|
|
4389
|
+
const periodStart = rpSubscription.current_start ? new Date(rpSubscription.current_start * 1e3) : null;
|
|
4390
|
+
const periodEnd = rpSubscription.current_end ? new Date(rpSubscription.current_end * 1e3) : null;
|
|
4391
|
+
const newStatus = toLocalStatus(rpSubscription.status);
|
|
4392
|
+
if (appTrialSub) {
|
|
4393
|
+
await ctx.context.adapter.update({
|
|
4394
|
+
model: "subscription",
|
|
4395
|
+
where: [{ field: "id", value: appTrialSub.id }],
|
|
4396
|
+
update: {
|
|
4397
|
+
data: {
|
|
4398
|
+
plan: plan.name,
|
|
4399
|
+
razorpaySubscriptionId: rpSubscription.id,
|
|
4400
|
+
status: newStatus,
|
|
4401
|
+
trialEnd: now,
|
|
4402
|
+
periodStart,
|
|
4403
|
+
periodEnd,
|
|
4404
|
+
seats: body.seats,
|
|
4405
|
+
updatedAt: now
|
|
4406
|
+
}
|
|
4407
|
+
}
|
|
4408
|
+
});
|
|
4409
|
+
if (subOpts.onSubscriptionCreated) {
|
|
4410
|
+
const updatedRecord = {
|
|
4411
|
+
...appTrialSub,
|
|
4412
|
+
plan: plan.name,
|
|
4413
|
+
razorpaySubscriptionId: rpSubscription.id,
|
|
4414
|
+
status: newStatus,
|
|
4415
|
+
trialEnd: now,
|
|
4416
|
+
periodStart,
|
|
4417
|
+
periodEnd,
|
|
4418
|
+
seats: body.seats,
|
|
4419
|
+
updatedAt: now
|
|
4420
|
+
};
|
|
4421
|
+
await subOpts.onSubscriptionCreated({
|
|
4422
|
+
razorpaySubscription: rpSubscription,
|
|
4423
|
+
subscription: updatedRecord,
|
|
4424
|
+
plan
|
|
4425
|
+
});
|
|
4426
|
+
}
|
|
4427
|
+
const data2 = {
|
|
4428
|
+
subscriptionId: appTrialSub.id,
|
|
4429
|
+
razorpaySubscriptionId: rpSubscription.id
|
|
4430
|
+
};
|
|
4431
|
+
if (!body.embed) {
|
|
4432
|
+
data2.checkoutUrl = body.disableRedirect ? rpSubscription.short_url : body.successUrl ? `${rpSubscription.short_url}?redirect=${encodeURIComponent(body.successUrl)}` : rpSubscription.short_url;
|
|
4433
|
+
}
|
|
4434
|
+
return { success: true, data: data2 };
|
|
4435
|
+
}
|
|
4382
4436
|
const subscriptionRecord = {
|
|
4383
4437
|
id: localId,
|
|
4384
4438
|
plan: plan.name,
|
|
4385
4439
|
referenceId: userId,
|
|
4386
4440
|
razorpayCustomerId: user.razorpayCustomerId ?? null,
|
|
4387
4441
|
razorpaySubscriptionId: rpSubscription.id,
|
|
4388
|
-
status:
|
|
4442
|
+
status: newStatus,
|
|
4389
4443
|
trialStart: null,
|
|
4390
4444
|
trialEnd: null,
|
|
4391
|
-
periodStart
|
|
4392
|
-
periodEnd
|
|
4445
|
+
periodStart,
|
|
4446
|
+
periodEnd,
|
|
4393
4447
|
cancelAtPeriodEnd: false,
|
|
4394
4448
|
seats: body.seats,
|
|
4395
4449
|
groupId: null,
|
|
@@ -4427,24 +4481,48 @@ import { createAuthEndpoint as createAuthEndpoint3 } from "better-auth/api";
|
|
|
4427
4481
|
async function resolvePlans2(plans) {
|
|
4428
4482
|
return typeof plans === "function" ? plans() : plans;
|
|
4429
4483
|
}
|
|
4430
|
-
|
|
4484
|
+
async function fetchPlanPrice(razorpay, planId) {
|
|
4485
|
+
try {
|
|
4486
|
+
const plan = await razorpay.plans.fetch(planId);
|
|
4487
|
+
const item = plan?.item;
|
|
4488
|
+
if (item && typeof item.amount === "number" && typeof item.currency === "string") {
|
|
4489
|
+
return {
|
|
4490
|
+
amount: item.amount,
|
|
4491
|
+
currency: item.currency,
|
|
4492
|
+
period: typeof plan.period === "string" ? plan.period : "monthly",
|
|
4493
|
+
interval: typeof plan.interval === "number" ? plan.interval : void 0
|
|
4494
|
+
};
|
|
4495
|
+
}
|
|
4496
|
+
} catch {
|
|
4497
|
+
}
|
|
4498
|
+
return void 0;
|
|
4499
|
+
}
|
|
4500
|
+
var getPlans = (razorpay, options) => createAuthEndpoint3("/razorpay/get-plans", { method: "GET" }, async (_ctx) => {
|
|
4431
4501
|
try {
|
|
4432
4502
|
const subOpts = options.subscription;
|
|
4433
4503
|
if (!subOpts?.enabled) {
|
|
4434
4504
|
return { success: true, data: [] };
|
|
4435
4505
|
}
|
|
4436
4506
|
const plans = await resolvePlans2(subOpts.plans);
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4507
|
+
const data = await Promise.all(
|
|
4508
|
+
plans.map(async (p) => {
|
|
4509
|
+
const [monthly, annual] = await Promise.all([
|
|
4510
|
+
fetchPlanPrice(razorpay, p.monthlyPlanId),
|
|
4511
|
+
p.annualPlanId ? fetchPlanPrice(razorpay, p.annualPlanId) : Promise.resolve(void 0)
|
|
4512
|
+
]);
|
|
4513
|
+
return {
|
|
4514
|
+
name: p.name,
|
|
4515
|
+
monthlyPlanId: p.monthlyPlanId,
|
|
4516
|
+
annualPlanId: p.annualPlanId,
|
|
4517
|
+
description: p.description,
|
|
4518
|
+
limits: p.limits,
|
|
4519
|
+
freeTrial: p.freeTrial ? { days: p.freeTrial.days } : void 0,
|
|
4520
|
+
monthly,
|
|
4521
|
+
annual
|
|
4522
|
+
};
|
|
4523
|
+
})
|
|
4524
|
+
);
|
|
4525
|
+
return { success: true, data };
|
|
4448
4526
|
} catch (error) {
|
|
4449
4527
|
return handleRazorpayError(error);
|
|
4450
4528
|
}
|
|
@@ -4855,6 +4933,7 @@ var razorpayPlugin = (options) => {
|
|
|
4855
4933
|
razorpayKeySecret,
|
|
4856
4934
|
razorpayWebhookSecret,
|
|
4857
4935
|
createCustomerOnSignUp = false,
|
|
4936
|
+
trialOnSignUp,
|
|
4858
4937
|
onCustomerCreate,
|
|
4859
4938
|
getCustomerCreateParams,
|
|
4860
4939
|
subscription: subOpts,
|
|
@@ -4912,7 +4991,7 @@ var razorpayPlugin = (options) => {
|
|
|
4912
4991
|
"subscription/cancel": cancelSubscription(razorpay),
|
|
4913
4992
|
"subscription/restore": restoreSubscription(razorpay),
|
|
4914
4993
|
"subscription/list": listSubscriptions({ subscription: subOpts }),
|
|
4915
|
-
"get-plans": getPlans({ subscription: subOpts }),
|
|
4994
|
+
"get-plans": getPlans(razorpay, { subscription: subOpts }),
|
|
4916
4995
|
...razorpayKeySecret ? { "verify-payment": verifyPayment(razorpayKeySecret) } : {},
|
|
4917
4996
|
webhook: webhook(razorpayWebhookSecret, options.onWebhookEvent ?? void 0, {
|
|
4918
4997
|
subscription: subOpts,
|
|
@@ -4951,6 +5030,34 @@ var razorpayPlugin = (options) => {
|
|
|
4951
5030
|
razorpayCustomer: { id: customer.id, ...customer }
|
|
4952
5031
|
});
|
|
4953
5032
|
}
|
|
5033
|
+
if (trialOnSignUp && typeof trialOnSignUp.days === "number" && trialOnSignUp.days > 0 && adapter.create) {
|
|
5034
|
+
const now = /* @__PURE__ */ new Date();
|
|
5035
|
+
const trialEnd = new Date(now.getTime() + trialOnSignUp.days * 24 * 60 * 60 * 1e3);
|
|
5036
|
+
const planName = trialOnSignUp.planName ?? "Trial";
|
|
5037
|
+
const localId = `sub_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
5038
|
+
const subscriptionRecord = {
|
|
5039
|
+
id: localId,
|
|
5040
|
+
plan: planName,
|
|
5041
|
+
referenceId: user.id,
|
|
5042
|
+
razorpayCustomerId: customer.id,
|
|
5043
|
+
razorpaySubscriptionId: null,
|
|
5044
|
+
status: "trialing",
|
|
5045
|
+
trialStart: now,
|
|
5046
|
+
trialEnd,
|
|
5047
|
+
periodStart: null,
|
|
5048
|
+
periodEnd: null,
|
|
5049
|
+
cancelAtPeriodEnd: false,
|
|
5050
|
+
seats: 1,
|
|
5051
|
+
groupId: null,
|
|
5052
|
+
createdAt: now,
|
|
5053
|
+
updatedAt: now
|
|
5054
|
+
};
|
|
5055
|
+
await adapter.create({
|
|
5056
|
+
model: "subscription",
|
|
5057
|
+
data: subscriptionRecord,
|
|
5058
|
+
forceAllowId: true
|
|
5059
|
+
});
|
|
5060
|
+
}
|
|
4954
5061
|
} catch (err) {
|
|
4955
5062
|
console.error("[better-auth-razorpay] Create customer on sign-up failed:", err);
|
|
4956
5063
|
}
|