微信支付异步回调mysql_微信支付异步回调,带你解决微信支付的深坑

1.首先我们先下载微信支付的服务器端demo

c086fad0e43bf30c13e5edddaf09c424

eeb800617562643e398eb5db9192c6e1

2.个文件作用介绍

index.jsp  下单  payRequest.jsp  获取微信支付prepay_id等。

重点我说说这个payNotifyUrl.jsp

//---------------------------------------------------------

//财付通支付通知(后台通知)示例,商户按照此文档进行开发即可

//---------------------------------------------------------

//商户号

String partner = "1900000109";

//密钥

String key = "8934e7d15453e97507ef794cf7b0519d";

//创建支付应答对象

ResponseHandler resHandler = new ResponseHandler(request, response);

resHandler.setKey(key);

//判断签名

if(resHandler.isTenpaySign()) {

//通知id

String notify_id = resHandler.getParameter("notify_id");

//创建请求对象

RequestHandler queryReq = new RequestHandler(null, null);

//通信对象

TenpayHttpClient httpClient = new TenpayHttpClient();

//应答对象

ClientResponseHandler queryRes = new ClientResponseHandler();

//通过通知ID查询,确保通知来至财付通

queryReq.init();

queryReq.setKey(key);

queryReq.setGateUrl("https://gw.tenpay.com/gateway/verifynotifyid.xml");

queryReq.setParameter("partner", partner);

queryReq.setParameter("notify_id", notify_id);

//通信对象

httpClient.setTimeOut(5);

//设置请求内容

httpClient.setReqContent(queryReq.getRequestURL());

System.out.println("queryReq:" + queryReq.getRequestURL());

//后台调用

if(httpClient.call()) {

//设置结果参数

queryRes.setContent(httpClient.getResContent());

System.out.println("queryRes:" + httpClient.getResContent());

queryRes.setKey(key);

//获取返回参数

String retcode = queryRes.getParameter("retcode");

String trade_state = queryRes.getParameter("trade_state");

String trade_mode = queryRes.getParameter("trade_mode");

//判断签名及结果

if(queryRes.isTenpaySign()&& "0".equals(retcode) && "0".equals(trade_state) && "1".equals(trade_mode)) {

System.out.println("订单查询成功");

//取结果参数做业务处理

System.out.println("out_trade_no:" + queryRes.getParameter("out_trade_no")+

" transaction_id:" + queryRes.getParameter("transaction_id"));

System.out.println("trade_state:" + queryRes.getParameter("trade_state")+

" total_fee:" + queryRes.getParameter("total_fee"));

//如果有使用折扣券,discount有值,total_fee+discount=原请求的total_fee

System.out.println("discount:" + queryRes.getParameter("discount")+

" time_end:" + queryRes.getParameter("time_end"));

//------------------------------

//处理业务开始

//------------------------------

//处理数据库逻辑

//注意交易单不要重复处理

//注意判断返回金额

//------------------------------

//处理业务完毕

//------------------------------

resHandler.sendToCFT("Success");

}

else{

//错误时,返回结果未签名,记录retcode、retmsg看失败详情。

System.out.println("查询验证签名失败或业务错误");

System.out.println("retcode:" + queryRes.getParameter("retcode")+

" retmsg:" + queryRes.getParameter("retmsg"));

}

} else {

System.out.println("后台调用通信失败");

System.out.println(httpClient.getResponseCode());

System.out.println(httpClient.getErrInfo());

//有可能因为网络原因,请求已经处理,但未收到应答。

}

}

else{

System.out.println("通知签名验证失败");

}

%>

就是上面的这代码。完全没有用。查看sdk源码才知道 这个异步回调是接收微信发送的所有参数,然后排序  加密 验签。  最坑的是  微信 的参数根本不是通过的参数返回的。而是通过的流。所以这个太坑了。下面我把我修改过的源码发出来 帮助大家解决回调问题。

首先是控制器

/**

* 异步回调接口

* @param request

* @param response

* @throws Exception

*/

