微信支付是集成在微信客户端的支付功能,用户可以通过手机完成快速的支付流程。微信支付以绑定银行卡的快捷支付为基础,向用户提供安全、快捷、高效的支付服务。
- 公众号支付
- APP支付
- 扫码支付
- 刷卡支付
- H5支付
- 小程序支付
(本文档主要介绍公众号支付和扫码支付)
注:微信公众号目前必须是服务认证号,且开通微信支付功能。公众号对应的商户号也必须开通支付功能。
一、公众号支付
公众号支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。应用场景有:
- 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
- 用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付
- 将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付
1. 设置JSSDK接口调用域名
先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
2. 设置授权域名
开发公众号支付时,在统一下单接口中要求必传用户openid,而获取openid则需要您在公众平台设置获取openid的域名,只有被设置过的域名才是一个有效的获取openid的域名,否则将获取失败。如下图:
3. 设置支付目录
请确保实际支付时的请求目录与后台配置的目录一致,否则将无法成功唤起微信支付。
在微信商户平台(pay.weixin.qq.com)设置您的公众号支付支付目录,设置路径:商户平台-->产品中心-->开发配置,如下图所示。公众号支付在请求支付的时候会校验请求来源是否有在商户平台做了配置,所以必须确保支付目录已经正确的被配置,否则将验证失败,请求支付不成功。
注意:这三个地方的域名需使用字母、数字及“-”的组合,不支持IP地址、端口号及短链域名,且填写的域名须通过ICP备案的验证。
4. 设置支付密钥app_key
点击帐户中心——API安全——设置API密钥(用于支付是的验签)
5. 获取openid
由于openid必须为当前用户在当前支付公众号内的身份标识,所以在智慧校园项目中采取实时获取的方式获得。
步骤一:用户同意授权,获取code
访问以下链接获得带code参数的Url:
参数说明:
参数 |
是否必须 |
说明 |
appid |
是 |
公众号的唯一标识 |
redirect_uri |
是 |
授权后重定向的回调链接地址,请使用urlencode对链接进行处理 |
response_type |
是 |
返回类型,请填写code |
scope |
是 |
应用授权作用域,snsapi_base(不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) |
state |
否 |
重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 |
#wechat_redirect |
是 |
无论直接打开还是做页面302重定向时候,必须带此参数 |
注:回调链接一定要urlencode,不然识别不出
步骤二:通过code换取网页授权access_token
首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。
获取code后,请求以下链接获取access_token:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明:
参数 |
是否必须 |
说明 |
appid |
是 |
公众号的唯一标识 |
secret |
是 |
公众号的appsecret |
code |
是 |
填写第一步获取的code参数 |
grant_type |
是 |
填写为authorization_code |
返回JSON数据包如下:
{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
附:关于网页授权access_token和普通access_token的区别
1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;
2、其他微信接口,如发微信消息接口,需要通过基础支持中的“获取access_token”接口(https://api.weixin.qq.com/cgi-bin/token)来获取到的普通access_token调用。
-----------------------------上述5个步骤都为支付的准备步骤。-----------------------------
支付业务流程及步骤如下图:
6. 微信内H5调起支付
步骤一:后台统一下单获取jsapi支付参数
请求地址:https://api.mch.weixin.qq.com/pay/unifiedorder
请求参数: appid(公众账号ID),
mch_id(商户号),
device_info(设备号),
nonce_str(随机字符串),
sign(签名),
sign_type(签名类型),
body(商品描述) ,
detail(商品详情),
attach(附加数据),
out_trade_no(商户订单号),
fee_type(标价币种),
total_fee(标价金额),
spbill_create_ip(终端IP),
time_start(交易起始时间),
time_expire(交易结束时间),
notify_url(支付回调地址),
trade_type(交易类型),
product_id(商品ID),
opened(用户标识)
注:参数值用XML转义即可,CDATA标签用于说明数据不被XML解析器解析。
具体下单过程可参照微信支付Demo:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
当请求成功,返回的XML中return_code 和result_code都为SUCCESS时会返回如下:
<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> <appid><![CDATA[wx3556f3b4523gf12r]]></appid> <mch_id><![CDATA[10000100]]></mch_id> <nonce_str><![CDATA[jfjsdh47fin0jdnv]]></nonce_str> <openid><![CDATA[oECxywCpJW8G-ktn3lwZ7MR4Cx2Q]]></openid> <sign><![CDATA[8SDVCNKDF89W32SDKCSAA0S32JKSDJJL]]></sign> <result_code><![CDATA[SUCCESS]]></result_code> <prepay_id><![CDATA[wx201801041172356eidnvnd9qk398324745]]></prepay_id> <trade_type><![CDATA[JSAPI]]></trade_type> </xml>
步骤二:H5发起微信支付
在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。
注意:WeixinJSBridge内置对象在其他浏览器中无效,参数名区分大小,大小写错误签名验证会失败。
引用js:http://res.wx.qq.com/open/js/jweixin-1.0.0.js。
调用支付js如下:
function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入 "timeStamp":"1395712654", //时间戳,自1970年以来的秒数 "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串 "package":"prepay_id=u802345jgfjsdfgsdg888", "signType":"MD5", //微信签名方式: "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 } ); } if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } }else{ onBridgeReady(); }
支付完成后,微信会将订单参数会以XML方式发送给商户系统回调地址,商户在回调地址接收参数并做相应处理。
回调的XML格式为:
<xml> <appid><![CDATA[wx2421b1c4370ec43b]]></appid> <attach><![CDATA[支付测试]]></attach> <bank_type><![CDATA[CFT]]></bank_type> <fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[Y]]></is_subscribe> <mch_id><![CDATA[10000100]]></mch_id> <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str> <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid> <out_trade_no><![CDATA[1409811653]]></out_trade_no> <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code> <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign> <sub_mch_id><![CDATA[10000100]]></sub_mch_id> <time_end><![CDATA[20140903131540]]></time_end> <total_fee>1</total_fee> <trade_type><![CDATA[JSAPI]]></trade_type> <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id> </xml>
推荐技术文档:
1.https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
2.https://wenku.baidu.com/view/cebde8a764ce0508763231126edb6f1aff007185.html?re=view
二、扫码支付
扫码支付可分为两种模式,商户根据支付场景选择相应模式。
【模式一】:
商户后台系统根据微信支付规则链接生成二维码,链接中带固定参数productid(可定义为产品标识或订单号)。用户扫码后,微信支付系统将productid和用户唯一标识(openid)回调商户后台系统(需要设置支付回调URL),商户后台系统根据productid生成支付交易,最后微信支付系统发起用户支付流程。
商户支付回调URL设置指引:进入商户平台-->产品中心-->开发配置,进行配置和修改,如下图所示。
【模式二】:
商户后台系统调用微信支付【统一下单API】生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易。注意:该模式的预付单有效期为2小时,过期后无法支付,不依赖设置的回调支付URL。
流程图:
业务流程说明:
(1)商户后台系统根据用户选购的商品生成订单。
(2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;
(3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。
(4)商户后台系统根据返回的code_url生成二维码。
(5)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。
(6)微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。
(7)用户在微信客户端输入密码,确认支付后,微信客户端提交授权。
(8)微信支付系统根据用户授权完成支付交易。
(9)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。
(10)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。
(11)未收到支付通知的情况,商户后台系统调用【查询订单API】。
(12)商户确认订单已支付后给用户发货。
附:
前端页面代码:
//前端页面 <img src=" MakeQRCode?code_url=@code_url" alt="二维码"/>
C#生成二维码后台代码:
//生成二维码方法 public FileResult MakeQRCode(string code_url) { if (string.IsNullOrEmpty(code_url)) throw new ArgumentException("code_url"); //初始化二维码生成工具 QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(); qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE; qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M; qrCodeEncoder.QRCodeVersion = 0; qrCodeEncoder.QRCodeScale = 4; //将字符串生成二维码图片 Bitmap image = qrCodeEncoder.Encode(code_url, Encoding.Default); //保存为PNG到内存流 MemoryStream ms = new MemoryStream(); image.Save(ms, ImageFormat.Jpeg); return File(ms.ToArray(), "image/jpeg"); }
推荐技术文档:
- https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1
- http://www.cnblogs.com/vinsonLu/p/5166214.html
(本文章是个人开发实践总结所写,请大家多多指教。码字不容易,转载请注明出处。谢谢!)