java微信公众号支付示例

开始之前,先准备好:appid、商家号、商户密匙。

工具类:

MD5Util.java

 1 package com.yiexpress.core.utils.wechat;
 2 
 3 import java.security.MessageDigest;
 4 
 5 /** 
 6  * MD5工具类 
 7  */  
 8 public class MD5Util {  
 9     public final static String MD5(String s) {  
10         char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};         
11   
12         try {  
13             byte[] btInput = s.getBytes();  
14          
15             MessageDigest mdInst = MessageDigest.getInstance("MD5");  
16            
17             mdInst.update(btInput);  
18           
19             byte[] md = mdInst.digest();  
20             
21             int j = md.length;  
22             char str[] = new char[j * 2];  
23             int k = 0;  
24             for (int i = 0; i < j; i++) {  
25                 byte byte0 = md[i];  
26                 str[k++] = hexDigits[byte0 >>> 4 & 0xf];  
27                 str[k++] = hexDigits[byte0 & 0xf];  
28             }  
29             String md5Str = new String(str);   
30             return md5Str;  
31         } catch (Exception e) {  
32             e.printStackTrace();  
33             return null;  
34         }  
35     }  
36 }  

SapUtils.java

  1 package com.yiexpress.core.utils;
  2 import java.lang.reflect.*;
  3 import java.util.List;
  4 import java.io.IOException;
  5 import java.io.StringWriter;
  6 
  7 import org.dom4j.Document;
  8 import org.dom4j.DocumentHelper;
  9 import org.dom4j.Element;
 10 import org.dom4j.io.OutputFormat;
 11 import org.dom4j.io.XMLWriter;
 12 import org.slf4j.Logger;
 13 import org.slf4j.LoggerFactory;
 14 import org.springframework.util.StringUtils;
 15 
 16 
 17 public class SapUtils {
 18     private static final Logger logger = LoggerFactory.getLogger(SapUtils.class);
 19     /** 根据反射对javabean转成xml文件的格式
 20      * 以类名为第一标签,所有属性作为第二节点,并放入对应的值,如果属性为空 就不放入该熟悉
 21      * @param dto 传入的对象
 22      * @param operationName 操作名称
 23      * @return
 24      */
 25     public static String formatToXml(Object dto,String operationName){
 26         logger.info("解析当前类{}为指定的xml文档格式的数据",dto.getClass().getName());
 27         logger.info("当前的同步方法是,{}",operationName);
 28         String result = null;
 29         Field fields[]=dto.getClass().getDeclaredFields();//dto 是实体类名称
 30         //DocumentHelper提供了创建Document对象的方法
 31         Document document = DocumentHelper.createDocument();
 32 
 33         //添加节点信息
 34          String className=dto.getClass().getName();
 35          // 操作的名称
 36         Element rootElement = document.addElement(operationName);
 37         try {
 38             Field.setAccessible(fields, true);
 39             for (int i = 0; i < fields.length; i++) {
 40                 //添加节点信息
 41                 if(!StringUtils.isEmpty(fields[i].get(dto))){
 42                     Class<?> type = fields[i].getType();
 43                     // 如果是list
 44                     if(type == List.class){
 45                         String listName = fields[i].getName();
 46                        createElement(rootElement, fields[i].get(dto),listName);
 47                     }
 48                     else{
 49                         Element element = rootElement.addElement(fields[i].getName());
 50                         element.setText((String) fields[i].get(dto));
 51                     }
 52                 }
 53             }
 54             // 设置XML文档格式
 55             OutputFormat outputFormat = OutputFormat.createPrettyPrint();  
 56             // 设置XML编码方式,即是用指定的编码方式保存XML文档到字符串(String),这里也可以指定为GBK或是ISO8859-1  
 57             outputFormat.setEncoding("UTF-8");
 58             // outputFormat.setSuppressDeclaration(true); //是否生产xml头
 59             outputFormat.setIndent(true); //设置是否缩进
 60             outputFormat.setIndent("    "); //以四个空格方式实现缩进
 61             outputFormat.setNewlines(true); //设置是否换行
 62             StringWriter stringWriter =null;  
 63             // Writer fileWriter =null;
 64             // xmlWriter是用来把XML文档写入字符串的(工具)  
 65             XMLWriter xmlWriter = null;  
 66            try {
 67                    // stringWriter字符串是用来保存XML文档的  
 68                 stringWriter = new StringWriter();  
 69                 // fileWriter = new FileWriter("D:\\modu11le.xml");
 70                 // xmlWriter是用来把XML文档写入字符串的(工具)  
 71                 xmlWriter = new XMLWriter(stringWriter, outputFormat);  
 72                 // 把创建好的XML文档写入字符串  
 73                 xmlWriter.write(document);
 74                 //fileWriter.write(stringWriter.toString());
 75                 result=stringWriter.toString();
 76             } catch (IOException e) {
 77                 logger.error("写入数据失败");
 78                 throw new RuntimeException("写入数据失败"+e);
 79             }finally{
 80                  try {
 81                      if(xmlWriter!=null){
 82                          xmlWriter.flush();
 83                          xmlWriter.close();
 84                      }
 85 /*                     if(fileWriter!=null){
 86                          fileWriter.flush();
 87                          fileWriter.close();
 88                      }*/
 89                      
 90                 } catch (IOException e) {
 91                     logger.error("关闭输出流出错");
 92                     throw new RuntimeException("关闭输出流出错"+e);
 93                 }
 94             }
 95         } catch (Exception e) {
 96             logger.error("添加xml的节点失败"+e);
 97         }
 98         logger.error("转换xml结束");
 99         return result;
100     } 
101     
102     /**
103      * 添加类中的list        
104      * @param element
105      * @param object
106      * @param name
107      * @return
108      * @throws IllegalArgumentException
109      * @throws IllegalAccessException
110      */
111     public static Element createElement(Element element ,Object object,String name ) throws IllegalArgumentException, IllegalAccessException{
112         Element nameElement = element.addElement(name);
113         List info = (List)object;
114         for(int j= 0;j<info.size();j++){
115             // 添加row的标签
116             Element rowElement = nameElement.addElement("row");
117             // 添加 对象的熟悉
118             Field fields[]=info.get(j).getClass().getDeclaredFields();//dto 是实体类名称
119             Field.setAccessible(fields, true);
120             for (int i = 0; i < fields.length; i++) {
121                 //添加节点信息
122                 if(!StringUtils.isEmpty(fields[i].get(info.get(j)))){
123                         Element childElement = rowElement.addElement(fields[i].getName());
124                         childElement.setText((String) fields[i].get(info.get(j)));
125                 }
126             }
127         }
128         return element;    
129     }
130 }

