java 企业付款到零钱 微信提现功能讲解

附官方地址:

       微信官方api     微信公众号获取用户openid

只讲容易遇到的坑

微信api说明,请求需要双向证书。 所以需要去商户管理后台下载api证书  微信支付平台 

在支付平台->账户中心->api安全 下载证书   并设置秘钥   

然后在营销中心->支付后配置  查看发起提现公众号的appid  此appid一定要和获取用户openid的appid一致

将上图这个id记住 这是商户号

从微信支付平台中我们要下载证书,设置秘钥,确保appid一致,获取商户号

api具体请求就不分析了 有文档  直接上代码

package com.liuyb.model;

/**
 * @Auther: liuyubo
 * @Date: 2018/8/10 20:30
 * @Description:实体类
 */
public class EnterprisesPayment {
    /**
     * 商户账号appid
     * 申请商户号的appid或商户号绑定的appid
     */
    private String mch_appid;

    /**
     * 商户号 微信支付分配的商户号
     */
    private String mchid;

    /**
     *设备号013467007045764
     * 微信支付分配的终端设备号
     */
    private String device_info;

    /**
     * 随机字符串	5K8264ILTKCH16CQ2502SI8ZNMTM67VS
     * 随机字符串,不长于32位
     */
    private String nonce_str;

    /**
     * 签名	C380BEC2BFD727A4B6845133519F3AD6
     */
    private String sign;

    /**
     *商户订单号  商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号)
     */
    private String partner_trade_no;

    /**
     *用户openid  商户appid下,某用户的openid
     */
    private String openid;

    /**
     * 校验用户姓名选项	 不校验真实姓名 NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名
     *
     */
    private String check_name;

    /**
     * 收款用户姓名		收款用户真实姓名。 如果check_name设置为FORCE_CHECK,则必填用户真实姓名
     */
    private String re_user_name;

    /**
     * 金额	 企业付款金额,单位为分
     */
    private Integer amount;

    /**
     * 企业付款描述信息	理赔	企业付款操作说明信息
     */
    private String desc;

    /**
     * Ip地址	该IP同在商户平台设置的IP白名单中的IP没有关联,该IP可传用户端或者服务端的IP。
     */
    private String spbill_create_ip;



    public String getMch_appid() {
        return mch_appid;
    }

    public void setMch_appid(String mch_appid) {
        this.mch_appid = mch_appid;
    }

    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 getPartner_trade_no() {
        return partner_trade_no;
    }

    public void setPartner_trade_no(String partner_trade_no) {
        this.partner_trade_no = partner_trade_no;
    }

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }

    public String getCheck_name() {
        return check_name;
    }

    public void setCheck_name(String check_name) {
        this.check_name = check_name;
    }

    public String getRe_user_name() {
        return re_user_name;
    }

    public void setRe_user_name(String re_user_name) {
        this.re_user_name = re_user_name;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    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 getMchid() {
        return mchid;
    }

    public void setMchid(String mchid) {
        this.mchid = mchid;
    }
}
package com.liuyb.util;


import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * @Auther: liuyubo
 * @Date: 2018/8/10 20:39
 * @Description: 加载证书 发送请求
 */
public class ClientCustomSSL {

    public static String doRefund(String url,String xmlData) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File(""));//P12文件目录  写证书的项目路径
        try {
            keyStore.load(instream, "xxxx".toCharArray());//这里写密码..默认是你的MCHID 证书密码
        } finally {
            instream.close();
        }


        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, "xxxx".toCharArray())//这里也是写密码的
                .build();

        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();

                String returnMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return returnMessage; //返回后自己解析结果
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}

/**
 * @Auther: liuyubo
 * @Date: 2018/8/10 20:46
 * @Description: 微信提现 xml数据 签名等
 */
public class WeixinpayUtil {


    private static final Logger LOG = Logger.getLogger(WeixinpayUtil.class);



