Skip to content

Commit

Permalink
White-label installment KTC was added
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Solovev committed Apr 22, 2024
1 parent 59cadd7 commit 0ed8ce3
Show file tree
Hide file tree
Showing 20 changed files with 133 additions and 39 deletions.
15 changes: 15 additions & 0 deletions ExampleApp/Views/ProductDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,21 @@ extension ProductDetailViewController: ChoosePaymentMethodDelegate {
func choosePaymentMethodDidCancel() {
omiseSDK.dismiss()
}

func choosePaymentMethodDidComplete(with whiteLabelInstallmentSource: Source, token: Token) {
print("White-label installment payment Token is created with id '\(token.id)', Source id: '\(whiteLabelInstallmentSource.id)'")
omiseSDK.dismiss {
let alertController = UIAlertController(
title: "Token & Source Created",
message: "A token with id of \(token.id) and source with id of \(whiteLabelInstallmentSource.id) was successfully created. Please send this id to server to create a charge.",
preferredStyle: .alert
)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
}

}
}

// MARK: - Custom Credit Card Form View Controller Delegate
Expand Down
1 change: 1 addition & 0 deletions OmiseSDK/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"SourceType.installment_scb" = "Siam Commercial Bank";
"SourceType.installment_ttb" = "TMBThanachart Bank";
"SourceType.installment_uob" = "United Overseas Bank";
"SourceType.installment_wlb_ktc" = "KTC";
"SourceType.internet_banking_bay" = "Bank of Ayudhya";
"SourceType.internet_banking_bbl" = "Bangkok Bank";
"SourceType.paynow" = "PayNow";
Expand Down
1 change: 1 addition & 0 deletions OmiseSDK/Resources/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"SourceType.installment_scb" = "サイアム・コマーシャル銀行";
"SourceType.installment_ttb" = "TMBタナチャート銀行";
"SourceType.installment_uob" = "ユナイテッド・オーバーシーズ銀行";
"SourceType.installment_wlb_ktc" = "クルンタイカード";
"SourceType.internet_banking_bay" = "アユタヤ銀行";
"SourceType.internet_banking_bbl" = "バンコク銀行";
"SourceType.paynow" = "PayNow";
Expand Down
1 change: 1 addition & 0 deletions OmiseSDK/Resources/th.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"SourceType.installment_scb" = "ธนาคารไทยพาณิชย์";
"SourceType.installment_ttb" = "ธนาคารทีเอ็มบีธนชาต";
"SourceType.installment_uob" = "ธนาคารยูโอบี";
"SourceType.installment_wlb_ktc" = "เคทีซี";
"SourceType.internet_banking_bay" = "ธนาคารกรุงศรีอยุธยา";
"SourceType.internet_banking_bbl" = "ธนาคารกรุงเทพ";
"SourceType.paynow" = "เพย์นาว";
Expand Down
10 changes: 10 additions & 0 deletions OmiseSDK/Sources/ChoosePaymentMethodDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Foundation

