微信app支付 java后台接Android

抽时间整理一下之前项目中的微信app支付,以备以后需要,如果对你可以有点帮助是最好不过的;

直接上代码:

public class WeChatAppConfig {
	
	 /**
	    * 预支付请求地址
	    */
	   public static final String  PrepayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	 
	   /**
	    * 查询订单地址
	    */
	   public static final String  OrderUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
	 
	   /**
	    * 关闭订单地址
	    */
	   public static final String  CloseOrderUrl = "https://api.mch.weixin.qq.com/pay/closeorder";
	 
	   /**
	    * 申请退款地址
	    */
	   public static final String  RefundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
	 
	   /**
	    * 查询退款地址
	    */
	   public static final String  RefundQueryUrl = "https://api.mch.weixin.qq.com/pay/refundquery";
	 
	   /**
	    * 下载账单地址
	    */
	   public static final String  DownloadBillUrl = "https://api.mch.weixin.qq.com/pay/downloadbill";
	 
	   /**
	    * 商户APPID
	    */
	   public static final String  AppId = "此处是商户appid";
	 
	   /**
	    * 商户账户 获取支付能力后,从邮件中得到
	    */
	   public static final String  MchId = "此处是mchid";
	 
	   /**
	    * 商户秘钥  32位,在微信商户平台中设置 api安全下的设置密钥(不是开放平台 )  注意!!! 注意!!!!
	    */
	   public static final String  AppSercret = "此处是商户密钥";
	 
	   /**
	    * sign type
	    */
	   public static final String  Sign = "MD5";
	   
	   /**
	    * 服务器异步通知页面路径
	    */
	  public static String notify_url = "http://catering.saimark.xusage.com/catering/a/****** (为后台url)";
	 
	   /**
	    * 页面跳转同步通知页面路径
	    */
	   public static String return_url = "此处为后台url";
	 
	   /**
	    * 退款通知地址
	    */
	   public static String refund_notify_url = "此处为后台url";
	 
	   /**
	    * 退款需要证书文件,证书文件的地址
	    */
	   public static String refund_file_path = "此处为后台url";
	 
	   /**
	    * 商品名称
	    */
	   public static String subject =  "subject(自己按需要更改,也可以传值进入)";
	 
	   /**
	    * 商品描述
	    */
	   public static String body = "微信支付(自己按需要更改,也可以传值进入)";
	 
	/*   private static  Properties properties;
	 
	   public static synchronized Properties getProperties(){
	      if(properties == null){
	         String path = System.getenv(RSystemConfig.KEY_WEB_HOME_CONF) + "/weichart.properties";
	         properties = PropertiesUtil.getInstance().getProperties(path);
	      }
	      return properties;
*/

}

HttpClientUtil:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
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;

public class HttpClientUtil {

