欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java微信公众号支付示例详解

程序员文章站 2022-04-02 23:04:21
本文实例为大家分享了java微信公众号支付示例代码,供大家参考,具体内容如下开始之前,先准备好:appid、商家号、商户密匙。工具类:md5util.javapackage com.yiexpress...

本文实例为大家分享了java微信公众号支付示例代码,供大家参考,具体内容如下

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

工具类:

md5util.java

package com.yiexpress.core.utils.wechat;

import java.security.messagedigest;

/**
 * md5工具类
 */
public class md5util {
  public final static string md5(string s) {
    char hexdigits[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

    try {
      byte[] btinput = s.getbytes();

      messagedigest mdinst = messagedigest.getinstance("md5");

      mdinst.update(btinput);

      byte[] md = mdinst.digest();

      int j = md.length;
      char str[] = new char[j * 2];
      int k = 0;
      for (int i = 0; i < j; i++) {
        byte byte0 = md[i];
        str[k++] = hexdigits[byte0 >>> 4 & 0xf];
        str[k++] = hexdigits[byte0 & 0xf];
      }
      string md5str = new string(str);
      return md5str;
    } catch (exception e) {
      e.printstacktrace();
      return null;
    }
  }
}

saputils.java

package com.yiexpress.core.utils;
import java.lang.reflect.*;
import java.util.list;
import java.io.ioexception;
import java.io.stringwriter;

import org.dom4j.document;
import org.dom4j.documenthelper;
import org.dom4j.element;
import org.dom4j.io.outputformat;
import org.dom4j.io.xmlwriter;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.util.stringutils;


public class saputils {
  private static final logger logger = loggerfactory.getlogger(saputils.class);
  /** 根据反射对javabean转成xml文件的格式
   * 以类名为第一标签,所有属性作为第二节点,并放入对应的值,如果属性为空 就不放入该熟悉
   * @param dto 传入的对象
   * @param operationname 操作名称
   * @return
   */
  public static string formattoxml(object dto,string operationname){
    logger.info("解析当前类{}为指定的xml文档格式的数据",dto.getclass().getname());
    logger.info("当前的同步方法是,{}",operationname);
    string result = null;
    field fields[]=dto.getclass().getdeclaredfields();//dto 是实体类名称
    //documenthelper提供了创建document对象的方法
    document document = documenthelper.createdocument();

    //添加节点信息
     string classname=dto.getclass().getname();
     // 操作的名称
    element rootelement = document.addelement(operationname);
    try {
      field.setaccessible(fields, true);
      for (int i = 0; i < fields.length; i++) {
        //添加节点信息
        if(!stringutils.isempty(fields[i].get(dto))){
          class<?> type = fields[i].gettype();
          // 如果是list
          if(type == list.class){
            string listname = fields[i].getname();
            createelement(rootelement, fields[i].get(dto),listname);
          }
          else{
            element element = rootelement.addelement(fields[i].getname());
            element.settext((string) fields[i].get(dto));
          }
        }
      }
      // 设置xml文档格式
      outputformat outputformat = outputformat.createprettyprint();
      // 设置xml编码方式,即是用指定的编码方式保存xml文档到字符串(string),这里也可以指定为gbk或是iso8859-1
      outputformat.setencoding("utf-8");
      // outputformat.setsuppressdeclaration(true); //是否生产xml头
      outputformat.setindent(true); //设置是否缩进
      outputformat.setindent("  "); //以四个空格方式实现缩进
      outputformat.setnewlines(true); //设置是否换行
      stringwriter stringwriter =null;
      // writer filewriter =null;
      // xmlwriter是用来把xml文档写入字符串的(工具)
      xmlwriter xmlwriter = null;
      try {
          // stringwriter字符串是用来保存xml文档的
        stringwriter = new stringwriter();
        // filewriter = new filewriter("d:\\modu11le.xml");
        // xmlwriter是用来把xml文档写入字符串的(工具)
        xmlwriter = new xmlwriter(stringwriter, outputformat);
        // 把创建好的xml文档写入字符串
        xmlwriter.write(document);
        //filewriter.write(stringwriter.tostring());
        result=stringwriter.tostring();
      } catch (ioexception e) {
        logger.error("写入数据失败");
        throw new runtimeexception("写入数据失败"+e);
      }finally{
         try {
           if(xmlwriter!=null){
             xmlwriter.flush();
             xmlwriter.close();
           }
/*           if(filewriter!=null){
             filewriter.flush();
             filewriter.close();
           }*/

        } catch (ioexception e) {
          logger.error("关闭输出流出错");
          throw new runtimeexception("关闭输出流出错"+e);
        }
      }
    } catch (exception e) {
      logger.error("添加xml的节点失败"+e);
    }
    logger.error("转换xml结束");
    return result;
  }