UnifiedOrderRequest.java

package com.yiexpress.core.utils.wechat;

public class UnifiedOrderRequest {
    private String appid;// 公众账号ID  
    private String mch_id;//商户号   
    private String device_info; //设备号   否  
    private String nonce_str;//随机字符串      
    private String sign;//签名     
    private String sign_type;//签名类型   
    private String body;//商品描述       
    private String detail;//商品详情   
    private String attach;//附加数据    
    private String out_trade_no;//商户订单号   
    private String fee_type;//标价币种     
    private String total_fee;//标价金额  
    private String spbill_create_ip;//终端IP   
    private String time_start;//交易起始时间   
    private String time_expire;//交易结束时间  
    private String goods_tag;//订单优惠标记   
    private String notify_url;//通知地址     
    private String trade_type;//交易类型   
    private String product_id;//商品ID  
    private String limit_pay;//指定支付方式  
    private String openid;//用户标识   
    public String getAppid() {
        return appid;
    }
    public void setAppid(String appid) {
        this.appid = appid;
    }
    public String getMch_id() {
        return mch_id;
    }
    public void setMch_id(String mch_id) {
        this.mch_id = mch_id;
    }
    public String getDevice_info() {
        return device_info;
    }
    public void setDevice_info(String device_info) {
        this.device_info = device_info;
    }
    public String getNonce_str() {
        return nonce_str;
    }
    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }
    public String getSign() {
        return sign;
    }
    public void setSign(String sign) {
        this.sign = sign;
    }
    public String getSign_type() {
        return sign_type;
    }
    public void setSign_type(String sign_type) {
        this.sign_type = sign_type;
    }
    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
    public String getDetail() {
        return detail;
    }
    public void setDetail(String detail) {
        this.detail = detail;
    }
    public String getAttach() {
        return attach;
    }
    public void setAttach(String attach) {
        this.attach = attach;
    }
    public String getOut_trade_no() {
        return out_trade_no;
    }
    public void setOut_trade_no(String out_trade_no) {
        this.out_trade_no = out_trade_no;
    }
    public String getFee_type() {
        return fee_type;
    }
    public void setFee_type(String fee_type) {
        this.fee_type = fee_type;
    }
    public String getTotal_fee() {
        return total_fee;
    }
    public void setTotal_fee(String total_fee) {
        this.total_fee = total_fee;
    }
    public String getSpbill_create_ip() {
        return spbill_create_ip;
    }
    public void setSpbill_create_ip(String spbill_create_ip) {
        this.spbill_create_ip = spbill_create_ip;
    }
    public String getTime_start() {
        return time_start;
    }
    public void setTime_start(String time_start) {
        this.time_start = time_start;
    }
    public String getTime_expire() {
        return time_expire;
    }
    public void setTime_expire(String time_expire) {
        this.time_expire = time_expire;
    }
    public String getGoods_tag() {
        return goods_tag;
    }
    public void setGoods_tag(String goods_tag) {
        this.goods_tag = goods_tag;
    }
    public String getNotify_url() {
        return notify_url;
    }
    public void setNotify_url(String notify_url) {
        this.notify_url = notify_url;
    }
    public String getTrade_type() {
        return trade_type;
    }
    public void setTrade_type(String trade_type) {
        this.trade_type = trade_type;
    }
    public String getProduct_id() {
        return product_id;
    }
    public void setProduct_id(String product_id) {
        this.product_id = product_id;
    }
    public String getLimit_pay() {
        return limit_pay;
    }
    public void setLimit_pay(String limit_pay) {
        this.limit_pay = limit_pay;
    }
    public String getOpenid() {
        return openid;
    }
    public void setOpenid(String openid) {
        this.openid = openid;
    }

}

UnifiedOrderRespose.java

package com.yiexpress.core.utils.wechat;

public class UnifiedOrderRespose {
    private String return_code;             //返回状态码  
    private String return_msg;              //返回信息  
    private String appid;                   //公众账号ID  
    private String mch_id;                  //商户号  
    private String device_info;             //设备号  
    private String nonce_str;               //随机字符串  
    private String sign;                    //签名  
    private String result_code;             //业务结果  
    private String err_code;                //错误代码  
    private String err_code_des;            //错误代码描述  
    private String trade_type;              //交易类型  
    private String prepay_id;               //预支付交易会话标识  
    private String code_url;                //二维码链接  
    public String getReturn_code() {
        return return_code;
    }
    public void setReturn_code(String return_code) {
        this.return_code = return_code;
    }
    public String getReturn_msg() {
        return return_msg;
    }
    public void setReturn_msg(String return_msg) {
        this.return_msg = return_msg;
    }
    public String getAppid() {
        return appid;
    }
    public void setAppid(String appid) {
        this.appid = appid;
    }
    public String getMch_id() {
        return mch_id;
    }
    public void setMch_id(String mch_id) {
        this.mch_id = mch_id;
    }
    public String getDevice_info() {
        return device_info;
    }
    public void setDevice_info(String device_info) {
        this.device_info = device_info;
    }
    public String getNonce_str() {
        return nonce_str;
    }
    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }
    public String getSign() {
        return sign;
    }
    public void setSign(String sign) {
        this.sign = sign;
    }
    public String getResult_code() {
        return result_code;
    }
    public void setResult_code(String result_code) {
        this.result_code = result_code;
    }
    public String getErr_code() {
        return err_code;
    }
    public void setErr_code(String err_code) {
        this.err_code = err_code;
    }
    public String getErr_code_des() {
        return err_code_des;
    }
    public void setErr_code_des(String err_code_des) {
        this.err_code_des = err_code_des;
    }
    public String getTrade_type() {
        return trade_type;
    }
    public void setTrade_type(String trade_type) {
        this.trade_type = trade_type;
    }
    public String getPrepay_id() {
        return prepay_id;
    }
    public void setPrepay_id(String prepay_id) {
        this.prepay_id = prepay_id;
    }
    public String getCode_url() {
        return code_url;
    }
    public void setCode_url(String code_url) {
        this.code_url = code_url;
    }
}

