今天,我们来一起探讨一下这个微信扫码支付。何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添加好友的时候,可以通过输入对方的微信号,也可以扫一扫对方的二维码。扫码支付,作为,微信支付里面,不可或缺的一个功能,对商品的支付提供了极为方便的体验,用途也非常的多。
例如我们在地铁、公交站常见的那些自动售货机(不错,就是那种投硬币,就可以自动出货的那种机器)中都用到。微信(支付宝)的扫码支付的出现,大大的减少了这方面的风险,近些年来,二维码的应用越来越广,甚至有些地方,直接用来自动售票(就是把起始点设定好,票价设定好,直接把二维码贴出来,让乘客自动扫相关的二维码,完成购票,上车的时候,只需要提供自己的支付凭证给乘车员验证即可),这样,不仅绿色环保了,还大大的提高了售票的速度(去过大车站购票的人应该深有体验,排队买个票,好歹半个小时以上,心里也是万头草泥马在奔腾的)。
咱就不扯远了,说回咱么今天要做的微信支付之扫码支付。微信官方的文档,这个扫码支付(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,

