{"_id":"@akshay4362/cashfree-plugin","name":"@akshay4362/cashfree-plugin","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@akshay4362/cashfree-plugin","version":"1.0.0","license":"GPL-3.0-or-later","main":"lib/index.js","types":"lib/index.d.ts","private":false,"scripts":{"watch":"tsc -p ./tsconfig.build.json --watch","build":"rimraf lib && tsc -p ./tsconfig.build.json","e2e":"cross-env PACKAGE=cashfree-plugin vitest --config ../../e2e-common/vitest.config.mts --run","e2e:watch":"cross-env PACKAGE=cashfree-plugin vitest --config ../../e2e-common/vitest.config.mts","lint":"eslint .","ci":"npm run build","dev-server":"npm run build && DB=sqlite node -r ts-node/register e2e/cashfree-dev-server.ts"},"homepage":"https://www.vendure.io/","funding":"https://github.com/sponsors/michaelbromley","publishConfig":{"access":"public"},"peerDependencies":{"@vendure/core":"^3.6.0-0","@vendure/common":"^3.6.0-0","cashfree-pg":"^6.x"},"devDependencies":{"@vendure/admin-ui-plugin":"3.6.0-minor-202603280303","@vendure/common":"3.6.0-minor-202603280303","@vendure/core":"3.6.0-minor-202603280303","@vendure/testing":"3.6.0-minor-202603280303","cashfree-pg":"^6.0.5","nock":"^13.1.4","rimraf":"^5.0.5","typescript":"5.8.2"},"_id":"@akshay4362/cashfree-plugin@1.0.0","gitHead":"5a22d86756e7aee3903f4d87b011f7124025327b","description":"Plugin to enable payments through [Cashfree](https://www.cashfree.com/docs/payments/overview) via the Orders API and the Cashfree Checkout JS SDK.","_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-Rk+seYQhwKoG5vNBvLJstbl0WKfrDBbaLQc7AiMrpCBpZhr67QpFs3KihvRSb1h7sd63V4GMNOjtKHkB48q66A==","shasum":"0253c5b5128f430587a77a6e1dd847c710c356fa","tarball":"https://registry.npmjs.org/@akshay4362/cashfree-plugin/-/cashfree-plugin-1.0.0.tgz","fileCount":38,"unpackedSize":72718,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDu4nBacK5s7Na0A6Qzt4mlRl1MzZUdyLd7Cr1ikaXcjQIgNASdtqVnmrl/yirAT+FVY7cD1vKVVfP24XKbmHozyGc="}]},"_npmUser":{"name":"akshay4362","email":"akshay.t@softobotics.com"},"directories":{},"maintainers":[{"name":"akshay4362","email":"akshay.t@softobotics.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cashfree-plugin_1.0.0_1788854728518_0.08266628299872703"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-08T08:05:28.340Z","1.0.0":"2026-09-08T08:05:28.642Z","modified":"2026-09-08T08:05:28.866Z"},"maintainers":[{"name":"akshay4362","email":"akshay.t@softobotics.com"}],"description":"Plugin to enable payments through [Cashfree](https://www.cashfree.com/docs/payments/overview) via the Orders API and the Cashfree Checkout JS SDK.","homepage":"https://www.vendure.io/","license":"GPL-3.0-or-later","readme":"# Cashfree Payment Plugin\n\nPlugin to enable payments through [Cashfree](https://www.cashfree.com/docs/payments/overview) via the Orders\nAPI and the Cashfree Checkout JS SDK.\n\n## Requirements\n\n1. You will need a Cashfree Merchant Dashboard account and your Client ID / Client Secret (Developers ->\n   API Keys).\n2. Register a webhook in the Cashfree Merchant Dashboard (Developers -> Webhooks) which listens to the\n   `PAYMENT_SUCCESS_WEBHOOK`, `PAYMENT_FAILED_WEBHOOK`, `REFUND_STATUS_WEBHOOK`, and\n   `AUTO_REFUND_STATUS_WEBHOOK` events. The URL should be `https://my-server.com/payments/cashfree`, where\n   `my-server.com` is the host of your Vendure server.\n3. Install the plugin and the Cashfree Node SDK:\n\n    ```shell\n    npm install @vendure-community/cashfree-plugin cashfree-pg\n    ```\n\n## Setup\n\n1. Add the plugin to your VendureConfig `plugins` array:\n    ```ts\n    import { CashfreePlugin } from '@vendure-community/cashfree-plugin';\n\n    // ...\n\n    plugins: [\n      CashfreePlugin.init({\n        // optional: see the CashfreePluginOptions type for refundSpeed\n      }),\n    ]\n    ```\n2. Create a new PaymentMethod in the Admin UI, and select \"Cashfree payments\" as the handler.\n3. Set the \"Client ID\", \"Client Secret\", and \"Environment\" (Sandbox/Production) arguments on the\n   PaymentMethod form. Each PaymentMethod using the Cashfree handler can be configured with its own Cashfree\n   account, so different channels/PaymentMethods can point at different accounts. Only one enabled\n   PaymentMethod using the Cashfree handler is supported per channel at a time.\n\n## Storefront Usage\n\n1. Call the `createCashfreeOrder` mutation to create a Cashfree Order for the active order, returning\n   `{ orderId, paymentSessionId, environment }`.\n2. Load the [Cashfree Checkout JS SDK](https://www.cashfree.com/docs/tools-ai/sdk) and open the checkout\n   modal:\n   ```js\n   const cashfree = await load({ mode: environment.toLowerCase() }); // 'sandbox' | 'production'\n   const result = await cashfree.checkout({\n     paymentSessionId,\n     redirectTarget: '_modal',\n   });\n   ```\n3. Once the modal resolves, call Vendure's standard `addPaymentToOrder` mutation with:\n   ```json\n   {\n     \"method\": \"<your payment method code>\",\n     \"metadata\": {\n       \"cfOrderId\": \"<orderId from createCashfreeOrder>\"\n     }\n   }\n   ```\n   The plugin does not trust the client-side checkout result (Cashfree's client-side flow carries no signed\n   proof equivalent to Razorpay's `razorpay_signature`); instead it independently fetches the order's\n   payments from the Cashfree API server-side and only settles once a payment with `payment_status: 'SUCCESS'`\n   and a matching amount is found.\n\nThe `/payments/cashfree` webhook acts as a reconciliation backstop only - it settles the order if the\nstorefront's `addPaymentToOrder` call never completes (e.g. the browser tab closed after payment).\n\n## Multi-channel / multi-account support\n\nLike the Razorpay plugin, each channel can have its own Cashfree PaymentMethod - so different channels/storefronts\ncan point at entirely different Cashfree accounts (own Client ID/Secret/Environment). This works because\n`CashfreeService.resolveForOrder` resolves the PaymentMethod (and therefore the credentials) from a\nchannel-scoped `RequestContext`, not from any plugin-wide configuration.\n\nWebhook routing is channel-aware too:\n\n- **Payment webhooks** echo back the `order_tags` set at order-creation time (`channelToken`/`languageCode`),\n  so the channel is identified directly from the payload.\n- **Refund webhooks** (`REFUND_STATUS_WEBHOOK` / `AUTO_REFUND_STATUS_WEBHOOK`) carry no such custom metadata,\n  since Cashfree's Refunds API has no arbitrary metadata field. Instead, the controller looks up which\n  channel the order actually belongs to directly (`cashfree.controller.ts#resolveChannelTokenForOrderCode`)\n  and verifies the webhook signature against that channel's PaymentMethod credentials - so refunds reconcile\n  correctly regardless of which channel/account processed the original payment.\n\n## Refunds\n\nCreating a refund via the Admin UI (or the `refundOrder` mutation) calls the\n[Cashfree Refunds API](https://www.cashfree.com/docs/api-reference/payments/latest/refunds/create-refund). By\ndefault, refunds are processed at Cashfree's `'STANDARD'` speed; set the `refundSpeed` plugin option to\n`'INSTANT'` to attempt an instant refund where supported, falling back to standard processing otherwise.\n\nBecause a refund can return `refund_status: 'PENDING'` or `'ONHOLD'`, the plugin registers a custom refund\nprocess that permits a `Pending -> Pending` self-transition (Vendure's default process only allows\n`Pending -> Settled | Failed`). The `/payments/cashfree` webhook then reconciles the refund to `Settled` or\n`Failed` once Cashfree sends the corresponding webhook event.\n\n## Local Development\n\nSet `CASHFREE_CLIENT_ID` and `CASHFREE_CLIENT_SECRET` in a `.env` file in this package (these seed the\ndev-server's Cashfree PaymentMethod handler arguments, not `CashfreePlugin.init()`), then run:\n\n```shell\nnpm run dev-server\n```\n","readmeFilename":"README.md","_rev":"1-638aac34f001bc8090c49facb0ad7af4"}