Преглед изворни кода

1.修改iOS Apex CRM Token上传。

Pen Li пре 7 година
родитељ
комит
db3642e061

+ 51 - 0
RedAnt CRM/APEX CRM/APEX CRM.xcodeproj/project.pbxproj

@@ -30,6 +30,12 @@
 		421F3EB621F9B951001A4BB9 /* RAEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 421F3EB021F9B951001A4BB9 /* RAEmptyView.m */; };
 		421F3EB721F9B951001A4BB9 /* UIScrollView+Empty.m in Sources */ = {isa = PBXBuildFile; fileRef = 421F3EB321F9B951001A4BB9 /* UIScrollView+Empty.m */; };
 		421F3EB821F9B951001A4BB9 /* RAEmptyDataView.m in Sources */ = {isa = PBXBuildFile; fileRef = 421F3EB421F9B951001A4BB9 /* RAEmptyDataView.m */; };
+		42201EE5220046F9008AEADE /* CRMUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 42201EE4220046F9008AEADE /* CRMUser.m */; };
+		42201EF022004FA7008AEADE /* NSString+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 42201EE722004FA7008AEADE /* NSString+Base64.m */; };
+		42201EF122004FA7008AEADE /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 42201EE822004FA7008AEADE /* LICENSE */; };
+		42201EF222004FA7008AEADE /* AESCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = 42201EE922004FA7008AEADE /* AESCrypt.m */; };
+		42201EF322004FA7008AEADE /* NSData+CommonCrypto.m in Sources */ = {isa = PBXBuildFile; fileRef = 42201EEE22004FA7008AEADE /* NSData+CommonCrypto.m */; };
+		42201EF422004FA7008AEADE /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 42201EEF22004FA7008AEADE /* NSData+Base64.m */; };
 		4232521721C491B600C77851 /* RAContactHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4232521621C491B600C77851 /* RAContactHelper.m */; };
 		4277784F21AFB98600BCF7FA /* RAMapNavigateHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 4277784E21AFB98600BCF7FA /* RAMapNavigateHandler.m */; };
 		42A8A21321AE7828003B854B /* RAPhotoPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 42A8A20B21AE7828003B854B /* RAPhotoPreviewController.m */; };
