From f29a89075ec16fe32f839f8cfeb00a057a6df5a1 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 15 Apr 2025 01:50:05 +0300 Subject: [PATCH 01/18] added support for new payment network himyan --- pay_ios/ios/Classes/PaymentExtensions.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pay_ios/ios/Classes/PaymentExtensions.swift b/pay_ios/ios/Classes/PaymentExtensions.swift index 3fe1a9d..cfb24e5 100644 --- a/pay_ios/ios/Classes/PaymentExtensions.swift +++ b/pay_ios/ios/Classes/PaymentExtensions.swift @@ -147,6 +147,9 @@ extension PKPaymentNetwork { case "girocard": guard #available(iOS 14.0, *) else { return nil } return .girocard + case "himyan": + guard #available(iOS 18.4, *) else { return nil } + return .himyan case "idCredit": return .idCredit case "interac": From b2eed5b1852b67d8ad7bd93b1d94875a51a0e948 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani <63131654+thp-42@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:41:07 +0300 Subject: [PATCH 02/18] Update pay_ios dependency to use Git repository --- pay/pubspec.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pay/pubspec.yaml b/pay/pubspec.yaml index 3bcb958..0652450 100644 --- a/pay/pubspec.yaml +++ b/pay/pubspec.yaml @@ -35,7 +35,11 @@ dependencies: flutter_localizations: sdk: flutter pay_android: ^3.1.1 - pay_ios: ^1.1.0 + pay_ios: + git: + url: https://github.com/dibsyhq/flutter-plugin.git + ref: main + path: pay_ios pay_platform_interface: ^2.0.0 meta: ^1.10.0 From 39ef35fe40f51f799515400d16a93c43777affe2 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Mon, 1 Dec 2025 10:46:44 +0300 Subject: [PATCH 03/18] Add support for supportedCountries configuration --- pay_ios/ios/Classes/PaymentHandler.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 887aadf..47f56d5 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -166,6 +166,13 @@ class PaymentHandler: NSObject { if let supportedNetworks = supportedNetworks(from: paymentConfigurationString) { paymentRequest.supportedNetworks = supportedNetworks } + + // Add supported countries if available (iOS 11+). + if #available(iOS 11.0, *) { + if let supportedCountries = paymentConfiguration["supportedCountries"] as? Array { + paymentRequest.supportedCountries = Set(supportedCountries) + } + } return paymentRequest } From 0da18cd0419578bcbb05649a7d2627395f083fb7 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 09:29:52 +0300 Subject: [PATCH 04/18] log paymentselection --- pay_ios/ios/Classes/PaymentHandler.swift | 55 ++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 47f56d5..b18dc1b 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -181,9 +181,58 @@ class PaymentHandler: NSObject { /// Extension that implements the completion methods in the delegate to respond to user selection. extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { - func paymentAuthorizationControllerWillAuthorizePayment(_ controller: PKPaymentAuthorizationController) { - paymentHandlerStatus = .authorizationStarted - } + func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { + + print("\n--- 🟢 DEBUG: PAYMENT METHOD SELECTED 🟢 ---") + + // 1. Display Name (e.g. "Visa 1234") + print("Display Name: \(paymentMethod.displayName ?? "nil")") + + // 2. Network (e.g. "Visa", "Amex") + if let network = paymentMethod.network { + print("Network (Raw Value): \(network.rawValue)") + } else { + print("Network: nil") + } + + // 3. Card Type + var typeString = "Unknown" + switch paymentMethod.type { + case .debit: typeString = "Debit" + case .credit: typeString = "Credit" + case .prepaid: typeString = "Prepaid" + case .store: typeString = "Store" + case .eMoney: typeString = "eMoney" + @unknown default: typeString = "Unknown Default" + } + print("Type: \(typeString)") + + // 4. Secure Element Pass (The actual digital card reference in Wallet) + // This is often nil in the simulator, but valuable on real devices + if let pass = paymentMethod.secureElementPass { + print("Secure Element Pass Found:") + print(" - Device Account ID: \(pass.deviceAccountIdentifier ?? "nil")") + print(" - Activation State: \(pass.passActivationState.rawValue)") + } else { + print("Secure Element Pass: nil") + } + + // 5. Billing Address (Often nil until full authorization, but good to check) + if let billing = paymentMethod.billingAddress { + print("Billing Address Contact Found: \(billing)") + } else { + print("Billing Address: nil (User has not fully authorized yet)") + } + + print("--------------------------------------------\n") + + // CRASH/FAIL LOGIC: + // We are returning an empty item list. This will cause the Apple Pay sheet + // to either show a $0 transaction or error out, stopping the flow here. + let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) + completion(emptyUpdate) + + } func paymentAuthorizationController(_: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { From 0b879542d3cb315a1c6bc1493aa0f6c37e82736b Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 09:50:57 +0300 Subject: [PATCH 05/18] billing address --- pay_ios/ios/Classes/PaymentHandler.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index b18dc1b..18fdd18 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -217,12 +217,6 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { print("Secure Element Pass: nil") } - // 5. Billing Address (Often nil until full authorization, but good to check) - if let billing = paymentMethod.billingAddress { - print("Billing Address Contact Found: \(billing)") - } else { - print("Billing Address: nil (User has not fully authorized yet)") - } print("--------------------------------------------\n") From df4696f3cd50c7ed9e7c7cb21e2a7713ba4d3465 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 09:55:10 +0300 Subject: [PATCH 06/18] just logging --- pay_ios/ios/Classes/PaymentHandler.swift | 35 +----------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 18fdd18..e6d4590 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -186,43 +186,10 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { print("\n--- 🟢 DEBUG: PAYMENT METHOD SELECTED 🟢 ---") // 1. Display Name (e.g. "Visa 1234") - print("Display Name: \(paymentMethod.displayName ?? "nil")") + print("Display Name: \(paymentMethod ?? "nil")") - // 2. Network (e.g. "Visa", "Amex") - if let network = paymentMethod.network { - print("Network (Raw Value): \(network.rawValue)") - } else { - print("Network: nil") - } - - // 3. Card Type - var typeString = "Unknown" - switch paymentMethod.type { - case .debit: typeString = "Debit" - case .credit: typeString = "Credit" - case .prepaid: typeString = "Prepaid" - case .store: typeString = "Store" - case .eMoney: typeString = "eMoney" - @unknown default: typeString = "Unknown Default" - } - print("Type: \(typeString)") - - // 4. Secure Element Pass (The actual digital card reference in Wallet) - // This is often nil in the simulator, but valuable on real devices - if let pass = paymentMethod.secureElementPass { - print("Secure Element Pass Found:") - print(" - Device Account ID: \(pass.deviceAccountIdentifier ?? "nil")") - print(" - Activation State: \(pass.passActivationState.rawValue)") - } else { - print("Secure Element Pass: nil") - } - - - print("--------------------------------------------\n") - // CRASH/FAIL LOGIC: // We are returning an empty item list. This will cause the Apple Pay sheet - // to either show a $0 transaction or error out, stopping the flow here. let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) completion(emptyUpdate) From e1f8018f76484227fdcc48f2d9f8d004eb94dfe7 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 10:14:41 +0300 Subject: [PATCH 07/18] dumpdata --- pay_ios/ios/Classes/PaymentHandler.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index e6d4590..123a5dc 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -183,17 +183,16 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { - print("\n--- 🟢 DEBUG: PAYMENT METHOD SELECTED 🟢 ---") - - // 1. Display Name (e.g. "Visa 1234") - print("Display Name: \(paymentMethod ?? "nil")") + ("\n--- 🟢 DUMPING PAYMENT METHOD 🟢 ---") + // This prints the whole structure recursively + dump(paymentMethod) // CRASH/FAIL LOGIC: // We are returning an empty item list. This will cause the Apple Pay sheet let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) completion(emptyUpdate) - } + } func paymentAuthorizationController(_: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { From 9b5340ba6fed10d1564a5e9fea4205ec587d7947 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 10:22:17 +0300 Subject: [PATCH 08/18] payment method log --- pay_ios/ios/Classes/PaymentHandler.swift | 51 +++++++++++++++++++----- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 123a5dc..1038d67 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -182,16 +182,47 @@ class PaymentHandler: NSObject { extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { - - ("\n--- 🟢 DUMPING PAYMENT METHOD 🟢 ---") - - // This prints the whole structure recursively - dump(paymentMethod) - // CRASH/FAIL LOGIC: - // We are returning an empty item list. This will cause the Apple Pay sheet - let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) - completion(emptyUpdate) - + + print("\n--- 🟢 MANUAL DATA INSPECTION 🟢 ---") + + // 1. Display Name (The text shown to user, e.g., "Visa 1234") + let name = paymentMethod.displayName ?? "nil" + print("Name: \(name)") + + // 2. Network (The card scheme, e.g., Visa, MasterCard, Amex) + // We use .rawValue to get the string representation + if let net = paymentMethod.network { + print("Network: \(net.rawValue)") + } else { + print("Network: nil") + } + + // 3. Type (Debit, Credit, etc.) + // We must switch on the Enum to get a readable string + let typeStr: String + switch paymentMethod.type { + case .debit: typeStr = "Debit" + case .credit: typeStr = "Credit" + case .prepaid: typeStr = "Prepaid" + case .store: typeStr = "Store Card" + case .eMoney: typeStr = "eMoney" + default: typeStr = "Unknown" + } + print("Type: \(typeStr)") + + // 4. Secure Element Pass (Advanced usage, often nil at this stage) + if let pass = paymentMethod.secureElementPass { + print("Pass Activation State: \(pass.passActivationState.rawValue)") + print("Device Account ID: \(pass.deviceAccountIdentifier ?? "nil")") + } else { + print("Secure Pass Object: nil") + } + + print("--------------------------------------\n") + + // Return empty update to keep the sheet alive + let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) + completion(emptyUpdate) } func paymentAuthorizationController(_: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { From 3bb3147fef3202811d1c92621fa4e7882d94bfd5 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 10:26:59 +0300 Subject: [PATCH 09/18] secureelementpass update --- pay_ios/ios/Classes/PaymentHandler.swift | 51 ++++++++++-------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 1038d67..3d46d26 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -183,43 +183,32 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { - print("\n--- 🟢 MANUAL DATA INSPECTION 🟢 ---") + print("\n--- 🟢 PAYMENT METHOD LOG 🟢 ---") - // 1. Display Name (The text shown to user, e.g., "Visa 1234") - let name = paymentMethod.displayName ?? "nil" - print("Name: \(name)") + // 1. Basic Info (Available on all versions) + print("Name: \(paymentMethod.displayName ?? "nil")") + print("Network: \(paymentMethod.network?.rawValue ?? "nil")") - // 2. Network (The card scheme, e.g., Visa, MasterCard, Amex) - // We use .rawValue to get the string representation - if let net = paymentMethod.network { - print("Network: \(net.rawValue)") + // 2. Secure Element Pass (Restricted to iOS 13.4+) + if #available(iOS 13.4, *) { + // It is safe to access secureElementPass inside this block + if let pass = paymentMethod.secureElementPass { + print("Secure Pass: Found") + print(" - Activation State: \(pass.passActivationState.rawValue)") + print(" - Device Account ID: \(pass.deviceAccountIdentifier ?? "nil")") + + // Primary Account Identifier is often what banks/payment processors need for verification + print(" - Primary Account ID: \(pass.primaryAccountIdentifier ?? "nil")") + } else { + print("Secure Pass: nil (Object is empty)") + } } else { - print("Network: nil") + // Logic for users on iOS 13.3 or older + print("Secure Pass: Not checked (Requires iOS 13.4+)") } - // 3. Type (Debit, Credit, etc.) - // We must switch on the Enum to get a readable string - let typeStr: String - switch paymentMethod.type { - case .debit: typeStr = "Debit" - case .credit: typeStr = "Credit" - case .prepaid: typeStr = "Prepaid" - case .store: typeStr = "Store Card" - case .eMoney: typeStr = "eMoney" - default: typeStr = "Unknown" - } - print("Type: \(typeStr)") - - // 4. Secure Element Pass (Advanced usage, often nil at this stage) - if let pass = paymentMethod.secureElementPass { - print("Pass Activation State: \(pass.passActivationState.rawValue)") - print("Device Account ID: \(pass.deviceAccountIdentifier ?? "nil")") - } else { - print("Secure Pass Object: nil") - } + print("--------------------------------\n") - print("--------------------------------------\n") - // Return empty update to keep the sheet alive let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) completion(emptyUpdate) From 8ee9045e134e9def150a8fc3330b241f2ad90686 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 10:38:14 +0300 Subject: [PATCH 10/18] log payment method and remove secureelementpass --- pay_ios/ios/Classes/PaymentHandler.swift | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 3d46d26..eef2045 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -188,25 +188,7 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { // 1. Basic Info (Available on all versions) print("Name: \(paymentMethod.displayName ?? "nil")") print("Network: \(paymentMethod.network?.rawValue ?? "nil")") - - // 2. Secure Element Pass (Restricted to iOS 13.4+) - if #available(iOS 13.4, *) { - // It is safe to access secureElementPass inside this block - if let pass = paymentMethod.secureElementPass { - print("Secure Pass: Found") - print(" - Activation State: \(pass.passActivationState.rawValue)") - print(" - Device Account ID: \(pass.deviceAccountIdentifier ?? "nil")") - - // Primary Account Identifier is often what banks/payment processors need for verification - print(" - Primary Account ID: \(pass.primaryAccountIdentifier ?? "nil")") - } else { - print("Secure Pass: nil (Object is empty)") - } - } else { - // Logic for users on iOS 13.3 or older - print("Secure Pass: Not checked (Requires iOS 13.4+)") - } - + print("Type: \(paymentMethod.type.stringValue)") print("--------------------------------\n") // Return empty update to keep the sheet alive From 4f3b79f3420b13503261f80f300369f84bf3b02f Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 10:42:26 +0300 Subject: [PATCH 11/18] log payment method --- pay_ios/ios/Classes/PaymentHandler.swift | 34 +++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index eef2045..1ccf80e 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -183,13 +183,19 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { - print("\n--- 🟢 PAYMENT METHOD LOG 🟢 ---") - - // 1. Basic Info (Available on all versions) - print("Name: \(paymentMethod.displayName ?? "nil")") - print("Network: \(paymentMethod.network?.rawValue ?? "nil")") - print("Type: \(paymentMethod.type.stringValue)") - print("--------------------------------\n") + // 1. Name (Handle optional) + let nameString = paymentMethod.displayName ?? "Unknown" + + // 2. Network (Extract raw string value) + let networkString = paymentMethod.network?.rawValue ?? "Unknown" + + // 3. Type (Uses the extension below) + let typeString = paymentMethod.type.stringValue + + // Log them to verify + print("Name: \(nameString)") + print("Network: \(networkString)") + print("Type: \(typeString)") // Return empty update to keep the sheet alive let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) @@ -226,3 +232,17 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { } } } + + +extension PKPaymentMethodType { + var stringValue: String { + switch self { + case .debit: return "Debit" + case .credit: return "Credit" + case .prepaid: return "Prepaid" + case .store: return "Store" + case .eMoney: return "eMoney" + default: return "Unknown" + } + } +} \ No newline at end of file From 9c4f50f1c415bb0e156bcf741aa1549ce32b1106 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 11:05:02 +0300 Subject: [PATCH 12/18] network fixes --- pay_ios/ios/Classes/PaymentHandler.swift | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 1ccf80e..8b6f60c 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -187,8 +187,7 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { let nameString = paymentMethod.displayName ?? "Unknown" // 2. Network (Extract raw string value) - let networkString = paymentMethod.network?.rawValue ?? "Unknown" - + let networkString = paymentMethod.network?.stringValue ?? "Unknown" // 3. Type (Uses the extension below) let typeString = paymentMethod.type.stringValue @@ -245,4 +244,24 @@ extension PKPaymentMethodType { default: return "Unknown" } } +} + + +extension PKPaymentNetwork { + var stringValue: String { + switch self { + case .visa: return "Visa" + case .masterCard: return "MasterCard" + case .amex: return "American Express" + case .discover: return "Discover" + case .JCB: return "JCB" + case .chinaUnionPay: return "UnionPay" + case .interac: return "Interac" + case .maestro: return "Maestro" + case .electron: return "Visa Electron" + case .vPay: return "V Pay" + // Add regional networks if needed (e.g., Mada, Suica, etc.) + default: return self.rawValue // Fallback to Apple's default string + } + } } \ No newline at end of file From 82983a0b1627ec3fa8f3b76a91880e5f3dfd86f1 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 11:11:05 +0300 Subject: [PATCH 13/18] paymetn network detection --- pay_ios/ios/Classes/PaymentHandler.swift | 36 +++++++++--------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 8b6f60c..4647c7f 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -186,14 +186,23 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { // 1. Name (Handle optional) let nameString = paymentMethod.displayName ?? "Unknown" - // 2. Network (Extract raw string value) - let networkString = paymentMethod.network?.stringValue ?? "Unknown" - // 3. Type (Uses the extension below) + let rawNetwork = paymentMethod.network + var detectedNetwork = "Unknown" + + // --- CHECK 1: The Official Way (System Constants) --- + if rawNetwork == .visa { + detectedNetwork = "Visa" + } else if rawNetwork == .masterCard { + detectedNetwork = "MasterCard" + } else if rawNetwork == .amex { + detectedNetwork = "Amex" + } + let typeString = paymentMethod.type.stringValue // Log them to verify print("Name: \(nameString)") - print("Network: \(networkString)") + print("Network: \(detectedNetwork)") print("Type: \(typeString)") // Return empty update to keep the sheet alive @@ -246,22 +255,3 @@ extension PKPaymentMethodType { } } - -extension PKPaymentNetwork { - var stringValue: String { - switch self { - case .visa: return "Visa" - case .masterCard: return "MasterCard" - case .amex: return "American Express" - case .discover: return "Discover" - case .JCB: return "JCB" - case .chinaUnionPay: return "UnionPay" - case .interac: return "Interac" - case .maestro: return "Maestro" - case .electron: return "Visa Electron" - case .vPay: return "V Pay" - // Add regional networks if needed (e.g., Mada, Suica, etc.) - default: return self.rawValue // Fallback to Apple's default string - } - } -} \ No newline at end of file From fedd5b34dfa12a66acdecc2c42cbdf1f5ea3d83d Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 16:07:34 +0300 Subject: [PATCH 14/18] credit card surcharge test --- pay_ios/ios/Classes/PaymentHandler.swift | 86 +++++++++++++++--------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 4647c7f..d071994 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -183,31 +183,55 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { - // 1. Name (Handle optional) - let nameString = paymentMethod.displayName ?? "Unknown" - - let rawNetwork = paymentMethod.network - var detectedNetwork = "Unknown" - - // --- CHECK 1: The Official Way (System Constants) --- - if rawNetwork == .visa { - detectedNetwork = "Visa" - } else if rawNetwork == .masterCard { - detectedNetwork = "MasterCard" - } else if rawNetwork == .amex { - detectedNetwork = "Amex" - } - - let typeString = paymentMethod.type.stringValue - - // Log them to verify - print("Name: \(nameString)") - print("Network: \(detectedNetwork)") - print("Type: \(typeString)") - - // Return empty update to keep the sheet alive - let emptyUpdate = PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: []) - completion(emptyUpdate) +let isCredit = paymentMethod.type == .credit + + // 2. Start with the clean, original list of items + // We make a copy so we don't permanently modify the base list + var currentItems = self.baseSummaryItems + + if isCredit { + // 3. Logic to add 2.5% Surcharge + + // Grab the original Total (usually the last item in the array) + if let originalTotalItem = currentItems.last { + + let originalAmount = originalTotalItem.amount + + // Define 2.5% + let surchargeRate = NSDecimalNumber(string: "0.025") + + // Calculate Surcharge: Amount * 0.025 + let rawSurcharge = originalAmount.multiplying(by: surchargeRate) + + // Round to 2 decimal places (Currency standard) + let behavior = NSDecimalNumberHandler(roundingMode: .plain, + scale: 2, + raiseOnExactness: false, + raiseOnOverflow: false, + raiseOnUnderflow: false, + raiseOnDivideByZero: false) + let surchargeAmount = rawSurcharge.rounding(accordingToBehavior: behavior) + + // Create the Surcharge Line Item + let surchargeItem = PKPaymentSummaryItem(label: "Credit Card Surcharge (2.5%)", amount: surchargeAmount) + + // Calculate New Grand Total + let newTotalAmount = originalAmount.adding(surchargeAmount) + let newTotalItem = PKPaymentSummaryItem(label: originalTotalItem.label, amount: newTotalAmount) + + // Remove the old total from the list + currentItems.removeLast() + + // Add the Surcharge Item + currentItems.append(surchargeItem) + + // Add the New Grand Total + currentItems.append(newTotalItem) + } + } + + // 4. Return the update (Either the list with surcharge, or the original clean list) + completion(PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: currentItems)) } func paymentAuthorizationController(_: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { @@ -245,12 +269,12 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { extension PKPaymentMethodType { var stringValue: String { switch self { - case .debit: return "Debit" - case .credit: return "Credit" - case .prepaid: return "Prepaid" - case .store: return "Store" - case .eMoney: return "eMoney" - default: return "Unknown" + case .debit: return "debit" + case .credit: return "credit" + case .prepaid: return "prepaid" + case .store: return "store" + case .eMoney: return "emoney" + default: return "unknown" } } } From 1d78012257c7e7af12e1ba29a010d4af157827a2 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 16:14:40 +0300 Subject: [PATCH 15/18] add baseSummaryItems to payment handler class --- pay_ios/ios/Classes/PaymentHandler.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index d071994..0d396db 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -36,6 +36,10 @@ enum PaymentHandlerStatus { /// paymentHandler.canMakePayments(stringArguments) /// ``` class PaymentHandler: NSObject { + + // CHANGE 1: Define the variable here so the class owns it. + // This stores the original prices without any surcharges. + var baseSummaryItems: [PKPaymentSummaryItem] = [] /// Holds the current status of the payment process. var paymentHandlerStatus: PaymentHandlerStatus! @@ -80,6 +84,7 @@ class PaymentHandler: NSObject { return } + self.baseSummaryItems = paymentRequest.paymentSummaryItems // Display the payment selector with the request created. let paymentController = PKPaymentAuthorizationController(paymentRequest: paymentRequest) paymentController.delegate = self @@ -183,7 +188,7 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { -let isCredit = paymentMethod.type == .credit + let isCredit = paymentMethod.type == .credit // 2. Start with the clean, original list of items // We make a copy so we don't permanently modify the base list From 80ae6112f462e757efe4d61cd4d73bf0354f441d Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 22:38:15 +0300 Subject: [PATCH 16/18] fix amount --- pay_ios/ios/Classes/PaymentHandler.swift | 96 ++++++++++++------------ 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index 0d396db..b720e1e 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -41,6 +41,7 @@ class PaymentHandler: NSObject { // This stores the original prices without any surcharges. var baseSummaryItems: [PKPaymentSummaryItem] = [] + var creditSurchargeRate: NSDecimalNumber = .zero /// Holds the current status of the payment process. var paymentHandlerStatus: PaymentHandlerStatus! @@ -78,6 +79,18 @@ class PaymentHandler: NSObject { // Reset payment handler status paymentHandlerStatus = .started + self.creditSurchargeRate = .zero // Reset to 0 before every new payment + + if let configDict = PaymentHandler.extractPaymentConfiguration(from: paymentConfiguration) { + if let processingFee = configDict["processingFee"] as? [String: Any], + let creditRate = processingFee["credit"] as? Double { + + // Convert "2.5" (percentage) to "0.025" (multiplier) + let multiplier = creditRate / 100.0 + self.creditSurchargeRate = NSDecimalNumber(value: multiplier) + } + } + // Deserialize payment configuration. guard let paymentRequest = PaymentHandler.createPaymentRequest(from: paymentConfiguration, paymentItems: paymentItems) else { result(FlutterError(code: "invalidPaymentConfiguration", message: "It was not possible to create a payment request from the provided configuration. Review your payment configuration and run again", details: nil)) @@ -187,55 +200,46 @@ class PaymentHandler: NSObject { extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { - + let isCredit = paymentMethod.type == .credit - - // 2. Start with the clean, original list of items - // We make a copy so we don't permanently modify the base list - var currentItems = self.baseSummaryItems - - if isCredit { - // 3. Logic to add 2.5% Surcharge - // Grab the original Total (usually the last item in the array) - if let originalTotalItem = currentItems.last { - - let originalAmount = originalTotalItem.amount - - // Define 2.5% - let surchargeRate = NSDecimalNumber(string: "0.025") - - // Calculate Surcharge: Amount * 0.025 - let rawSurcharge = originalAmount.multiplying(by: surchargeRate) - - // Round to 2 decimal places (Currency standard) - let behavior = NSDecimalNumberHandler(roundingMode: .plain, - scale: 2, - raiseOnExactness: false, - raiseOnOverflow: false, - raiseOnUnderflow: false, - raiseOnDivideByZero: false) - let surchargeAmount = rawSurcharge.rounding(accordingToBehavior: behavior) - - // Create the Surcharge Line Item - let surchargeItem = PKPaymentSummaryItem(label: "Credit Card Surcharge (2.5%)", amount: surchargeAmount) - - // Calculate New Grand Total - let newTotalAmount = originalAmount.adding(surchargeAmount) - let newTotalItem = PKPaymentSummaryItem(label: originalTotalItem.label, amount: newTotalAmount) - - // Remove the old total from the list - currentItems.removeLast() - - // Add the Surcharge Item - currentItems.append(surchargeItem) + // 1. Start with the clean, original list of items + var currentItems = self.baseSummaryItems + + // 2. Check if it is credit AND if we actually have a rate > 0 + if isCredit && self.creditSurchargeRate.compare(.zero) == .orderedDescending { - // Add the New Grand Total - currentItems.append(newTotalItem) - } - } - - // 4. Return the update (Either the list with surcharge, or the original clean list) + if let originalTotalItem = currentItems.last { + + let originalAmount = originalTotalItem.amount + + // Calculate the multiplier (e.g. 1.025 for a 2.5% increase) + let one = NSDecimalNumber(value: 1) + let multiplier = one.adding(self.creditSurchargeRate) + + // Calculate New Total: Original * 1.025 + let rawNewTotal = originalAmount.multiplying(by: multiplier) + + // Round to 2 decimal places + let behavior = NSDecimalNumberHandler(roundingMode: .plain, + scale: 2, + raiseOnExactness: false, + raiseOnOverflow: false, + raiseOnUnderflow: false, + raiseOnDivideByZero: false) + + let finalNewTotal = rawNewTotal.rounding(accordingToBehavior: behavior) + + // Create the New Total Item + // We reuse the original label (e.g., "Total" or "Dibsy") but use the new higher price + let newTotalItem = PKPaymentSummaryItem(label: originalTotalItem.label, amount: finalNewTotal) + + // Remove the old total and add the new higher total + currentItems.removeLast() + currentItems.append(newTotalItem) + } + } + completion(PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: currentItems)) } From 2cee13e3c11dd4954e893348da21e0281d3d24b4 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Tue, 2 Dec 2025 22:41:09 +0300 Subject: [PATCH 17/18] fix --- pay_ios/ios/Classes/PaymentHandler.swift | 69 ++++++++++++------------ 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index b720e1e..bcc2073 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -202,43 +202,42 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { let isCredit = paymentMethod.type == .credit + + // 1. Start with the clean, original list of items + var currentItems = self.baseSummaryItems + + // CHANGE: Use 'NSDecimalNumber.zero' explicitly because 'compare' expects an NSNumber + if isCredit && self.creditSurchargeRate.compare(NSDecimalNumber.zero) == .orderedDescending { - // 1. Start with the clean, original list of items - var currentItems = self.baseSummaryItems - - // 2. Check if it is credit AND if we actually have a rate > 0 - if isCredit && self.creditSurchargeRate.compare(.zero) == .orderedDescending { + if let originalTotalItem = currentItems.last { + + let originalAmount = originalTotalItem.amount + + // Calculate the multiplier (e.g. 1.025 for a 2.5% increase) + // CHANGE: Use 'NSDecimalNumber.one' for safety + let multiplier = NSDecimalNumber.one.adding(self.creditSurchargeRate) + + // Calculate New Total: Original * 1.025 + let rawNewTotal = originalAmount.multiplying(by: multiplier) - if let originalTotalItem = currentItems.last { - - let originalAmount = originalTotalItem.amount - - // Calculate the multiplier (e.g. 1.025 for a 2.5% increase) - let one = NSDecimalNumber(value: 1) - let multiplier = one.adding(self.creditSurchargeRate) - - // Calculate New Total: Original * 1.025 - let rawNewTotal = originalAmount.multiplying(by: multiplier) - - // Round to 2 decimal places - let behavior = NSDecimalNumberHandler(roundingMode: .plain, - scale: 2, - raiseOnExactness: false, - raiseOnOverflow: false, - raiseOnUnderflow: false, - raiseOnDivideByZero: false) - - let finalNewTotal = rawNewTotal.rounding(accordingToBehavior: behavior) - - // Create the New Total Item - // We reuse the original label (e.g., "Total" or "Dibsy") but use the new higher price - let newTotalItem = PKPaymentSummaryItem(label: originalTotalItem.label, amount: finalNewTotal) - - // Remove the old total and add the new higher total - currentItems.removeLast() - currentItems.append(newTotalItem) - } - } + // Round to 2 decimal places + let behavior = NSDecimalNumberHandler(roundingMode: .plain, + scale: 2, + raiseOnExactness: false, + raiseOnOverflow: false, + raiseOnUnderflow: false, + raiseOnDivideByZero: false) + + let finalNewTotal = rawNewTotal.rounding(accordingToBehavior: behavior) + + // Create the New Total Item + let newTotalItem = PKPaymentSummaryItem(label: originalTotalItem.label, amount: finalNewTotal) + + // Remove the old total and add the new higher total + currentItems.removeLast() + currentItems.append(newTotalItem) + } + } completion(PKPaymentRequestPaymentMethodUpdate(paymentSummaryItems: currentItems)) } From 6f62e88c0317804acc354c99e4ec47e1567a8689 Mon Sep 17 00:00:00 2001 From: Tanish Panjwani Date: Wed, 3 Dec 2025 15:14:11 +0300 Subject: [PATCH 18/18] add surcharge line item --- pay_ios/ios/Classes/PaymentHandler.swift | 40 +++++++++++++++--------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/pay_ios/ios/Classes/PaymentHandler.swift b/pay_ios/ios/Classes/PaymentHandler.swift index bcc2073..97c3d71 100644 --- a/pay_ios/ios/Classes/PaymentHandler.swift +++ b/pay_ios/ios/Classes/PaymentHandler.swift @@ -201,26 +201,18 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didSelectPaymentMethod paymentMethod: PKPaymentMethod, handler completion: @escaping (PKPaymentRequestPaymentMethodUpdate) -> Void) { - let isCredit = paymentMethod.type == .credit +let isCredit = paymentMethod.type == .credit // 1. Start with the clean, original list of items var currentItems = self.baseSummaryItems - - // CHANGE: Use 'NSDecimalNumber.zero' explicitly because 'compare' expects an NSNumber + if isCredit && self.creditSurchargeRate.compare(NSDecimalNumber.zero) == .orderedDescending { if let originalTotalItem = currentItems.last { let originalAmount = originalTotalItem.amount - // Calculate the multiplier (e.g. 1.025 for a 2.5% increase) - // CHANGE: Use 'NSDecimalNumber.one' for safety - let multiplier = NSDecimalNumber.one.adding(self.creditSurchargeRate) - - // Calculate New Total: Original * 1.025 - let rawNewTotal = originalAmount.multiplying(by: multiplier) - - // Round to 2 decimal places + // 2. Define Rounding Behavior (Bankers rounding or Plain) let behavior = NSDecimalNumberHandler(roundingMode: .plain, scale: 2, raiseOnExactness: false, @@ -228,13 +220,31 @@ extension PaymentHandler: PKPaymentAuthorizationControllerDelegate { raiseOnUnderflow: false, raiseOnDivideByZero: false) - let finalNewTotal = rawNewTotal.rounding(accordingToBehavior: behavior) + // 3. Calculate the Surcharge Amount (e.g., 100 * 0.025 = 2.5) + let rawSurcharge = originalAmount.multiplying(by: self.creditSurchargeRate) + let surchargeAmount = rawSurcharge.rounding(accordingToBehavior: behavior) - // Create the New Total Item - let newTotalItem = PKPaymentSummaryItem(label: originalTotalItem.label, amount: finalNewTotal) + // 4. Create the Surcharge Line Item + // Optional: Format the percentage for the label (e.g. "Credit Card Fee (2.5%)") + let percentage = self.creditSurchargeRate.multiplying(byPowerOf10: 2) + let surchargeLabel = "Credit Card Fee (\(percentage.stringValue)%)" - // Remove the old total and add the new higher total + let surchargeItem = PKPaymentSummaryItem(label: surchargeLabel, amount: surchargeAmount) + // Note: If you want to show it as an additional cost, usually types are final. + surchargeItem.type = .final + + // 5. Calculate New Grand Total (Original + Surcharge) + let newTotalAmount = originalAmount.adding(surchargeAmount) + let newTotalItem = PKPaymentSummaryItem(label: originalTotalItem.label, amount: newTotalAmount) + + // 6. Construct the new list + // Remove the old total currentItems.removeLast() + + // Add the surcharge line item + currentItems.append(surchargeItem) + + // Add the new Grand Total at the very end (Apple Pay requirement) currentItems.append(newTotalItem) } }