PaymentViewController.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. //
  2. // PaymentViewController.swift
  3. // MTP2_iOS
  4. //
  5. // Created by 曹晓亮 on 2020/12/10.
  6. // Copyright © 2020 Muchinfo. All rights reserved.
  7. //
  8. import UIKit
  9. import WHToast
  10. import NVActivityIndicatorView
  11. import SwiftyAttributes
  12. import SwiftDate
  13. /// 支付收银台视图容器控制类
  14. class PaymentViewController: BaseViewController {
  15. // MARK: - 属性相关
  16. /// 支付按钮
  17. @IBOutlet weak var payment: UIButton!
  18. /// 支付金额
  19. @IBOutlet weak var amount: UILabel!
  20. /// 支付剩余时间
  21. @IBOutlet weak var timeDown: UILabel!
  22. /// 列表
  23. @IBOutlet weak var tableView: UITableView!
  24. /// cellIdentifier
  25. let cellIdentifier = "Payment_Cell"
  26. /// 支付方式
  27. var payWays: [(title: String, image: UIImage, key: Int)] {
  28. get {
  29. /// 异常
  30. guard let accountManager = MTP2BusinessCore.shared.accountManager,
  31. let constants = accountManager.enums?.filter({$0.enumdiccode == "cashpaymode"}) else {
  32. return []
  33. }
  34. /// 终端配置
  35. let dics = ConfigUtils.getValue(key: .payWay) as? Array<String>
  36. var ways: [(title: String, image: UIImage, key: Int)] = []
  37. constants.forEach({ (obj) in
  38. if dics?.contains(where: {$0 == "\(obj.enumitemname)"}) ?? false {
  39. if obj.enumitemname == 1 || obj.enumitemname == 2 { /// 微信
  40. ways.append((title: obj.enumdicname, image: UIImage(named: "payment_wechat")!, key: obj.enumitemname))
  41. } else if obj.enumitemname == 3 || obj.enumitemname == 4 { /// 支付宝
  42. ways.append((title: obj.enumdicname, image: UIImage(named: "payment_alipay")!, key: obj.enumitemname))
  43. } else if obj.enumitemname == 7 { /// apple pay
  44. ways.append((title: obj.enumdicname, image: UIImage(named: "payment_applepay")!, key: obj.enumitemname))
  45. } else {
  46. ways.append((title: obj.enumdicname, image: UIImage(named: "payment_quick")!, key: obj.enumitemname))
  47. }
  48. }
  49. })
  50. return ways
  51. }
  52. }
  53. /// 当前选中的支付方式
  54. var payWay: (title: String, image: UIImage, key: Int)?
  55. /// 待付款单据
  56. var myPayOrder: MoMyPayOrders? {
  57. didSet {}
  58. }
  59. /// 系统时间戳
  60. var systemTime: String? {
  61. didSet {
  62. /// 初始化定时器
  63. self.initTimer()
  64. }
  65. }
  66. /// 倒计时
  67. var timer: Timer?
  68. /// 计时器
  69. var count = 0.0
  70. // MARK: - 生命周期相关
  71. override func viewDidLoad() {
  72. super.viewDidLoad()
  73. // Do any additional setup after loading the view.
  74. /// UI界面初始化
  75. buildView()
  76. }
  77. deinit {
  78. /// 定时器失效
  79. timer?.invalidate()
  80. timer = nil
  81. }
  82. override func viewWillAppear(_ animated: Bool) {
  83. super.viewWillAppear(animated)
  84. /// 隐藏导航栏
  85. self.navigationController?.setNavigationBarHidden(false, animated: true)
  86. }
  87. // MARK: - 初始化相关
  88. /// UI界面初始化
  89. fileprivate func buildView() {
  90. /// 异常
  91. guard let obj = myPayOrder else {
  92. return
  93. }
  94. /// 支付金额
  95. self.amount.attributedText = ("\(obj.currencysign) ".withFont(.font_14)+"\(obj.payamount)".withFont(.font_22)).withTextColor(UIColorFromHex(rgbValue: 0xdf5958))
  96. /// 刷新列表
  97. tableView.reloadData()
  98. /// 获取系统世间
  99. self.requestGetSystemTime()
  100. }
  101. // MARK: - 交互相关
  102. /// 按钮点击响应交互事件
  103. /// - Parameter sender: sender
  104. @IBAction fileprivate func onButtonPressed(_ sender: UIControl) {
  105. switch sender {
  106. case payment:
  107. /// 未选择支付渠道
  108. guard let way = self.payWay,
  109. let obj = myPayOrder else {
  110. WHToast.showError(withMessage: "请选择支付渠道", duration: 1.5, finishHandler: {})
  111. return
  112. }
  113. doPayment(EPayWay(rawValue: way.key)!, obj.tradeid)
  114. default:
  115. break
  116. }
  117. }
  118. // MARK: - 倒计时相关
  119. /// 初始化定时器
  120. fileprivate func initTimer() {
  121. if self.timer != nil {
  122. self.timer?.invalidate()
  123. self.timer = nil
  124. }
  125. /// 开始计时
  126. self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.calculateTimeDown), userInfo: nil, repeats: true)
  127. self.timer?.fire()
  128. /// 滚动时失效
  129. RunLoop.current.add(self.timer!, forMode: .common)
  130. }
  131. /// 倒计时计算
  132. @objc fileprivate func calculateTimeDown() {
  133. /// 异常
  134. guard let obj = myPayOrder,
  135. let paylimitedtime = DateUtils.getTDateString(obj.paylimitedtime, "yyyy-MM-dd HH:mm:ss").date(formatter: "yyyy-MM-dd HH:mm:ss"),
  136. let sysTime = self.systemTime?.date(formatter: "yyyy-MM-dd HH:mm:ss"),
  137. let dateComponents = DateUtils.diffs(paylimitedtime.timeIntervalSinceNow, sysTime.timeIntervalSinceNow-28800.0, count) else { return }
  138. /// 格式化
  139. let hour = abs(dateComponents.hour ?? 0), hourStr = hour < 10 ? "0\(hour)" : "\(hour)"
  140. let minute = abs(dateComponents.minute ?? 0), minuteStr = minute < 10 ? "0\(minute)" : "\(minute)"
  141. let second = abs(dateComponents.second ?? 0), secondStr = second < 10 ? "0\(second)" : "\(second)"
  142. /// 倒计时
  143. timeDown.text = "支付剩余时间 \(hourStr):\(minuteStr):\(secondStr)"
  144. /// 计数器
  145. count += 1.0
  146. /// 重新去请求商品数据信息
  147. if dateComponents.hour == 0,
  148. dateComponents.minute == 0,
  149. dateComponents.second == 0 {
  150. WHToast.showMessage("订单已超时", duration: 1.5, finishHandler: {
  151. self.navigationController?.popViewController(animated: true)
  152. })
  153. }
  154. }
  155. // MARK: - 微信支付
  156. /// 构建微信支付请求参数
  157. /// - Parameter payChannel: 支付类型
  158. fileprivate func buildPayParmaert(_ way: EPayWay, _ param: MoPayParam?) {
  159. /// "请求支付参数错误!"
  160. guard let _ = param else {
  161. WHToast.showError(withMessage: "请求支付参数错误!", duration: 1.5, finishHandler: {})
  162. return
  163. }
  164. let dic: NSMutableDictionary = NSMutableDictionary()
  165. dic.setValue(param?.appPayRequest ?? "", forKey: "appPayRequest")
  166. switch way {
  167. case .WeChat, .WeChatUni: /// 微信支付
  168. self.sendWeiXinPayRequest(dic as NSDictionary?)
  169. case .AliPay, .AliUniPay: /// 支付宝支付
  170. self.sendAlipayRequest(dic as NSDictionary?)
  171. default: /// 云闪付支付
  172. self.sendUnifyQuickPayRequest(dic as NSDictionary?)
  173. }
  174. }
  175. /// 微信支付请求
  176. /// - Parameter response: response
  177. fileprivate func sendWeiXinPayRequest(_ response: NSDictionary?) {
  178. if (response?["appPayRequest"] != nil) {
  179. /// 前去支付
  180. UMSPPPayUnifyPayPlugin.pay(withPayChannel: CHANNEL_WEIXIN, payData: response?["appPayRequest"] as? String) { (resultCode, resultInfo) in
  181. DispatchQueue.main.async {
  182. if resultCode == "0000" {
  183. self.navigationController?.popViewController(animated: true)
  184. } else {
  185. let data = resultInfo?.data(using: .utf8)
  186. let dic = (try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)) as? NSDictionary
  187. let msg = dic?["resultMsg"] as? String
  188. WHToast.showMessage("\(msg ?? "未知错误")", duration: 2.0, finishHandler: {})
  189. }
  190. }
  191. }
  192. }
  193. }
  194. /// 支付宝支付请求
  195. /// - Parameter response: response
  196. fileprivate func sendAlipayRequest(_ response: NSDictionary?) {
  197. if (response?["appPayRequest"] != nil) {
  198. /// 发送请求
  199. UMSPPPayUnifyPayPlugin.pay(withPayChannel: CHANNEL_ALIMINIPAY, payData: response?["appPayRequest"] as? String) { (resultCode, resultInfo) in
  200. if resultCode == "1003" {
  201. DispatchQueue.main.async {
  202. if resultCode == "0000" {
  203. self.navigationController?.popViewController(animated: true)
  204. } else {
  205. WHToast.showMessage("resultCode = \(resultCode ?? "")\nresultInfo = \(resultInfo ?? "")", duration: 1.5, finishHandler: {})
  206. }
  207. }
  208. }
  209. }
  210. }
  211. }
  212. /// 银闪付支付请求
  213. /// - Parameter response: response
  214. fileprivate func sendUnifyQuickPayRequest(_ response: NSDictionary?) {
  215. if (response?["appPayRequest"] != nil) {
  216. /// 发送请求
  217. UMSPPPayUnifyPayPlugin.cloudPay(withURLSchemes: "haishangbaoyeunifypay", payData: response?["appPayRequest"] as? String, viewController: self) { (resultCode, resultInfo) in
  218. DispatchQueue.main.async {
  219. if resultCode == "0000" {
  220. self.navigationController?.popViewController(animated: true)
  221. } else {
  222. let data = resultInfo?.data(using: .utf8)
  223. let dic = (try? JSONSerialization.jsonObject(with: data!, options: .allowFragments)) as? NSDictionary
  224. let msg = dic?["resultMsg"] as? String
  225. WHToast.showMessage("\(msg ?? "未知错误")", duration: 1.5, finishHandler: {})
  226. }
  227. }
  228. }
  229. }
  230. }
  231. // MARK: - 接口请求
  232. /// 支付请求响应方法
  233. fileprivate func doPayment(_ payWay: EPayWay, _ orderNo: String) {
  234. /// 异常
  235. guard let bankManager = MTP2BusinessCore.shared.bankManager,
  236. let accountManager = MTP2BusinessCore.shared.accountManager,
  237. let payOrder = myPayOrder,
  238. let accountName = accountManager.moAccountBaseInfo?.accountInfo.accountName else {
  239. return
  240. }
  241. /// 开启Loading
  242. NVActivityIndicatorPresenter.sharedInstance.startAnimating(ActivityData(message: "支付中......".localized, type: .ballClipRotate, color: UIColorFromHex(rgbValue: 0xA8B6CC)), NVActivityIndicatorView.DEFAULT_FADE_IN_ANIMATION)
  243. /// 请求生成下单参数
  244. bankManager.requestQuickPay(payOrder.marketid, payOrder.tradeid, Date().getString(formatter: "yyyy-MM-dd"), payOrder.payamount, payWay, accountName) { (isComplete, error, param) in
  245. DispatchQueue.main.async {
  246. /// stop loding.....
  247. NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION)
  248. if isComplete,
  249. param?.errCode == "SUCCESS" {
  250. /// 构建支付参数
  251. self.buildPayParmaert(payWay, param)
  252. } else {
  253. WHToast.showError(withMessage: "支付失败,原因:\(param?.errMsg ?? "未知错误。")", duration: 1.5, finishHandler: {})
  254. }
  255. }
  256. }
  257. }
  258. /// 获取系统世间
  259. fileprivate func requestGetSystemTime() {
  260. /// 异常
  261. guard let accountManager = MTP2BusinessCore.shared.accountManager else {
  262. return
  263. }
  264. /// 获取系统世间
  265. accountManager.requestGetServerTime { (isComplete, error, time) in
  266. DispatchQueue.main.async {
  267. if isComplete {
  268. /// 初始化定时器
  269. self.systemTime = time ?? Date().description
  270. } else { /// 获取失败
  271. WHToast.showError(withMessage: "获取系统时间失败!", duration: 1.5, finishHandler: {
  272. self.navigationController?.popViewController(animated: true)
  273. })
  274. }
  275. }
  276. }
  277. }
  278. }
  279. extension PaymentViewController: UITableViewDelegate, UITableViewDataSource {
  280. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  281. return payWays.count
  282. }
  283. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  284. let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! PaymentCell
  285. /// 回调
  286. cell.block = { (_ model: (title: String, image: UIImage, key: Int)?) in
  287. /// 选中的支付方式
  288. self.payWay = model
  289. }
  290. cell.model = payWays[indexPath.row]
  291. return cell
  292. }
  293. func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  294. return 60.0
  295. }
  296. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  297. for (index, obj) in tableView.visibleCells.enumerated() {
  298. (obj as! PaymentCell).isCheck = index == indexPath.row
  299. }
  300. }
  301. }
  302. class PaymentCell: BaseTableViewCell<(title: String, image: UIImage, key: Int)> {
  303. /// 类型
  304. @IBOutlet weak var typeImage: UIImageView!
  305. /// 支付名称
  306. @IBOutlet weak var titleLabel: UILabel!
  307. /// 类型
  308. @IBOutlet weak var checkImage: UIImageView!
  309. /// 是否选中
  310. var isCheck: Bool = false {
  311. didSet {
  312. checkImage.isHidden = !isCheck
  313. /// 执行回调
  314. if let callBack = block, isCheck {
  315. callBack(model)
  316. }
  317. }
  318. }
  319. /// 数据模型
  320. override var model: (title: String, image: UIImage, key: Int)? {
  321. didSet {
  322. guard let obj = model else {
  323. return
  324. }
  325. /// 支付名称
  326. titleLabel.text = obj.title
  327. /// 类型
  328. typeImage.image = obj.image
  329. }
  330. }
  331. /// 回调块
  332. var block: ((_ model: (title: String, image: UIImage, key: Int)?) -> Void)?
  333. }