最近工作遇到了和微信合作的需求,【微信扫码支付】和【微信扫码登录】,下面已现有网站为例解读一下针对这两种需求的解决方案。仅供参考。
1、微信扫码登录
其实微信开发者中心说的很全面,大家可以看下:
登录:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN
获取token、用户信息等:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316518&token=&lang=zh_CN
下面以一号店为例说一下开发过程:
1、点击微信登录会打开一个tab页,网址如下:
https://open.weixin.qq.com/connect/qrconnect?appid=wxbdc5610cc59c1631&redirect_uri=https://passport.yhd.com/wechat/callback.do&response_type=code&scope=snsapi_login&state=e68abe3f7542883fb323f60a2ec43fbe#wechat_redirect
appid:微信公众平台注册的appId
redirect_uri:实际上就是扫码之后的回调,微信会根据这个参数将当前页面跳转,直接redirect掉。会带上code和state的参数。
实际redirect url:https://passport.yhd.com/wechat/callback.do?code=微信返回的CODE&state=e68abe3f7542883fb323f60a2ec43fbe
response_type:响应的类型为code
scope:目前网页登录就是snsapi_login
state:自己传入的参数,防止被攻击。
2、用户扫码成功后,tab页的url会redirect为:https://passport.yhd.com/wechat/callback.do?code=微信返回的CODE&state=e68abe3f7542883fb323f60a2ec43fbe
此时callback.do 相当于是一号店自己的controller,那么这里面可以处理自己的逻辑。很显然逻辑就是用户登录
①步骤一:通过code获取access_token和openid
微信接口:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
返回:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
②步骤二:通过access_token和openid获取用户基本信息
微信接口:https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
返回:
{
"openid":"OPENID",
"nickname":"NICKNAME",
"sex":1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege":[
"PRIVILEGE1",
"PRIVILEGE2"
],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
③步骤三:通过返回的用户基本信息,做登录或者注册登录的业务逻辑。
④步骤四:完成登录后,页面应该会被刷新。
这个时候需要知道一下js的基本知识:window.opener 获取父级url,然后改变父级url的location并关闭当前扫码页。
2、微信扫码支付
开发文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1#
下面模式二为例,线上也有成功的例子京东和凡客。下面对微信文档中的步骤做解释。
(1)商户后台系统根据用户选购的商品生成订单。
(2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;
这里需要查看统一下单的接口,文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
如果下单成功,返回结果中:code_url是生成二维码扫码链接。
(3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。
(4)商户后台系统根据返回的code_url生成二维码。
这里面说明一下几种生成二维码的方式,无论是C#和java网上都有现成的方式,实际上典型的验证码应用。下面以C#为例:
方式一: 通过ZXing.dll
Bitmap img = null;
if (!string.IsNullOrEmpty(code_url))
{
BarcodeWriter writer = new BarcodeWriter();
writer.Format = BarcodeFormat.QR_CODE;
writer.Options.Hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");//编码问题
writer.Options.Hints.Add(
EncodeHintType.ERROR_CORRECTION,
ZXing.QrCode.Internal.ErrorCorrectionLevel.H
);
const int codeSizeInPixels = 250; //设置图片长宽
writer.Options.Height = writer.Options.Width = codeSizeInPixels;
writer.Options.Margin = 0;//设置边框
ZXing.Common.BitMatrix bm = writer.Encode(code_url);
img = writer.Write(bm);
}
生成的 Bitmap 直接response到页面。
if (img != null)
{
img.Save(MStream, System.Drawing.Imaging.ImageFormat.Jpeg);
//图片转btye[]
this.ViewBag.ImgArray = MStream.ToArray();
Response.ContentType = "image/Gif";
Response.ClearContent();
Response.BinaryWrite(MStream.ToArray());
Response.Flush();
Response.Close();
}
html会生成一下img标签装载图片
方式二:controller直接return File(MStream.ToArray(), "image/Gif");
方式三:base64位编码。
string base64DataString = Convert.ToBase64String(imgData);//byte转base64字符串
<img alt="微信扫码" title="微信扫码" src="data:image/png;base64,@base64DataString" />//html中img标签设置src
(5)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。
(6)微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。
(7)用户在微信客户端输入密码,确认支付后,微信客户端提交授权。
(8)微信支付系统根据用户授权完成支付交易。
(9)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。
(10)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。
商户后台系统接收到消息,做自己的业务处理。
(11)未收到支付通知的情况,商户后台系统调用【查询订单API】。
(12)商户确认订单已支付后给用户发货。
另,有些业务需求要求扫码的网站也要给予更友好的提示,如支付成功、支付失败等温馨提醒,针对这种需求的解决方案为:
扫码的网站异步查询订单状态,文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_2
实际上微信的速度还是很不错。代码: <script type="text/javascript">
var timeer;
$(document).ready(function () {
timeer = setInterval("GetStatus()",3000);
});
function GetStatus(){
$.ajax({
url: "查询url",
async:true,
type:"GET",
timeout:4000,
success:function(result){
if (成功) {
//处理自己的业务逻辑
}esle{
//处理自己的业务逻辑
}
}
});
}
</script>
说到底,微信文档给出的API已经很完善了。好好研究就行。
End.