最近开发微信小程序中用到了微信支付功能,接口开发用的ASP.NET WEB API;

在支付成功后,接口接受到微信服务器的支付通知结果,处理完数据,接口返回给微信服务数据时出现了问题。

微信服务器识别不到返回的数据,导致重复通知。

最终解决代码如下:

        protected virtual HttpResponseMessage RetMessage(object msg){return new HttpResponseMessage{Content =  new StringContent(msg.ToString(),new UTF8Encoding(false), "text/plain")};}
        [HttpPost]public HttpResponseMessage Wx_Notify(){//业务处理代码,以下为返回WxPayData res = new WxPayData();res.SetValue("return_code", "SUCCESS");res.SetValue("return_msg", "OK");return RetMessage(res.ToXml());}

WxPayData 为腾讯官方提供源码中的类

namespace WxPayAPI
{/// <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{//2015-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 = Json.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 = md5.ComputeHash(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;}}
}

ASP.NET WEB API微信支付通知接口,返回xml数据,微信服务器不识别问题相关推荐

  1. 用ASP.NET Web API技术开发HTTP接口(一)

    <转载自 "浮点指向"> 启动Visual Studio 2015,新建一个ASP.NET Web应用程序,命名为SimpleAPI.选择Empty模板,并勾选&quo ...

  2. php接收微信支付异步回调返回的数据

    之前在接触的项目中,微信支付回调函数都是使用以下变量获取POST数据: 前提:php配置中,必须启用 always_populate_raw_post_data //php.ini 配置 always ...

  3. C# 如何理解 ASP.NET Web API 的 REST

    什么是Web API 谈谈REST与ASP.NET Web API 怎样理解 REST.RESTful 关于什么是 Web API seaconch 也就不再这里多说了 web api 是一个 面向资 ...

  4. 【Web API系列教程】1.3 — 实战:用ASP.NET Web API和Angular.js创建单页面应用程序(上)

    前言 在传统的web应用程序中,客户端(浏览器)通过请求页面来启动与服务器的通信.然后服务器处理该请求,并发送HTML页面到客户端.在随后页面上的操作中--例如,用户导航到一个链接或提交一个包含数据的 ...

  5. php写的接口返回数据的页面,PHP怎么解析 WEBSERVICES接口返回的数据

    PHP如何解析 WEBSERVICES接口返回的数据 WEBSERVICE服务器,他们用.net写了个接口 http://XXX.XXX.XXX.XX/Info.asmx?wsdl 我用PHP调用这个 ...

  6. ASP.NET Web API 接口执行时间监控

    软件产品常常会出现这样的情况:产品性能因某些无法预料的瓶颈而受到干扰,导致程序的处理效率降低,性能得不到充分的发挥.如何快速有效地找到软件产品的性能瓶颈,则是我们感兴趣的内容之一. 在本文中,我将解释 ...

  7. ASP.NET Web API 入门 (API接口、寄宿方式、HttpClient调用)

    一.ASP.NET Web API接口定义 ASP.NET Web API默认实现了Action方法和HTTP方法的映射,Action方法方法名体现了其能处理的请求必须采用的HTTP方法 二.寄宿方式 ...

  8. 实战微信支付 APIv3 接口(小程序的)

    开场白直接引用官方文档的吧. 为了在保证支付安全的前提下,带给商户简单.一致且易用的开发体验,我们推出了全新的微信支付 APIv3 接口. 为啥不用官方 SDK? 官方 SDK 不错,只是依赖 Apa ...

  9. 使用NATAPP.cn测试微信支付回调接口

    个人资源与分享网站:http://xiaocaoshare.com/ 1.在工作中,开发微信支付有点的难度的地方就是微信支付回调接口的测试,现在推荐一款在线调试工具https://natapp.cn ...

最新文章

  1. iOS 自定义返回按钮,保留系统滑动返回
  2. 阻碍GIS产业发展的三大问题
  3. mxnet加载resnet,进行预测
  4. mdf与ldf文件如何还原到SQLserver数据库
  5. linux卸载keystone服务,关于linux下卸载apache后安装apache
  6. 在阿里云Serverless K8S集群上部署Spark任务并连接OSS(详细步骤)
  7. 解决HTML embed标签显示在div上层(not z-index)
  8. 获取页眉值vba_VBA抓取股票历史数据的整体表处理
  9. 数据结构学习笔记:利用Python列表实现栈结构
  10. fragment中嵌套viewpager,vierpager中有多个fragment,不显示 .
  11. sklearn 3.随机森林(菜菜课程)
  12. 牛客小白月赛11 J Rinne Loves Math
  13. 笔记:Java 性能优化权威指南 第5章 Java 应用性能分析
  14. 求最小公倍数(扩展版)
  15. AR虚拟互动系统创造身临其境的多元互动体验
  16. linux usb gadget 日志
  17. 合同和协议的区别_合同和协议有什么区别?
  18. mysql 中文数字转换_数据库中数字和中文的转换问题
  19. 命令提示符(CMD)切换到指定目录的方法
  20. java11的新特性

热门文章

  1. 今日头条的推荐阅读你为什么都喜欢?
  2. 24.双边滤波和中值滤波器(自定义中值滤波器去除椒盐噪声、exp含义)-- OpenCV从零开始到图像(人脸 + 物体)识别系列
  3. LOJ 3124 「CTS2019 | CTSC2019」氪金手游——概率+树形DP
  4. Docker系列五基于CentOS制造镜像
  5. 浏览器野史 UserAgent 列传(上)
  6. Oracle PRM-DUL使用经验
  7. 炸机不可怕,可怕的是你不知道为什么炸
  8. latex超级基础的文档手册——第二部分:符号、图片、表格
  9. 输出素数并统计个数 (10分)
  10. iOS的电量测试(Sysdiagnose)