@@ -111,6 +117,17 @@
 		421F3EB321F9B951001A4BB9 /* UIScrollView+Empty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+Empty.m"; sourceTree = "<group>"; };
 		421F3EB421F9B951001A4BB9 /* RAEmptyDataView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAEmptyDataView.m; sourceTree = "<group>"; };
 		421F3EB521F9B951001A4BB9 /* UIScrollView+Empty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+Empty.h"; sourceTree = "<group>"; };
+		42201EE3220046F9008AEADE /* CRMUser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRMUser.h; sourceTree = "<group>"; };
+		42201EE4220046F9008AEADE /* CRMUser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRMUser.m; sourceTree = "<group>"; };
+		42201EE722004FA7008AEADE /* NSString+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Base64.m"; sourceTree = "<group>"; };
+		42201EE822004FA7008AEADE /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+		42201EE922004FA7008AEADE /* AESCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AESCrypt.m; sourceTree = "<group>"; };
+		42201EEA22004FA7008AEADE /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Base64.h"; sourceTree = "<group>"; };
+		42201EEB22004FA7008AEADE /* NSData+CommonCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+CommonCrypto.h"; sourceTree = "<group>"; };
+		42201EEC22004FA7008AEADE /* AESCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESCrypt.h; sourceTree = "<group>"; };
+		42201EED22004FA7008AEADE /* NSString+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Base64.h"; sourceTree = "<group>"; };
+		42201EEE22004FA7008AEADE /* NSData+CommonCrypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+CommonCrypto.m"; sourceTree = "<group>"; };
+		42201EEF22004FA7008AEADE /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Base64.m"; sourceTree = "<group>"; };
 		4232521521C491B600C77851 /* RAContactHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RAContactHelper.h; sourceTree = "<group>"; };
 		4232521621C491B600C77851 /* RAContactHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RAContactHelper.m; sourceTree = "<group>"; };
 		4277784D21AFB98600BCF7FA /* RAMapNavigateHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RAMapNavigateHandler.h; sourceTree = "<group>"; };
@@ -321,6 +338,32 @@
 			path = "../../../common/UIScrollVIew+Empty";
 			sourceTree = "<group>";
 		};
+		42201EE2220046E1008AEADE /* User */ = {
+			isa = PBXGroup;
+			children = (
+				42201EE3220046F9008AEADE /* CRMUser.h */,
+				42201EE4220046F9008AEADE /* CRMUser.m */,
+			);
+			path = User;
+			sourceTree = "<group>";
+		};
+		42201EE622004FA7008AEADE /* AES */ = {
+			isa = PBXGroup;
+			children = (
+				42201EEC22004FA7008AEADE /* AESCrypt.h */,
+				42201EE922004FA7008AEADE /* AESCrypt.m */,
+				42201EE822004FA7008AEADE /* LICENSE */,
+				42201EEA22004FA7008AEADE /* NSData+Base64.h */,
+				42201EEF22004FA7008AEADE /* NSData+Base64.m */,
+				42201EEB22004FA7008AEADE /* NSData+CommonCrypto.h */,
+				42201EEE22004FA7008AEADE /* NSData+CommonCrypto.m */,
+				42201EED22004FA7008AEADE /* NSString+Base64.h */,
+				42201EE722004FA7008AEADE /* NSString+Base64.m */,
+			);
+			name = AES;
+			path = ../../../common/AES;
+			sourceTree = "<group>";
+		};
 		4232521421C491A000C77851 /* Contact */ = {
 			isa = PBXGroup;
 			children = (
@@ -485,6 +528,8 @@
 		7106E80721A684F20056DD20 /* APEX CRM */ = {
 			isa = PBXGroup;
 			children = (
+				42201EE622004FA7008AEADE /* AES */,
+				42201EE2220046E1008AEADE /* User */,
 				421F3EAE21F9B951001A4BB9 /* EmptyView */,
 				421F3EB121F9B951001A4BB9 /* UIScrollVIew+Empty */,
 				4232521421C491A000C77851 /* Contact */,
@@ -620,6 +665,7 @@
 				42F53F8621B617E4008EAEFC /* signature.storyboard in Resources */,
 				4212AB8E21AD22AB00BE4E45 /* QRCode.storyboard in Resources */,
 				7106E81021A684F20056DD20 /* Main.storyboard in Resources */,
+				42201EF122004FA7008AEADE /* LICENSE in Resources */,
 				4212ABA321AD2B7300BE4E45 /* Localizable.strings in Resources */,
 				4212AB9121AD22AB00BE4E45 /* camera.xcassets in Resources */,
 				42A8A21421AE7828003B854B /* PhotoList.storyboard in Resources */,
@@ -637,9 +683,11 @@
 			files = (
 				4277784F21AFB98600BCF7FA /* RAMapNavigateHandler.m in Sources */,
 				4212ABCC21AD450A00BE4E45 /* LPShareActivity.m in Sources */,
+				42201EF322004FA7008AEADE /* NSData+CommonCrypto.m in Sources */,
 				421F3EB821F9B951001A4BB9 /* RAEmptyDataView.m in Sources */,
 				4212AB9821AD25C800BE4E45 /* RAPreviewController.m in Sources */,
 				42F53F8821B617E4008EAEFC /* SignatureView.m in Sources */,
+				42201EE5220046F9008AEADE /* CRMUser.m in Sources */,
 				4212ABC521AD3C3200BE4E45 /* RADataProvider.m in Sources */,
 				42A8A21F21AE842E003B854B /* RAPhotoModel.m in Sources */,
 				7106E83D21AD1B070056DD20 /* zip.c in Sources */,
@@ -670,11 +718,14 @@
 				7106E82F21AD1ACD0056DD20 /* RAUtils.m in Sources */,
 				42A8A21321AE7828003B854B /* RAPhotoPreviewController.m in Sources */,
 				7106E80A21A684F20056DD20 /* AppDelegate.m in Sources */,
+				42201EF222004FA7008AEADE /* AESCrypt.m in Sources */,
 				4212AB9321AD22AB00BE4E45 /* RATakePhotoPreviewController.m in Sources */,
 				7106E84021AD1B0D0056DD20 /* ZipArchive.mm in Sources */,
 				7106E82621A698D20056DD20 /* RAWKWebView.m in Sources */,
+				42201EF422004FA7008AEADE /* NSData+Base64.m in Sources */,
 				4212AB9421AD22AB00BE4E45 /* RAExceptionHandler.m in Sources */,
 				4214C4A521B25EC20091A528 /* NSString+RAJavascript.m in Sources */,
+				42201EF022004FA7008AEADE /* NSString+Base64.m in Sources */,
 				42F53F8921B617E4008EAEFC /* SignatureViewController.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 2 - 0
RedAnt CRM/APEX CRM/APEX CRM/DataProvider/RADataProvider.h

@@ -13,5 +13,7 @@
 
 + (void)GET_DownloadFile:(NSString *)url toFolder:(NSString *)dir progressHandler:(progressHandler)progressHandler completionHandler:(resultHandler)resultHandler;
 
++ (void)uploadDeviceToken;
+
 @end
 

+ 111 - 0
RedAnt CRM/APEX CRM/APEX CRM/DataProvider/RADataProvider.m

@@ -8,6 +8,9 @@
 
 #import "RADataProvider.h"
 #import "RAUtils.h"
+#import "CRMUser.h"
+
+static NSString * const URL_UPLOAD_TOKEN = @"";
 
 @implementation RADataProvider
 
@@ -77,4 +80,112 @@
     }
 }
 
++(NSMutableDictionary*) prepare_addtional_params:(NSMutableDictionary* ) params
+{
+    
+    if (params == nil) {
+        params = [NSMutableDictionary dictionary];
+    }
+    
+    NSString *user = params[@"name"];
+    if (!user) {
+        user = [CRMUser sharedUser].user;
+        if (user) {
+            params[@"name"] = [CRMUser.sharedUser encryptyString:user];
+        }
+    }
+    
+    NSString *password = params[@"password"];
+    if (!password) {
+        password = [CRMUser sharedUser].password;
+        if (password) {
+            params[@"password"] = [CRMUser.sharedUser decryptString:password];
+        }
+    }
+    
+    [params setObject:@"iOS" forKey:@"platform"];
+    
+    NSDictionary* infoDict =[[NSBundle mainBundle] infoDictionary];
+    NSString* short_version =[infoDict objectForKey:@"CFBundleShortVersionString"];
+    [params setValue:short_version forKey:@"app_short_ver"];
+    
+    NSString *localeLanguageCode = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode];
+    [params setValue:localeLanguageCode forKey:@"language"];
+    
+#if TARGET_IPHONE_SIMULATOR//模拟器
+    [params setValue:@"simulator_uuid" forKey:@"deviceid"];
+#elif TARGET_OS_IPHONE//真机
+    UIDevice * dev = [UIDevice currentDevice];
+    NSUUID* uuid =dev.identifierForVendor;
+    [params setValue:uuid.UUIDString forKey:@"deviceid"];
+#endif
+    
+    return params;
+}
+
++(NSData*)get_json : (NSString*) url parameters:(NSMutableDictionary *) params file:(NSString *) file //delegate:(id < NSURLConnectionDelegate >)delegate
+{
+    
+    
+    
+    params = [self prepare_addtional_params:params];
+    
+    return [NetworkUtils get_json:url parameters:params file:file err_recorder:@"" result_handler:^NSMutableDictionary *(NSMutableDictionary *jsobj) {
+        int result=[[jsobj valueForKey:@"result"] intValue];
+        
+        switch (result) {
+            case -9:
+            case 0:
+                [jsobj setValue:MSG_USERAUTH_ERROR forKey:@"err_msg"];
+                break;
+            case 1:
+                [jsobj setValue:MSG_ERROR forKey:@"err_msg"];
+                break;
+            case RESULT_TRUE:
+                [jsobj setValue:MSG_SUCCESS forKey:@"err_msg"];
+                break;
+            case 9:
+                [jsobj setValue:[jsobj valueForKey:@"msg"] forKey:@"err_msg"];
+                break;
+            case RESULT_TIMEOUT:
+                [jsobj setValue:MSG_TIMEOUT forKey:@"err_msg"];
+                break;
+            default: {
+                NSString *msg = [jsobj valueForKey:@"msg"];
+                if (msg.length == 0) {
+                    [jsobj setValue:MSG_ERROR forKey:@"err_msg"];
+                } else {
+                    [jsobj setValue:msg forKey:@"err_msg"];
+                }
+            }
+                break;
+        }
+        
+        return jsobj;
+    } decrypt_handler:^NSMutableDictionary *(NSMutableDictionary *jsobj) {
+        
+        return nil;
+    }];
+    
+    
+    /*
+     
+     
+     
+     */
+    return nil;
+}
+
++ (void)uploadDeviceToken {
+    
+    dispatch_async(dispatch_get_global_queue(0, 0), ^{
+       
+        NSMutableDictionary *params = [@{
+                                         @"token": CRMUser.sharedUser.deviceToken
+                                         } mutableCopy];
+    
+        [self get_json:URL_UPLOAD_TOKEN parameters:params file:nil];
+    });
+}
+
 @end

+ 12 - 2
RedAnt CRM/APEX CRM/APEX CRM/RAWKWebView.h

@@ -8,16 +8,26 @@
 
 #import <UIKit/UIKit.h>
 #import <WebKit/WebKit.h>
-NS_ASSUME_NONNULL_BEGIN
+
+@class RAWKWebView;
+@protocol RAWebViewDelegate <NSObject>
+
+- (void)webview:(RAWKWebView *)webview didLogin:(NSString *)user password:(NSString *)password;
+- (void)webviewDidLogout:(RAWKWebView *)webview;
+
+@end
 
 @interface RAWKWebView : UIView <WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>
 
+@property (nonatomic,weak) id<RAWebViewDelegate> delegate;
+
 - (void)LoadFromURL:(NSString*)url;
 
 @property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior API_AVAILABLE(ios(11.0),tvos(11.0));
 
 @property (nonatomic , copy) void (^JumpTo)(NSString* url,NSString* module);
 
+- (void)evaluateJs:(NSString *)js completionHandler:(void (^) (id result, NSError *error))handler ;
+
 @end
 
-NS_ASSUME_NONNULL_END

+ 42 - 0
RedAnt CRM/APEX CRM/APEX CRM/RAWKWebView.m

@@ -124,6 +124,10 @@
     [self.wkwebView.configuration.userContentController addScriptMessageHandler:self name:@"SelectContact"];
     [self.wkwebView.configuration.userContentController addScriptMessageHandler:self name:@"requestApplicationVersion"];
     [self.wkwebView.configuration.userContentController addScriptMessageHandler:self name:@"cleanCache"];
+    
+    [self.wkwebView.configuration.userContentController addScriptMessageHandler:self name:@"login"];
+    [self.wkwebView.configuration.userContentController addScriptMessageHandler:self name:@"logout"];
+    
     //    [self.configuration.userContentController addScriptMessageHandler:self name:@"Color"];
     //    [self.configuration.userContentController addScriptMessageHandler:self name:@"Pay"];
     //    [self.configuration.userContentController addScriptMessageHandler:self name:@"Shake"];
@@ -147,6 +151,9 @@
     [self.wkwebView.configuration.userContentController removeScriptMessageHandlerForName:@"SelectContact"];
     [self.wkwebView.configuration.userContentController removeScriptMessageHandlerForName:@"requestApplicationVersion"];
     [self.wkwebView.configuration.userContentController removeScriptMessageHandlerForName:@"cleanCache"];
+    
+    [self.wkwebView.configuration.userContentController removeScriptMessageHandlerForName:@"login"];
+    [self.wkwebView.configuration.userContentController removeScriptMessageHandlerForName:@"logout"];
 }
 - (void)dealloc
 {
@@ -627,6 +634,20 @@
     }];
 }
 
+- (void)ra_handleLogin:(NSString *)user password:(NSString *)password {
+    
+    if (self.delegate && [self.delegate respondsToSelector:@selector(webview:didLogin:password:)]) {
+        [self.delegate webview:self didLogin:user password:password];
+    }
+}
+
+- (void)ra_handleLogout {
+    
+    if (self.delegate && [self.delegate respondsToSelector:@selector(webviewDidLogout:)]) {
+        [self.delegate webviewDidLogout:self];
+    }
+}
+
 #pragma mark - Utils
 
 - (NSString *)adjustNilString:(NSString *)str {
@@ -680,6 +701,10 @@
     }
 }
 
