今天,我们来一起探讨一下这个微信扫码支付。何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添加好友的时候,可以通过输入对方的微信号,也可以扫一扫对方的二维码。扫码支付,作为,微信支付里面,不可或缺的一个功能,对商品的支付提供了极为方便的体验,用途也非常的多。
例如我们在地铁、公交站常见的那些自动售货机(不错,就是那种投硬币,就可以自动出货的那种机器)中都用到。微信(支付宝)的扫码支付的出现,大大的减少了这方面的风险,近些年来,二维码的应用越来越广,甚至有些地方,直接用来自动售票(就是把起始点设定好,票价设定好,直接把二维码贴出来,让乘客自动扫相关的二维码,完成购票,上车的时候,只需要提供自己的支付凭证给乘车员验证即可),这样,不仅绿色环保了,还大大的提高了售票的速度(去过大车站购票的人应该深有体验,排队买个票,好歹半个小时以上,心里也是万头草泥马在奔腾的)。
咱就不扯远了,说回咱么今天要做的微信支付之扫码支付。微信官方的文档,这个扫码支付(NativePay)分为两种,一种是“生成扫描支付模式”,另外一种是“生成直接支付url,支付url有效期为2小时”,至于这里面,两种扫码模式,怎么灵活利用呢,官方也没有一个明确的说明。个人理解为,第一种(生成扫描支付模式),适用于固定二维码的,就是永久使用的那种。
例如一些商家的公众号的二维码,是永久的,什么时候扫,都是关注这个公众号的,但是,这种的话,我记得微信是有限量的,貌似是一个公众号,限量10w,个人观点,觉得这个限量,是足够我们使用的。第二种(生成直接支付url,支付url有效期为2小时),这种的话,因为有有效期这种时间限制,超过了2个小时,该二维码就失效,但是对生成的二维码数量没有限制,所以,这种个人观点觉得适用于那种临时根据实际情况生成的二维码,例如:公众平台登陆的时候二次验证的二维码,自定义生成,仅为一次性缴费使用的二维码,等等)。接下来,我们就开始讲讲实际例子,首先将的就是第一种模式。
扫码支付之模式一(生成扫描支付模式):
首先,我们新建一个“MVC”的项目(asp.net的官方的demo就是了,要asp.net的自己看demo吧,demo地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1),然后把系统自动生成的HomeControler和View中的Home都删了。
然后自己新建一个HomeControler,代码如下:
// GET: Home public ActionResult Index() { return View(); }</div>
再添加一个View,代码如下:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>首页</title> </head> <body> <div> </div> </body> </html></div>
接下来,我们先把官方的demo的一些我们会用到的东西拷贝过来,其中包括以下几个文件夹,如下图:
就这个lib和business两个,把这两个文件夹,支付复制到咱们的新项目中,并且包含在项目中,如下:
然后我们再“重新生成”以下项目,或者快捷键:ctrl+shift+b,这时候,会提下如下错误:
这时候,我们去添加引用,把lib文件夹中的LitJson.dll 添加上即可,如下图:
到这里,我们就基本把官方的demo的环境给搭建好了,接下来,我们就要开始编写代码了。
首先,我的逻辑是,从前到后,就是从前端到后端。前端是显示二维码的地方,那么我们就先给他一个div(本文使用到的是jquery的二维码生成插件,全名叫:jquery.qrcode.min.js,我会传到附件上),然后在页面加载完毕的时候,会请求后台,让他返回二维码字符串,然后再通过jquery的二维码生成插件,让他生成二维码并显示在前台,代码如下:
前端:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>首页</title> <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" /> <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" /> <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" /> </head> <body> <p> 模式一:生成扫描支付模式 <br /> <div id="QRCode1"> </div> </p> <p> 模式二:生成直接支付url,支付url有效期为2小时 <br /> <div id="QRCode2"> </div> </p> <script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script> <script src="~/Scripts/jquery.qrcode.min.js"></script> <script type="text/javascript"> $(function () { fGetQRCode1(); }) function fGetQRCode1() { $.messager.progress({ title: "", msg: "正在生成二维码:模式一,请稍后..." }); $.ajax({ type: "post", url: "/Home/GetQRCode1", data: { time: new Date(), productId:7788 }, success: function (json) { $.messager.progress('close');//记得关闭 if (json.result) { $('#QRCode1').qrcode(json.str); //生成二维码 } else { $('#QRCode1').html("二维码生成失败"); } } }) } </script> </body> </html></div>
后端:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using WxPayAPI; namespace WxPay.Controllers { public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } /// <summary> /// 模式一 /// </summary> /// <returns></returns> [HttpPost] public ActionResult GetQRCode1() { object objResult = ""; string strProductID = Request.Form["productId"]; string strQRCodeStr = GetPrePayUrl(strProductID); if (!string.IsNullOrWhiteSpace(strProductID)) { objResult = new { result = true, str = strQRCodeStr }; } else { objResult = new { result = false }; } return Json(objResult); } /** * 生成扫描支付模式一URL * @param productId 商品ID * @return 模式一URL */ public string GetPrePayUrl(string productId) { WxPayData data = new WxPayData(); data.SetValue("appid", WxPayConfig.APPID);//公众帐号id data.SetValue("mch_id", WxPayConfig.MCHID);//商户号 data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//时间戳 data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串 data.SetValue("product_id", productId);//商品ID data.SetValue("sign", data.MakeSign());//签名 string str = ToUrlParams(data.GetValues());//转换为URL串 string url = "weixin://wxpay/bizpayurl?" + str; return url; } /** * 参数数组转换为url格式 * @param map 参数名与参数值的映射表 * @return URL字符串 */ private string ToUrlParams(SortedDictionary<string, object> map) { string buff = ""; foreach (KeyValuePair<string, object> pair in map) { buff += pair.Key + "=" + pair.Value + "&"; } buff = buff.Trim('&'); return buff; } } }</div>
这时候,模式一是不是感觉就完成了?那么我们现在试试,我们浏览该页面,如下:
然后用微信扫一扫功能扫一下,发现提示如下:
这是什么鬼,是不是,你心里面是不是想知道为啥,那我来告诉你,这是为啥,这是因为,你还没有设置回调页面或者回调页面有问题,这个时候,我们再新建一个Control,