// // CheckMobileViewController.swift // MTP2_iOS // // Created by Muchinfo on 2018/11/15. // Copyright © 2018 Muchinfo. All rights reserved. // import UIKit import NVActivityIndicatorView import WHToast class CheckMobileViewController: BaseViewController { private let TAG_BACK = 100 private let TAG_CAPTCHA = 101 private let TAG_COMMIT = 102 private let TAG_MOBILEAREACODE = 103 /// 导航栏标题 @IBOutlet weak var navTitle: UINavigationItem! /// 手机号码输入框 @IBOutlet weak var mobileTextField: UITextField! { didSet { mobileTextField.attributedPlaceholder = "pleaseEnterPhoneNumber".withTextColor(Color_placeholder_text) } } /// 区号按钮 @IBOutlet weak var areaButton: UIButton! { didSet { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.2) { self.areaButton.layer.masksToBounds = false self.areaButton.layer.cornerRadius = 0 } } } /// 验证码输入框 @IBOutlet weak var captchaTextField: UITextField! { didSet { captchaTextField.attributedPlaceholder = "请输入手机验证码".withTextColor(Color_placeholder_text) } } /// 提交按钮 @IBOutlet weak var commitButton: UIButton! /// 验证码按钮 @IBOutlet weak var captchaButton: UIButton! /// 定时器 @IBOutlet weak var timerLabel: UILabel! /// 高度约束 @IBOutlet weak var referralLayoutConstraint: NSLayoutConstraint! /// 推荐码 @IBOutlet weak var referralField: UITextField! { didSet { referralField.attributedPlaceholder = "请输入推荐码".withTextColor(Color_placeholder_text) } } /// 登录类型 var type = CheckMobileType.MobileSignin /// 三方登录的OpenID, 注册业务必需 var openID: String? var accessToken: String? /// 三方登录类型,“1”为微信;“2”为支付宝。注册业务必需 var authType: String? /// 手机区号 默认为+86 var areaCode: String = "+86" /// 是否需要显示推荐码 0不需要显示推荐码 var isShowRefer: Int = 0 { didSet { referralLayoutConstraint.constant = isShowRefer == 0 ? 0.0 : 55.0 } } /// 短信验证码 lazy var imageCodeViewController: ImageCodeViewController = { $0.popBlock = { [weak self] (_ takeInfo: String?) in /// 发送验证码 self?.sendCaptcha() } return $0 } (viewController(name: "ResetPwd", identifier: "ImageCodeID") as! ImageCodeViewController) /// 定时器相关 private let captchaTimerID = "captchaTimerID" private var captchaCD = 60 // MARK: - 生命周期相关 override func viewDidLoad() { super.viewDidLoad() /// UI界面初始化 buildView() } deinit { /// 销毁定时器 MCGCDTimer.shared.cancleTimer(WithTimerName: self.captchaTimerID) } // MARK: - 生命周期相关 /// UI界面初始化 private func buildView() { switch type { case .AuthSignup: // 三方登录注册业务 navTitle.title = "手机验证" commitButton.setTitle("验证", for: .normal) case .MobileSignin: // 手机号码登录 navTitle.title = "手机登录" commitButton.setTitle("登录", for: .normal) } /// 获取上次登录的手机账号 guard let phone = UserDefaultsUtils.getLoginPhone(), phone != "" else { return } mobileTextField.text = phone } // MARK: - 交互相关 @IBAction func onViewPressed(_ sender: UIControl) { switch sender.tag { case TAG_BACK: self.navigationController?.dismiss(animated: true, completion: nil) case TAG_CAPTCHA: // 发送短信验证码 /// 手机号码 guard let mobile = mobileTextField.text, mobile != "" else { WHToast.showError(withMessage: "请输入手机号码", duration: 1.5, finishHandler: {}) return } self.present(imageCodeViewController, animated: true, completion: {}) case TAG_MOBILEAREACODE: /// 手机区号 let mobileArearCodeViewController = viewController(name: "ResetPwd", identifier: "MobileAreaCodeID") as! MobileAreaCodeViewController /// 设置手机区号 mobileArearCodeViewController.popBlock = { [weak self] (_ code: String) in DispatchQueue.main.async { self?.areaCode = code self?.areaButton.setTitle(code, for: .normal) } } self.navigationController?.pushViewController(mobileArearCodeViewController, animated: true) case TAG_COMMIT: // 提交 self.view.endEditing(true) guard let mobile = mobileTextField.text, mobile != "" else { WHToast.showError(withMessage: "pleaseentercorrectmobilenumber", duration: 1.0, finishHandler: {}) return } guard let captcha = captchaTextField.text, captcha.trimmingCharacters(in: .whitespaces) != "" else { WHToast.showError(withMessage: "pleaseEnterCheckCode", duration: 1.0, finishHandler: {}) return } if self.type == .AuthSignup { // 三方登录注册业务 authSignup(nil) } else { // 手机号码登录 mobileLogin(nil) } default: break } } // MARK: - 验证码相关 /// 设置验证码按钮状态的方法 /// /// - Parameter enable: 是否可用,如为不可用则开始60s倒计时 private func setCaptcha(enable: Bool) { if enable { MCGCDTimer.shared.cancleTimer(WithTimerName: self.captchaTimerID) DispatchQueue.main.async { self.captchaButton.isEnabled = true self.captchaButton.setTitle("获取验证码", for: .normal) self.timerLabel.isHidden = true } } else { DispatchQueue.main.async { self.captchaCD = 60 self.captchaButton.isEnabled = false self.captchaButton.setTitle("", for: .disabled) self.timerLabel.text = "\(self.captchaCD)秒" self.timerLabel.isHidden = false self.captchaTextField.becomeFirstResponder() MCGCDTimer.shared.cancleTimer(WithTimerName: self.captchaTimerID) MCGCDTimer.shared.scheduledDispatchTimer(WithTimerName: self.captchaTimerID, timeInterval: 1.0, queue: .main, repeats: true, isNowRun: false) { DispatchQueue.main.async { self.captchaCD -= 1 self.timerLabel.text = "\(self.captchaCD)秒" if self.captchaCD <= 0 { self.setCaptcha(enable: true) } } } } } } /// 发送短信验证码的方法 private func sendCaptcha() { /// 数据异常 guard let accountManager = MTP2BusinessCore.shared.accountManager else { return } /// 手机号码 let mobile = mobileTextField.text ?? "" accountManager.requestSendMobileCaptchaCode(mobile, areaCode, callback: { (isCompleted, errorInfo, showRefer, vcode) in DispatchQueue.main.async { if !isCompleted { self.showHintController(title: "提示", message: errorInfo?.retMsg ?? "发送失败,请稍后重试") return } else { /// 是否显示推荐码 self.isShowRefer = showRefer ?? 0 } } }) self.setCaptcha(enable: false) } /// 三方登录注册的方法 /// /// - Parameter memareacode: 所属机构代码 private func authSignup(_ memareacode: String?) { /// 数据异常 guard let accountManager = MTP2BusinessCore.shared.accountManager else { return } /// pleaseEnterCheckCode guard let captcha = self.captchaTextField.text else { WHToast.showError(withMessage: "pleaseEnterCheckCode", duration: 1.0, finishHandler: {}) return } /// 缺少必要数据,请稍后重试 guard let openID = self.openID, let authType = self.authType, let mobile = mobileTextField.text else { WHToast.showError(withMessage: "缺少必要数据,请稍后重试", duration: 1.0, finishHandler: {}) return } /// 三方登录注册 accountManager.authSignup(mobile: mobile, captcha: captcha, authType: authType, openID: openID, memareacode: memareacode, verifyType: nil) { isCompleted, resultDic in if let resultDic = resultDic, let success = resultDic["success"] as? String, let msg = resultDic["msg"] as? String { if success == "false" { /// 注册返回false,可能为需要补机构代码,也可以是注册失败 let array = msg.split(separator: "^") if array.count > 1 && array[1] == "2" { /// 需要补充所属机构 “请输入会员和机构代码” DispatchQueue.main.async { let alertController = UIAlertController(title: "提示", message: "请输入会员或机构代码", preferredStyle: .alert) alertController.addTextField { textField in textField.keyboardType = UIKeyboardType.numberPad } alertController.addAction(UIAlertAction(title: "提交", style: .destructive) { action in guard let textField = alertController.textFields?[0], let value = textField.text else { WHToast.showError(withMessage: "请输入会员或机构代码", duration: 1.0, finishHandler: {}) return } self.authSignup(value) }) alertController.addAction(UIAlertAction(title: "cancle", style: .cancel) { action in DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) } }) self.present(alertController, animated: true, completion: nil) } } else { DispatchQueue.main.sync { // 正常失败 NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "\(msg.replacingOccurrences(of: "^1", with: ""))") } } return } else { /// 注册成功,并已登录成功,进行连接恢复和Token校验 /// 构建LoginRsp do { guard let range = msg.range(of: "?response=", options: .backwards, range: nil, locale: nil), let probufDataString = msg.suffix(msg.lengthOfBytes(using: .utf8) - range.upperBound.utf16Offset(in: "")).removingPercentEncoding, let data = Data(base64Encoded: String(probufDataString), options: Data.Base64DecodingOptions.init(rawValue: 0)) else { DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "注册失败,请稍后重试") } return } let authLoginRsp = try AuthLoginRsp(serializedData: data) if authLoginRsp.retCode == 0 { let loginRsp = LoginRsp.with { $0.loginID = authLoginRsp.loginID $0.loginUserType = authLoginRsp.loginUserType $0.accountStatus = authLoginRsp.accountStatus $0.userID = authLoginRsp.userID $0.memberUserID = authLoginRsp.memberUserID $0.accountIds = authLoginRsp.accountIds $0.token = authLoginRsp.token $0.systemTime = authLoginRsp.systemTime $0.hasUpdatedPwd_p = authLoginRsp.hasUpdatedPwd_p } accountManager.thenLogined(loginRsp: loginRsp) /// 连接交易链路,并进行CheckToken accountManager.recoverLogin(loginRsp: loginRsp) { isCompleted in if !isCompleted { DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "loginFailPleaseTryAgainLater") } return } /// 调用登录后的处理方法 self.loginedToDo() } } else { DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: ErrorUtils.getDesc(errorCode: Int(authLoginRsp.retCode)) ?? "loginFailPleaseTryAgainLater") } } } catch { DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "loginFailPleaseTryAgainLater") } } } } } } /// 手机号码登录的方法 /// /// - Parameter memareacode: 所属机构代码 private func mobileLogin(_ memareacode: String?) { /// 输入不合规 guard checkInputValue(), let accountManager = MTP2BusinessCore.shared.accountManager else { return } /// 手机号码 let mobile = mobileTextField.text ?? "" /// 短信验证码 let captcha = captchaTextField.text ?? "" /// 推荐码 let referral = isShowRefer == 0 ? nil : (referralField.text ?? "") /// 开启Loading NVActivityIndicatorPresenter.sharedInstance.startAnimating(ActivityData(message: "请稍等……", type: .ballClipRotate, color: UIColorFromHex(rgbValue: 0xA8B6CC)), NVActivityIndicatorView.DEFAULT_FADE_IN_ANIMATION) /// 手机号码登录 accountManager.mobileLogin(mobile: areaCode+mobile, referral, captcha: captcha, memareacode: memareacode) { isCompleted, resultDic in if let resultDic = resultDic, let success = resultDic["success"] as? String, let msg = (resultDic["msg"] as? String)?.removingPercentEncoding { if success == "false" { /// 注册返回false,可能为需要补机构代码,也可以是注册失败 let array = msg.split(separator: "^") if array.count > 1 && array[1] == "2" { /// 需要补充所属机构 “请输入会员和机构代码” DispatchQueue.main.async { let alertController = UIAlertController(title: "提示", message: "请输入会员或机构代码", preferredStyle: .alert) alertController.addTextField { textField in textField.keyboardType = UIKeyboardType.numberPad } alertController.addAction(UIAlertAction(title: "提交", style: .destructive) { action in guard let textField = alertController.textFields?[0], let value = textField.text else { self.showHintController(title: "提示", message: "请输入会员或机构代码") return } self.mobileLogin(value) }) alertController.addAction(UIAlertAction(title: "cancle", style: .cancel) { action in DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) } }) self.present(alertController, animated: true, completion: nil) } } else { DispatchQueue.main.sync { /// 正常失败 NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "\(msg.replacingOccurrences(of: "^1", with: ""))") } } return } else { /// 注册成功,并已登录成功,进行连接恢复和Token校验 /// 构建LoginRsp do { guard let data = Data(base64Encoded: msg, options: Data.Base64DecodingOptions.init(rawValue: 0)) else { DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "loginFailPleaseTryAgainLater") } return } /// 手机号码登录返回的是LoginRsp let loginRsp = try LoginRsp(serializedData: data) if loginRsp.retCode == 0 { accountManager.thenLogined(loginRsp: loginRsp) /// 连接交易链路,并进行CheckToken accountManager.recoverLogin(loginRsp: loginRsp) { isCompleted in if isCompleted == false { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "loginFailPleaseTryAgainLater") return } /// 记录本次登录的手机号码 UserDefaultsUtils.setLoginPhone(mobile) /// 调用登录后的处理方法 self.loginedToDo() } } else { DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: ErrorUtils.getDesc(errorCode: Int(loginRsp.retCode)) ?? "loginFailPleaseTryAgainLater") } } } catch { DispatchQueue.main.sync { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(NVActivityIndicatorView.DEFAULT_FADE_OUT_ANIMATION) self.showHintController(title: "提示", message: "loginFailPleaseTryAgainLater") } } } } } } /// 登录成功后调用的方法 func loginedToDo() { /// FIXME: - 实属无奈才把ui的内容放到这里,后期要处理 let appDelegate = UIApplication.shared.delegate as! AppDelegate /// 异常 guard let accountManager = MTP2BusinessCore.shared.accountManager else { return } /// 用户与商品信息统一查询 accountManager.queryAccountAndGoods(callback: { (isCompleted, error) in if isCompleted { /// TODO: 查询是否需要修改密码 accountManager.configQueryPostting{ (isSuccess, errorInfo) in DispatchQueue.main.async { /// 记录本地用户信息 try? DatabaseHelper.addUser(userID: MTP2BusinessCore.shared.getUserID(), loginID: String(MTP2BusinessCore.shared.getLoginID()), loginDate: Date(), type: Int16(appDelegate.currentAuthType)) /// 进入主界面 let storyboard = UIStoryboard(name: "Main", bundle: nil) if let mainTabBarController: UITabBarController = storyboard.instantiateViewController(withIdentifier: "MainTabBarController") as? UITabBarController { appDelegate.window?.rootViewController = mainTabBarController } } } } else { DispatchQueue.main.async { if appDelegate.window?.rootViewController?.isKind(of: LoginViewController.self) ?? false, let loginViewController = (appDelegate.window?.rootViewController as? BaseNavigationController)?.topViewController as? LoginViewController { loginViewController.showHintController(title: "提示", message: "注册失败,请稍后重试") } } } }) } /// 合规性校验 private func checkInputValue() -> Bool { /// 手机号码 guard let mobile = mobileTextField.text, mobile != "" else { WHToast.showError(withMessage: "请输入手机号码", duration: 1.5, finishHandler: {}) return false } /// 短信验证码 guard let captcha = self.captchaTextField.text, captcha != "" else { WHToast.showError(withMessage: "请输入验证码", duration: 1.5, finishHandler: {}) return false } /// 需要显示推荐码 if isShowRefer != 0 { /// 短信验证码 guard let referral = self.referralField.text, referral != "" else { WHToast.showError(withMessage: "请输入推荐码", duration: 1.5, finishHandler: {}) return false } } return true } }