// // ScanVC.m // jiaPei // // Created by apple on 16/4/19. // Copyright © 2016年 JCZ. All rights reserved. // #import "ScanVC.h" #import #import "DES3Util.h" #import "Tools.h" #define KWidth (kSize.width/2.0 + 30) @interface ScanVC () { BOOL isDown; NSTimer *timer; NSInteger num; UIImageView *scanBackground; UIImageView *line; AVCaptureDevice *device; AVCaptureSession *session; AVCaptureDeviceInput *input; AVCaptureMetadataOutput *output; AVCaptureVideoPreviewLayer *preview; NSInteger order; NSString *dataString; } @end @implementation ScanVC - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = backGroundColor; self.title = @"二维码扫描"; [self configNavigationBar]; scanBackground = [[UIImageView alloc] initWithFrame:CGRectMake((kSize.width - KWidth)/2.0, (kSize.height - KWidth)/2.0 - kNavOffSet, KWidth, KWidth)]; scanBackground.image = [[UIImage imageNamed:@"scanBackground.png"] tint:RQ_MAIN_COLOR]; [self.view addSubview:scanBackground]; line = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetMinX(scanBackground.frame)+5, CGRectGetMinY(scanBackground.frame)+5, KWidth-10,2)]; line.image = [[UIImage imageNamed:@"scanLine.png"] tint:RQ_MAIN_COLOR]; [self.view addSubview:line]; [self setOverView]; [self initScan]; order = 0; isDown = YES; num = 0; timer = [NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:@selector(timeRunToAnimation) userInfo:nil repeats:YES]; } -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; num = 0; //让先从最上面开始扫描 if (timer) { [timer setFireDate:[NSDate distantPast]]; } if (session && ![session isRunning]) { [session startRunning]; } } -(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if (timer) { [timer setFireDate:[NSDate distantFuture]]; } if (session && [session isRunning]) { [session stopRunning]; } } - (void)timeRunToAnimation { if (isDown) { num ++; if (num > (KWidth-10)/2.0) { isDown = NO; } }else{ num --; if (num == 0) { isDown = YES; } } line.frame = CGRectMake(CGRectGetMinX(scanBackground.frame)+5, CGRectGetMinY(scanBackground.frame)+5 + num*2, KWidth-10,2); } //二维码操作 -(void)initScan { NSString *mediaType = AVMediaTypeVideo; AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType]; if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) { [self.navigationController popViewControllerAnimated:YES]; [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"请在iPhone的“设置”-“隐私”-“相机”功能中,找到“极速驾培”打开相机访问权限" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) { if (selectedOtherButtonIndex == 0) { NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; } } }]; return; } //获取设备 device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //输入流 input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; //输出流 output = [[AVCaptureMetadataOutput alloc] init]; //设置代理 //(kSize.width - KWidth)/2.0, (kSize.height - KWidth)/2.0, KWidth, KWidth) //这里添加一点 这样就很容易扫到码了 CGRect rect = scanBackground.frame; rect.origin.x = (kSize.width - KWidth - 80)/2.0; rect.origin.y = (kSize.height - KWidth - 80)/2.0; rect.size.width = rect.size.height = KWidth + 80; [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; output.rectOfInterest =[self rectOfInterestByScanViewRect:rect]; //NSLog(@"%@",output.rectOfInterest); //起连接作用的回执 session = [[AVCaptureSession alloc] init]; [session setSessionPreset:AVCaptureSessionPresetHigh]; if ([session canAddInput:input]){ [session addInput:input]; } if ([session canAddOutput:output]){ [session addOutput:output]; } //指定output所能扫描的类型 output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeQRCode]; //界面 preview = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; preview.videoGravity = AVLayerVideoGravityResizeAspectFill; preview.frame = self.view.bounds; [self.view.layer insertSublayer:preview atIndex:0]; [self.view bringSubviewToFront:scanBackground]; //开始扫描 [session startRunning]; } //扫描到的信息通过output的协议方法返回 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { if (metadataObjects.count > 0) { AVMetadataMachineReadableCodeObject *object = [metadataObjects firstObject]; //session关闭 [session stopRunning]; [timer setFireDate:[NSDate distantFuture]]; //需要我们对接的二维码抬头 if ([object.stringValue containsString:@"#DECODE#"] && object.stringValue.length > 8) { BOOL SP_IS_MNQisTure = NO; for (ParamsItem *item in RQ_USER_MANAGER.currentUser.params) { if ([item.KEY isEqualToString:@"SP_IS_MNQ"]) { if ([item.VALUE isEqualToString:@"1"]) { SP_IS_MNQisTure = YES; } } } //程序内某些验证 NSString *testString = [DES3Util decrypt:[object.stringValue substringFromIndex:8]]; NSArray *scanArray = [testString componentsSeparatedByString:@";"]; /* 是APP的二维码*/ if ([[scanArray firstObject] isEqualToString:@"#JSDTMO#"]) { //二维码是否过期 NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSDate *scanDate = [formatter dateFromString:[scanArray lastObject]]; NSTimeInterval time = [scanDate timeIntervalSinceNow]; if (time < 0) { ShowMsg(@"二维码信息已过期"); [session startRunning]; [timer setFireDate:[NSDate distantPast]]; return; } /* 非计划实操计时 标识符 type 教练outID 教练姓名 价格 科目 教练手机号码 终端设备号 有效时间 */ if ([scanArray[1] isEqualToString:@"signIn"]) { if(self.type == 2){ [self showMsgByAlertControllerWithString:@"二维码类型错误,请扫描\"模拟计时\"二维码"]; return; } order = 1; dataString = [[testString componentsSeparatedByString:@"signIn;"] lastObject]; [self alertShowWithString:[NSString stringWithFormat:@"当前所选为%@教练,是否开始实操练习?",scanArray[3]]]; return; } /* 计划实操计时 标识符 type 教练outID 教练姓名 学生证号 预约ID 电话号码 终端设备号 有效时间 */ if ([scanArray[1] isEqualToString:@"planSignIn"]) { if(self.type == 2){ [self showMsgByAlertControllerWithString:@"二维码类型错误,请扫描\"模拟计时\"二维码"]; return; } if (![scanArray[4] isEqualToString:RQ_USER_MANAGER.currentUser._id]) { ShowMsg(@"当前准教学员信息与本人不符,请核对二维码"); [Tools playAudioWithString:@"当前准教学员信息与本人不符,请核对二维码"]; [session startRunning]; [timer setFireDate:[NSDate distantPast]]; return; } order = 2; dataString = [[testString componentsSeparatedByString:@"planSignIn;"] lastObject]; [self alertShowWithString:[NSString stringWithFormat:@"当前所选为%@教练,是否开始实操练习?",scanArray[3]]]; return; } /* 实操结束计时 标识符 type 教练outID 学生身份证明 有效时间 */ if ([scanArray[1] isEqualToString:@"signOut"] || [scanArray[1] isEqualToString:@"planSignOut"]) { if(self.type == 2){ [self showMsgByAlertControllerWithString:@"二维码类型错误,请扫描\"模拟计时\"二维码"]; return; } NSDictionary *gatherTrainDic; NSString *filePath = [Tools getPathWithFileName:@"gatherTrainDic.plist"]; if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { gatherTrainDic = [NSMutableDictionary dictionaryWithContentsOfFile:filePath]; } if ([gatherTrainDic[@"isPlan"] isEqualToString:@"1"] && [scanArray[1] isEqualToString:@"signOut"]) { ShowMsg(@"请选择正确结束方式!"); return; } if ([gatherTrainDic[@"isPlan"] isEqualToString:@"2"] && [scanArray[1] isEqualToString:@"planSignOut"]) { ShowMsg(@"请选择正确结束方式!"); return; } NSString *identString = RQ_USER_MANAGER.currentUser.outId; if ([scanArray[1] isEqualToString:@"planSignOut"]) { identString = RQ_USER_MANAGER.currentUser._id; } if (![scanArray[3] isEqualToString:identString]) { ShowMsg(@"当前准教学员信息与本人不符,请核对二维码"); [Tools playAudioWithString:@"当前准教学员信息与本人不符,请核对二维码"]; [session startRunning]; [timer setFireDate:[NSDate distantPast]]; return; } order = 3; if ([scanArray[1] isEqualToString:@"signOut"]) { dataString = [[testString componentsSeparatedByString:@"signOut;"] lastObject]; }else{ dataString = [[testString componentsSeparatedByString:@"planSignOut;"] lastObject]; } [self alertShowWithString:[NSString stringWithFormat:@"结束实操练习?"]]; return; } /* 模拟开始计时 标识符 type 教练outID 教练名字 教练经度 教练纬度 有效时间 */ if ([scanArray[1] isEqualToString:@"imitSignIn"]) { if (self.type == 1) { [self showMsgByAlertControllerWithString:@"二维码类型错误,请扫描\"实操计时\"二维码"]; return; } if (SP_IS_MNQisTure) { ShowMsg(@"请使用模拟机设备计时"); [session startRunning]; [timer setFireDate:[NSDate distantPast]]; return; } order = 4; dataString = [[testString componentsSeparatedByString:@"imitSignIn;"] lastObject]; [self alertShowWithString:[NSString stringWithFormat:@"当前所选为%@教练,是否开始模拟练习?",scanArray[3]]]; return; } /*模拟设备(非app二维码)(不包含#JSDTMO#)*/ }else if ([[scanArray firstObject] isEqualToString:@"#MNQ#"]){ if (self.type == 1) { [self showMsgByAlertControllerWithString:@"二维码类型错误,请扫描\"实操计时\"二维码"]; return; } /* 模拟开始 模拟设备打模拟学时 #MNQ#;序列号(devSn);动态码(dynamicCode);签到/签退类型(1签到 3签退) */ if (!SP_IS_MNQisTure) { ShowMsg(@"暂不能使用模拟起设备"); [session startRunning]; [timer setFireDate:[NSDate distantPast]]; return; } order = 5; dataString = [[testString componentsSeparatedByString:@"#MNQ#;"] lastObject]; NSString *showString = @"正在进行模拟计时签到,是否开始模拟练习?"; if ([[NSString stringWithFormat:@"%@",[scanArray lastObject]] isEqualToString:@"2"]) { showString = @"签退"; } [self alertShowWithString:showString]; return; }else{ //包含#decode# 非@"#JSDTMO#" 非#MNQ# } } /*无须我们对接的二维码(不包含#DECODE#)*/ if (self.type == 1) { [self showMsgByAlertControllerWithString:@"二维码类型错误,请扫描\"实操计时\"二维码"]; }else if(self.type == 2){ [self showMsgByAlertControllerWithString:@"二维码类型错误,请扫描\"模拟计时\"二维码"]; } //判断是否进入进某网址 // if ([object.stringValue containsString:@".com"] || [object.stringValue containsString:@".cn"]) { // [[UIApplication sharedApplication] openURL:[NSURL URLWithString:object.stringValue]]; // [self.navigationController popViewControllerAnimated:YES]; // return; // } //扫码网页登录用 // order = -1; // dataString = object.stringValue; // [self alertShowWithString:@"是否允许登录公众平台?"]; } } -(void)showMsgByAlertControllerWithString:(NSString *)str { [RQ_SHARE_FUNCTION showAlertWithTitle:@"提示" message:str alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"重新扫描" otherButtonTitles:@[@"退出"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) { switch (selectedOtherButtonIndex) { case NSNotFound: { //取消就重新打开扫描 [session startRunning]; [timer setFireDate:[NSDate distantPast]]; break; } case 0: { [self.navigationController popViewControllerAnimated:YES]; break; } default: break; } }]; // UIAlertController *alertFind = [UIAlertController alertControllerWithTitle:@"提示" message:str preferredStyle:UIAlertControllerStyleAlert]; // // [alertFind addAction:[UIAlertAction actionWithTitle:@"重新扫描" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { // //取消就重新打开扫描 // [session startRunning]; // [timer setFireDate:[NSDate distantPast]]; // }]]; // [alertFind addAction:[UIAlertAction actionWithTitle:@"退出" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { // [self.navigationController popViewControllerAnimated:YES]; // }]]; // [self presentViewController:alertFind animated:true completion:nil]; } - (void)alertShowWithString:(NSString *)string { [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:string alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) { if (selectedOtherButtonIndex == 0) { switch (order) { case -1: { [self downloadFJJP]; } break; case 1://非计划实操计时 { NSDictionary *dic = @{@"scanType":@"scPeriod",@"dataString":dataString}; if (scanBlock) { scanBlock(dic); [self.navigationController popViewControllerAnimated:YES]; } } break; case 2://计划实操计时 { NSDictionary *dic = @{@"scanType":@"jhPeriod",@"dataString":dataString}; if (scanBlock) { scanBlock(dic); [self.navigationController popViewControllerAnimated:YES]; } } break; case 3://结束计时 { NSDictionary *dic = @{@"scanType":@"allSignOut",@"dataString":dataString}; if (scanBlock) { scanBlock(dic); [self.navigationController popViewControllerAnimated:YES]; } } break; case 4://模拟计时开始 { NSDictionary *dic = @{@"scanType":@"imPeriod",@"dataString":dataString}; if (scanBlock) { scanBlock(dic); [self.navigationController popViewControllerAnimated:YES]; } } break; case 5://模拟计时开始/结束 { NSDictionary *dic = @{@"scanType":@"imitatePeriod",@"dataString":dataString}; if (scanBlock) { scanBlock(dic); [self.navigationController popViewControllerAnimated:YES]; } } break; default: break; } }else if (selectedOtherButtonIndex == NSNotFound) { //取消就重新打开扫描 [session startRunning]; [timer setFireDate:[NSDate distantPast]]; return; } }]; } //登录网页社会公众平台 -(void)downloadFJJP { if (!dataString || dataString.length < 1) { [session startRunning]; [timer setFireDate:[NSDate distantPast]]; return; } //发送请求 [LoadingView showHUD]; NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; NSString *account = [ud objectForKey:@"identifyNum"]; NSString *key = [ud objectForKey:@"password"]; NSString *params = [NSString stringWithFormat:@"%@;%@;%@",dataString,account,key]; //NSLog(@"获取的二维码---->%@----\nparams---->%@\n---->%@",object.stringValue,params,[DES3Util encrypt:params]); NSString *URL = [NSString stringWithFormat:@"http://www.jppt.com.cn/gzpt/index/phoneLogin?params=%@",[DES3Util encrypt:params]]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:URL]]; [request setHTTPMethod:@"GET"]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 返回数据转为字符串 RemoveHUD(); NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if ([dataStr isEqualToString:@"true"]) { ShowMsg(@"登录成功"); [self.navigationController popViewControllerAnimated:YES]; }else{ ShowMsg(@"登录失败"); [session startRunning]; [timer setFireDate:[NSDate distantPast]]; } }]; [task resume]; } -(void)scanBlock:(MyBlockType)block { scanBlock = block; } - (CGRect)rectOfInterestByScanViewRect:(CGRect)rect { CGFloat width = CGRectGetWidth(self.view.frame); CGFloat height = CGRectGetHeight(self.view.frame); CGFloat x = (height - CGRectGetHeight(rect)) / 2 / height; CGFloat y = (width - CGRectGetWidth(rect)) / 2 / width; CGFloat w = CGRectGetHeight(rect) / height; CGFloat h = CGRectGetWidth(rect) / width; return CGRectMake(x, y, w, h); } #pragma mark - 添加模糊效果 - (void)setOverView { CGFloat width = CGRectGetWidth(self.view.frame); CGFloat height = CGRectGetHeight(self.view.frame); CGFloat x = CGRectGetMinX(scanBackground.frame); CGFloat y = CGRectGetMinY(scanBackground.frame); CGFloat w = CGRectGetWidth(scanBackground.frame); CGFloat h = CGRectGetHeight(scanBackground.frame); [self creatView:CGRectMake(0, 0, width, y)]; [self creatView:CGRectMake(0, y, x, h)]; [self creatView:CGRectMake(0, y + h, width, height - y - h)]; [self creatView:CGRectMake(x + w, y, width - x - w, h)]; } - (void)creatView:(CGRect)rect { CGFloat alpha = 0.5; UIColor *backColor = [UIColor grayColor]; UIView *view = [[UIView alloc] initWithFrame:rect]; view.backgroundColor = backColor; view.alpha = alpha; [self.view addSubview:view]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end