@deiondz/better-auth-razorpay 2.0.10 → 2.0.12

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/dist/index.js CHANGED
@@ -2,6 +2,9 @@ import {
2
2
  __export
3
3
  } from "./chunk-PZ5AY32C.js";
4
4
 
5
+ // index.ts
6
+ import Razorpay from "razorpay";
7
+
5
8
  // api/cancel-subscription.ts
6
9
  import { createAuthEndpoint, sessionMiddleware } from "better-auth/api";
7
10
 
@@ -4114,12 +4117,14 @@ function handleRazorpayError(error) {
4114
4117
 
4115
4118
  // lib/schemas.ts
4116
4119
  var createOrUpdateSubscriptionSchema = external_exports.object({
4117
- plan: external_exports.string().min(1, "Plan name is required"),
4120
+ plan: external_exports.string().min(1, "Plan name or Razorpay plan ID (plan_*) is required"),
4118
4121
  annual: external_exports.boolean().optional().default(false),
4119
4122
  seats: external_exports.number().int().min(1).optional().default(1),
4120
4123
  subscriptionId: external_exports.string().optional(),
4121
4124
  successUrl: external_exports.string().url().optional(),
4122
- disableRedirect: external_exports.boolean().optional().default(false)
4125
+ disableRedirect: external_exports.boolean().optional().default(false),
4126
+ /** When true, checkout runs in-page via Razorpay modal; no checkoutUrl redirect. */
4127
+ embed: external_exports.boolean().optional().default(false)
4123
4128
  });
4124
4129
  var cancelSubscriptionSchema = external_exports.object({
4125
4130
  subscriptionId: external_exports.string().min(1, "Subscription ID (local) is required"),
@@ -4238,7 +4243,9 @@ var createOrUpdateSubscription = (razorpay, options) => createAuthEndpoint2(
4238
4243
  };
4239
4244
  }
4240
4245
  const plans = await resolvePlans(subOpts.plans);
4241
- const plan = plans.find((p) => p.name === body.plan);
4246
+ const plan = body.plan.startsWith("plan_") ? plans.find(
4247
+ (p) => p.monthlyPlanId === body.plan || p.annualPlanId === body.plan
4248
+ ) : plans.find((p) => p.name === body.plan);
4242
4249
  if (!plan) {
4243
4250
  return {
4244
4251
  success: false,
@@ -4301,23 +4308,42 @@ var createOrUpdateSubscription = (razorpay, options) => createAuthEndpoint2(
4301
4308
  }
4302
4309
  const rpSub = existing.razorpaySubscriptionId ? await razorpay.subscriptions.fetch(existing.razorpaySubscriptionId) : null;
4303
4310
  if (rpSub) {
4304
- return {
4305
- success: true,
4306
- data: {
4307
- checkoutUrl: rpSub.short_url,
4308
- subscription: {
4309
- id: existing.id,
4310
- plan: existing.plan,
4311
- status: existing.status,
4312
- razorpaySubscriptionId: existing.razorpaySubscriptionId,
4313
- cancelAtPeriodEnd: existing.cancelAtPeriodEnd,
4314
- periodEnd: existing.periodEnd,
4315
- seats: existing.seats
4316
- }
4311
+ const data2 = {
4312
+ subscription: {
4313
+ id: existing.id,
4314
+ plan: existing.plan,
4315
+ status: existing.status,
4316
+ razorpaySubscriptionId: existing.razorpaySubscriptionId ?? null,
4317
+ cancelAtPeriodEnd: existing.cancelAtPeriodEnd ?? false,
4318
+ periodEnd: existing.periodEnd ?? null,
4319
+ seats: existing.seats ?? 1
4317
4320
  }
4318
4321
  };
4322
+ if (!body.embed) data2.checkoutUrl = rpSub.short_url;
4323
+ return { success: true, data: data2 };
4319
4324
  }
4320
4325
  }
4326
+ const existingSubs = await ctx.context.adapter.findMany({
4327
+ model: "subscription",
4328
+ where: [{ field: "referenceId", value: userId }]
4329
+ });
4330
+ const activeStatuses = [
4331
+ "active",
4332
+ "trialing",
4333
+ "pending",
4334
+ "created",
4335
+ "halted"
4336
+ ];
4337
+ const hasActiveSubscription = (existingSubs ?? []).filter((s) => activeStatuses.includes(s.status)).length > 0;
4338
+ if (hasActiveSubscription) {
4339
+ return {
4340
+ success: false,
4341
+ error: {
4342
+ code: "ALREADY_SUBSCRIBED",
4343
+ description: "You already have an active subscription. Cancel or let it expire before creating another."
4344
+ }
4345
+ };
4346
+ }
4321
4347
  const totalCount = body.annual ? 1 : 12;
4322
4348
  const subscriptionPayload = {
4323
4349
  plan_id: planId,
@@ -4372,7 +4398,8 @@ var createOrUpdateSubscription = (razorpay, options) => createAuthEndpoint2(
4372
4398
  };
4373
4399
  await ctx.context.adapter.create({
4374
4400
  model: "subscription",
4375
- data: subscriptionRecord
4401
+ data: subscriptionRecord,
4402
+ forceAllowId: true
4376
4403
  });
4377
4404
  if (subOpts.onSubscriptionCreated) {
4378
4405
  await subOpts.onSubscriptionCreated({
@@ -4381,15 +4408,14 @@ var createOrUpdateSubscription = (razorpay, options) => createAuthEndpoint2(
4381
4408
  plan
4382
4409
  });
4383
4410
  }
4384
- const checkoutUrl = body.disableRedirect ? rpSubscription.short_url : body.successUrl ? `${rpSubscription.short_url}?redirect=${encodeURIComponent(body.successUrl)}` : rpSubscription.short_url;
4385
- return {
4386
- success: true,
4387
- data: {
4388
- checkoutUrl,
4389
- subscriptionId: localId,
4390
- razorpaySubscriptionId: rpSubscription.id
4391
- }
4411
+ const data = {
4412
+ subscriptionId: localId,
4413
+ razorpaySubscriptionId: rpSubscription.id
4392
4414
  };
4415
+ if (!body.embed) {
4416
+ data.checkoutUrl = body.disableRedirect ? rpSubscription.short_url : body.successUrl ? `${rpSubscription.short_url}?redirect=${encodeURIComponent(body.successUrl)}` : rpSubscription.short_url;
4417
+ }
4418
+ return { success: true, data };
4393
4419
  } catch (error) {
4394
4420
  return handleRazorpayError(error);
4395
4421
  }
@@ -4825,18 +4851,31 @@ async function processWebhookEvent(adapter, rawBody, fallbackBody, onWebhookEven
4825
4851
  var razorpayPlugin = (options) => {
4826
4852
  const {
4827
4853
  razorpayClient,
4828
- razorpayWebhookSecret,
4854
+ razorpayKeyId,
4829
4855
  razorpayKeySecret,
4856
+ razorpayWebhookSecret,
4830
4857
  createCustomerOnSignUp = false,
4831
4858
  onCustomerCreate,
4832
4859
  getCustomerCreateParams,
4833
4860
  subscription: subOpts,
4834
4861
  onEvent
4835
4862
  } = options;
4836
- if (!razorpayClient) {
4837
- throw new Error("Razorpay plugin: razorpayClient is required");
4838
- }
4839
- const razorpay = razorpayClient;
4863
+ const hasClient = Boolean(razorpayClient);
4864
+ const hasCredentials = Boolean(razorpayKeyId && razorpayKeySecret);
4865
+ if (!hasClient && !hasCredentials) {
4866
+ throw new Error(
4867
+ "Razorpay plugin: provide either razorpayClient or both razorpayKeyId and razorpayKeySecret"
4868
+ );
4869
+ }
4870
+ if (hasClient && hasCredentials) {
4871
+ throw new Error(
4872
+ "Razorpay plugin: provide either razorpayClient or credentials (razorpayKeyId + razorpayKeySecret), not both"
4873
+ );
4874
+ }
4875
+ if (!hasClient && (typeof razorpayKeyId !== "string" || typeof razorpayKeySecret !== "string")) {
4876
+ throw new Error("Razorpay plugin: both razorpayKeyId and razorpayKeySecret are required when not providing razorpayClient");
4877
+ }
4878
+ const razorpay = razorpayClient ?? new Razorpay({ key_id: razorpayKeyId, key_secret: razorpayKeySecret });
4840
4879
  const plugin = {
4841
4880
  id: "razorpay-plugin",
4842
4881
  schema: {