Вышел Модуль интеграций 2.0 для MedusaЧитать анонс
R

Razorpay

Razorpay payment provider for Medusa v2 with INR test/live checkout, refunds, signed webhooks and reconciliation helpers.

npm install @abhi1693/medusa-payment-razorpay
Категория
Создано
Версия
0.0.3
Последнее обновление
4 дня назад
Ежемесячные загрузки
Загрузка данных

Medusa Razorpay

CI

Medusa 2.22.2 / 2.22.4 MIT license Sponsor

A Razorpay payment provider for Medusa v2, with verified checkout results, automatic-capture payments, full and partial refunds, and reusable server-side reconciliation helpers. Uses native Medusa payment sessions, payments, captures and refunds without additional models or a financial ledger.

Supports INR with explicitly configured Razorpay test or live credentials. Unsupported currencies and mode/key mismatches are rejected. Automatic capture must already be configured in the selected Razorpay account. Live-mode support is a configuration capability, not a claim that real-money processing or a deployment has been validated.

Setup · Checkout · Webhooks · Server integration · Operations

Supported payment lifecycle

CapabilityBehavior
Payment sessionsCreates a Razorpay order from the server-provided Medusa amount, with precise rupee-to-paise conversion and a native session association.
Checkout verificationVerifies the signature, fetched payment and order, amount, INR currency and session association before accepting payment.
Automatic captureRequires captured gateway funds before authorization completes. Native capture verifies gateway state and never sends another capture request.
Failed attemptsAllows another attempt on the same order after the previous bound attempt has failed. Successful or in-progress associations cannot silently be replaced.
CancellationCancels/deletes an unpaid session locally; rejects cancellation when gateway payment is authorized or captured. It does not cancel a Razorpay order or issue an implicit refund.
RefundsFull and partial normal-speed refunds, minimum INR 1.00, with a stable native operation key sent through Razorpay's idempotent refund API.
Payment webhooksSigned and events re-fetch gateway state; native processing proceeds only after capture.
Refund observationSigned refund events trigger authenticated current-state checks through optional application wiring. The optional importer records verified processed Dashboard and deferred native refunds in native accounting without sending funds again. Pending/failed refunds do not create accounting entries.

The declared framework peer versions are 2.22.2 and 2.22.4. Native application validation targets Medusa 2.22.2; package development uses 2.22.4. This repository provides a payment module provider and server helpers. Checkout UI, customer authorization, terms acceptance, order-completion policy and infrastructure belong to the consuming application.

Installation and configuration

For source installation, use a reviewed full commit SHA and commit your application's lockfile:

Git installation runs the package's TypeScript build through its script. Your build environment needs Git, Node.js and the declared peer dependency. The repository's Docker toolchain uses Node.js 24.

Add the provider to your existing Payment Module configuration in :

Configure the backend's private environment:

These are placeholders. Never commit actual credentials or expose the secret or webhook secret to a frontend. The key ID is public checkout configuration. Set explicitly to or : the key ID must begin with the matching or prefix and a nonempty API secret is required. Missing/unknown modes, malformed IDs and mismatches fail before network access; the plugin never infers live mode from a key. This validates configuration shape, not whether the key/secret pair is valid at Razorpay.

For live configuration, use , a matching live key ID and that environment's API and webhook secrets. Live provider initialization requires a nonempty webhook secret. Test mode may omit it for initial Admin setup, but webhook delivery always fails closed without a valid secret. Use separate deployments/data, credentials and webhook endpoints/secrets for test and live; do not switch an existing test database into live processing. See account modes.

Start the backend through your application's normal workflow. In Admin → Settings → Regions → your region, select the Razorpay payment provider. This registration produces provider ID . Registration alone does not associate it with a region. There is no enabled/disabled environment toggle and no custom Admin menu or plugin migration.

Storefront checkout

  1. Create/select a native Medusa payment session using .
  2. Initialize Razorpay Checkout using the session's public , , (paise) and ().
  3. Submit , and through Medusa's Store payment-session client-data endpoint (). Keep the stored server session fields authoritative.
  4. Complete the cart through your backend's normal ownership, cart-total and acceptance checks. While automatic capture is pending, wait/reconcile rather than treating authorization as a completed payment.

The provider includes no checkout widget and makes no blanket promise about individual Razorpay payment methods. Available methods depend on the merchant account and Checkout configuration. Enforce application rules on the server: native payment webhooks may complete carts without the browser returning.

Webhooks

For the example registration above, use your backend's public HTTPS origin with:

/hooks/payment/razorpay_razorpay

Subscribe to and in the matching Razorpay account and mode. Preserve the exact raw request bytes and header. The provider verifies HMAC signatures and fetches current gateway state, making repeated and out-of-order notifications safe to re-evaluate. and other unsupported payment events are ignored; they do not invalidate a later checkout attempt.