@RequestMapping(value="/weixin_parent_notify.do",produces="text/html;charset=utf-8")

@ResponseBody

public String WeixinParentNotifyPage(HttpServletRequest request,HttpServletResponse response) throws Exception{

ServletInputStream instream = request.getInputStream();

StringBuffer sb = new StringBuffer();

int len = -1;

byte[] buffer = new byte[1024];

while((len = instream.read(buffer)) != -1){

sb.append(new String(buffer,0,len));

}

instream.close();

SortedMap map = WXRequestUtil.doXMLParseWithSorted(sb.toString());//接受微信的通知参数

Map return_data = new HashMap();

//创建支付应答对象

ResponseHandler resHandler = new ResponseHandler(request, response);

resHandler.setAllparamenters(map);

resHandler.setKey(ConstantUtil.PARTNER_KEY[0]);

//判断签名

if(resHandler.isTenpaySign()){

if(!map.get("return_code").toString().equals("SUCCESS")){

return_data.put("return_code", "FAIL");

return_data.put("return_msg", "return_code不正确");

}else{

if(!map.get("result_code").toString().equals("SUCCESS")){

return_data.put("return_code", "FAIL");

return_data.put("return_msg", "result_code不正确");

}

String out_trade_no = map.get("out_trade_no").toString();

String time_end = map.get("time_end").toString();

BigDecimal total_fee = new BigDecimal(map.get("total_fee").toString());

//付款完成后,支付宝系统发送该交易状态通知

System.out.println("交易成功");

Map order = orderdao.PaymentEndGetOrderInfo(out_trade_no);

if(order == null){

System.out.println("订单不存在");

return_data.put("return_code", "FAIL");

return_data.put("return_msg", "订单不存在");

return WXRequestUtil.GetMapToXML(return_data);

}

int order_type = (int) order.get("order_type");

boolean payment_status = (boolean) order.get("payment_status");

int supplier_id = (int) order.get("supplier_id");

BigDecimal p = new BigDecimal("100");

BigDecimal amount = (BigDecimal) order.get("amount");

amount = amount.multiply(p);

//如果订单已经支付返回错误

if(payment_status){

System.out.println("订单已经支付");

return_data.put("return_code", "SUCCESS");

return_data.put("return_msg", "OK");

return WXRequestUtil.GetMapToXML(return_data);

}

//如果支付金额不等于订单金额返回错误

if(amount.compareTo(total_fee)!=0){

System.out.println("资金异常");

return_data.put("return_code", "FAIL");

return_data.put("return_msg", "金额异常");

return WXRequestUtil.GetMapToXML(return_data);

}

//更新订单信息

if(orderdao.PaymentEndUpdateOrder(out_trade_no, time_end)){

System.out.println("更新订单成功");

//如果该订单是幼儿产品 并且 存在代理

if(order_type == 2){

if(supplier_id != 0){

Map su = userdao.getSupplierInfo(supplier_id);

String phone = (String) su.get("phone_number");

String nickname = (String) su.get("nickname");

String app_token = (String) su.get("app_token");

String content = "【三盛科创】尊敬的"+ nickname +"您好。您在我们平台出售的商品有新用户下单。请您点击该链接查看发货信息。"+Config.WEB_SERVER+"/order/SupplierOrderInfo.do?order_number="+out_trade_no+"&sid="+app_token+".请您务必妥善包管。";

MessageUtil.SendMessage(phone,content);

}

}else{

orderdao.UpdateOrderStatus(out_trade_no, 3);//更新订单为已完成

}

return_data.put("return_code", "SUCCESS");

return_data.put("return_msg", "OK");

return WXRequestUtil.GetMapToXML(return_data);

}else{

return_data.put("return_code", "FAIL");

return_data.put("return_msg", "更新订单失败");

return WXRequestUtil.GetMapToXML(return_data);

}

}

}else{

return_data.put("return_code", "FAIL");

return_data.put("return_msg", "签名错误");

}

String xml = WXRequestUtil.GetMapToXML(return_data);

return xml;

}

微信工具类WXRequestUtil.java

