lankapay_justpay_flutter 0.2.11
lankapay_justpay_flutter: ^0.2.11 copied to clipboard
Flutter plugin bridging LankaPay LPTrusted (JustPay): getDeviceId and createIdentityAndSign over MethodChannel justpay_sdk/methods. Host apps must supply bank JSON and SDK binaries per README.
Complete setup guide: lankapay_justpay_flutter #
This document is the full, ordered checklist for integrating the plugin. Follow it top to bottom the first time you integrate. Example XML in the Android and iOS sections matches common MID patterns for MNV cleartext hosts; always confirm values against your official MID.
Related files in this repo
| Item | Location |
|---|---|
| Short overview | README.md |
| Example app | example/ |
| Method channel name | justpay_sdk/methods |
Table of contents #
- Before you write any code
- Update your Flutter project
- Add the Dart dependency
- Android — LPTrusted AAR
- Android — Gradle (app module)
- Android — Config JSON in
res/raw - Android — Permissions (
AndroidManifest.xml) - Android — Network security (cleartext / MNV)
- Android — ProGuard / R8 (release)
- iOS — LPTrusted xcframework layout
- iOS — CocoaPods
- iOS — Bundle JSON
- iOS — App Transport Security (ATS)
- iOS — Xcode build settings
- iOS — Embed & Sign the framework
- Dart — Usage in your app
- Config JSON — Required keys (reference)
- Verify the integration
- Migrating from embedded native JustPay code
- Troubleshooting
1. Before you write any code #
Obtain from your bank / LankaPay onboarding (not from this open-source repo):
| Asset | Android | iOS |
|---|---|---|
justpay.json |
Place in res/raw |
Add to Runner bundle |
mnv.json |
Place in res/raw |
Add to Runner bundle |
| Native SDK | LPTrustedSDK.aar |
LPTrustedSDK.xcframework |
2. Update your Flutter project #
-
Use a stable Flutter channel and a Dart SDK compatible with the plugin’s
pubspec.yaml(environment.sdk). -
From your app root:
flutter upgrade flutter doctor -v
Fix any Android SDK / Xcode / CocoaPods issues flutter doctor reports before continuing.
3. Add the Dart dependency #
In your app’s pubspec.yaml:
dependencies:
flutter:
sdk: flutter
lankapay_justpay_flutter: ^0.2.11 # or path: / git: for your team
Then:
flutter pub get
Import:
import 'package:lankapay_justpay_flutter/lankapay_justpay_flutter.dart';
4. Android — LPTrusted AAR #
-
Create the folder
android/app/libs/if it does not exist. -
Copy the bank’s file
LPTrustedSDK.aarinto:android/app/libs/LPTrustedSDK.aarUse exactly this filename unless you change every Gradle reference yourself.
-
The plugin’s Android module uses
compileOnlyagainst:$rootProjectDir/app/libs/LPTrustedSDK.aar(same path relative to your Flutter app’s
android/folder). If this file is missing, Android Gradle fails with an explicit error from the plugin — that is expected until the AAR is present.
5. Android — Gradle (app module) #
Edit android/app/build.gradle or android/app/build.gradle.kts.
Kotlin DSL (build.gradle.kts) — recommended pattern #
Add a dependencies { } block (or merge into your existing one):
dependencies {
// Required: packages LPTrusted into the APK. The plugin only compileOnly-compiles against it.
implementation(files("libs/LPTrustedSDK.aar"))
// MID-aligned versions (OkHttp 4.9.3, json-simple non-transitive).
// The plugin also declares OkHttp + json-simple; duplicating here is optional but explicit.
implementation("com.squareup.okhttp3:okhttp:4.9.3")
implementation("com.googlecode.json-simple:json-simple:1.1.1") {
isTransitive = false
}
}
Groovy (build.gradle) #
dependencies {
implementation files('libs/LPTrustedSDK.aar')
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation('com.googlecode.json-simple:json-simple:1.1.1') {
transitive = false
}
}
If your build fails with duplicate classes from org.apache.commons.io.* or org.slf4j.*, add this in the app module:
configurations.configureEach {
exclude(group = "commons-io", module = "commons-io")
exclude(group = "org.slf4j", module = "slf4j-api")
}
configurations.all {
exclude group: "commons-io", module: "commons-io"
exclude group: "org.slf4j", module: "slf4j-api"
}
applicationId / flavors: The value of package inside justpay.json must match the built app’s applicationId (including flavor suffixes such as .dev). If they differ, identity and signing will fail.
6. Android — Config JSON in res/raw #
-
Copy your bank’s files to:
android/app/src/main/res/raw/justpay.jsonandroid/app/src/main/res/raw/mnv.json
-
Resource names are the filenames without extension:
justpayandmnv. Do not rename tojustpay_config.jsonunless you also change native loading logic (this plugin expects those two names). -
The plugin validates required keys before calling the SDK (see section 17).
7. Android — Permissions (AndroidManifest.xml) #
JustPay / LPTrusted needs network access. Declaring network state is optional but useful for connectivity-aware behavior.
Minimum recommended for JustPay networking #
Inside <manifest> (not inside <application>):
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Other permissions #
Typical banking apps also declare permissions for notifications, camera, biometric, and so on. Those are not required by this plugin unless your app uses those features. For JustPay-only networking, INTERNET (+ optionally ACCESS_NETWORK_STATE) is the core set.
Optional (only if your MID or bank doc says so): Some integrations mention telephony. Follow your MID if it requires READ_PHONE_STATE or similar.
Application attribute for network security #
On <application>, point to your XML config (see next section). Example:
<application
android:name="${applicationName}"
android:label="your_app_name"
android:icon="@mipmap/ic_launcher"
android:networkSecurityConfig="@xml/network_security_config">
<!-- activities, meta-data, etc. -->
</application>
8. Android — Network security (cleartext / MNV) #
Mobile network validation (MNV) often uses HTTP to specific operator endpoints. Android 9+ blocks cleartext unless you allow it per domain.
-
Create
android/app/src/main/res/xml/network_security_config.xml. -
Example content (replace domains with those from your MID if they differ):
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">mobileauth.ideabiz.lk</domain>
<domain includeSubdomains="true">gsmacnv.mobitel.lk</domain>
<domain includeSubdomains="true">apihub.hutch.lk</domain>
<domain includeSubdomains="true">heapihub.hutch.lk</domain>
</domain-config>
</network-security-config>
- Ensure
AndroidManifest.xmlreferences it (see section 7).
Important: If your bank’s MID lists different hosts for sandbox/production, replace these domains accordingly. The block above is an example, not a substitute for your MID.
9. Android — ProGuard / R8 (release) #
-
This plugin publishes
consumer-rules.prowith:-keep class com.lankapay.justpay.** { *; } -
If LankaPay or your bank supplies additional ProGuard rules, merge them into your app’s
proguard-rules.pro(or the rules file your release build uses). -
Always run a release build on a real device and exercise JustPay onboarding before store submission.
10. iOS — LPTrustedSDK via LPTrustedSDK_Vendored (recommended) #
lankapay_justpay_flutter is its own CocoaPods target (a separate dynamic framework). If you only link LPTrustedSDK.xcframework on the Runner app target in Xcode, Runner can build while the plugin pod still fails with Framework 'LPTrustedSDK' not found, because the linker search paths for the plugin target do not automatically inherit “whatever Runner linked”.
Recommended fix: use a tiny local pod LPTrustedSDK_Vendored that sets s.vendored_frameworks = '../LPTrustedSDK.xcframework'. CocoaPods then links and embeds LPTrusted for all dependents (Runner + plugin) in one pipeline.
-
Copy
doc/LPTrustedSDK_Vendored/into your app asios/LPTrustedSDK_Vendored/(keep the innerLPTrustedSDK_Vendored.podspec). -
Place the bank’s
LPTrustedSDK.xcframeworkatios/LPTrustedSDK.xcframework(sibling of the vendored folder). -
In
ios/Podfile, insidetarget 'Runner' do(beforeflutter_install_all_ios_pods):pod 'LPTrustedSDK_Vendored', :path => 'LPTrustedSDK_Vendored' -
Remove any manual Runner → Embed Frameworks entry for LPTrustedSDK if it causes a cycle with
[CP] Embed Pods Frameworks/ Thin Binary — let the pod own embed/link.
See doc/LPTrustedSDK_Vendored/README.txt for the full layout.
Optional: doc/LPTrustedSDK.podspec.example remains a generic template if you publish a spec-repo pod named LPTrustedSDK instead; the plugin expects the pod name LPTrustedSDK_Vendored as shipped in this repo.
11. iOS — CocoaPods #
-
Open a terminal at
your_app/ios/. -
Run:
pod install -
If you change the plugin version or iOS native deps, run again:
pod install --repo-update -
Open
Runner.xcworkspacein Xcode (notRunner.xcodeprojalone).
Podfile platform: Use at least iOS 13.0 (MID). Your team may standardize on a higher minimum; that is fine as long as it meets MID requirements.
12. iOS — Bundle JSON #
- In Xcode, select
justpay.jsonandmnv.json. - In the File inspector, under Target Membership, enable Runner.
- Confirm both appear under Build Phases → Copy Bundle Resources.
Filenames on disk should be justpay.json and mnv.json so Bundle.main.url(forResource:withExtension:) finds them.
13. iOS — App Transport Security (ATS) #
iOS blocks insecure HTTP unless you declare exceptions. Add NSAppTransportSecurity for the same operator hosts you allow in Android cleartext (example below; align with your MID):
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>mobileauth.ideabiz.lk</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>gsmacnv.mobitel.lk</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>apihub.hutch.lk</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>heapihub.hutch.lk</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
How to add in Xcode: Open Runner → Info.plist as source code, or use Information Property List editor: add App Transport Security Settings → Exception Domains and mirror the keys above.
Again: confirm hosts with your MID for non-production environments.
14. iOS — Xcode build settings #
Per MID:
| Setting | Value |
|---|---|
| iOS Deployment Target | ≥ 13.0 (MID minimum; your app may use a higher floor) |
| Enable Bitcode | No (MID) |
In Xcode: Runner target → Build Settings → search “Bitcode” → Enable Bitcode → No.
15. iOS — Verify Pod linking #
- Run
pod install --repo-updateand openRunner.xcworkspace. - Confirm
Podfile.locklistsLPTrustedSDK_Vendored(and thatpod installdid not skip it). - In Xcode, confirm
LPTrustedSDKappears for the Pods / Runner integration as provided by CocoaPods (do not duplicate manual embed unless your MID explicitly requires an extra step).
If you still see Framework 'LPTrustedSDK' not found, the plugin target is not getting the vendored pod: re-check the LPTrustedSDK_Vendored path pod line and that ios/LPTrustedSDK.xcframework exists next to that folder.
16. Dart — Usage in your app #
final justPay = LankapayJustpayFlutter();
// 1) Optional: device id for your backend
final deviceId = await justPay.getDeviceId();
// 2) challenge from your bank API; contentToSign = e.g. terms text user agreed to
final result = await justPay.createIdentityAndSign(
challenge: challengeFromApi,
contentToSign: termsPlainText,
);
if (result.success) {
final signature = result.signature;
final mobileReference = result.mobileReference;
// Send signature + mobileReference to your bank API per integration guide.
} else {
// Show result.message to the user or log for support.
}
Threading: Native callbacks complete on the platform main thread; the plugin returns a Future to Dart as usual.
17. Config JSON — Required keys (reference) #
These are validated before the SDK runs (mirroring typical native LPTrusted integration checks).
justpay.json (string values, non-empty after trim) #
| Key |
|---|
url |
package |
justpay_code |
key_encipher |
key_signer |
justpay_cert |
issuer |
mnv.json #
| Key |
|---|
dialog |
hutch |
mobitel |
If any are missing, you get a structured error message in the Dart result (Android) or the same shape from iOS.
18. Verify the integration #
Use this checklist on a physical device when possible (MNV often depends on real carrier data).
- ❌
flutter pub getsucceeds. - ❌
cd ios && pod installsucceeds. - ❌ Android:
LPTrustedSDK.aarexists atandroid/app/libs/LPTrustedSDK.aar. - ❌ Android:
justpay.json/mnv.jsonexist underres/raw/with correct names. - ❌ Android:
network_security_config.xmlpresent and referenced in the manifest. - ❌ iOS:
LPTrustedSDK.xcframeworkatios/LPTrustedSDK.xcframework,LPTrustedSDK_Vendoredfolder copied toios/LPTrustedSDK_Vendored/, andpod 'LPTrustedSDK_Vendored', :path => 'LPTrustedSDK_Vendored'inios/Podfile;pod installsucceeds. - ❌ iOS: JSON files in Copy Bundle Resources.
- ❌ iOS: ATS exceptions for the four domains (or MID-approved set).
- ❌
justpay.jsonpackagematches AndroidapplicationId. - ❌
getDeviceIdreturns a non-empty string when the SDK is correctly linked (empty often means iOS framework not linked or stub path). - ❌
createIdentityAndSigncompletes withsuccess: truein a full test onboarding (uses bank sandbox as directed).
19. Migrating from embedded native JustPay code #
If you previously registered a custom MethodChannel in MainActivity / FlutterActivity or AppDelegate that called LPTrusted directly:
- Add
lankapay_justpay_fluttertopubspec.yaml. - Remove your custom JustPay
MethodChannelsetup and any duplicate LPTrusted handler classes from the host app (the plugin registersjustpay_sdk/methodson its own). - Replace your Dart bridge class with
LankapayJustpayFlutterfrom this package. - Keep Firebase, notifications, other channels, and unrelated manifest keys as they are.
- Run full JustPay regression on Android and iOS.
20. Troubleshooting #
| Symptom | What to check |
|---|---|
| Gradle: AAR not found | Path android/app/libs/LPTrustedSDK.aar and spelling of filename. |
Gradle: duplicate classes (org.apache.commons.io.* / org.slf4j.*) |
LPTrustedSDK AAR may already include commons-io and slf4j-api. Exclude external duplicates in app Gradle using configurations.configureEach { exclude(...) } (Kotlin DSL) or configurations.all { exclude ... } (Groovy), then run flutter clean. |
| Android: “Missing res/raw/…” | Files named justpay.json / mnv.json under app/src/main/res/raw/. |
| Android: cleartext / SSL errors | network_security_config.xml domains vs MID; manifest networkSecurityConfig. |
Android: package mismatch |
justpay.json package vs applicationId (flavors). |
iOS: Framework 'LPTrustedSDK' not found |
Use LPTrustedSDK_Vendored path pod + ios/LPTrustedSDK.xcframework; remove duplicate manual Runner embed if it cycles with [CP] Embed Pods Frameworks. |
iOS: import LPTrustedSDK / link errors |
Verify LPTrustedSDK_Vendored in Podfile and Podfile.lock, run pod install --repo-update, open Runner.xcworkspace. |
| iOS: HTTP load fails | ATS entries in Info.plist for operator hosts. |
iOS: empty getDeviceId |
LPTrustedSDK not linked at compile time (stub) or SDK not initialized; verify LPTrustedSDK_Vendored resolves and #if canImport(LPTrustedSDK) is true on device. |
Dart: success: false with config message |
JSON keys missing/wrong; read message string. |
| Debug logs (recommended) | Android: view logcat and filter by tag LankapayJustpay. iOS: view the Xcode console for lines starting with [LankapayJustpay]. Dart: debug console output (only in debug mode). |
| Debug mocks (optional) | In debug builds you can enable failure simulation as success. This can help you continue UI/backend registration flow without native success. Enable with LankapayJustpayFlutter(enableDebugMocks: true). Backend may still reject dummy signature or mobileReference if it validates strictly. |
| Release-only crashes | R8/ProGuard rules; test release on device. |
Quick command recap #
# From app root
flutter pub get
cd ios && pod install && cd ..
# Android
cd android && ./gradlew :app:assembleDebug && cd ..
# iOS (from app root)
flutter build ios --no-codesign
If anything in this guide conflicts with your bank’s MID, the MID wins.