A Drupal Commerce 2.x offsite payment gateway for the U.CASH Pay platform. Buyers are redirected to the hosted pay.u.cash checkout, pay in their preferred cryptocurrency, and the order is settled through an HMAC-signed webhook.
Non-custodial: this module never sees funds or private keys. The payment happens at pay.u.cash; the module only creates the checkout, listens for the webhook, and marks the local order paid.
- Drupal 9 or 10
- Commerce 2.x (commerce_payment, commerce_order, commerce_checkout)
- PHP 7.4+ with cURL
-
Copy this directory to
web/modules/contrib/ucashpay(ormodules/custom/ucashpay). -
Enable the module at
Extend(/admin/modules) or via Drush:drush en ucashpay -y -
Clear caches:
drush cr
-
Create a store on pay.u.cash and copy the store cloud token and webhook secret from Account > Stores.
-
In your Drupal Commerce store, go to Commerce > Configuration > Payment gateways (
/admin/commerce/config/payment-gateways) and add a new U.CASH Pay gateway. -
Fill in:
- Store cloud token: the publishable cloud token from pay.u.cash.
- Webhook secret: the HMAC signing secret from pay.u.cash.
- U.CASH platform URL: leave as
https://pay.u.cashunless self-hosted. - Button label: the checkout redirect button text (optional).
The configuration form displays the Webhook URL to copy into pay.u.cash. It is of the form:
https://your-store.example/ucashpay/webhook -
On pay.u.cash, set the store webhook URL to the value above. The webhook must be reachable from the public internet.
-
Enable the gateway for your checkout flow at Commerce > Configuration > Checkout flows.
- Checkout selection: the buyer chooses U.CASH Pay on the payment step.
The offsite form auto-submits to
/checkout/{order}/ucashpay/redirect. - Server-side checkout creation: the redirect controller calls the shared
PayUCashIntegrationSDK to create a pay.u.cash transaction viacreate-transaction, provisions a local Commerce payment in theauthorizationstate, then issues a 302 to the returnedpayment_url. - Buyer pays at the hosted pay.u.cash checkout in their chosen coin.
- Webhook settlement: pay.u.cash POSTs an HMAC-signed event to
/ucashpay/webhook.onNotify()verifies the signature, enforces event idempotency via Drupal key/value expirable storage (one hour window), resolves the local payment byexternal_reference(of the formcommerce_order:{id}), and transitions it tocompleted. - Buyer returns:
onReturn()is called when the buyer lands back on the store. It shows a success or pending message; the webhook is the source of truth for final settlement so a slightly delayed webhook is never a false failure on the thank-you page.
| File | Purpose |
|---|---|
ucashpay.info.yml |
Module info. |
ucashpay.module |
hook_commerce_payment_gateway_info() registration + help. |
ucashpay.routing.yml |
Redirect controller + webhook notify routes. |
ucashpay.libraries.yml |
Auto-submit JS library. |
PayUCashIntegration.php |
Shared, platform-agnostic SDK (curl, no deps). |
src/Plugin/Commerce/PaymentGateway/UcashPay.php |
The gateway plugin: config, onReturn, onNotify, payment provisioning. |
src/PluginForm/UcashPayOffsiteForm.php |
The offsite redirect form rendered on the checkout pane. |
src/Controller/RedirectController.php |
Server-side checkout creation + 302 to pay.u.cash. |
src/PluginForm/WebhookController.php |
Anonymous webhook dispatch shim to the gateway onNotify(). |
js/ucashpay-auto-submit.js |
Auto-submits the offsite form on load. |
- The webhook signature is verified with HMAC-SHA256 plus a 300-second
timestamp window, using
hash_equalsfor constant-time comparison. - Webhook events are de-duplicated by event id for one hour to prevent replays.
- The redirect controller is access-checked against order ownership; anonymous carts are allowed only during the active checkout session.
- The webhook secret and cloud token are stored in the gateway's encrypted configuration through Commerce's standard plugin configuration API.
MIT. The shared PayUCashIntegration.php SDK is also MIT.