digetpay_plugin 0.1.0 copy "digetpay_plugin: ^0.1.0" to clipboard
digetpay_plugin: ^0.1.0 copied to clipboard

Pure-Dart DigetPay payment plugin: hosted (PCI-safe) checkout via WebView plus transaction management over the DigetPay REST API.

digetpay_plugin #

Pure-Dart Flutter plugin for the DigetPay payment gateway. Card entry uses a hosted, PCI-safe WebView checkout — raw card data never passes through your app. Built on http (REST) and webview_flutter.

Getting started #

dependencies:
  digetpay_plugin:
    path: ../ # or a pub/git reference

Initialize once at startup:

import 'package:digetpay_plugin/digetpay_plugin.dart';

DigetPaySdk.initialize(
  apiKey: '<your-api-key>',
  baseUrl: kDigetPayDefaultBaseUrl, // https://fin-api.digetpay.com/v1
);

Every call before initialize() throws DigetPaySdkIsNotInitializedException.

Platform setup #

This is a pure-Dart plugin — you do not write or register any native code. It relies on webview_flutter (federated: Android WebView, iOS WKWebView) for the hosted checkout and http for the REST calls, so your app only needs the standard network/WebView configuration below.

Android #

  • Minimum SDK. This plugin requires minSdkVersion 24 (Android 7.0). Set it in android/app/build.gradle:

    android {
        defaultConfig {
            minSdkVersion 24
        }
    }
    
  • Internet permission. REST calls and the checkout WebView need the INTERNET permission. Add it to android/app/src/main/AndroidManifest.xml (a direct child of <manifest>, before <application>):

    <uses-permission android:name="android.permission.INTERNET"/>
    

    Flutter's debug/profile manifests include this automatically, but the release manifest does not — add it explicitly so production builds can reach the gateway.

No Hybrid Composition or manual PlatformView registration is required — webview_flutter 4.x handles that internally.

iOS #

  • Deployment target. Set the platform to iOS 13.0 or higher in ios/Podfile, and match it in the Runner target's Minimum Deployments in Xcode:

    platform :ios, '13.0'
    
  • WKWebView is used automatically; no Info.plist entry is required to enable it.

  • App Transport Security. DigetPay endpoints and the hosted checkout page are served over HTTPS, so the default ATS policy works with no changes. You would only add an NSAppTransportSecurity exception to ios/Runner/Info.plist if you deliberately point baseUrl or your success/failure URLs at a non-HTTPS host (e.g. a local test server). Avoid a blanket NSAllowsArbitraryLoads in production.

Completion detection & result URLs (optional) #

The SDK detects the end of checkout when the WebView reaches a terminal page — DigetPay's own hosted result pages (…/pay/checkout/success and …/pay/checkout/failure) — and closes the WebView. The definitive success-vs-failure decision is not taken from that URL (the gateway may briefly route to /success before correcting to /failure); instead the SDK fetches the authoritative checkout status and decides from paymentStatus.

Because of that, setResultUrls(...) is optional and rarely needed. The SDK ships HTTPS defaults (kDigetPayDefaultSuccessUrl / kDigetPayDefaultFailureUrl) and also recognizes the gateway's own result pages by path. Call setResultUrls(successUrl:, failureUrl:) only if your account is configured to redirect to specific custom return URLs; if you do, use distinct HTTPS paths.

Supported platforms #

webview_flutter targets Android and iOS. Hosted checkout is not supported on Flutter web or desktop in this version.

Security requirement — mobile API key #

DigetPayConfig.apiKey is embedded in your app binary, and anything shipped in a mobile app can be extracted. Always initialize the SDK with a publishable / restricted mobile key scoped only to the client operations this SDK performs — never a full server secret. Rotate the key if it is ever exposed, and keep privileged operations behind your own server. This is why the plugin implements only the hosted (PCI-safe) card flow: raw card data never touches the device.

await DigetPaySdk.cardPay()
    .setOrder(DigetPaySaleOrder(
      id: orderId, description: 'Coffee', currency: 'SAR', amount: 15))
    .setPayer(DigetPayPayer(
      firstName: 'Demo', lastName: 'User', address: 'Riyadh',
      country: 'SA', city: 'Riyadh', zip: '00000',
      email: 'demo@example.com', phone: '+966500000000'))
    // .setResultUrls(...) is optional — omit to use the SDK defaults.
    .onTransactionSuccess((res) { /* res.status, res.transactionId ... */ })
    .onTransactionFailure((res) { /* res.message, res.errorCode */ })
    .onDismiss(() { /* user backed out */ })
    .start(context);

start() calls POST /payment/checkout/intiate, opens the returned redirectUrl in a WebView, and — once the hosted page reaches a result page — fetches GET /sdk/status?sessionId= and dispatches success or failure from the transaction's paymentStatus.

Hosted Checkout flow #

Flutter App
  │
  │  DigetPaySdk.cardPay()...start(context)
  ▼
