博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.Net版微信支付
阅读量:6612 次
发布时间:2019-06-24

本文共 20121 字,大约阅读时间需要 67 分钟。

一. 案例介绍

这里模拟一个实际业务场景,进行介绍微信支付,业务功能包括:登录、注册、充值、查看充值记录。

  

 

页面图:

        

二. 概要设计

1.数据库设计

  这里数据库包括两张表:用户表和订单表。

  用户表: 主键id、用户名、密码、openid、注册时间

  订单表: 主键id、用户id,商品名称、订单状态(0代表下单了未支付,1代表支付成功)、商品价钱、下单时间

  

 

2.微信支付流程

  这里结合该案例,来说明微信支付流程。

  该流程中涉及到4种角色,分别是微信用户、微信客户端、商户系统(自己的系统)、微信支付系统。

  流程1:

  ①用户登录微信客户端系统→②进入主页→③去支付→④生成商户系统订单→⑤调用微信统一下单API,在微信支付系统里生成预支付订单,并返回预支付订单信息→

  ⑥商户系统拿到返回的预支付订单信息,进行签名,便按照一定的格式返给微信客户端(JSAPI页面)→⑦微信客户端JSAPI页面拿到参数,请求支付,输入密码,进行支付→

  ⑧这时会进行2个并行处理→异步通知商户支付结果,商户系统接到通知后,需要修改订单的业务逻辑(该案例修改订单状态0改为1),商户系统需要告知微信系统处理结果

  →给微信客户端发送支付结果,并发微信消息提示 

  ⑨微信客户端跳转到商户H5页面,查询商户后台支付结果

  ⑩ 这时候分两种情况

    A. 商户后台系统,已经接到通知,进行了业务修改,直接返回成功。

    B. 商户后台系统,没有接到通知,这时去查询微信支付系统,如果微信支付系统成功,说明确实付款成功,只是因为网络延迟造成商户后台暂时没有接到通知,如果查询后发现未付款成功,则返回付款失败。

微信支付业务流程图:
       

3.代码配置

(1).参数配置

(2).前端页面代码

