KNET Payment Integration for Mobile Apps: A Practical Guide
How KNET payment gateway integration works in mobile apps: bank vs payment provider, the hosted-page flow in React Native, verification and testing.
Full-Stack, Mobile & AI Engineer
If your app sells to customers in Kuwait, KNET isn't optional. It's the national debit network most Kuwaiti bank cards run on, and many customers expect to see it at checkout next to cards and Apple Pay. Yet English-language documentation for developers is thin, scattered across bank PDFs, plugin manuals and old forum threads.
This is a practical guide to KNET payment gateway integration for mobile apps: the two ways to connect, how the payment flow works inside a React Native app, how to verify payments safely, and how to test. I integrated KNET, Apple Pay, Google Pay and cards for Floey, a fitness booking platform in Kuwait, so this is written from the developer's side of the problem.
Key takeaways
- KNET payments happen on a hosted payment page. The customer enters their debit card details and PIN there, not inside your app.
- There are two routes: a direct integration through a KNET member bank (Tranportal credentials and a resource key), or a payment service provider that offers KNET alongside cards and wallets in one API.
- In a mobile app, open the payment page in an in-app browser, then let your server confirm the result before the app shows "paid".
- Never trust the redirect alone. Verify every payment server-side and make your order updates idempotent.
- Apple allows KNET for physical goods and real-world services (like gym classes), but digital content inside iOS apps still falls under in-app purchase rules.
What KNET is
KNET (The Shared Electronic Banking Services Company) runs Kuwait's national payment network. Online, a KNET payment works like this: your system creates a payment, the customer is redirected to KNET's payment page, selects their bank, enters their card number, expiry and PIN, and KNET returns the result to a response URL you provided.
That hosted-page design is good for security, because card details never touch your app or servers, but it shapes how you build the mobile flow.
Two ways to integrate KNET
| Direct via a KNET member bank | Through a payment service provider | |
|---|---|---|
| How you get access | Contract with a Kuwaiti bank that's a KNET member | Sign up with a provider that supports KNET (for example Tap, Checkout.com, MyFatoorah) |
| Credentials | Tranportal ID, Tranportal password, terminal resource key | API keys from the provider |
| Integration | Build encrypted requests and parse responses yourself | Provider's API and SDKs |
| Other methods | KNET only, unless you integrate others separately | Usually cards, Apple Pay and Google Pay in the same API |
| Fees and settlement | Negotiated with the bank | Provider's pricing, settlement to your account |
| Best for | High volume, strong in-house payments expertise | Most apps, especially when launching quickly |
With a direct integration, the bank provides sandbox credentials pointing to KNET's test environment and separate production credentials once you pass verification. Request parameters are encrypted with your terminal resource key, and responses must be decrypted and validated on your server.
With a provider, you call one API to create a KNET payment, redirect the customer to the provider's page, and receive a webhook with the result, often with the same code path you use for cards.
The payment flow in a React Native app
The safe pattern has five steps:
- The app asks your server to start a payment for an order (never the amount alone; the server decides the amount).
- Your server creates the payment with the bank or provider and returns the payment page URL.
- The app opens the payment page in an in-app browser.
- KNET or the provider returns the result to your server through the response URL or a webhook. Your server verifies it and marks the order paid.
- The browser redirects back to your app through a deep link, and the app asks the server for the order's status.
Here's the app side with Expo's web browser module:
import * as WebBrowser from "expo-web-browser";
import * as Linking from "expo-linking";
export async function payWithKnet(orderId: string) {
const res = await fetch(`${API_URL}/payments/knet`, {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
body: JSON.stringify({ orderId }),
});
const { paymentUrl } = await res.json();
const returnUrl = Linking.createURL("payment-complete");
await WebBrowser.openAuthSessionAsync(paymentUrl, returnUrl);
// Whatever the browser result, the server is the source of truth.
const status = await fetch(`${API_URL}/orders/${orderId}`).then((r) => r.json());
return status.paymentStatus; // "paid" | "failed" | "pending"
}The important line is the last one. A user can close the browser, lose connection, or the redirect can fail after a successful payment. Your server's verified record is what decides whether the order is paid.
Verifying payments safely
On your server:
- Verify every response. For a direct integration, decrypt and validate the response from KNET; for a provider, verify the webhook signature or fetch the payment status from their API.
- Match the amount and order. Check that the verified payment matches the order ID and amount you created.
- Be idempotent. Responses and webhooks can arrive more than once. Recording "payment X confirmed" twice must not book two classes or extend a membership twice.
- Handle "pending" and timeouts. If the result never arrives, query the payment status before marking anything failed.
- Reconcile daily. Compare your records with the bank's or provider's settlement reports.
From the field: For Floey, I integrated Kuwaiti payment rails (KNET, Apple Pay, Google Pay and cards) with idempotent, webhook-driven billing and automatic monthly membership renewals. The rule that kept it reliable was that the app never decides whether something is paid; the server does, once, from a verified event.
KNET and App Store rules
Apple's guideline 3.1.3(e) says that if your app sells "physical goods or services that will be consumed outside of the app", you must use payment methods other than in-app purchase, "such as Apple Pay or traditional credit card entry". Gym classes, memberships at a physical gym, deliveries and bookings all fall here, so KNET is allowed.
Digital content and features used inside the app are different: those generally require in-app purchase on iOS (with the US storefront exceptions for external links). Make sure your product fits the right category before building the checkout.
Testing KNET
- Get sandbox credentials from your bank or provider, along with their current test card numbers and PINs. Test card details vary by provider and change over time, so use the ones in your provider's documentation.
- Test success, decline, cancel and timeout cases, and closing the browser mid-payment.
- Test duplicate notifications by replaying a webhook or response to confirm idempotency.
- Test on real devices, because in-app browser and deep link behaviour differs from simulators.
Where to find KNET documentation
KNET doesn't publish an open developer portal. When you integrate directly, the integration documentation and test credentials come from your acquiring bank once your merchant account is approved. Payment providers that support KNET, such as Tap, MyFatoorah and Checkout.com, publish their own public API documentation, which is one reason many teams start with a provider and move to a direct bank integration later, if at all.
FAQ
How do I integrate KNET into a mobile app?
Create the payment on your server, open the KNET (or provider) payment page in an in-app browser, and let your server receive and verify the result. Then return the user to the app with a deep link and show the status from your server. The customer enters card details and PIN only on the hosted page.
Do I need a Kuwaiti bank to accept KNET?
For a direct KNET integration, yes: credentials come through a contract with a KNET member bank. Payment service providers that support KNET handle that relationship, which is why most apps start with a provider.
Can I use KNET for automatic subscription renewals?
KNET payments are authorised by the cardholder on the hosted page, so automatic recurring charges usually rely on cards or wallets that support saved, tokenised payments through your provider. Many apps offer KNET for one-off payments and renewals by card. Confirm what your provider supports.
Is KNET allowed in iOS apps?
Yes, for physical goods and services consumed outside the app, such as bookings, deliveries and gym memberships, which Apple's guideline 3.1.3(e) requires to use non-in-app-purchase payment methods. Digital content and in-app features generally still require Apple's in-app purchase.
Next steps
If you're launching an app in Kuwait or the wider GCC and need KNET, cards and wallets working reliably, I've built exactly that and can help you choose the route and implement it. Get in touch, or see how I work as a React Native developer.
Sources
- KNET, Tap Payments developer docs
- KNET, Checkout.com docs
- App Review Guidelines (3.1.3(e)), Apple
- WebBrowser, Expo
- KNET .NET Core integration (open source example), GitHub
Related
Accepting Payments in Kuwait and the GCC from a Mobile App
How to accept payments in a mobile app in Kuwait and the GCC: local debit networks, Apple Pay, BNPL, payment providers, 3-decimal currencies, VAT and RTL.
In-App Purchases in React Native: RevenueCat vs Going Direct
React Native in-app purchases in 2026: RevenueCat vs expo-iap and react-native-iap, server validation, Android acknowledgement and when each choice wins.
Stripe in React Native: Payment Sheet, Apple Pay and Google Pay
Accept payments in React Native with Stripe: Payment Sheet setup in Expo, the server side, Apple Pay and Google Pay, webhooks, and when Stripe is allowed.
