<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width,minimum-scale=1,user-scalable=no,maximum- scale=1,initial-scale=1" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="format-detection" content="telephone=no" /> <script src="../js/jquery-1.7.2.min.js" type="text/javascript"></script> <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script type="text/javascript"> wx.config({ debug: false,// 为true时,启用调试功能,微信会把错误信息以alert的形式弹出 appId: '<%=WxConfig.AppID%>', // 必填,公众号的唯一标识 timestamp: <%=WxConfig.Timestamp%>,//时间戳 nonceStr: "<%=WxConfig.NonceStr%>",//随机字符串 signature: "<%=WxConfig.Signature%>", //权限签名 与微信支付签名没有半毛钱关系 jsApiList: [// 必填,需要使用的JS接口列表 'onMenuShareTimeline', 'onMenuShareAppMessage', 'getNetworkType', 'chooseWXPay' ] }); function callPay() { wx.chooseWXPay({ timestamp: <%=WxConfig.Timestamp%>, // 支付签名时间戳 nonceStr: "<%=WxConfig.NonceStr%>", // 支付签名随机串 package: "<%=WxConfig.Package%>", // 统一支付接口返回的package包 signType: "<%=WxConfig.SignType%>", // 签名方式,'MD5' paySign: "<%=WxConfig.PaySign %>", // 支付签名 success: function (res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok ,但并不保证它绝对可靠。 if (res.err_msg == "get_brand_wcpay_request:ok") { location.href = "<%=WxConfig.ReturnUrl%>?sp_billno=<%=sp_billno%>"; } else { alert("支付未完成"); } } }); } <%if (Flag == "1") {%> $(function () { callPay(); }); <%}%> </script> </head> <body> <form id="form2" runat="server"> <div id="block_top"> <span class="block_top_l"><a href="Index.aspx"></a></span> <h1>捐赠信息</h1> </div> <div class="login_btn"> <input type="button" id="rePay" onclick="callPay()" value="重新支付" /> </div> </form> </body>
</html>
public partial class pay3 : PageBase { public string Flag = "0"; public string sp_billno = string.Empty; public WxConfig WxConfig = new WxConfig(); public tb_Deposit Deposit = new tb_Deposit(); public int depId = 0; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { try { InitWxConfig();// 初始化微信公众号配置信息。 InitTacket();// 初始化捐赠票据。 InitPackage();// 初始化支付包参数。 } catch (Exception ex) { Log.Write(typeof(pay3), ex.Message, ex); } } } public void InitWxConfig() { WxConfig.Timestamp = TenpayUtil.getTimestamp(); WxConfig.NonceStr = TenpayUtil.getNoncestr(); WxConfig.SignType = "MD5"; WxConfig.PaySign = string.Empty; if (Session["openid"] == null || string.IsNullOrEmpty(Session["openid"].ToString())) { GetOpenId(); } WxConfig.OpenId = (string)Session["openid"]; } public void InitTacket() { string token = string.Empty; string ticket = string.Empty; if (!CacheHelper.TryGetCache<string>("access_token", out token)) { token = new HP.CPS.BLL.WeiXin.WXServices().Getaccesstoken(WxConfig.AppID, WxConfig.AppSecret); if (!string.IsNullOrEmpty(token)) { CacheHelper.SetCache("access_token", token, new TimeSpan(2, 0, 0)); } } WxConfig.Accesstoken = token; if (!CacheHelper.TryGetCache<string>("jsapi_ticket", out ticket)) { ticket = new HP.CPS.BLL.WeiXin.WXServices().Getjsapiticket(token); if (!string.IsNullOrEmpty(ticket)) { CacheHelper.SetCache("jsapi_ticket", ticket, new TimeSpan(2, 0, 0)); } } WxConfig.Jsapiticket = ticket; WxConfig.Signature = SHA1Util.getSha1(string.Format("jsapi_ticket={0}&noncestr={1}timestamp={2}&url={3}", ticket, WxConfig.NonceStr, WxConfig.Timestamp, Server.UrlEncode(Request.Url.ToString()))); } public void InitPackage() { if (int.TryParse(Convert.ToString(Request["id"]), out depId)) { Deposit = Factory.CreateFactory.CreateFundMgtBLL().Get_tb_DepositEntity(depId); sp_billno = Deposit.nv_donateCertificate; } else { Deposit = new tb_Deposit(); } int money = 0; money = Decimal.ToInt32(Deposit.m_donateAmount * 100); Hashtable Package = new Hashtable(); //请求参数集合 Package.Add("appid", WxConfig.AppID);//公众账号ID Package.Add("mch_id", WxConfig.PartnerId);//商户号 Package.Add("nonce_str", WxConfig.NonceStr);//随机字符串 Package.Add("body", Deposit.nv_projectTitle);//商品描述 Package.Add("out_trade_no", Deposit.nv_donateCertificate);//商户订单号 Package.Add("total_fee", money.ToString());//总金额 Package.Add("spbill_create_ip", Page.Request.UserHostAddress);//终端IP Package.Add("notify_url", WxConfig.NotifyUrl);//通知地址 Package.Add("trade_type", "JSAPI");//交易类型 Package.Add("openid", WxConfig.OpenId);//用户标识 WxConfig.PaySign = GetSin(Package, WxConfig.ApiToken); Package.Add("sign", WxConfig.PaySign);//签名 string pak = getXml(Package); string urlFormat = "https://api.mch.weixin.qq.com/pay/unifiedorder"; var result = PostDataToUrl.Post(urlFormat, pak); //接收微信返回的xml数据 var res = XDocument.Parse(result); if (res.Element("xml").Element("return_code").Value == "SUCCESS") { //下单成功返回 string repayId = res.Element("xml").Element("prepay_id").Value; WxConfig.Package = string.Format("prepay_id={0}", repayId); Flag = "1"; } } string GetSin(Hashtable ParametersTosin, string appkey) { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(ParametersTosin.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)ParametersTosin[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { sb.Append(k + "=" + v + "&"); } } sb.Append("key=" + appkey); return MD5Util.GetMD5(sb.ToString(), Request.ContentEncoding.BodyName).ToUpper(); } string getXml(Hashtable kvs) { string xml = "<xml>"; foreach (DictionaryEntry kv in kvs) { if (kv.Value != null) { xml += string.Format("<{0}>{1}</{0}>", kv.Key, kv.Value); } } xml += "</xml>"; return xml; } }
这是接收通知页面的代码逻辑,必须要把对通知处理的结果返回给微信。如果微信发送通知后收不到回复,会以每隔30分钟的频率,向通知页面发送8次通知。
protected void Page_Load(object sender, EventArgs e)
{ string postStr = ""; /// <summary> /// 微信支付回调 /// </summary> /// <param name="xml"></param> if (Request.HttpMethod.ToLower() == "post") { Stream s = System.Web.HttpContext.Current.Request.InputStream; byte[] b = new byte[s.Length]; s.Read(b, 0, (int)s.Length); postStr = Encoding.UTF8.GetString(b); if (!string.IsNullOrEmpty(postStr)) { var res = XDocument.Parse(postStr); if (res.Element("xml").Element("return_code").Value == "SUCCESS") { Response.Write(string.Format(@"<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>")); Response.End(); } Response.Write(string.Format(@"<xml><return_code><![CDATA[{0}]]></return_code><return_msg><![CDATA[{1}]]></return_msg></xml>", "FAIL", res.Element("xml").Element("return_msg").Value)); } } }
一定要注意微信配置项,和微信支付2.0不同的地方是要加一个api_token,这个参数从“微信支付商户平台”中配置,首先登陆商户平台,依次打开“账户设置”、“安全设置”、“API安全”,在API密钥中点击“设置密钥”按钮,自定义API密钥。
/// <summary> /// 微信配置类 /// </summary> public class WxConfig { /// <summary> /// 应用ID /// </summary> public string AppID { get { return (string)System.Configuration.ConfigurationManager.AppSettings["WXAppID"]; } } /// <summary> /// 应用密钥 /// </summary> public string AppSecret { get { return (string)System.Configuration.ConfigurationManager.AppSettings["WXAppSecret"]; } } /// <summary> /// API密钥(支付密钥) /// </summary> public string ApiToken { get { return (string)System.Configuration.ConfigurationManager.AppSettings["WXApiToken"]; } } /// <summary> /// 商户号 /// </summary> public string PartnerId { get { return (string)System.Configuration.ConfigurationManager.AppSettings["PartnerId"]; } } /// <summary> /// 接受通知的页面 /// </summary> public string NotifyUrl { get { return Convert.ToString(System.Configuration.ConfigurationManager.AppSettings["NotifyUrl"]); } } /// <summary> /// 支付后跳转的页面 /// </summary> public string ReturnUrl { get { return Convert.ToString(System.Configuration.ConfigurationManager.AppSettings["ReturnUrl"]); } } /// <summary> /// 用户唯一标识 /// </summary> public string OpenId { get; set; } /// <summary> /// 公众号的全局唯一票据 /// </summary> public string Accesstoken { get; set; } /// <summary> /// JS-SDK临时票据 /// </summary> public string Jsapiticket { get; set; } /// <summary> /// 时间戳 /// </summary> public string Timestamp { get; set; } /// <summary> /// 随机串 /// </summary> public string NonceStr { get; set; } /// <summary> /// JS-SDK权限验证的签名 /// </summary> public string Signature { get; set; } /// <summary> /// 支付包参数 /// </summary> public string Package { get; set; } /// <summary> /// 签名方式(新版微信支付为MD5) /// </summary> public string SignType { get; set; } /// <summary> /// 支付签名 /// </summary> public string PaySign { get; set; } }