package com.tenpay.util;

import java.io.BufferedReader;

import java.io.ByteArrayInputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.ConnectException;

import java.net.HttpURLConnection;

import java.net.InetAddress;

import java.net.URL;

import java.security.KeyStore;

import java.util.Date;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.SortedMap;

import java.util.TreeMap;

import javax.net.ssl.SSLContext;

import org.apache.http.Consts;

import org.apache.http.HttpEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import org.apache.http.conn.ssl.SSLContexts;

import org.apache.http.entity.StringEntity;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

import org.glassfish.jersey.internal.util.Base64;

import org.jdom.Document;

import org.jdom.Element;

import org.jdom.input.SAXBuilder;

import com.zhiweism.util.MD5;

import com.zhiweism.util.Util;

/*

* 用户发起统一下单请求

* 作者:董志平

* 用于发起微信扫码支付接口

*/

public class WXRequestUtil {

private static String WXSign = null;

测试

public static void main(String[] args) {

//Map res = SendPayment("苹果","20170106113325",1,0);

}

/*

* 发起支付请求

* body商品描述

* out_trade_no订单号

* total_fee订单金额单位 元

* product_id商品ID

*/

public static Map SendPayment(String body,String out_trade_no,double total_fee,int app_type){

String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

String xml = WXParamGenerate(body,out_trade_no,total_fee,app_type);

String res = httpsRequest(url,"POST",xml);

Map data = null;

try {

data = doXMLParse(res);

} catch (Exception e) {

data = null;

}

return data;

}

/**

* 获取签名

* @return

*/

public static String getWXSign() {

return WXSign;

}

/**

* 获得随机字符串

*

*/

public static String NonceStr(){

String res = Base64.encodeAsString(Math.random()+"::"+new Date().toString()).substring(0, 30);

return res;

}

/**

* 获取时间戳

*/

public static String GetTimeStamp(){

int t = (int)(System.currentTimeMillis()/1000);

return t+"";

}

/**

* 获取用户的ip

*

*/

public static String GetIp() {

InetAddress ia=null;

try {

ia=InetAddress.getLocalHost();

String localip=ia.getHostAddress();

return localip;

} catch (Exception e) {

return null;

}

}

/**

* 获取签名

*

*/

public static String GetSign(Map param,int app_type){

String StringA = Util.formatUrlMap(param, false, false);

String stringSignTemp = MD5.md5(StringA+"&key="+ConstantUtil.PARTNER_KEY[app_type]).toUpperCase();

return stringSignTemp;

}

/**

*

* Map转xml数据

*/

public static String GetMapToXML(Map param){

StringBuffer sb = new StringBuffer();

sb.append("");

for (Map.Entry entry : param.entrySet()) {

sb.append("");

sb.append(entry.getValue());

sb.append(""+ entry.getKey() +">");

}

sb.append("");

return sb.toString();

}

//微信统一下单参数设置

public static String WXParamGenerate(String description,String out_trade_no,double total_fee,int app_type){

int fee = (int)(total_fee * 100.00);

Map param = new HashMap();

param.put("appid", ConstantUtil.APP_ID[app_type]);

param.put("mch_id", ConstantUtil.PARTNER[app_type]);

param.put("nonce_str",NonceStr());

param.put("body",description);

param.put("out_trade_no",out_trade_no);

param.put("total_fee", fee+"");

param.put("spbill_create_ip", GetIp());

param.put("notify_url", ConstantUtil.WEIXIN_NOTIFY[app_type]);

param.put("trade_type", "APP");

WXSign = GetSign(param,app_type);

param.put("sign", WXSign);

return GetMapToXML(param);

}

//发起微信支付请求

public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {

try {

URL url = new URL(requestUrl);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setDoOutput(true);

conn.setDoInput(true);

conn.setUseCaches(false);

// 设置请求方式(GET/POST)

conn.setRequestMethod(requestMethod);

conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");

// 当outputStr不为null时向输出流写数据

if (null != outputStr) {

OutputStream outputStream = conn.getOutputStream();

// 注意编码格式

outputStream.write(outputStr.getBytes("UTF-8"));

outputStream.close();

}

// 从输入流读取返回内容

InputStream inputStream = conn.getInputStream();

InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");

BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

String str = null;

StringBuffer buffer = new StringBuffer();

while ((str = bufferedReader.readLine()) != null) {

buffer.append(str);

}

// 释放资源

bufferedReader.close();

inputStreamReader.close();

inputStream.close();

inputStream = null;

conn.disconnect();

return buffer.toString();

} catch (ConnectException ce) {

System.out.println("连接超时:{}"+ ce);

} catch (Exception e) {

System.out.println("https请求异常:{}"+ e);

}

return null;

}

//退款的请求方法

public static String httpsRequest2(String requestMethod, String outputStr) throws Exception {

KeyStore keyStore = KeyStore.getInstance("PKCS12");

StringBuilder res = new StringBuilder("");

FileInputStream instream = new FileInputStream(new File("/home/apiclient_cert.p12"));

try {

keyStore.load(instream, "".toCharArray());

} finally {

instream.close();

}

// Trust own CA and all self-signed certs

SSLContext sslcontext = SSLContexts.custom()

.loadKeyMaterial(keyStore, "1313329201".toCharArray())

.build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(

sslcontext,

new String[] { "TLSv1" },

null,

SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom()

.setSSLSocketFactory(sslsf)

.build();

try {

HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");

httpost.addHeader("Connection", "keep-alive");

httpost.addHeader("Accept", "*/*");

httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

httpost.addHeader("Host", "api.mch.weixin.qq.com");

httpost.addHeader("X-Requested-With", "XMLHttpRequest");

httpost.addHeader("Cache-Control", "max-age=0");

httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");

StringEntity entity2 = new StringEntity(outputStr ,Consts.UTF_8);

httpost.setEntity(entity2);

System.out.println("executing request" + httpost.getRequestLine());

CloseableHttpResponse response = httpclient.execute(httpost);

try {

HttpEntity entity = response.getEntity();

System.out.println("----------------------------------------");

System.out.println(response.getStatusLine());

if (entity != null) {

System.out.println("Response content length: " + entity.getContentLength());

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));

String text = "";

res.append(text);

while ((text = bufferedReader.readLine()) != null) {

res.append(text);

System.out.println(text);

}

}

EntityUtils.consume(entity);

} finally {

response.close();

}

} finally {

httpclient.close();

}

return res.toString();

}