WXPayConstants.java

package com.yiexpress.core.utils.wechat;

public class WXPayConstants {
     public enum SignType {  
        MD5, HMACSHA256  
    }  
    public static final String FAIL     = "FAIL";  
    public static final String SUCCESS  = "SUCCESS";  
    public static final String HMACSHA256 = "HMAC-SHA256";  
    public static final String MD5 = "MD5";  
    public static final String FIELD_SIGN = "sign";  
    public static final String FIELD_SIGN_TYPE = "sign_type";
}

WXPayUtil.java

package com.yiexpress.core.utils.wechat;

import java.io.BufferedOutputStream;  
import java.io.BufferedReader;  
import java.io.ByteArrayInputStream;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.io.StringWriter;  
import java.io.Writer;  
import java.net.HttpURLConnection;  
import java.net.URL;  
import java.util.*;  
import java.security.MessageDigest;  

import org.w3c.dom.Node;  
import org.w3c.dom.NodeList;  




import com.yiexpress.core.utils.SapUtils;
import com.yiexpress.core.utils.XmlUtil;


import com.yiexpress.core.utils.wechat.WXPayConstants.SignType;

import javax.crypto.Mac;  
import javax.crypto.spec.SecretKeySpec;  
import javax.xml.parsers.DocumentBuilder;  
import javax.xml.parsers.DocumentBuilderFactory;  
import javax.xml.transform.OutputKeys;  
import javax.xml.transform.Transformer;  
import javax.xml.transform.TransformerFactory;  
import javax.xml.transform.dom.DOMSource;  
import javax.xml.transform.stream.StreamResult;  

import org.jdom2.Document;  
import org.jdom2.Element;  
import org.jdom2.input.SAXBuilder;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
/** 
 * 支付工具类 
 */  
public class WXPayUtil {  
    private static Logger log = LoggerFactory.getLogger(WXPayUtil.class);  
      
    /** 
     * 生成订单对象信息 
     * @param orderId 订单号 
     * @param appId 微信appId 
     * @param mch_id 微信分配的商户ID 
     * @param body  支付介绍主体 
     * @param price 支付价格(放大100倍) 
     * @param spbill_create_ip 终端IP 
     * @param notify_url  异步直接结果通知接口地址 
     * @param noncestr  
     * @return 
     */  
    public static Map<String,Object> createOrderInfo(Map<String, String> requestMap,String shopKey) {    
        //生成订单对象    
        UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();    
        unifiedOrderRequest.setAppid(requestMap.get("appId"));//公众账号ID    
        unifiedOrderRequest.setBody(requestMap.get("body"));//商品描述    
        unifiedOrderRequest.setMch_id(requestMap.get("mch_id"));//商户号    
        unifiedOrderRequest.setNonce_str(requestMap.get("noncestr"));//随机字符串      
        unifiedOrderRequest.setNotify_url(requestMap.get("notify_url"));//通知地址    
        unifiedOrderRequest.setOpenid(requestMap.get("userWeixinOpenId"));  
        unifiedOrderRequest.setDetail(requestMap.get("detail"));//详情  
        unifiedOrderRequest.setOut_trade_no(requestMap.get("out_trade_no"));//商户订单号    
        unifiedOrderRequest.setSpbill_create_ip(requestMap.get("spbill_create_ip"));//终端IP    
        unifiedOrderRequest.setTotal_fee(requestMap.get("payMoney"));  //金额需要扩大100倍:1代表支付时是0.01    
        unifiedOrderRequest.setTrade_type("JSAPI");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付  
        SortedMap<String, String> packageParams = new TreeMap<String, String>();    
        packageParams.put("appid", unifiedOrderRequest.getAppid());    
        packageParams.put("body", unifiedOrderRequest.getBody());    
        packageParams.put("mch_id", unifiedOrderRequest.getMch_id());    
        packageParams.put("nonce_str", unifiedOrderRequest.getNonce_str());    
        packageParams.put("notify_url", unifiedOrderRequest.getNotify_url());  
        packageParams.put("openid", unifiedOrderRequest.getOpenid());  
        packageParams.put("detail", unifiedOrderRequest.getDetail());  
        packageParams.put("out_trade_no", unifiedOrderRequest.getOut_trade_no());    
        packageParams.put("spbill_create_ip", unifiedOrderRequest.getSpbill_create_ip());    
        packageParams.put("total_fee", unifiedOrderRequest.getTotal_fee());    
        packageParams.put("trade_type", unifiedOrderRequest.getTrade_type());
       
        try {  
            unifiedOrderRequest.setSign(generateSignature(packageParams,shopKey));//签名  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        //将订单对象转为xml格式    
        String orderstr=SapUtils.formatToXml(unifiedOrderRequest,"xml").replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>","");
        log.debug("封装好的统一下单请求数据:"+orderstr.replace("__", "_"));  
        Map<String,Object> responseMap = new HashMap<String,Object>();  
        responseMap.put("orderInfo_toString", orderstr.replace("__", "_"));  
        responseMap.put("unifiedOrderRequest",unifiedOrderRequest);  
        return responseMap;    
    }   
      
    public static void main(String[] args) {
//         UnifiedOrderRequest ut=new UnifiedOrderRequest();
//         ut.setAppid("wx1234156789");
//         ut.setBody("内容body");
//         ut.setMch_id("商户号");
//         ut.setNonce_str("随机字符串");
//         ut.setNotify_url("回调地址");
//         ut.setOpenid("openid");
//         ut.setDetail("详情");
//         ut.setOut_trade_no("订单号");
//         ut.setSpbill_create_ip("终端IP");
//         ut.setTotal_fee("金额");
//         ut.setTrade_type("调用类型JSAPI");
//         System.out.println("---"+SapUtils.formatToXml(ut,"xml")+"---");
//         UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();    
//         unifiedOrderRequest.setAppid("dsfsdf");//公众账号ID    
//         unifiedOrderRequest.setBody("sdfsdf");//商品描述    
//         unifiedOrderRequest.setMch_id("sdfsd");//商户号    
//         unifiedOrderRequest.setNonce_str("dfsd");//随机字符串      
//         unifiedOrderRequest.setNotify_url("sdfdsf");//通知地址    
//         unifiedOrderRequest.setOpenid("sdfsdf");  
//             
//         unifiedOrderRequest.setTrade_type("JSAPI");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付  
//         
//         System.out.println("---"+SapUtils.formatToXml(unifiedOrderRequest,"xml").replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>","")+"---");
//         String str="<xml><appid>dsfsdf</appid><mch_id>sdfsd</mch_id><nonce_str>dfsd</nonce_str><body>sdfsdf</body><notify_url>sdfdsf</notify_url><trade_type>JSAPI</trade_type><openid>sdfsdf</openid></xml>";
//         UnifiedOrderRequest s=SapUtils.getBeanByxml(str,UnifiedOrderRequest.class);
//         System.out.println(s.getAppid()+"---"+s.getMch_id()+"--"+s.getFee_type());

    }
    
    /**  
     * 生成签名  
     * @param appid_value  
     * @param mch_id_value  
     * @param productId  
     * @param nonce_str_value  
     * @param trade_type   
     * @param notify_url   
     * @param spbill_create_ip   
     * @param total_fee   
     * @param out_trade_no   
     * @return  
     */    
    private static String createSign(UnifiedOrderRequest unifiedOrderRequest,String shopKey) {    
        //根据规则创建可排序的map集合    
        SortedMap<String, String> packageParams = new TreeMap<String, String>();    
        packageParams.put("appid", unifiedOrderRequest.getAppid());    
        packageParams.put("body", unifiedOrderRequest.getBody());    
        packageParams.put("mch_id", unifiedOrderRequest.getMch_id());    
        packageParams.put("nonce_str", unifiedOrderRequest.getNonce_str());    
        packageParams.put("notify_url", unifiedOrderRequest.getNotify_url());    
        packageParams.put("out_trade_no", unifiedOrderRequest.getOut_trade_no());    
        packageParams.put("spbill_create_ip", unifiedOrderRequest.getSpbill_create_ip());    
        packageParams.put("trade_type", unifiedOrderRequest.getTrade_type());    
        packageParams.put("total_fee", unifiedOrderRequest.getTotal_fee());    
        StringBuffer sb = new StringBuffer();    
        Set es = packageParams.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 (null != v && !"".equals(v) && !"sign".equals(k)  && !"key".equals(k)) {    
                sb.append(k + "=" + v + "&");    
            }    
        }    
        //第二步拼接key,key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置    
        sb.append("key="+shopKey);    
        String sign = MD5Util.MD5(sb.toString()).toUpperCase();//MD5加密    
        log.error("方式一生成的签名="+sign);  
        return sign;    
    }    
      
