|
|
Рядок 11: |
Рядок 11: |
|
| |
|
| <div style="text-align: center; color: #003366; font-size: 24px; font-family: Arial, sans-serif; font-weight: bold; margin-top: 20%;"> | | <div style="text-align: center; color: #003366; font-size: 24px; font-family: Arial, sans-serif; font-weight: bold; margin-top: 20%;"> |
|
| |
| ==== 1.1 Налаштування залежностей ====
| |
| У файлі '''settings.gradle''' (рівень проекту) додайте наступне:<syntaxhighlight lang="markdown">
| |
| pluginManagement {
| |
| val flutterSdkPath = run {
| |
| val properties = java.util.Properties()
| |
| file("local.properties").inputStream().use { properties.load(it) }
| |
| val flutterSdkPath = properties.getProperty("flutter.sdk")
| |
| require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
| |
| flutterSdkPath
| |
| }
| |
| includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
| |
| repositories {
| |
| google()
| |
| mavenCentral()
| |
| gradlePluginPortal()
| |
| }
| |
| }
| |
|
| |
| </syntaxhighlight>У файлі '''build.gradle''' (рівень додатку):<syntaxhighlight lang="markdown">
| |
| dependencies {
| |
| implementation("ua.easypay:EasyPay-Sdk:1.0.0-alpha8")
| |
| }
| |
| </syntaxhighlight>
| |
|
| |
| <br>
| |
|
| |
| ==== 1.2 Ініціалізація SDK в класі <code>Application</code> ====
| |
| У вашому класі '''Application''' додайте ініціалізацію EasyPay SDK:<syntaxhighlight lang="kotlin">
| |
| class FlutterApp : Application() {
| |
| override fun onCreate() {
| |
| super.onCreate()
| |
| EasyPaySdk.init(
| |
| context = PlatformContext(this),
| |
| secret = "your secret",
| |
| partnerKey = "your partner key"
| |
| )
| |
| }
| |
| }
| |
|
| |
| </syntaxhighlight>
| |
| <br>
| |
|
| |
| ==== 1.3 Створення <code>MethodChannel</code> для навігації на оплату та на перегляд/додавання/видалення карток ====
| |
| У файлі '''MainActivity''' реалізуйте <code>MethodChannel</code> для обробки методів оплати і роботи з картками:<syntaxhighlight lang="kotlin">
| |
| class MainActivity : FlutterFragmentActivity() {
| |
| private val CHANNEL = "com.example.sdk/payment"
| |
| private var pendingResult: MethodChannel.Result? = null
| |
| private val paymentLauncher = registerForActivityResult(SdkPaymentContract()) { sdkResult ->
| |
| pendingResult?.let { result ->
| |
| result.success(sdkResult?.toString())
| |
| pendingResult = null
| |
| }
| |
| }
| |
|
| |
| override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
| |
| super.configureFlutterEngine(flutterEngine)
| |
| MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
| |
| if (call.method == "startPayment") {
| |
| val args = call.arguments as? Map<*, *>
| |
| if (args != null) {
| |
| try {
| |
| val serviceKey = args["serviceKey"] as? String ?: throw IllegalArgumentException("Missing serviceKey")
| |
| val orderId = args["orderId"] as? String ?: throw IllegalArgumentException("Missing orderId")
| |
| val amount = (args["amount"] as? String)?.toDoubleOrNull() ?: throw IllegalArgumentException("Missing/invalid amount")
| |
| val description = args["description"] as? String ?: throw IllegalArgumentException("Missing description")
| |
| val additionalItems = (args["additionalItems"] as? Map<*, *>)?.mapKeys { it.key.toString() }?.mapValues { it.value.toString() }
| |
| val phoneNumber = args["phoneNumber"] as? String
| |
| val showPaymentResult = args["showPaymentResult"] as? Boolean ?: false
| |
| val paymentInstrumentArgs = PaymentInstrumentArgs(
| |
| serviceKey = serviceKey,
| |
| orderId = orderId,
| |
| amount = amount,
| |
| description = description,
| |
| additionalItems = additionalItems,
| |
| phoneNumber = phoneNumber
| |
| )
| |
| val sdkArgs = SdkPaymentContractArgs(
| |
| paymentInstrumentArgs = paymentInstrumentArgs,
| |
| showPaymentResult = showPaymentResult
| |
| )
| |
| pendingResult = result
| |
| paymentLauncher.launch(sdkArgs)
| |
|
| |
| } catch (e: Exception) {
| |
| result.error("INVALID_ARGS", "Failed to parse args: ${e.localizedMessage}", null)
| |
| }
| |
| } else {
| |
| result.error("INVALID_ARGS", "Args were null", null)
| |
| }
| |
| } else if (call.method == "openCardListScreen") {
| |
| val phoneNumber = call.argument<String>("phoneNumber") ?: ""
| |
| val args = SdkCardsContractArgs(phoneNumber = phoneNumber)
| |
| | |
| result.success(null)
| |
| } else {
| |
| result.notImplemented()
| |
| }
| |
| }
| |
| }
| |
| }
| |
|
| |
| </syntaxhighlight>
| |
|
| |
| <div style="text-align: center; color: #003366; font-size: 24px; font-family: Arial, sans-serif; font-weight: bold; margin-top: 20%;">
| |
|
| |
| == IOS частина ==
| |
| </div>
| |
| ----
| |
|
| |
| ==== 2.1 Підключення SDK ====
| |
| Для підключення SDK до iOS проекту необхідно завантажити '''EasyPaySdkIos.xcframework''' і вставити його в папку з проектом '''../YourProject/iOS/Runner/'''.
| |
| [[Файл:Знімок екрана 2025-06-11 о 12.42.46.png|центр|міні|600x600пкс]]
| |
|
| |
| Перевірте, чи з'явився фреймворк в розділі '''Frameworks, Libraries, and Embedded Content'''.
| |
|
| |
| Також додайте папку '''compose-resources''', яка знаходиться всередині '''EasyPaySdkIos.xcframework''', до '''Copy Bundle Resources'''.
| |
| [[Файл:Знімок екрана 2025-06-11 о 12.44.20.png|центр|міні|600x600пкс]]
| |
| [[Файл:Знімок екрана 2025-06-11 о 12.45.06.png|центр|міні|600x600пкс]]
| |
| <br>
| |
| <p style="border: 1px solid #FFA500; background-color: rgba(255, 165, 0, 0.1); padding: 15px; border-radius: 8px; font-family: Arial, sans-serif; font-size: 14px; font-weight: normal; color: #333; position: relative; width: 100%; display: block;">
| |
| ⚠️ <strong>Важливо!</strong> <br>
| |
| <br> При додаванні <span style="background-color: #EDEDED; padding: 2px 5px; border-radius: 4px; font-family: monospace; color: #D63384;">compose-resources</span> в діалозі додавання виберіть наступні опції: <br> 1. <strong>Destination:</strong> Resources <br> 2. <strong>Copy Items if Needed:</strong> Поставте галочку.
| |
| </p>
| |
| <br>
| |
|
| |
| ==== 2.2 Ініціалізація SDK в AppDelegate.swift ====
| |
| У файлі '''AppDelegate.swift''' додайте ініціалізацію SDK:<syntaxhighlight lang="swift">
| |
| import Flutter
| |
| import UIKit
| |
| import EasyPaySdkIos
| |
|
| |
| @main
| |
| @objc class AppDelegate: FlutterAppDelegate {
| |
| override func application(
| |
| _ application: UIApplication,
| |
| didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
| |
| ) -> Bool {
| |
| EasyPaySdk.shared.doInit(
| |
| context: PlatformContext(),
| |
| secret: "your secret",
| |
| partnerKey: "your partner key",
| |
| applePayMerchantId: "merchant.com.example"
| |
| )
| |
| GeneratedPluginRegistrant.register(with: self)
| |
| return super.application(application, didFinishLaunchingWithOptions: launchOptions)
| |
| }
| |
| }
| |
|
| |
| </syntaxhighlight>
| |
|
| |
| ==== 2.3 Створення MethodChannel для методів навігації на оплату та на перегляд/додавання/видалення карток ====
| |
| У файлі '''AppDelegate.swift''' додайте код для методів навігації та оплати:<syntaxhighlight lang="swift">
| |
| import Flutter
| |
| import UIKit
| |
| import EasyPaySdkIos
| |
|
| |
| @main
| |
| @objc class AppDelegate: FlutterAppDelegate {
| |
| override func application(
| |
| _ application: UIApplication,
| |
| didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
| |
| ) -> Bool {
| |
| EasyPaySdk.shared.doInit(
| |
| context: PlatformContext(),
| |
| secret: "your secret",
| |
| partnerKey: "your partner key",
| |
| applePayMerchantId: "merchant.com.example"
| |
| )
| |
| let controller = window?.rootViewController as! FlutterViewController
| |
| let channel = FlutterMethodChannel(name: "com.example.sdk/payment", binaryMessenger: controller.binaryMessenger)
| |
| channel.setMethodCallHandler { [weak controller] call, result in
| |
| if call.method == "startPayment" {
| |
| guard let args = call.arguments as? [String: Any] else {
| |
| result(FlutterError(code: "INVALID_ARGS", message: "Args were null", details: nil))
| |
| return
| |
| }
| |
| let vc = createPaymentVC(args: args) { sdkResult in
| |
| if let sdkResult = sdkResult {
| |
| result(sdkResult.description)
| |
| } else {
| |
| result("Cancelled")
| |
| }
| |
| }
| |
| controller?.present(vc, animated: true)
| |
| } else if call.method == "openCardListScreen" {
| |
| let phoneNumber = (call.arguments as? [String: Any])?["phoneNumber"] as? String ?? ""
| |
| let vc = SdkCardsViewControllerKt.SdkCardsViewController(
| |
| args: SdkCardsContractArgs(phoneNumber: phoneNumber, urlToNotifyMerchant: nil)
| |
| ) {
| |
| result(nil)
| |
| }
| |
| controller?.present(vc, animated: true)
| |
| } else {
| |
| result(FlutterMethodNotImplemented)
| |
| }
| |
| }
| |
| GeneratedPluginRegistrant.register(with: self)
| |
| return super.application(application, didFinishLaunchingWithOptions: launchOptions)
| |
| }
| |
| }
| |
|
| |
| </syntaxhighlight>
| |
|
| |
| == 3. Ініціалізація оплати ==
| |
| ----Для запуску оплати через Flutter використовуйте наступний код:<syntaxhighlight lang="dart">
| |
| SizedBox(
| |
| width: double.infinity,
| |
| child: FloatingActionButton.extended(
| |
| onPressed: () async {
| |
| final args = {
| |
| 'serviceKey': 'SomeServiceKey',
| |
| 'orderId': 'SomeOrderId',
| |
| 'amount': '3.0',
| |
| 'description': 'payment description',
| |
| 'phoneNumber': '380990000000', // Необов'язково
| |
| 'showPaymentResult': true,
| |
| };
| |
| try {
| |
| final result = await platform.invokeMethod('startPayment', args);
| |
| setState(() {
| |
| _paymentResult = result; // Це рядок, який повертається з Android
| |
| });
| |
| } on PlatformException catch (e) {
| |
| setState(() {
| |
| _paymentResult = "Не вдалося отримати результат оплати: '${e.message}'.";
| |
| });
| |
| }
| |
| },
| |
| label: const Text('Зробити платіж'),
| |
| ),
| |
| )
| |
|
| |
| </syntaxhighlight>
| |
|
| |
| == 4. Перехід на екран перегляду/додавання/видалення карток ==
| |
| ----<syntaxhighlight lang="dart">
| |
| SizedBox(
| |
| width: double.infinity,
| |
| child: FloatingActionButton.extended(
| |
| onPressed: () async {
| |
| final phoneNumber = _phoneNumberController.text;
| |
| try {
| |
| await platform.invokeMethod('openCardListScreen', {
| |
| 'phoneNumber': phoneNumber,
| |
| });
| |
| } on PlatformException catch (e) {
| |
| print('Не вдалося відкрити екран карток: ${e.message}');
| |
| }
| |
| },
| |
| label: const Text('Перейти до карток'),
| |
| ),
| |
| )
| |
|
| |
| </syntaxhighlight>
| |
|
| |
| === Підсумок ===
| |
|
| |
| # '''Налаштуйте залежності''' для Flutter у '''settings.gradle''' та '''build.gradle'''.
| |
| # '''Ініціалізуйте SDK''' в класах '''Application''' (для Android) та '''AppDelegate''' (для iOS).
| |
| # '''Запускайте оплату''' за допомогою '''MethodChannel''' у Flutter.
| |
| # '''Додайте функціонал для роботи з картками''' за допомогою навігації та <code>MethodChannel</code>.
| |
|
| |
| Ці кроки дозволяють вам інтегрувати EasyPay SDK у Flutter додаток для зручної та безпечної обробки платежів.
| |