@codemind.ec/medusa-plugin-bank-transfer
v1.0.2
Published
Bank transfer payment provider for Medusa v2 — multi-account management, receipt uploads, and order payment tracking.
Maintainers
Readme
@codemind.ec/medusa-plugin-bank-transfer
Bank transfer payment provider for Medusa v2 — multi-account management, receipt uploads, image compression, and automated email notifications.
Features
- Multiple bank accounts — create, update, reorder, and toggle active/inactive accounts via admin API.
- Payment provider — full lifecycle: initiate → authorize → capture → refund → cancel.
- Receipt upload — customers upload payment receipts (images/PDFs) from the storefront; images are automatically compressed (JPEG, 1600px max, quality 80).
- Email notifications — automatic transactional emails to customer & admin on first receipt upload (requires a notification provider like Listmonk).
- Admin UI widgets — manage bank accounts and view receipts directly in the Medusa admin dashboard.
- Store API — public endpoint for active bank accounts (cached 5 min) and receipt upload.
Prerequisites
| Requirement | Version | |-------------|---------| | Node.js | >= 20 | | Medusa | >= 2.4.0 |
Installation
npm install @codemind.ec/medusa-plugin-bank-transfer
# or
pnpm add @codemind.ec/medusa-plugin-bank-transferConfiguration
Add the plugin and its modules to your medusa-config.ts:
import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig({
// ...
modules: [
// Bank accounts module (CRUD de cuentas bancarias)
{
resolve: "@codemind.ec/medusa-plugin-bank-transfer/bank-accounts",
definition: { isQueryable: true },
},
// Payment receipt module (comprobantes de pago)
{
resolve: "@codemind.ec/medusa-plugin-bank-transfer/payment-receipt",
definition: { isQueryable: true },
},
// Payment provider
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "@codemind.ec/medusa-plugin-bank-transfer/payment",
id: "bank-transfer",
options: {},
},
],
},
},
],
plugins: [
{
resolve: "@codemind.ec/medusa-plugin-bank-transfer",
options: {},
},
],
})Nota: El plugin necesita tres registros en
modules[](bank-accounts, payment-receipt, y el payment provider) además de la entrada enplugins[]que carga admin UI, API routes y subscribers.
Environment Variables (optional)
These are used by the receipt-upload email templates:
| Variable | Description | Default |
|----------|-------------|---------|
| ADMIN_EMAIL | Admin email for receipt notifications | — |
| BRAND_COLOR | Brand hex color for email templates | #049839 |
| BRAND_LOGO | Logo URL for email headers | — |
| STORE_URL | Storefront base URL | — |
| BACKEND_URL | Medusa backend URL | — |
| ADMIN_URL | Admin dashboard URL | — |
| WHATSAPP_NUMBER | WhatsApp number shown in emails | — |
Architecture
Modules
bank-accounts
Manages bank account records customers reference when making transfers.
| Field | Type | Description |
|-------|------|-------------|
| id | string | Primary key |
| bank_name | string | Bank name |
| account_type | "savings" | "checking" | Account type |
| account_number | string | Account number |
| account_holder | string | Account holder name |
| identification | string? | ID / tax number |
| is_active | boolean | Active flag (default true) |
| display_order | number | Sort order (default 0) |
| metadata | JSON? | Extra data |
payment-receipt
Stores uploaded receipt files linked to payment collections and orders.
| Field | Type | Description |
|-------|------|-------------|
| id | string | Primary key |
| payment_collection_id | string | Associated payment collection |
| order_id | string? | Associated order |
| file_url | string | Receipt file URL |
| file_id | string? | File module reference |
| original_filename | string? | Original upload name |
| mime_type | string? | MIME type |
| file_size | number? | File size in bytes |
| uploaded_by | "customer" | "admin" | Upload source |
Payment Provider
Identifier: bank-transfer
| Lifecycle Method | Behavior |
|-----------------|----------|
| initiatePayment() | Creates session with status pending, reference PED-{sessionId} |
| authorizePayment() | Transitions to authorized |
| capturePayment() | Requires receipt_url in payment.data |
| cancelPayment() | Sets status to canceled |
| refundPayment() | Records refund_amount |
| getPaymentStatus() | Evaluates timestamps: captured_at → canceled_at → authorized_at |
API Reference
Admin Routes
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /admin/bank-accounts | Create a bank account |
| GET | /admin/bank-accounts | List all accounts (sorted by display_order) |
| GET | /admin/bank-accounts/:id | Get a single account |
| PUT | /admin/bank-accounts/:id | Update an account (partial) |
| DELETE | /admin/bank-accounts/:id | Delete an account |
| POST | /admin/orders/:id/receipt | Admin receipt upload |
Store Routes
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /store/bank-accounts | List active accounts (public, cached 5 min) |
| POST | /store/orders/:id/receipt | Upload payment receipt (multipart, max 5 MB) |
| POST | /store/payment-collections/:id/receipt | Upload receipt by payment collection |
Upload a Receipt
curl -X POST https://your-backend.com/store/orders/{order_id}/receipt \
-H "Content-Type: multipart/form-data" \
-F "[email protected]"What happens on upload:
- If the file is an image, it's compressed to JPEG (1600 px max width, quality 80).
- The filename is sanitized (accents and special characters removed).
- The file is saved via Medusa's File module.
order.metadata.receipt_urlis updated.- Each bank-transfer payment's
data.receipt_urlis updated. - Events
order.receipt_uploadedandpayment.receipt_uploadedare emitted.
Events
| Event | Trigger |
|-------|---------|
| order.receipt_uploaded | First receipt upload for an order |
| payment.receipt_uploaded | Receipt linked to a payment |
The built-in subscriber sends email notifications to both the customer and admin on the first upload, with exponential backoff retry (3 attempts).
TypeScript Exports
import type {
BankAccountDTO,
CreateBankAccountData,
UpdateBankAccountData,
PaymentReceiptDTO,
CreatePaymentReceiptData,
} from "@codemind.ec/medusa-plugin-bank-transfer"
// Module re-exports
import BankAccountModule from "@codemind.ec/medusa-plugin-bank-transfer/modules/bank-accounts"
import PaymentReceiptModule from "@codemind.ec/medusa-plugin-bank-transfer/modules/payment-receipt"
// Workflows
import { workflows } from "@codemind.ec/medusa-plugin-bank-transfer/workflows"Validation
All admin inputs are validated with Zod schemas:
bank_name— non-empty stringaccount_type—"savings"or"checking"account_number— non-empty stringaccount_holder— non-empty stringidentification— optional stringis_active— optional booleandisplay_order— optional numbermetadata— optional JSON object
License
MIT — CodeMind