    public static String createDocumentForEnterprisesPayment(EnterprisesPayment enterprisesPayment) {
        final StringBuffer result = new StringBuffer();
        result.append("<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><xml>");
        result.append("<mch_appid>" + enterprisesPayment.getMch_appid() + "</mch_appid>");
        result.append("<mchid>" + enterprisesPayment.getMchid() + "</mchid>");
        result.append("<nonce_str>" + enterprisesPayment.getNonce_str() + "</nonce_str>");
        result.append("<partner_trade_no>" + enterprisesPayment.getPartner_trade_no() + "</partner_trade_no>");
        result.append("<openid>" + enterprisesPayment.getOpenid() + "</openid>");
        result.append("<check_name>" + enterprisesPayment.getCheck_name() + "</check_name>");
        result.append("<re_user_name>" + enterprisesPayment.getRe_user_name() + "</re_user_name>");
        result.append("<amount>" +enterprisesPayment.getAmount()+ "</amount>");
        result.append("<desc>" + enterprisesPayment.getDesc() + "</desc>");
        result.append("<spbill_create_ip>" + enterprisesPayment.getSpbill_create_ip() + "</spbill_create_ip>");
        result.append("<sign>" + enterprisesPayment.getSign() + "</sign>");
        result.append("</xml>");
        return result.toString();
    }

    


    public static String getSignCode(Map<String, String> map,String keyValue) {
        String result = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {

                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });

            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (item.getKey() != null || item.getKey() != "") {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(key + "=" + val + "&");
                    }
                }

            }
            sb.append("key="+keyValue);
            result = sb.toString();

            //进行MD5加密
            result = WeixinpayUtil.md5(result).toUpperCase();
        } catch (Exception e) {
            return null;
        }
        return result;
    }

    /**
     * 生成32位编码
     * @return string
     */
    public static String getUUID(){
        String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
        return uuid;
    }

    /**
     *  生成提现订单号
     * @return string
     */
    public static String getOrderId() {
        int machineId = 1;//最大支持1-9个集群机器部署
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if(hashCodeV < 0) {//有可能是负数
            hashCodeV = - hashCodeV;
        }
        return machineId+String.format("%015d", hashCodeV);
    }

    /**
     *  md5加密
     * @param text
     * @return
     */
    public static String md5(final String text) {
       //自己写一个md5方法 这里我就不写了  记得大写
        return Md5Encrypt.md5(text).toUpperCase();

    }


}
/**
 * @Auther: liuyubo
 * @Date: 2018/8/10 20:59
 * @Description: test
 */
public class Test {

   private SortedMap<String,String> sortedMap = new TreeMap<>();

    public static void main(String[] args) {

        String sginCode = getSgin(openid,amount);//获取用户openid 和 用户要提现的金额  拿到签名
        EnterprisesPayment enterprisesPayment  = addEnterprisesPayment(openid,amount,sginCode);//拿到签名后加密得到要发送到对象数据
        String enterprisesPaymentXML = WeixinpayUtil.createDocumentForEnterprisesPayment(enterprisesPayment);
  //封装xml 数据发送
        String returnXmlData =
  ClientCustomSSL.doRefund("url地址",enterprisesPaymentXML);



    }


    public EnterprisesPayment addEnterprisesPayment(String openid, Integer amount,String sginCode){

        EnterprisesPayment enterprisesPayment = new EnterprisesPayment();

        enterprisesPayment.setMch_appid("appid");//商户号appid

        enterprisesPayment.setMchid("商户号");//商户号

        // enterprisesPayment.setDevice_info(null);//设备号 非必填

        enterprisesPayment.setNonce_str(sortedMap.get("nonce_str"));//随机字符串

        enterprisesPayment.setSign(sginCode);//签名

        enterprisesPayment.setPartner_trade_no(sortedMap.get("partner_trade_no"));//商户订单号

        enterprisesPayment.setOpenid(openid);
    
        enterprisesPayment.setCheck_name("NO_CHECK");

        enterprisesPayment.setRe_user_name(null); 根据checkName字段判断是否需要

        enterprisesPayment.setAmount(amount);//金额

        enterprisesPayment.setDesc("desc");//描述

        enterprisesPayment.setSpbill_create_ip("ip");//ip地址

        return enterprisesPayment;

    }

    


public String getSgin(String openid, Integer amount) {

        sortedMap.put("mch_appid","appid");

        sortedMap.put("mchid","商户号");

        sortedMap.put("nonce_str", WeixinpayUtil.getUUID());

        sortedMap.put("partner_trade_no", WeixinpayUtil.getOrderId());

        sortedMap.put("openid", openid);

        sortedMap.put("check_name", "NO_CHECK");

        sortedMap.put("amount", amount.toString());

        sortedMap.put("desc", "desc");

        sortedMap.put("spbill_create_ip", "ip");

        sortedMap.put("re_user_name", "null");

        return WeixinpayUtil.getSignCode(sortedMap,"api秘钥");

    }
}

具体就这些吧 不懂到来问我 q群 8028492

猜你喜欢

转载自blog.csdn.net/qq_31896043/article/details/81569164