+- (void)evaluateJs:(NSString *)js completionHandler:(void (^) (id result, NSError *error))handler {
+    [self.wkwebView evaluateJavaScript:js completionHandler:handler];
+}
+
 #pragma mark - MFMailComposeViewControllerDelegate delegate
 
 - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
@@ -828,6 +853,12 @@
     } else if ([message.name isEqualToString:@"cleanCache"]) {
         
         [self handleCleanCache:params];
+    } else if ([message.name isEqualToString:@"login"]) {
+        
+        [self handleLogin:params];
+    } else if ([message.name isEqualToString:@"logout"]) {
+        
+        [self handleLogout];
     }
     else
     {
@@ -953,6 +984,17 @@
     [self ra_cleanCache:params];
 }
 
+- (void)handleLogin:(NSDictionary *)params {
+    
+    NSString *user = params[@"user"];
+    NSString *password = params[@"password"];
+    [self ra_handleLogin:user password:password];
+}
+
+- (void)handleLogout {
+    [self ra_handleLogout];
+}
+
 #pragma mark - WKNavigationDelegate
 
 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {

+ 29 - 0
RedAnt CRM/APEX CRM/APEX CRM/User/CRMUser.h

@@ -0,0 +1,29 @@
+//
+//  CRMUser.h
+//  APEX CRM
+//
+//  Created by Jack on 2019/1/29.
+//  Copyright © 2019 USAI. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface CRMUser : NSObject
+
+@property (nonatomic,readonly,copy) NSString *user;
+@property (nonatomic,readonly,copy) NSString *password;
+@property (nonatomic,copy) NSString *deviceToken;
+@property (nonatomic,readonly,assign) BOOL isLogin;
+@property (nonatomic,readonly,assign) BOOL shouldUploadToken;
+
+
++ (instancetype)sharedUser;
+
+- (void)loginUser:(NSString *)user password:(NSString *)password;
+- (void)logout;
+
+- (NSString *)encryptyString:(NSString *)str;
+- (NSString *)decryptString:(NSString *)str;
+
+@end
+

+ 75 - 0
RedAnt CRM/APEX CRM/APEX CRM/User/CRMUser.m

@@ -0,0 +1,75 @@
+//
+//  CRMUser.m
+//  APEX CRM
+//
+//  Created by Jack on 2019/1/29.
+//  Copyright © 2019 USAI. All rights reserved.
+//
+
+#import "CRMUser.h"
+#import "AESCrypt.h"
+
+static NSString *const SecretKey = @"usai";
+
+@interface CRMUser()
+
+@property (nonatomic,copy) NSString *user;
+@property (nonatomic,copy) NSString *password;
+
+@end
+
+@implementation CRMUser
+
++ (instancetype)sharedUser {
+    static CRMUser *user;
+    static dispatch_once_t token;
+    dispatch_once(&token, ^{
+        user = [CRMUser new];
+    });
+    return user;
+}
+
+- (void)loginUser:(NSString *)user password:(NSString *)password {
+    self.user = user;
+    self.password = password;
+}
+
+- (void)logout {
+    self.user = nil;
+    self.password = nil;
+}
+
+- (void)setUser:(NSString *)user {
+    _user = [user copy];
+}
+
+- (void)setPassword:(NSString *)password {
+    _password = [_password copy];
+}
+
+- (BOOL)isLogin {
+    return _user.length > 0 && _password.length > 0;
+}
+
+- (BOOL)shouldUploadToken {
+    if (self.isLogin && self.deviceToken) {
+        return YES;
+    }
+    return NO;
+}
+
+- (NSString *)encryptyString:(NSString *)str {
+    if (str) {
+        str = [AESCrypt encrypt:str password:SecretKey];
+    }
+    return str;
+}
+
+- (NSString *)decryptString:(NSString *)str {
+    if (str) {
+        str = [AESCrypt decrypt:str password:SecretKey];
+    }
+    return str;
+}
+
+@end

+ 4 - 4
RedAnt CRM/APEX CRM/APEX CRM/WKWebTestViewController.h

@@ -8,10 +8,10 @@
 
 #import <UIKit/UIKit.h>
 
-NS_ASSUME_NONNULL_BEGIN
-
 @interface WKWebTestViewController : UIViewController
+
 @property (strong, nonatomic) NSString *url;
-@end
 
-NS_ASSUME_NONNULL_END
+- (void)readNotificationNow:(NSInteger)notificationId;
+
+@end

+ 52 - 1
RedAnt CRM/APEX CRM/APEX CRM/WKWebTestViewController.m

@@ -8,8 +8,11 @@
 
 #import "WKWebTestViewController.h"
 #import "RAWKWebView.h"
+#import "CRMUser.h"
+#import "RADataProvider.h"
+#import "NSString+RAJavascript.h"
 
-@interface WKWebTestViewController ()
+@interface WKWebTestViewController () <RAWebViewDelegate>
 @property (weak, nonatomic) IBOutlet RAWKWebView *webview;
 
 @end
@@ -33,6 +36,7 @@
         _url = @"https://ra.apexshipping.com/apexcrm/crm/mobile/login";
     }
     
