Receiving payments
Enable UPI & bank transfer in Settings → Payment providers. Add the seller’s bank-issued UPI ID, bank account details, or both. Checkout shows a UPI QR and app link, or copyable bank instructions for IMPS and NEFT. RTGS is also shown for payments of at least ₹200,000. The seller receives INR directly; OurPay does not receive or hold that money. The buyer-facing UPI ID masks the middle of the account identifier, showing its first two and last three characters plus the bank handle, for example83*****779@ybl. Short identifiers are fully masked. There is no UPI ID copy or
reveal control. The QR and app link still contain the full receiving ID to route
the payment; display masking does not hide it from the payment app or QR decoding.
New domestic payment requests include an OurPay order reference before payment.
The same reference appears in the QR’s transaction reference, the buyer’s payment
instructions, and Finance → Collections. The UPI payment note contains only the
product name at the time the request is created, without an added reference or prefix.
OurPay’s 64-character product-name limit fits within
Google Pay’s 80-character transaction-note limit.
Existing requests retain their original note, reference, and receiving instructions,
including after a product is renamed. The QR screen identifies the seller;
the UPI app displays the recipient identity registered with their bank. OurPay branding
does not replace that bank identity.
The OurPay order reference identifies the payment request. It is separate from the bank
reference / UTR issued after payment and cannot be submitted as proof of a bank receipt.
Add an INR price to the product. Multi-currency checkouts include a Payment currency
selector and refresh the available payment methods when the buyer changes currency.
Append ?currency=inr to a checkout link to open it in INR directly. The product must
have an INR price; unsupported currencies are rejected rather than converted.
The buyer can submit a bank reference after paying. This is a request for verification, not proof
of payment. In Finance → Collections, the seller checks their statement, selects the actual
payment method, and confirms the reference and full amount. This completes the native OurPay
order. Repeating the same confirmation is safe; a reference cannot fund another order for the
same receiving account.
Owners and admins can configure receiving details and confirm receipts. Finance-role members
can review the inbox; ordinary members cannot access collection financial details.
UPI QR/intent generation needs no commercial gateway integration. Automatic bank confirmation
requires an authenticated connection to the seller’s bank. This implementation supplies the
receipt interface below; it does not claim access to a public NPCI transaction-status API.
Bank and network charges, where applicable, are separate from OurPay’s integration.
NPCI’s merchant FAQ describes the acquiring-bank
relationship. RBI’s RTGS FAQ specifies its minimum.
Native USDC across networks
One-time checkout can accept native Circle-issued USDC on Polygon, Base, Arbitrum, Ethereum, OP Mainnet, Avalanche, Linea, Monad, HyperEVM, Unichain, World Chain, Sei, and Solana. Enable USDC in the seller’s payment settings. The buyer connects a wallet and checkout checks supported networks for enough native USDC and estimated gas. It selects a funded network, preferring the wallet’s current EVM network when that network can pay. Buyers can review the chosen network and change it before signing. When the connected wallet also supports Solana, checkout can request its Solana account if no checked EVM network can pay. Balance discovery uses the invoice’s native-token allowlist through the backend, with bounded RPC timeouts. An unavailable RPC is shown as an unknown balance, not a zero balance. Gas checks are estimates: EVM uses a buffered execution estimate, and Solana includes a fee reserve and the receiving token-account deposit when needed. Wallet fees, including rollup data fees, can change. The wallet shows the final transaction before approval. A submitted transaction keeps its original network after reload, and discovery never authorizes or submits a payment. This flow neither bridges nor swaps assets. Receipts remain in the operator’s wallet on the network the buyer used. The current network and token allowlist is inserver/ourpay/integrations/usdc/networks.py, based on
Circle’s native USDC registry.
Other tokens, bridged USDC, BNB Chain, Tron, and Bitcoin are not accepted by this adapter.
The operator configures public receiving addresses in the API, worker, and scheduler:
POST /v1/payment-collections/client/{client_secret}/usdc/prepareverifies the sender signature and returns a recent Solana blockhash when needed.POST /v1/payment-collections/client/{client_secret}/usdc/transactionrecords the hash for reconciliation. Repeated submission of the same hash is idempotent.
uv run python -m scripts.usdc_preflight with the proposed public-address config.
Only then enable new invoices across API, worker, and scheduler. Disabling the flag stops new
native-USDC invoices; keep this adapter deployed to reconcile existing ones. Preserve any
existing Bitcart configuration and services for outstanding legacy invoices. There is no
database migration specific to this adapter. Automatic subscriptions use separately configured EVM deployments.
Legacy Bitcart invoices
Production uses direct native-USDC verification and subscription contracts.OURPAY_BITCART_ENABLED=false; a Bitcart server is not required. The old deployment
was retired after checking legacy invoices and archiving its database.
The internal bitcart processor identifier and existing receipt records remain
compatible with older API clients. This identifier does not mean a new payment
uses the Bitcart gateway. Operators with a separate legacy deployment must reconcile
outstanding invoices and save their records before retiring its services.
What appears in OurPay
Verified receipts use the existing checkout-success flow, including:- Paid orders and payment attempts in Sales and customer order history.
- Organization-issued invoice numbers, invoices, and downloadable receipts.
- Discounts, quantities, metadata, customer details, and existing tax calculation when configured.
- Normal order/payment reporting, events, webhooks, emails, and product benefit grants.
- A Collections inbox with pending receipts, customer references, asset/network details, verification source, and links to completed orders.
Automatic USDC subscriptions
An optional Polygon contract supports fixed USD subscriptions paid in native USDC. This feature stays disabled until the operator deploys and verifies the contract and configures a dedicated relayer with POL for gas. Existing one-time collections do not use the subscription contract.- Checkout shows the first payment, maximum USDC per renewal, calendar interval, and finite payment count. The default authorization covers 12 payments, including the first.
- The buyer connects their wallet, grants a limited USDC allowance, and authorizes the subscription. Authorization also transfers the first payment to OurPay’s receiving wallet.
- OurPay verifies the finalized transfer before creating the subscription and paid order. The normal billing scheduler creates future invoices and the relayer submits each renewal. The buyer does not sign every month, provided the mandate, balance and allowance remain valid.
- Cancellation in the customer portal stops future billing and queues permanent on-chain cancellation. The buyer can also cancel directly through the contract. A transaction already being processed may still settle; access continues through the paid period.
contracts/README.md. The API exposes
subscription wallet instructions through the existing payment-collection endpoint and accepts
the submitted transaction hash at POST /v1/payment-collections/client/{client_secret}/crypto-subscription.
This client-secret endpoint is used by hosted checkout; it does not replace on-chain verification.
Bank receipt adapter
This is OurPay’s internal adapter contract. A bank-specific connector must first authenticate the bank’s notification or status response using that bank’s issued integration specification. Indian Bank onboarding is being evaluated; no Indian Bank connector or API access is configured. Operator preparation is documented ininfra/indian-bank/.
Set OURPAY_DOMESTIC_BANK_WEBHOOK_SECRET only on the operator API and the trusted bank adapter.
After independently verifying a credited transfer with the bank, the adapter posts:
timestamp + "." + raw_request_body using SHA-256. Timestamps must be within
five minutes. amount is integer paise. payee must match the snapshotted UPI ID, or the account
number when method is bank_transfer. Mismatched amounts are rejected; repeat receipts are
idempotent. Never issue signatures for buyer-supplied references or screenshots.
An authenticated bank receipt can complete the order without buyer reference submission
or seller confirmation. The bank supplies the transaction identifier. Without a connected
bank adapter, payment continues to require the seller’s verification.
Deployment and verification
Apply the additive Alembic migration before starting the new API and worker, regenerate the client, and deploy the frontend with the API. The worker registerspayment_collection.reconcile
and the minute-based recovery task. Keep wallet credentials in deployment secrets and use TLS
between deployments. No Bitcart secrets are returned by the checkout API.
Gateway-dependent tests mock the provider transport and exercise real OurPay order creation.
They do not demonstrate a live blockchain receipt. Before accepting live funds, configure the
operator’s actual wallets and perform a controlled end-to-end receipt check for each enabled
network. Domestic automatic confirmation also needs a real bank adapter; seller confirmation is
available without it.
Implementation references
- Bitcart: multi-asset invoices and monitoring.
- BTCPay Server: Bitcoin checkout reference.
- Hyperswitch: capability-based payment routing reference.
- Medusa manual payments: manual receipt workflow reference.