C# .NET MVC微信JSAPI支付
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
开发工具与关键技术:Visual Studio 2015 ASP .NET MVC
作者:熊俊杰
撰写时间:2020.8.7
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
经过本人不断翻找资料和百度终于结合一些大佬的经验和思路弄出来一个MVC的微信支付了。
再弄微信支付之前我们需要先有一个商户号,并且开通了微信支付的JSAPI支付功能,也需要申请微信公众号并绑定指定的商户号。
首先我们根据微信官方给出的文档得知我们要在H5调起微信支付的流程如下:
文档的链接 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4
在H5中调起微信支付,官方已经明确的告诉了我们我们需要拿到哪些数据才可以调起微信支付的功能,如下:
只有拿到了这些数据并使用微信指定的方法‘WeixinJSBridge.invoke()’通过’getBrandWCPayRequest’来拉起微信支付,当然这些都是最后的步骤。
首先我们需要检测页面是否在微信内置环境中打开,先使用微信官方给的一个插件:
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
然后在使用如下方法判断:
var ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
//ios的ua中无miniProgram,但都有MicroMessenger(表示是微信浏览器)//https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
wx.miniProgram.getEnv((res) => {
if (openid == "") {
getCode();
}
})
} else {
//alert('不在微信里');
}
因为微信的JSAPI支付只能在微信环境下才可以调起支付,在其他的环境中我们无法拉起微信支付的功能。
然后我们要去微信官方下载一个C#的JSAPI支付的示例,然后把其中的business和lib这两个文件夹拷贝到自己的项目里面去
在这之前我们需要在控制器里面自定义一个实体
public class ModelForOrder
{
public string appId { get; set; }
public string timeStamp { get; set; }
public string nonceStr { get; set; }
public string packageValue { get; set; }
public string paySign { get; set; }
public string msg { get; set; }
}
然后我们再去将js传过来支付的金额传到我们的控制器,再通过微信官方给的方法去获取出我们需要的数据出来
JsApiPay jsApiPay = new JsApiPay();
[HttpPost]
public ActionResult MeterRecharge()
{
object objResult = "";
string strTotal_fee = Request.Form["totalfee"];
string strFee = (double.Parse(strTotal_fee) * 100).ToString();
var openid = Session["openid"].ToString();//用户的OpenID
//若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数
jsApiPay.openid = openid;//
jsApiPay.total_fee = int.Parse(strFee);
//JSAPI支付预处理
try
{
string strBody = "wx";//商品描述
WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(strBody);
WxPayData wxJsApiParam = jsApiPay.GetJsApiParameters();
var dingdanhao = WxPayApi.DingDanHao;
Session["DingDanHao"] = dingdanhao;
ModelForOrder aOrder = new ModelForOrder()
{
appId = wxJsApiParam.GetValue("appId").ToString(),
nonceStr = wxJsApiParam.GetValue("nonceStr").ToString(),
packageValue = wxJsApiParam.GetValue("package").ToString(),
paySign = wxJsApiParam.GetValue("paySign").ToString(),
timeStamp = wxJsApiParam.GetValue("timeStamp").ToString(),
msg = "成功下单,正在接入微信支付."
};
objResult = aOrder;
}
catch (Exception ex)
{
ModelForOrder aOrder = new ModelForOrder()
{
appId = "",
nonceStr = "",
packageValue = "",
paySign = "",
timeStamp = "",
msg = "下单失败,请重试,多次失败,请联系管理员."
};
objResult = aOrder;
}
return Json(objResult);
}
在这里我们需要将官方的这个JsApiPay实体里面稍微做一些改动,在这我也是参照网络上的模板来弄的,如下:
public JsApiPay(Page page)
{
this.page = page;
}
需要改为:
public JsApiPay()
{
}
由于官方的这个GetJsApiParameters()实例是string类型的,这里我们改成了WxPayData类型的实例
public string GetJsApiParameters()
{
Log.Debug(this.GetType().ToString(), "JsApiPay::GetJsApiParam is processing...");
WxPayData jsApiParam = new WxPayData();
jsApiParam.SetValue("appId", unifiedOrderResult.GetValue("appid"));
jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());
jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr());
jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
jsApiParam.SetValue("signType", "MD5");
jsApiParam.SetValue("paySign", jsApiParam.MakeSign());
string parameters = jsApiParam.ToJson();
Log.Debug(this.GetType().ToString(), "Get jsApiParam : " + parameters);
return parameters;
}
需要改为:
public WxPayData GetJsApiParameters()
{
Log.Debug(this.GetType().ToString(), "JsApiPay::GetJsApiParam is processing...");
WxPayData jsApiParam = new WxPayData();
jsApiParam.SetValue("appId", unifiedOrderResult.GetValue("appid"));
jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());
jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr());
jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
jsApiParam.SetValue("signType", "MD5");
jsApiParam.SetValue("paySign", jsApiParam.MakeSign());
string parameters = jsApiParam.ToJson();
Log.Debug(this.GetType().ToString(), "Get jsApiParam : " + parameters);
return jsApiParam;
}
弄完这些我们还需要再lib文件夹的 DemoConfig这个示例里面的一些私人数据,比如商户号,商户密匙,公众号APPID 和公众号密匙AppSecret等等.
弄完这些差不多就可以实现调起微信支付了,这里需要特别声明这里支付的结果回调官方给了特别说明,不能保证绝对的正确,所以我们需要再去根据商户订单号或者微信支付号再去查询回调结果保证数据不会出现错误。