WooCommerce

Install and configure the Qasimha Payment Gateway plugin for WooCommerce, including webhooks, refunds and fulfilment.

The Qasimha Payment Gateway plugin adds "Qasimha — pay in instalments" to a WooCommerce store. It uses the Qasimha PHP SDK for every API call, keeps your secret key encrypted in the WordPress database, and loads only the instalment widget (with your publishable key) in the shopper's browser.

Requirements

ItemRequirement
PHP8.1 or later
WordPress6.4 or later
WooCommerce8.0 or later; HPOS and cart/checkout Blocks compatible
Store currencySAR (the method hides itself otherwise)
HTTPSRequired (plain http works only on localhost)
Plugin slugqasimha-payment-gateway
LicenseGPL-2.0-or-later

Install

  1. In WordPress admin, go to Plugins → Add New → Upload Plugin.
  2. Upload the release zip and activate the plugin. The zip already contains the SDK in its vendor/ directory.

You can also install it from the WordPress.org plugin directory.

Developers installing from source:

composer install --no-dev

Then copy or symlink the directory to wp-content/plugins/qasimha-payment-gateway.

Configure

Go to WooCommerce → Settings → Payments → Qasimha.

SettingWhat to enter
EnvironmentSandbox (sk_test_ / pk_test_) or Production (sk_live_ / pk_live_). The SDK picks the API host from the key prefix.
Sandbox / Production secret keyYour sk_test_... or sk_live_... key. Shown masked (sk_live_…AbCd) after saving. Leave blank to keep the saved key.
Publishable keyYour pk_test_... or pk_live_... key. Used only by the widget. Must match the environment.
Webhook secretThe signing secret from the Merchant Portal. The webhook URL to register is shown next to this field.
Test connectionChecks the saved keys of the selected environment against the API.
Title / descriptionOne pair for Arabic and one for English. The shopper's locale decides which is shown.
Minimum / maximum amountHides the method outside this range.
Widget on product / cart pagesShows the instalment summary under the price and under the cart total.
Debug logAdds info/debug lines to WooCommerce → Status → Logs, source qasimha. Errors are always logged.

The settings screen warns you when the store currency is not SAR.

Register the webhook

Register this URL in the Qasimha Merchant Portal, then paste the secret the portal gives you into Webhook secret:

https://<your-store>/wc-api/qasimha_webhook

Copy the exact URL shown next to the Webhook secret field; it reflects your site address. See Webhooks.

The webhook answers:

StatusMeaning
200Received
400Bad body
401Bad signature, or no webhook secret saved
503Qasimha API unreachable — Qasimha retries

How a payment flows

  1. Place order. The plugin creates the checkout session from the WooCommerce order, saves the Qasimha order id on the order (_qasimha_order_id) and redirects the shopper to the hosted checkout.
  2. Return. The shopper comes back to /wc-api/qasimha_return. The plugin checks its own token, reads the order from the API, and marks the order paid only when the Qasimha order is Confirmed, the reference matches and the total matches to the halala. Otherwise the order stays pending.
  3. Webhook. Confirms the order the same way if the shopper never comes back.

The order reference sent to Qasimha is the WooCommerce order number, then number-2, number-3 and so on for each new attempt. So a shopper who retries after a decline or expiry is not blocked.

Order status changes

EventWhat happens to the WooCommerce order
Qasimha order Confirmed (return or webhook)Marked paid
Declined at checkout creationMarked failed with a private note; shopper sees one neutral line
Declined event on an unpaid orderMarked failed
Shopper cancels on the hosted checkoutStays pending; shopper goes back to the cart with a notice
order.voided eventCancelled
Refund event from QasimhaOrder note added
Any other API error at checkoutPrivate note with the error code and request id; "payment not completed" notice

Each step writes a private order note with the Qasimha order id, the reference and the API request id.

Widget placement

  • Product page: <qasimha-widget type="summary"> under the price, using the displayed price.
  • Cart page: under the cart total.
  • Checkout: the widget is loaded on the checkout page. In Blocks checkout the method shows its title, description and the card snippet, and hides itself outside the amount range.

The widget script is bundled inside the plugin (WordPress.org does not allow remote scripts). Language follows the store locale (Arabic or English). See Plans widget.

Fulfilment, refunds and cancellations

  • Fulfilment: when you set the order to Completed, the plugin reports fulfilment to Qasimha with the order total. It runs once per order; if it fails, a note is added and it is tried again the next time the order is completed.
  • Refund: use the normal Refund button on the order screen. WooCommerce keeps the refund only when Qasimha accepts it. If Qasimha refuses (for example AMOUNT_EXCEEDED), the message appears in the refund dialog as Qasimha wrote it.
  • Cancel: cancelling an unpaid order also cancels the Qasimha order while it is still AwaitingCheckout.

Test in UAT

  • Environment set to Sandbox; sk_test_ and pk_test_ keys saved; Test connection passes.
  • Webhook URL registered for sandbox and the secret saved.
  • Widget shows on a product page and the cart page.
  • Place an order with Qasimha, complete the hosted checkout: order is marked paid and the note shows the Qasimha order id.
  • Place an order and cancel on the hosted checkout: order stays pending, you are back in the cart.
  • Set a paid order to Completed: a fulfilment note appears.
  • Refund part of a paid order, then try to refund more than is left: the second refund is refused with Qasimha's message.
  • Check WooCommerce → Status → Logs (source qasimha) for errors.

Troubleshooting

Qasimha does not appear at checkout

Check that the store currency is SAR, the order total is inside the minimum/maximum range, and the method is enabled with a key saved for the selected environment.

Webhook deliveries fail with 401

No webhook secret is saved, or it does not match the endpoint registered in the Merchant Portal. Paste the secret again for the environment you are testing.

Order stays pending after a successful checkout

The plugin marks the order paid only when the Qasimha order is Confirmed and both the reference and the total match. Check the private order notes and the qasimha log for the status it read. If the shopper did not return to the store, the webhook confirms the order; check that the webhook is registered.

Payment refused before the shopper is redirected

The SDK checks the request before sending it. The private order note lists the field names that failed (never their values). A negative calculated tax amount means the order cannot be expressed and is refused.

Security

  • Secret key: stored encrypted in the WordPress options table (libsodium secretbox, AES-256-GCM fallback) with a key derived from wp_salt('auth'). Masked on screen and never logged.
  • Browser: only the publishable key. The secret key and webhook secret never leave the server.
  • CSRF: the settings form uses WooCommerce's settings nonce and the manage_woocommerce capability; Test connection checks its own nonce and the capability.
  • Return route: a GET that only selects an order and asks the API. Nothing changes on the strength of URL parameters.
  • Webhook route: no nonce by design; protected by the HMAC signature (constant-time compare, 5-minute tolerance, rotated secrets). See Webhook signatures.
  • PCI DSS: no card data touches the store; you stay in SAQ-A scope.

Report vulnerabilities privately to the security contact in the Merchant Portal, not in a public issue.

Next steps


Did this page help you?