POST /payment/checkout/intiate        (order + payer → flat body)
  │
  ▼
{ id, redirectUrl }
  │
  │  push CheckoutPage → load redirectUrl
  ▼
WebView (hosted page: card form + 3-D Secure)
  │
  ├─ reaches a result page (…/pay/checkout/success | /failure)
  │        │
  │        ▼
  │   GET /sdk/status?sessionId=<id>   (authoritative outcome)
  │        │
  │        ├─ paymentStatus == APPROVED ─▶ onTransactionSuccess(res) + pop
  │        └─ otherwise                 ─▶ onTransactionFailure(res) + pop
  │
  └─ user backs out (no result page) ───▶ onDismiss()

Notes:

  • intiate is spelled that way on the backend (kept verbatim so the docs match the wire call).
  • The terminal callback fires exactly once; onDismiss only fires when the page is popped without reaching a result page.
  • The status response is authoritative — the SDK does not trust the result URL alone, because the gateway can route to /success briefly before settling on /failure.

Other operations #

await DigetPaySdk.capture(transactionId: id, amount: 10);       // /payment/s2s/capture
await DigetPaySdk.voidd(id);                                     // /payment/s2s/void
await DigetPaySdk.refund(transactionId: id, amount: 10);         // /payment/refund
final bySession = await DigetPaySdk.getCheckoutStatus(sessionId); // /sdk/status?sessionId=
final byTxn     = await DigetPaySdk.getTransactionById(id);       // /payment/checkout/status?id=

capture/voidd/refund return a typed DigetPayResponse (isSuccess, status, message, transactionId, needs3ds, …). HTTP errors and declines are returned as an unsuccessful response — they do not throw. The status lookups return a typed Transaction? (a DECLINED transaction is still returned — check paymentStatus).

Handling the transaction data (sensitive fields) #

The status response carries the merchant's own transaction, which includes some sensitive fields — the SDK delivers them to you but never logs them:

  • pan — already masked by the backend (4323 2** **** 0853); safe to show.
  • cardHolderName — PII; display it, but don't log/persist broadly.
  • recurringTokensensitive: it can initiate future charges. Store it server-side, never log it, and don't surface it in the UI.

Access them via the typed model: res.transaction?.recurringToken, .rrn, .pan, etc. The built-in logger only ever emits a redacted summary (code/status/txn/rrn/…) and never these values.

Debug logging #

Pass an optional logger to initialize for a redacted, step-by-step trace of the flow — HTTP method + path + status, checkout milestones, WebView navigation paths, and the terminal outcome. It never receives the API key, card data, request/response bodies, or URL query values.

import 'dart:developer' as developer;

DigetPaySdk.initialize(
  apiKey: '<key>',
  baseUrl: kDigetPayDefaultBaseUrl,
  logger: (message) => developer.log(message, name: 'DigetPay'),
);

A successful checkout traces roughly like this (icons come from the example's digetPayLog):

💳 checkout: creating session for order 6f… (15.0 SAR)
➡️ → POST /payment/checkout/intiate
⬅️ ← 201 OK POST /payment/checkout/intiate {code=201, session=ab02…, redirect=https://fin-admin.digetpay.com/pay/checkout}
💳 checkout: session ab02… created → opening WebView
🌐 webview → https://fin-admin.digetpay.com/pay/checkout
🌐 webview → https://fin-admin.digetpay.com/pay/checkout/success
🌐 webview: ✓ terminal page reached
💳 checkout: terminal page → confirming via status
➡️ → GET /sdk/status?sessionId
⬅️ ← 200 OK GET /sdk/status {code=200, status=APPROVED, txn=070ae…, msg=Success}
✅ checkout: APPROVED (txnStatus=SUCCESS, payStatus=APPROVED, rrn=616510265041) → onTransactionSuccess

Each line carries a redacted response summary (code, result, status, txn/paymentId, session, redirect, err, msg) — the safe typed fields, never the raw body (which can hold a masked PAN, cardholder name, or tokens). Need the full payload? Read DigetPayResponse.data inside your callback.

Leave logger unset (the default) for zero logging in production. The webview → lines are especially useful for confirming where the hosted page redirects on completion — that redirect is what triggers the success/failure callbacks.

Not yet available #

sale (raw-card S2S — disabled to keep card data off-device), applePay (needs native wallet support), externalPayment, recurring, getTransactionByOrderId, and getTransactionByRrn return a guarded failure / null until the backend exposes the corresponding endpoints. See the TODO markers in the source.

1
likes
0
points
287
downloads

Publisher

unverified uploader

Weekly Downloads

Pure-Dart DigetPay payment plugin: hosted (PCI-safe) checkout via WebView plus transaction management over the DigetPay REST API.

Homepage

License

unknown (license)

Dependencies

flutter, http, uuid, webview_flutter

More

Packages that depend on digetpay_plugin

Packages that implement digetpay_plugin