    //xml解析      
    public static SortedMap<String, String> doXMLParseWithSorted(String strxml) throws Exception {      
          strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");      
          if(null == strxml || "".equals(strxml)) {      
              return null;      
          }      
          SortedMap<String,String> m = new TreeMap<String,String>();       
          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("<" + name + ">");      
                if(!list.isEmpty()) {      
                    sb.append(getChildrenText(list));      
                }      
                sb.append(value);      
                sb.append("</" + name + ">");      
            }      
        }       
        return sb.toString();      
    }   
    /**  
     * 调统一下单API  
     * @param orderInfo  
     * @return  
     */    
    public static UnifiedOrderRespose httpOrder(String orderInfo,int index) {
        //统一下单接口地址 自动适应  1中国境内  2东南亚   3其他
        String[] urlList={"https://api.mch.weixin.qq.com/pay/unifiedorder","https://apihk.mch.weixin.qq.com/pay/unifiedorder"
                ,"https://apius.mch.weixin.qq.com/pay/unifiedorder "};
        //String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";    
        try {    
            HttpURLConnection conn = (HttpURLConnection) new URL(urlList[index]).openConnection();    
            //加入数据      
            conn.setRequestMethod("POST");      
            conn.setDoOutput(true);      
            BufferedOutputStream buffOutStr = new BufferedOutputStream(conn.getOutputStream());      
            buffOutStr.write(orderInfo.getBytes("UTF-8"));    
            buffOutStr.flush();      
            buffOutStr.close();      
            //获取输入流      
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));      
            String line = null;      
            StringBuffer sb = new StringBuffer();      
            while((line = reader.readLine())!= null){      
                sb.append(line);      
            }   
            //xml转对象
            UnifiedOrderRespose unifiedOrderRespose =XmlUtil.getBeanByxml(sb.toString(),UnifiedOrderRespose.class);    
            return unifiedOrderRespose;  
        } catch (Exception e) {    
            e.printStackTrace();    
        }    
        return null;    
    }
    
    /** 
     * XML格式字符串转换为Map 
     * 
     * @param strXML XML字符串 
     * @return XML数据转换后的Map 
     * @throws Exception 
     */  
    public static Map<String, String> xmlToMap(String strXML) throws Exception {  
        try {  
            Map<String, String> data = new HashMap<String, String>();  
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();  
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();  
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));  
            org.w3c.dom.Document doc = documentBuilder.parse(stream);  
            doc.getDocumentElement().normalize();  
            NodeList nodeList = doc.getDocumentElement().getChildNodes();  
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {  
                Node node = nodeList.item(idx);  
                if (node.getNodeType() == Node.ELEMENT_NODE) {  
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;  
                    data.put(element.getNodeName(), element.getTextContent());  
                }  
            }  
            try {  
                stream.close();  
            } catch (Exception ex) {  
                // do nothing  
            }  
            return data;  
        } catch (Exception ex) {  
            WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);  
            throw ex;  
        }  
  
    }  
  
    /** 
     * 将Map转换为XML格式的字符串 
     * 
     * @param data Map类型数据 
     * @return XML格式的字符串 
     * @throws Exception 
     */  
    public static String mapToXml(Map<String, String> data) throws Exception {  
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();  
        DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();  
        org.w3c.dom.Document document = documentBuilder.newDocument();  
        org.w3c.dom.Element root = document.createElement("xml");  
        document.appendChild(root);  
        for (String key: data.keySet()) {  
            String value = data.get(key);  
            if (value == null) {  
                value = "";  
            }  
            value = value.trim();  
            org.w3c.dom.Element filed = document.createElement(key);  
            filed.appendChild(document.createTextNode(value));  
            root.appendChild(filed);  
        }  
        TransformerFactory tf = TransformerFactory.newInstance();  
        Transformer transformer = tf.newTransformer();  
        DOMSource source = new DOMSource(document);  
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");  
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");  
        StringWriter writer = new StringWriter();  
        StreamResult result = new StreamResult(writer);  
        transformer.transform(source, result);  
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");  
        try {  
            writer.close();  
        }  
        catch (Exception ex) {  
        }  
        return output;  
    }  
  
  
    /** 
     * 生成带有 sign 的 XML 格式字符串 
     * 
     * @param data Map类型数据 
     * @param key API密钥 
     * @return 含有sign字段的XML 
     */  
    public static String generateSignedXml(final Map<String, String> data, String key) throws Exception {  
        return generateSignedXml(data, key, SignType.MD5);  
    }  
  
    /** 
     * 生成带有 sign 的 XML 格式字符串 
     * 
     * @param data Map类型数据 
     * @param key API密钥 
     * @param signType 签名类型 
     * @return 含有sign字段的XML 
     */  
    public static String generateSignedXml(final Map<String, String> data, String key, SignType signType) throws Exception {  
        String sign = generateSignature(data, key, signType);  
        data.put(WXPayConstants.FIELD_SIGN, sign);  
        return mapToXml(data);  
    }  
  
  
    /** 
     * 判断签名是否正确 
     * 
     * @param xmlStr XML格式数据 
     * @param key API密钥 
     * @return 签名是否正确 
     * @throws Exception 
     */  
    public static boolean isSignatureValid(String xmlStr, String key) throws Exception {  
        Map<String, String> data = xmlToMap(xmlStr);  
        if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {  
            return false;  
        }  
        String sign = data.get(WXPayConstants.FIELD_SIGN);  
        return generateSignature(data, key).equals(sign);  
    }  
  
    /** 
     * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。 
     * 
     * @param data Map类型数据 
     * @param key API密钥 
     * @return 签名是否正确 
     * @throws Exception 
     */  
    public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {  
        return isSignatureValid(data, key, SignType.MD5);  
    }  
  
    /** 
     * 判断签名是否正确,必须包含sign字段,否则返回false。 
     * 
     * @param data Map类型数据 
     * @param key API密钥 
     * @param signType 签名方式 
     * @return 签名是否正确 
     * @throws Exception 
     */  
    public static boolean isSignatureValid(Map<String, String> data, String key, SignType signType) throws Exception {  
        if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {  
            return false;  
        }  
        String sign = data.get(WXPayConstants.FIELD_SIGN);  
        return generateSignature(data, key, signType).equals(sign);  
    }  
  
    /** 
     * 生成签名 
     * 
     * @param data 待签名数据 
     * @param key API密钥 
     * @return 签名 
     */  
    public static String generateSignature(final Map<String, String> data, String key) throws Exception {  
        return generateSignature(data, key, SignType.MD5);  
    }  
  
    /** 
     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 
     * 
     * @param data 待签名数据 
     * @param key API密钥 
     * @param signType 签名方式 
     * @return 签名 
     */  
    public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {  
        Set<String> keySet = data.keySet();  
        String[] keyArray = keySet.toArray(new String[keySet.size()]);  
        Arrays.sort(keyArray);  
        StringBuilder sb = new StringBuilder();  
        for (String k : keyArray) {  
            if (k.equals(WXPayConstants.FIELD_SIGN)) {  
                continue;  
            }  
            if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名  
                sb.append(k).append("=").append(data.get(k).trim()).append("&");  
        }  
        sb.append("key=").append(key);  
        if (SignType.MD5.equals(signType)) {  
            return MD5(sb.toString()).toUpperCase();  
        }  
        else if (SignType.HMACSHA256.equals(signType)) {  
            return HMACSHA256(sb.toString(), key);  
        }  
        else {  
            log.error("获取签名失败,失败原因:"+String.format("Invalid sign_type: %s", signType));  
            throw new Exception(String.format("Invalid sign_type: %s", signType));  
        }  
    }  
  
  
    /** 
     * 获取随机字符串 Nonce Str 
     * @return String 随机字符串 
     */  
    public static String generateNonceStr() {  
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);  
    }  
    /**  
     * Map转xml数据  
     */    
    public static String GetMapToXML(Map<String,String> param){    
        StringBuffer sb = new StringBuffer();    
        sb.append("<xml>");    
        for (Map.Entry<String,String> entry : param.entrySet()) {     
            sb.append("<"+ entry.getKey() +">");    
            sb.append(entry.getValue());    
            sb.append("</"+ entry.getKey() +">");    
        }      
        sb.append("</xml>");    
        return sb.toString();    
    }    
  
    /** 
     * 生成 MD5 
     * @param data 待处理数据 
     * @return MD5结果 
     */  
    public static String MD5(String data) throws Exception {  
        java.security.MessageDigest md = MessageDigest.getInstance("MD5");  
        byte[] array = md.digest(data.getBytes("UTF-8"));  
        StringBuilder sb = new StringBuilder();  
        for (byte item : array) {  
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));  
        }  
        return sb.toString().toUpperCase();  
    }  
  
    /** 
     * 生成 HMACSHA256 
     * @param data 待处理数据 
     * @param key 密钥 
     * @return 加密结果 
     * @throws Exception 
     */  
    public static String HMACSHA256(String data, String key) throws Exception {  
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");  
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");  
        sha256_HMAC.init(secret_key);  
        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));  
        StringBuilder sb = new StringBuilder();  
        for (byte item : array) {  
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));  
        }  
        return sb.toString().toUpperCase();  
    }  
  
    /** 
     * 日志 
     * @return 
     */  
    public static Logger getLogger() {  
        Logger logger = LoggerFactory.getLogger("wxpay java sdk");  
        return logger;  
    }  
  
    /** 
     * 获取当前时间戳,单位秒 
     * @return 
     */  
    public static long getCurrentTimestamp() {  
        return System.currentTimeMillis()/1000;  
    }  
  
    /** 
     * 获取当前时间戳,单位毫秒 
     * @return 
     */  
    public static long getCurrentTimestampMs() {  
        return System.currentTimeMillis();  
    }  
  
    /** 
     * 生成 uuid, 即用来标识一笔单,也用做 nonce_str 
     * @return 
     */  
    public static String generateUUID() {  
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);  
    }  
  
    /**  
     * 支付签名  
     * @param timestamp  
     * @param noncestr  
     * @param packages  
     * @return  
     * @throws UnsupportedEncodingException   
     */    
    public static String paySign(String timestamp, String noncestr,String packages,String appId){    
        Map<String, String> paras = new HashMap<String, String>();    
        paras.put("appid", appId);    
        paras.put("timestamp", timestamp);    
        paras.put("noncestr", noncestr);    
        paras.put("package", packages);    
        paras.put("signType", "MD5");    
        StringBuffer sb = new StringBuffer();    
        Set es = paras.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 (null != v && !"".equals(v) && !"sign".equals(k)  && !"key".equals(k)) {    
                sb.append(k + "=" + v + "&");    
            }    
        }    
        String sign = MD5Util.MD5(sb.toString()).toUpperCase();//MD5加密    
        return sign;    
    }    
}  