//xml解析

public static Map doXMLParse(String strxml) throws Exception {

strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

if(null == strxml || "".equals(strxml)) {

return null;

}

Map m = new HashMap();

InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));

SAXBuilder builder = new SAXBuilder();

Document doc = builder.build(in);

Element root = doc.getRootElement();

List list = root.getChildren();

Iterator it = list.iterator();

while(it.hasNext()) {

Element e = (Element) it.next();

String k = e.getName();

String v = "";

List children = e.getChildren();

if(children.isEmpty()) {

v = e.getTextNormalize();

} else {

v = getChildrenText(children);

}

m.put(k, v);

}

//关闭流

in.close();

return m;

}

//xml解析

public static SortedMap doXMLParseWithSorted(String strxml) throws Exception {

strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

if(null == strxml || "".equals(strxml)) {

return null;

}

SortedMap m = new TreeMap();

InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));

SAXBuilder builder = new SAXBuilder();

Document doc = builder.build(in);

Element root = doc.getRootElement();

List list = root.getChildren();

Iterator it = list.iterator();

while(it.hasNext()) {

Element e = (Element) it.next();

String k = e.getName();

String v = "";

List children = e.getChildren();

if(children.isEmpty()) {

v = e.getTextNormalize();

} else {

v = getChildrenText(children);

}

m.put(k, v);

}

//关闭流

in.close();

return m;

}