  /**
   * 添加类中的list
   * @param element
   * @param object
   * @param name
   * @return
   * @throws illegalargumentexception
   * @throws illegalaccessexception
   */
  public static element createelement(element element ,object object,string name ) throws illegalargumentexception, illegalaccessexception{
    element nameelement = element.addelement(name);
    list info = (list)object;
    for(int j= 0;j<info.size();j++){
      // 添加row的标签
      element rowelement = nameelement.addelement("row");
      // 添加 对象的熟悉
      field fields[]=info.get(j).getclass().getdeclaredfields();//dto 是实体类名称
      field.setaccessible(fields, true);
      for (int i = 0; i < fields.length; i++) {
        //添加节点信息
        if(!stringutils.isempty(fields[i].get(info.get(j)))){
            element childelement = rowelement.addelement(fields[i].getname());
            childelement.settext((string) fields[i].get(info.get(j)));
        }
      }
    }
    return element;
  }
}

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

package com.yiexpress.core.utils;
import java.io.stringreader;
import java.lang.reflect.field;
import java.util.date;


import org.dom4j.document;
import org.dom4j.element;
import org.dom4j.io.saxreader;
import org.xml.sax.inputsource;

public class xmlutil{
  /**
   * json 数据转换对象
   *
   * @param element
   *      要转换的element数据
   * @param pojo
   *      要转换的目标对象类型
   * @return 转换的目标对象
   * @throws exception
   *       转换失败
   */
  @suppresswarnings("rawtypes")
  public static object fromxmltobean(element rootelt, class pojo) throws exception{
    // 首先得到pojo所定义的字段
    field[] fields = pojo.getdeclaredfields();
    // 根据传入的class动态生成pojo对象
    object obj = pojo.newinstance();
    for (field field : fields)
    {
      // 设置字段可访问(必须,否则报错)
      field.setaccessible(true);
      // 得到字段的属性名
      string name = field.getname();
      // 这一段的作用是如果字段在element中不存在会抛出异常,如果出异常,则跳过。
      try
      {
        rootelt.elementtexttrim(name);
      }
      catch (exception ex)
      {
        continue;
      }
      if (rootelt.elementtexttrim(name) != null && !"".equals(rootelt.elementtexttrim(name)))
      {
        // 根据字段的类型将值转化为相应的类型,并设置到生成的对象中。
        if (field.gettype().equals(long.class) || field.gettype().equals(long.class))
        {
          field.set(obj, long.parselong(rootelt.elementtexttrim(name)));
        }
        else if (field.gettype().equals(string.class))
        {
          field.set(obj, rootelt.elementtexttrim(name));
        }
        else if (field.gettype().equals(double.class) || field.gettype().equals(double.class))
        {
          field.set(obj, double.parsedouble(rootelt.elementtexttrim(name)));
        }
        else if (field.gettype().equals(integer.class) || field.gettype().equals(int.class))
        {
          field.set(obj, integer.parseint(rootelt.elementtexttrim(name)));
        }
        else if (field.gettype().equals(java.util.date.class))
        {
          field.set(obj, date.parse(rootelt.elementtexttrim(name)));
        }
        else
        {
          continue;
        }
      }
    }
    return obj;
  }

