2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 实例:用C#.NET手把手教你做微信公众号开发(20)--使用微信支付线上收款:jsapi方式

实例:用C#.NET手把手教你做微信公众号开发(20)--使用微信支付线上收款:jsapi方式

时间:2021-03-09 07:45:28

相关推荐

实例:用C#.NET手把手教你做微信公众号开发(20)--使用微信支付线上收款:jsapi方式

在做线上、线下销售时,可以使用微信便捷支付,通过微信公众号收款有很多种收款方式,如下图:

今天我们来讲一下jsapi支付,场景就是在微信内打开某个页面,完成在线支付,同样一个网页,使用微信打开就是jsapi方式,使用手机浏览器打开就是H5方式,我们下一篇讲H5方式。

一、操作演示

使用微信扫描下面图片,打开支付页面

在线收取1分钱,可以全流程感受

对CSDN的自动审核真的很无语,什么二维码都判定为违规图片,nnd,吐槽一下。

猿友们可以复制下面链接到微信对话框(如文件传输助手)后打开,即可体验支付全流程。

http://www.jjlm.ltd/weixinold/RedirectWithOpenIdFirst.aspx?final_url=WeixinPayRecvJsApiTest.aspx

二、微信支付配置

在本系列文章第18篇((2条消息) 实例:用C#.NET手把手教你做微信公众号开发(18)--使用微信支付给粉丝发红包_乱世刀疤的博客-CSDN博客)有介绍过,除了基础配置之外,以下配置是关键:

三、jsapi演示源码

首先要通过oauth获取微信用户openid(源码在讲完支付的篇幅之后给出)。

前端页面源码如下:

记得一定要引入:<script src="http://res./open/js/jweixin-1.2.0.js"></script>

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="WeixinPayRecvJsApiTest.aspx.cs" Inherits="Jjlm.WeixinPayRecvJsApiTest" %><!DOCTYPE html><html xmlns="/1999/xhtml"><head runat="server"><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"><script src="/jquery-latest.js"></script><script src="/jquery/2.1.1/jquery.min.js"></script><script src="/bootstrap/3.3.7/js/bootstrap.min.js"></script><link rel="stylesheet" href="mui-master/dist/css/mui.min.css"><script src="mui-master/dist/js/mui.min.js"></script><script src="http://res./open/js/jweixin-1.2.0.js"></script><title>微信支付JsApi收款测试</title></head><style>img{width: 100%;display: block;}body{margin:0;padding:0;background-image: url(img/maidanglao/bg.jpg);background-repeat: no-repeat;background-size: 100% 100%;}.line{display: flex;justify-content:space-between;height: 40px;margin: 0 20px;}.boline{border-bottom: 1px solid #ddd;}.ti{font-size: 18px;line-height: 40px;}.text{font-size: 16px;line-height: 40px;}</style><script type="text/javascript">//调用微信JS api 支付function jsApiCall(){WeixinJSBridge.invoke('getBrandWCPayRequest',<%=wxJsApiParam%>,//json串function (res) {/*if(res.err_msg == "get_brand_wcpay_request:ok" )//支付成功返回{alert("支付成功");}else{alert("支付失败");}*///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><div style="width: 100%;background:#555;color:#fff;font-size:20px;height: 40px;line-height: 40px;text-align: center;">收银台</div><form id="form1" runat="server"><div><div style="margin-top:10px;background: #fff;"><div class="line boline"><span class="ti">订单号:</span><asp:Label runat="server" id="lbBillNo" Text="" Visible="true" class="text" /></div><div class="line boline"><span class="ti">商品名称:</span><asp:Label runat="server" id="lbproductname" Text="" Visible="true" class="text" /></div><div class="line boline"><span class="ti">商品数量: </span><asp:Label runat="server" id="product_num" Text="1" Visible="true" class="text" /></div><div class="line"><span class="ti">支付金额:</span><asp:Label runat="server" id="lbtotal_fee" Text="0.01" Visible="true" class="text" style="color: crimson;" /></div></div><div style="margin: 10px auto;"><img src="img/wxzf.jpg" alt="" style="width: 100%;"></div><div style="margin: 10px auto;width: 90%;height: 40px;background: #20a91d;border-radius:10px;text-align: center;" runat="server" id="divBtn"><asp:Button ID="submit" runat="server" Text="立即支付" width="100%" Style="background: #20a91d;border-width:0px;color: #fff;line-height: 40px;font-size: 20px;" OnClick="btnCallPayClick"/></div></br><center><asp:HyperLink ID="hlSeeOrder" runat="server" Visible="false"><asp:Label runat="server" id="lbResult" Text="点击此处查看订单"></asp:Label></asp:HyperLink></center><asp:Label runat="server" id="lbopenid" Visible="false"></asp:Label></div></form></body></html>

后端源码如下:

using System;using System.Collections.Generic;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using ;using System.IO;using System.Threading;using LitJson;using System.Web.Security;using System.Data;using System.Data.SqlClient;using System.Text;using QinMing.Config;using QinMing.WeixinPayCollect;namespace Jjlm{public partial class WeixinPayRecvJsApiTest : System.Web.UI.Page{public static string wxJsApiParam {get;set;} //H5调起JS API参数protected void Page_Load(object sender, EventArgs e){lbBillNo.Text = DateTime.Now.ToString("yyyyMMddHHmmssms");lbproductname.Text = "微信支付JsApi收款测试";lbopenid.Text = Request.QueryString["open_id"]; }protected void btnCallPayClick(object sender, EventArgs e){string fee = (Convert.ToDouble(lbtotal_fee.Text)*100).ToString(); ///微信单位分string out_trade_no = lbBillNo.Text;//若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数JsApiPay jsApiPay = new JsApiPay(this);jsApiPay.openid = lbopenid.Text;jsApiPay.total_fee = int.Parse(fee);try{//使用预先生成好的订单编号out_trade_noWxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(out_trade_no, lbproductname.Text);wxJsApiParam = jsApiPay.GetJsApiParameters();//获取H5调起JS API参数 Log.Debug(this.GetType().ToString(), "wxJsApiParam : " + wxJsApiParam);//调用前台javascript支付函数this.Page.ClientScript.RegisterStartupScript(this.Page.GetType(), "", "<script language='javascript'>callpay();</script>", false); ///调用前台callpay()函数完成支付//Thread.Sleep(3000);divBtn.Visible = false; //EnabledhlSeeOrder.Visible = true;hlSeeOrder.NavigateUrl = "MyOrderList.aspx?openid=" + lbopenid.Text;}catch(Exception ex){Log.showlog("zhifu_callpay","下订单失败请返回重试"+ex.ToString());submit.Visible = false;}}}}

四、所用数据表

CREATE TABLE weixin_pay_collect_record(open_id nvarchar(50), --微信用户openidnonce_str nvarchar(32), --微信支付参数result_code nvarchar(20), --支付动作返回结果is_subscribe nvarchar(2), --是否关注公众号,未关注公众号的微信用户也能支付trade_type nvarchar(20), --交易类型bank_type nvarchar(20), --银行类型total_fee int NULL, --交易金额,单位:分cash_fee int NULL, --现金金额transaction_id nvarchar(50), --微信内支付编码out_trade_no nvarchar(50),--应用方自定的交易编码time_end nvarchar(20),--完成时间input_time datetime NULL, --记录生成时间mark nvarchar(10)--备注)

五、收款类源码

using System;using System.Collections;using System.Collections.Generic;using System.Web;using System.Web.UI;using System.Web.Security;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls.WebParts;using ;using .Security; using System.IO;using System.Text;using System.Xml;using System.Security.Cryptography;using System.Security.Authentication;using System.Security.Cryptography.X509Certificates;using LitJson;using System.Runtime.Serialization;using System.Data;using System.Data.SqlClient;using QinMing.Config;using QinMing.Tools;using QinMing.WeixinContainer;namespace QinMing.WeixinPayCollect{/*** 配置账号信息*/public class WxPayConfig{//=======【基本信息设置】=====================================/* 微信公众号信息配置* APPID:绑定支付的APPID(必须配置)* MCHID:商户号(必须配置)* KEY:商户支付密钥,参考开户邮件设置(必须配置)* APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置)*/public const string APPID = QinMingConfig.Weixin_AppId;public const string MCHID = QinMingConfig.Weixin_MchId;public const string KEY = QinMingConfig.Weixin_MchIdKey;public const string APPSECRET = QinMingConfig.Weixin_AppSecret;//=======【证书路径设置】===================================== /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)*/public const string SSLCERT_PATH = QinMingConfig.certPath; //cert/apiclient_cert.p12public const string SSLCERT_PASSWORD = QinMingConfig.Weixin_OperationPassword;//=======【支付结果通知url】===================================== /* 支付结果通知回调url,用于商户接收支付结果*/public const string NOTIFY_URL = "/weixin/WeixinPayRecvResultNotify.aspx";//=======【商户系统后台机器IP】===================================== /* 此参数可手动配置也可在程序中自动获取*/public const string IP = "8.8.8.8";//=======【代理服务器设置】===================================/* 默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置)*/public const string PROXY_URL = "http://10.152.18.220:8080";//=======【上报信息配置】===================================/* 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报*/public const int REPORT_LEVENL = 1;//=======【日志级别】===================================/* 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息*/public const int LOG_LEVENL = 3;}/// <summary>/// 回调处理基类/// 主要负责接收微信支付后台发送过来的数据,对数据进行签名验证/// 子类在此类基础上进行派生并重写自己的回调处理过程/// </summary>public class Notify{public Page page {get;set;}public Notify(Page page){this.page = page;}/// <summary>/// 接收从微信支付后台发送过来的数据并验证签名/// </summary>/// <returns>微信支付后台返回的数据</returns>public WxPayData GetNotifyData(){//接收从微信后台POST过来的数据System.IO.Stream s = page.Request.InputStream;int count = 0;byte[] buffer = new byte[1024];StringBuilder builder = new StringBuilder();while ((count = s.Read(buffer, 0, 1024)) > 0){builder.Append(Encoding.UTF8.GetString(buffer, 0, count));}s.Flush();s.Close();s.Dispose();Log.Info(this.GetType().ToString(), "Receive data from WeChat : " + builder.ToString());//转换数据格式并验证签名WxPayData data = new WxPayData();try{data.FromXml(builder.ToString());}catch(WxPayException ex){//若签名错误,则立即返回结果给微信支付后台WxPayData res = new WxPayData();res.SetValue("return_code", "FAIL");res.SetValue("return_msg", ex.Message);Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml());page.Response.Write(res.ToXml());page.Response.End();}Log.Info(this.GetType().ToString(), "Check sign success");return data;}//派生类需要重写这个方法,进行不同的回调处理public virtual void ProcessNotify(){}}/// <summary>/// 支付结果通知回调处理类/// 负责接收微信支付后台发送的支付结果并对订单有效性进行验证,将验证结果反馈给微信支付后台/// </summary>public class ResultNotify:Notify{public ResultNotify(Page page):base(page){}public override void ProcessNotify(){WxPayData notifyData = GetNotifyData();//检查支付结果中transaction_id是否存在if (!notifyData.IsSet("transaction_id")){//若transaction_id不存在,则立即返回结果给微信支付后台WxPayData res = new WxPayData();res.SetValue("return_code", "FAIL");res.SetValue("return_msg", "支付结果中微信订单号不存在");Log.Error(this.GetType().ToString(), "The Pay result is error : " + res.ToXml());page.Response.Write(res.ToXml());page.Response.End();}string transaction_id = notifyData.GetValue("transaction_id").ToString();//查询订单,判断订单真实性if (!QueryOrder(transaction_id)){//若订单查询失败,则立即返回结果给微信支付后台WxPayData res = new WxPayData();res.SetValue("return_code", "FAIL");res.SetValue("return_msg", "订单查询失败");Log.Error(this.GetType().ToString(), "Order query failure : " + res.ToXml());page.Response.Write(res.ToXml());page.Response.End();}//查询订单成功else{if(notifyData.GetValue("return_code").ToString() == "SUCCESS"){//判断支付是否成功,成功则插入支付记录。SqlConnection Conn = new SqlConnection(QinMingConfig.DatabaseConnStr);Conn.Open();SqlCommand Comm = new SqlCommand();Comm.Connection = Conn;SqlDataReader dr;mandText = "insert into weixin_pay_collect_record "+ "(open_id,nonce_str,result_code,is_subscribe,trade_type,bank_type,total_fee,cash_fee,transaction_id,out_trade_no,time_end,input_time,mark) values "+ "('"+ notifyData.GetValue("openid").ToString() +"','"+ notifyData.GetValue("nonce_str").ToString() +"', "+ "'"+ notifyData.GetValue("result_code").ToString() +"','"+ notifyData.GetValue("is_subscribe").ToString() +"', "+ "'"+ notifyData.GetValue("trade_type").ToString() +"','"+ notifyData.GetValue("bank_type").ToString() +"', "+ notifyData.GetValue("total_fee").ToString() +","+ notifyData.GetValue("cash_fee").ToString() +", "+ "'"+ notifyData.GetValue("transaction_id").ToString() +"','"+ notifyData.GetValue("out_trade_no").ToString() +"', "+ "'"+ notifyData.GetValue("time_end").ToString() +"', "+ "GETDATE(),'') ";Comm.ExecuteScalar();if (Conn.State == ConnectionState.Open){Conn.Close();Conn.Dispose();}}WxPayData res = new WxPayData();res.SetValue("return_code", "SUCCESS");res.SetValue("return_msg", "OK");Log.Info(this.GetType().ToString(), "order query success : " + res.ToXml());page.Response.Write(res.ToXml());page.Response.End();}}//查询订单private bool QueryOrder(string transaction_id){WxPayData req = new WxPayData();req.SetValue("transaction_id", transaction_id);WxPayData res = WxPayApi.OrderQuery(req);if (res.GetValue("return_code").ToString() == "SUCCESS" &&res.GetValue("result_code").ToString() == "SUCCESS"){return true;}else{return false;}}}/*JsApi支付方式实现类,微信app内发起的支付模式*/public class JsApiPay{/// <summary>/// 保存页面对象,因为要在类的方法中使用Page的Request对象/// </summary>private Page page {get;set;}/// <summary>/// openid用于调用统一下单接口/// </summary>public string openid { get; set; }/// <summary>/// access_token用于获取收货地址js函数入口参数/// </summary>public string access_token { get; set; }/// <summary>/// 商品金额,用于统一下单/// </summary>public int total_fee { get; set; }/// <summary>/// 统一下单接口返回结果/// </summary>public WxPayData unifiedOrderResult { get; set; } public JsApiPay(Page page){this.page = page;}/*** * 网页授权获取用户基本信息的全部过程* 详情请参看网页授权获取用户基本信息:http://mp./wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html* 第一步:利用url跳转获取code* 第二步:利用code去获取openid和access_token* */public void GetOpenidAndAccessToken(){if (!string.IsNullOrEmpty(page.Request.QueryString["code"])){//获取code码,以获取openid和access_tokenstring code = page.Request.QueryString["code"];Log.Debug(this.GetType().ToString(), "Get code : " + code);GetOpenidAndAccessTokenFromCode(code);}else{//构造网页授权获取code的URLstring host = page.Request.Url.Host;string path = page.Request.Path;string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);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./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换取网页授权access_token和openid的返回数据,正确时返回的JSON数据包如下:* {* "access_token":"ACCESS_TOKEN",* "expires_in":7200,* "refresh_token":"REFRESH_TOKEN",* "openid":"OPENID",* "scope":"SCOPE",* "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"* }* 其中access_token可用于获取共享收货地址* openid是微信支付jsapi支付接口统一下单时必须的参数* 更详细的说明请参考网页授权获取用户基本信息:http://mp./wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html* @失败时抛异常WxPayException*/public void GetOpenidAndAccessTokenFromCode(string code){try{//构造获取openid及access_token的urlWxPayData data = new WxPayData();data.SetValue("appid", WxPayConfig.APPID);data.SetValue("secret", WxPayConfig.APPSECRET);data.SetValue("code", code);data.SetValue("grant_type", "authorization_code");string url = "https://api./sns/oauth2/access_token?" + data.ToUrl();//请求url以获取数据string result = HttpService.Get(url);Log.Debug(this.GetType().ToString(), "GetOpenidAndAccessTokenFromCode response : " + result);//保存access_token,用于收货地址获取JsonData jd = JsonMapper.ToObject(result);access_token = (string)jd["access_token"];//获取用户openidopenid = (string)jd["openid"];Log.Debug(this.GetType().ToString(), "Get openid : " + openid);Log.Debug(this.GetType().ToString(), "Get access_token : " + access_token);}catch (Exception ex){Log.Error(this.GetType().ToString(), ex.ToString());throw new WxPayException(ex.ToString());}}/*** 调用统一下单,获得下单结果* @return 统一下单结果* @失败时抛异常WxPayException*/public WxPayData GetUnifiedOrderResult(string out_trade_no, string product_name){//统一下单WxPayData data = new WxPayData();//data.SetValue("body", "test_body");data.SetValue("body", product_name);data.SetValue("attach", "");//data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());data.SetValue("out_trade_no", out_trade_no);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", "");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;}/*** * 从统一下单成功返回的数据中获取微信浏览器调起jsapi支付所需的参数,* 微信浏览器调起JSAPI时的输入参数格式如下:* {* "appId" : "wx2421b1c4370ec43b",//公众号名称,由商户传入* "timeStamp":" 1395712654", //时间戳,自1970年以来的秒数* "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串* "package" : "prepay_id=u802345jgfjsdfgsdg888",* "signType" : "MD5", //微信签名方式: * "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 * }* @return string 微信浏览器调起JSAPI时的输入参数,json格式可以直接做参数用* 更详细的说明请参考网页端调起支付API:http://pay./wiki/doc/api/jsapi.php?chapter=7_7* */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());//增加测试//jsApiParam.SetValue("out_trade_no", unifiedOrderResult.GetValue("out_trade_no"));string parameters = jsApiParam.ToJson();Log.Debug(this.GetType().ToString(), "Get jsApiParam : " + parameters);return parameters;}/*** * 获取收货地址js函数入口参数,详情请参考收货地址共享接口:http://pay./wiki/doc/api/jsapi.php?chapter=7_9* @return string 共享收货地址js函数需要的参数,json格式可以直接做参数使用*/public string GetEditAddressParameters(){string parameter = "";try{string host = page.Request.Url.Host;string path = page.Request.Path;string queryString = page.Request.Url.Query;//这个地方要注意,参与签名的是网页授权获取用户信息时微信后台回传的完整urlstring url = "http://" + host + path + queryString;//构造需要用SHA1算法加密的数据WxPayData signData = new WxPayData();signData.SetValue("appid",WxPayConfig.APPID);signData.SetValue("url", url);signData.SetValue("timestamp",WxPayApi.GenerateTimeStamp());signData.SetValue("noncestr",WxPayApi.GenerateNonceStr());signData.SetValue("accesstoken",access_token);string param = signData.ToUrl();Log.Debug(this.GetType().ToString(), "SHA1 encrypt param : " + param);//SHA1加密string addrSign = FormsAuthentication.HashPasswordForStoringInConfigFile(param, "SHA1");Log.Debug(this.GetType().ToString(), "SHA1 encrypt result : " + addrSign);//获取收货地址js函数入口参数WxPayData afterData = new WxPayData();afterData.SetValue("appId",WxPayConfig.APPID);afterData.SetValue("scope","jsapi_address");afterData.SetValue("signType","sha1");afterData.SetValue("addrSign",addrSign);afterData.SetValue("timeStamp",signData.GetValue("timestamp"));afterData.SetValue("nonceStr",signData.GetValue("noncestr"));//转为json格式parameter = afterData.ToJson();Log.Debug(this.GetType().ToString(), "Get EditAddressParam : " + parameter);}catch (Exception ex){Log.Error(this.GetType().ToString(), ex.ToString());throw new WxPayException(ex.ToString());}return parameter;}}/*H5支付方式实现类,任何浏览器内发起的微信支付模式*/public class H5Pay{public WxPayData unifiedOrderResult { get; set; } public string GetPayUrl(string thip){Log.Info(this.GetType().ToString(), "H5 pay url is producing...");WxPayData data = new WxPayData();data.SetValue("body","testproduct");//这里替换成你的数据data.SetValue("attach", "testproduct1");//这里替换成你的数据data.SetValue("out_trade_no",DateTime.Now.ToString("yyyyMMddHHmmssms"));//这里替换成你的数据data.SetValue("total_fee","1");//这里替换成你的数据data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));data.SetValue("spbill_create_ip",thip);//终端IPdata.SetValue("trade_type", "MWEB");//交易类型data.SetValue("scene_info", "{'h5_info':{'type':'Wap','wap_url':'www.jjlm.ltd','wap_name':'降价联盟'}}");//场景信息WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口//return result.ToXml();if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "" || result.GetValue("mweb_url").ToString() == ""){Log.Error(this.GetType().ToString(), "UnifiedOrder response error!");throw new WxPayException("UnifiedOrder response error!");}string url = result.GetValue("mweb_url").ToString();//获得统一下单接口返回的链接Log.Info(this.GetType().ToString(), "Get H5 pay url : " + url);unifiedOrderResult = result;return url;}public string GetPayUrl(string thip,string total_fee,string out_trade_no,string product_id,string productname){Log.Info(this.GetType().ToString(), "H5 pay url is producing...");WxPayData data = new WxPayData();data.SetValue("body",productname);//这里替换成你的数据data.SetValue("attach", product_id);//这里替换成你的数据data.SetValue("out_trade_no",out_trade_no);//这里替换成你的数据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("spbill_create_ip",thip);//终端IPdata.SetValue("trade_type", "MWEB");//交易类型data.SetValue("scene_info", "{'h5_info':{'type':'Wap','wap_url':'www.jjlm.ltd','wap_name':'降价联盟'}}");//场景信息WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口//return result.ToXml();if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "" || result.GetValue("mweb_url").ToString() == ""){Log.Error(this.GetType().ToString(), "UnifiedOrder response error!");throw new WxPayException("UnifiedOrder response error!");}string url = result.GetValue("mweb_url").ToString();//获得统一下单接口返回的链接Log.Info(this.GetType().ToString(), "Get H5 pay url : " + url);unifiedOrderResult = result;return url;}}public class Log{//在网站根目录下创建日志目录public static string path = HttpContext.Current.Request.PhysicalApplicationPath + "logs";/*** 向日志文件写入调试信息* @param className 类名* @param content 写入内容*/public static void Debug(string className, string content){if(WxPayConfig.LOG_LEVENL >= 3){WriteLog("DEBUG", className, content);}}/*** 向日志文件写入运行时信息* @param className 类名* @param content 写入内容*/public static void Info(string className, string content){if (WxPayConfig.LOG_LEVENL >= 2){WriteLog("INFO", className, content);}}/*** 向日志文件写入出错信息* @param className 类名* @param content 写入内容*/public static void Error(string className, string content){if(WxPayConfig.LOG_LEVENL >= 1){WriteLog("ERROR", className, content);}}public static void showlog(string className, string content){WriteLog("showlog", className, content);}/*** 实际的写日志操作* @param type 日志记录类型* @param className 类名* @param content 写入内容*/protected static void WriteLog(string type, string className, string content){if(!Directory.Exists(path))//如果日志目录不存在就创建{Directory.CreateDirectory(path);}string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");//获取当前系统时间string filename = path + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";//用日期对日志文件命名//创建或打开日志文件,向日志文件末尾追加记录StreamWriter mySw = File.AppendText(filename); //向日志文件写入内容string write_content = time + " " + type + " " + className + ": " + content;mySw.WriteLine(write_content);//关闭日志文件mySw.Close();}}public class WxPayException : Exception {public WxPayException(string msg) : base(msg) {}}/// <summary>/// http连接基础类,负责底层的http通信/// </summary>public class HttpService{public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors){//直接确认,否则打不开 return true;}public static string Post(string xml, string url, bool isUseCert, int timeout){System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接string result = "";//返回结果HttpWebRequest request = null;HttpWebResponse response = null;Stream reqStream = null;try{//设置最大连接数ServicePointManager.DefaultConnectionLimit = 200;//设置https验证方式if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)){ServicePointManager.ServerCertificateValidationCallback =new RemoteCertificateValidationCallback(CheckValidationResult);}/**************************************************************** 下面设置HttpWebRequest的相关属性* ************************************************************/request = (HttpWebRequest)WebRequest.Create(url);request.Method = "POST";request.Timeout = timeout * 1000;//设置代理服务器//WebProxy proxy = new WebProxy();//定义一个网关对象//proxy.Address = new Uri(WxPayConfig.PROXY_URL); //网关服务器端口:端口//request.Proxy = proxy;//设置POST的数据类型和长度request.ContentType = "text/xml";byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);request.ContentLength = data.Length;//是否使用证书if (isUseCert){string path = HttpContext.Current.Request.PhysicalApplicationPath;X509Certificate2 cert = new X509Certificate2(path + WxPayConfig.SSLCERT_PATH, WxPayConfig.SSLCERT_PASSWORD);request.ClientCertificates.Add(cert);Log.Debug("WxPayApi", "PostXml used cert");}//往服务器写入数据reqStream = request.GetRequestStream();reqStream.Write(data, 0, data.Length);reqStream.Close();//获取服务端返回response = (HttpWebResponse)request.GetResponse();//获取服务端返回数据StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);result = sr.ReadToEnd().Trim();sr.Close();}catch (System.Threading.ThreadAbortException e){Log.Error("HttpService", "Thread - caught ThreadAbortException - resetting.");Log.Error("Exception message: {0}", e.Message);System.Threading.Thread.ResetAbort();}catch (WebException e){Log.Error("HttpService", e.ToString());if (e.Status == WebExceptionStatus.ProtocolError){Log.Error("HttpService", "StatusCode : " + ((HttpWebResponse)e.Response).StatusCode);Log.Error("HttpService", "StatusDescription : " + ((HttpWebResponse)e.Response).StatusDescription);}throw new WxPayException(e.ToString());}catch (Exception e){Log.Error("HttpService", e.ToString());throw new WxPayException(e.ToString());}finally{//关闭连接和流if (response != null){response.Close();}if(request != null){request.Abort();}}return result;}/// <summary>/// 处理http GET请求,返回数据/// </summary>/// <param name="url">请求的url地址</param>/// <returns>http GET成功后返回的数据,失败抛WebException异常</returns>public static string Get(string url){System.GC.Collect();string result = "";HttpWebRequest request = null;HttpWebResponse response = null;//请求url以获取数据try{//设置最大连接数ServicePointManager.DefaultConnectionLimit = 200;//设置https验证方式if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)){ServicePointManager.ServerCertificateValidationCallback =new RemoteCertificateValidationCallback(CheckValidationResult);}/**************************************************************** 下面设置HttpWebRequest的相关属性* ************************************************************/request = (HttpWebRequest)WebRequest.Create(url);request.Method = "GET";//设置代理//WebProxy proxy = new WebProxy();//proxy.Address = new Uri(WxPayConfig.PROXY_URL);//request.Proxy = proxy;//获取服务器返回response = (HttpWebResponse)request.GetResponse();//获取HTTP返回数据StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);result = sr.ReadToEnd().Trim();sr.Close();}catch (System.Threading.ThreadAbortException e){Log.Error("HttpService","Thread - caught ThreadAbortException - resetting.");Log.Error("Exception message: {0}", e.Message);System.Threading.Thread.ResetAbort();}catch (WebException e){Log.Error("HttpService", e.ToString());if (e.Status == WebExceptionStatus.ProtocolError){Log.Error("HttpService", "StatusCode : " + ((HttpWebResponse)e.Response).StatusCode);Log.Error("HttpService", "StatusDescription : " + ((HttpWebResponse)e.Response).StatusDescription);}throw new WxPayException(e.ToString());}catch (Exception e){Log.Error("HttpService", e.ToString());throw new WxPayException(e.ToString());}finally{//关闭连接和流if (response != null){response.Close();}if (request != null){request.Abort();}}return result;}}/// <summary>/// 微信支付协议接口数据类,所有的API接口通信都依赖这个数据结构,/// 在调用接口之前先填充各个字段的值,然后进行接口通信,/// 这样设计的好处是可扩展性强,用户可随意对协议进行更改而不用重新设计数据结构,/// 还可以随意组合出不同的协议数据包,不用为每个协议设计一个数据包结构/// </summary>public class WxPayData{public WxPayData(){}//采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();/*** 设置某个字段的值* @param key 字段名* @param value 字段值*/public void SetValue(string key, object value){m_values[key] = value;}/*** 根据字段名获取某个字段的值* @param key 字段名* @return key对应的字段值*/public object GetValue(string key){object o = null;m_values.TryGetValue(key, out o);return o;}/*** 判断某个字段是否已设置* @param key 字段名* @return 若字段key已被设置,则返回true,否则返回false*/public bool IsSet(string key){object o = null;m_values.TryGetValue(key, out o);if (null != o)return true;elsereturn false;}/*** @将Dictionary转成xml* @return 经转换得到的xml串* @throws WxPayException**/public string ToXml(){//数据为空时不能转化为xml格式if (0 == m_values.Count){Log.Error(this.GetType().ToString(), "WxPayData数据为空!");throw new WxPayException("WxPayData数据为空!");}string xml = "<xml>";foreach (KeyValuePair<string, object> pair in m_values){//字段值不能为null,会影响后续流程if (pair.Value == null){Log.Error(this.GetType().ToString(), "WxPayData内部含有值为null的字段!");throw new WxPayException("WxPayData内部含有值为null的字段!");}if (pair.Value.GetType() == typeof(int)){xml += "<" + pair.Key + ">" + pair.Value + "</" + pair.Key + ">";}else if (pair.Value.GetType() == typeof(string)){xml += "<" + pair.Key + ">" + "<![CDATA[" + pair.Value + "]]></" + pair.Key + ">";}else//除了string和int类型不能含有其他数据类型{Log.Error(this.GetType().ToString(), "WxPayData字段数据类型错误!");throw new WxPayException("WxPayData字段数据类型错误!");}}xml += "</xml>";return xml;}/*** @将xml转为WxPayData对象并返回对象内部的数据* @param string 待转换的xml串* @return 经转换得到的Dictionary* @throws WxPayException*/public SortedDictionary<string, object> FromXml(string xml){if (string.IsNullOrEmpty(xml)){Log.Error(this.GetType().ToString(), "将空的xml串转换为WxPayData不合法!");throw new WxPayException("将空的xml串转换为WxPayData不合法!");}XmlDocument xmlDoc = new XmlDocument();xmlDoc.LoadXml(xml);XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>XmlNodeList nodes = xmlNode.ChildNodes;foreach (XmlNode xn in nodes){XmlElement xe = (XmlElement)xn;m_values[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中}try{//-06-29 错误是没有签名if(m_values["return_code"] != "SUCCESS"){return m_values;}CheckSign();//验证签名,不通过会抛异常}catch(WxPayException ex){throw new WxPayException(ex.Message);}return m_values;}/*** @Dictionary格式转化成url参数格式* @ return url格式串, 该串不包含sign字段值*/public string ToUrl(){string buff = "";foreach (KeyValuePair<string, object> pair in m_values){if (pair.Value == null){Log.Error(this.GetType().ToString(), "WxPayData内部含有值为null的字段!");throw new WxPayException("WxPayData内部含有值为null的字段!");}if (pair.Key != "sign" && pair.Value.ToString() != ""){buff += pair.Key + "=" + pair.Value + "&";}}buff = buff.Trim('&');return buff;}/*** @Dictionary格式化成Json* @return json串数据*/public string ToJson(){string jsonStr = JsonMapper.ToJson(m_values);return jsonStr;}/*** @values格式化成能在Web页面上显示的结果(因为web页面上不能直接输出xml格式的字符串)*/public string ToPrintStr(){string str = "";foreach (KeyValuePair<string, object> pair in m_values){if (pair.Value == null){Log.Error(this.GetType().ToString(), "WxPayData内部含有值为null的字段!");throw new WxPayException("WxPayData内部含有值为null的字段!");}str += string.Format("{0}={1}<br>", pair.Key, pair.Value.ToString());}Log.Debug(this.GetType().ToString(), "Print in Web Page : " + str);return str;}/*** @生成签名,详见签名生成算法* @return 签名, sign字段不参加签名*/public string MakeSign(){//转url格式string str = ToUrl();//在string后加入API KEYstr += "&key=" + WxPayConfig.KEY;//MD5加密var md5 = MD5.Create();var bs = puteHash(Encoding.UTF8.GetBytes(str));var sb = new StringBuilder();foreach (byte b in bs){sb.Append(b.ToString("x2"));}//所有字符转为大写return sb.ToString().ToUpper();}/*** * 检测签名是否正确* 正确返回true,错误抛异常*/public bool CheckSign(){//如果没有设置签名,则跳过检测if (!IsSet("sign")){Log.Error(this.GetType().ToString(), "WxPayData签名存在但不合法!");throw new WxPayException("WxPayData签名存在但不合法!");}//如果设置了签名但是签名为空,则抛异常else if(GetValue("sign") == null || GetValue("sign").ToString() == ""){Log.Error(this.GetType().ToString(), "WxPayData签名存在但不合法!");throw new WxPayException("WxPayData签名存在但不合法!");}//获取接收到的签名string return_sign = GetValue("sign").ToString();//在本地计算新的签名string cal_sign = MakeSign();if (cal_sign == return_sign){return true;}Log.Error(this.GetType().ToString(), "WxPayData签名验证错误!");throw new WxPayException("WxPayData签名验证错误!");}/*** @获取Dictionary*/public SortedDictionary<string, object> GetValues(){return m_values;}}/* 支付接口*/public class WxPayApi{/*** 提交被扫支付API* 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,* 由商户收银台或者商户后台调用该接口发起支付。* @param WxPayData inputObj 提交给被扫支付API的参数* @param int timeOut 超时时间* @throws WxPayException* @return 成功时返回调用结果,其他抛异常*/public static WxPayData Micropay(WxPayData inputObj, int timeOut = 10){string url = "https://api.mch./pay/micropay";//检测必填参数if (!inputObj.IsSet("body")){throw new WxPayException("提交被扫支付API接口中,缺少必填参数body!");}else if (!inputObj.IsSet("out_trade_no")){throw new WxPayException("提交被扫支付API接口中,缺少必填参数out_trade_no!");}else if (!inputObj.IsSet("total_fee")){throw new WxPayException("提交被扫支付API接口中,缺少必填参数total_fee!");}else if (!inputObj.IsSet("auth_code")){throw new WxPayException("提交被扫支付API接口中,缺少必填参数auth_code!");}inputObj.SetValue("spbill_create_ip", WxPayConfig.IP);//终端ipinputObj.SetValue("appid", WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串inputObj.SetValue("sign", inputObj.MakeSign());//签名string xml = inputObj.ToXml();var start = DateTime.Now;//请求开始时间Log.Debug("WxPayApi", "MicroPay request : " + xml);string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口以提交数据到APILog.Debug("WxPayApi", "MicroPay response : " + response);var end = DateTime.Now;int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时//将xml格式的结果转换为对象以返回WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** * 查询订单* @param WxPayData inputObj 提交给查询订单API的参数* @param int timeOut 超时时间* @throws WxPayException* @return 成功时返回订单查询结果,其他抛异常*/public static WxPayData OrderQuery(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./pay/orderquery";//检测必填参数if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id")){throw new WxPayException("订单查询接口中,out_trade_no、transaction_id至少填一个!");}inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串inputObj.SetValue("sign", inputObj.MakeSign());//签名string xml = inputObj.ToXml();var start = DateTime.Now;Log.Debug("WxPayApi", "OrderQuery request : " + xml);string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口提交数据Log.Debug("WxPayApi", "OrderQuery response : " + response);var end = DateTime.Now;int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时//将xml格式的数据转化为对象以返回WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** * 撤销订单API接口* @param WxPayData inputObj 提交给撤销订单API接口的参数,out_trade_no和transaction_id必填一个* @param int timeOut 接口超时时间* @throws WxPayException* @return 成功时返回API调用结果,其他抛异常*/public static WxPayData Reverse(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./secapi/pay/reverse";//检测必填参数if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id")){throw new WxPayException("撤销订单API接口中,参数out_trade_no和transaction_id必须填写一个!");}inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串inputObj.SetValue("sign", inputObj.MakeSign());//签名string xml = inputObj.ToXml();var start = DateTime.Now;//请求开始时间Log.Debug("WxPayApi", "Reverse request : " + xml);string response = HttpService.Post(xml, url, true, timeOut);Log.Debug("WxPayApi", "Reverse response : " + response);var end = DateTime.Now;int timeCost = (int)((end - start).TotalMilliseconds);WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** * 申请退款* @param WxPayData inputObj 提交给申请退款API的参数* @param int timeOut 超时时间* @throws WxPayException* @return 成功时返回接口调用结果,其他抛异常*/public static WxPayData Refund(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./secapi/pay/refund";//检测必填参数if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id")){throw new WxPayException("退款申请接口中,out_trade_no、transaction_id至少填一个!");}else if (!inputObj.IsSet("out_refund_no")){throw new WxPayException("退款申请接口中,缺少必填参数out_refund_no!");}else if (!inputObj.IsSet("total_fee")){throw new WxPayException("退款申请接口中,缺少必填参数total_fee!");}else if (!inputObj.IsSet("refund_fee")){throw new WxPayException("退款申请接口中,缺少必填参数refund_fee!");}else if (!inputObj.IsSet("op_user_id")){throw new WxPayException("退款申请接口中,缺少必填参数op_user_id!");}inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串inputObj.SetValue("sign", inputObj.MakeSign());//签名string xml = inputObj.ToXml();var start = DateTime.Now;Log.Debug("WxPayApi", "Refund request : " + xml);string response = HttpService.Post(xml, url, true, timeOut);//调用HTTP通信接口提交数据到APILog.Debug("WxPayApi", "Refund response : " + response);var end = DateTime.Now;int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时//将xml格式的结果转换为对象以返回WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** * 查询退款* 提交退款申请后,通过该接口查询退款状态。退款有一定延时,* 用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。* out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个* @param WxPayData inputObj 提交给查询退款API的参数* @param int timeOut 接口超时时间* @throws WxPayException* @return 成功时返回,其他抛异常*/public static WxPayData RefundQuery(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./pay/refundquery";//检测必填参数if(!inputObj.IsSet("out_refund_no") && !inputObj.IsSet("out_trade_no") &&!inputObj.IsSet("transaction_id") && !inputObj.IsSet("refund_id")){throw new WxPayException("退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个!");}inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串inputObj.SetValue("sign",inputObj.MakeSign());//签名string xml = inputObj.ToXml();var start = DateTime.Now;//请求开始时间Log.Debug("WxPayApi", "RefundQuery request : " + xml);string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口以提交数据到APILog.Debug("WxPayApi", "RefundQuery response : " + response);var end = DateTime.Now;int timeCost = (int)((end-start).TotalMilliseconds);//获得接口耗时//将xml格式的结果转换为对象以返回WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** 下载对账单* @param WxPayData inputObj 提交给下载对账单API的参数* @param int timeOut 接口超时时间* @throws WxPayException* @return 成功时返回,其他抛异常*/public static WxPayData DownloadBill(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./pay/downloadbill";//检测必填参数if (!inputObj.IsSet("bill_date")){throw new WxPayException("对账单接口中,缺少必填参数bill_date!");}inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串inputObj.SetValue("sign", inputObj.MakeSign());//签名string xml = inputObj.ToXml();Log.Debug("WxPayApi", "DownloadBill request : " + xml);string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口以提交数据到APILog.Debug("WxPayApi", "DownloadBill result : " + response);WxPayData result = new WxPayData();//若接口调用失败会返回xml格式的结果if (response.Substring(0, 5) == "<xml>"){result.FromXml(response);}//接口调用成功则返回非xml格式的数据elseresult.SetValue("result", response);return result;}/*** * 转换短链接* 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),* 减小二维码数据量,提升扫描速度和精确度。* @param WxPayData inputObj 提交给转换短连接API的参数* @param int timeOut 接口超时时间* @throws WxPayException* @return 成功时返回,其他抛异常*/public static WxPayData ShortUrl(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./tools/shorturl";//检测必填参数if(!inputObj.IsSet("long_url")){throw new WxPayException("需要转换的URL,签名用原串,传输需URL encode!");}inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串inputObj.SetValue("sign",inputObj.MakeSign());//签名string xml = inputObj.ToXml();var start = DateTime.Now;//请求开始时间Log.Debug("WxPayApi", "ShortUrl request : " + xml);string response = HttpService.Post(xml, url, false, timeOut);Log.Debug("WxPayApi", "ShortUrl response : " + response);var end = DateTime.Now;int timeCost = (int)((end - start).TotalMilliseconds);WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** * 统一下单* @param WxPaydata inputObj 提交给统一下单API的参数* @param int timeOut 超时时间* @throws WxPayException* @return 成功时返回,其他抛异常*/public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./pay/unifiedorder";//检测必填参数if (!inputObj.IsSet("out_trade_no")){throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");}else if (!inputObj.IsSet("body")){throw new WxPayException("缺少统一支付接口必填参数body!");}else if (!inputObj.IsSet("total_fee")){throw new WxPayException("缺少统一支付接口必填参数total_fee!");}else if (!inputObj.IsSet("trade_type")){throw new WxPayException("缺少统一支付接口必填参数trade_type!");}//关联参数if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid")){throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");}if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id")){throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");}//异步通知url未设置,则使用配置文件中的urlif (!inputObj.IsSet("notify_url")){inputObj.SetValue("notify_url", WxPayConfig.NOTIFY_URL);//异步通知url}inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号inputObj.SetValue("spbill_create_ip", WxPayConfig.IP);//终端ipinputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串//签名inputObj.SetValue("sign", inputObj.MakeSign());string xml = inputObj.ToXml();var start = DateTime.Now;Log.Debug("WxPayApi", "UnfiedOrder request : " + xml);string response = HttpService.Post(xml, url, false, timeOut);Log.Debug("WxPayApi", "UnfiedOrder response : " + response);var end = DateTime.Now;int timeCost = (int)((end - start).TotalMilliseconds);WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** * 关闭订单* @param WxPayData inputObj 提交给关闭订单API的参数* @param int timeOut 接口超时时间* @throws WxPayException* @return 成功时返回,其他抛异常*/public static WxPayData CloseOrder(WxPayData inputObj, int timeOut = 6){string url = "https://api.mch./pay/closeorder";//检测必填参数if(!inputObj.IsSet("out_trade_no")){throw new WxPayException("关闭订单接口中,out_trade_no必填!");}inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串inputObj.SetValue("sign",inputObj.MakeSign());//签名string xml = inputObj.ToXml();var start = DateTime.Now;//请求开始时间string response = HttpService.Post(xml, url, false, timeOut);var end = DateTime.Now;int timeCost = (int)((end - start).TotalMilliseconds);WxPayData result = new WxPayData();result.FromXml(response);ReportCostTime(url, timeCost, result);//测速上报return result;}/*** * 测速上报* @param string interface_url 接口URL* @param int timeCost 接口耗时* @param WxPayData inputObj参数数组*/private static void ReportCostTime(string interface_url, int timeCost, WxPayData inputObj){//如果不需要进行上报if(WxPayConfig.REPORT_LEVENL == 0){return;} //如果仅失败上报if(WxPayConfig.REPORT_LEVENL == 1 && inputObj.IsSet("return_code") && inputObj.GetValue("return_code").ToString() == "SUCCESS" &&inputObj.IsSet("result_code") && inputObj.GetValue("result_code").ToString() == "SUCCESS"){return;}//上报逻辑WxPayData data = new WxPayData();data.SetValue("interface_url",interface_url);data.SetValue("execute_time_",timeCost);//返回状态码if(inputObj.IsSet("return_code")){data.SetValue("return_code",inputObj.GetValue("return_code"));}//返回信息if(inputObj.IsSet("return_msg")){data.SetValue("return_msg",inputObj.GetValue("return_msg"));}//业务结果if(inputObj.IsSet("result_code")){data.SetValue("result_code",inputObj.GetValue("result_code"));}//错误代码if(inputObj.IsSet("err_code")){data.SetValue("err_code",inputObj.GetValue("err_code"));}//错误代码描述if(inputObj.IsSet("err_code_des")){data.SetValue("err_code_des",inputObj.GetValue("err_code_des"));}//商户订单号if(inputObj.IsSet("out_trade_no")){data.SetValue("out_trade_no",inputObj.GetValue("out_trade_no"));}//设备号if(inputObj.IsSet("device_info")){data.SetValue("device_info",inputObj.GetValue("device_info"));}try{Report(data);}catch (WxPayException ex){//不做任何处理}}/*** * 测速上报接口实现* @param WxPayData inputObj 提交给测速上报接口的参数* @param int timeOut 测速上报接口超时时间* @throws WxPayException* @return 成功时返回测速上报接口返回的结果,其他抛异常*/public static WxPayData Report(WxPayData inputObj, int timeOut = 1){string url = "https://api.mch./payitil/report";//检测必填参数if(!inputObj.IsSet("interface_url")){throw new WxPayException("接口URL,缺少必填参数interface_url!");} if(!inputObj.IsSet("return_code")){throw new WxPayException("返回状态码,缺少必填参数return_code!");} if(!inputObj.IsSet("result_code")){throw new WxPayException("业务结果,缺少必填参数result_code!");} if(!inputObj.IsSet("user_ip")){throw new WxPayException("访问接口IP,缺少必填参数user_ip!");} if(!inputObj.IsSet("execute_time_")){throw new WxPayException("接口耗时,缺少必填参数execute_time_!");}inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号IDinputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号inputObj.SetValue("user_ip",WxPayConfig.IP);//终端ipinputObj.SetValue("time",DateTime.Now.ToString("yyyyMMddHHmmss"));//商户上报时间 inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串inputObj.SetValue("sign",inputObj.MakeSign());//签名string xml = inputObj.ToXml();Log.Info("WxPayApi", "Report request : " + xml);string response = HttpService.Post(xml, url, false, timeOut);Log.Info("WxPayApi", "Report response : " + response);WxPayData result = new WxPayData();result.FromXml(response);return result;}/*** 根据当前系统时间加随机序列来生成订单号* @return 订单号*/public static string GenerateOutTradeNo(){var ran = new Random();return string.Format("{0}{1}{2}", WxPayConfig.MCHID, DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(999));}/*** 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数* @return 时间戳*/public static string GenerateTimeStamp(){TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);return Convert.ToInt64(ts.TotalSeconds).ToString();}/*** 生成随机串,随机串包含字母或数字* @return 随机串*/public static string GenerateNonceStr(){return Guid.NewGuid().ToString().Replace("-", "");}}}

六、收款后收款记录状态更新

前端代码:WeixinPayRecvResultNotify.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="WeixinPayRecvResultNotify.aspx.cs" Inherits="QinMing.WeixinPayCollect.WeixinPayRecvResultNotify" %><!DOCTYPE html><html xmlns="/1999/xhtml"><head runat="server"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title></title></head><body><form id="form1" runat="server"><div></div></form></body></html>

后端代码:WeixinPayRecvResultNotify.aspx.cs

using System;using System.Collections;using System.Collections.Generic;using System.Configuration;using System.Data;using System.Data.SqlClient;using System.Linq;using System.IO;using System.Text;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;namespace QinMing.WeixinPayCollect{public partial class WeixinPayRecvResultNotify : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){ResultNotify resultNotify = new ResultNotify(this);resultNotify.ProcessNotify();} }}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。