XmlUtil.java

  1 package com.yiexpress.core.utils;
  2 import java.io.StringReader;
  3 import java.lang.reflect.Field;  
  4 import java.util.Date;  
  5   
  6 
  7 import org.dom4j.Document;
  8 import org.dom4j.Element;  
  9 import org.dom4j.io.SAXReader;
 10 import org.xml.sax.InputSource;
 11   
 12 public class XmlUtil{  
 13     /** 
 14      * json 数据转换对象 
 15      *  
 16      * @param Element 
 17      *            要转换的Element数据 
 18      * @param pojo 
 19      *            要转换的目标对象类型 
 20      * @return 转换的目标对象 
 21      * @throws Exception 
 22      *             转换失败 
 23      */  
 24     @SuppressWarnings("rawtypes")  
 25     public static Object fromXmlToBean(Element rootElt, Class pojo) throws Exception{  
 26         // 首先得到pojo所定义的字段  
 27         Field[] fields = pojo.getDeclaredFields();  
 28         // 根据传入的Class动态生成pojo对象  
 29         Object obj = pojo.newInstance();  
 30         for (Field field : fields)  
 31         {  
 32             // 设置字段可访问(必须,否则报错)  
 33             field.setAccessible(true);  
 34             // 得到字段的属性名  
 35             String name = field.getName();  
 36             // 这一段的作用是如果字段在Element中不存在会抛出异常,如果出异常,则跳过。  
 37             try  
 38             {  
 39                 rootElt.elementTextTrim(name);  
 40             }  
 41             catch (Exception ex)  
 42             {  
 43                 continue;  
 44             }  
 45             if (rootElt.elementTextTrim(name) != null && !"".equals(rootElt.elementTextTrim(name)))  
 46             {  
 47                 // 根据字段的类型将值转化为相应的类型,并设置到生成的对象中。  
 48                 if (field.getType().equals(Long.class) || field.getType().equals(long.class))  
 49                 {  
 50                     field.set(obj, Long.parseLong(rootElt.elementTextTrim(name)));  
 51                 }  
 52                 else if (field.getType().equals(String.class))  
 53                 {  
 54                     field.set(obj, rootElt.elementTextTrim(name));  
 55                 }  
 56                 else if (field.getType().equals(Double.class) || field.getType().equals(double.class))  
 57                 {  
 58                     field.set(obj, Double.parseDouble(rootElt.elementTextTrim(name)));  
 59                 }  
 60                 else if (field.getType().equals(Integer.class) || field.getType().equals(int.class))  
 61                 {  
 62                     field.set(obj, Integer.parseInt(rootElt.elementTextTrim(name)));  
 63                 }  
 64                 else if (field.getType().equals(java.util.Date.class))  
 65                 {  
 66                     field.set(obj, Date.parse(rootElt.elementTextTrim(name)));  
 67                 }  
 68                 else  
 69                 {  
 70                     continue;  
 71                 }  
 72             }  
 73         }  
 74         return obj;  
 75     }  
 76     
 77     /** 
 78      * 把xml格式转化为指定对象 
 79      *  
 80      * @param xml 
 81      * @return 
 82      */  
 83     @SuppressWarnings("unchecked")
 84     public static <T> T getBeanByxml(String xml, Class<T> valueType) {  
 85         T person = null;  
 86         InputSource in = new InputSource(new StringReader(xml));  
 87         in.setEncoding("UTF-8");  
 88         SAXReader reader = new SAXReader();  
 89         Document document;  
 90         try {  
 91             document = reader.read(in);  
 92             Element root = document.getRootElement();  
 93             person = (T) XmlUtil.fromXmlToBean(root, valueType);  
 94   
 95         } catch (Exception e) {  
 96             // TODO Auto-generated catch block  
 97             e.printStackTrace();  
 98             System.out.println("数据解析错误");  
 99   
100         }  
101         return person;  
102     }
103 }  

