原文:ASP.NET WEB API微信支付通知接口,返回xml数据,微信服务器不识别问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MrTraum/article/details/80897239

最近开发微信小程序中用到了微信支付功能,接口开发用的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;
else
return 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 KEY
str += "&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 2013 SQL Server 2008 R2 准备工作 启动Visual Studio 2013,新建一个ASP.NET Web应用程序,命名为SimpleAP ...

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

    开发工具 Visual Studio 2013 SQL Server 2008 R2 准备工作 启动Visual Studio 2013,新建一个ASP.NET Web应用程序,命名为SimpleAP ...

  3. 用ASP.NET Web API技术开发HTTP接口(二)

    在第一部分,我们创建了一个基本的ASP.NET Web API项目,新建成功了数据表,然后添加了一些测试数据,最后创建了API控制器,用json格式把数据表里面的内容成功输出到浏览器上.接下来我们将继 ...

  4. ASP.NET Web API 2:Action的返回类型

    Web API控制器中的Action方法有如下几种返回类型: void HttpResponseMessage IHttpActionResult 其它类型 基于上面几种不同的返回类型,Web API ...

  5. 能省则省:在ASP.NET Web API中通过HTTP Headers返回数据

    对于一些返回数据非常简单的 Web API,比如我们今天遇到的“返回指定用户的未读站内短消息数”,返回数据就是一个数字,如果通过 http response body 返回数据,显得有些奢侈.何不直接 ...

  6. .NetCore Web Api 利用ActionFilterAttribute统一接口返回值格式

    .Net Core 同 Asp.Net MVC一样有几种过滤器,这里不再赘述每个过滤器的执行顺序与作用. 在实际项目开发过程中,统一API返回值格式对前端或第三方调用将是非常必要的,在.NetCore ...

  7. How do I get ASP.NET Web API to return JSON instead of XML using Chrome

    public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Ro ...

  8. ASP.NET Web API路由系统:路由系统的几个核心类型

    虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分(定义在程序集System.Web.Http.dll中)已经移除 ...

  9. ASP.NET Web API 2 入门

    本文参考:http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web ...

随机推荐

  1. UVa 10801 Lift Hopping【floyd 】

    题意:给出n个电梯,每个电梯的运行时间,每个电梯只能在相应的楼层停靠,而且没有楼梯,再给出想去的楼层,问从0层能否到达想去的楼层,求到达的最短时间 建图还是没有建出来--- 因为n<100,可以 ...

  2. swift语言点评十三-Lazy

    Lazy Stored Properties A lazy stored property is a property whose initial value is not calculated un ...

  3. Spring 与CXF整合(spring3.2,cxf3.1.11)

    1,jar包导入,从官网下载zip文件后里面会有很多jar包,哪些必须哪些不是必须,我能力有限,从其他人那参考了导入的一下jar包. 2.配置相关文件 web.xml中配置servlet <se ...

  4. 捕捉soap的xml形式

    下面是我以前对Php的soap接口进行抓包分析出的结果,这个分析在当服务端或者客户端的Php没有安装soap模块时,可以使用构建xml的方式实现相同的功能 服务端: $data = $HTTP_RAW ...

  5. KVM 日常使用命令

    [root@Eren liwm]# ps ax | grep kvm  681 ?        S<     0:00 [kvm-irqfd-clean]17597 pts/0    S+   ...

  6. const int *a与int *const a,const int *const a的区别

    来源:https://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰 ...

  7. 基于json数据格式实现的简单数据库——jsonDB

    已在github上建立项目:https://github.com/ThinkerCodeChina/jsonDB /** +-------------------------------------- ...

  8. hadoop-15-Ambari进行HDP、zookeeper安装

    hadoop-15-Ambari进行HDP.zookeeper安装 1,登陆server_1:8080 admin/admin 2,命名:Hdp_cluster 3,输入HDP.HDP_Utils 地 ...

  9. unix中文件I/O

    在unix中可用的文件I/O函数包含打开文件,读文件,写文件等. Unix系统中的大多数文件I/O须要用到5个函数:open,read,write,lseek,close. 这里要说明的是read,w ...

  10. HDU4324 Triangle LOVE【拓扑排序】

    Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...