我们在写一个不太了解的新功能的时候,又稳又快的一个方法就是借(chao)鉴(xi)其他的人的实现方法。所以我们先不急着开始写代码,先看一下各互联网巨头都是如何实现的。
F12调出控制台,可以看出淘宝一直在发送请求查看这个二维码的状态
可以看出京东也是这么做的,看到这里大家都有点思路了把
接着我们还是不着急写代码,先把思路理清楚。这里我们采用前后端分离的方法来实现这个功能(暂不考虑二维码过期、该二维码登录过一次等复杂情况,只实现扫码登录功能)。
1.让前端页获取唯一的QRUUID(唯一字符串就可以)生成一个二维码用的接口。
2.APP端扫描到QRUUID后去请求的接口,功能是把用户和这个QRUUID绑定(可以传User_id或者token什么的,具体看需求)。
3.前端在获取到第一个的接口返回的QRUUID后去轮询请求的接口,功能是查询这个QRUUID是不是被APP端扫描并绑定。
其实就是Ajax请求PHP接口获得QRUUID然后生成二维码,接着使用setInterval() 方法去请求第三个PHP接口。(前端生成二维码的开放API:http://www.topscan.com/pingtai/)
使用AVFoundation扫描二维码获得信息,然后请求PHP接口将用户数据和QRUUID绑定。
DROP TABLE IF EXISTS `qrcodelogin`;
CREATE TABLE `qrcodelogin` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`qruuid` varchar(15) NOT NULL DEFAULT '',
`user_id` int(11) DEFAULT NULL,
`user_token` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
SET FOREIGN_KEY_CHECKS = 1;
//config.php 数据库配置文件
$db_host = '192.168.1.103';
$db_name = 'test';
$db_user = 'root';
$db_pwd = 'a123456';
/**
* getqruuid.php
* 用于前端获取qruuid(二维码唯一ID)使用
*
* User: caohan
*/
require('config.php');
$mysqli = new mysqli($db_host, $db_user, $db_pwd, $db_name);
if (mysqli_connect_error())
echo mysqli_connect_error();
$mysqli->set_charset("utf8");
//生成随机的UUID 用于二维码显示的内容 和 绑定用
$qruuid = substr(md5(uniqid(mt_rand(), true)), 0, 15);//生成uuid
$sql = "insert into qrcodelogin (qruuid) values ('". $qruuid ."')";
$result = $mysqli->query($sql);
if($result === false){
echo $mysqli->error;
echo $mysqli->errno;
}
$mysqli->close();
$arr = ['code'=>1, 'msg' => '生成qruuid成功','data'=>$qruuid];
echo json_encode($arr);
exit();
/**
* bindqruuid.php
* App端扫描二维码获得qruuid以后
* 然后请求这个接口 二维码的qruuid和用户绑定并把用户信息传入
* (token或者user_info什么的 具体看需求)
*
* User: caohan
*/
require('config.php');
$mysqli = new mysqli($db_host, $db_user, $db_pwd, $db_name);
if (mysqli_connect_error())
echo mysqli_connect_error();
$mysqli->set_charset("utf8");
$qruuid = $_GET['qruuid'];
$user_id = $_GET['user_id'];
$user_token = $_GET['user_token'];
$sql = "update qrcodelogin set user_id='" . $user_id . "',user_token='" . $user_token . "' where qruuid='" . $qruuid . "'";
$result = $mysqli->query($sql);
if ($result === false) {
echo $mysqli->error;
echo $mysqli->errno;
}
$mysqli->close();
$arr = ['code' => 1, 'msg' => '绑定成功'];
echo json_encode($arr);
exit();
/**
* checkqruuid.php
* 用于前端页轮询 查询该qruuid是否被绑定
*
* User: caohan
*/
require('config.php');
$mysqli = new mysqli($db_host, $db_user, $db_pwd, $db_name);
if (mysqli_connect_error())
echo mysqli_connect_error();
$mysqli->set_charset("utf8");
$qruuid = $_GET['qruuid'];
$sql = "select * from qrcodelogin where qruuid='" . $qruuid . "'";
$result = $mysqli->query($sql)->fetch_array();
if ($result === false) {
echo $mysqli->error;
echo $mysqli->errno;
}
$mysqli->close();
if (!is_null($result['user_id']))
$arr = ['code' => 1, 'msg' => '登录成功', 'data' => $result];
else
$arr = ['code' => 500, 'msg' => 'qruuid暂时未被绑定','data'=>$qruuid];
echo json_encode($arr);
exit();
?>
<html>
<head>
<script src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js">script>
<title>这个一个二维码登录页Demotitle>
head>
<body>
<h4>
这个一个二维码登录页Demo
h4>
<h5>
用APP扫描下方二维码模拟登录
h5>
<img id="qrcodeimg" />
body>
<script>
$.ajax({
type: "GET",
url: "getqruuid.php",
data: {},
success: function (result) {
var data = JSON.parse(result);
if (data.code == 1) {
//显示到网页上 免费在线二维码生成的API
$("#qrcodeimg").attr('src', 'http://qr.topscan.com/api.php?text=' + data.data);
//轮询 查询该qruuid的状态 直到登录成功或者过期(过期这里没判断,留给大家)
var interval1= setInterval(function () {
$.ajax({
type: "GET",
url: "checkqruuid.php",
data: {'qruuid': data.data},
success: function (result) {
var data = JSON.parse(result);
if (data.code == 1) {
alert('扫码成功(即登录成功),进行跳转.....');
//停止轮询
clearInterval(interval1);
//TODO 拿到需要的信息 然后跳转什么的
}
}
});
}, 1000);//1秒钟 频率按需求
}
}
});
script>
html>
//
// ViewController.m
// QRCode
#import "ViewController.h"
#import "QRCodeViewController.h"
@interface ViewController () <QRCodeViewControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)scanCode:(UIButton *)sender {
QRCodeViewController *qrVc = [[QRCodeViewController alloc] init];
qrVc.delegate = self;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:qrVc];
// 设置扫描完成后的回调
__weak typeof (self) wSelf = self;
[qrVc setCompletionWithBlock:^(NSString *resultAsString) {
[wSelf.navigationController popViewControllerAnimated:YES];
// [[[UIAlertView alloc] initWithTitle:@"扫描完成" message:resultAsString delegate:self cancelButtonTitle:@"好的" otherButtonTitles: nil] show];
}];
[self presentViewController:nav animated:YES completion:nil];
}
#pragma mark - 代理方法
- (void)reader:(QRCodeViewController *)reader didScanResult:(NSString *)result
{
NSLog(@"%@",result);
//模拟用户已登录状态
//创建假的user_id和假的user_token用于绑定(根据实际需求传递参数)
NSInteger user_id = 1;
NSString *user_token = @"this_is_user_token";
[self dismissViewControllerAnimated:YES completion:^{
//请求服务端接口
NSError *error;
NSString *urlString = [NSString stringWithFormat:@"http://192.168.1.103/qrcodelogin/bindqruuid.php?qruuid=%@&user_id=%ld&user_token=%@",result,(long)user_id,user_token];
//加载一个NSURL对象
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
//将请求的url数据放到NSData对象中
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
NSLog(@"接收到的数据为%@",jsonDic);
}];
}
@end
PS:我在CSDN下了一个扫描二维码的Demo,并且修改一下,这里放出我下载的Demo的地址:http://download.csdn.net/download/u013438373/9808825
HTML登录页
APP扫码过程
扫描后的网页