{"id":17174,"library":"better-auth-razorpay","title":"Better Auth Razorpay Plugin","description":"The `better-auth-razorpay` package provides a robust and type-safe integration of Razorpay payment functionalities into applications utilizing `better-auth`. As of version 2.0.7, it offers comprehensive support for the full Razorpay subscription lifecycle, including creation, upgrades, cancellations, pauses, and resumptions, alongside features like trial abuse prevention and automatic customer synchronization with user details. It caters to various billing models, including organization and seat-based billing, and provides secure, HMAC-SHA256 verified webhook processing for all critical Razorpay events. The plugin also ships with pre-built React hooks leveraging TanStack Query for seamless client-side integration and boasts end-to-end TypeScript coverage, ensuring type safety across its API. While a specific release cadence isn't published, it aligns with `better-auth` ecosystem updates and feature-driven development, often introducing new capabilities or refinements.","status":"active","version":"2.0.7","language":"javascript","source_language":"en","source_url":"https://github.com/iamjasonkendrick/better-auth-razorpay","tags":["javascript","better-auth","razorpay","payments","billing","subscription","authentication","plugin","typescript"],"install":[{"cmd":"npm install better-auth-razorpay","lang":"bash","label":"npm"},{"cmd":"yarn add better-auth-razorpay","lang":"bash","label":"yarn"},{"cmd":"pnpm add better-auth-razorpay","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core authentication library this plugin extends.","package":"better-auth","optional":false},{"reason":"Official Razorpay SDK used for server-side interactions.","package":"razorpay","optional":false},{"reason":"Required for client-side React hooks for data fetching and caching.","package":"@tanstack/react-query","optional":true},{"reason":"Required for client-side React hooks functionality.","package":"react","optional":true}],"imports":[{"note":"This is the server-side plugin initializer. Prefer ESM imports for `better-auth` plugins.","wrong":"const { razorpay } = require('better-auth-razorpay');","symbol":"razorpay","correct":"import { razorpay } from 'better-auth-razorpay';"},{"note":"This is the client-side plugin initializer, imported from a subpath. Ensure correct named import.","wrong":"import { razorpay } from 'better-auth-razorpay/client';","symbol":"razorpayClient","correct":"import { razorpayClient } from 'better-auth-razorpay/client';"},{"note":"Always use `import type` for type-only imports to prevent accidental runtime imports and optimize bundle size.","wrong":"import { RazorpayPluginOptions } from 'better-auth-razorpay';","symbol":"RazorpayPluginOptions","correct":"import type { RazorpayPluginOptions } from 'better-auth-razorpay';"}],"quickstart":{"code":"import { betterAuth } from \"better-auth\";\nimport { razorpay } from \"better-auth-razorpay\";\nimport Razorpay from \"razorpay\";\n\nconst razorpayClient = new Razorpay({\n  key_id: process.env.RAZORPAY_KEY_ID ?? '',\n  key_secret: process.env.RAZORPAY_KEY_SECRET ?? ''\n});\n\nexport const auth = betterAuth({\n  plugins: [\n    razorpay({\n      razorpayClient,\n      razorpayWebhookSecret: process.env.RAZORPAY_WEBHOOK_SECRET ?? '',\n      createCustomerOnSignUp: true,\n\n      subscription: {\n        enabled: true,\n        plans: [\n          {\n            planId: \"plan_XXXXXXXXXX\", // Replace with your Razorpay Plan ID\n            name: \"pro\",\n            totalCount: 12,\n          },\n          {\n            planId: \"plan_YYYYYYYYYY\", // Replace with your Razorpay Plan ID\n            annualPlanId: \"plan_ZZZZZZZZZZ\", // Optional: Annual Plan ID\n            name: \"enterprise\",\n            totalCount: 1,\n            quantity: 1, // seat-based example\n          },\n        ],\n\n        onSubscriptionActivated: async ({ subscription, plan, event }) => {\n          console.log(`Subscription activated: ${subscription.id} for plan ${plan.name}`);\n          // Implement your business logic here, e.g., update user roles\n        },\n        // ... other lifecycle callbacks\n      },\n    }),\n  ],\n});","lang":"typescript","description":"Demonstrates how to initialize the `better-auth-razorpay` plugin on the server, configure the Razorpay client, set up webhooks, and define subscription plans with lifecycle callbacks."},"warnings":[{"fix":"Consult the `better-auth-razorpay` GitHub repository for specific migration instructions or breaking changes documentation associated with your target version.","message":"Major version updates (e.g., from 1.x to 2.x) may introduce breaking changes to the plugin's configuration options or API surface. Always review release notes or migration guides when upgrading major versions to avoid unexpected issues.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure `razorpayWebhookSecret` matches the secret configured in your Razorpay dashboard exactly. Store this secret securely in environment variables and never hardcode it.","message":"The `razorpayWebhookSecret` is critical for verifying the authenticity of Razorpay webhooks using HMAC-SHA256. Misconfiguration, exposure, or failure to set this secret can lead to security vulnerabilities or processing of fraudulent webhook events.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Use a robust environment variable management system (e.g., `.env` files, cloud secrets managers) to inject these sensitive values at runtime. Never embed them directly in your codebase.","message":"API keys (`RAZORPAY_KEY_ID`, `RAZORPAY_KEY_SECRET`) and the webhook secret should always be managed as environment variables. Hardcoding these credentials or committing them to version control poses a significant security risk.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Carefully review the required webhook events in the `better-auth-razorpay` documentation and ensure all specified events are enabled and correctly configured in your Razorpay dashboard for the registered webhook URL.","message":"Failure to select all necessary webhook events in the Razorpay dashboard (as outlined in the documentation, e.g., `subscription.activated`, `subscription.cancelled`, `subscription.updated`) will result in incomplete or incorrect subscription lifecycle management within your application.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always use `import { razorpay } from 'better-auth-razorpay';` for server-side `betterAuth` configuration and `import { razorpayClient } from 'better-auth-razorpay/client';` for client-side `createAuthClient` configuration.","message":"The `better-auth-razorpay` plugin has distinct server-side (`razorpay`) and client-side (`razorpayClient`) initializers, typically imported from different paths (`better-auth-razorpay` vs. `better-auth-razorpay/client`). Mismatched or incorrect imports are a common source of setup errors.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure `process.env.RAZORPAY_WEBHOOK_SECRET` exactly matches the secret in your Razorpay dashboard. If using a web framework like Express, ensure you are using `express.raw()` or similar middleware for the webhook endpoint to capture the raw request body before parsing.","cause":"The `razorpayWebhookSecret` configured in the plugin does not match the secret set in the Razorpay dashboard, or the raw request body was not properly passed to the handler.","error":"Error: Webhook signature verification failed."},{"fix":"Double-check all `planId` values in your `better-auth-razorpay` server-side configuration against active plans in your Razorpay dashboard. Ensure the `name` property for each plan is unique and correctly corresponds to the Razorpay `planId`.","cause":"The `planId` configured in your `subscription.plans` array does not exist, is inactive, or is incorrectly mapped in your Razorpay account.","error":"Razorpay Error: Bad Request - The subscription plan specified is invalid."},{"fix":"Verify that `razorpay({...})` is included in the `plugins` array for `betterAuth` on the server, and `razorpayClient({...})` is included in the `plugins` array for `createAuthClient` on the client. Ensure all required configuration options are provided to the plugin.","cause":"The `better-auth-razorpay` plugin was not correctly initialized and passed to the `betterAuth` instance's `plugins` array on the server, or the client-side plugin was not passed to `createAuthClient`.","error":"TypeError: Cannot read properties of undefined (reading 'plugins') or Plugin 'razorpay' not found."},{"fix":"Ensure you are using the correct import statement: `import { razorpayClient } from 'better-auth-razorpay/client';`. If the issue persists, check your `tsconfig.json` for appropriate `moduleResolution` settings and ensure the package is correctly installed.","cause":"Incorrect import path for the client-side plugin or a TypeScript module resolution issue.","error":"TS2307: Cannot find module 'better-auth-razorpay/client' or its corresponding type declarations."}],"ecosystem":"npm","meta_description":null}