获取预支付ID和签名的controller

package com.yiexpress.jerry.controller.ewe.wechat;

import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yiexpress.core.utils.wechat.UnifiedOrderRequest;
import com.yiexpress.core.utils.wechat.UnifiedOrderRespose;
import com.yiexpress.core.utils.wechat.WXPayUtil;

/** 
 * 微信支付controller  
 */  
@Controller  
@RequestMapping(value = "/wxpay")  
public class WXPayController{  
    private static final Logger LOGGER = LoggerFactory.getLogger(WXPayController.class);
    
    
    private String appId="公总号 appid";//公总号 appid
    private String mchId="商家号";//商家号
    private String apiKey="商户密匙";//商户密匙

    /** 
     * 获取终端IP 
     * @param request 
     * @return 
     */  
    public static String getIpAddr(HttpServletRequest request)  {    
        String ip  =  request.getHeader( " x-forwarded-for " );    
        if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip))  {    
            ip = request.getHeader( " Proxy-Client-IP " );    
        }     
        if (ip  == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip))  {    
            ip  =  request.getHeader( " WL-Proxy-Client-IP " );    
        }     
        if (ip  == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip))  {    
            ip  =  request.getRemoteAddr();    
        }     
        return  ip;    
     }   
  
    /** 
     * 支付初始化   返回预支付ID、签名等信息
     * @param payMoney 
     * @return  map 
     * result  -1
     */  
    @RequestMapping("/toPayInit")  
    @ResponseBody  
    public Map<String,Object> toPay(HttpServletRequest request,@RequestParam(value="payMoney",required=true)float payMoney,@RequestParam(value="openId",required=true) String openId,@RequestParam(value="orderId",required=true)String orderId){  
        Map<String,Object> map = new HashMap<>();  
        //订单号 目前生产的随机数  后面放入指定系统唯一的单号  
        //判断单号是否存在
        String noncestr = WXPayUtil.generateNonceStr();  
        Map<String,String> requestMap = new HashMap<String, String>();  
        requestMap.put("appId",appId);  
        requestMap.put("userWeixinOpenId",openId);  
        //之前使用ETCA单号作为商户订单号,现在改为自动生成的账单号    2018-10-25 Peter
        //requestMap.put("out_trade_no",auShipmentBrief.getShipmentReference());  
        requestMap.put("out_trade_no","订单号");  
        requestMap.put("mch_id",mchId);  
        //计算金额   微信支付的金额的单位是分,例如:实际支付1.23元,传入参数就是123
        int money=0;
        try {
            money=(int)(payMoney*100);
        } catch (Exception e) {
            map.put("result",-1);
            map.put("msg","金额格式不正确");
            return map;
        }
        
        requestMap.put("payMoney",money+"");  
        requestMap.put("spbill_create_ip", getIpAddr(request));  
        requestMap.put("notify_url","回调地址");
        requestMap.put("noncestr", noncestr);  
        requestMap.put("body","微信下单账单支付");  
        requestMap.put("detail","散客下单账单支付"); 
        Map<String,Object> requestInfo = WXPayUtil.createOrderInfo(requestMap,apiKey);  
        String orderInfo_toString = (String) requestInfo.get("orderInfo_toString");  
        LOGGER.debug("request 请求字符串:"+orderInfo_toString);
         //判断返回码        
        UnifiedOrderRespose orderResponse = WXPayUtil.httpOrder(orderInfo_toString,0);// 调用统一下单接口
        //判断超时的情况
        if(orderResponse==null || orderResponse.getReturn_code()==null || ("SUCCESS".equals(orderResponse.getReturn_code()) && (orderResponse.getErr_code()==null || "SYSTEMERROR".equals(orderResponse.getErr_code())))){
            orderResponse = WXPayUtil.httpOrder(orderInfo_toString,1);
            if(orderResponse==null || orderResponse.getReturn_code()==null || ("SUCCESS".equals(orderResponse.getReturn_code()) && (orderResponse.getErr_code()==null || "SYSTEMERROR".equals(orderResponse.getErr_code())))){
                orderResponse = WXPayUtil.httpOrder(orderInfo_toString,2);
            }
        }
        
        
        LOGGER.debug("response 返回字段:==》{}",orderResponse);
        //根据微信文档return_code 和result_code都为SUCCESS的时候才会返回code_url    
        if(null!=orderResponse  && "SUCCESS".equals(orderResponse.getReturn_code()) && "SUCCESS".equals(orderResponse.getResult_code())){    
            String timestamp = String.valueOf(WXPayUtil.getCurrentTimestamp());  
            map.put("timestamp",timestamp);  
            map.put("noncestr",noncestr);  
            UnifiedOrderRequest unifiedOrderRequest = (UnifiedOrderRequest) requestInfo.get("unifiedOrderRequest");  
            map.put("unifiedOrderRequest",unifiedOrderRequest);  
            SortedMap<String, String> packageParams = new TreeMap<String, String>();    
            packageParams.put("appId",appId);    
            packageParams.put("signType","MD5");    
            packageParams.put("nonceStr", noncestr);    
            packageParams.put("timeStamp", timestamp);    
            String packages = "prepay_id="+orderResponse.getPrepay_id();  
            packageParams.put("package",packages); 
            
            String sign = null;
            try {  
                //生成签名
                sign = WXPayUtil.generateSignature(packageParams,apiKey); 
            } catch (Exception e) {  
                map.put("result",-1);
                map.put("msg","支付签名信息异常");
                e.printStackTrace();  
            }
            if(sign!=null && !"".equals(sign)){ 
                
                LOGGER.debug("------------支付签名:"+sign+"-------------------");
                map.put("paySign",sign);  
                map.put("result",1);
                map.put("appId",appId);
            }else{  
                map.put("result",-1); 
                map.put("msg","支付签名信息异常");
            } 
           
            map.put("prepay_id",orderResponse.getPrepay_id());  
            return map;    
        }else{ //不成功  
            if(orderResponse!=null){
                String text = "调用微信支付出错,返回状态码:"+orderResponse.getReturn_code()+",返回信息:"+orderResponse.getReturn_msg();  
                if(orderResponse.getErr_code()!=null && !"".equals(orderResponse.getErr_code())){  
                    text = text +",错误码:"+orderResponse.getErr_code()+",错误描述:"+orderResponse.getErr_code_des();  
                }  
                LOGGER.error(text);
            }else{
                LOGGER.error("返回值   orderResponse对象为空");
            }
            map.put("result",-1);
            map.put("msg","支付环境异常,请稍后再试");
            return map;    
        }  
    }  
   
    
}  

