Browse Source

implement recharge api

pull/1/head
InKwon James Kim 5 years ago
parent
commit
0339507333
  1. 4
      GME Remit.xcodeproj/project.pbxproj
  2. 30
      GME Remit/APIs/Router/APIRouter.swift
  3. 34
      GME Remit/Modules/PowerCallModules/PhoneCardRecharge/Application Logic/Model/RechargeModel.swift
  4. 35
      GME Remit/Modules/PowerCallModules/PhoneCardRecharge/User Interface/Presenter/PhoneCardRechargePresenter.swift
  5. 12
      GME Remit/Modules/PowerCallModules/PhoneCardRecharge/User Interface/View/PhoneCardRechargeViewController.swift
  6. 26
      GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Interactor/RechargePaymentInteractor.swift
  7. 5
      GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Interactor/RechargePaymentInteractorIO.swift
  8. 105
      GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Model/CreditCardReceipt.swift
  9. 39
      GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Model/VerificationAndBuy.swift
  10. 46
      GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Service/RechargePaymentService.swift
  11. 6
      GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Service/RechargePaymentServiceType.swift
  12. 61
      GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/Presenter/RechargePaymentPresenter.swift
  13. 41
      GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/View/RechargePayment.storyboard
  14. 90
      GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/View/RechargePaymentViewController.swift
  15. 2
      GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/Wireframe/RechargePaymentWireframe.swift
  16. 4
      GME Remit/Utilities/CustomUI/BootPayViewController.swift

4
GME Remit.xcodeproj/project.pbxproj

@ -290,6 +290,7 @@
734BF6882353F7D8004E8D60 /* PhoneCardRechargeWireframeInputOutput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 734BF67E2353F7D8004E8D60 /* PhoneCardRechargeWireframeInputOutput.swift */; };
734BF6892353F7D8004E8D60 /* PhoneCardRechargeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 734BF6802353F7D8004E8D60 /* PhoneCardRechargeViewController.swift */; };
734BF68A2353F7D8004E8D60 /* PhoneCardRecharge.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 734BF6812353F7D8004E8D60 /* PhoneCardRecharge.storyboard */; };
734DD31A2366881600BFA7EE /* VerificationAndBuy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 734DD3192366881600BFA7EE /* VerificationAndBuy.swift */; };
73538B2222EFC5FA00188CDD /* CommonServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73538B2122EFC5FA00188CDD /* CommonServiceType.swift */; };
7366BECC235D326C00A8AE7C /* CardList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7366BECB235D326C00A8AE7C /* CardList.swift */; };
7366BECE235D331B00A8AE7C /* PriceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7366BECD235D331B00A8AE7C /* PriceModel.swift */; };
@ -2558,6 +2559,7 @@
734BF67E2353F7D8004E8D60 /* PhoneCardRechargeWireframeInputOutput.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneCardRechargeWireframeInputOutput.swift; sourceTree = "<group>"; };
734BF6802353F7D8004E8D60 /* PhoneCardRechargeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneCardRechargeViewController.swift; sourceTree = "<group>"; };
734BF6812353F7D8004E8D60 /* PhoneCardRecharge.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = PhoneCardRecharge.storyboard; sourceTree = "<group>"; };
734DD3192366881600BFA7EE /* VerificationAndBuy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerificationAndBuy.swift; sourceTree = "<group>"; };
73538B2122EFC5FA00188CDD /* CommonServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonServiceType.swift; sourceTree = "<group>"; };
7366BECB235D326C00A8AE7C /* CardList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardList.swift; sourceTree = "<group>"; };
7366BECD235D331B00A8AE7C /* PriceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceModel.swift; sourceTree = "<group>"; };
@ -6133,6 +6135,7 @@
isa = PBXGroup;
children = (
733E8F76235804810050E499 /* CreditCardReceipt.swift */,
734DD3192366881600BFA7EE /* VerificationAndBuy.swift */,
);
path = Model;
sourceTree = "<group>";
@ -14539,6 +14542,7 @@
73B6D68E2306413100A0CB6E /* RecipientCommonType.swift in Sources */,
D962231E212C126500B7A115 /* ExchangeModel.swift in Sources */,
D903113D214786EA00AD5BA9 /* ForgotPasswordServiceType.swift in Sources */,
734DD31A2366881600BFA7EE /* VerificationAndBuy.swift in Sources */,
D9B39677214F7DDC0072A9B8 /* ImageCroper.swift in Sources */,
730D78B9227A94F2007E517E /* SearchAddressInteractor.swift in Sources */,
D923EBBB215C7E67008A3026 /* HomeCollectionModel.swift in Sources */,

