微信支付笔记

    一、开发前的准备:

        开发前需要配置支付授权目录,支付相关的页面全部要在这个指定的目录中,不能在子目录中。测试授权目录和测试白名单可以不用管。

微信支付笔记

    二、微信支付开发前需要这几个参数:

       1、AppID    在微信公众号管理后台(https://mp.weixin.qq.com/)的开发者中心获取

       2、微信支付商户号  在微信公众号管理后台(https://mp.weixin.qq.com/)的 微信支付 菜单下可以看到

       3、商户密匙   微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置

 

    三、微信公众号支付的逻辑是这样的:

         1. 我们自己的系统生成待支付订单信息 [订单号、金额、商品名称、说明等信息]

         2. 将系统的订单信息使用统一下单的数据格式提交到微信服务器 ,微信服务器会返回一个预支付交易会话标识 prepay_id

              统一下单的API文档: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

         3. 使用公众号APPID和第二部返回的预支付交易会话标识 prepay_id,加上时间戳 timeStamp、 随机字符串nonceStr ,签名 paySign 生成js参数,在HTML页面里完成支付

     网页端调起支付API文档:   https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

         4. 微信服务器异步通知我们服务器上的回调地址,完成支付

 

    从第三部分的HTML页面讲起,我们看到官方文档中微信的网页支付的代码是这样的:

function onBridgeReady() {
    WeixinJSBridge.invoke(‘getBrandWCPayRequest‘, {
        "appId":"wx2421b1c4370ec43b",
        //公众号名称,由商户传入     
        "timeStamp":" 1395712654",
        //时间戳,自1970年以来的秒数     
        "nonceStr":"e61463f8efa94090b1f366cccfbbb444",
        //随机串     
        "package":"prepay_id=u802345jgfjsdfgsdg888",
        "signType":"MD5",
        //微信签名方式:     
        "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
    },
    function(res) {
        if (res.err_msg == "get_brand_wcpay_request:ok") {}
    });
}
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 {
    onBridgeReady();
}

 

    注意:这个JS需要在微信浏览器里面直接调用,无需引用其他js文件,其他浏览器是不行的.

    第一次看到这个js脚本的时候比较奇怪,这里怎么没有支付的金额、商品名称、订单号呢,后来才知道订单的信息是需要提前提交给微信服务器的,这个提交的过程就叫统一下单

    支付页面的Javascript代码很简单,只有这几个参数需要我们自己根据实际情况进行替换:

        "appId":"wx2421b1c4370ec43b",  //公众号名称,由商户传入  |  这个参数已知           
        "timeStamp":" 1395712654",     //时间戳,自1970年以来的秒数 | 写个函数生成下即可,简单           
        "nonceStr":"e61463f8efa94090b1f366cccfbbb444",       //随机串 | 写个函数生成下        
        "package":"prepay_id=u802345jgfjsdfgsdg888",    //prepay_id 就是前面提到的支付交易会话标识,具体怎么生成在后面讲
        "signType":"MD5",                                    //微信签名方式:固定的,填写MD5即可             

//微信签名 签名生成方法可见API文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3,我在文章后面会给出代码
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89"

    我们先搞定最简单的部分:随机字符串和时间戳的生成C#实现

微信支付笔记
        /// <summary>
        /// 随机串 
        /// </summary>
        public static string getNoncestr()
        {
            Random random = new Random();
            return MD5Util.GetMD5(random.Next(1000).ToString(), "utf-8").ToLower().Replace("s", "S");
        }

        /// <summary>
        /// 时间截,自1970年以来的秒数
        /// </summary>
        public static string getTimestamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
View Code

 

   现在只有prepay_idpaySign目前不知道怎么产生的,另外几个参数都搞定了。

   prepay_id需要通过统一下单接口https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1获取到,我们看这个接口要传的参数有不少,新建一个UnifiedOrder类:

微信支付笔记
    /// <summary>
    /// 微信统一接口请求实体对象
    /// </summary>
    [Serializable]
    public class UnifiedOrder
    {
        /// <summary>
        /// 公共号ID(微信分配的公众账号 ID)
        /// </summary>
        public string appid = "";
        /// <summary>
        /// 商户号(微信支付分配的商户号)
        /// </summary>
        public string mch_id = "";
        /// <summary>
        /// 微信支付分配的终端设备号
        /// </summary>
        public string device_info = "";
        /// <summary>
        /// 随机字符串,不长于 32 位
        /// </summary>
        public string nonce_str = "";
        /// <summary>
        /// 签名
        /// </summary>
        public string sign = "";
        /// <summary>
        /// 商品描述
        /// </summary>
        public string body = "";
        /// <summary>
        /// 附加数据,原样返回
        /// </summary>
        public string attach = "";
        /// <summary>
        /// 商户系统内部的订单号,32个字符内、可包含字母,确保在商户系统唯一,详细说明
        /// </summary>
        public string out_trade_no = "";
        /// <summary>
        /// 订单总金额,单位为分,不能带小数点
        /// </summary>
        public int total_fee = 0;
        /// <summary>
        /// 终端IP
        /// </summary>
        public string spbill_create_ip = "";
        /// <summary>
        /// 订 单 生 成 时 间 , 格 式 为yyyyMMddHHmmss,如 2009 年12 月 25 日 9 点 10 分 10 秒表示为 20091225091010。时区为 GMT+8 beijing。该时间取自商户服务器
        /// </summary>
        public string time_start = "";
        /// <summary>
        /// 交易结束时间
        /// </summary>
        public string time_expire = "";
        /// <summary>
        /// 商品标记 商品标记,该字段不能随便填,不使用请填空,使用说明详见第 5 节
        /// </summary>
        public string goods_tag = "";
        /// <summary>
        /// 接收微信支付成功通知
        /// </summary>
        public string notify_url = "";
        /// <summary>
        /// JSAPI、NATIVE、APP
        /// </summary>
        public string trade_type = "";
        /// <summary>
        /// 用户标识 trade_type 为 JSAPI时,此参数必传
        /// </summary>
        public string openid = "";
        /// <summary>
        /// 只在 trade_type 为 NATIVE时需要填写。
        /// </summary>
        public string product_id = "";
    }
View Code

   用参数填充这个对象

        //统一下单
        UnifiedOrder order = new UnifiedOrder();
        order.appid = "1111111111111111";                   //公众账号ID,请替换成公众号实际的appid
        order.mch_id = "111111111111111";                   //调用接口提交的商户号,请替换成真实的商户号 
        order.device_info = "WEB";                          //终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB"  固定值
        order.nonce_str = TenpayUtil.getNoncestr();         //随机字符串,不长于32位,见前面的随机字符串函数 TenpayUtil代码后面给出
        order.body = "xxxxxxx设备充值";                      //商品或支付单简要描述
        order.attach = "这是一个支付测试订单";                 //附加数据
        order.out_trade_no = "11111111111111111111111";     //商户系统内部的订单号,32个字符内、可包含字母,请替换成真实的订单号
        order.total_fee = 0.01 * 100;                       //int类型,订单总金额,单位为分,请填写实际订单金额
        order.spbill_create_ip = Page.Request.UserHostAddress;              //用户端ip  11.11.11.11 格式
        order.notify_url = "http://baidu.com/notify_url.aspx";  //接收微信支付异步通知回调地址,请替换成真实的回调地址,回调页面文章后面会给出例子
        order.openid = "111111111111111111111111111111";      //trade_type=JSAPI,此参数必传,请替换成用户在商户appid下的唯一标识,用户的openid怎么获取请参考微信开发的API文档
        order.trade_type = "JSAPI";                         //交易类型 JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付

      将这些信息提交给微信服务器就能获取到临时支付交易会话标识 prepay_id了,下面代码里的paySignKey是商户密匙。

        //得到 prepay_id 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时
        string prepay_id = tenpay.getPrepay_id(order, paySignKey);    //tenapy代码文章末尾给出
        string timeStamp = TenpayUtil.getTimestamp();   //时间戳 
        string nonceStr = TenpayUtil.getNoncestr();     //随机字符串

     签名参数paySign的获取:

        // 4.根据得到的prepay_id计算paySign 签名
        SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();
        sParams.Add("appId", "1111111111111111111");        //请替换成真实的APPID
        sParams.Add("timeStamp", timeStamp);
        sParams.Add("nonceStr", nonceStr);
        sParams.Add("package", "prepay_id=" + prepay_id);
        sParams.Add("signType", "MD5");
        string paySign = tenpay.getsign(sParams, paySignKey);   //得到 paySign 签名  paySingKey 是商户密匙

      这样paySign和prepay_id参数都成功获取到了,将这些参数替换掉HTML页面的js参数就可以弹出微信支付窗口:

                          微信支付笔记

 

需要用到的一些代码:

TenpayUtil

微信支付笔记
    public class TenpayUtil
    {
        /// <summary>
        /// 统一支付接口
        /// </summary>
        const string UnifiedPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        /// <summary>
        /// 网页授权接口
        /// </summary>
        const string access_tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";

        /// <summary>
        /// 微信订单查询接口
        /// </summary>
        const string OrderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery";

        /// <summary>
        /// 随机串
        /// </summary>
        public static string getNoncestr()
        {
            Random random = new Random();
            return MD5Util.GetMD5(random.Next(1000).ToString(), "utf-8").ToLower().Replace("s", "S");
        }

        /// <summary>
        /// 时间截,自1970年以来的秒数
        /// </summary>
        public static string getTimestamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /// <summary>
        /// 网页授权接口
        /// </summary>
        public static string getAccess_tokenUrl()
        {
            return access_tokenUrl;
        }

        /// <summary>
        /// 获取微信签名
        /// 将集合M内非空参数值的参数按照参数名ASCII码从小到大排序
        /// 格式(即key1=value1&key2=value2…)拼接成字符串stringA
        /// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
        /// </summary>
        /// <param name="sParams">集合M</param>
        /// <param name="key">key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置</param>
        /// <returns></returns>
        public string getsign(SortedDictionary<string, string> sParams, string key)
        {
            int i = 0;
            string sign = string.Empty;
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair<string, string> temp in sParams)
            {
                if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "sign")
                {
                    continue;
                }
                i++;
                sb.Append(temp.Key.Trim() + "=" + temp.Value.Trim() + "&");
            }
            sb.Append("key=" + key.Trim() + "");
            string signkey = sb.ToString();
            sign = MD5Util.GetMD5(signkey, "utf-8");

            return sign;
        }

        /// <summary>
        /// Post数据到指定接口并返回数据
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="postData">要提交的数据</param>
        /// <returns></returns>
        public string PostXmlToUrl(string url, string postData)
        {
            string returnmsg = "";
            Bird.Net.Http.HttpHelper httpHelper = new Bird.Net.Http.HttpHelper();
            httpHelper.Encoding = Encoding.UTF8;
            returnmsg = httpHelper.GetHtml(url, postData, true);
            /*
            using (System.Net.WebClient wc = new System.Net.WebClient())
            {
                returnmsg = wc.UploadString(url, "POST", postData);
            }*/
            return returnmsg;
        }

        public string order_request_data = "";
        public string order_post_data = "";

        /// <summary>
        /// 统一下单获取prepay_id
        /// </summary>
        /// <param name="order">统一下单</param>
        /// <param name="key">商户密匙</param>
        /// <returns>prepay_id</returns>
        public string getPrepay_id(UnifiedOrder order, string key)
        {
            string prepay_id = "";
            order_post_data = getUnifiedOrderXml(order, key);
            order_request_data = PostXmlToUrl(UnifiedPayUrl, order_post_data);
            SortedDictionary<string, string> requestXML = GetInfoFromXml(order_request_data);
            foreach (KeyValuePair<string, string> k in requestXML)
            {
                if (k.Key == "prepay_id")
                {
                    prepay_id = k.Value;
                    break;
                }
            }
            return prepay_id;
        }

        /// <summary>
        /// 获取微信订单明细
        /// </summary>
        public OrderDetail getOrderDetail(QueryOrder queryorder, string key)
        {
            string post_data = getQueryOrderXml(queryorder, key);
            string request_data = PostXmlToUrl(OrderQueryUrl, post_data);
            OrderDetail orderdetail = new OrderDetail();
            SortedDictionary<string, string> requestXML = GetInfoFromXml(request_data);
            foreach (KeyValuePair<string, string> k in requestXML)
            {
                switch (k.Key)
                {
                    case "retuen_code":
                        orderdetail.result_code = k.Value;
                        break;
                    case "return_msg":
                        orderdetail.return_msg = k.Value;
                        break;
                    case "appid":
                        orderdetail.appid = k.Value;
                        break;
                    case "mch_id":
                        orderdetail.mch_id = k.Value;
                        break;
                    case "nonce_str":
                        orderdetail.nonce_str = k.Value;
                        break;
                    case "sign":
                        orderdetail.sign = k.Value;
                        break;
                    case "result_code":
                        orderdetail.result_code = k.Value;
                        break;
                    case "err_code":
                        orderdetail.err_code = k.Value;
                        break;
                    case "err_code_des":
                        orderdetail.err_code_des = k.Value;
                        break;
                    case "trade_state":
                        orderdetail.trade_state = k.Value;
                        break;
                    case "device_info":
                        orderdetail.device_info = k.Value;
                        break;
                    case "openid":
                        orderdetail.openid = k.Value;
                        break;
                    case "is_subscribe":
                        orderdetail.is_subscribe = k.Value;
                        break;
                    case "trade_type":
                        orderdetail.trade_type = k.Value;
                        break;
                    case "bank_type":
                        orderdetail.bank_type = k.Value;
                        break;
                    case "total_fee":
                        orderdetail.total_fee = k.Value;
                        break;
                    case "coupon_fee":
                        orderdetail.coupon_fee = k.Value;
                        break;
                    case "fee_type":
                        orderdetail.fee_type = k.Value;
                        break;
                    case "transaction_id":
                        orderdetail.transaction_id = k.Value;
                        break;
                    case "out_trade_no":
                        orderdetail.out_trade_no = k.Value;
                        break;
                    case "attach":
                        orderdetail.attach = k.Value;
                        break;
                    case "time_end":
                        orderdetail.time_end = k.Value;
                        break;
                    default:
                        break;
                }
            }
            return orderdetail;
        }

        /// <summary>
        /// 把XML数据转换为SortedDictionary[string, string]集合
        /// </summary>
        /// <param name="strxml">XML数据</param>
        /// <returns>集合</returns>
        public SortedDictionary<string, string> GetInfoFromXml(string xmlstring)
        {
            SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xmlstring);
                XmlElement root = doc.DocumentElement;
                int len = root.ChildNodes.Count;
                for (int i = 0; i < len; i++)
                {
                    string name = root.ChildNodes[i].Name;
                    if (!sParams.ContainsKey(name))
                    {
                        sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim());
                    }
                }
            }
            catch { }
            return sParams;
        }

        /// <summary>
        /// 微信统一下单接口xml参数整理
        /// </summary>
        /// <param name="order">微信支付参数实例</param>
        /// <param name="key">商户密钥</param>
        /// <returns></returns>
        protected string getUnifiedOrderXml(UnifiedOrder order, string key)
        {
            string return_string = string.Empty;
            SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();
            sParams.Add("appid", order.appid);
            sParams.Add("attach", order.attach);
            sParams.Add("body", order.body);
            sParams.Add("device_info", order.device_info);
            sParams.Add("mch_id", order.mch_id);
            sParams.Add("nonce_str", order.nonce_str);
            sParams.Add("notify_url", order.notify_url);
            sParams.Add("openid", order.openid);
            sParams.Add("out_trade_no", order.out_trade_no);
            sParams.Add("spbill_create_ip", order.spbill_create_ip);
            sParams.Add("total_fee", order.total_fee.ToString());
            sParams.Add("trade_type", order.trade_type);
            order.sign = getsign(sParams, key);
            sParams.Add("sign", order.sign);

            //拼接成XML请求数据
            StringBuilder sbPay = new StringBuilder();
            foreach (KeyValuePair<string, string> k in sParams)
            {
                if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
                {
                    sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");
                }
                else
                {
                    sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">");
                }
            }
            return_string = string.Format("<xml>{0}</xml>", sbPay.ToString());
            return return_string;

        }

        /// <summary>
        /// 微信订单查询接口XML参数整理
        /// </summary>
        /// <param name="queryorder">微信订单查询参数实例</param>
        /// <param name="key">密钥</param>
        /// <returns></returns>
        protected string getQueryOrderXml(QueryOrder queryorder, string key)
        {
            string return_string = string.Empty;
            SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();
            sParams.Add("appid", queryorder.appid);
            sParams.Add("mch_id", queryorder.mch_id);
            sParams.Add("transaction_id", queryorder.transaction_id);
            sParams.Add("out_trade_no", queryorder.out_trade_no);
            sParams.Add("nonce_str", queryorder.nonce_str);
            queryorder.sign = getsign(sParams, key);
            sParams.Add("sign", queryorder.sign);

            //拼接成XML请求数据
            StringBuilder sbPay = new StringBuilder();
            foreach (KeyValuePair<string, string> k in sParams)
            {
                if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
                {
                    sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");
                }
                else
                {
                    sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">");
                }
            }
            return_string = string.Format("<xml>{0}</xml>", sbPay.ToString().TrimEnd(,));
            return return_string;
        }
    }