jsp代码

 1 <script type="text/javascript">
 2 
 3 //点击支付按钮 开始支付
 4 function toPay(){  
 5     
 6     //初步判断数据
 7     var openId=$("#openId").val();
 8     var payMoney=$("#payMoney").val();
 9     $.ajax({  
10         url : "${pageContext.request.contextPath}/toPayInit",  
11         type:"POST",  
12         dataType : 'json',
13         data:{  
14             payMoney:payMoney,  
15             openId:openId,  
16             orderId:"订单号"
17         },  
18         success : function(result) { 
19             if(result.result==1){
20                 var paySign = result.paySign;  
21                 var prepay_id = result.prepay_id;  
22                 var nonceStr = result.noncestr;  
23                 var timestamp = result.timestamp;  
24                 var unifiedOrderRequest = result.unifiedOrderRequest;  
25                 var spbill_create_ip = unifiedOrderRequest.spbill_create_ip;  
26                 var detail = unifiedOrderRequest.detail;  
27                 var out_trade_no = unifiedOrderRequest.out_trade_no;  
28                 var appId=result.appId;
29                 onBridgeReady(paySign,prepay_id,nonceStr,timestamp,appId);
30             }else{  
31                 alert("失败");
32             }  
33         },  
34         error : function(data, status, e) { // 服务器响应失败时的处理函数  
35             alert("数据异常,支付失败", 'error'); 
36         }  
37     });  
38 }
39 
40 //调起公众号支付 
41 function onBridgeReady(paySign,prepay_id,nonceStr,timestamp,appId){  
42    WeixinJSBridge.invoke(  
43        'getBrandWCPayRequest', {  
44            "appId":appId,     //appid       
45            "timeStamp":timestamp,        
46            "nonceStr":nonceStr, //随机串       
47            "package":"prepay_id="+prepay_id,       
48            "signType":"MD5",      
49            "paySign":paySign //微信签名 
50        },  
51        function(res){  
52             // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。   
53            if(res.err_msg == "get_brand_wcpay_request:ok" ) {
54                alert("支付完成", 'success');
55            }else if(res.err_msg == "get_brand_wcpay_request:cancel" ) { 
56                alert("取消支付", 'success');  
57                
58            }else if(res.err_msg == "get_brand_wcpay_request:fail"){
59                alert("支付失败", 'success');
60               
61            }      
62        }  
63    );   
64 } 
65 </script>