/// Omise Payment delegate protocol is required to process payment results
public protocol ChoosePaymentMethodDelegate: AnyObject {
func choosePaymentMethodDidComplete(with source: Source)
func choosePaymentMethodDidComplete(with token: Token)
func choosePaymentMethodDidComplete(with whiteLabelInstallmentSource: Source, token: Token)
func choosePaymentMethodDidComplete(with error: Error)
func choosePaymentMethodDidCancel()
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ extension Source.Payment.Installment {
return [ 4, 6, 8, 9, 10 ]
case .installmentMBB:
return [ 6, 12, 18, 24 ]
case .installmentKTC:
case .installmentKTC, .installmentWhiteLabelKTC:
return [ 3, 4, 5, 6, 7, 8, 9, 10 ]
case .installmentKBank:
return [ 3, 4, 6, 10 ]
Expand Down
10 changes: 10 additions & 0 deletions OmiseSDK/Sources/OmiseAPI/SourceType/SourceType+Installments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,20 @@ extension SourceType {
.installmentSCB,
.installmentTTB,
.installmentUOB
] + whiteLabelInstallments
}

public static var whiteLabelInstallments: [SourceType] {
[
.installmentWhiteLabelKTC
]
}

var isInstallment: Bool {
Self.installments.contains(self)
}

var isWhiteLabelInstallment: Bool {
Self.whiteLabelInstallments.contains(self)
}
}
2 changes: 2 additions & 0 deletions OmiseSDK/Sources/OmiseAPI/SourceType/SourceType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public enum SourceType: String, Codable, CaseIterable {
case installmentTTB = "installment_ttb"
/// United Overseas Bank (UOB) https://docs.opn.ooo/installment-payments
case installmentUOB = "installment_uob"
/// Krungthai Card (KTC) https://docs.opn.ooo/installment-white-label-payments
case installmentWhiteLabelKTC = "installment_wlb_ktc"
/// Bank of Ayudhya (Krungsri) https://docs.opn.ooo/internet-banking
case internetBankingBAY = "internet_banking_bay"
/// Bangkok Bank https://docs.opn.ooo/internet-banking
Expand Down
20 changes: 0 additions & 20 deletions OmiseSDK/Sources/OmiseSDK.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,6 @@
import Foundation
import UIKit

/// Omise Payment delegate protocol is required to process payment results
public protocol ChoosePaymentMethodDelegate: AnyObject {
func choosePaymentMethodDidComplete(with source: Source)
func choosePaymentMethodDidComplete(with token: Token)
func choosePaymentMethodDidComplete(with error: Error)
func choosePaymentMethodDidCancel()
}

/// Payment Results
public enum PaymentResult {
/// Payment completed with Card payment and contains Token object
case token(Token)
/// Payment completed with Source payment and contains Source object
case source(Source)
/// Payment completed with Error
case error(Error)
/// Payment was cancelled by user
case cancel
}

public class OmiseSDK {
/// Static container that allows to assign a shared instance of OmiseSDK to be used as a Singleton object
public static var shared = OmiseSDK(publicKey: "pkey_")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,36 @@ extension ChoosePaymentCoordinator {
completion()
}
}

func processWhiteLabelInstallmentPayment(_ payment: Source.Payment, card: CreateTokenPayload.Card, completion: @escaping () -> Void) {

guard let delegate = choosePaymentMethodDelegate else { return }
let sourcePayload = CreateSourcePayload(
amount: amount,
currency: currency,
details: payment
)

let tokenPayload = CreateTokenPayload(card: card)

client.createSource(payload: sourcePayload) { [weak self, weak delegate, tokenPayload] result in
guard let self = self else { return }
switch result {
case .failure(let error):
self.processError(error)
case .success(let source):
self.client.createToken(payload: tokenPayload) { [weak self, weak delegate] result in
switch result {
case .success(let token):
delegate?.choosePaymentMethodDidComplete(with: source, token: token)
case .failure(let error):
self?.processError(error)
}
completion()
}
}
}
}
}

extension ChoosePaymentCoordinator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ class ChoosePaymentCoordinator: NSObject, ViewAttachable {
}