30
GME Remit/APIs/Router/APIRouter.swift

@ -54,7 +54,8 @@ enum APIRouter {
// MARK: - Recharge Prepiad Phone
case fetchCardList(type: String, mobile: String)
case verificationAndBuy
case verificationAndBuy(model: RechargeModel)
case verifyPassword(password: String)
}
// MARK: - Request
@ -449,6 +450,8 @@ extension APIRouter {
return "\(baseUrl)/powerCall/GetCardList/"
case .verificationAndBuy:
return "\(baseUrl)/powerCall/VerificationAndBuy/"
case .verifyPassword:
return "\(baseUrl)/powerCall/VerificationAndBuy/"
}
}
}
@ -517,6 +520,8 @@ extension APIRouter {
return .post
case .verificationAndBuy:
return .post
case .verifyPassword:
return .post
}
}
@ -724,18 +729,23 @@ extension APIRouter {
"getcardType": type,
"phoneNo": mobile
]
case .verificationAndBuy:
case .verificationAndBuy(let model):
let senderID = GMEDB.shared.user.string(.senderId) ?? ""
return [
"BuyType" : "1",
"CustomerId" : "40154",
"ReceiptId" : "qwkeljklal",
"OrderNo" : "gmesub_000000002",
"ChargeType": "PPS_01",
"PhoneNo" : "01059394397 ",
"Price" : "10000",
"UseWalletPrice" : "0",
"BuyType" : model.type,
"CustomerId" : senderID,
"ReceiptId" : model.receiptID ?? "",
"OrderNo" : model.orderNo ?? "",
"ChargeType": model.chargeType,
"PhoneNo" : model.mobile,
"ProductPrice" : model.productPrice ?? "",
"UseBalancePrice" : model.useBalancePrice ?? ""
]
case .verifyPassword(let password):
return [
"password": password
]
default: return nil
}

34
GME Remit/Modules/PowerCallModules/PhoneCardRecharge/Application Logic/Model/RechargeModel.swift

@ -7,5 +7,37 @@
//
struct RechargeModel {
let paymentAmount: String
let type: String
let chargeType: String
let mobile: String
var productPrice: String?
var useBalancePrice: String?
var receiptID: String?
var orderNo: String?
var password: String?
init(
type: String,
chargeType: String,
mobile: String,
price: String
) {
self.type = type
self.chargeType = chargeType
self.mobile = mobile
self.productPrice = price
}
mutating func addReceipt(_ data: [String: Any]?) {
self.orderNo = data?["order_id"] as? String ?? ""
self.receiptID = data?["receipt_id"] as? String ?? ""
}
mutating func addUseBalance(_ balance: String) {
self.useBalancePrice = balance
}
mutating func addPassword(_ password: String) {
self.password = password
}
}

35
GME Remit/Modules/PowerCallModules/PhoneCardRecharge/User Interface/Presenter/PhoneCardRechargePresenter.swift

