This page explains what happens when a customer places an order, what WooCommerce does with the order status as it moves through the flow, and how PayBridgeNP confirms payment. Read it once and you’ll know which part of the flow to check when something doesn’t behave as expected.Documentation Index
Fetch the complete documentation index at: https://docs.paybridgenp.com/llms.txt
Use this file to discover all available pages before exploring further.
The payment flow
Customer places an order and picks PayBridgeNP
The customer reaches your WooCommerce checkout (classic shortcode or Blocks - both work), picks PayBridgeNP as the payment method, and clicks Place order.WooCommerce creates a new order in the
pending status and asks the PayBridgeNP gateway to start checkout.Plugin creates a PayBridgeNP checkout session
The plugin:
- Reads the order total and converts it to paisa (
total × 100, rounded) - Builds the return and cancel URLs for your store
- Creates a PayBridgeNP checkout session with the amount, currency (NPR), return URL, cancel URL, and order metadata
- Records the PayBridgeNP session reference on the order for traceability
- Adds an order note for support/debugging
Customer pays on PayBridgeNP's hosted checkout
The customer lands on
https://checkout.paybridgenp.com/checkout/cs_..., sees your merchant name and the order total, picks a wallet (eSewa, Khalti, or Fonepay), and completes the payment.Browser return - order → On hold
After the wallet confirms the payment, PayBridgeNP redirects the customer’s browser back to your store with the session reference and success status.The return handler:
- Validates the order id + order key (using
hash_equalsto prevent timing attacks and cross-order tampering) - If the order is already paid (webhook arrived before the browser), redirects straight to the order-received page
- Otherwise, moves the order to On hold with a note (“PayBridgeNP: payment submitted, awaiting server confirmation”)
- Redirects the customer to WooCommerce’s standard order-received page
return URL with a valid order key and a fake status=success. The webhook (next step) is the only trustworthy confirmation.Webhook delivery - order → Processing
A few seconds after the wallet confirms the payment, PayBridgeNP sends a signed
payment.succeeded webhook to your store.The webhook handler:- Reads the raw request body and the
X-Paybridge-Signatureheader - Looks up the webhook signing secret from gateway settings - refuses with HTTP 400 if the secret is not configured (no unsigned fallback)
- Verifies the HMAC-SHA256 signature via the PayBridgeNP PHP SDK’s
constructEvent()- rejects forged events and replays older than 5 minutes - Extracts the order id from
event.data.metadata.order_id - Validates the order key from
event.data.metadata.order_keyagainst the stored order key (samehash_equalsguard as the return handler) - Marks the WooCommerce order as paid, which:
- Sets the order to Processing (or Completed for virtual/downloadable products)
- Records the PayBridgeNP payment id as the transaction id (visible in WC admin under the order)
- Reduces stock levels
- Lets WooCommerce run its normal post-payment notifications and fulfilment hooks
- Adds an order note recording the provider name, provider reference, and amount
- Returns HTTP 200
OK
Order state machine
The plugin moves orders through these WooCommerce states:| State | When | Who sets it |
|---|---|---|
pending | Order created, customer hasn’t returned from PayBridgeNP yet | WooCommerce core |
on-hold | Customer returned successfully, webhook hasn’t arrived yet | PayBridgeNP return handling |
processing | Webhook confirmed payment.succeeded, transaction id recorded | PayBridgeNP webhook handling |
cancelled | Customer clicked cancel on PayBridgeNP’s hosted checkout | PayBridgeNP return handling |
failed | Customer returned failed, OR webhook delivered payment.failed / payment.cancelled for an unpaid order | PayBridgeNP return or webhook handling |
completed | Fulfilment complete (virtual/downloadable products auto-complete on payment_complete) | WooCommerce core |
What the webhook handler does for each event type
| Event | Order state (if unpaid) | Order state (if already paid) |
|---|---|---|
payment.succeeded | → processing through WooCommerce’s normal paid-order flow | No change - idempotent skip |
payment.failed | → failed with the reason in an order note | No change - we never un-pay |
payment.cancelled | → failed with the reason in an order note | No change - we never un-pay |
is_paid() check before every state transition is the idempotency guard - PayBridgeNP retries webhooks, and we never want a duplicate delivery to accidentally “un-pay” an already-confirmed order.
Block checkout vs classic checkout
Both are supported out of the box. You don’t have to choose one or the other - if your theme uses the classic checkout, the classic gateway renders. If your theme uses the Blocks checkout (the default for stores created since late 2023), the Blocks gateway renders. Both use the same payment flow.HPOS (High-Performance Order Storage)
The plugin declares HPOS compatibility, so you can enable HPOS in WooCommerce → Settings → Advanced → Features and the plugin will continue to work.Security model
- Webhook signature verification is mandatory. The plugin refuses to process webhooks unless the signing secret is configured (HTTP 400 response). There is no unsigned fallback.
- Order key validation in both the return and webhook handlers prevents an attacker from guessing an order id and forging a success event for someone else’s order.
hash_equalscomparison for order keys uses a timing-safe string compare.add_query_arg+sanitize_text_fieldfor all incoming query params.wp_unslashon every$_GET/$_SERVERread to undo WordPress’s automatic slash-escaping.- No raw SQL anywhere - all order operations go through the WooCommerce CRUD layer.
What’s next
- Troubleshooting - common issues and how to fix them
- Back to installation if you haven’t set up the gateway yet