asciisd/knet
Laravel package for integrating KNET payments into PHP applications. It simplifies payment initiation, callback handling, and response verification, giving developers a straightforward way to accept Kuwaiti debit card payments.
414 is hard-coded into the flow. That constrains how you model prices, rounding, and minimum order value (min 0.001 KWD). PMs should confirm the pricing model handles 3-decimal currency before committing to tiered plans or per-unit metering.payWithKfast() and an overridable kfastToken() strategy, so the product decision is: do we invest in a stable customer-token identity (e.g., mapping to customer_number rather than user ID) and negotiate KFAST enablement with the acquirer? This is a roadmap item, not an engineering blocker — but KFAST must be enabled on the terminal by the bank, which is a business-development dependency with lead time.action = 2, original_transaction_id). This makes a meaningful difference to support cost and to whether you can offer a self-serve refund policy in the T&Cs rather than a manual, bank-mediated process.KnetPaymentSucceeded, KnetPaymentFailed, KnetRefundSucceeded/Failed, KnetTransactionCreated/Updated, KnetResponseReceived/Handled) is the integration seam. The PM decision is what "paid" means in the product: the redirect back to KNET_REDIRECT_URL is a UX signal, while the server-to-server POST to /knet/response is the source of truth. Fulfillment must key off the callback/event path, not the browser return — otherwise you ship a class of bugs where users see "failed" but are charged, or vice versa.inquireAndUpdateTransaction() and the PaymentStatus enum (with pending states: INITIATED, PENDING, UNKNOWN) support a scheduled reconciliation job. This determines whether finance can close the books daily and whether you need a human to eyeball a spreadsheet — a recurring operating cost that should be in the business case.udf1–udf5 are the only clean way to carry your own identifiers (order ID, subscription ID, product SKU) through the gateway lifecycle. Deciding a UDF convention up front is a small decision with outsized impact on analytics, reconciliation, and dispute handling later.KNET_TRANSPORT_ID, KNET_TRANSPORT_PASSWORD, KNET_RESOURCE_KEY). If the roadmap includes multiple brands, regions, or merchant accounts, budget for config layering or per-tenant credential resolution — do not assume this is free.Adopt when most of these hold:
knet:check) but cannot substitute for the acquirer relationship.CreatesPayments, InquiresPayments, RefundsPayments) that keep your controllers honest.knet:install publishes config, runs migrations, and validates setup; the HasKnet trait gives you pay(), payWithKfast(), refund(), and a knetTransactions() relationship in one line on your User model.Look elsewhere, or plan to build, when:
414 are baked into the request contract.For executives — one paragraph. KNET is the payment rail that decides whether we can sell in Kuwait at all. This package is a production-shaped Laravel integration for KNET covering checkout, faster checkout (KFAST), full and partial refunds, and transaction status inquiry, with card data never touching our infrastructure (redirect-based flow, so PCI exposure stays minimal). It replaces what would otherwise be a bespoke protocol implementation — AES-encrypted payloads, gateway action codes, callback decryption — with configuration, a trait, and events. It is MIT-licensed and free, which means the cost is not license fees but ownership: it is a small, single-maintainer package, so we should treat it as code we adopt and are prepared to own, pin the version, test against the KNET sandbox, and plan a fork if upstream goes quiet. The gating dependency is commercial, not technical: the acquirer must issue our tranportal credentials and enable KFAST on the terminal, and that lead time should drive the launch date, not engineering.
For engineering — the short version. Redirect-based RAW integration. knet:install publishes config, migrates the knet_transactions table, validates setup. Add HasKnet to your billable model and you get pay(), payWithKfast(), refund(), and a transactions relationship. Depend on the narrow contracts (CreatesPayments, InquiresPayments, RefundsPayments) rather than the concrete KnetPaymentService so your controllers stay testable. The callback is a signed, encrypted POST to /knet/response; middleware decrypts once and stashes the payload in request attributes, then KnetPaymentSucceeded / KnetPaymentFailed fire. Treat the server callback as the source of truth for fulfillment; the redirect to KNET_REDIRECT_URL is presentation only. Amounts are 3-decimal strings (KWD), track IDs are unique, and udf1–udf5 are our channel for order/subscription IDs — agree the convention before the first commit. Routes and migrations are both opt-out (Knet::ignoreRoutes(), Knet::ignoreMigrations()) if they collide with our conventions.
Risks to name in the same breath. Small community and single maintainer; no support contract; KNET-specific with no multi-gateway abstraction; single-terminal credentials from env; KFAST requires bank-side enablement. None of these are blockers for a first Kuwait launch — all of them are things we should be able to state we accepted deliberately rather than discovered in month three.
How can I help you explore Laravel packages today?