现象

写好异步通知代码后,测试时发现支付宝以及微信在进行异步通知时都在一直发送消息,说明我们返回的“成功”它们没有收到,尽管输出了相应的 success 或者success相关的xml。

原因

由于异步通知接口方法使用了@ResponseBody注解,而配合了如下配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- Jackson转换器 -->
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>

<!-- 启动Spring MVC的注解功能,完成请求和返回的POJO-json/xml自动转换 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<!-- json转换器 -->
<ref bean="mappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>

这会导致所有请求均返回json数据,而对于支付宝,将返回“success”,注意是带有双引号的success。而微信将返回

1
2
3
4
5
6
7
8
<xml>
<return_code>
<![CDATA[FAIL]]>
</return_code>
<return_msg>
<![CDATA[通知签名验证失败]]>
</return_msg>
</xml>

也带有双引号,因此支付宝和微信不能正确识别。

解决方案

因此需要另外配置一个string转换器,将结果以string方式转换,这样就不会出现双引号。
配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- String转换器(为配合APP支付异步通知) -->
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" index="0"></constructor-arg><!--避免出现乱码 -->
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/xml;charset=UTF-8</value>
</list>
</property>
</bean>

<!-- 启动Spring MVC的注解功能,完成请求和返回的POJO-json/xml自动转换 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<!-- json转换器 -->
<ref bean="mappingJacksonHttpMessageConverter" />
<ref bean="stringHttpMessageConverter" />
</list>
</property>
</bean>

以上的text/plaintext/xml表示response的ContentType如果为这两种格式,则交由string转换器转换。同时接口方法代码上应类同于如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* Description: 支付宝异步通知地址 <BR>
*
* @author ran.chunlin
* @date 2017年5月17日 下午1:47:37
* @param request
* @param response
* @throws Exception
* @version 1.0
*/
@RequestMapping("/alipayNotify.do")
public void alipayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
String mString = alipayService.notifyHandle(request);
response.setContentType("text/plain;charset=UTF-8");
ServletOutputStream out = response.getOutputStream();
out.write(mString.getBytes());
out.flush();
out.close();
}

/**
* Description:微信异步通知地址 <BR>
*
* @author ran.chunlin
* @date 2017年5月11日 下午2:47:51
* @param request
* @param response
* @throws Exception
* @version 1.0
* @return
*/
@RequestMapping("/tenpayNotify.do")
public void tenpayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
String mString = tenpayService.notifyHandle(request);
response.setContentType("text/xml;charset=UTF-8");
ServletOutputStream out = response.getOutputStream();
out.write(mString.getBytes());
out.flush();
out.close();
}