  /**
   * 把xml格式转化为指定对象
   *
   * @param xml
   * @return
   */
  @suppresswarnings("unchecked")
  public static <t> t getbeanbyxml(string xml, class<t> valuetype) {
    t person = null;
    inputsource in = new inputsource(new stringreader(xml));
    in.setencoding("utf-8");
    saxreader reader = new saxreader();
    document document;
    try {
      document = reader.read(in);
      element root = document.getrootelement();
      person = (t) xmlutil.fromxmltobean(root, valuetype);

    } catch (exception e) {
      // todo auto-generated catch block
      e.printstacktrace();
      system.out.println("数据解析错误");

    }
    return person;
  }
}

获取预支付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代码

<script type="text/javascript">

//点击支付按钮 开始支付
function topay(){

  //初步判断数据
  var openid=$("#openid").val();
  var paymoney=$("#paymoney").val();
  $.ajax({
    url : "${pagecontext.request.contextpath}/topayinit",
    type:"post",
    datatype : 'json',
    data:{
      paymoney:paymoney,
      openid:openid,
      orderid:"订单号"
    },
    success : function(result) {
      if(result.result==1){
        var paysign = result.paysign;
        var prepay_id = result.prepay_id;
        var noncestr = result.noncestr;
        var timestamp = result.timestamp;
        var unifiedorderrequest = result.unifiedorderrequest;
        var spbill_create_ip = unifiedorderrequest.spbill_create_ip;
        var detail = unifiedorderrequest.detail;
        var out_trade_no = unifiedorderrequest.out_trade_no;
        var appid=result.appid;
        onbridgeready(paysign,prepay_id,noncestr,timestamp,appid);
      }else{
        alert("失败");
      }
    },
    error : function(data, status, e) { // 服务器响应失败时的处理函数
      alert("数据异常,支付失败", 'error');
    }
  });
}

//调起公众号支付
function onbridgeready(paysign,prepay_id,noncestr,timestamp,appid){
  weixinjsbridge.invoke(
    'getbrandwcpayrequest', {
      "appid":appid,   //appid
      "timestamp":timestamp,
      "noncestr":noncestr, //随机串
      "package":"prepay_id="+prepay_id,
      "signtype":"md5",
      "paysign":paysign //微信签名
    },
    function(res){
      // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回  ok,但并不保证它绝对可靠。
      if(res.err_msg == "get_brand_wcpay_request:ok" ) {
        alert("支付完成", 'success');
      }else if(res.err_msg == "get_brand_wcpay_request:cancel" ) {
        alert("取消支付", 'success');

      }else if(res.err_msg == "get_brand_wcpay_request:fail"){
        alert("支付失败", 'success');

      }
    }
  );
}
</script>

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

package com.yiexpress.api.controller.ewe.aupost;
 
import java.util.hashmap;
import java.util.map;
 
import javax.annotation.resource;
import javax.servlet.servletinputstream;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
 
import org.apache.commons.collections.maputils;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.beans.factory.annotation.value;
import org.springframework.http.converter.json.mappingjackson2httpmessageconverter;
import org.springframework.stereotype.controller;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.responsebody;
 
import com.yiexpress.core.utils.wechat.wxpayutil;
@controller
@requestmapping("/api")
public class apiaupostcontroller {

  private static final logger logger=loggerfactory.getlogger(apiaupostcontroller.class);
 
   
   @resource(name = "jacksonbean")
   private mappingjackson2httpmessageconverter jackson;
   private string apikey="商户密匙";//商户密匙
 
   /** 
     * 异步回调接口 
     * @param request 
     * @param response 
     * @throws exception 
     */ 
     @requestmapping(value="/paymentnotice",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(); 
       map<string,string> map = wxpayutil.xmltomap(sb.tostring());//接受微信的回调的通知参数 
       map<string,string> return_data = new hashmap<string,string>(); 
       //判断签名是否正确 
       if(wxpayutil.issignaturevalid(map,apikey)){ 
         if(map.get("return_code").tostring().equals("fail")){ 
           return_data.put("return_code", "fail"); 
           return_data.put("return_msg", map.get("return_msg")); 
         }else {
           string return_code=maputils.getstring(map,"return_code");
           string result_code=maputils.getstring(map,"result_code");
           if(return_code!=null && "success".equals(return_code) && result_code!=null && "success".equals(result_code)){
             string out_trade_no =maputils.getstring(map,"out_trade_no");//系统订单号 
             //支付成功,可以自定义新逻辑
             
           }
         } 
       }else{ 
         return_data.put("return_code", "fail"); 
         return_data.put("return_msg", "签名错误"); 
       } 
       string xml = wxpayutil.getmaptoxml(return_data); 
       logger.error("支付通知回调结果:"+xml); 
      return xml; 
     }
     
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。