	public static String post(String url, Map<String, String> headMap, Map<String, String> params) {
		try {
			HttpClient httpclient = new HttpClient();
			httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			PostMethod httpPost = new PostMethod(url);
			if (null != headMap) {
				for (String key : headMap.keySet()) {
					httpPost.setRequestHeader(key, headMap.get(key));
				}
			}

			if (null != params) {
				for (String pkey : params.keySet()) {
					httpPost.addParameter(pkey, params.get(pkey));
				}
			}
			httpclient.executeMethod(httpPost);

			BufferedReader reader = new BufferedReader(new InputStreamReader(httpPost.getResponseBodyAsStream()));
			StringBuffer stringBuffer = new StringBuffer();
			String str = "";
			while ((str = reader.readLine()) != null) {
				stringBuffer.append(str);
			}
			reader.close();
			return stringBuffer.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String postHttplient(String url, String xmlInfo) {
		try {
			HttpClient httpclient = new HttpClient();
			httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			PostMethod httpPost = new PostMethod(url);
			httpPost.setRequestEntity(new StringRequestEntity(xmlInfo));
			httpclient.executeMethod(httpPost);

			BufferedReader reader = new BufferedReader(new InputStreamReader(httpPost.getResponseBodyAsStream()));
			StringBuffer stringBuffer = new StringBuffer();
			String str = "";
			while ((str = reader.readLine()) != null) {
				stringBuffer.append(str);
			}
			reader.close();
			return stringBuffer.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 需要加密执行的
	 * 
	 * @param url
	 * @param xmlInfo
	 * @return
	 * @throws Exception
	 */
	public static String postHttplientNeedSSL(String url, String xmlInfo, String cretPath, String mrchId)
			throws Exception {
		// 选择初始化密钥文件格式
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		// 得到密钥文件流
		FileInputStream instream = new FileInputStream(new File(cretPath));
		try {
			// 用商户的ID 来解读文件
			keyStore.load(instream, mrchId.toCharArray());
		} finally {
			instream.close();
		}
		// 用商户的ID 来加载
		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mrchId.toCharArray()).build();
		// Allow TLSv1 protocol only
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		// 用最新的httpclient 加载密钥
		CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		StringBuffer ret = new StringBuffer();
		try {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new StringEntity(xmlInfo));
			CloseableHttpResponse response = httpclient.execute(httpPost);
			try {
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
					String text;
					while ((text = bufferedReader.readLine()) != null) {
						ret.append(text);
					}
				}
				EntityUtils.consume(entity);
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
		return ret.toString();
	}

	public static String postHtpps(String urlStr, String xmlInfo) {
		try {
			URL url = new URL(urlStr);
			URLConnection con = url.openConnection();
			con.setDoOutput(true);
			//con.setRequestProperty("Pragma:", "no-cache");
			con.setRequestProperty("Cache-Control", "no-cache");
			con.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
			OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), "utf-8");
			out.write(xmlInfo);
			out.flush();
			out.close();
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
			StringBuffer lines = new StringBuffer();
			String line = "";
			for (line = br.readLine(); line != null; line = br.readLine()) {
				lines.append(line);
			}
			return lines.toString();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

}

WeiMd5:

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class WeiMd5 {

	// 全局数组
    private final static String[] strDigits = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    // 返回形式为数字跟字符串
    private static String byteToArrayString(byte bByte) {
        int iRet = bByte;
        // System.out.println("iRet="+iRet);
        if (iRet < 0) {
            iRet += 256;
        }
        int iD1 = iRet / 16;
        int iD2 = iRet % 16;
        return strDigits[iD1] + strDigits[iD2];
    }


    // 转换字节数组为16进制字串
    private static String byteToString(byte[] bByte) {
        StringBuffer sBuffer = new StringBuffer();
        for (int i = 0; i < bByte.length; i++) {
            sBuffer.append(byteToArrayString(bByte[i]));
        }
        return sBuffer.toString();
    }

    public static String encode(String strObj) {
        String resultString = null;
        try {
            resultString = new String(strObj);
            MessageDigest md = MessageDigest.getInstance("MD5");
            // md.digest() 该函数返回值为存放哈希值结果的byte数组
            try{
               resultString = byteToString(md.digest(strObj.getBytes("UTF-8")));
            }catch(UnsupportedEncodingException e){
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return resultString;
    }
	
}

WeiChartUtil:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import xusage.xcharge.support.xentity.RechargeUpdateFromWechatAppNotify;


public class WeiChartUtil {

	   /**
	    * 返回状态码
	    */
	   public static final String ReturnCode = "return_code";

	   /**
	    * 返回信息
	    */
	   public static final String ReturnMsg = "return_msg";

	   /**
	    * 业务结果
	    */
	   public static final String ResultCode = "result_code";

	   /**
	    * 预支付交易会话标识
	    */
	   public static final String PrepayId = "prepay_id";
	   /**
	    * 得到微信预付单的返回ID
	    * @param orderId  商户自己的订单号
	    * @param totalFee  总金额  (分)
	    * @return
	    */
	   public static Map<String, String> getPreyId(String orderId,
	                                  String totalFee,String schoolLabel){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());

	      reqMap.put("body", schoolLabel+"_"+ WeChatAppConfig.body);
	      //reqMap.put("detail", WeChatAppConfig.subject); //非必填
	      //reqMap.put("attach", "附加数据"); //非必填
	      reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
	      reqMap.put("total_fee", changeToFen(Double.valueOf(totalFee))); //订单总金额,单位为分
	      reqMap.put("spbill_create_ip", getHostIp()); //用户端实际ip
	      Date date = new Date();
	      //reqMap.put("time_start", String.valueOf(date.getTime()/1000)); //交易起始时间 非必填
	      // reqMap.put("time_expire", "172.16.40.18"); //交易结束时间  非必填
	      // reqMap.put("goods_tag", "172.16.40.18"); //商品标记 非必填
	      reqMap.put("notify_url", WeChatAppConfig.notify_url); //通知地址
	      reqMap.put("trade_type", "APP"); //交易类型
	      //reqMap.put("limit_pay", "no_credit"); //指定支付方式,no_credit 指定不能使用信用卡支  非必填
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.PrepayUrl, reqStr);
	      return getInfoByXml(retStr);
	   }

	   /**
	    * 关闭订单
	    * @param orderId  商户自己的订单号
	    * @return
	    */
	   public static Map<String, String> closeOrder(String orderId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.CloseOrderUrl, reqStr);
	      return getInfoByXml(retStr);
	   }


	   /**
	    * 查询订单
	    * @param orderId 商户自己的订单号
	    * @return
	    */
	   public static Map<String, String> getOrder(String orderId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.OrderUrl, reqStr);
	      //return retStr;
	      return getInfoByXml(retStr);
	   }


	   /**
	    * 退款
	    * @param orderId  商户订单号
	    * @param refundId  退款单号
	    * @param totralFee 总金额(分)
	    * @param refundFee 退款金额(分)
	    * @param opUserId 操作员ID
	    * @return
	    */
	   public static Map<String, String> refundWei(String orderId,String refundId,String totralFee,String refundFee,String opUserId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
	      reqMap.put("out_refund_no", refundId); //商户退款单号
	      reqMap.put("total_fee", totralFee); //总金额
	      reqMap.put("refund_fee", refundFee); //退款金额
	      reqMap.put("op_user_id", opUserId); //操作员
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = "";
	      try{
	         retStr = HttpClientUtil.postHttplientNeedSSL(WeChatAppConfig.RefundUrl, reqStr, WeChatAppConfig.refund_file_path, WeChatAppConfig.MchId);
	      }catch(Exception e){
	         e.printStackTrace();
	         return null;
	      }
	      return getInfoByXml(retStr);
	   }


	   /**
	    * 退款查询
	    * @param refundId  退款单号
	    * @return
	    */
	   public static Map<String, String> getRefundWeiInfo(String refundId){
	      Map<String, String> reqMap = new HashMap<String, String>();
	      reqMap.put("appid", WeChatAppConfig.AppId);
	      reqMap.put("mch_id", WeChatAppConfig.MchId);
	      reqMap.put("nonce_str", getRandomString());
	      reqMap.put("out_refund_no", refundId); //商户退款单号
	      reqMap.put("sign", getSign(reqMap));

	      String reqStr = creatXml(reqMap);
	      String retStr = HttpClientUtil.postHtpps(WeChatAppConfig.RefundQueryUrl, reqStr);
	      return getInfoByXml(retStr);
	   }

	   /**这个方法 可以自己写,以前我使用的是我公司封装的类,后来很多人找我要JAR包,所以我改成了这样,方便部分人直接使用代码,我自己未测试,不过应该问题不大,欢迎使用有问题的找我。
	    * 传入map  生成头为XML的xml字符串,例:<xml><key>123</key></xml>
	    * @param reqMap
	    * @return
	    */
	   public static String creatXml(Map<String, String> reqMap){
	      Set<String> set = reqMap.keySet();
	      StringBuffer b = new StringBuffer();
	      b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	      b.append("<xml>");
	      for(String key : set){
	         b.append("<"+key+">").append(reqMap.get(key)).append("</"+key+">");
	      }
	      b.append("</xml>");
	      return b.toString();
	   }

	   /**
	    * 得到加密值
	    * @param map
	    * @return
	    */
	   public static String getSign(Map<String, String> map){
	      String[] keys = map.keySet().toArray(new String[0]);
	      Arrays.sort(keys);
	      StringBuffer reqStr = new StringBuffer();
	      for(String key : keys){
	         String v = map.get(key);
	         if(v != null && !v.equals("")){
	            reqStr.append(key).append("=").append(v).append("&");
	         }
	      }
	      reqStr.append("key").append("=").append(WeChatAppConfig.AppSercret);

	      return WeiMd5.encode(reqStr.toString()).toUpperCase();
	   }

	   /**
	    * 得到10 位的时间戳
	    * 如果在JAVA上转换为时间要在后面补上三个0 
	    * @return
	    */
	   public static String getTenTimes(){
	      String t = new Date().getTime()+"";
	      t = t.substring(0, t.length()-3);
	      return t;
	   }

	   /**
	    * 得到随机字符串
	    * @param length
	    * @return
	    */
	   public static String getRandomString(){
	      int length = 32;
	      String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	      Random random = new Random();
	      StringBuffer sb = new StringBuffer();

	      for(int i = 0; i < length; ++i){
	         int number = random.nextInt(62);//[0,62)  
	         sb.append(str.charAt(number));
	      }
	      return sb.toString();
	   }

	   /**
	    * 得到本地机器的IP
	    * @return
	    */
	   private static String getHostIp(){
	      String ip = "";
	      try{
	         ip = InetAddress.getLocalHost().getHostAddress();
	      }catch(UnknownHostException e){
	         e.printStackTrace();
	      }
	      return ip;
	   }
	   /**
	    * 将xml解析成map
	    * @param xmlStr
	    * @return
	    */
	   public static Map<String, String> getInfoByXml(String xmlStr){
	      try{
	         Map<String, String> m = new HashMap<String, String>();
	         Document d = DocumentHelper.parseText(xmlStr);
	         Element root = d.getRootElement();
	         for ( Iterator<?> i = root.elementIterator(); i.hasNext(); ) {
	            Element element = (Element) i.next();
	            String name = element.getName();
	            if(!element.isTextOnly()){
	               //不是字符串 跳过。确定了微信放回的xml只有根目录
	               continue;
	            }else{
	               m.put(name, element.getTextTrim());
	            }
	         }
	         //对返回结果做校验.去除sign 字段再去加密
	         String retSign = m.get("sign");
	         m.remove("sign");
	         String rightSing = getSign(m);
	         if(rightSing.equals(retSign)){
	        	m.put("sign", retSign);
	            return m;
	         }
	      }catch(DocumentException e){
	         e.printStackTrace();
	      }
	      return null;
	}

	   /**
	    * 将金额转换成分
	    * @param fee 元格式的
	    * @return 分
	    */
	   public static String changeToFen(Double fee){
	      String priceStr = "";
	      if(fee != null){
	          int p = (int)(fee * 100); //价格变为分
	          priceStr = Integer.toString(p);
	      }
	      return priceStr;
	   }
	   

	   /**
	     * 接收微信的异步通知
	     * 
	     * @throws IOException
	     */
	    public static String reciverWx(HttpServletRequest request) throws IOException
	    {
	        InputStream inputStream;
	        StringBuffer sb = new StringBuffer();
	        inputStream = request.getInputStream();
	        String s;
	        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
	        while ((s = in.readLine()) != null)
	        {
	            sb.append(s);
	        }
	        in.close();
	        inputStream.close();
	        return sb.toString();
	    }
	    
	    /**
	     * 验证回调签名
	     * @return
	     */
	   /* public static boolean isTenpaySign(Map<String, String> map) {
	       String signFromAPIResponse = map.get("sign");
	       if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
	    	   LOGGER.error("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
	    	   return false;
	       }
	       LOGGER.info("服务器回包里面的签名是:" + signFromAPIResponse);
	     //将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
	     //算出签名
	       String resultSign = "";
	       map.remove("sign");
	       String tobesign = getSign(map);
    	   try{
    		   resultSign = WeiMd5.encode(tobesign).toUpperCase();
    	   }catch (Exception e) {
    		   resultSign = WeiMd5.encode(tobesign).toUpperCase();
    	   }
    	   LOGGER.info("微信回调;再次验证签名正确与否生成的签名:{}", resultSign);
	       String tenpaySign = signFromAPIResponse.toUpperCase();
	       return tenpaySign.equals(resultSign);

	    } */
	    private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(WeiChartUtil.class);

}

至此,如果配置好config数据后 不出意外就可以得到prepayid了;

Android端需要的数据为: appid  partnerid  prepayid  noncestr  package  timestamp;

这时有几个地方需要注意:

1. 获取prepayid后 返回给Android端的是需要二次签名的;也就是说再次获取通过WeiChartUtil.getSign()获取签名,传入只包含这6个参数的map(也要注意这6个参数名的大小写,微信端定义好的);

2.package 现在默认值为 “Sign=WXPay” ;

3.timestamp 为十位的时间戳 ,自己做下处理,去掉后三位即可; 不过看到有说timestamp和noncestr在Android端可以那边自己做;反正我是一并处理返回过去了;

好了;后台支付的接口至此结束,接下来就是Android端的对接了;

 

接下来是支付完成后,微信会请求事先再WeChatAppConfig中配置好的回调url;

这里我就只放处理的代码了:

