zoukankan      html  css  js  c++  java
  • 微信支付接口之心酸

    微信接口,对于某些人来说,很容易,宝宝自己尝试了一下,瞬间感觉泪奔呀,唉。

    首先,统一下单接口

            [HttpPost]
            [Route("~/api/WXPay/UnifiedOrder")]
            public HttpResponseMessage UnifiedOrder()
            {
                try
                {
                    NameValueCollection param = Request.Content.ReadAsFormDataAsync().Result;
                    string body = param["body"].ToString();//简单描述
                    string out_trade_no = param["out_trade_no"].ToString();
                    string total_fee = param["total_fee"].ToString();
                    string spbill_create_ip = param["spbill_create_ip"].ToString();
                    var stringADict = new Dictionary<string, string>();
                    stringADict.Add("appid", "这里是公众号ID");
                    stringADict.Add("mch_id", "商户号");
                    stringADict.Add("device_info", device_info);
                    stringADict.Add("nonce_str", CreateNonce_str());
                    stringADict.Add("body", body);
                    stringADict.Add("out_trade_no", out_trade_no);
                    stringADict.Add("total_fee", total_fee);
                    stringADict.Add("spbill_create_ip", spbill_create_ip);
                    stringADict.Add("notify_url", "回调函数");
                    stringADict.Add("trade_type", "APP");
                    var sign = Sign(stringADict, "签名字符串");//生成签名字符串
                    var postdata = GeneralPostdata(stringADict, sign);
                    var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
                    var client = new HttpClient();
                    var result = client.PostAsync(url, new StringContent(postdata)).Result;
                    if (!result.IsSuccessStatusCode) return null;
                    dynamic doc = new DynamicXml(result.Content.ReadAsStringAsync().Result);
                    JObject obj = new JObject();
                    var a = doc.return_code.Value;
                    var c = doc.return_msg.Value;
                    if (doc.return_code.Value == "SUCCESS" && doc.result_code.Value == "SUCCESS")
                    {
                        obj.Add("prepay_id", doc.prepay_id.Value);
                        obj.Add("trade_type", doc.trade_type.Value);
                        obj.Add("sign", doc.sign.Value);
                        obj.Add("nonce_str", doc.nonce_str.Value);
    
                        obj.Add("result_code", doc.result_code.Value);
                        obj.Add("return_code", doc.return_code.Value);
                        obj.Add("return_msg", doc.return_msg.Value);
                        obj.Add("RetCode", 0);
                        obj.Add("RetMsg", "");
                    }
                    else
                    {
                        obj.Add("RetCode", -1);
                        obj.Add("doc", doc.return_code.ToString() + doc.return_msg.ToString());
                    }
                    return Request.CreateResponse(obj);
                }
                catch (Exception e)
                {
                    JObject obj = new JObject();
                    obj.Add("RetCode", "-1");
                    obj.Add("ErrorDescription", e.ToString());
                    obj.Add("RetMsg", "错误代码:" + Guid.NewGuid().ToString());
                    return Request.CreateResponse(obj);
                }
            }
    

      在这里,必须要说明的是DynamicXml,在这个动态读取XML的时候,可坑死宝宝了。

     public class DynamicXml : DynamicObject, IEnumerable
        {
            private readonly List<XElement> _elements;
            public DynamicXml(string text)
            {
                var doc = XDocument.Parse(text);
                _elements = new List<XElement> { doc.Root };
            }
    
            protected DynamicXml(XElement element)
            {
                _elements = new List<XElement> { element };
            }
    
            protected DynamicXml(IEnumerable<XElement> elements)
            {
                _elements = new List<XElement>(elements);
            }
    
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                result = null;
                if (binder.Name == "Value")
                    result = _elements[0].Value;
                else if (binder.Name == "Count")
                    result = _elements.Count;
                else
                {
                    var attr = _elements[0].Attribute(XName.Get(binder.Name));
                    if (attr != null)
                        result = attr;
                    else
                    {
                        var items = _elements.Descendants(XName.Get(binder.Name));
                        if (items == null || items.Count() == 0) return false;
                        result = new DynamicXml(items);
                    }
                }
                return true;
            }
    
          
    
    
            public IEnumerator GetEnumerator()
            {
                foreach (var element in _elements)
                    yield return new DynamicXml(element);
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="binder"></param>
            /// <param name="indexes"></param>
            /// <param name="result"></param>
            /// <returns></returns>
            public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
            {
                int ndx = (int)indexes[0];
                result = new DynamicXml(_elements[ndx]);
                return true;
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                StringWriter message = new StringWriter();
                foreach (var item in _elements)
                    message.WriteLine("{0}:	{1}", item.Document,
                    item.Value);
                return message.ToString();
            }
        }
    

      因为刚开始没有加上ToString和TryGetIndex的重写,然后呢,解析了一天,都不知道哪里的错。唉

    OK,微信回调接口

            [HttpPost]
            [Route("~/api/WXPay/Notify")]
            public HttpResponseMessage Notify()
            {
                try
                {
    
                    byte[] a = Request.Content.ReadAsByteArrayAsync().Result;
                    string b = Encoding.UTF8.GetString(a);
                    var sParam = GetRequestPost(b);
    
                    if (sParam.Count <= 0)
                    {
                        throw new ArgumentNullException();
                    }
                    JObject obj = new JObject();
                    obj.Add("RetCode", 0);
                    obj.Add("RetMsg", "");
    
                    if (sParam["return_code"] == "SUCCESS" && sParam["result_code"] == "SUCCESS")
                    {
                        var sign = sParam["sign"];
                        var signValue = Sign(sParam, "签名字符串");
                        bool isVerify = sign == signValue;
                        if (isVerify)
                        {
                            var out_trade_no = sParam["out_trade_no"];
                            //具体的后期业务操作
                        }
                        obj.Add("return_code", "success");
                    }
                    else
                    {
                        obj.Add("return_code", "fail");
                    }
                    return Request.CreateResponse(HttpStatusCode.OK, obj);
                }
                catch (ArgumentNullException e)
                {
                    JObject obj = new JObject();
                    obj.Add("RetCode", "-1");
                    obj.Add("RequestMsg", "暂无参数!");
    
                    return Request.CreateResponse(obj);
                }
                catch (Exception e)
                {
                    JObject obj = new JObject();
                    obj.Add("RetCode", "-1");
                    obj.Add("ErrorDescription", e.ToString());
                    obj.Add("RetMsg", "错误代码:" + Guid.NewGuid().ToString());
                    return Request.CreateResponse(obj);
                }
            }
    

      对于这里的GetRequestPost方法,其实就是组合生成一个标准的xml字符串。

            private SortedDictionary<string, string> GetRequestPost(string xml)
            {
                SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
    
                dynamic resultXml = new DynamicXml(xml);
    
                sArray.Add("appid", resultXml.appid.Value);
                sArray.Add("bank_type", resultXml.bank_type.Value);
                sArray.Add("cash_fee", resultXml.cash_fee.Value);
                sArray.Add("fee_type", resultXml.fee_type.Value);
    
                sArray.Add("is_subscribe", resultXml.is_subscribe.Value);
                sArray.Add("mch_id", resultXml.mch_id.Value);
                sArray.Add("nonce_str", resultXml.nonce_str.Value);
                sArray.Add("openid", resultXml.openid.Value);
    
                sArray.Add("out_trade_no", resultXml.out_trade_no.Value);
                sArray.Add("time_end", resultXml.time_end.Value);
                sArray.Add("total_fee", resultXml.total_fee.Value);
                sArray.Add("transaction_id", resultXml.transaction_id.Value);
    
    
                sArray.Add("trade_type", resultXml.trade_type.Value);
                sArray.Add("sign", resultXml.sign.Value);
                sArray.Add("result_code", resultXml.result_code.Value);
                sArray.Add("return_code", resultXml.return_code.Value);
    
    
                return sArray;
            }
    

      附,后面的辅助方法,包含签名生成工具等。

            public static string GeneralPostdata(IDictionary<string, string> postdataDict, string sign)
            {
                var sb2 = new StringBuilder();
                sb2.Append("<xml>");
                foreach (var sA in postdataDict.OrderBy(x => x.Key))
                {
                    sb2.Append("<" + sA.Key + ">")
                       .Append(Transfer(sA.Value))
                       .Append("</" + sA.Key + ">");
                }
                sb2.Append("<sign>").Append(sign).Append("</sign>");
                sb2.Append("</xml>");
                return sb2.ToString();
            }
    
            public static string Transfer(string instr)
            {
                if (instr == null) return "";
                return instr.Replace("&", "&").Replace("<", "<")
                            .Replace(">", ">").Replace(""", """);
            }
    
    
            /// <summary>
            /// 生成签名
            /// 签名在线验证工具:
            /// http://mch.weixin.qq.com/wiki/tools/signverify/
            /// </summary>
            /// <param name="stringADict">参与签名生成的参数列表</param>
            /// <param name="partnerKey">商家私钥</param>
            /// <returns></returns>
            public static string Sign(IDictionary<string, string> stringADict, string partnerKey)
            {
                var sb = new StringBuilder();
                foreach (var sA in stringADict.OrderBy(x => x.Key))
                {
                    if (string.IsNullOrEmpty(sA.Value)) continue;
                    if (string.Compare(sA.Key, "sign", true) == 0) continue; 
                    sb.Append(sA.Key).Append("=").Append(sA.Value).Append("&");
                }
                var string1 = sb.ToString();
                sb.Append("key=").Append(partnerKey);
                var stringSignTemp = sb.ToString();
                var sign = MD5(stringSignTemp, "UTF-8").ToUpper();
                return sign;
            }
    
            public static string MD5(string encypStr, string charset = "UTF-8")
            {
                string retStr;
                MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
                byte[] inputBye;
                byte[] outputBye;
                try
                {
                    inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr);
                }
                catch
                {
                    inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
                }
                outputBye = m5.ComputeHash(inputBye);
    
                retStr = System.BitConverter.ToString(outputBye);
                retStr = retStr.Replace("-", "").ToUpper();
                return retStr;
            }
    

      OK,只是一个简单的记录,可以直接套用的,当然,对于.net来说,特别注意的就是那个DynamicXML那个类,太尼玛坑爹了,百毒了半天,然后看了半天,终于晓得问题了,唉。不喜勿喷。谢谢

          其中,很多包含借鉴网上的东西,如有版权牵扯,请及时联系本人,谢谢。

  • 相关阅读:
    使用TCMalloc优化OpenResty
    CentOS下强行umount卸载设备
    几种提高jQuery性能的代码
    知乎首页延时交互的小思路
    OpenResty+lua+GraphicsMagick生成缩略图
    __builtin__与__builtins__的区别与关系
    python语法学习之函数、类、模块
    os.popen与os.system区别
    getattr()函数详解
    python异常处理
  • 原文地址:https://www.cnblogs.com/JeffController/p/5531494.html
Copyright © 2011-2022 走看看