asp.net 微信jsapi支付
来源:互联网 发布:数据爆炸时代 编辑:程序博客网 时间:2024/05/21 09:48
开始做jsapi支付时看了好多的demo及好多的博客感觉有大坑,果不其然,一点一点从坑中爬出。
- 前期准备,首先微信公众号中的配置,现在微信支付中配置好支付授权目录,先解释一下支付授权目录时做什么的,在微信发起支付时要获取用户的openid,而获取openid之前要获取一个code,而这个code是获取openid的凭证,而在获取code时微信会有一个回调页面而这个页面就是你的授权支付目录,如果这个目录不正确则后续没有办法进行。例如:你要支付的页面为www.weixin.com/wxpay/JsApiPayPage.aspx时,你需要将目录配置为www.weixin.com/wxpay/以免出现问题。
- 其次要配置的就是网页授权获取用户基本信息接口 这个配置的作用使你能访问到支付的接口及回调页面能够返回,其中的域名必须是备案的。
- 正式开始从坑中爬,首先介绍微信调试工具微信web开发工具调微信页面神器,微信网站都可以用这个工具。首先拿到微信支付demo然后各种运行然后不行,首先在default页面中的
<a href="http://paysdk.weixin.qq.com/example/ProductPage.aspx">JSAPI支付</a>
全部都是微信的链接而不是你project的目录,这里在example目录中发现了所有的目录,你可以将default页面的中链接改为exampe目录中的页面,也可以不用改,直接运行example中你想要的接口的页面。下面看到jsapipage.aspx就是jsapi的demo了。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="JsApiPayPage.aspx.cs" Inherits="WxPayAPI.JsApiPayPage" %><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <meta http-equiv="content-type" content="text/html;charset=utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>微信支付样例-JSAPI支付</title></head> <script type="text/javascript"> //调用微信JS api 支付 function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <%=wxJsApiParam%>,//josn串 function (res) { WeixinJSBridge.log(res.err_msg); alert(res.err_code + res.err_desc + res.err_msg); } ); } function callpay() { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } } else { jsApiCall(); } } </script><body> <form runat="server"> <br/> <div align="center"> <br/><br/><br/> <asp:Button ID="submit" runat="server" Text="立即支付" OnClientClick="callpay()" style="width:210px; height:50px; border-radius: 15px;background-color:#00CD00; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" /> </div> </form></body></html>
using System;using System.Collections.Generic;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Net;using System.IO;using System.Threading;using LitJson;using System.Web.Security;namespace WxPayAPI{ public partial class JsApiPayPage : System.Web.UI.Page { public static string wxJsApiParam {get;set;} //H5调起JS API参数 protected void Page_Load(object sender, EventArgs e) { Log.Info(this.GetType().ToString(), "page load"); if (!IsPostBack) { string openid = Request.QueryString["openid"]; string total_fee = Request.QueryString["total_fee"]; //检测是否给当前页面传递了相关参数 if (string.IsNullOrEmpty(openid) || string.IsNullOrEmpty(total_fee)) { Response.Write("<span style='color:#FF0000;font-size:20px'>" + "页面传参出错,请返回重试" + "</span>"); Log.Error(this.GetType().ToString(), "This page have not get params, cannot be inited, exit..."); submit.Visible = false; return; } //若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数 JsApiPay jsApiPay = new JsApiPay(this); jsApiPay.openid = openid; jsApiPay.total_fee = int.Parse(total_fee); //JSAPI支付预处理 try { WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(); wxJsApiParam = jsApiPay.GetJsApiParameters();//获取H5调起JS API参数 Log.Debug(this.GetType().ToString(), "wxJsApiParam : " + wxJsApiParam); //在页面上显示订单信息 Response.Write("<span style='color:#00CD00;font-size:20px'>订单详情:</span><br/>"); Response.Write("<span style='color:#00CD00;font-size:20px'>" + unifiedOrderResult.ToPrintStr() + "</span>"); } catch(Exception ex) { Response.Write("<span style='color:#FF0000;font-size:20px'>" + "下单失败,请返回重试" + "</span>"); submit.Visible = false; } } } }}
在这第一个坑,可以看到首先是获取querystring中的openid和total_fee
这两个参数是一个是关注微信的唯一标识和订单的价格,然而首先在获取openid这就是个坑,要获取openid首先要获取到code,在获取到code之后才能获取到openid和access_token。我的做法是在pageLode中加这个。
try { //调用【网页授权获取用户信息】接口获取用户的openid和access_token jsApiPay.GetOpenidAndAccessToken(); mOpenid = jsApiPay.openid; mAccess_token = jsApiPay.access_token; }catch (Exception ex) { Response.Write("<span style='color:#FF0000;font-size:20px'>" + ex.Message + "</span>"); }
其中GetOpenidAndAccessToken方法就有将获取code带码
/** * * 网页授权获取用户基本信息的全部过程 * 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html * 第一步:利用url跳转获取code * 第二步:利用code去获取openid和access_token * */ public void GetOpenidAndAccessToken() { if (!string.IsNullOrEmpty(page.Request.QueryString["code"])) { //获取code码,以获取openid和access_token string code = page.Request.QueryString["code"]; Log.Debug(this.GetType().ToString(), "Get code : " + code); GetOpenidAndAccessTokenFromCode(code); } else { //构造网页授权获取code的URL string host = page.Request.Url.Host; string path = page.Request.Path; string redirect_uri = HttpUtility.UrlEncode("http://www.weixin.com/wxpay.aspx"); WxPayData data = new WxPayData(); data.SetValue("appid", WxPayConfig.APPID); data.SetValue("redirect_uri", redirect_uri); data.SetValue("response_type", "code"); data.SetValue("scope", "snsapi_base"); data.SetValue("state", "STATE" + "#wechat_redirect"); string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl(); Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url); try { //触发微信返回code码 page.Response.Redirect(url);//Redirect函数会抛出ThreadAbortException异常,不用处理这个异常 } catch (System.Threading.ThreadAbortException ex) { } } }
其中首先会判断是否获取到了code,如果没有就会执行获取code操作,其中的redirect_uri就是回掉地址,会在这个页面返回code继续执行获取openid和access_token的操作。而在之前pageload中加的那段代码就是在同一个页面两次执行GetOpenidAndAccessToken方法。
4.下面是一个巨坑,当你获取到openid之后还有个非常重要的pay_sign要获取之后还有一个回调地址,这个地址是你在成功支付后微信返回的回调通知。每发起一次支付操作都要获取一次pay_sign操作,而这个参数是发起调用jsapi操作的必须的参数。
function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <%=wxJsApiParam%>,//josn串 function (res) { WeixinJSBridge.log(res.err_msg); alert(res.err_code + res.err_desc + res.err_msg); } ); }
就是<%=wxJsApiParam%>,而<%=wxJsApiParam%>是由
在demo中lib文件夹中的WxpayApi.cs中的UnifiedOrder方法中获取这些参数,而其中的回调页面的地址是写在配置文件中的 public const string NOTIFY_URL = “http://paysdk.weixin.qq.com/example/ResultNotifyPage.aspx“;而这个配置文件并不是webcofig是在lib中的config.cs中商户号等一系列的配置也在其中。之后就可以发起支付了。
5.最后一坑,支付成功后的返回,在js中只有一个
function (res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 switch (res.err_msg) { case "get_brand_wcpay_request:ok": alert("支付成功"); break; case "get_brand_wcpay_request:cancel": alert("支付取消"); //location.href = "JsApiPayPage.aspx?tepid=1"; break; default: alert("支付失败"); //location.href = "JsApiPayPage.aspx?tepid=2"; break; } }
真正的支付回调页面在ResultNotifyPage.aspx中,其中有回调支付的判断,更有返回的订单的信息,可以在这个页面对支付成功或失败的订单进行处理。
总结:微信jaspi的坑总算爬出来了,其中发起支付到最后的支付成功总共调用了4次接口。更深表demo很坑。
- asp.net 微信jsapi支付
- 微信JSAPI支付
- 微信 jsapi 支付
- 微信支付Jsapi支付
- 微信支付JSAPI支付
- asp.net mvc下实现微信公众号(JsApi)支付介绍
- 微信支付(JsApi)总结
- 微信JSAPI支付教程
- c# 微信jsapi支付
- 微信jsApi支付备忘
- thinkphp微信支付-JSAPI
- 微信JSAPI支付实现
- 微信支付V3.3.7(jsapi支付)
- 6.微信支付之JSAPI支付
- C# 微信支付之JSAPI支付
- 微信支付V3版(JSAPI)
- 微信JSAPI支付(JAVA版)
- jsapi微信支付v3版
- 真正解决问题:maven eclipse tomcat java.lang.ClassNotFoundException: org.springframework.web.context.Contex
- React Native在现有项目中的使用
- WPF解决界面全屏化但不遮挡任务栏的问题
- java基础进阶-------代理(Proxy)
- 网络编程序列2——C#TCP服务端代码实现一
- asp.net 微信jsapi支付
- CAP定理
- openssl移植
- 排序的稳定性和时间复杂度
- STM32单片机程序启动
- 第十周—小学生数学考试系统2
- TextView使用SpannableString设置复合文本
- 定义几个常见的术语(tkinter,Python3.x)
- Python-numpy逻辑报错:The truth value of an array with more than one element is ambiguous