123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224 |
- //
- // O2AuthSDK.swift
- // O2OA_SDK_Framwork
- //
- // Created by FancyLou on 2018/11/6.
- //
- import UIKit
- import RxSwift
- import Moya
- import CommonCrypto
- public class O2AuthSDK: NSObject {
-
- /// 单例
- public static let shared: O2AuthSDK = O2AuthSDK()
-
- private override init() {}
-
- private let registerAPI: O2MoyaProvider<O2RegisterAPI> = {
- return O2MoyaProvider<O2RegisterAPI>()
- }()
- private let loginAPI: O2MoyaProvider<O2LoginAPI> = {
- return O2MoyaProvider<O2LoginAPI>()
- }()
-
-
- //MARK: - public 公开本地对象
-
-
- /// 当前登录用户信息
- ///
- /// - Returns:
- public func myInfo() -> O2LoginAccountModel? {
- return O2UserDefaults.shared.myInfo
- }
-
- /// 当前绑定单位服务器信息
- ///
- /// - Returns:
- public func bindUnit() -> O2BindUnitModel? {
- return O2UserDefaults.shared.unit
- }
-
- /// 当前绑定的设备信息
- ///
- /// - Returns:
- public func bindDevice() -> O2BindDeviceModel? {
- return O2UserDefaults.shared.device
- }
-
- /// 设置设备token 极光推送用的
- ///
- /// - Parameter token: 极光推送deviceToken
- public func setDeviceToken(token: String) {
- O2UserDefaults.shared.deviceToken = token
- }
-
- /// 获取设备token
- ///
- /// - Returns: 极光推送deviceToken
- public func getDeviceToken() -> String {
- return O2UserDefaults.shared.deviceToken ?? ""
- }
-
- /// O2OA服务器信息
- ///
- /// - Returns:
- public func centerServerInfo() -> O2CenterServerModel? {
- return O2UserDefaults.shared.centerServer
- }
-
- /// O2OA 服务器 各个微服务信息
- ///
- /// - Parameter context: 微服务
- /// - Returns:
- public func o2APIServer(context: O2ModuleContext) -> O2APIServerModel? {
- guard let dic = O2UserDefaults.shared.centerServer?.assembles else {
- return nil
- }
- switch context {
- case .x_processplatform_assemble_surface_script:
- return dic["x_processplatform_assemble_surface_script"]
-
- case .x_processplatform_assemble_surface_task:
- return dic["x_processplatform_assemble_surface_task"]
-
- case .x_processplatform_assemble_surface_worklog:
- return dic["x_processplatform_assemble_surface_worklog"]
-
- case .x_processplatform_assemble_surface_workcompleted:
- return dic["x_processplatform_assemble_surface_workcompleted"]
-
- case .x_processplatform_assemble_surface_attachment:
- return dic["x_processplatform_assemble_surface_attachment"]
-
- case .x_processplatform_assemble_surface_work:
- return dic["x_processplatform_assemble_surface_work"]
-
- case .x_file_assemble_control:
- return dic["x_file_assemble_control"]
-
- case .x_meeting_assemble_control:
- return dic["x_meeting_assemble_control"]
-
- case .x_attendance_assemble_control:
- return dic["x_attendance_assemble_control"]
-
- case .x_okr_assemble_control:
- return dic["x_okr_assemble_control"]
-
- case .x_bbs_assemble_control:
- return dic["x_bbs_assemble_control"]
-
- case .x_hotpic_assemble_control:
- return dic["x_hotpic_assemble_control"]
-
- case .x_processplatform_assemble_surface_applicationdict:
- return dic["x_processplatform_assemble_surface_applicationdict"]
-
- case .x_cms_assemble_control:
- return dic["x_cms_assemble_control"]
-
- case .x_organization_assemble_control:
- return dic["x_organization_assemble_control"]
-
- case .x_collaboration_assemble_websocket:
- return dic["x_collaboration_assemble_websocket"]
-
- case .x_organization_assemble_custom:
- return dic["x_organization_assemble_custom"]
-
- case .x_processplatform_assemble_surface:
- return dic["x_processplatform_assemble_surface"]
-
- case .x_processplatform_assemble_surface_read:
- return dic["x_processplatform_assemble_surface_read"]
-
- case .x_processplatform_assemble_surface_readcompleted:
- return dic["x_processplatform_assemble_surface_readcompleted"]
-
- case .x_organization_assemble_express:
- return dic["x_organization_assemble_express"]
-
- case .x_organization_assemble_personal:
- return dic["x_organization_assemble_personal"]
-
- case .x_processplatform_assemble_surface_taskcompleted:
- return dic["x_processplatform_assemble_surface_taskcompleted"]
-
- case .x_processplatform_assemble_surface_process:
- return dic["x_processplatform_assemble_surface_process"]
-
- case .x_component_assemble_control:
- return dic["x_component_assemble_control"]
-
- case .x_processplatform_assemble_surface_application:
- return dic["x_processplatform_assemble_surface_application"]
-
- case .x_processplatform_assemble_surface_data:
- return dic["x_processplatform_assemble_surface_data"]
-
- case .x_processplatform_assemble_designer:
- return dic["x_processplatform_assemble_designer"]
-
- case .x_processplatform_assemble_surface_review:
- return dic["x_processplatform_assemble_surface_review"]
-
- case .x_organization_assemble_authentication:
- return dic["x_organization_assemble_authentication"]
-
- case .x_portal_assemble_surface:
- return dic["x_portal_assemble_surface"]
-
- case .x_calendar_assemble_control:
- return dic["x_calendar_assemble_control"]
-
- case .x_jpush_assemble_control:
- return dic["x_jpush_assemble_control"]
- }
- }
-
- /// 移动端配置信息
- ///
- /// - Returns:
- public func customStyle() -> O2CustomStyleModel? {
- return O2UserDefaults.shared.customStyle
- }
-
- /// 移动端配置hash值
- ///
- /// - Returns:
- public func customStyleHash() -> String? {
- return O2UserDefaults.shared.customStyleHash
- }
-
- /// 移动端应用列表
- ///
- /// - Returns:
- public func o2AppList() -> [O2AppModel] {
- var list: [O2AppModel] = []
- if let nativeList = O2UserDefaults.shared.customStyle?.nativeAppList {
- for native in nativeList {
- let app = O2AppModel()
- app.id = native.key
- app.name = native.name
- app.portalUrl = ""
- app.portalCategory = ""
- app.type = O2ConfigInfo.O2_APP_TYPE_NATIVE
- app.enable = native.enable
- list.append(app)
- }
- }
- if let portalList = O2UserDefaults.shared.customStyle?.portalList {
- for portal in portalList {
- let app = O2AppModel()
- app.id = portal.id
- app.name = portal.name
- if let webserver = O2UserDefaults.shared.centerServer?.webServer {
- app.portalUrl = "\(webserver.httpProtocol ?? "http")://\(webserver.host ?? ""):\(webserver.port ?? 80)/\(O2ConfigInfo.O2_DESKTOP_CONTEXT)/appMobile.html?app=portal.Portal&status={\"portalId\":\"\(portal.id ?? "")\"}"
- }
- app.portalCategory = portal.portalCategory
- app.type = O2ConfigInfo.O2_APP_TYPE_PORTAL
- app.enable = portal.enable
- list.append(app)
- }
- }
-
- return list
- }
-
- //MARK: - public 公开方法
-
- /// 启动
- /// 整个过程包括绑定信息检查,客户端信息检查,登录检查
- /// - Parameter callback: O2LaunchProcessState
- public func launch(callback: @escaping (_ state: O2LaunchProcessState, _ msg: String?)->()) {
- _ = checkBindUnit()
- // .flatMap { (device) -> Observable<Response> in
- // return self.checkBindUnitIsExpired(device: device)
- // }
- .flatMap { (unit) -> Observable<Response> in
- // let o2Res = response.mapObject(BaseO2ResponseData<O2BindUnitModel>.self)
- // if o2Res?.isSuccess() == false {
- // throw O2AuthError.bindExpireError
- // }else {
- // guard let unit = o2Res?.data else {
- // throw O2AuthError.bindExpireError
- // }
- // // 每次验证完成后更新unit 信息 , 连接unit的中心服务器
- // O2UserDefaults.shared.unit = unit
- // return self.connectToCenterServer(unit: unit)
- // }
- return self.connectToCenterServer(unit: unit)
-
- }.flatMap({ (response) -> Observable<Response> in
- let result = response.mapObject(BaseO2ResponseData<O2CenterServerModel>.self)
- if let centerServer = result?.data {
- let unit = O2UserDefaults.shared.unit
- let httpProtocol = unit?.httpProtocol ?? "http"
- centerServer.assembles?.forEach({ (key,value) in
- value.httpProtocol = httpProtocol
- centerServer.assembles![key] = value
- })
- centerServer.webServer?.httpProtocol = httpProtocol
- // 保存中心服务器数据
- O2UserDefaults.shared.centerServer = centerServer
- return self.checkCustomStyleNeedUpdate(unit: unit!)
- }else {
- throw O2AuthError.blockError("无法连接中心服务器!")
- }
- }).flatMap { (response) -> Observable<Bool> in
- let o2Res = response.mapObject(BaseO2ResponseData<O2StringValueModel>.self)
- let currentHash = O2UserDefaults.shared.customStyleHash ?? ""
- if o2Res?.isSuccess() == false {
- throw O2AuthError.blockError("检查移动端配置是否需要更新时出错, \(o2Res?.message ?? "")")
- }else {
- if let newHash = o2Res?.data?.value {
- if newHash == currentHash { // 没有更新不需要下载
- return self.boolObservableCreate(true)
- }else {
- //保存这个hash码,并下载
- O2UserDefaults.shared.customStyleHash = newHash
- return self.downloadCustomStyle()
- }
- }else {
- throw O2AuthError.blockError("检查移动端配置是否需要更新时出错, 没有获取到hash值")
- }
- }
- }.flatMap { (result) -> Observable<Response> in
- if result {
- if let token = O2UserDefaults.shared.myInfo?.token {
- return self.loginWithToken(token)
- }else {
- guard let mobile = O2UserDefaults.shared.device?.mobile, let code = O2UserDefaults.shared.device?.code else {
- throw O2AuthError.noLoginError
- }
- return self.loginWithPhoneCode(mobile, code)
- }
- }else {
- throw O2AuthError.blockError("下载移动端配置时出错!!!")
- }
- }.flatMap { (response) -> Observable<Bool> in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- return self.boolObservableCreate(true)
- }else {
- throw O2AuthError.noLoginError
- }
- }else {
- throw O2AuthError.noLoginError
- }
- }
- .subscribe { (event) in
- switch event {
- case .next(let element):
- if element {
- callback(O2LaunchProcessState.success, nil)
- }else {
- callback(O2LaunchProcessState.loginError, "登录失败!")
- }
- break
- case .error(let error):
- if error is O2AuthError {
- let aError = error as! O2AuthError
- switch aError {
- case .noLoginError:
- callback(O2LaunchProcessState.loginError, "登录失败!")
- break
- case .noBindError:
- callback(O2LaunchProcessState.bindError, "绑定失败!")
- break
- case .bindExpireError:
- callback(O2LaunchProcessState.bindError, "绑定过期!")
- break
- case .blockError(let msg):
- callback(O2LaunchProcessState.unknownError, msg)
- break
- }
- }else {
- callback(O2LaunchProcessState.unknownError, "未知错误,\(String(describing: error))")
- }
- break
- case .completed:
- break
- }
- }
-
- }
-
-
- /// 内网版本启动入口
- ///
- /// - Parameters:
- /// - unit: 内网服务器信息
- /// - callback: O2LaunchProcessState
- public func launchInner(unit: O2BindUnitModel, callback: @escaping (_ state: O2LaunchProcessState, _ msg: String?)->()) {
- // 保存数据 连接unit的中心服务器
- O2UserDefaults.shared.unit = unit
- _ = connectToCenterServer(unit: unit).flatMap { (response) -> Observable<Response> in
- let result = response.mapObject(BaseO2ResponseData<O2CenterServerModel>.self)
- if let centerServer = result?.data {
- let httpProtocol = unit.httpProtocol ?? "http"
- centerServer.assembles?.forEach({ (key,value) in
- value.httpProtocol = httpProtocol
- centerServer.assembles![key] = value
- })
- centerServer.webServer?.httpProtocol = httpProtocol
- // 保存中心服务器数据
- O2UserDefaults.shared.centerServer = centerServer
- return self.checkCustomStyleNeedUpdate(unit: unit)
- }else {
- throw O2AuthError.blockError("无法连接中心服务器!")
- }
- }
- .flatMap { (response) -> Observable<Bool> in
- let o2Res = response.mapObject(BaseO2ResponseData<O2StringValueModel>.self)
- let currentHash = O2UserDefaults.shared.customStyleHash ?? ""
- if o2Res?.isSuccess() == false {
- throw O2AuthError.blockError("检查移动端配置是否需要更新时出错, \(o2Res?.message ?? "")")
- }else {
- if let newHash = o2Res?.data?.value {
- if newHash == currentHash { // 没有更新不需要下载
- return self.boolObservableCreate(true)
- }else {
- //保存这个hash码,并下载
- O2UserDefaults.shared.customStyleHash = newHash
- return self.downloadCustomStyle()
- }
- }else {
- throw O2AuthError.blockError("检查移动端配置是否需要更新时出错, 没有获取到hash值")
- }
- }
- }.flatMap { (result) -> Observable<Response> in
- if result {
- if let token = O2UserDefaults.shared.myInfo?.token {
- return self.loginWithToken(token)
- }else {
- guard let mobile = O2UserDefaults.shared.device?.mobile, let code = O2UserDefaults.shared.device?.code else {
- throw O2AuthError.noLoginError
- }
- return self.loginWithPhoneCode(mobile, code)
- }
- }else {
- throw O2AuthError.blockError("下载移动端配置时出错!!!")
- }
- }.flatMap { (response) -> Observable<Bool> in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- return self.boolObservableCreate(true)
- }else {
- throw O2AuthError.noLoginError
- }
- }else {
- throw O2AuthError.noLoginError
- }
- }.subscribe { (event) in
- switch event {
- case .next(let element):
- if element {
- callback(O2LaunchProcessState.success, nil)
- }else {
- callback(O2LaunchProcessState.loginError, "登录失败!")
- }
- break
- case .error(let error):
- if error is O2AuthError {
- let aError = error as! O2AuthError
- switch aError {
- case .noLoginError:
- callback(O2LaunchProcessState.loginError, "登录失败!")
- break
- case .blockError(let msg):
- callback(O2LaunchProcessState.unknownError, msg)
- break
- default :
- callback(O2LaunchProcessState.unknownError, "")
- break
- }
- }else {
- callback(O2LaunchProcessState.unknownError, "未知错误,\(String(describing: error))")
- }
- break
- case .completed:
- break
- }
- }
- }
-
-
- /// 登录 手机号码 验证码
- ///
- /// - Parameters:
- /// - mobile: 手机号码
- /// - code: 验证码
- /// - callback: 登录结果
- public func login(mobile: String, code: String, callback: @escaping (_ result: Bool, _ error: String?) ->() ) {
- _ = self.loginWithPhoneCode(mobile, code)
- .subscribe(onNext: { (response) in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- callback(true, nil)
- }else {
- callback(false, "登录失败,用户名是: 找不到该用户信息 ! ")
- }
- }else {
- callback(false, "登录失败,\(account?.message ?? "")")
- }
- }, onError: { (error) in
- callback(false, "登录失败,\(String(describing: error))")
- }, onCompleted: {
- print("login completed!")
- }) {
- print("login finish!")
- }
- }
-
- /// 登录 扫码登录
- public func loginWithScanCode(meta: String, callback: @escaping (_ result: Bool, _ error: String?) ->()) {
- _ = self.loginAPI.rx.request(.loginWithScanCode(meta)).asObservable().subscribe(onNext: { (response) in
- let back = response.mapObject(BaseO2ResponseData<O2NodeResModel>.self)
- if back?.isSuccess() == true {
- if let v = back?.data, v.value == true {
- callback(true, nil)
- }else {
- callback(false, "登录失败!")
- }
- }else {
- callback(false, "登录失败,\(back?.message ?? "")")
- }
- }, onError: { (error) in
- callback(false, "登录失败,\(String(describing: error))")
- }, onCompleted: {
- print("loginWithScanCode completed!")
- }) {
- print("loginWithScanCode finish!")
- }
- }
-
- public func loginWithPassword(username: String, password: String, callback: @escaping (_ result: Bool, _ error: String?) ->()) {
- _ = self.loginWithUsernamePassword(username, password)
- .subscribe(onNext: { (response) in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- callback(true, nil)
- }else {
- callback(false, "登录失败,用户名是: 找不到该用户信息 ! ")
- }
- }else {
- callback(false, "登录失败,\(account?.message ?? "")")
- }
- }, onError: { (error) in
- callback(false, "登录失败,\(String(describing: error))")
- }, onCompleted: {
- print("login completed!")
- }) {
- print("login finish!")
- }
- }
-
- /// 人脸识别登录
- ///
- /// - Parameters:
- /// - userId: 用户uid
- /// - callback:
- public func faceRecognizeLogin(userId: String, callback: @escaping (_ result: Bool, _ error: String?) ->()) {
- _ = self.desEncrypt(userId).flatMap { (token) -> Observable<Response> in
- return self.loginWithSSO(token)
- }.subscribe(onNext: { (response) in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- callback(true, nil)
- }else {
- callback(false, "登录失败,找不到该用户信息 ! ")
- }
- }else {
- callback(false, "登录失败,\(account?.message ?? "")")
- }
- }, onError: { (error) in
- callback(false, "登录失败,\(String(describing: error))")
- }, onCompleted: nil, onDisposed: nil)
- }
-
- /// 登出 清除当前登录的用户信息
- ///
- /// - Parameter callback:
- public func logout(callback: @escaping (_ result: Bool, _ error: String?) ->()) {
- _ = Observable<Bool>.create { (observer) -> Disposable in
- O2UserDefaults.shared.myInfo = nil
- let device = O2UserDefaults.shared.device
- device?.code = nil
- O2UserDefaults.shared.device = device
- observer.onNext(true)
- observer.onCompleted()
- return Disposables.create()
- }.subscribe(onNext: { (result) in
- callback(result, nil)
- }, onError: { (error) in
- callback(false, "\(String(describing: error))")
- }, onCompleted: nil, onDisposed: nil)
- }
-
- /// 解除绑定前 清空本地数据
- ///
- /// - Parameter callback: 返回结果
- public func clearAllInformationBeforeReBind(callback: @escaping (_ result: Bool, _ error: String?) ->()) {
- _ = Observable<Bool>.create { (observer) -> Disposable in
- //清除本地关于账号 单位等信息
- O2UserDefaults.shared.unit = nil
- O2UserDefaults.shared.device = nil
- O2UserDefaults.shared.myInfo = nil
- O2UserDefaults.shared.customStyle = nil
- O2UserDefaults.shared.customStyleHash = nil
- O2UserDefaults.shared.centerServer = nil
- observer.onNext(true)
- observer.onCompleted()
- return Disposables.create()
- }.subscribe(onNext: { (result) in
- callback(result, nil)
- }, onError: { (error) in
- callback(false, "\(String(describing: error))")
- }, onCompleted: nil, onDisposed: nil)
-
- }
-
- /// 登录的时候 发送短信验证码
- ///
- /// - Parameters:
- /// - mobile: 手机号码
- /// - callback:
- public func sendLoginSMS(mobile: String, callback: @escaping (_ result: Bool, _ error: String?) ->()) {
- _ = loginAPI.rx.request(.createLoginCode(mobile)).asObservable()
- .subscribe(onNext: { (response) in
- let account = response.mapObject(BaseO2ResponseData<O2NodeResModel>.self)
- if let result = account?.data?.value, result == true {
- callback(true, nil)
- }else {
- callback(false, "发送短信失败!")
- }
- }, onError: { (error) in
- callback(false, "发送短信失败!\(error)")
- }, onCompleted: nil, onDisposed: nil)
- }
-
-
- /// 绑定手机的时候 发送短信验证码
- ///
- /// - Parameters:
- /// - mobile: 手机号码
- /// - callback:
- public func sendBindSMS(mobile: String, callback: @escaping (_ result: Bool, _ error: String?) ->()) {
- let req = O2NodeReqModel()
- req.mobile = mobile
- _ = registerAPI.rx.request(.generateVerifiyCode(req)).asObservable()
- .subscribe(onNext: { (response) in
- let account = response.mapObject(BaseO2ResponseData<O2MobileCodeResModel>.self)
- if account?.isSuccess() == true {
- callback(true, nil)
- }else {
- callback(false, "发送短信失败!")
- }
- }, onError: { (error) in
- callback(false, "发送短信失败!\(error)")
- }, onCompleted: nil, onDisposed: nil)
- }
-
- /// 绑定到sample 服务器,苹果上架使用
-
- /// - Parameters:
- /// - mobile: 手机号码
- public func bindSampleServer(mobile: String, callback: @escaping (_ result: O2BindProcessState, _ error: String?) ->()) {
- //填入sample的服务器信息
- let _ = Observable<O2BindUnitModel>.create { (observer) -> Disposable in
- let unit: O2BindUnitModel = O2BindUnitModel()
- unit.id = "61a4d035-81ee-44a6-af3b-ab3d374ee24d"
- unit.name = "演示站点"
- unit.pinyin = "yanshizhandian"
- unit.pinyinInitial = "yszd"
- unit.centerHost = "sample.o2oa.net"
- unit.centerPort = 40030
- unit.centerContext = "/x_program_center"
- unit.httpProtocol = "https"
- O2UserDefaults.shared.unit = unit
- observer.onNext(unit)
- observer.onCompleted()
- return Disposables.create()
- }.flatMap { (unit) -> Observable<Response> in
- let bindDevice: O2BindDeviceModel = O2BindDeviceModel()
- bindDevice.unit = unit.name
- bindDevice.name = O2UserDefaults.shared.deviceToken
- bindDevice.mobile = mobile
- bindDevice.code = ""
- bindDevice.deviceType = "ios"
- O2UserDefaults.shared.device = bindDevice
- return self.connectToCenterServer(unit: unit)
- }.flatMap({ (response) -> Observable<Response> in
- let result = response.mapObject(BaseO2ResponseData<O2CenterServerModel>.self)
- if let centerServer = result?.data {
- let unit = O2UserDefaults.shared.unit
- let httpProtocol = unit?.httpProtocol ?? "http"
- centerServer.assembles?.forEach({ (key,value) in
- value.httpProtocol = httpProtocol
- centerServer.assembles![key] = value
- })
- centerServer.webServer?.httpProtocol = httpProtocol
- // 保存中心服务器数据
- O2UserDefaults.shared.centerServer = centerServer
- return self.checkCustomStyleNeedUpdate(unit: unit!)
- }else {
- O2UserDefaults.shared.unit = nil
- O2UserDefaults.shared.device = nil
- throw O2BindDiscontinue.unknownError("无法连接中心服务器!")
- }
- }).flatMap { (response) -> Observable<Bool> in
- let o2Res = response.mapObject(BaseO2ResponseData<O2StringValueModel>.self)
- let currentHash = O2UserDefaults.shared.customStyleHash ?? ""
- if o2Res?.isSuccess() == false {
- throw O2BindDiscontinue.noLoginError("检查移动端配置是否需要更新时出错, \(o2Res?.message ?? "")")
- }else {
- if let newHash = o2Res?.data?.value {
- if newHash == currentHash { // 没有更新不需要下载
- return self.boolObservableCreate(true)
- }else {
- //保存这个hash码,并下载
- O2UserDefaults.shared.customStyleHash = newHash
- return self.downloadCustomStyle()
- }
- }else {
- throw O2BindDiscontinue.noLoginError("检查移动端配置是否需要更新时出错, 没有获取到hash值")
- }
- }
- }.flatMap { (result) -> Observable<Response> in
- if result {
- //sample的默认密码
- guard let mobile = O2UserDefaults.shared.device?.mobile else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- return self.loginWithUsernamePassword(mobile, "o2")
- // if let token = O2UserDefaults.shared.myInfo?.token {
- // return self.loginWithToken(token)
- // }else {
- // guard let mobile = O2UserDefaults.shared.device?.mobile, let code = O2UserDefaults.shared.device?.code else {
- // throw O2BindDiscontinue.noLoginError("登录失败!")
- // }
- // return self.loginWithPhoneCode(mobile, code)
- // }
- }else {
- throw O2BindDiscontinue.noLoginError("下载移动端配置时出错!!!")
- }
- }.flatMap { (response) -> Observable<Bool> in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- return self.boolObservableCreate(true)
- }else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- }else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- }.subscribe(onNext: { (result) in
- if result {
- callback(O2BindProcessState.success, nil)
- }else {
- callback(O2BindProcessState.goToLogin, "登录失败!")
- }
- }, onError: { (error) in
- if error is O2BindDiscontinue {
- let bError = error as! O2BindDiscontinue
- switch bError {
- case O2BindDiscontinue.tooManyUnit(let list):
- callback(O2BindProcessState.goToChooseBindServer(list), nil)
- break
- case O2BindDiscontinue.noLoginError(let msg):
- callback(O2BindProcessState.goToLogin, msg)
- break
- case O2BindDiscontinue.noUnitCanBindError:
- callback(O2BindProcessState.noUnitCanBindError, nil)
- break
- case O2BindDiscontinue.unknownError(let msg):
- callback(O2BindProcessState.unknownError, msg)
- break
- }
- }else {
- callback(O2BindProcessState.unknownError, "\(error)")
- }
- }, onCompleted: nil, onDisposed: nil)
- }
-
- /// 绑定手机号码到服务器, 并且完成全部的登录过程。
- /// 第一步绑定的时候用的,如果单位列表大于1个就抛异常, 外面接收到这个特殊异常就走第二步选择单位
- ///
- /// - Parameters:
- /// - mobile: 手机号码
- /// - code: 验证码
- /// - callback:
- public func bindMobileToSever(mobile: String, code: String, callback: @escaping (_ result: O2BindProcessState, _ error: String?) ->()) {
- let bindDevice: O2BindDeviceModel = O2BindDeviceModel()
- let req = O2NodeReqModel()
- req.mobile = mobile
- req.value = code
- _ = registerAPI.rx.request(.verifiyCode(req)).asObservable()
- .flatMap { (response) -> Observable<Response> in
- let listResult = response.mapObject(BaseO2ResponseData<[O2BindUnitModel]>.self)
- if let list = listResult?.data, list.count > 0 {
- if list.count > 1 {
- throw O2BindDiscontinue.tooManyUnit(list)
- }else {
- // 保存单位信息
- O2UserDefaults.shared.unit = list[0]
- bindDevice.unit = list[0].name
- bindDevice.name = O2UserDefaults.shared.deviceToken
- bindDevice.mobile = mobile
- bindDevice.code = code
- return self.bindToCollect(device: bindDevice)
- }
- }else {
- throw O2BindDiscontinue.noUnitCanBindError
- }
- }
- .flatMap { (response) -> Observable<Response> in
- let idData = response.mapObject(BaseO2ResponseData<O2IdDataModel>.self)
- if idData?.isSuccess() == true {
- // 保存device
- O2UserDefaults.shared.device = bindDevice
- let unit = O2UserDefaults.shared.unit
- return self.connectToCenterServer(unit: unit!)
- }else {
- O2UserDefaults.shared.unit = nil
- throw O2BindDiscontinue.unknownError("绑定失败!")
- }
- }.flatMap({ (response) -> Observable<Response> in
- let result = response.mapObject(BaseO2ResponseData<O2CenterServerModel>.self)
- if let centerServer = result?.data {
- let unit = O2UserDefaults.shared.unit
- let httpProtocol = unit?.httpProtocol ?? "http"
- centerServer.assembles?.forEach({ (key,value) in
- value.httpProtocol = httpProtocol
- centerServer.assembles![key] = value
- })
- centerServer.webServer?.httpProtocol = httpProtocol
- // 保存中心服务器数据
- O2UserDefaults.shared.centerServer = centerServer
- return self.checkCustomStyleNeedUpdate(unit: unit!)
- }else {
- O2UserDefaults.shared.unit = nil
- O2UserDefaults.shared.device = nil
- throw O2BindDiscontinue.unknownError("无法连接中心服务器!")
- }
- }).flatMap { (response) -> Observable<Bool> in
- let o2Res = response.mapObject(BaseO2ResponseData<O2StringValueModel>.self)
- let currentHash = O2UserDefaults.shared.customStyleHash ?? ""
- if o2Res?.isSuccess() == false {
- throw O2BindDiscontinue.noLoginError("检查移动端配置是否需要更新时出错, \(o2Res?.message ?? "")")
- }else {
- if let newHash = o2Res?.data?.value {
- if newHash == currentHash { // 没有更新不需要下载
- return self.boolObservableCreate(true)
- }else {
- //保存这个hash码,并下载
- O2UserDefaults.shared.customStyleHash = newHash
- return self.downloadCustomStyle()
- }
- }else {
- throw O2BindDiscontinue.noLoginError("检查移动端配置是否需要更新时出错, 没有获取到hash值")
- }
- }
- }.flatMap { (result) -> Observable<Response> in
- if result {
- if let token = O2UserDefaults.shared.myInfo?.token {
- return self.loginWithToken(token)
- }else {
- guard let mobile = O2UserDefaults.shared.device?.mobile, let code = O2UserDefaults.shared.device?.code else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- return self.loginWithPhoneCode(mobile, code)
- }
- }else {
- throw O2BindDiscontinue.noLoginError("下载移动端配置时出错!!!")
- }
- }.flatMap { (response) -> Observable<Bool> in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- return self.boolObservableCreate(true)
- }else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- }else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- }.subscribe(onNext: { (result) in
- if result {
- callback(O2BindProcessState.success, nil)
- }else {
- callback(O2BindProcessState.goToLogin, "登录失败!")
- }
- }, onError: { (error) in
- if error is O2BindDiscontinue {
- let bError = error as! O2BindDiscontinue
- switch bError {
- case O2BindDiscontinue.tooManyUnit(let list):
- callback(O2BindProcessState.goToChooseBindServer(list), nil)
- break
- case O2BindDiscontinue.noLoginError(let msg):
- callback(O2BindProcessState.goToLogin, msg)
- break
- case O2BindDiscontinue.noUnitCanBindError:
- callback(O2BindProcessState.noUnitCanBindError, nil)
- break
- case O2BindDiscontinue.unknownError(let msg):
- callback(O2BindProcessState.unknownError, msg)
- break
- }
- }else {
- callback(O2BindProcessState.unknownError, "\(error)")
- }
- }, onCompleted: nil, onDisposed: nil)
- }
-
- /// 绑定手机到服务器,并完成全部的登录过程
- ///
- /// - Parameters:
- /// - unit: 绑定的单位服务器对象
- /// - mobile: 手机号码
- /// - code: 验证码
- /// - callback:
- public func bindMobileToServer(unit: O2BindUnitModel, mobile: String, code: String, callback: @escaping (_ result: O2BindProcessState, _ error: String?) ->()) {
- // 保存单位信息
- O2UserDefaults.shared.unit = unit
- let bindDevice: O2BindDeviceModel = O2BindDeviceModel()
- bindDevice.unit = unit.name
- bindDevice.name = O2UserDefaults.shared.deviceToken
- bindDevice.mobile = mobile
- bindDevice.code = code
- bindDevice.deviceType = "ios"
- _ = self.bindToCollect(device: bindDevice)
- .flatMap { (response) -> Observable<Response> in
- let idData = response.mapObject(BaseO2ResponseData<O2IdDataModel>.self)
- if idData?.isSuccess() == true {
- // 保存device
- O2UserDefaults.shared.device = bindDevice
- let unit = O2UserDefaults.shared.unit
- return self.connectToCenterServer(unit: unit!)
- }else {
- O2UserDefaults.shared.unit = nil
- throw O2BindDiscontinue.unknownError("绑定失败!")
- }
- }.flatMap({ (response) -> Observable<Response> in
- let result = response.mapObject(BaseO2ResponseData<O2CenterServerModel>.self)
- if let centerServer = result?.data {
- let unit = O2UserDefaults.shared.unit
- let httpProtocol = unit?.httpProtocol ?? "http"
- centerServer.assembles?.forEach({ (key,value) in
- value.httpProtocol = httpProtocol
- centerServer.assembles![key] = value
- })
- centerServer.webServer?.httpProtocol = httpProtocol
- // 保存中心服务器数据
- O2UserDefaults.shared.centerServer = centerServer
- return self.checkCustomStyleNeedUpdate(unit: unit!)
- }else {
- O2UserDefaults.shared.unit = nil
- O2UserDefaults.shared.device = nil
- throw O2BindDiscontinue.unknownError("无法连接中心服务器!")
- }
- }).flatMap { (response) -> Observable<Bool> in
- let o2Res = response.mapObject(BaseO2ResponseData<O2StringValueModel>.self)
- let currentHash = O2UserDefaults.shared.customStyleHash ?? ""
- if o2Res?.isSuccess() == false {
- throw O2BindDiscontinue.noLoginError("检查移动端配置是否需要更新时出错, \(o2Res?.message ?? "")")
- }else {
- if let newHash = o2Res?.data?.value {
- if newHash == currentHash { // 没有更新不需要下载
- return self.boolObservableCreate(true)
- }else {
- //保存这个hash码,并下载
- O2UserDefaults.shared.customStyleHash = newHash
- return self.downloadCustomStyle()
- }
- }else {
- throw O2BindDiscontinue.noLoginError("检查移动端配置是否需要更新时出错, 没有获取到hash值")
- }
- }
- }.flatMap { (result) -> Observable<Response> in
- if result {
- if let token = O2UserDefaults.shared.myInfo?.token {
- return self.loginWithToken(token)
- }else {
- guard let mobile = O2UserDefaults.shared.device?.mobile, let code = O2UserDefaults.shared.device?.code else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- return self.loginWithPhoneCode(mobile, code)
- }
- }else {
- throw O2BindDiscontinue.noLoginError("下载移动端配置时出错!!!")
- }
- }.flatMap { (response) -> Observable<Bool> in
- let account = response.mapObject(BaseO2ResponseData<O2LoginAccountModel>.self)
- if account?.isSuccess() == true {
- if let myInfo = account?.data, myInfo.name != "anonymous" {
- O2UserDefaults.shared.myInfo = myInfo
- return self.boolObservableCreate(true)
- }else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- }else {
- throw O2BindDiscontinue.noLoginError("登录失败!")
- }
- }.subscribe(onNext: { (result) in
- if result {
- callback(O2BindProcessState.success, nil)
- }else {
- callback(O2BindProcessState.goToLogin, "登录失败!")
- }
- }, onError: { (error) in
- if error is O2BindDiscontinue {
- let bError = error as! O2BindDiscontinue
- switch bError {
- case O2BindDiscontinue.tooManyUnit(let list):
- callback(O2BindProcessState.goToChooseBindServer(list), nil)
- break
- case O2BindDiscontinue.noLoginError(let msg):
- callback(O2BindProcessState.goToLogin, msg)
- break
- case O2BindDiscontinue.noUnitCanBindError:
- callback(O2BindProcessState.noUnitCanBindError, nil)
- break
- case O2BindDiscontinue.unknownError(let msg):
- callback(O2BindProcessState.unknownError, msg)
- break
- }
- }else {
- callback(O2BindProcessState.unknownError, "\(error)")
- }
- }, onCompleted: nil, onDisposed: nil)
- }
-
- /// 绑定的设备列表
- ///
- /// - Parameters:
- /// - unitId: 绑定的单位id
- /// - mobile: 手机号码
- /// - token: 设备号 O2BindDeviceModel.name
- /// - callback:
- public func bindDeviceList(unitId: String, mobile: String, token: String, callback: @escaping (_ list: [O2BindDeviceModel], _ error: String?)->Void) {
- _ = registerAPI.rx.request(.deviceList(unitId, mobile, token)).asObservable()
- .subscribe(onNext: { (response) in
- let result = response.mapObject(BaseO2ResponseData<[O2BindDeviceModel]>.self)
- if result?.isSuccess() == true {
- callback(result?.data ?? [], nil)
- }else {
- let message = "查询设备失败,\(result?.message ?? "")"
- callback([], message)
- }
- }, onError: { (error) in
- let message = "查询设备异常,\(error.localizedDescription)"
- callback([], message)
- }, onCompleted: nil, onDisposed: nil)
- }
-
- /// 解除设备绑定
- ///
- /// - Parameters:
- /// - device: 设备对象 主要是name 就是设备号
- /// - callback:
- public func unBindFromCollect(deviceId: String, callback: @escaping (_ result:Bool, _ error:String?)->Void) {
- let device: O2BindDeviceModel = O2BindDeviceModel()
- device.name = deviceId
- _ = registerAPI.rx.request(.unBindFromDevice(device)).asObservable()
- .subscribe(onNext: { (response) in
- let result = response.mapObject(BaseO2ResponseData<O2IdDataModel>.self)
- if result?.isSuccess() == true {
- callback(true, nil)
- }else {
- let message = "解除绑定失败,\(result?.message ?? "")"
- callback(false, message)
- }
- }, onError: { (error) in
- let message = "解除绑定异常,\(error.localizedDescription)"
- callback(false, message)
- }, onCompleted: nil, onDisposed: nil)
- }
-
-
- //MARK: - private
-
- private func boolObservableCreate(_ result: Bool) -> Observable<Bool> {
- return Observable<Bool>.create({ (observer) -> Disposable in
- observer.on(.next(result))
- observer.on(.completed)
- return Disposables.create()
- })
- }
-
- /// 检查是否绑定过
- ///
- /// - Returns:
- private func checkBindUnit() -> Observable<O2BindUnitModel> {
- // return Observable<O2BindDeviceModel>.create({ (any) -> Disposable in
- // if let device = O2UserDefaults.shared.device {
- // any.onNext(device)
- // any.onCompleted()
- // }else {
- // any.onError(O2AuthError.noBindError)
- // }
- // return Disposables.create()
- // })
-
- return Observable<O2BindUnitModel>.create ({ (any) -> Disposable in
- if let unit = O2UserDefaults.shared.unit {
- any.onNext(unit)
- any.onCompleted()
- } else {
- any.onError(O2AuthError.noBindError)
- }
- return Disposables.create()
- })
- }
- /// 检查当前绑定信息是否过期
- ///
- /// - Parameter device: 手机号码等设备信息
- /// - Returns:
- private func checkBindUnitIsExpired(device: O2BindDeviceModel) -> Observable<Response> {
- return registerAPI.rx.request(.queryBindInfo(device)).asObservable()
- }
-
-
- /// 连接到O2OA中心服务器
- ///
- /// - Parameter unit: 单位服务器信息
- /// - Returns:
- private func connectToCenterServer(unit: O2BindUnitModel) -> Observable<Response> {
- return registerAPI.rx.request(.downloadNodeAPI(unit)).asObservable()
- }
-
- /// 检查移动端配置信息是否有更新
- ///
- /// - Parameter unit: 当前绑定的党委
- /// - Returns:
- private func checkCustomStyleNeedUpdate(unit: O2BindUnitModel) -> Observable<Response> {
- return registerAPI.rx.request(.verConfigInfo(unit)).asObservable()
- }
-
- /// 下载移动端配置信息
- ///
- /// - Returns:
- private func downloadCustomStyle() -> Observable<Bool> {
- if let unit = O2UserDefaults.shared.unit {
- return registerAPI.rx.request(.downloadConfigInfo(unit))
- .asObservable()
- .flatMap { (response) -> Observable<Bool> in
-
- let result = response.mapObject(BaseO2ResponseData<O2CustomStyleModel>.self)
- if result?.isSuccess() == true {
- //保存移动端配置信息
- O2UserDefaults.shared.customStyle = result?.data
- return self.boolObservableCreate(true)
- }else {
- throw O2AuthError.blockError("下载移动端配置时出错, \(result?.message ?? "")")
- }
- }
- }else {
- return self.boolObservableCreate(false)
- }
- }
-
- /// token登录
- ///
- /// - Parameter token: 用户登录的token
- /// - Returns:
- private func loginWithToken(_ token: String) -> Observable<Response> {
- return loginAPI.rx.request(.loginWithToken(token)).asObservable()
- }
-
- /// 手机验证码登录
- ///
- /// - Parameters:
- /// - mobile: 手机号码
- /// - code: 验证码
- /// - Returns:
- private func loginWithPhoneCode(_ mobile: String, _ code: String) -> Observable<Response> {
- return loginAPI.rx.request(.loginWithCredntial(mobile, code)).asObservable()
- }
-
-
- /// 用户名密码登录
- ///
- /// - Parameters:
- /// - username: 用户名
- /// - password: 密码
- /// - Returns:
- private func loginWithUsernamePassword(_ username: String, _ password: String) -> Observable<Response> {
- return loginAPI.rx.request(.loginWithPassword(username, password)).asObservable()
- }
-
- /// sso 登录
- ///
- /// - Parameter token: 加密后的token
- /// - Returns:
- private func loginWithSSO(_ token: String) -> Observable<Response> {
- return loginAPI.rx.request(.loginWithSSO(O2ConfigInfo.O2_OA_SSO_CLIENT, token)).asObservable()
- }
-
- /// 绑定到wcollect服务器
- ///
- /// - Parameters:
- /// - device: 设备对象
- /// - Returns:
- private func bindToCollect(device: O2BindDeviceModel) -> Observable<Response> {
- return registerAPI.rx.request(.bindMobileToDevice(device)).asObservable()
- }
-
-
-
- /// des 加密
- ///
- /// - Parameter uid:
- /// - Returns:
- private func desEncrypt(_ uid: String) -> Observable<String> {
- return Observable<String>.create({ (observer) -> Disposable in
- do {
- let en = SymmetricCryptor(algorithm: .des, options: (kCCOptionECBMode + kCCOptionPKCS7Padding))
- en.setRandomIV()
- let timeInterval = Date().timeIntervalSince1970
- let time = CLongLong(round(timeInterval*1000))
- let code = "\(uid)#\(time)"
- print("code: \(code)")
- let encrypt = try en.crypt(string: code, key: O2ConfigInfo.O2_OA_DES_KEY)
- let base64 = encrypt.base64EncodedString()
- print("加密后的字符串:\(base64)")
- let decrypt = try en.decrypt(encrypt, key: O2ConfigInfo.O2_OA_DES_KEY)
- let deString = String(data: decrypt, encoding: String.Encoding.utf8)
- print("解密后的字符串:\(deString ?? "")")
- let first = base64.replacingOccurrences(of: "+", with: "-")
- let second = first.replacingOccurrences(of: "/", with: "_")
- let token = second.replacingOccurrences(of: "=", with: "")
- print("安全替换后的字符串:\(token)")
- observer.onNext(token)
- }catch {
- print("加密异常,\(error)")
- observer.onError(error)
- }
- observer.onCompleted()
- return Disposables.create()
- })
- }
-
- }
|