View Code

MD5Util

微信支付笔记
    public class MD5Util
    {
        public MD5Util() { }

        /** 获取大写的MD5签名结果 */
        public static string GetMD5(string encypStr, string charset)
        {
            string retStr;
            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

            //创建md5对象
            byte[] inputBye;
            byte[] outputBye;

            try
            {
                inputBye = Encoding.UTF8.GetBytes(encypStr);
            }
            catch (Exception ex)
            {
                inputBye = Encoding.UTF8.GetBytes(encypStr);
            }
            outputBye = m5.ComputeHash(inputBye);

            retStr = System.BitConverter.ToString(outputBye);
            retStr = retStr.Replace("-", "").ToUpper();
            return retStr;
        }
    }
View Code

OrderDetail

微信支付笔记
    /// <summary>
    /// 微信订单明细实体对象
    /// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
    /// </summary>
    [Serializable]
    public class OrderDetail
    {
        /// <summary>
        /// 返回状态码,SUCCESS/FAIL 此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断
        /// </summary>
        public string return_code = "";

        /// <summary>
        /// 返回信息返回信息,如非空,为错误原因 签名失败 参数格式校验错误
        /// </summary>
        public string return_msg = "";

        /// <summary>
        /// 公共号ID(微信分配的公众账号 ID)
        /// </summary>
        public string appid = "";

        /// <summary>
        /// 商户号(微信支付分配的商户号)
        /// </summary>
        public string mch_id = "";

        /// <summary>
        /// 随机字符串,不长于32位
        /// </summary>
        public string nonce_str = "";

        /// <summary>
        /// 签名详见签名算法 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
        /// </summary>
        public string sign = "";

        /// <summary>
        /// 业务结果,SUCCESS/FAIL 
        /// 此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
        /// </summary>
        public string result_code = "";

        /// <summary>
        /// 错误代码    详细参见第6节错误列表
        /// </summary>
        public string err_code = "";

        /// <summary>
        /// 错误代码描述
        /// </summary>
        public string err_code_des = "";

        /// <summary>
        /// 交易状态
        ///SUCCESS—支付成功
        ///REFUND—转入退款
        ///NOTPAY—未支付
        ///CLOSED—已关闭
        ///REVOKED—已撤销
        ///USERPAYING--用户支付中
        ///NOPAY--未支付(输入密码或确认支付超时) PAYERROR--支付失败(其他原因,如银行返回失败)
        /// </summary>
        public string trade_state = "";

        /// <summary>
        /// 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB"
        /// </summary>
        public string device_info = "";

        /// <summary>
        /// 用户在商户appid下的唯一标识
        /// </summary>
        public string openid = "";

        /// <summary>
        /// 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
        /// </summary>
        public string is_subscribe = "";

        /// <summary>
        /// 交易类型,取值如下:JSAPI,NATIVE,APP,详细说明见参数规定
        /// </summary>
        public string trade_type = "";

        /// <summary>
        /// 银行类型,采用字符串类型的银行标识
        /// </summary>
        public string bank_type = "";

        /// <summary>
        /// 订单总金额,单位为分
        /// </summary>
        public string total_fee = "";

        /// <summary>
        /// 现金券支付金额<=订单总金额,订单总金额-现金券金额为现金支付金额
        /// </summary>
        public string coupon_fee = "";

        /// <summary>
        /// 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY
        /// </summary>
        public string fee_type = "";

        /// <summary>
        /// 微信支付订单号
        /// </summary>
        public string transaction_id = "";

        /// <summary>
        /// 商户系统的订单号,与请求一致。
        /// </summary>
        public string out_trade_no = "";

        /// <summary>
        /// 商家数据包,原样返回
        /// </summary>
        public string attach = "";

        /// <summary>
        /// 支付完成时间,格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
        /// 时区为GMT+8 beijing。该时间取自微信支付服务器
        /// </summary>
        public string time_end = "";

    }
