OpenCart
Install and configure the Qasimha payment extension for OpenCart 4, including status mapping, webhooks and the order-page actions.
The Qasimha extension adds "Qasimha - pay in instalments" to an OpenCart 4 store. The shopper is sent to the Qasimha hosted checkout and comes back to your thank-you page. The store marks the order paid only after it has read the order back from Qasimha. Fulfilment, refunds and status checks run from the order page.
Requirements
| Item | Requirement |
|---|---|
| OpenCart | 4.0.2.0 or later |
| PHP | 8.1 or later with curl, json and mbstring |
| Currency | Saudi riyal (SAR) configured as a store currency. Qasimha is offered when the shopper's selected currency is SAR. |
| HTTPS | Required (plain http works only on localhost) |
| Package | qasimha-opencart-<version>.ocmod.zip |
| License | MIT |
Install
- Download
qasimha-opencart-<version>.ocmod.zipfrom the extension's releases. - In the admin, open Extensions → Installer, upload the file, then press Install on the row that appears.
- Open Extensions → Extensions, choose the type Payments, find Qasimha and press Install. This creates the tables
oc_qasimha_orderandoc_qasimha_webhook_eventand registers the storefront events for the widget. - Press Edit and fill in the settings below.
If your Arabic language uses a directory other than ar (for example ar-sa), copy extension/qasimha/admin/language/ar and extension/qasimha/catalog/language/ar to that name.
Uninstalling from the Payments list removes the events and the webhook table but keeps oc_qasimha_order, so past orders keep their Qasimha order id.
Configure
Go to Extensions → Extensions → Payments → Qasimha → Edit.
| Tab | Setting | What to enter |
|---|---|---|
| General | Status | Enables the payment method. |
| General | Environment | Sandbox uses the sk_test_ key and never moves money. Production uses the sk_live_ key. |
| General | Minimum / Maximum total | Qasimha is offered only when the cart total in riyals is in this range. 0 means no limit. |
| General | Debug log | Writes each step to storage/logs/qasimha.log. |
| General | Sort order | Position in the payment-method list. |
| API keys | Sandbox / Production secret key | From the Merchant Portal, Settings → API keys. Shown masked after saving; leave empty to keep the stored key. A key from the other environment is refused. |
| API keys | Publishable key | pk_test_... or pk_live_.... The only key that reaches the browser. |
| API keys | Webhook URL | Read-only. Register it in the Merchant Portal. |
| API keys | Webhook secret | The secret the Merchant Portal shows for that webhook. |
| API keys | Test connection | Checks the keys in the form (saved or not) and reports the environment and order count. |
| Order statuses | Six mappings | See the next section. |
| Widget | Product / cart page, placement selectors | See Widget placement. |
Order status mapping
Set these on the Order statuses tab.
| Mapping | Default | When it is applied |
|---|---|---|
| Awaiting checkout | Pending | The checkout session was created and the shopper was sent to Qasimha. |
| Payment confirmed | Processing | The order was read back from Qasimha and is Confirmed with the same reference and total. |
| Fulfilled | Shipped | After Fulfil in Qasimha on the order page. |
| Fully refunded | Refunded | Refunds bring the refunded amount to the order total. Partial refunds add a history comment and keep the status. |
| Voided | Voided | Qasimha reports the order voided or cancelled. |
| Declined | Denied | Qasimha declined the order. Only applied while the order is still awaiting checkout. |
The extension never moves an order backwards. A paid order is not set back to pending by a later webhook.
Register the webhook
Register this URL in the Merchant Portal and paste the secret into Webhook secret:
https://<your-store>/index.php?route=extension/qasimha/payment/qasimha.webhookThe webhook answers:
| Status | Meaning |
|---|---|
200 | Received ({"received":true,"action":…}) |
400 | Bad signature or bad body |
503 | No webhook secret configured |
500 | The order could not be read back from Qasimha — Qasimha retries |
The event body only says which order to look at. The extension reads the order from Qasimha before changing anything.
How a payment flows
- Confirm. The shopper presses Continue to Qasimha. The extension creates the checkout session from the order, sets Awaiting checkout and redirects the shopper.
- Reference. The reference is the OpenCart order id. If the shopper cancels and places the same order again, the next attempt is
<id>-2,<id>-3, and the abandoned Qasimha order is cancelled. - Return. The shopper returns to the
qasimha.callbackroute with the order id and a token. The extension checks the token, reads the order from Qasimha, and marks it paid only when it isConfirmedwith the same reference and total. Otherwise OpenCart's payment-failed page is shown. - Decline. The shopper sees one line — "Your Qasimha payment was not completed. Please choose another payment method." — and never a reason.
Widget placement
With a publishable key saved, the extension shows the instalment summary (<qasimha-widget type="summary">) on product pages (under the price) and the cart page (under the totals), and a "pay in instalments with Qasimha" card at checkout.
Placement is a list of CSS selectors tried left to right, separated by ||. The widget is inserted after the first match. Defaults for the OpenCart 4 default theme:
- Product page:
#content h2 || .product-price || .price - Cart page:
#checkout-total || #content .table:last-of-type
Change them if your theme uses different markup. The widget is only injected when the shopper's currency is SAR and renders nothing when the amount is outside your plans. If you use a Content Security Policy, allow connect-src for the Qasimha API host of your environment; the script itself is served from your store. See Plans widget.
Fulfilment, refunds and cancellations
Open Sales → Orders, then an order paid with Qasimha. The Qasimha tab shows the Qasimha order id, reference, environment and last known status, with three actions:
- Check status — reads the order again and shows captured, refunded and refundable amounts.
- Fulfil in Qasimha — reports the whole order as fulfilled, once. The order moves to the Fulfilled status.
- Refund via Qasimha — enter an amount and an optional reason. History is updated only when Qasimha accepts. A refund above the refundable amount shows Qasimha's
AMOUNT_EXCEEDEDmessage as is.
Fulfilment is manual on OpenCartShipping the order in OpenCart does not notify Qasimha. Press Fulfil in Qasimha when you ship. Qasimha needs this call to release your settlement.
When the shopper cancels on the hosted checkout, the cancel route cancels the Qasimha order and returns the shopper to the cart.
Test in UAT
- Environment
Sandbox,sk_test_andpk_test_keys saved; Test connection passes. - Webhook URL registered for sandbox and the secret saved.
- Widget shows under the product price and the cart totals (adjust selectors if not).
- Complete a hosted checkout: order moves to Payment confirmed (default Processing).
- Cancel on the hosted checkout: you are back in the cart.
- Fulfil in Qasimha: order moves to Fulfilled.
- Partial refund, then a refund larger than what is left: the second shows
AMOUNT_EXCEEDED. -
storage/logs/qasimha.logshows no errors.
Troubleshooting
Qasimha is not offered at checkout
Check that Status is enabled, the shopper's currency is SAR, and the cart total is inside the minimum/maximum range.
The widget does not appear
Check that a publishable key is saved, the widget is turned on for that page, and one of the placement selectors matches an element in your theme. The widget also renders nothing when the amount is outside your plans.
Arabic text is missing
Your Arabic language directory is not named ar. Copy the two language/ar directories to your directory name (see Install).
Webhook returns 503
No webhook secret is saved. Paste the secret from the Merchant Portal.
Security
- Admin: every save and button checks the admin
user_tokenand themodifypermission onextension/qasimha/payment/qasimha. Give that permission only to trusted admin users. - Keys: the secret keys and webhook secret are saved in OpenCart's
settingtable without encryption and shown masked on the settings page. Restrict database and backup access accordingly. - Browser: only the publishable key.
- Return route: checks a per-attempt token and reads the order from Qasimha before changing it.
- Webhook route: verifies the HMAC signature (5-minute tolerance, secret rotation) and de-duplicates on the event id. See Webhook signatures.
- Logs: secret keys, the webhook secret and customer data are never written; key-shaped strings are masked.
- PCI DSS: no card data passes through the store; you stay in SAQ-A scope.
Report security issues privately, never in a public issue.
Next steps
Updated 3 days ago
