Salesforce B2C Commerce Cloud
Install and configure the Qasimha LINK cartridges for Salesforce B2C Commerce storefronts built on SFRA.
The Qasimha cartridges add "Qasimha — pay in instalments" to a Salesforce B2C Commerce storefront built on SFRA. The cartridges call the Qasimha API directly through a dw.svc service (there is no SDK on this platform). Your secret key lives only in the Business Manager service credential. The shopper's browser only loads the instalment widget with your publishable key.
Requirements
| Item | Requirement |
|---|---|
| SFRA | 5.1 or later |
| Site currency | SAR |
| HTTPS | Required |
| Cartridges | int_qasimha (core) and int_qasimha_sfra (SFRA overlay) |
| License | MIT |
Install
- Import metadata. Rename
metadata/site_import/sites/RefArchto your site id, zip thesite_importdirectory (npm run release:metadataproducesbuild/site_import.zip), and import it in Administration → Site Development → Site Import & Export. This creates the Qasimha site-preference group, the order attributes, theQasimhaWebhookEventcustom object, theQASIMHApayment method and processor, theqasimha.merchant.apiservice and theQasimha-Fulfilmentjob. - Upload code. Upload both cartridges (
npm run uploadCartridgewith adw.json, or any WebDAV client). Add them to the storefront cartridge path in front of the SFRA base:
int_qasimha_sfra:int_qasimha:app_storefront_baseThere is no compile step.
- Secret key. Go to Administration → Operations → Services → Credentials. Open
qasimha.merchant.api.sandbox(orqasimha.merchant.api.production) and paste the secret key (sk_test_...orsk_live_...) into the password field. The user id is not used. Point the serviceqasimha.merchant.apiat the credential for your environment. Do not enter the key anywhere else. - Site preferences. Fill in the Qasimha group (next section).
- Payment method. Go to Merchant Tools → Ordering → Payment Methods and check that
QASIMHAis enabled. The import creates it enabled and restricted toSAR. - Webhook. Register the webhook URL (see below) and copy the secret into the site preference.
- Job. Go to Administration → Operations → Jobs → Qasimha-Fulfilment, set the site and enable the recurring trigger. Hourly is a good default.
Configure
Go to Merchant Tools → Site Preferences → Custom Preferences → Qasimha.
| Preference | What to enter |
|---|---|
| Enabled | Offers the method and renders the widget. |
| Environment | sandbox or production. Must agree with the credential's key prefix; a mismatch is logged as a warning and the API refuses the key. |
| Publishable key | pk_test_... or pk_live_.... Used only by the widget. |
| Webhook secret | The whsec_... secret of the endpoint registered for Qasimha-Webhook. A password-type preference. |
| Minimum / maximum order amount | Hides the method outside the range. |
| Widget on product pages / on the cart page | Turns the widget on per page (see Widget placement). |
Register the webhook
Register this URL in the Qasimha Merchant Portal, replacing your host, site id and locale:
https://<your-host>/on/demandware.store/Sites-<site>-Site/<locale>/Qasimha-WebhookCopy the secret into the Webhook secret preference. The webhook answers:
| Status | Meaning |
|---|---|
200 | Received, duplicate or ignored |
400 | Bad body |
401 | Bad signature, or no secret saved |
503 | Qasimha API unreachable — Qasimha retries |
How a payment flows
- Billing step. The Qasimha tab appears in the payment options. It is hidden when the basket is not in
SAR, is outside the amount range, or has a gift certificate applied. - Place order. The cartridge creates the order, creates the checkout session with the order number as
orderReferenceId, storescustom.qasimhaOrderId,custom.qasimhaPaymentUrlandcustom.qasimhaStatuson the order, and sends the shopper to the hosted checkout throughQasimha-Start. - Return.
Qasimha-Returnchecks the order token, reads the order from Qasimha, and places the order only when it isConfirmed, the reference matches and the total matches to the halala. - Webhook. Applies the same rule when Qasimha sends an event.
SFRA creates a new order number for every attempt, so a retry never collides with an earlier reference.
Order status changes
| Situation | What happens to the SFCC order |
|---|---|
Qasimha order Confirmed (return or webhook) | Placed (OrderMgr.placeOrder), payment status PAID, confirmation email sent |
| Declined at checkout creation or on return | Order failed, basket reopened, one neutral decline line on the payment step |
Expired, Cancelled or Voided on return | Order failed, "payment not completed" |
| Cancel route, or failure return, while the Qasimha order is still open | Qasimha order cancelled, store order failed, shopper sent to the cart |
| Success return but Qasimha not settled yet, or API unreachable | Order kept in CREATED; "we are confirming your payment" page; the webhook completes it |
order.voided or order.cancelled event | Fails an unplaced order or cancels a placed one |
| Declined or expired event | Fails an unplaced order |
Refund event (order.refunded) | Order note added |
Each step writes an order note with the Qasimha order id, the reference and the request id.
Widget placement
- Product page: shown under the price on
Product-Showautomatically (the overlay includesproduct/qasimhaWidget.isml). - Checkout: the Qasimha tab shows a summary for the order total and the card snippet.
- Cart page: not automatic. Add this line to your site's
cart/cartTotals.ismlwhere you want the badge:
<isinclude template="cart/qasimhaWidget" />The amount on the cart page stays in sync when the cart changes. The widget script is bundled in the cartridge (LINK cartridges must not load remote scripts). See Plans widget.
Fulfilment, refunds and cancellations
- Fulfilment: the
Qasimha-Fulfilmentjob reports every shipped order with a Qasimha order id, once, with the carrier and tracking number from the default shipment. It marks the order withcustom.qasimhaFulfilled. If Qasimha refuses (already fulfilled, not found), the job gives up with a note; network failures are retried on the next run. The job also deletes webhook records older than 30 days. - Refunds: the cartridge does not send refunds to Qasimha. When a refund event arrives, it adds an order note.
- Cancellations: handled on the shopper's cancel and failure returns, and through
order.voided/order.cancelledevents.
Enable the fulfilment jobFulfilment is reported only by the
Qasimha-Fulfilmentjob. If its trigger is not enabled, Qasimha never learns that orders shipped.
Test in UAT
- Metadata imported, both cartridges on the cartridge path,
QASIMHApayment method enabled. -
sk_test_key in theqasimha.merchant.api.sandboxcredential password; service points at it; Environmentsandbox. -
pk_test_key and webhook secret saved in site preferences. - Widget shows on a product page, the cart (after adding the include) and the checkout tab.
- Complete a hosted checkout: order placed with payment status
PAID. - Cancel on the hosted checkout: store order failed, shopper back in the cart.
- Ship an order and run the
Qasimha-Fulfilmentjob:custom.qasimhaFulfilledset and a note added. -
custom-qasimha-*logs show no errors.
Troubleshooting
Qasimha tab does not appear at checkout
Check that the preference Enabled is on, the QASIMHA payment method is enabled, the basket is in SAR and inside the amount range, and no gift certificate is applied.
API calls are refused with a key error
The Environment preference does not match the key prefix in the service credential (sk_test_ for sandbox, sk_live_ for production). A warning is logged.
No widget on the cart page
The cartridge does not override the cart totals template. Add <isinclude template="cart/qasimhaWidget" /> to your cart/cartTotals.isml.
I need the API call details in the logs
In Administration → Operations → Custom Log Settings, set the custom-qasimha category to DEBUG.
Security
- Secret key: only in the service credential's password field. Never in code, site preferences, templates, custom objects or logs. The logger masks
sk_,pk_andwhsec_values and redacts customer fields. - Browser: only the publishable key.
- CSRF:
Qasimha-Startis a POST guarded bycsrfProtection.validateRequest, the order token and the session owner. The return routes areGETs that only select an order and ask the API. - Webhook route: exempt from CSRF; protected by the HMAC signature (rotated secrets, 5-minute tolerance, constant-time compare) and de-duplicated with the
QasimhaWebhookEventcustom object. See Webhook signatures. - TLS: the service URL is
https://and certificate validation cannot be turned off. - PCI DSS: no card data touches the storefront; you stay in SAQ-A scope.
Report vulnerabilities privately to the security contact in the Merchant Portal, not in a public issue.
Next steps
Updated 3 days ago