View Code

UnifiedOrder

微信支付笔记
    /// <summary>
    /// 微信统一接口请求实体对象
    /// </summary>
    [Serializable]
    public class UnifiedOrder
    {
        /// <summary>
        /// 公共号ID(微信分配的公众账号 ID)
        /// </summary>
        public string appid = "";
        /// <summary>
        /// 商户号(微信支付分配的商户号)
        /// </summary>
        public string mch_id = "";
        /// <summary>
        /// 微信支付分配的终端设备号
        /// </summary>
        public string device_info = "";
        /// <summary>
        /// 随机字符串,不长于 32 位
        /// </summary>
        public string nonce_str = "";
        /// <summary>
        /// 签名
        /// </summary>
        public string sign = "";
        /// <summary>
        /// 商品描述
        /// </summary>
        public string body = "";
        /// <summary>
        /// 附加数据,原样返回
        /// </summary>
        public string attach = "";
        /// <summary>
        /// 商户系统内部的订单号,32个字符内、可包含字母,确保在商户系统唯一,详细说明
        /// </summary>
        public string out_trade_no = "";
        /// <summary>
        /// 订单总金额,单位为分,不能带小数点
        /// </summary>
        public int total_fee = 0;
        /// <summary>
        /// 终端IP
        /// </summary>
        public string spbill_create_ip = "";
        /// <summary>
        /// 订 单 生 成 时 间 , 格 式 为yyyyMMddHHmmss,如 2009 年12 月 25 日 9 点 10 分 10 秒表示为 20091225091010。时区为 GMT+8 beijing。该时间取自商户服务器
        /// </summary>
        public string time_start = "";
        /// <summary>
        /// 交易结束时间
        /// </summary>
        public string time_expire = "";
        /// <summary>
        /// 商品标记 商品标记,该字段不能随便填,不使用请填空,使用说明详见第 5 节
        /// </summary>
        public string goods_tag = "";
        /// <summary>
        /// 接收微信支付成功通知
        /// </summary>
        public string notify_url = "";
        /// <summary>
        /// JSAPI、NATIVE、APP
        /// </summary>
        public string trade_type = "";
        /// <summary>
        /// 用户标识 trade_type 为 JSAPI时,此参数必传
        /// </summary>
        public string openid = "";
        /// <summary>
        /// 只在 trade_type 为 NATIVE时需要填写。
        /// </summary>
        public string product_id = "";
    }