/// Creates Credit Carc Payment screen and attach current flow object inside created controller to be deallocated together
func createCreditCardPaymentController() -> CreditCardPaymentController {
let viewModel = CreditCardPaymentViewModel(currentCountry: currentCountry, delegate: self)
func createCreditCardPaymentController(paymentType: CreditCardPaymentOption = .card) -> CreditCardPaymentController {
let viewModel = CreditCardPaymentViewModel(currentCountry: currentCountry, paymentType: paymentType, delegate: self)
let viewController = CreditCardPaymentController(nibName: nil, bundle: .omiseSDK)
viewController.viewModel = viewModel
viewController.title = PaymentMethod.creditCard.localizedTitle
Expand Down Expand Up @@ -105,10 +105,16 @@ class ChoosePaymentCoordinator: NSObject, ViewAttachable {

/// Creates Installement screen and attach current flow object inside created controller to be deallocated together
func createInstallmentController() -> SelectPaymentController {
let sourceTypes = client.latestLoadedCapability?.availableSourceTypes(SourceType.installments)
var sourceTypes = client.latestLoadedCapability?.availableSourceTypes(SourceType.installments) ?? []

// Remove .installmentKTC if .installmentWhiteLabelKTC is present
if sourceTypes.contains(.installmentWhiteLabelKTC) {
sourceTypes.removeAll { $0 == .installmentKTC }
}

let viewModel = SelectSourceTypePaymentViewModel(
title: PaymentMethod.installment.localizedTitle,
sourceTypes: sourceTypes ?? [],
sourceTypes: sourceTypes,
delegate: self
)

Expand Down Expand Up @@ -191,10 +197,19 @@ extension ChoosePaymentCoordinator: FPXPaymentFormControllerDelegate {
}

extension ChoosePaymentCoordinator: CreditCardPaymentDelegate {
func didSelectCardPayment(_ card: CreateTokenPayload.Card, completion: @escaping () -> Void) {
processPayment(card, completion: completion)
func didSelectCardPayment(
paymentType: CreditCardPaymentOption,
card: CreateTokenPayload.Card,
completion: @escaping () -> Void
) {
switch paymentType {
case .card:
processPayment(card, completion: completion)
case .whiteLabelInstallment(let payment):
processWhiteLabelInstallmentPayment(payment, card: card, completion: completion)
}
}

func didCancelCardPayment() {
didCancelPayment()
}
Expand Down Expand Up @@ -249,6 +264,12 @@ extension ChoosePaymentCoordinator: SelectSourceTypeDelegate {

extension ChoosePaymentCoordinator: SelectSourcePaymentDelegate {
func didSelectSourcePayment(_ payment: Source.Payment, completion: @escaping () -> Void) {
processPayment(payment, completion: completion)
if payment.sourceType.isWhiteLabelInstallment {
navigate(to: createCreditCardPaymentController(
paymentType: .whiteLabelInstallment(payment: payment)
))
} else {
processPayment(payment, completion: completion)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ extension SourceType: ViewPresentable {
return "TMBThanachart Bank"
case .installmentUOB:
return "United Overseas Bank"
case .installmentWhiteLabelKTC:
return "Krungthai Card (KTC)"
case .internetBankingBAY:
return "Bank of Ayudhya"
case .internetBankingBBL:
Expand Down Expand Up @@ -151,7 +153,7 @@ extension SourceType: ViewPresentable {
return "First Choice"
case .installmentKBank:
return "KBANK"
case .installmentKTC:
case .installmentKTC, .installmentWhiteLabelKTC:
return "KTC"
case .installmentMBB:
return "FPX/maybank"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

protocol CreditCardPaymentDelegate: AnyObject {
func didSelectCardPayment(_ card: CreateTokenPayload.Card, completion: @escaping () -> Void)
func didSelectCardPayment(paymentType: CreditCardPaymentOption, card: CreateTokenPayload.Card, completion: @escaping () -> Void)
func didCancelCardPayment()
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import Foundation
import os.log

enum CreditCardPaymentOption {
case card
case whiteLabelInstallment(payment: Source.Payment)
}

class CreditCardPaymentViewModel: CreditCardPaymentViewModelProtocol, CountryListViewModelProtocol {

let paymentType: CreditCardPaymentOption

var addressFields: [AddressField] = [.address, .city, .state, .postalCode]

var fieldForShippingAddressHeader: AddressField?

var isAddressFieldsVisible: Bool {
Expand All @@ -18,9 +26,10 @@ class CreditCardPaymentViewModel: CreditCardPaymentViewModelProtocol, CountryLis

private weak var delegate: CreditCardPaymentDelegate?

init(currentCountry: Country?, delegate: CreditCardPaymentDelegate?) {
init(currentCountry: Country?, paymentType: CreditCardPaymentOption, delegate: CreditCardPaymentDelegate?) {
self.delegate = delegate
self.selectedCountry = currentCountry
self.paymentType = paymentType
}

// MARK: CountryListViewModelProtocol
Expand Down Expand Up @@ -62,6 +71,6 @@ class CreditCardPaymentViewModel: CreditCardPaymentViewModelProtocol, CountryLis
postalCode: viewContext[.postalCode]
)

delegate?.didSelectCardPayment(card, completion: completion)
delegate?.didSelectCardPayment(paymentType: paymentType, card: card, completion: completion)
}
}
22 changes: 17 additions & 5 deletions dev.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
756C8F262A40698600D53059 /* TextFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 756C8F252A40698600D53059 /* TextFieldView.swift */; };
757B0A742AD71E3100DEAE8F /* OmiseUnitTestKit in Frameworks */ = {isa = PBXBuildFile; productRef = 757B0A732AD71E3100DEAE8F /* OmiseUnitTestKit */; };
757B0A752AD71E3100DEAE8F /* OmiseUnitTestKit in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 757B0A732AD71E3100DEAE8F /* OmiseUnitTestKit */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
757E14352BD61DFE005F08AD /* ChoosePaymentMethodDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757E14342BD61DFE005F08AD /* ChoosePaymentMethodDelegate.swift */; };
7588011E2BAAB37C00F02934 /* AppDeeplink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7588011D2BAAB37C00F02934 /* AppDeeplink.swift */; };
758801202BAAC70200F02934 /* URL+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7588011F2BAAC70200F02934 /* URL+Helpers.swift */; };
759856242A286C880087B605 /* UIScrollView+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759856232A286C880087B605 /* UIScrollView+Helpers.swift */; };
Expand Down Expand Up @@ -335,6 +336,7 @@
756C8F252A40698600D53059 /* TextFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldView.swift; sourceTree = "<group>"; };
757B0A712AD71D7B00DEAE8F /* OmiseSwiftUIKit */ = {isa = PBXFileReference; lastKnownFileType = text; name = OmiseSwiftUIKit; path = Helpers/OmiseSwiftUIKit; sourceTree = SOURCE_ROOT; };
757B0A722AD71DCD00DEAE8F /* OmiseUnitTestKit */ = {isa = PBXFileReference; lastKnownFileType = text; name = OmiseUnitTestKit; path = Helpers/OmiseUnitTestKit; sourceTree = SOURCE_ROOT; };
757E14342BD61DFE005F08AD /* ChoosePaymentMethodDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChoosePaymentMethodDelegate.swift; sourceTree = "<group>"; };
7588011D2BAAB37C00F02934 /* AppDeeplink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDeeplink.swift; sourceTree = "<group>"; };
7588011F2BAAC70200F02934 /* URL+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Helpers.swift"; sourceTree = "<group>"; };
759856232A286C880087B605 /* UIScrollView+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIScrollView+Helpers.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -693,6 +695,18 @@
path = "UI Extensions";
sourceTree = "<group>";
};
757E14332BD61DBB005F08AD /* ViewModels */ = {
isa = PBXGroup;
children = (
75D13DC02B8400610073A831 /* SelectPaymentMethodViewModel.swift */,
75D13DC82B8529790073A831 /* SelectSourceTypePaymentViewModel.swift */,
75D13DCC2B8536B10073A831 /* SelectInstallmentTermsViewModel.swift */,
7501266F2B8A490000ED5E14 /* SelectFPXBankViewModel.swift */,
750126732B8A580500ED5E14 /* SelectDuitNowOBWBankViewModel.swift */,
);
path = ViewModels;
sourceTree = "<group>";
};
75CFC4EF2B753AB900422A8F /* JSON Models */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -857,13 +871,9 @@
75D13DF62B866C650073A831 /* Select Payment From Lists */ = {
isa = PBXGroup;
children = (
757E14332BD61DBB005F08AD /* ViewModels */,
75D13DDC2B8658660073A831 /* SelectPaymentPresentableProtocol.swift */,
75D13DBA2B83FB470073A831 /* SelectPaymentController.swift */,
75D13DC02B8400610073A831 /* SelectPaymentMethodViewModel.swift */,
75D13DC82B8529790073A831 /* SelectSourceTypePaymentViewModel.swift */,
75D13DCC2B8536B10073A831 /* SelectInstallmentTermsViewModel.swift */,
7501266F2B8A490000ED5E14 /* SelectFPXBankViewModel.swift */,
750126732B8A580500ED5E14 /* SelectDuitNowOBWBankViewModel.swift */,
);
path = "Select Payment From Lists";
sourceTree = "<group>";
Expand Down Expand Up @@ -972,6 +982,7 @@
75E0EBBF2B7D13D200E3198A /* OmiseAPI */,
75D13DEE2B866BCA0073A831 /* Views */,
75CFC4D12B73AFD500422A8F /* OmiseSDK.swift */,
757E14342BD61DFE005F08AD /* ChoosePaymentMethodDelegate.swift */,
755CD9222BA2000600E8FCDA /* ClientProtocol.swift */,
);
path = Sources;
Expand Down Expand Up @@ -1441,6 +1452,7 @@
75CFC4DD2B73F75C00422A8F /* OmiseAPI.swift in Sources */,
75348D4E29C3FCC70008C8A3 /* Bundle+OmiseSDK.swift in Sources */,
755CD9232BA2000600E8FCDA /* ClientProtocol.swift in Sources */,
757E14352BD61DFE005F08AD /* ChoosePaymentMethodDelegate.swift in Sources */,
75E0EB9D2B7BD00F00E3198A /* CardBrand.swift in Sources */,
75E0EB9A2B7BD00F00E3198A /* Currency.swift in Sources */,
75405A9C2A266F50008C21F6 /* AtomePaymentFormViewModel.swift in Sources */,
Expand Down

0 comments on commit 0ed8ce3

Please sign in to comment.