public static String getChildrenText(List children) {

StringBuffer sb = new StringBuffer();

if(!children.isEmpty()) {

Iterator it = children.iterator();

while(it.hasNext()) {

Element e = (Element) it.next();

String name = e.getName();

String value = e.getTextNormalize();

List list = e.getChildren();

sb.append("");

if(!list.isEmpty()) {

sb.append(getChildrenText(list));

}

sb.append(value);

sb.append("" + name + ">");

}

}

return sb.toString();

}

}

修改微信ResponseHandler.java

package com.tenpay;

import java.io.IOException;

import java.io.PrintWriter;

import java.io.UnsupportedEncodingException;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import java.util.SortedMap;

import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.tenpay.util.MD5Util;

import com.tenpay.util.TenpayUtil;

/**

*

* @author miklchen

*

*/

public class ResponseHandler {

private String key;

private SortedMap parameters;

private String debugInfo;

private HttpServletRequest request;

private HttpServletResponse response;

private String uriEncoding;

/**

*

* @param request

* @param response

*/

public ResponseHandler(HttpServletRequest request,

HttpServletResponse response) {

this.request = request;

this.response = response;

this.key = "";

this.parameters = new TreeMap();

this.debugInfo = "";

this.uriEncoding = "";

}

/**

*/

public String getKey() {

return key;

}

/**

*

*/

public void setKey(String key) {

this.key = key;

}

/**

* @param parameter

* @return String

*/

public String getParameter(String parameter) {

String s = (String)this.parameters.get(parameter);

return (null == s) ? "" : s;

}

/**

* @param parameter

* @param parameterValueֵ

*/

public void setParameter(String parameter, String parameterValue) {

String v = "";

if(null != parameterValue) {

v = parameterValue.trim();

}

this.parameters.put(parameter, v);

}

/**

*

* @return SortedMap

*/

public SortedMap getAllParameters() {

return this.parameters;

}

public void setAllparamenters(SortedMap map){

this.parameters = map;

}

/**

* 微信异步回调签名

* @return boolean

*/

public boolean isTenpaySign() {

StringBuffer sb = new StringBuffer();

Set es = this.parameters.entrySet();

Iterator it = es.iterator();

while(it.hasNext()) {

Map.Entry entry = (Map.Entry)it.next();

String k = (String)entry.getKey();

String v = (String)entry.getValue();

if(!"sign".equals(k) && null != v && !"".equals(v)) {

sb.append(k + "=" + v + "&");

}

}

sb.append("key="+this.getKey());

String enc = TenpayUtil.getCharacterEncoding(this.request, this.response);

String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();

String tenpaySign = this.getParameter("sign").toLowerCase();

System.out.println("sign:"+sign+" tenpaysign:"+tenpaySign);

return tenpaySign.equals(sign);

}

/**

*

* @throws IOException

*/

public void sendToCFT(String msg) throws IOException {

String strHtml = msg;

PrintWriter out = this.getHttpServletResponse().getWriter();

out.println(strHtml);

out.flush();

out.close();

}

/**

*

* @return String

*/

public String getUriEncoding() {

return uriEncoding;

}

/**

* @param uriEncoding

* @throws UnsupportedEncodingException

*/

public void setUriEncoding(String uriEncoding)

throws UnsupportedEncodingException {

if (!"".equals(uriEncoding.trim())) {

this.uriEncoding = uriEncoding;

String enc = TenpayUtil.getCharacterEncoding(request, response);

Iterator it = this.parameters.keySet().iterator();

while (it.hasNext()) {

String k = (String) it.next();

String v = this.getParameter(k);

v = new String(v.getBytes(uriEncoding.trim()), enc);

this.setParameter(k, v);

}

}

}

/**

*/

public String getDebugInfo() {

return debugInfo;

}

/**

*

*/

protected void setDebugInfo(String debugInfo) {

this.debugInfo = debugInfo;

}

protected HttpServletRequest getHttpServletRequest() {

return this.request;

}

protected HttpServletResponse getHttpServletResponse() {

return this.response;

}

}

试试是不是已经可以发起异步回调了。记得key  在  微信支付 -》API安全  下面设置。

标签:

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页