View Code

回调页面测试:

微信支付笔记
public partial class tools_WeChat_Pay_notify_url : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //接收从微信后台POST过来的数据
        System.IO.Stream s = 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();

        TenpayUtil payUtil = new TenpayUtil();
        SortedDictionary<string, string> requestXML = payUtil.GetInfoFromXml(builder.ToString());

        const string paySignKey = "111111111111111111111111111111111111";
        string sing = payUtil.getsign(requestXML, paySignKey);

        if (requestXML.ContainsKey("return_code"))
        {
            //Response.Write(requestXML["return_code"]);
        }

        //成功返回
        Response.Write("<xml>");
        Response.Write("<return_code><![CDATA[SUCCESS]]></return_code>");
        Response.Write("<return_msg><![CDATA[OK]]></return_msg>");
        Response.Write("</xml>");
    }

    /// <summary>
    /// 从XML数据中获取值
    /// </summary>
    /// <param name="requestXML">XML数据</param>
    /// <param name="key">Key</param>
    /// <returns>Value</returns>
    public string getVal(SortedDictionary<string, string> data, string key)
    {
        if (data.ContainsKey(key))
        {
            return data[key];
        }
        return "";
    }
}
View Code

 

微信支付笔记

上一篇:移动前端工作的那些事---前端制作之微信小技巧篇


下一篇:【完全开源】微信客户端.NET版