Capture and approve the order
When your customer reaches checkout, the SDK extracts the order from the merchant page and hands it to your app. You show your own approval UI, and — once the customer confirms — your backend creates the transaction.
Detect checkout
A checkout counts as detected when both hold: the WebView URL matches one of the session's checkoutDetection.urls patterns, and every applicable checkoutDetection.ready condition holds on the page.
listener = object : CheckoutListener {
override fun onCheckoutReady() {
// Customer is on a payable checkout page: show your payment hint / button
}
override fun onCheckoutExited() {
// Customer left checkout, or the page stopped being payable: hide the hint
}
}
URL patterns are glob-style: ** matches any characters including /, * any characters except /.
The DOM conditions are what make the detection payable rather than merely on-the-right-URL, such as whether the shipping address and delivery information have been entered.
The SDK keeps watching after the first match. If a condition stops holding (the pay button goes back to disabled), onCheckoutExited fires, and onCheckoutReady fires again once it holds once more.
onCheckoutReady is debounced: it fires when the checkout state is entered, not on every URL change within the same checkout pattern. On a single-URL SPA checkout it may fire once for the whole visit. It takes no arguments, so if you need to know which page the customer is on, read the WebView URL.
Request order details
When the customer taps your payment entry point, ask the SDK to capture and analyze the current page:
session.readOrder(object : OrderCallback {
override fun onOrderReady(orderInfo: OrderInfo) {
// Show your approval UI with the extracted order
}
override fun onError(error: OpenFabricError) {
// Extraction failed — let the customer pay with the
// merchant's own payment methods
}
})
The SDK captures the checkout page (sanitized — scripts stripped, sensitive values redacted), submits it to Open Fabric for extraction, and returns:
OrderInfo field | Description |
|---|---|
items | Line items: itemName, and optional itemImageUrl, itemPrice, itemQuantity. |
totalAmount | The displayed order total. |
customerInfo | Optional firstName, lastName, email, mobileNumber extracted from the page. |
shippingAddress | Optional addressLine1, postalCode, city. |
totalAmount, itemPrice, and itemQuantity are passed through verbatim from the merchant page — they may include currency symbols and arbitrary formatting. Display them as-is; the authoritative transaction amount is set at transaction creation on your backend.
readOrder captures whatever page the WebView is showing at the moment you call it. The SDK checks only that the session is active; it does not verify the page is a checkout.
Drive the call from onCheckoutReady rather than from a control the customer can reach earlier, and make sure the merchant's checkout_detection.urls are scoped to the payment page rather than the whole checkout funnel. If detection fires too early for a merchant, report it to Open Fabric. The patterns are part of the merchant configuration we maintain.
On merchants with an established configuration, extraction returns in a couple of seconds. The very first sessions on a newly onboarded merchant may take noticeably longer while Open Fabric derives the merchant's checkout structure — show a loading state in your approval UI.
Show your approval UI
The approval experience is fully yours: render the order (items, total, shipping details) in your own overlay or bottom sheet, apply your credit/risk checks, and let the customer confirm. The SDK injects no payment UI into the merchant page.
Create and approve the transaction
On confirmation, your app calls your backend, and your backend calls the Create Transaction API with instrument: in_app_shopping and the session_id from session creation:
Sample request
Headers:
Idempotency-Key: 40709949-0712-487c-a2fe-1dd2e64af506
{
"tenant_reference_id": "your-order-123456",
"amount": 129.00,
"currency": "SGD",
"instrument": "in_app_shopping",
"session_id": "01927d8a-9c3e-7b7a-9f4e-1d2a3b4c5d6e"
}
Sample response
{
"id": "9f2c1e3a-7b4d-4f5e-8c9a-1b2d3e4f5a6b",
"tenant_id": "7c1b2e3a-4f5d-4b8e-9a1c-2d3e4f5a6b7c",
"tenant_reference_id": "your-order-123456",
"amount": 129.00,
"currency": "SGD",
"status": "approved",
"card_fetch_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"payment_attempt_id": "01927d8b-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"created_at": "2026-07-08T10:15:00Z",
"updated_at": "2026-07-08T10:15:00Z"
}
Unlike other instruments (which create a transaction your backend approves in a second step), in_app_shopping creates and approves the transaction in one call — your customer has already consented in your approval UI. The virtual card is minted immediately and the response always contains card_fetch_token and payment_attempt_id.
Return card_fetch_token and payment_attempt_id to your app. They are the inputs to the final step.
Next: Run the payment.