1    $(function () { 2             // 当微信内置浏览器完成内部初始化后会触发WeixinJSBridgeReady事件。 3             document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { 4                 //公众号支付 5                 document.getElementById("pay").onclick = function () { 6                     //1.前端验证 7                     var money = $('#num').val(); 8                     if (money == "") { 9                         alert('请将信息输入完整');10                         return;11                     }12                     mui('#pay').button('loading');13                     //2.进行下单14                     $.ajax({15                         type: 'POST',16                         url: '/WeiXinGz/GetAPI',17                         data: { "money": money },18                         cache: false,19                         dataType: 'json',20                         success: function (jsonData) {21                             if (jsonData.status == "1") {22                                 //公众号支付23                                 WeixinJSBridge.invoke('getBrandWCPayRequest', jsonData.payData, function (res) {24                                     // 使用以下方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。25                                     //【因此微信团队建议:】当收到ok返回时,向商户后台询问是否收到交易成功的通知,26                                     //若收到通知,前端展示交易成功的界面;27                                     //若此时未收到通知,商户后台主动调用查询订单接口,查询订单的当前状态,并反馈给前端展示相应的界面。28                                     if (res.err_msg == "get_brand_wcpay_request:ok") {29                                         //JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回30                                         $.ajax({31                                             type: 'POST',32                                             url: '/WeiXinGz/QueryOrder',33                                             data: {34                                                 orderId: jsonData.orderId35                                             },36                                             cache: false,37                                             dataType: 'text',38                                             success: function (jsonData) {39                                                 if (jsonData == "ok") {40                                                     alert("支付成功", "提示", function () {41                                                         alert("页面跳转等业务处理");42                                                     });43                                                     mui('#pay').button('reset');44                                                 } else {45                                                     alert("支付失败,请稍后重试!如果收到支付通知,切勿重复支付1!");46                                                     mui('#pay').button('reset');47                                                 }48                                             },49                                             error: function (XMLHttpRequest, textStatus, errorThrown) {50                                                 alert("支付失败,请稍后重试!如果收到支付通知,切勿重复支付2!");51                                                 mui('#pay').button('reset');52                                             }53                                         });54                                     } else if (res.err_msg == "get_brand_wcpay_request:cancel") {55                                         //由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。56                                         alert("您放弃了支付");57                                         mui('#pay').button('reset');58                                     } else {59                                         //由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。60                                         alert("支付失败,请稍后重试!如果收到支付通知,切勿重复支付3!");61                                         mui('#pay').button('reset');62                                     }63                                 });64                             } else {65                                 alert(jsonData.promptInfor);66                                 mui('#pay').button('reset');67                             }68                         },69                         error: function (XMLHttpRequest, textStatus, errorThrown) {70                             alert("微信订单提交失败,请稍后重试4!");71                             mui('#pay').button('reset');72                         }73                     });74 75                 }76             }, false);77         });

 

(3).统一下单接口

1    ///  2         /// 统一下单接口 3         ///  4         /// 钱数 5         /// 
6 public ActionResult GetAPI(string money) 7 { 8 try 9 {10 //一.系统本身自有的业务处理11 //1.必要信息的初始化12 string userId = Session["userId"].ToString(); //用户主键13 UserInfor userInfor = db.Set
().Where(a => a.id == userId).FirstOrDefault();14 string orderId = GenerateOrderNum(); //生成订单号15 string totalFee = money;//设置默认商品费用为【1分】16 string nonceStr = TenPayV3Util.GetNoncestr(); //获取 随机字符串17 string openid = userInfor.openId;18 //2.自己商户系统下单19 OrderInfor orderInfor = new OrderInfor();20 orderInfor.id = orderId;21 orderInfor.uid = userInfor.id;22 orderInfor.goodName = "测试商品";23 orderInfor.goodPrice = totalFee;24 orderInfor.addTime = DateTime.Now;25 orderInfor.status = "0"; //已经下单,但未付款26 db.Set
().Add(orderInfor);27 db.SaveChanges();28 29 30 //二.微信系统下单31 //1.创建支付应答对象并初始化32 RequestHandler packageReqHandler = new RequestHandler(null);33 packageReqHandler.Init();34 //1.1设置统一下单的参数35 packageReqHandler.SetParameter("appid", ConfigHelp.AppSettings("AppId")); //公众账号ID36 packageReqHandler.SetParameter("mch_id", ConfigHelp.AppSettings("MchId")); //商户号37 packageReqHandler.SetParameter("nonce_str", nonceStr); //随机字符串38 packageReqHandler.SetParameter("body", "科技-服务"); //商品描述39 packageReqHandler.SetParameter("out_trade_no", orderId); //商户订单号40 packageReqHandler.SetParameter("total_fee", totalFee); //商品金额,以分为单位41 packageReqHandler.SetParameter("spbill_create_ip", Request.UserHostAddress); //终端IP42 packageReqHandler.SetParameter("notify_url", ConfigHelp.AppSettings("notify_url")); //微信支付异步通知回调地址43 packageReqHandler.SetParameter("trade_type", "JSAPI"); //交易类型 代表公众号支付44 packageReqHandler.SetParameter("openid", openid); //用户标识45 string sign = packageReqHandler.CreateMd5Sign("key", ConfigHelp.AppSettings("key")); //预支付签名46 packageReqHandler.SetParameter("sign", sign);47 //1.2 下单数据格式转换48 string data = packageReqHandler.ParseXML();49 //1.3 进行下单50 string result = TenPayV3.Unifiedorder(data);51 //2.对下单返回结果进行分析52 XDocument res = XDocument.Parse(result);53 //2.1 对返回结果进行判断54 55 //2.2 成功的情况下获取必要的参数56 string prepayId = res.Element("xml").Element("prepay_id").Value; //获取预支付订单编号prepayId57 //3. 获取支付参数并签名58 string timeStamp = TenPayV3Util.GetTimestamp(); //获取时间戳59 //设置支付参数60 RequestHandler paySignReqHandler = new RequestHandler(null);61 paySignReqHandler.SetParameter("appId", ConfigHelp.AppSettings("AppId"));62 paySignReqHandler.SetParameter("timeStamp", TenPayV3Util.GetTimestamp());63 paySignReqHandler.SetParameter("nonceStr", nonceStr);64 paySignReqHandler.SetParameter("package", string.Format("prepay_id={0}", prepayId));65 paySignReqHandler.SetParameter("signType", "MD5"); //签名【MD5】66 string paySign = paySignReqHandler.CreateMd5Sign("key", ConfigHelp.AppSettings("key")); //JSAPI支付签名67 var payData = new68 {69 appId = ConfigHelp.AppSettings("AppId"),70 timeStamp = timeStamp,71 nonceStr = nonceStr,72 package = string.Format("prepay_id={0}", prepayId),73 signType = "MD5",74 paySign = paySign,75 };76 return Json(new77 {78 status = "1",79 promptInfor = "微信下单成功",80 payData = payData,81 orderId = orderId82 });83 }84 catch (Exception ex)85 {86 string a = ex.Message;87 88 return Json(new89 {90 status = "0",91 promptInfor = a92 });93 }94 }

(4).微信异步通知接口

1   public ActionResult PayNotifyUrl() 2         { 3             //获取当前http请求 4             HttpContext httpContext = System.Web.HttpContext.Current; 5             ResponseHandler notifyDataHandler = new ResponseHandler(httpContext); 6             //返回状态码【SUCCESS/FAIL】此字段是通信标识 7             string return_code = notifyDataHandler.GetParameter("return_code"); 8             //返回信息【如非空,为错误原因】 9             string return_msg = notifyDataHandler.GetParameter("return_msg");10             //表示通信成功11             if (return_code == "SUCCESS")12             {13                 //获取业务结果【交易是否成功(SUCCESS/FAIL)】14                 string result_code = notifyDataHandler.GetParameter("result_code");15                 //表示业务结果成功16                 if (result_code == "SUCCESS")17                 {18                     //设置签名密钥19                     notifyDataHandler.SetKey(ConfigHelp.AppSettings("key"));20                     //验证请求是否从微信发过来(安全)【验证签名】21                     if (notifyDataHandler.IsTenpaySign())22                     {23                         //获取订单编号24                         string out_trade_no = notifyDataHandler.GetParameter("out_trade_no");25                         //检查是否返回商户订单号26                         if (!string.IsNullOrEmpty(out_trade_no))27                         {28                             try29                             {30                                 OrderInfor orderInfor = db.Set
().Where(a => a.id == out_trade_no).FirstOrDefault();31 if (orderInfor != null)32 {33 //这里需要根据订单号更改系统的业务34 //这里模拟测试记录订单号35 orderInfor.status = "1"; //表示付款成功,成功回调36 db.Entry(orderInfor).State = EntityState.Modified;37 db.SaveChanges();38 39 return_code = "SUCCESS";40 return_msg = "OK";41 }42 else43 {44 return_code = "FAIL";45 return_msg = "商户系统中不存在该订单";46 }47 }48 catch (Exception ex)49 {50 //系统异常51 return_code = "FAIL";52 return_msg = ex.Message;53 }54 }55 else56 {57 //支付结果中商户订单号不存在58 return_code = "FAIL";59 return_msg = "支付结果中商户订单号不存在";60 }61 }62 else63 {64 //签名失败65 return_code = "FAIL";66 return_msg = "签名失败";67 }68 }69 else70 {71 //交易失败72 return_code = "FAIL";73 return_msg = "交易失败";74 }75 }76 //商户处理后同步返回给微信参数77 string xml = string.Format(@"
", return_code, return_msg);78 //返回处理结果79 return Content(xml, "text/xml");80 }

(5).JSAPI接口请求

1  //公众号支付 2                                 WeixinJSBridge.invoke('getBrandWCPayRequest', jsonData.payData, function (res) { 3                                     // 使用以下方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 4                                     //【因此微信团队建议:】当收到ok返回时,向商户后台询问是否收到交易成功的通知, 5                                     //若收到通知,前端展示交易成功的界面; 6                                     //若此时未收到通知,商户后台主动调用查询订单接口,查询订单的当前状态,并反馈给前端展示相应的界面。 7                                     if (res.err_msg == "get_brand_wcpay_request:ok") { 8                                         //JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回 9                                         $.ajax({10                                             type: 'POST',11                                             url: '/WeiXinGz/QueryOrder',12                                             data: {13                                                 orderId: jsonData.orderId14                                             },15                                             cache: false,16                                             dataType: 'text',17                                             success: function (jsonData) {18                                                 if (jsonData == "ok") {19                                                     alert("支付成功", "提示", function () {20                                                         alert("页面跳转等业务处理");21                                                     });22                                                     mui('#pay').button('reset');23                                                 } else {24                                                     alert("支付失败,请稍后重试!如果收到支付通知,切勿重复支付1!");25                                                     mui('#pay').button('reset');26                                                 }27                                             },28                                             error: function (XMLHttpRequest, textStatus, errorThrown) {29                                                 alert("支付失败,请稍后重试!如果收到支付通知,切勿重复支付2!");30                                                 mui('#pay').button('reset');31                                             }32                                         });33                                     } else if (res.err_msg == "get_brand_wcpay_request:cancel") {34                                         //由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。35                                         alert("您放弃了支付");36                                         mui('#pay').button('reset');37                                     } else {38                                         //由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。39                                         alert("支付失败,请稍后重试!如果收到支付通知,切勿重复支付3!");40                                         mui('#pay').button('reset');41                                     }42                                 });
 
(6).微信订单查询接口
 
1  ///  2         /// 微信订单查询接口 3         ///  4         /// 订单编号id 5         /// 
6 //[WeixinInternalRequest("无法访问!")] 7 public ActionResult QueryOrder(string orderId) 8 { 9 try10 {11 //一.先查商户后台的订单状态,判断微信端是否异步通知商户后台了!!!12 OrderInfor orderInfor = db.Set
().Where(a => a.id == orderId).FirstOrDefault();13 //判断订单状态14 if (orderInfor.status == "1")15 {16 //表示查询成功17 return Content("ok");18 }19 else if (orderInfor == null || orderInfor.status != "1")20 {21 //二.进行调用下面的微信查询api进行查询22 //生成随机字符串23 string nonceStr = TenPayV3Util.GetNoncestr();24 RequestHandler packageReqHandler = new RequestHandler(null);25 //设置package订单参数26 packageReqHandler.SetParameter("appid", ConfigHelp.AppSettings("AppId")); //公众账号ID27 packageReqHandler.SetParameter("mch_id", ConfigHelp.AppSettings("MchId")); //商户号 28 packageReqHandler.SetParameter("out_trade_no", orderId); //填入商家订单号29 packageReqHandler.SetParameter("nonce_str", nonceStr); //随机字符串30 string sign = packageReqHandler.CreateMd5Sign("key", ConfigHelp.AppSettings("key"));//参数进行签名31 packageReqHandler.SetParameter("sign", sign); //参数中添加签名字符串 32 string data = packageReqHandler.ParseXML(); //将传的参数转化为XML格式字符串33 var result = TenPayV3.OrderQuery(data); //调用订单查询接口34 var res = XDocument.Parse(result);35 //返回状态码【SUCCESS/FAIL】此字段是通信标识36 string return_code = res.Element("xml").Element("return_code").Value;37 if (return_code == "SUCCESS")38 {39 //获取业务结果【交易是否成功(SUCCESS/FAIL)】40 string result_code = res.Element("xml").Element("result_code").Value;41 if (result_code == "SUCCESS")42 {43 //交易状态 44 /**SUCCESS—支付成功 45 *REFUND—转入退款 46 *NOTPAY—未支付 47 *CLOSED—已关闭 48 *REVOKED—已撤销(刷卡支付) 49 *USERPAYING--用户支付中 50 *PAYERROR--支付失败(其他原因,如银行返回失败)51 */52 string trade_state = res.Element("xml").Element("trade_state").Value;53 if (return_code == "SUCCESS")54 {55 return Content("ok");56 }57 }58 }59 60 }61 //未查询到该订单或者该订单交易状态不相符62 return Content("error");63 }64 catch (Exception ex)65 {66 //抛异常信息,返回异常消息67 return Content(ex.Message);68 }69 }
View Code

 

上述代码中,用到的openid,需要事先获取

 亲测好用,如有问题,可联系QQ 604649488
 
 
 
 
 
 
 
 

 

转载于:https://www.cnblogs.com/yaopengfei/p/6093316.html

你可能感兴趣的文章
sqlplus登陆方式说明
查看>>
窝里斗,只给微软看笑话
查看>>
递归函数打印斐波那契数列
查看>>
Too many open files 问题的解决
查看>>
CF976D. Degree Set
查看>>
I2C总线介绍及AT24C02驱动编写 笔记
查看>>
我的友情链接
查看>>
Nginx 在window server 2008R2上装有IIS启动不了
查看>>
C# 无法解析程序集
查看>>
利用expect实现交互登录
查看>>
Oracle服务器上Swap的配置
查看>>
MySQL复制
查看>>
laravel5.5+adminLte搭建后台
查看>>
PHP
查看>>
Python运行效率低的原因
查看>>
CentOS中zip压缩和unzip解压缩命令详解
查看>>
server 2008 r2 hyper-v 硬盘扩容
查看>>
Android之DOM解析XML
查看>>
关于字符串输入的问题
查看>>
NSD基础交换-子网划分
查看>>