			String sb = WeiChartUtil.reciverWx(request);
			//解析xml成map  
			Map<String, String> xmlMap = new HashMap<String, String>();  
			xmlMap = WeiChartUtil.getInfoByXml(sb);  //此方法里已经验证过是否是微信返回的签名
			//判断签名是否正确  
			if(xmlMap != null) {  
				//------------------------------  
				//处理业务开始  
				//------------------------------  
				String resXml = "";  
				if("SUCCESS".equals((String)xmlMap.get("result_code"))){  
					// 这里是支付成功  
					//执行自己的业务逻辑  
					String mch_id = (String)xmlMap.get("mch_id");  
					String openid = (String)xmlMap.get("openid");  
					String is_subscribe = (String)xmlMap.get("is_subscribe");  
					String out_trade_no = (String)xmlMap.get("out_trade_no");    //这个就是我们内部传给微信的订单号
					String total_fee = (String)xmlMap.get("total_fee");  
					LOGGER.info("is_subscribe:{}, out_trade_no: {}, total_fee: {},mch_id: {}, openid: {}",is_subscribe,out_trade_no,total_fee,mch_id,openid);  
					
					
					//执行自己的业务逻辑  
					LOGGER.info("支付成功");  
					//通知微信.异步确认成功.必写.不然会一直通知后台.九次之后就认为交易失败了.  通知频率为15/15/30/180/1800/1800/1800/1800/3600 
					resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
							+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  
					result.setResXml("SUCCESS");
				} else {  
					result.setResXml("FAIL");
					LOGGER.info("支付失败,错误信息:" + xmlMap.get("err_code"));  
					resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
							+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
				}  
				//------------------------------  
				//处理业务完毕  
				//------------------------------  
				BufferedOutputStream out = new BufferedOutputStream(  
						response.getOutputStream());  
				out.write(resXml.getBytes());
				out.flush();  
				out.close();  
			} else{  
				result.setResXml("FAIL");
				LOGGER.info("通知签名验证失败");  
			}  

再接收到回调时候,最好是要对签名做下再次认证的,因为我图方便,将再次认证就放在getInfoByXml()方法里的,这个是可以直接拿来用的,如果觉得想分离出来手动处理下吧,再WeiChatUtils中最下边也有现成的注释掉的方法;

如果项目需要做单笔交易查询再次认证;调用相应的方法即可;传入自己数据库中订单的id去查询(out_trade_no:商户系统内部的订单号)

好啦;微信app支付到此结束; 希望对你能有帮助 

  • 6
    点赞
  • 3
    收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿门阿前那棵葡萄树

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值