+    self.webview.delegate = self;
     [self.webview LoadFromURL:_url];
     self.webview.JumpTo = ^(NSString* url, NSString* module){
         
@@ -88,4 +92,51 @@
 }
 */
 
+#pragma mark - WebViewDelegate
+
+- (void)webview:(RAWKWebView *)webview didLogin:(NSString *)user password:(NSString *)password {
+    [[CRMUser sharedUser] loginUser:user password:password];
+    if (CRMUser.sharedUser.shouldUploadToken) {
+        [RADataProvider uploadDeviceToken];
+    }
+}
+
+- (void)webviewDidLogout:(RAWKWebView *)webview {
+    [[CRMUser sharedUser] logout];
+}
+
+#pragma mark - Notification
+
+- (void)handleNotificationByJs:(NSInteger)notificationId {
+    
+    NSString *user = CRMUser.sharedUser.user;
+    NSString *password = CRMUser.sharedUser.password;
+    
+    user = [user ra_stringByEscapingForJavascriptWithDelimiter:'\'' wrapWithDelimiters:YES];
+    password = [password ra_stringByEscapingForJavascriptWithDelimiter:'\'' wrapWithDelimiters:YES];
+    
+    NSString *jsFunction = [NSString stringWithFormat:@"showPageForNotification(%@, %@, %ld)", user, password, (long)notificationId];
+    [self.webview evaluateJs:jsFunction completionHandler:^(id result, NSError *error) {
+       
+        NSLog(@"handleNotificationByJs: Result: %@ Error: %@", result, error.localizedDescription);
+    }];
+}
+
+- (void)readNotificationNow:(NSInteger)notificationId {
+    if (!CRMUser.sharedUser.isLogin) {
+        
+        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Warning" message:@"you should login first" preferredStyle:UIAlertControllerStyleAlert];
+        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+            
+        }];
+        
+        [alertVC addAction:okAction];
+        
+        [self presentViewController:alertVC animated:YES completion:nil];
+        return;
+    }
+    
+    [self handleNotificationByJs:notificationId];
+}
+
 @end