C# .NETMVC 微信JSAPI支付
C# .NET MVC微信JSAPI支付
经过本人不断翻找资料和百度终于结合一些大佬的经验和思路弄出来一个MVC的微信支付了。
再弄微信支付之前我们需要先有一个商户号,并且开通了微信支付的JSAPI支付功能,也需要申请微信公众号并绑定指定的商户号。
首先我们根据微信官方给出的文档得知我们要在H5调起微信支付的流程如下:
文档的链接 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4
在H5中调起微信支付,官方已经明确的告诉了我们我们需要拿到哪些数据才可以调起微信支付的功能,如下:
只有拿到了这些数据并使用微信指定的方法‘WeixinJSBridge.invoke()’通过’getBrandWCPayRequest’来拉起微信支付,当然这些都是最后的步骤。
首先我们需要检测页面是否在微信内置环境中打开,先使用微信官方给的一个插件:
然后在使用如下方法判断:
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_CNwx.miniProgram.getEnv((res) => {if (openid == "") {getCode();}})} else {//alert('不在微信里');}//初始化微信支付环境function fCharge() {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 {fPostCharge();}}//提交充值数据function fPostCharge() {var vChargeVal = $("#ChargeVal").val();if (vChargeVal > 0) {$.ajax({type: "post",data: "totalfee=" + vChargeVal,url: "MeterRecharge",success: function (json) {onBridgeReady(json.objResult);ddan = json.dingdanhao;$("#selectdingdan").val(ddan)},error: function () {alert('调用微信支付模块失败,请稍后再试。')}})}else {alert("充值金额不可以为空或者为负数。")}}//调用微信支付模块function onBridgeReady(json) {setTimeout(function () {cxdingdan();//撤销订单}, '60000');WeixinJSBridge.invoke('getBrandWCPayRequest',{"appId": json.appId, //公众号名称,由商户传入"timeStamp": json.timeStamp, //时间戳,自1970年以来的秒数"nonceStr": json.nonceStr, //随机串"package": json.packageValue,"signType": "MD5", //微信签名方式:"paySign": json.paySign //微信签名},function (res) {if (res.err_msg == "get_brand_wcpay_request:ok") {alert("支付成功0,请稍后查询余额,如有疑问,请联系管理员.");fAlreadyPay();} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。else if (res.err_msg == "get_brand_wcpay_request:cancel") {alert("支付取消1");//支付过程中用户取消}else if (res.err_msg == "get_brand_wcpay_request:fail") {alert("支付失败2");//支付失败}});}
因为微信的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; }}
public static string GenerateOutTradeNo1(){var ran = new Random();return string.Format("{0}{1}", DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(999));}
然后我们再去将js传过来支付的金额传到我们的控制器,再通过微信官方给的方法去获取出我们需要的数据出来
JsApiPay jsApiPay = new JsApiPay();
/// <summary>/// 充值/// </summary>/// <returns></returns>[HttpPost]public ActionResult MeterRecharge(){var dingdanhao = "";object objResult = "";string strTotal_fee = Request.Form["totalfee"];string strFee = (double.Parse(strTotal_fee) * 100).ToString();//var openid = "o1FBe1tSXimasQAlsxppBd8zgPuA";var openid = Session["OpenID"].ToString();//若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数jsApiPay.openid = openid;//jsApiPay.total_fee = int.Parse(strFee);//JSAPI支付预处理try{var UserID = "123";string strBody = "WXZF";//商品描述var weixindanhao = GenerateOutTradeNo1().ToString();weixindanhao = weixindanhao + UserID.ToString();WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(strBody, weixindanhao);WxPayData wxJsApiParam = jsApiPay.GetJsApiParameters();//获取H5调起JS API参数,注意,这里引用了官方的demo的方法,由于原方法是返回string的,所以,要对原方法改为下面的代码,代码在下一段//dingdanhao = WxPayApi.DingDanHao;dingdanhao = weixindanhao;Session["DingDanHao"] = dingdanhao;Session["czjine"] = strTotal_fee;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(new { objResult, dingdanhao });}
在这里我们需要将官方的这个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;}
最后还要改一个地方,JsApiPay.cs 将其中的GetUnifiedOrderResult这个方法改成下面这样的格式,因为微信官方给的订单号是根据时间戳来拼接的,所以在同一时间发起微信支付生成的订单号是重复的,所以我们需要自己弄一个不会重复的订单号,最好是拼接上用户的id之类的,另外一个传的是金额我们不动他,如下:
/*** 调用统一下单,获得下单结果* @return 统一下单结果* @失败时抛异常WxPayException*/public WxPayData GetUnifiedOrderResult(string strBody,string weixindanhao){
WxPayData data = new WxPayData();data.SetValue("body", strBody);data.SetValue("attach", "test");data.SetValue("out_trade_no", weixindanhao);data.SetValue("total_fee", total_fee);data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));data.SetValue("goods_tag", "test");data.SetValue("trade_type", "JSAPI");data.SetValue("openid", openid);WxPayData result = WxPayApi.UnifiedOrder(data);if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == ""){Log.Error(this.GetType().ToString(), "UnifiedOrder response error!");throw new WxPayException("UnifiedOrder response error!");}unifiedOrderResult = result;return result;}
弄完这些我们还需要再lib文件夹的 DemoConfig这个示例里面的一些私人数据,比如商户号,商户密匙,公众号APPID 和公众号密匙AppSecret等等,
弄完这些差不多就可以实现调起微信支付了,这里需要特别声明这里支付的结果回调官方给了特别说明,不能保证绝对的正确,所以我们需要再去根据商户订单号或者微信支付号再去查询回调结果保证数据不会出现错误。
在这里我们需要用到两个引用,这个需要自己去网上找一下,
LitJson.dll 和 Senparc.Weixin.TenPay.dll
(可以去Nuget程序包里面下载)
支付成功微信会将我们的支付结果给到我们那个回调的路径里面,所以我们需要根据那个回调路径拿到支付完成的结果,并将我们支付成功的结果返回给微信官方,否在微信会一直回调这个路径10次才停止回调,如下 huidiao() 是我这里支付成功的回调路径:
#region 微信回调方法[HttpPost][ValidateInput(false)]public ActionResult huidiao(){var xml = "";try{ResponseHandler resHandler = new ResponseHandler(null);string return_msg = resHandler.GetParameter("return_msg");//返回结果string result_code = resHandler.GetParameter("result_code");//业务结果string return_code = resHandler.GetParameter("return_code");//返回状态吗string jine = resHandler.GetParameter("total_fee");string out_trade_no = resHandler.GetParameter("out_trade_no");//商户订单号string WEXIN_OPENID = resHandler.GetParameter("openid");//微信openidstring transaction_id = resHandler.GetParameter("transaction_id");//微信支付单号ZhiFuHuiDiao1 zfhd = ZhiFuHuiDiao1.GetZhiFuHuiDiao1();string bit = zfhd.UpdateHuiDiao1(jine, out_trade_no, transaction_id, return_code);if (bit == "支付成功"){xml = string.Format(@"<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>", return_code, return_msg);}return Content(xml, "text/xml");}catch (Exception ex){dqwj(ex.ToString());//throw;}return Json("11s", JsonRequestBehavior.AllowGet);}
#endregion
在这里我还遇到了一个问题,就是当用户长时间未支付,等了将近7分钟才支付的,这样微信可能拿不到回调结果,所以我们要给一个时间端,如果超过了3分钟我们就撤销订单,让用户查询下单:
/// <summary>/// 订单超时,撤销订单/// </summary>/// <returns></returns>public ActionResult cxdingdan(){try{var dingdanhao = Session["DingDanHao"].ToString();string out_trade_no = dingdanhao.Trim();WxPayData data = new WxPayData();data.SetValue("out_trade_no", out_trade_no);//授权码WxPayData result = WxPayApi.CloseOrder(data, 10); //提交被扫支付,接收返回结果//如果提交被扫支付接口调用失败,则抛异常if (!result.IsSet("return_code") || result.GetValue("return_code").ToString() == "FAIL"){string returnMsg = result.IsSet("return_msg") ? result.GetValue("return_msg").ToString() : "";Log.Error("MicroPay", "Micropay API interface call failure, result : " + result.ToXml());throw new WxPayException("Micropay API interface call failure, return_msg : " + returnMsg);}var zt = result;return Json(zt, JsonRequestBehavior.AllowGet);}catch (Exception ex){var dingdanhao = Session["DingDanHao"].ToString();return Json(dingdanhao, JsonRequestBehavior.AllowGet);//throw;}}
源码下载:https://download.csdn.net/download/weixin_44486443/12766371
C# .NETMVC 微信JSAPI支付相关推荐
- php微信jsapi支付小结,ThinkPHP接入微信支付 - JSAPI支付
一.支付准备 二.获取用户openid 首先,到微信公众平台后台 - 设置 - 网页授权域名(别忘了添加开发者) // 在头部引入WechatPubService.php文件,见附录一 use app ...
- 微信JSAPI支付 跟 所遇到的那些坑
首先介绍一下我在调用微信支付接口使用的是 weixin.senparc SDK,非常方便好用开源的一个微信开发SDK. weixin.senparc SDK 官网:http://weixin.senp ...
- 微信JSApi支付~订单号和微信交易号
返回目录 谈谈transactionId和out_trade_no 前一篇微信JSApi支付~坑和如何填坑文章反映不错,所以又写了个后篇,呵呵. 每个第三方在线支付系统中都会有至少两类订单号,其一为支 ...
- 微信JSAPI支付对接流程及支付接口设计
文章目录 前言 一.JSAPI支付场景及逻辑 二.开发步骤 1.设置支付目录 2.设置授权域名 3.业务流程 三.代码设计 1. 支付页面 2. Controller 3. JS调起支付 4. 工具类 ...
- 关于微信JSAPI支付成功后,点击完成后没有返回值并且页面被自动关闭问题
微信JSAPI支付成功后,点击完成后没有返回值并且页面被自动关闭 简介 解决方式 错误的处理方式 总结 简介 最近很多人可能都遇到一个问题,在使用微信JSAPI支付成功后,不走成功的回调方法,只有支付 ...
- JAVA+微信JSAPI支付
JAVA+微信JSAPI支付 引入依赖 获取请求ip 组装微信支付请求 回调处理 引入依赖 <dependency><groupId>com.github.binarywang ...
- php接入微信JSAPI支付,微信内拉起支付,基于thinkPHP框架 WeChatDeveloper支付类包
文章:php接入微信支付,扫码支付和H5支付(非微信浏览器),基于thinkPHP框架 WeChatDeveloper支付类包 踩坑指南 文章:php快速接入支付宝即时支付,PC网站支付和手机网站支付 ...
- php 微信统一下单接口,微信JSAPI支付,统一下单接口
微信JSAPI支付,统一下单接口 今天小编给大家分享一下微信支付的统一下单接口,其实微信官网上也有SDK和DEMO下载了,但是不太好理解,小编就自己整理一份容易理解的代码,看不懂官方的,就来看看小编这 ...
- Java 微信jsapi支付
spring boot微信jsapi支付 话不多说,撸起袖子就是干,下面上源码 pom.xml 配置文件 resources/wx.properties 配置类 service(WechatPaySe ...
最新文章
- 基于SmartQQ协议的QQ聊天机器人-7
- 一条mysql分组查询的问题分析
- POJ 1979 Red and Black (简单dfs)
- IDEA下的使用git
- 【OS学习笔记】三十六 保护模式十:通过中断发起任务切换----中断任务
- 配置jupyter-pytorch深度学习环境
- applicationproperties不是小叶子_为何“砂糖桔”是带着叶子出售?原来其中有着“猫腻”,涨知识了...
- 在Windows XP 32位系统中安装JDK 1.8
- 3D模型在线转换,CAD格式转换,Solidworks版本转换
- C# 谷歌邮箱发送邮件
- 2019年云计算发展趋势如何 怎么加入云计算行业
- linux free空闲内存用尽,Linux中显示空闲内存空间的free命令的基本用法
- 大数据面试题汇总(含数仓)
- zabbix与nagios对比
- 教你如何用PCtoLCD2002生成字模以及软件的下载
- paste shell 分隔符_Shell paste命令
- 了解sprin是什么?有啥用?为什么要用?
- ArcGIS Pro添加在线底图
- rk3399 9.0修改系统默认输入法
- java支持库 易语言_易语言支持库|易语言支持库更新集合包下载233个 - 欧普软件下载...
热门文章
- golang中字符串和数字转换
- [CGAL] 3D快速相交和距离计算(AABB_tree)- 三角形碰撞检测
- BUUCTF-----SoulLike
- Ubuntu使用魅族手机进行Debug
- FebHost:什么是俄罗斯.ru域名,注册需要什么条件?
- 小组问题解决8D - 为什么需要8D?
- 使用深度学习来识别 captcha 验证码
- ios 分享功能 集成友盟分享
- 华为3e手机html查看器,【IT之家评测室】华为 nova 3e手机图赏:小仙女的美拍神器...
- C51 常见数据类型详解