定义微信支付成功回调接口APIAupostController.java

 1 package com.yiexpress.api.controller.ewe.aupost;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 import javax.annotation.Resource;
 7 import javax.servlet.ServletInputStream;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import org.apache.commons.collections.MapUtils;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Value;
15 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
16 import org.springframework.stereotype.Controller;
17 import org.springframework.web.bind.annotation.RequestMapping;
18 import org.springframework.web.bind.annotation.ResponseBody;
19 
20 import com.yiexpress.core.utils.wechat.WXPayUtil;
21 @Controller
22 @RequestMapping("/api")
23 public class APIAupostController {
24 
25     private static final Logger LOGGER=LoggerFactory.getLogger(APIAupostController.class);
26 
27     
28     @Resource(name = "jacksonBean")
29     private MappingJackson2HttpMessageConverter jackson;
31     private String apiKey="商户密匙";//商户密匙
32 
33      /** 
34          * 异步回调接口 
35          * @param request 
36          * @param response 
37          * @throws Exception 
38          */  
39         @RequestMapping(value="/paymentNotice",produces="text/html;charset=utf-8")  
40         @ResponseBody  
41         public String WeixinParentNotifyPage(HttpServletRequest request,HttpServletResponse response) throws Exception{  
42             ServletInputStream instream = request.getInputStream();  
43             StringBuffer sb = new StringBuffer();  
44             int len = -1;  
45             byte[] buffer = new byte[1024];  
46             while((len = instream.read(buffer)) != -1){  
47                 sb.append(new String(buffer,0,len));  
48             }  
49             instream.close();  
50             Map<String,String> map = WXPayUtil.xmlToMap(sb.toString());//接受微信的回调的通知参数  
51             Map<String,String> return_data = new HashMap<String,String>();  
52             //判断签名是否正确  
53             if(WXPayUtil.isSignatureValid(map,apiKey)){  
54                 if(map.get("return_code").toString().equals("FAIL")){  
55                     return_data.put("return_code", "FAIL");  
56                     return_data.put("return_msg", map.get("return_msg"));  
57                 }else {
58                     String return_code=MapUtils.getString(map,"return_code");
59                     String result_code=MapUtils.getString(map,"result_code");
60                     if(return_code!=null && "SUCCESS".equals(return_code) && result_code!=null && "SUCCESS".equals(result_code)){
61                         String out_trade_no =MapUtils.getString(map,"out_trade_no");//系统订单号  
62                         //支付成功,可以自定义新逻辑
63                         
64                     }
65                 }  
66             }else{  
67                 return_data.put("return_code", "FAIL");  
68                 return_data.put("return_msg", "签名错误");  
69             }  
70             String xml = WXPayUtil.GetMapToXML(return_data);  
71             LOGGER.error("支付通知回调结果:"+xml);  
72             return xml;  
73         }
74         
75 }

完工!

posted @ 2019-03-28 17:47  齐华枫  阅读(319)  评论(0编辑  收藏  举报