NewVerification layer for wallet payments. DPay can now apply a small adjustment to the amount wallet payers are asked to send, so same-amount payments verify automatically instead of waiting for manual review. Recommended — enable it in Settings. amount_paid reports what was received.Read more

DPay for WooCommerce

Take Easypaisa, JazzCash, NayaPay and bank-transfer payments on a WordPress shop, verified automatically, straight into your own account. No code: install the plugin, paste one key, done.

Download: dpay-for-woocommerce.zip · version 1.0.1 · GPL-2.0 · needs WordPress 6.2+, WooCommerce 7.6+, PHP 7.4+.

What it does

  • Adds Bank transfer / Easypaisa / JazzCash as a payment method, with the DPay logo, in both the classic checkout and the block checkout.
  • Sends the customer to DPay's hosted checkout for the order total. Paisa is rounded up to whole rupees (PKR 1,850.50 becomes PKR 1,851), because no Pakistani transfer carries paisa; the order note records what was paid.
  • Marks the order paid the moment DPay verifies the transfer from your bank's alert — three ways, so it works even where webhooks cannot reach: the signed webhook, the customer coming back to the order page (which then refreshes itself until confirmed), and a sync every five minutes for any order still pending.
  • Puts the DPay reference, the customer's bank and the status on the order, with a Check with DPay now button and a link to the payment in your DPay dashboard.
  • Registers its webhook with DPay by itself when you save the key, and rotates the secret if the site is reinstalled.
  • Supports High-Performance Order Storage (HPOS) and the block cart and checkout.

Nothing about the money passes through the plugin or through DPay: the customer transfers into your own NayaPay or Meezan account, DPay only proves it arrived.

Before you start

  1. A DPay account at dpay.com.pk with a receiving account (NayaPay recommended: alerts arrive in seconds) and the Gmail inbox its alerts land in connected under Integrations.
  2. An API key from Developers. A test key (dpay_test_sk_…) runs the whole flow without moving money; a live key (dpay_live_sk_…) needs a paid plan and takes real payments.
  3. The shop's currency set to PKR (WooCommerce → Settings → General). DPay is not offered at checkout in any other currency.

Install

  1. Download dpay-for-woocommerce.zip.
  2. In WordPress: Plugins → Add New → Upload Plugin, choose the zip, Install Now, then Activate.
  3. WooCommerce → Settings → Payments → DPay (or the *Settings* link under the plugin on the Plugins screen).
  4. Paste the API key and Save changes. The status panel at the top should now read Connected · your business name, and Webhook · Registered with your site's address.
  5. On Developers → Webhooks, press Send test event next to your site. The settings page shows *Last event received* once it lands.

That is the whole setup. The title and description shown to customers, how long a checkout waits for the transfer (15 minutes by default, up to 24 hours), and the checkout popup are on the same page.

The checkout popup

On a desktop browser the DPay payment page opens in a window over your checkout, so the customer never leaves your shop: pick a bank, see the account to pay into, and the moment the transfer is verified the popup closes onto your order-received page. On a phone the customer is taken to the payment page itself — that is where switching to Easypaisa or a banking app and back works best. Closing the popup lands on the order-received page too, which keeps checking for the transfer and offers a way back to the payment page or to another method. Untick *Checkout popup* in the gateway settings to always redirect instead.

The popup loads the payment page at ?embed=1; it only renders inside a page on the site that created the session, and the messages it sends your page carry the session id and status alone — the order is still confirmed by asking DPay, never by the popup.

Try it before going live

With a test key, place an order on your own shop. You land on DPay's checkout with the order total and a reference like DPAY-8F4K29. Nothing to pay: open the DPay dashboard → Integrations → Inbox simulator, deliver an alert for that payment, and watch the WooCommerce order turn *Processing* with the note *"DPay verified the transfer…"*. Then swap in the live key.

How an order moves

What happensWooCommerce order
Customer presses *Pay by bank transfer*Pending payment, note with the DPay reference; customer is on DPay's checkout (in the popup on desktop)
Transfer verifiedProcessing (or *Completed* for virtual goods), payment_complete() with the DPay session id as transaction id
DPay finds two transfers that could both be this paymentOn hold, note asking you to pick one in the DPay dashboard; the order updates itself when you do
Customer transfers a little more than the orderOn hold for review in the DPay dashboard, with the extra flagged — accept it (and refund the difference) or reject; if the exact amount also arrives it settles on its own
Checkout window closed without a transferstays Pending with a note; the customer can pay again from *My account → Orders*, and a late transfer honoured in DPay still lands
Customer presses *cancel* on DPaystays Pending; they are returned to the order's pay page with a notice
Payment failed at DPayFailed
Refund or dispute recorded at DPaynote on the order (refunds are transfers you make from your own bank; record them in WooCommerce as usual)

A customer who comes back to pay a pending order gets the same DPay checkout and reference while it is still open; a new one only once it has closed.

The received amount

With *Verification layer for wallet payments* on in your DPay Settings (recommended), DPay may apply a small adjustment to the amount a customer paying from a wallet is asked to send, so payments of the same amount verify automatically instead of waiting for your manual review. The order note and the _dpay_paid_amount meta record what DPay actually received; the order is still marked paid in full. Reconcile your bank statement against that figure. The setting is off until you enable it, and customers are never told how the amount is chosen.

If the webhook cannot reach your site

Some hosts block the WordPress REST API, some sites sit behind a login or a firewall. The plugin does not depend on the webhook: the customer's return to the order page checks with DPay at once, and every pending DPay order is checked every five minutes by WP-Cron. Orders confirm a little later, not never. The settings page tells you whether a webhook has ever arrived.

If WP-Cron is disabled on your host (DISABLE_WP_CRON), make sure a system cron hits wp-cron.php, as WooCommerce itself already needs.

Where things are

  • Logs: WooCommerce → Status → Logs → source dpay.
  • Order screen: the *DPay* box on the right shows the reference, status, bank and amount, with *Check with DPay now* and *Open in DPay*.
  • Options: woocommerce_dpay_settings (the settings), dpay_wc_webhook (endpoint id, URL and signing secret), dpay_wc_account (who the key belongs to). Deleting the plugin removes all three; orders and their notes stay.
  • Filters: dpay_wc_payment_session_body (the session DPay is asked to create — add metadata, change the description), dpay_wc_webhook_url, dpay_wc_api_base_url.
  • Constant: DPAY_API_BASE_URL in wp-config.php points the plugin at a sandbox or self-hosted DPay.

Questions

Can customers pay by card? No. DPay is bank transfer and wallets, which is how 92% of Pakistani e-commerce pays. Run a card gateway alongside if you need one.

Is there a fee per order? No. DPay charges a flat plan price; the plugin is free.

Does it work with subscriptions or deposits plugins? Version 1.0 supports one-off orders (products). Recurring charges need a card on file, which bank transfer cannot do; DPay's own subscriptions bill by invoice instead.

Something is wrong. Write to support@dpay.com.pk with the order number and the DPay reference, or check the dpay log first.