For refund observation, also subscribe to , , and , and wire the exported server helpers into an application subscriber. These events require an application subscriber calling the importer; provider registration alone does not import accounting. A speed change updates informational observations only; it never means settlement or initiates a refund.

See server integration for the helper contract, shared locking hook and subscriber requirements. Use durable Medusa event infrastructure and monitor failed jobs; HTTP acknowledgement is not proof of successful reconciliation.

Refunds and reconciliation

Initiate refunds through Medusa's native refund workflow and preserve the operation identity. A synchronously processed response completes normally. A pending gateway response returns an explanatory conflict and remains outside successful native refund accounting. Wire the signed refund subscriber below: a later processed event imports one successful native refund, while a later failed event creates no successful refund accounting. The original native failed attempt remains as audit evidence; it does not mean the gateway request failed. Do not issue a new operation merely to retry a pending request. is an immutable processed-response snapshot, not proof of bank receipt.

The exported reconciliation helpers compare authenticated gateway payment/order/refund information with native records. The read-only report helpers never change records. The optional importer uses native financial APIs only for individually verified processed Dashboard and deferred native refunds and rejects ambiguous associations. Review discrepancies before retrying an uncertain request. Applications can supply a and a common distributed lock covering the session and its associated order to coordinate refund execution, observation and order completion.

Read operations and validation for pending/failed refund handling, uncertain outcomes, monitoring and test limits. The exported and helpers provide a controlled operator path for supported processed-refund imports, with reviewed snapshots, application-enforced maintenance controls and post-recovery accounting checks. Original pending reservations remain quarantined. Known incomplete canonical accounting requires the operator path; automatic takeover scheduling is disabled.

Logging

Set provider option to , (default), , , , or . Thresholds include the selected level and higher severities. emits no plugin log records. JSON records contain , a clear , and . The simple shared logger uses Medusa's injected logger, with a console fallback. Warning uses the sink; critical uses while retaining its JSON severity.

All API calls use one typed HTTP client with , , , and . Authentication, timeout, parsing, and request/response logging live in its single executor. Callers do not add HTTP logging code or classifications. Request context includes the complete supplied API path (including pagination), method, a local correlation UUID and timing. Paths contain opaque gateway resource IDs; these are included as requested.

Debug records receive the complete request body and provider response, including unknown response keys. There is no provider-field extraction or event-schema framework. Authentication headers are never supplied to the logger. Redaction is intentionally not implemented for the current debugging stage. Raw debug bodies can contain personal or sensitive data. Restrict access and retention, and use test data. Keep live deployments at or higher (or ); raw payloads are not suitable for routine live logging. Authentication headers and configured credentials are not intentionally added to log context; an upstream response or caller-supplied body can still contain sensitive values. Other levels omit request/response bodies.

Common API client

takes a named object with explicit , matching credentials, optional Medusa logger, log level, timeout and injectable for isolated testing. The base host is fixed, redirects are rejected, authentication cannot be overridden by custom headers, and timeout is bounded at 15 seconds. Reconciliation uses its GET-only adapter with a 30-second aggregate deadline. The compatibility method delegates to the same executor; plugin internals use explicit verbs.

has typed method, failure kind and optional HTTP status. Transport failures are generic; response errors remain distinct from HTTP errors. No HTTP method retries automatically. is a precaution on failed writes, not proof of a mismatch or a completed reconciliation. GET failures set it false. A successful HTTP response does not establish refund settlement.

Development

Run project commands through Docker Compose:

Prettier checks the repository, including documentation and configuration; and define the shared editor style. Generated files, private environment files and local scratch files are ignored. To apply formatting to the checkout, use the tools container with the repository mounted at and its image dependencies available, or the Compose bootstrap service after installing development dependencies.

Typecheck validates both the published source and unit tests. The test project matches Vitest's ESM resolution; malformed runtime fixture values remain explicit test boundaries. The scripts under are consuming-Medusa integration fixtures and resolve/run inside that application's isolated test environment, not the standalone unit-test project.

The GitHub workflow runs formatting, lint, typecheck and build as separately visible checks, reusing the Node CI and security workflows from . Each unit suite runs independently in its own matrix job and uploads JUnit XML. Reproduce a selected suite locally with . These self-contained suites use mocked gateway/service fixtures and do not perform gateway transactions. Hosted results and consuming-application integration evidence remain separate from local unit checks.

Rejected refund requests

A refund POST rejected with HTTP 400 raises (, code ). Medusa Admin can show its actionable message instead of a generic server error. The message asks operators to verify the refund status and available balance before retrying. HTTP 400 alone does not establish insufficient balance. Transport failures and other uncertain responses retain reconciliation handling; the provider never retries a refund automatically.

License

MIT © Abhimanyu Saharan.