@ -59,7 +59,7 @@ class PhoneCardRechargePresenter: ViewModelType {
let isError: Driver<Error>
let isProgress: Driver<Bool>
let isEnableNext: Driver<Bool>
let isSuccessPayment: Driver<CreditCardReceipt>
let isSuccessPayment: Driver<VerificationAndBuy>
let regularModel: Driver<[PriceModel]>
let fixedModel: Driver<[MainCardInformation]>
let carrierPlanModel: Driver<[CardInformation]>
@ -71,7 +71,7 @@ class PhoneCardRechargePresenter: ViewModelType {
private let progressLinker = PublishSubject<Bool>()
private let errorLinker = PublishSubject<Error>()
private let isSuccessPayment = PublishSubject<CreditCardReceipt>()
private let isSuccessPayment = PublishSubject<VerificationAndBuy>()
private let regularModel = BehaviorSubject<[PriceModel]>(value: [])
private let fixedModel = BehaviorSubject<[MainCardInformation]>(value: [])
@ -88,6 +88,7 @@ class PhoneCardRechargePresenter: ViewModelType {
.disposed(by: disposeBag)
let combinedInput = Observable.combineLatest(
input.selectedMobile.asObservable(),
input.selectedRechargeType.asObservable(),
input.selectedAmountButtonTag.asObservable()
.withLatestFrom(regularModel) { tag, model -> PriceModel? in
@ -103,7 +104,7 @@ class PhoneCardRechargePresenter: ViewModelType {
let detailCarrierPlanModel = input.selectedCarrierPlan.map { $0?.planInfo }
let isEnableNext = combinedInput
.map { type, priceModel, carrierType, carrierPlan, dataOnlyType -> Bool in
.map { _, type, priceModel, carrierType, carrierPlan, dataOnlyType -> Bool in
switch type {
case .regular: return priceModel != nil
case .fixed: return carrierType != nil && carrierPlan != nil
@ -113,11 +114,29 @@ class PhoneCardRechargePresenter: ViewModelType {
input.nextTap
.withLatestFrom(combinedInput.asDriverOnErrorJustComplete()) {$1}
.map { (type, priceModel, _, carrierPlan, dataOnlyType) -> RechargeModel? in
.map { ( mobile, type, priceModel, _, carrierPlan, dataOnlyType) -> RechargeModel? in
switch type {
case .regular: return RechargeModel(paymentAmount: priceModel?.price ?? "0")
case .fixed: return RechargeModel(paymentAmount: carrierPlan?.facePrice ?? "0")
case .dataOnly: return RechargeModel(paymentAmount: dataOnlyType?.facePrice ?? "0")
case .regular:
return RechargeModel(
type: type.value,
chargeType: "",
mobile: mobile,
price: priceModel?.price ?? "0"
)
case .fixed:
return RechargeModel(
type: type.value,
chargeType: carrierPlan?.cardType ?? "",
mobile: mobile,
price: carrierPlan?.facePrice ?? "0"
)
case .dataOnly:
return RechargeModel(
type: type.value,
chargeType: dataOnlyType?.cardCode ?? "",
mobile: mobile,
price: dataOnlyType?.facePrice ?? "0"
)
}
}.drive(onNext: {
guard let model = $0 else { return }
@ -166,7 +185,7 @@ extension PhoneCardRechargePresenter: PhoneCardRechargeWireframeOutput {
}
extension PhoneCardRechargePresenter: RechargePayementDelegate {
func rechargePayment(_ viewController: RechargePaymentViewController, didComplete data: CreditCardReceipt) {
func rechargePayment(_ viewController: UIViewController, didComplete data: VerificationAndBuy) {
isSuccessPayment.onNext(data)
}
}

12
GME Remit/Modules/PowerCallModules/PhoneCardRecharge/User Interface/View/PhoneCardRechargeViewController.swift

@ -180,16 +180,8 @@ extension PhoneCardRechargeViewController {
output.isSuccessPayment
.drive(
onNext: {[weak self] receipt in
self?.alertWithOk(
type: .normal,
message: "You will receive message about recharge result through SMS.",
title: "Payment Request completed",
okTitle: "Ok"
) {
print(receipt)
// TODO: Receipt send to Server
self?.navigationController?.popToRootViewController(animated: true)
}
print("receipt: \(receipt)")
self?.navigationController?.popToRootViewController(animated: true)
}).disposed(by: disposeBag)
output.isEnableNext

26
GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Interactor/RechargePaymentInteractor.swift

@ -30,4 +30,30 @@ extension RechargePaymentInteractor: RechargePaymentInteractorInput {
func fetchModel() {
output?.setModel(with: model)
}
func verify(of password: String) {
service.verify(
of: password,
success: { [weak self] in
self?.output?.setSuccess()
},
failure: { [weak self] in
self?.output?.setError(with: $0)
}
)
}
func submit(with model: RechargeModel) {
print("model: \(model)")
service.submit(
of: model,
success: { [weak self] in
self?.output?.setSubmitSuccess(with: $0)
},
failure: {[weak self] in
self?.output?.setError(with: $0)
}
)
}
}

5
GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Interactor/RechargePaymentInteractorIO.swift

@ -8,8 +8,13 @@
protocol RechargePaymentInteractorInput: class {
func fetchModel()
func verify(of password: String)
func submit(with model: RechargeModel)
}
protocol RechargePaymentInteractorOutput: class {
func setModel(with model: RechargeModel?)
func setSubmitSuccess(with model: VerificationAndBuy)
func setSuccess()
func setError(with error: Error)
}

105
GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Model/CreditCardReceipt.swift

@ -7,55 +7,68 @@
//
struct CreditCardReceipt {
let pgName: String
let taxFree: String
let purchasedAt: String
// let pgName: String
// let taxFree: String
// let purchasedAt: String
let price: String
let cardOtherPayType: String
let amount: String
let params: [String: Any]?
let url: String
let cardQuota: String
let status: String
// let cardOtherPayType: String
// let amount: String
// let params: [String: Any]?
// let url: String
// let cardQuota: String
// let status: String
let orderID: String
let paymentGroup: String
let requestedAt: String
let itemName: String
let paymentName: String
let methodName: String
let cardNo: String
let pg: String
let cardName: String
let paymentGroupName: String
let cardCode: String
let method: String
let action: String
// let paymentGroup: String
// let requestedAt: String
// let itemName: String
// let paymentName: String
// let methodName: String
// let cardNo: String
// let pg: String
// let cardName: String
// let paymentGroupName: String
// let cardCode: String
// let method: String
// let action: String
let receiptID: String
let password: String
init(data: [String: Any]) {
pgName = data["pg_name"] as? String ?? ""
taxFree = data["tax_free"] as? String ?? ""
purchasedAt = data["purchased_at"] as? String ?? ""
price = data["price"] as? String ?? ""
cardOtherPayType = data["card_other_pay_type"] as? String ?? ""
amount = data["amount"] as? String ?? ""
params = data["params"] as? [String: Any]
url = data["url"] as? String ?? ""
cardQuota = data["card_quota"] as? String ?? ""
status = data["status"] as? String ?? ""
orderID = data["order_id"] as? String ?? ""
paymentGroup = data["payment_group"] as? String ?? ""
requestedAt = data["requested_at"] as? String ?? ""
itemName = data["item_name"] as? String ?? ""
paymentName = data["payment_name"] as? String ?? ""
methodName = data["method_name"] as? String ?? ""
cardNo = data["card_no"] as? String ?? ""
pg = data["pg"] as? String ?? ""
cardName = data["card_name"] as? String ?? ""
paymentGroupName = data["payment_group_name"] as? String ?? ""
cardCode = data["card_code"] as? String ?? ""
method = data["method"] as? String ?? ""
action = data["action"] as? String ?? ""
receiptID = data["receipt_id"] as? String ?? ""
init(data: [String: Any], password: String) {
// "BuyType" : "1",
// "CustomerId" : "40154",
// "ReceiptId" : "qwkeljklal",
// "OrderNo" : "gmesub_000000002",
// "ChargeType": "",
// "PhoneNo" : "01059394397 ",
// "Price" : "10000",
// "UseWalletPrice" : "0",
// "PassWord" : "123"
// pgName = data["pg_name"] as? String ?? ""
// taxFree = data["tax_free"] as? String ?? ""
// purchasedAt = data["purchased_at"] as? String ?? ""
price = data["price"] as? String ?? "" //
// cardOtherPayType = data["card_other_pay_type"] as? String ?? ""
// amount = data["amount"] as? String ?? ""
// params = data["params"] as? [String: Any]
// url = data["url"] as? String ?? ""
// cardQuota = data["card_quota"] as? String ?? ""
// status = data["status"] as? String ?? ""
orderID = data["order_id"] as? String ?? "" //
// paymentGroup = data["payment_group"] as? String ?? ""
// requestedAt = data["requested_at"] as? String ?? ""
// itemName = data["item_name"] as? String ?? ""
// paymentName = data["payment_name"] as? String ?? ""
// methodName = data["method_name"] as? String ?? ""
// cardNo = data["card_no"] as? String ?? ""
// pg = data["pg"] as? String ?? ""
// cardName = data["card_name"] as? String ?? ""
// paymentGroupName = data["payment_group_name"] as? String ?? ""
// cardCode = data["card_code"] as? String ?? ""
// method = data["method"] as? String ?? ""
// action = data["action"] as? String ?? ""
receiptID = data["receipt_id"] as? String ?? "" //
self.password = password
}
// func add(at model:)
}

39
GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Model/VerificationAndBuy.swift

@ -0,0 +1,39 @@
//
// VerificationAndBuy.swift
// GME Remit
//
// Created by InKwon James Kim on 2019/10/28.
// Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved.
//
import ObjectMapper
struct VerificationAndBuy: Mappable {
var result: String?
var cause: String?
var currentMoney: String?
var successCnt: String?
var saleNo: String?
var saleType: String?
var cardNo: String?
var cardNo2: String?
var cardType: String?
var totalPayDeposit: String?
var totalSalePrice: String?
init?(map: Map) { }
mutating func mapping(map: Map) {
result <- map["result"]
cause <- map["cause"]
currentMoney <- map["current_money"]
successCnt <- map["success_cnt"]
saleNo <- map["sale_no"]
saleType <- map["sale_type"]
cardNo <- map["card_no"]
cardNo2 <- map["card_no2"]
cardType <- map["card_type"]
totalPayDeposit <- map["total_pay_deposit"]
totalSalePrice <- map["total_sale_price"]
}
}

46
GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Service/RechargePaymentService.swift

@ -9,5 +9,51 @@
import Foundation
class RechargePaymentService: RechargePaymentServiceType {
func verify(of password: String, success: @escaping () -> Void, failure: @escaping (Error) -> Void) {
//FIXME: Test
// APIRouter.verifyPassword(password: password)
// .json(success: success, failure: failure)
success()
}
func submit(of model: RechargeModel, success: @escaping (VerificationAndBuy) -> Void, failure: @escaping (Error) -> Void) {
//FIXME: Test
let text =
"""
{
"ErrorCode": "0",
"Msg": "Success",
"Id": "",
"Extra": "",
"Extra2": "",
"Data": {
"result": "0000",
"cause": "1000",
"current_money": "2000",
"success_cnt": "1",
"sale_no": "gmesub_000000002",
"sale_type": "3",
"card_no": "26866721587",
"card_no2": "",
"card_type": "PPS_06",
"total_pay_deposit": "9000",
"total_sale_price": "10000"
}
}
"""
guard
let json = ResponseContainerObject<VerificationAndBuy>(JSONString: text),
let data = json.data else {
let error = NSError(domain: "Test Error", code: 0, message: "Test JSON Error")
failure(error)
return
}
success(data)
// APIRouter.verificationAndBuy(model: model).json(
// success: success,
// failure: failure
// )
}
}

6
GME Remit/Modules/PowerCallModules/RechargePayment/Application Logic/Service/RechargePaymentServiceType.swift

@ -7,5 +7,11 @@
//
protocol RechargePaymentServiceType: class {
func verify(of password: String, success: @escaping () -> Void, failure: @escaping (Error) -> Void)
func submit(
of model: RechargeModel,
success: @escaping (VerificationAndBuy) -> Void,
failure: @escaping (Error) -> Void
)
}

61
GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/Presenter/RechargePaymentPresenter.swift

@ -13,21 +13,24 @@ class RechargePaymentPresenter: ViewModelType {
var interactor: RechargePaymentInteractorInput?
var wireframe: RechargePaymentWireframeInput?
private var model = BehaviorSubject<RechargeModel?>(value: nil)
struct Input {
let viewWillAppear: Driver<Void>
let availableBalance: Driver<String>
let useBalance: Driver<String>
let rechargeSuccess: Driver<CreditCardReceipt>
let password: Driver<String>
let submit: Driver<[String: Any]?>
}
struct Output {
let isError: Driver<Error>
let isProgress: Driver<Bool>
let rechargeModel: Driver<RechargeModel?>
let paymentAmount: Driver<String>
let isAvailableUseBalance: Driver<Bool>
let finalPaymentAmount: Driver<String>
let verifySuccess: Driver<Void>
let submitSuccess: Driver<VerificationAndBuy>
}
private let disposeBag = DisposeBag()
@ -35,6 +38,10 @@ class RechargePaymentPresenter: ViewModelType {
private let progressLinker = PublishSubject<Bool>()
private let errorLinker = PublishSubject<Error>()
private var model = BehaviorSubject<RechargeModel?>(value: nil)
private var verifySuccess = PublishSubject<Void>()
private var submitSuccess = PublishSubject<VerificationAndBuy>()
func transform(input: Input) -> Output {
input.viewWillAppear.withLatestFrom(model.asDriverOnErrorJustComplete()) {$1}
@ -42,7 +49,6 @@ class RechargePaymentPresenter: ViewModelType {
if model == nil {
self?.interactor?.fetchModel()
}
}).disposed(by: disposeBag)
input.rechargeSuccess.withLatestFrom(model.asDriverOnErrorJustComplete()) {($0, $1)}
@ -51,6 +57,30 @@ class RechargePaymentPresenter: ViewModelType {
self?.wireframe?.goReceipt(receiptModel: receipt, rechargeModel: model)
}).disposed(by: disposeBag)
input.password.drive(onNext: {[weak self] in
self?.progressLinker.onNext(true)
self?.interactor?.verify(of: $0)
}).disposed(by: disposeBag)
let requestModel = Driver.combineLatest(
model.asDriverOnErrorJustComplete(),
input.useBalance.map {$0.currencyToDecimal()},
input.password
).map { (model, balance, password) -> RechargeModel? in
var addedModel = model
addedModel?.addPassword(password)
addedModel?.addUseBalance(balance)
return addedModel
}
input.submit.withLatestFrom(requestModel) {($0, $1)}
.drive(onNext: {[weak self] (receipt, model) in
guard var model = model else { return }
model.addReceipt(receipt)
self?.interactor?.submit(with: model)
}).disposed(by: disposeBag)
let mergeAvailableBalanceAndUseBalance = Driver
.combineLatest(
input.availableBalance.map {Int($0.stringRemovingComma()) ?? 0},
@ -62,7 +92,7 @@ class RechargePaymentPresenter: ViewModelType {
.debounce(0.2)
.distinctUntilChanged()
.withLatestFrom(
model.asDriverOnErrorJustComplete().map { Int($0?.paymentAmount ?? "0") ?? 0}
model.asDriverOnErrorJustComplete().map { Int($0?.productPrice ?? "0") ?? 0}
) { ($0, $1) }
.map { (balance, paymentAmount) -> String in
guard let balance = balance else { return "\(paymentAmount)" }
@ -73,7 +103,7 @@ class RechargePaymentPresenter: ViewModelType {
let isAvailableUseBalance = mergeAvailableBalanceAndUseBalance
.withLatestFrom(
model.asDriverOnErrorJustComplete().map { Int($0?.paymentAmount ?? "0") ?? 0}
model.asDriverOnErrorJustComplete().map { Int($0?.productPrice ?? "0") ?? 0}
) { ($0, $1) }
.map { (balance, paymentAmount) -> Bool in
guard let balance = balance else { return false }
@ -85,18 +115,35 @@ class RechargePaymentPresenter: ViewModelType {
return Output(
isError: errorLinker.asDriverOnErrorJustComplete(),
isProgress: progressLinker.asDriverOnErrorJustComplete(),
paymentAmount: model.map {$0?.paymentAmount ?? "0"}.asDriverOnErrorJustComplete(),
rechargeModel: model.asDriverOnErrorJustComplete(),
paymentAmount: model.map {$0?.productPrice ?? "0"}.asDriverOnErrorJustComplete(),
isAvailableUseBalance: isAvailableUseBalance,
finalPaymentAmount: finalPaymentAmount
finalPaymentAmount: finalPaymentAmount,
verifySuccess: verifySuccess.asDriverOnErrorJustComplete(),
submitSuccess: submitSuccess.asDriverOnErrorJustComplete()
)
}
}
// MARK: RechargePayment interactor output interface
extension RechargePaymentPresenter: RechargePaymentInteractorOutput {
func setSuccess() {
progressLinker.onNext(false)
verifySuccess.onNext(())
}
func setError(with error: Error) {
progressLinker.onNext(false)
errorLinker.onNext(error)
}
func setModel(with model: RechargeModel?) {
self.model.onNext(model)
}
func setSubmitSuccess(with model: VerificationAndBuy) {
submitSuccess.onNext(model)
}
}
// MARK: RechargePayment wireframe output interface

41
GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/View/RechargePayment.storyboard

@ -29,7 +29,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="l8P-RE-lSE">
<rect key="frame" x="0.0" y="362" width="375" height="305"/>
<rect key="frame" x="0.0" y="332" width="375" height="335"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fDs-Q8-JOQ">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
@ -65,13 +65,13 @@
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" placeholderIntrinsicWidth="375" placeholderIntrinsicHeight="667" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="esj-KG-eg7">
<rect key="frame" x="20" y="54" width="335" height="181"/>
<rect key="frame" x="20" y="54" width="335" height="211"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="d4v-Yx-EgD">
<rect key="frame" x="0.0" y="0.0" width="335" height="181"/>
<rect key="frame" x="0.0" y="0.0" width="335" height="211"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="NYE-1b-eNd">
<rect key="frame" x="0.0" y="0.0" width="335" height="181"/>
<rect key="frame" x="0.0" y="0.0" width="335" height="211"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="AMo-yX-AN5">
<rect key="frame" x="0.0" y="0.0" width="335" height="50"/>
@ -119,10 +119,10 @@
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="R7o-6l-c57">
<rect key="frame" x="0.0" y="60.5" width="335" height="120.5"/>
<rect key="frame" x="0.0" y="60.5" width="335" height="150.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="QYJ-9E-2G3">
<rect key="frame" x="0.0" y="0.0" width="335" height="120.5"/>
<rect key="frame" x="0.0" y="0.0" width="335" height="150.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="sGF-Gp-Wks">
<rect key="frame" x="0.0" y="0.0" width="335" height="40"/>
@ -209,8 +209,31 @@
<constraint firstItem="1zK-8Q-G0a" firstAttribute="leading" secondItem="wOB-Gw-plc" secondAttribute="leading" id="uib-bo-6Yf"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="fgR-ra-siH">
<rect key="frame" x="0.0" y="120.5" width="335" height="30"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="252" text="●" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="swS-ur-DiI">
<rect key="frame" x="0.0" y="0.0" width="8.5" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="8.5" id="CLp-A5-5Dj"/>
</constraints>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Medium" family="San Francisco Display" pointSize="14"/>
<color key="textColor" name="ThemeBlack"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="The payment amount deducted from your balance will be charged to your check(credit) card." lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="fOi-hA-dxC">
<rect key="frame" x="10.5" y="0.0" width="324.5" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="h0K-re-9jN"/>
</constraints>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Regular" family="San Francisco Display" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="8pQ-ti-hwB">
<rect key="frame" x="0.0" y="120.5" width="335" height="40"/>
<rect key="frame" x="0.0" y="150.5" width="335" height="40"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" text="Final Payment" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bSL-cS-o4N">
<rect key="frame" x="0.0" y="0.0" width="108" height="40"/>
@ -250,7 +273,7 @@
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nox-A9-teb" userLabel="Separate">
<rect key="frame" x="0.0" y="181" width="335" height="11"/>
<rect key="frame" x="0.0" y="211" width="335" height="11"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6EF-No-ScT">
<rect key="frame" x="-20" y="10" width="375" height="1"/>
@ -282,7 +305,7 @@
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Dz3-R4-DPX">
<rect key="frame" x="10" y="245" width="355" height="60"/>
<rect key="frame" x="10" y="275" width="355" height="60"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="lhy-bf-cVT">
<rect key="frame" x="0.0" y="0.0" width="355" height="60"/>

90
GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/View/RechargePaymentViewController.swift

@ -19,24 +19,27 @@ enum RechargePaymentMode {
}
protocol RechargePayementDelegate: class {
func rechargePayment(_ viewController: RechargePaymentViewController, didComplete data: CreditCardReceipt)
func rechargePayment(_ viewController: UIViewController, didComplete data: VerificationAndBuy)
}
class RechargePaymentViewController: UIViewController {
// MARK: Properties
var presenter: RechargePaymentPresenter!
weak var delegate: RechargePayementDelegate?
private let disposeBag = DisposeBag()
weak var delegate: RechargePayementDelegate?
private lazy var selectedPaymentMode = RechargePaymentMode.wallet
private lazy var bootpayController = BootpayController()
private lazy var availableBalance = BehaviorSubject<String>(value: "0")
private lazy var rechargeSuccess = PublishSubject<CreditCardReceipt>()
private lazy var selectedPaymentMode = PublishSubject<RechargePaymentMode>()
private lazy var password = PublishSubject<String>()
private lazy var bootPayData = PublishSubject<[String: Any]?>()
private var isFirst = true
// MARK: Computed Properties
// MARK: IBOutlets
@IBOutlet private weak var mainView: UIView!
@ -123,7 +126,9 @@ extension RechargePaymentViewController {
viewWillAppear: viewWillAppear,
availableBalance: availableBalance.asDriverOnErrorJustComplete(),
useBalance: useBalanceTextField.rx.text.orEmpty.asDriverOnErrorJustComplete(),
rechargeSuccess: rechargeSuccess.asDriverOnErrorJustComplete()
rechargeSuccess: rechargeSuccess.asDriverOnErrorJustComplete(),
password: password.asDriverOnErrorJustComplete(),
submit: bootPayData.asDriverOnErrorJustComplete()
)
let output = presenter.transform(input: input)
@ -147,7 +152,7 @@ extension RechargePaymentViewController {
output.finalPaymentAmount
.map {[weak self] in
$0 == "0" ? self?.selectedPaymentMode.onNext(.wallet) : self?.selectedPaymentMode.onNext(.card)
self?.selectedPaymentMode = $0 == "0" ? .wallet : .card
let title = "Pay ₩\(Utility.getCommaSeperatedString(numberString: $0) ?? "")"
UIView.animate(withDuration: 0.2) {
@ -174,18 +179,47 @@ extension RechargePaymentViewController {
})
.disposed(by: disposeBag)
rechargeButton.rx.tap.withLatestFrom(selectedPaymentMode)
.bind { [weak self] mode in
output.verifySuccess
.drive(onNext: {[weak self] in
guard let `self` = self else {return}
switch mode {
switch self.selectedPaymentMode {
case .card:
let vc = BootPayViewController(dataSource: self, delegate: self)
self.present(vc, animated: true)
self.alertWithOk(
message: "Move to screen for card payment.",
title: "Authentication Success",
okTitle: "Ok"
) {
let vc = BootPayViewController(dataSource: self, delegate: self)
self.present(vc, animated: true)
}
case .wallet:
BiometricAuthenticationWireframe().openWithDelegate(on: self, delegate: self)
DispatchQueue.main.async {self.bootPayData.onNext(nil)}
}
}.disposed(by: disposeBag)
}).disposed(by: disposeBag)
output.submitSuccess
.drive(onNext: { [weak self] model in
guard let `self` = self else { return }
self.alertWithOk(
type: .normal,
message: "You will receive message about recharge result through SMS.",
title: "Payment Request completed",
okTitle: "Ok"
) {
self.dismiss(animated: true) {
self.delegate?.rechargePayment(self, didComplete: model)
}
}
})
.disposed(by: disposeBag)
rechargeButton.rx.tap.asDriver()
.drive(onNext: {[weak self] in
guard let `self` = self else {return}
BiometricAuthenticationWireframe().openWithDelegate(on: self, delegate: self)
}).disposed(by: disposeBag)
availableBalance.asDriverOnErrorJustComplete()
.drive(balanceLabel.rx.text)
@ -199,13 +233,6 @@ extension RechargePaymentViewController {
})
.disposed(by: disposeBag)
useBalanceTextField.rx.controlEvent(.editingDidBegin)
.bind { [weak self] in
guard let `self` = self else { return }
self.useBalanceTextField.text = "0"
self.useBalanceTextField.sendActions(for: .editingChanged)
}.disposed(by: disposeBag)
let tapGestureRecognizer = UITapGestureRecognizer()
tapGestureRecognizer.delegate = self
tapGestureRecognizer.rx.event.asDriver()
@ -309,10 +336,8 @@ extension RechargePaymentViewController: BootPayDataSource {
// MARK: BootPayDelegate
extension RechargePaymentViewController: BootPayDelegate {
func bootPay(_ viewController: BootPayViewController, didComplete data: CreditCardReceipt) {
dismiss(animated: true) {
self.delegate?.rechargePayment(self, didComplete: data)
}
func bootPay(_ viewController: BootPayViewController, didComplete data: [String: Any]) {
self.bootPayData.onNext(data)
}
}
@ -330,8 +355,8 @@ extension RechargePaymentViewController: BiometricAuthenticationViewControllerDe
informationTitleLabel titleLabel: UILabel,
authenticationButton button: UIButton
) {
titleLabel.text = "Recharge"
button.setTitle("Recharge", for: .normal)
titleLabel.text = "Please enter authentication information for recharge"
button.setTitle("Try Authentication", for: .normal)
}
func didComplete(_ viewController: BiometricAuthenticationViewController) {
@ -340,12 +365,7 @@ extension RechargePaymentViewController: BiometricAuthenticationViewControllerDe
MainWireframe.logoutWarningAlert(message: "To use biometrics authentication you have to login again.")
return
}
// TODO: set password
self.dismiss(animated: true) {
let data = CreditCardReceipt(data: ["pg_name": ""])
self.delegate?.rechargePayment(self, didComplete: data)
}
self.password.onNext(encryptedPW)
}
}
@ -378,10 +398,6 @@ extension RechargePaymentViewController: BiometricAuthenticationViewControllerDe
// MARK: SecureKeypadDelegate
extension RechargePaymentViewController: SecureKeypadDelegate {
func didComplete(_ encryptedString: String, garbagePassword: String, length: Int) {
//TODO: set password
self.dismiss(animated: true) {
let data = CreditCardReceipt(data: ["pg_name": ""])
self.delegate?.rechargePayment(self, didComplete: data)
}
password.onNext(encryptedString)
}
}

2
GME Remit/Modules/PowerCallModules/RechargePayment/User Interface/Wireframe/RechargePaymentWireframe.swift

@ -12,7 +12,7 @@ class RechargePaymentWireframe {
weak var view: UIViewController!
weak var output: RechargePaymentWireframeOutput?
private var model: RechargeModel?
private var delegate: RechargePayementDelegate?
private weak var delegate: RechargePayementDelegate?
}
extension RechargePaymentWireframe: RechargePaymentWireframeInput {

4
GME Remit/Utilities/CustomUI/BootPayViewController.swift

@ -24,7 +24,7 @@ extension BootPayDataSource {
/// Delegate
protocol BootPayDelegate: class {
func bootPay(_ viewController: BootPayViewController, didComplete data: CreditCardReceipt)
func bootPay(_ viewController: BootPayViewController, didComplete data: [String: Any])
func bootPay(_ viewController: BootPayViewController, didError error: [String: Any])
func bootPay(_ viewController: BootPayViewController, didReady data: [String: Any])
func bootPay(_ viewController: BootPayViewController, didCancel data: [String: Any])
@ -109,7 +109,7 @@ extension BootPayViewController: BootpayRequestProtocol {
func onDone(data: [String: Any]) {
self.dismiss(animated: true) {[weak self] in
guard let `self` = self else { return }
self.delegate.bootPay(self, didComplete: CreditCardReceipt(data: data))
self.delegate.bootPay(self, didComplete: data)
}
}

Loading…
Cancel
Save