zoukankan      html  css  js  c++  java
  • 微信支付接口对接文档

    建立子包demo,demo里面创建controller包、domain包、service包
    目录结构:
     
    controller包中创建Pay_controller
     
    package com.ccunix.ihousekeeping.demo.controller;
     
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import com.ccunix.ihousekeeping.base.controller.BaseMultiController;
    import com.ccunix.ihousekeeping.demo.domain.WxOa;
    import com.ccunix.ihousekeeping.demo.service.UUID_Tools;
    import com.ccunix.ihousekeeping.demo.service.WxSignUtil;
     
    /**
    *
    * @ClassName: Pay_Controller
    * @author xyp
    * @date 2019年8月12日 上午9:57:46
    *
    */
     
    @Controller
    @RequestMapping("Pay_Controller")
    public class Pay_Controller extends BaseMultiController {
     
    WxSignUtil wxSignUtil = new WxSignUtil();
     
    // 微信预下单交易
    @ResponseBody
    @RequestMapping("/yuxiadan")
    public Map yuxiadan() throws Exception {
    WxOa wxOa = new WxOa();
    // 应用ID
    wxOa.setAppid("xxxxxxxxxxxxxx");
    // 商户号
    wxOa.setMch_id("xxxxxxxx");
    // 随机字符串 不长于32位
    wxOa.setNonce_str(UUID_Tools.getUUID());
    // 商品描述
    wxOa.setBody("phone");
    // 商户订单号
    wxOa.setOut_trade_no("12345");
    // 订单总金额,单位为分
    wxOa.setTotal_fee(10);
    // 终端IP
    wxOa.setSpbill_create_ip("127.0.0.1");
    // 通知地址
    wxOa.setNotify_url(wxSignUtil.unifiedorderUrl);
    // 交易类型 APP
    wxOa.setTrade_type("NATIVE");
    // 将数据放入map中
    Map map = wxSignUtil.WxMd5Sign(wxOa, "9dffe0f7a65bb1976d4b33d7a8b1f7ac");
    //转换为set集合
    Set<Map.Entry<Integer, String>> entries = map.entrySet();
    //迭代器进行遍历
    Iterator<Map.Entry<Integer, String>> iteratorMap = entries.iterator();
    while (iteratorMap.hasNext()) {
    Map.Entry<Integer, String> next = iteratorMap.next();
    System.err.println(next);
    }
    return map;
    }
     
    }
     
     
    domain包中创建bean类:
     
    WxOa类:
     
    package com.ccunix.ihousekeeping.demo.domain;
     
    import java.io.Serializable;
    import java.util.Date;
     
    //微信预下单参数
    public class WxOa implements Serializable {
     
    // 应用ID
    private String appid;
    // 商户号
    private String mch_id;
    // 设备号
    private String device_info;
    // 随机字符串 不长于32位
    private String nonce_str;
    // 商品描述
    private String body;
    // 附加数据
    private String attach;
    // 商户订单号
    private String out_trade_no;
    // 订单总金额,单位为分
    private int total_fee;
    // 终端IP
    private String spbill_create_ip;
    // 交易起始时间
    private Date time_start;
    // 交易结束时间
    private Date time_expire;
    // 通知地址
    private String notify_url;
    // 交易类型 APP
    private String trade_type;
    // openid
    private String openid;
    //code_url
    private String code_url;
     
     
    public String getCode_url() {
    return code_url;
    }
     
    public void setCode_url(String code_url) {
    this.code_url = code_url;
    }
     
    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 getBody() {
    return body;
    }
     
    public void setBody(String body) {
    this.body = body;
    }
     
    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 int getTotal_fee() {
    return total_fee;
    }
     
    public void setTotal_fee(int 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 Date getTime_start() {
    return time_start;
    }
     
    public void setTime_start(Date time_start) {
    this.time_start = time_start;
    }
     
    public Date getTime_expire() {
    return time_expire;
    }
     
    public void setTime_expire(Date time_expire) {
    this.time_expire = time_expire;
    }
     
    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 getOpenid() {
    return openid;
    }
     
    public void setOpenid(String openid) {
    this.openid = openid;
    }
     
    }
     
     
    WxPayOa类:
     
    package com.ccunix.ihousekeeping.demo.domain;
     
    import java.io.Serializable;
     
    public class WxPayOa implements Serializable {
     
    // 应用ID
    private String appid;
    // 随机字符串
    private String noncestr;
    // 扩展字段
    private String packageace;
    // 商户号
    private String partnerid;
    // 预支付交易会话ID
    private String prepayid;
    // 时间戳
    private String timestamp;
     
    public String getAppid() {
    return appid;
    }
     
    public void setAppid(String appid) {
    this.appid = appid;
    }
     
    public String getNoncestr() {
    return noncestr;
    }
     
    public void setNoncestr(String noncestr) {
    this.noncestr = noncestr;
    }
     
    public String getPackageace() {
    return packageace;
    }
     
    public void setPackageace(String packageace) {
    this.packageace = packageace;
    }
     
    public String getPartnerid() {
    return partnerid;
    }
     
    public void setPartnerid(String partnerid) {
    this.partnerid = partnerid;
    }
     
    public String getPrepayid() {
    return prepayid;
    }
     
    public void setPrepayid(String prepayid) {
    this.prepayid = prepayid;
    }
     
    public String getTimestamp() {
    return timestamp;
    }
     
    public void setTimestamp(String timestamp) {
    this.timestamp = timestamp;
    }
     
    }
     
    service包中为工具类,其中重要的为WxSignUtil类
     
    WxSignUtil类:
     
    package com.ccunix.ihousekeeping.demo.service;
     
    import java.io.BufferedInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import javax.crypto.spec.SecretKeySpec;
    import javax.net.ssl.SSLContext;
    import javax.servlet.http.HttpServletRequest;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.HttpStatus;
    import org.apache.commons.httpclient.methods.PostMethod;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLContexts;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import com.alibaba.fastjson.JSONObject;
    import com.ccunix.ihousekeeping.demo.domain.WxOa;
    import com.ccunix.ihousekeeping.demo.domain.WxPayOa;
     
    //微信签名
    public class WxSignUtil {
     
    // 微信预下单 请求地址
    public static final String unifiedorderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
     
    // 微信申请退款请求地址
    public static final String callbackamounturl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
     
    // 微信小程序统一下单地址
    public static final String smallprogramorderurl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
     
    // 微信App支付预下单接口
    public static Map WxMd5Sign(WxOa wxOa, String key) throws Exception {
    String stringA = "appid=" + wxOa.getAppid() + "&attach=" + wxOa.getAttach() + "&body=" + wxOa.getBody()
    + "&mch_id=" + wxOa.getMch_id() + "&nonce_str=" + wxOa.getNonce_str() + "&notify_url="
    + wxOa.getNotify_url() + "&out_trade_no=" + wxOa.getOut_trade_no() + "&spbill_create_ip="
    + wxOa.getSpbill_create_ip() + "&total_fee=" + wxOa.getTotal_fee() + "&trade_type="
    + wxOa.getTrade_type();
    String stringSignTemp = stringA + "&key=" + key;
    String stringSignTemp1 = new String(stringSignTemp.getBytes("iso8859-1"));
    // String stringSignTemp1=new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
    String par = "<xml>" + "<appid>" + wxOa.getAppid() + "</appid>" + "<attach>" + wxOa.getAttach() + "</attach>"
    + "<body><![CDATA[" + wxOa.getBody() + "]]></body>" + "<mch_id>" + wxOa.getMch_id() + "</mch_id>"
    + "<nonce_str>" + wxOa.getNonce_str() + "</nonce_str>" + "<notify_url>" + wxOa.getNotify_url()
    + "</notify_url>" + "<out_trade_no>" + wxOa.getOut_trade_no() + "</out_trade_no>" + "<spbill_create_ip>"
    + wxOa.getSpbill_create_ip() + "</spbill_create_ip>" + "<total_fee>" + wxOa.getTotal_fee()
    + "</total_fee>" + "<trade_type>" + wxOa.getTrade_type() + "</trade_type>" + "<sign>" + sign + "</sign>"
    + "</xml> ";
     
    String ret = WxSignUtil.post(unifiedorderUrl, par);
    System.out.println(ret);
    Map<String, String> map = readStringXmlOut(ret);
    return map;
    }
     
    // 调起支付加签
    public static String WxPrePaySign(WxPayOa wxPayOa, String key) throws Exception {
    // //应用ID
    // String appid="";
    // //随机字符串
    // String noncestr="";
    // //扩展字段
    // String packageace="";
    // //商户号
    // String partnerid="";
    // //预支付交易会话ID
    // String prepayid="";
    // //时间戳
    // String timestamp="";
    String stringA = "appid=" + wxPayOa.getAppid() + "&noncestr=" + wxPayOa.getNoncestr() + "&package="
    + wxPayOa.getPackageace() + "&partnerid=" + wxPayOa.getPartnerid() + "&prepayid="
    + wxPayOa.getPrepayid() + "&timestamp=" + wxPayOa.getTimestamp();
    String stringSignTemp = stringA + "&key=" + key;
    String stringSignTemp1 = new String(stringSignTemp.getBytes("iso8859-1"));
    // String stringSignTemp1=new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
    return sign;
    }
     
    /**
    * 发送xml数据请求到server端
    *
    * @param url
    * xml请求数据地址
    * @param xmlString
    * 发送的xml数据流
    * @return null发送失败,否则返回响应内容
    */
    public static String post(String url, String xmlFileName) {
    // 关闭
    System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
    System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
    System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "stdout");
     
    // 创建httpclient工具对象
    HttpClient client = new HttpClient();
    // 创建post请求方法
    PostMethod myPost = new PostMethod(url);
    // 设置请求超时时间
    client.setConnectionTimeout(300 * 1000);
    String responseString = null;
    try {
    // 设置请求头部类型
    myPost.setRequestHeader("Content-Type", "text/xml");
    myPost.setRequestHeader("charset", "iso8859-1");
    // myPost.setRequestHeader("charset","utf-8");
     
    // 设置请求体,即xml文本内容,注:这里写了两种方式,一种是直接获取xml内容字符串,一种是读取xml文件以流的形式
    myPost.setRequestBody(xmlFileName);
     
    // InputStream body=this.getClass().getResourceAsStream("/"+xmlFileName);
    // myPost.setRequestBody(body);
    // myPost.setRequestEntity(new
    // StringRequestEntity(xmlString,"text/xml","utf-8"));
    int statusCode = client.executeMethod(myPost);
    if (statusCode == HttpStatus.SC_OK) {
    BufferedInputStream bis = new BufferedInputStream(myPost.getResponseBodyAsStream());
    byte[] bytes = new byte[1024];
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    int count = 0;
    while ((count = bis.read(bytes)) != -1) {
    bos.write(bytes, 0, count);
    }
    byte[] strByte = bos.toByteArray();
    responseString = new String(strByte, 0, strByte.length, "utf-8");
    // System.out.println(responseString);
    bos.close();
    bis.close();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    myPost.releaseConnection();
    return responseString;
    }
     
    /**
    * @description 将xml字符串转换成map
    * @param xml
    * @return Map
    */
    public static Map<String, String> readStringXmlOut(String xml) {
    Map<String, String> map = new HashMap<String, String>();
    Document doc = null;
    try {
    doc = DocumentHelper.parseText(xml); // 将字符串转为XML
    Element rootElt = doc.getRootElement(); // 获取根节点
    @SuppressWarnings("unchecked")
    List<Element> list = rootElt.elements();// 获取根节点下所有节点
    for (Element element : list) { // 遍历节点
    map.put(element.getName(), element.getText()); // 节点的name为map的key,text为map的value
    }
    } catch (DocumentException e) {
    e.printStackTrace();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return map;
    }
     
    // 支付回调验证签名
    public static boolean wxPayChack(Map map, String key) throws Exception {
    String stringA = "appid=" + map.get("appid") + "&attach=" + map.get("attach") + "&bank_type="
    + map.get("bank_type") + "&cash_fee=" + map.get("cash_fee") + "" + "&fee_type=" + map.get("fee_type")
    + "&is_subscribe=" + map.get("is_subscribe") + "&mch_id=" + map.get("mch_id") + "&nonce_str="
    + map.get("nonce_str") + "&openid=" + map.get("openid") + "&out_trade_no=" + map.get("out_trade_no")
    + "&result_code=" + map.get("result_code") + "&return_code=" + map.get("return_code") + "&time_end="
    + map.get("time_end") + "&total_fee=" + map.get("total_fee") + "&trade_type=" + map.get("trade_type")
    + "&transaction_id=" + map.get("transaction_id");
    String stringSignTemp = stringA + "&key=" + key;
    String stringSignTemp1 = new String(stringSignTemp.getBytes("iso8859-1"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
    String retSign = (String) map.get("sign");
    if (retSign.equals(sign)) {
    return true;
    }
    return false;
    }
     
    // 接收微信回调request 获取xml参数信息
    public static Map<String, String> inputStream2String(HttpServletRequest request) throws Exception {
    InputStream is = request.getInputStream();
    String xml = WxSignUtil.inputStream2String(is, "utf-8");
    return WxSignUtil.readStringXmlOut(xml);
    }
     
    /**
    * InputStream流转换成String字符串
    *
    * @param inStream
    * InputStream流
    * @param encoding
    * 编码格式
    * @return String字符串
    */
    public static String inputStream2String(InputStream inStream, String encoding) {
    String result = null;
    try {
    if (inStream != null) {
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    byte[] tempBytes = new byte[1000];
    int count = -1;
    while ((count = inStream.read(tempBytes, 0, 1000)) != -1) {
    outStream.write(tempBytes, 0, count);
    }
    tempBytes = null;
    outStream.flush();
    result = new String(outStream.toByteArray(), encoding);
    }
    } catch (Exception e) {
    result = null;
    }
    return result;
    }
     
    // 获取用户的openid
    public static String getUserOpenId(Map<String, String> map) {
    String param = "appid=" + map.get("openappid") + "&secret=" + map.get("opensecret") + "&code=" + map.get("code")
    + "&grant_type=authorization_code";
    String ret = HttpUtil.doGet(map.get("openidurl"), param);
    JSONObject jon = JSONObject.parseObject(ret);
    String openId = jon.getString("openid");
    return openId;
    }
     
    // 微信公众号预下单
    public static Map WxH5Md5Sign(Map map, String key) throws Exception {
    // //公众账号ID
    // String appid="";
    // //商品描述
    // String body="";
    // //商户号
    // String mch_id="";
    // //随机字符串
    // String nonce_str="";
    // //通知地址
    // String notify_url="";
    // //用户标识
    // String openid="";
    // //商户订单号
    // String out_trade_no="";
    // //终端IP
    // String spbill_create_ip="";
    // //订单总金额
    // int total_fee=0;
    // //交易类型
    // String trade_type="";
     
    String stringA = "appid=" + map.get("openappid") + "&body=" + map.get("body") + "&mch_id="
    + map.get("openmchid") + "&nonce_str=" + map.get("nonce_str") + "&notify_url="
    + map.get("opencallbackurl") + "&openid=" + map.get("openid") + "&out_trade_no="
    + map.get("out_trade_no") + "&spbill_create_ip=127.0.0.1&total_fee=" + map.get("total_fee")
    + "&trade_type=JSAPI";
    String stringSignTemp = stringA + "&key=" + key;
    // String stringSignTemp1=new String(stringSignTemp.getBytes("iso8859-1"));
    String stringSignTemp1 = new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
     
    String par = "<xml>" + "<appid><![CDATA[" + map.get("openappid") + "]]></appid>" + "<mch_id><![CDATA["
    + map.get("openmchid") + "]]></mch_id>" + "<openid><![CDATA[" + map.get("openid") + "]]></openid>"
    + "<body><![CDATA[" + map.get("body") + "]]></body>" + "<nonce_str><![CDATA[" + map.get("nonce_str")
    + "]]></nonce_str>" + "<notify_url><![CDATA[" + map.get("opencallbackurl") + "]]></notify_url>"
    + "<out_trade_no><![CDATA[" + map.get("out_trade_no") + "]]></out_trade_no>"
    + "<spbill_create_ip><![CDATA[127.0.0.1]]></spbill_create_ip>" + "<total_fee><![CDATA["
    + map.get("total_fee") + "]]></total_fee>" + "<trade_type><![CDATA[JSAPI]]></trade_type>" + "<sign>"
    + sign + "</sign>" + "</xml>";
     
    // B8971A5E8220F8B9A1C314FDDA7440C4
    String ret = WxSignUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", par);
    Map<String, String> mapret = readStringXmlOut(ret);
    return mapret;
    }
     
    // 公众号预下单回调验证签名
    public static boolean orderPayCallbackChack(Map map, String key) throws Exception {
    String stringA = "appid=" + map.get("appid") + "&bank_type=" + map.get("bank_type") + "&cash_fee="
    + map.get("cash_fee") + "&fee_type=" + map.get("fee_type") + "&is_subscribe=" + map.get("is_subscribe")
    + "&mch_id=" + map.get("mch_id") + "&nonce_str=" + map.get("nonce_str") + "&openid=" + map.get("openid")
    + "&out_trade_no=" + map.get("out_trade_no") + "&result_code=" + map.get("result_code")
    + "&return_code=" + map.get("return_code") + "&time_end=" + map.get("time_end") + "&total_fee="
    + map.get("total_fee") + "&trade_type=" + map.get("trade_type") + "&transaction_id="
    + map.get("transaction_id");
    String stringSignTemp = stringA + "&key=" + key;
    String stringSignTemp1 = new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
    String retsign = map.get("sign") + "";
    if (sign.equals(retsign)) {
    return true;
    }
    return false;
    }
     
    // 公众号调起支付签名
    public static String openSignPayMd5(Map map, String key) throws Exception {
    // 公众号id
    String appId = "";
    // 时间戳
    String timeStamp = "";
    // 随机字符串
    String nonceStr = "";
    // 订单详情扩展字符串
    String packageout = "";
    // 签名方式
    String signType = "";
     
    // String
    // stringA="appid=wx8731a2e298f48739&nonceStr=123456&package=123456&signType=MD5&timeStamp=123456";
    String stringA = "appId=" + map.get("appId") + "&nonceStr=" + map.get("nonceStr") + "&package="
    + map.get("package") + "&signType=" + map.get("signType") + "&timeStamp=" + map.get("timeStamp");
    String stringSignTemp = stringA + "&key=" + key;
    // String stringSignTemp1=new String(stringSignTemp.getBytes("iso8859-1"));
    String stringSignTemp1 = new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
    return sign;
    }
     
    // 微信支付商户退款
    public static Map wxPayMachBackToUser(Map map, String key) throws Exception {
     
    // //公众账号ID
    // String appid="";
    // //商户号
    // String mch_id="";
    // //随机字符串
    // String nonce_str="";
    // //微信订单号 流水号
    // String transaction_id="";
    //// //商户订单号
    //// String out_trade_no="";
    // //商户退款单号
    // String out_refund_no="";
    // //订单金额 订单总金额,单位为分,只能为整数
    // String total_fee="";
    // //退款金额
    // String refund_fee="";
    // 退款结果通知url
    // String notify_url="";
     
    String stringA = "appid=" + map.get("appid") + "&mch_id=" + map.get("mch_id") + "&nonce_str="
    + map.get("nonce_str") + "&notify_url=" + map.get("notify_url") + "&out_refund_no="
    + map.get("out_refund_no") + "&refund_fee=" + map.get("refund_fee") + "&total_fee="
    + map.get("total_fee") + "&transaction_id=" + map.get("transaction_id");
     
    String stringSignTemp = stringA + "&key=" + key;
    // String stringSignTemp1=new String(stringSignTemp.getBytes("iso8859-1"));
    String stringSignTemp1 = new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
     
    String par = "<xml>" + " <appid><![CDATA[" + map.get("appid") + "]]></appid>" + " <mch_id><![CDATA["
    + map.get("mch_id") + "]]></mch_id>" + " <nonce_str><![CDATA[" + map.get("nonce_str")
    + "]]></nonce_str>" + " <notify_url><![CDATA[" + map.get("notify_url") + "]]></notify_url>"
    + " <out_refund_no><![CDATA[" + map.get("out_refund_no") + "]]></out_refund_no>"
    + " <refund_fee><![CDATA[" + map.get("refund_fee") + "]]></refund_fee>" + " <total_fee><![CDATA["
    + map.get("total_fee") + "]]></total_fee>" + " <transaction_id><![CDATA[" + map.get("transaction_id")
    + "]]></transaction_id>" + " <sign>" + sign + "</sign>" + "</xml>";
     
    // String ret=WxSignUtil.post("https://api.mch.weixin.qq.com/secapi/pay/refund",
    // par);
    String ret = WxSignUtil.postData("https://api.mch.weixin.qq.com/secapi/pay/refund", par, map.get("mch_id") + "",
    map.get("keyPath") + "");
    Map<String, String> mapret = readStringXmlOut(ret);
    return mapret;
    }
     
    // 解密微信退款加密字段
    public static Map desDecodeWxPayCallBack(Map<String, String> map, String key) throws Exception {
    // 对商户key做md5,得到32位小写key*
    // String mdkey=LogisticsInfoMD5.encode(key).toLowerCase();
    SecretKeySpec mdkey = new SecretKeySpec(LogisticsInfoMD5.encode(key).toLowerCase().getBytes(), "AES");
     
    // 微信订单号
    String transaction_id = map.get("transaction_id");
    if (transaction_id != null) {
    // 对加密串A做base64解码,得到加密串B
    transaction_id = new String(Base64Util.decode(transaction_id));
    transaction_id = AESUtil.decryptData(transaction_id, mdkey);
    map.put(transaction_id, transaction_id);
    }
    return map;
    }
     
    private static int socketTimeout = 10000;// 连接超时时间,默认10秒
    private static int connectTimeout = 30000;// 传输超时时间,默认30秒
    private static RequestConfig requestConfig;// 请求器的配置
    private static CloseableHttpClient httpClient;// HTTP请求器
     
    /**
    * 通过Https往API post xml数据
    *
    * @param url
    * API地址
    * @param xmlObj
    * 要提交的XML数据对象
    * @param mchId
    * 商户ID
    * @param certPath
    * 证书位置
    * @return
    */
    public static String postData(String url, String xmlObj, String mchId, String certPath) {
    // 加载证书
    try {
    initCert(mchId, certPath);
    } catch (Exception e) {
    e.printStackTrace();
    }
    String result = null;
    HttpPost httpPost = new HttpPost(url);
    // 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
    StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
    httpPost.addHeader("Content-Type", "text/xml");
    httpPost.setEntity(postEntity);
    // 根据默认超时限制初始化requestConfig
    requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout)
    .build();
    // 设置请求器的配置
    httpPost.setConfig(requestConfig);
    try {
    HttpResponse response = null;
    try {
    response = httpClient.execute(httpPost);
    } catch (IOException e) {
    e.printStackTrace();
    }
    HttpEntity entity = response.getEntity();
    try {
    result = EntityUtils.toString(entity, "UTF-8");
    } catch (IOException e) {
    e.printStackTrace();
    }
    } finally {
    httpPost.abort();
    }
    return result;
    }
     
    /**
    * 加载证书
    *
    * @param mchId
    * 商户ID
    * @param certPath
    * 证书位置
    * @throws Exception
    */
    private static void initCert(String mchId, String certPath) throws Exception {
    // 证书密码,默认为商户ID
    String key = mchId;
    // 证书的路径
    String path = certPath;
    // 指定读取证书格式为PKCS12
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    // 读取本机存放的PKCS12证书文件
    FileInputStream instream = new FileInputStream(new File(path));
    try {
    // 指定PKCS12的密码(商户ID)
    keyStore.load(instream, key.toCharArray());
    } finally {
    instream.close();
    }
    SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
    httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }
     
    // 微信小程序統一下單
    public static Map WxSmallProgramMd5Sign(Map map, String key) throws Exception {
    String stringA = "appid=" + map.get("appid") + "&attach=" + map.get("attach") + "&body=" + map.get("body")
    + "&mch_id=" + map.get("mch_id") + "&nonce_str=" + map.get("nonce_str") + "&notify_url="
    + map.get("notify_url") + "&openid=" + map.get("openid") + "&out_trade_no=" + map.get("out_trade_no")
    + "&spbill_create_ip=" + map.get("spbill_create_ip") + "&total_fee=" + map.get("total_fee")
    + "&trade_type=" + map.get("trade_type");
     
    String stringSignTemp = stringA + "&key=" + key;
    String stringSignTemp1 = new String(stringSignTemp.getBytes("iso8859-1"));
    // String stringSignTemp1=new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
     
    String par = "<xml>" + "<appid>" + map.get("appid") + "</appid>" + "<attach>" + map.get("attach") + "</attach>"
    + "<body>" + map.get("body") + "</body>" + "<mch_id>" + map.get("mch_id") + "</mch_id>" + "<nonce_str>"
    + map.get("nonce_str") + "</nonce_str>" + "<notify_url>" + map.get("notify_url") + "</notify_url>"
    + "<openid>" + map.get("openid") + "</openid>" + "<out_trade_no>" + map.get("out_trade_no")
    + "</out_trade_no>" + "<spbill_create_ip>" + map.get("spbill_create_ip") + "</spbill_create_ip>"
    + "<total_fee>" + map.get("total_fee") + "</total_fee>" + "<trade_type>" + "JSAPI" + "</trade_type>"
    + "<sign>" + sign + "</sign>" + "</xml>";
    String ret = WxSignUtil.post(smallprogramorderurl, par);
    Map<String, String> retmap = readStringXmlOut(ret);
    return retmap;
    }
     
    // 微信小程序调起支付签名
    public static Map wxSmallProgramPaySign(Map map, String key) throws Exception {
    String stringA = "appId=" + map.get("appid") + "&nonceStr=" + map.get("nonceStr") + "&package=prepay_id="
    + map.get("prepay_id") + "&signType=MD5&timeStamp=" + map.get("timeStamp");
     
    String stringSignTemp = stringA + "&key=" + key;
    String stringSignTemp1 = new String(stringSignTemp.getBytes("iso8859-1"));
    // String stringSignTemp1=new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
     
    Map retmap = new HashMap();
    retmap.put("time", map.get("timeStamp"));
    retmap.put("package", "prepay_id=" + map.get("prepay_id"));
    retmap.put("paySign", sign);
    retmap.put("signType", "MD5");
    retmap.put("nonceStr", map.get("nonceStr"));
    return retmap;
    }
     
    // 微信小程序获得openid
    public static String wxSmallProgramGetOpenId(Map map, String secret) throws Exception {
    String getUrl = "https://api.weixin.qq.com/sns/jscode2session";
    String param = "appid=" + map.get("appid") + "&secret=" + secret + "&js_code=" + map.get("code")
    + "&grant_type=authorization_code";
    String ret = HttpUtil.doGet(getUrl, param);
    // {"session_key":"vz5yE67kF3p8CKpTtLgobw==","openid":"oMEFK5M53RmMPTow1_GoBRKkrOI4"}
    JSONObject json = JSONObject.parseObject(ret);
    String openid = json.getString("openid");
    String session_key = json.getString("session_key");
    return openid + "," + session_key;
    }
     
    // 查询微信订单
    public static void queryOrderPayInfo() throws Exception {
    String stringA = "appid=wx608bbf2ae0956623&mch_id=1512285851&nonce_str=456168546545&out_trade_no=0a3f639a3f174529a7ca236632f36d4d&key=9dffe0f7a65bb1976d4b33d7a8b1f7ac";
    String stringSignTemp = stringA;
    String stringSignTemp1 = new String(stringSignTemp.getBytes("utf-8"));
    String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
     
    String par = "<xml>" + "<appid><![CDATA[wx608bbf2ae0956623]]></appid>"
    + "<mch_id><![CDATA[1512285851]]></mch_id>" + "<nonce_str><![CDATA[456168546545]]></nonce_str>"
    + "<out_trade_no><![CDATA[0a3f639a3f174529a7ca236632f36d4d]]></out_trade_no>" + "<sign>" + sign
    + "</sign>" + "</xml>";
    String ret = WxSignUtil.post("https://api.mch.weixin.qq.com/pay/orderquery", par);
    Map<String, String> mapret = readStringXmlOut(ret);
    System.out.println(mapret);
    }
     
    }
     
     
    pom.xml:
     
     
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
     
    <groupId>isweb</groupId>
    <artifactId>ccunix.is</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
     
     
     
    <properties>
    <srping.version>4.0.2.RELEASE</srping.version>
    <mybatis.version>3.2.8</mybatis.version>
    <slf4j.version>1.7.12</slf4j.version>
    <log4j.version>1.2.17</log4j.version>
    </properties>
    <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>3.8.1</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <scope>provided</scope>
    <version>7.0</version>
    </dependency>
    <!-- spring框架包 start -->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <!-- google zxing 生成二维码 -->
    <dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.3.3</version>
    </dependency>
     
    <!-- 长链接转短链接 相关 -->
    <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    </dependency>
     
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-oxm</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${srping.version}</version>
    </dependency>
    <!-- spring框架包 end -->
    <!-- mybatis框架包 start -->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>${mybatis.version}</version>
    </dependency>
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.2.2</version>
    </dependency>
    <!-- mybatis框架包 end -->
     
    <!-- 数据库驱动 -->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.35</version>
    </dependency>
    <!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->
    <dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.4</version>
    </dependency>
    <!-- jstl标签类 -->
    <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
    </dependency>
     
    <!-- 中文转拼音jar -->
    <dependency>
    <groupId>com.belerweb</groupId>
    <artifactId>pinyin4j</artifactId>
    <version>2.5.0</version>
    </dependency>
     
    <!-- log start -->
    <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>${log4j.version}</version>
    </dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
    </dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>${slf4j.version}</version>
    </dependency>
    <!-- log END -->
     
    <!-- Json -->
    <!-- 格式化对象,方便输出日志 -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.6</version>
    </dependency>
    <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
    </dependency>
     
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.2</version>
    </dependency>
     
     
    <!-- 上传组件包 start -->
    <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
    </dependency>
    <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
    </dependency>
    <dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
    </dependency>
    <!-- 上传组件包 end -->
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.6.12</version>
    </dependency>
    <!-- redis -->
    <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.0.2.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>3.1.2.RELEASE</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.1.0</version>
    </dependency>
     
    <!-- apollo相关 -->
     
    <dependency>
    <groupId>org.eclipse.paho</groupId>
    <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
    <version>1.2.0</version>
    </dependency>
    <dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
    </dependency>
     
    <dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20090211</version>
    </dependency>
     
    <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.3.5</version>
    </dependency>
     
     
    <!-- poi excel导入导出 -->
    <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.9</version>
    </dependency>
    <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.9</version>
    </dependency>
     
     
    <!-- springMVC 数据校验 -->
     
    <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.3.0.Alpha1</version>
    </dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
    </dependency>
     
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
    </dependency>
    <!-- 解密 -->
    <dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.55</version>
    </dependency>
    <dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
    </dependency>
     
    <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
    <dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
    </dependency>
     
    <dependency>
    <groupId>com.baidu.aip</groupId>
    <artifactId>java-sdk</artifactId>
    <version>4.8.0</version>
    </dependency>
     
     
    </dependencies>
    <build>
    <plugins>
     
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
    <source>1.7</source>
    <target>1.7</target>
    </configuration>
    </plugin>
     
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.0.0</version>
    </plugin>
     
    </plugins>
    <finalName>maven_project</finalName>
     
     
    </build>
     
     
    </project>
     
     
    点击支付页面:demo.jsp
     
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@include file="/WEB-INF/html/base/baseurl.jsp"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <script src="<%=baseurl%>/js/jquery.js"></script>
    <script src="<%=baseurl%>/bootstrap/js/bootstrap.min.js"></script>
    </head>
    <body>
    <script type="text/javascript"
    src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <h2>微信支付</h2>
    <script>
    $(document).ready(function() {
    $("#yuzhifu").click(function() {
    alert(6)
    //js方法的调用
    yuzhifu();
    });
    });
     
    function yuzhifu() {
    //通过Ajax调用
    $.ajax({
    url : getRootPath() + "/Pay_Controller/yuxiadan.action",
    data : null,
    success : info
    });
    }
     
    function info(data) {
    var d = $(data);
    //页面跳转,并将code_url传到另一个页面中
    location.href = getRootPath()
    + "/BaseMultiController/toPage.action?page=main/demo/qrcode&param="
    + d[0].code_url;
     
    }
    </script>
    <input type="button" value=支付 id="yuzhifu">
     
     
     
    </body>
    </html>
     
     
    生成二维码页面:qrcode.jsp
     
     
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@include file="/WEB-INF/html/base/baseurl.jsp"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
    <head>
    <title>Javascript 二维码生成库:QRCode</title>
    <%
    out.print("<input type="hidden" id="hidden" value="");%><%=request.getAttribute("param") %><% out.print(""");
    %>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport"
    content="width=device-width,initial-scale=1,user-scalable=no" />
    <script type="text/javascript"
    src="http://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script type="text/javascript"
    src="http://static.runoob.com/assets/qrcode/qrcode.min.js"></script>
    </head>
    <body>
    <!-- <input id="text" type="text" value="http://www.runoob.com"
    style=" 80%" /> -->
    <br />
    <div id="qrcode" style=" 100px; height: 100px; margin-top: 15px;"></div>
     
    <script type="text/javascript">
    var qrcode = new QRCode(document.getElementById("qrcode"), {
    width : 300,
    height : 300
    });
     
    function makeCode() {
    var elText = document.getElementById("hidden");
    if (!elText.value) {
    alert("Input a text");
    elText.focus();
    return;
    }
     
    qrcode.makeCode(elText.value);
    }
     
    makeCode();
     
    $("#text").on("blur", function() {
    makeCode();
    }).on("keydown", function(e) {
    if (e.keyCode == 13) {
    makeCode();
    }
    });
    </script>
    </body>
    </html>
     
     
    注意:appid需要跟商户号绑定
     
     
  • 相关阅读:
    SQLServer2012数据库降级至SQLServer2008R2的方法
    男程序猿和女程序猿的网恋—相见(二)
    收藏关于AI的相关的文章
    JAVA提高九:集合体系
    JAVA提高八:动态代理技术
    JAVA提高七:类加载器
    JAVA提高六:泛型
    JAVA提高五:注解Annotation
    JAVA提高四:反射基本应用
    JAVA提高三:反射总结
  • 原文地址:https://www.cnblogs.com/bailing80/p/11449202.html
Copyright © 2011-2022 走看看