java-微信银行卡提现和零钱提现记录


背景

商城项目客户需要提现功能,之前没有对接过,也遇到了一些小问题,防止以后出问题,这里做下简单记录。第一次写可能不是特别好,希望大家能够指出,一起进步。


准备

  • 获取微信商户证书

获取方式:微信商户后台-》账户中心-》API安全-》申请证书

  • 微信证书转16进制字符串存储(感谢 CS*N-代码风)
       try {
           FileInputStream file = new FileInputStream("E://xxx.p12");
           String s1 = Hex.encodeHexString(StreamUtils.copyToByteArray(file));
           System.out.println(s1);
       } catch (Exception e) {
           e.printStackTrace();
       }

   }
image.png
  • 商户APIkey

微信商户后台-》账户中心-》API安全-》API秘钥(没有的话生成一个)

使用条件
  • 商户号(或同主体其他非服务商商户号)已入驻90日
  • 截止今日回推30天,商户号(或同主体其他非服务商商户号)连续不间断保持有交易
  • 登录微信支付商户平台-产品中心,开通企业付款。
    (否则接口会返回没有权限,而且需要注意的是,未达到条件的微信商户,无法在产品中心看到该功能)

1.企业付款到零钱

官方文档

  • 调用接口:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
  • 是否需要证书:需要
  • API调用类
 /**
     * 企业付款到零钱
     * @param vo
     * @param mchApiKey
     * 必传参数
     *    vo => mch_appid           申请商户号的appid或商户号绑定的appid 微信appid  小程序appid
     *          mchid               商户号id
     *          partner_trade_no    商户订单号
     *          openid              用户openid
     *          amount              金额 单位 分
     *          desc                备注
     * @return
     */
    public static Map cashTransfers(TransfresParamsVo vo, String mchApiKey){

        Map returnMap = null; //返回结果
        try {
            //计算签名
            vo.setNonce_str(RandomUtil.randomString(32)); //随机字符串
            //实体类转map 工具包 hutool
            Map paramMap = BeanUtil.beanToMap(vo);
            //获取签名
            String sign = WechatSginUtils.getWechatPaySignStr(paramMap , mchApiKey); 
            vo.setSign(sign); //设置签名
            //对象转xml ture:是否去掉默认报文头 true去掉
            String apiParamXml = XmlUtils.beanToXml(vo, TransfresParamsVo.class, true);
            logger.info("transfresParams:{}", apiParamXml);
            //提交请求
            String reponseStr = HttpRequest.sendP12PostRequest(WECHAT_TRANSFRES_API, WECHAT_CRET_P12, apiParamXml, vo.getMchid());
            //xml转map
            returnMap = XmlUtils.xml2map(reponseStr, false);
        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnMap;
    }
  • 参数实体类
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * 微信提现到零钱参数
 */
@XmlRootElement(name = "xml") //实体转xml时的根节点
public class TransfresParamsVo {
    private String mch_appid; //申请商户号的appid或商户号绑定的appid 微信appid  小程序appid
    private String mchid; //商户号id
    private String nonce_str; //随机字符串
    private String sign; //签名
    private String partner_trade_no; //商户订单号
    private String openid; //用户openid
    private String check_name = "NO_CHECK"; //校验用户姓名选项 NO_CHECK 不校验真实姓名  FORCE_CHECK:强校验真实姓名
    private int amount; //金额 单位 分
    private String desc; //备注

    @XmlElement(name="mch_appid")
    public String getMch_appid() {
        return mch_appid;
    }

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

    @XmlElement(name="mchid")
    public String getMchid() {
        return mchid;
    }

    public void setMchid(String mchid) {
        this.mchid = mchid;
    }
    @XmlElement(name="nonce_str")
    public String getNonce_str() {
        return nonce_str;
    }

    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }

    @XmlElement(name="sign")
    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }
    @XmlElement(name="partner_trade_no")
    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;
    }

    @XmlElement(name="openid")
    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }
    @XmlElement(name="check_name")
    public String getCheck_name() {
        return check_name;
    }

    public void setCheck_name(String check_name) {
        this.check_name = check_name;
    }
    @XmlElement(name="amount")
    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }
    @XmlElement(name="desc")
    public String getDesc() {
        return desc;
    }

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

2.企业付款到银行卡

官方文档

接口: https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
是否需要证书:需要

按照常用惯例,得吐槽一下,微信文档,真的有点折磨人,本来俩个小时搞定的事情,偏偏因为一个小问题多花了一个小时,微信文档真不适合小白看。
与付款到零钱不同,付款到银行卡需要提供 银行卡号收款方用户名(废话),且在微信传参时 RSA加密,而这个RSA加密,需要调用 接口 获取 微信方的RSA公钥;然后按照下面的方式,对字符进行处理:

  • 调用获取RSA公钥API获取RSA公钥,落地成本地文件,假设为public.pem
  • 确定public.pem文件的存放路径,同时修改代码中文件的输入路径,加载RSA公钥
  • 用标准的RSA加密库对敏感信息进行加密,选择RSA_PKCS1_OAEP_PADDING填充模式
    (eg:Java的填充方式要选 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING")
  • 得到进行rsa加密并转base64之后的密文
  • 将密文传给微信侧相应字段,如付款接口(enc_bank_no/enc_true_name)
    (我星星特m的星星)
  • 获取微信RSA公钥
public static void main(String[] args) throws Exception {
       Map map = new HashMap<>();
        map.put("mch_id","***");
        map.put("nonce_str",RandomUtil.randomString(32));
        map.put("sign_type","MD5");
        String sign =WechatSginUtils.getWechatPaySignStr(map, "*****");
        map.put("sign", sign);
        Map map2 = map;
        String apiParamXml = XmlUtils.map2XmlString(map2); //对象转xml
        //带证书请求获取RSA公钥
        String reponseStr = HttpRequest.sendP12PostRequest("https://fraud.mch.weixin.qq.com/risk/getpublickey", WECHAT_CRET_P12, apiParamXml, "1584991451");
        System.out.println(reponseStr);
    }
  • 获取到的RSA公钥转一下 PKCS#8 这里我用的网页转的:传送门
  • 转换前:
    -----BEGIN RSA PRIVATE KEY-----
    MIICWwIBAAKBgQC9XrJWcWbj0LhDBzN4uwEOLA/UJKmCkkbvlVgN/qei3e/jVFpx
    R6D3fzshnv5QNB4+BJ/rjRWbbxCJ0djzPxsLS1dJ+bDwagZWZ9hNXARTq4K0uxw6
    Ol5jGD9Od6w5n5uxyaEk9/edvYwMhthIxC/uADRp2pNSutwyLX3bUJnHZwIDAQAB
    AoGANN3S+7788my6hDvmarYKPWKfqKHzkLg1hX0z7/Q/6H/9EIHkHevZTD8AywoQ
    BWQHbVjtLF1ewt3myBMFdiMP8UOx0WVErcyuVRh8AUcRZIEwz73jmLmpRd8fVAzy
    8uoijKvExt/fdu9aIfVmV4nXvL5dDpsoL/mVRDgNCZ+9mMECQQDzWLnqty25mgEs
    73rJ8mhehifwblg44uO+9xpmKZhG3NFZW+beG1iPZklBVlaQ6m53e77VbVotC+LF
    efsaOtU7AkEAxzd3q0REhF/FaFcq9TV3Eu3C4B/aqARKgkpJKiaCC4tnAqny7Rvd
    /anxLBf8DFPYjPMkPrNqXoDA8rAC9TwDxQJBAPF6mHOMdvl5E7WNp6GCxYMXScbT
    GQTKUgoMl8vNdujK84vjIMRDCqyyaftGO/zuRdSXnZWZQCT3aH9iPoWW4EUCQB1r
    NYLXK/8YXYCRDsjzQkhLUDHkwld5er9O1QsicKXfyjB8hGE7ckbZZ8IJMLFpWFtI
    NJwFxrl57gRotacdW7kCP2r3MkJqtHdrjUbaCJJCnHmX9BhYcBhaYS2yGFW9uyNT
    5TGOrrzjz+CXBNrif3JkDbDYv2z/cCgd7kqV1kPl/g==
    -----END RSA PRIVATE KEY-----
  • 转换后
    -----BEGIN PRIVATE KEY-----
    MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAL1eslZxZuPQuEMH
    M3i7AQ4sD9QkqYKSRu+VWA3+p6Ld7+NUWnFHoPd/OyGe/lA0Hj4En+uNFZtvEInR
    2PM/GwtLV0n5sPBqBlZn2E1cBFOrgrS7HDo6XmMYP053rDmfm7HJoST39529jAyG
    2EjEL+4ANGnak1K63DItfdtQmcdnAgMBAAECgYA03dL7vvzybLqEO+Zqtgo9Yp+o
    ofOQuDWFfTPv9D/of/0QgeQd69lMPwDLChAFZAdtWO0sXV7C3ebIEwV2Iw/xQ7HR
    ZUStzK5VGHwBRxFkgTDPveOYualF3x9UDPLy6iKMq8TG399271oh9WZXide8vl0O
    mygv+ZVEOA0Jn72YwQJBAPNYueq3LbmaASzvesnyaF6GJ/BuWDji4773GmYpmEbc
    0Vlb5t4bWI9mSUFWVpDqbnd7vtVtWi0L4sV5+xo61TsCQQDHN3erRESEX8VoVyr1
    NXcS7cLgH9qoBEqCSkkqJoILi2cCqfLtG939qfEsF/wMU9iM8yQ+s2pegMDysAL1
    PAPFAkEA8XqYc4x2+XkTtY2noYLFgxdJxtMZBMpSCgyXy8126Mrzi+MgxEMKrLJp
    +0Y7/O5F1JedlZlAJPdof2I+hZbgRQJAHWs1gtcr/xhdgJEOyPNCSEtQMeTCV3l6
    v07VCyJwpd/KMHyEYTtyRtlnwgkwsWlYW0g0nAXGuXnuBGi1px1buQI/avcyQmq0
    d2uNRtoIkkKceZf0GFhwGFphLbIYVb27I1PlMY6uvOPP4JcE2uJ/cmQNsNi/bP9w
    KB3uSpXWQ+X+
    -----END PRIVATE KEY-----
  • 获取到pks8私钥后你可以转存文件xxx.pem,或者用静态常量存储调用,常量存储需要去掉-----BEGIN PRIVATE KEY----- -----END PRIVATE KEY-----,只留下中间的字符


    image.png
  • API调用

/**
     * 企业付款到银行卡
     * @param vo
     * @param mchApiKey
     * @return
     */
    public static Map cashPayBank(CashPayBankVo vo, String mchApiKey){
        Map returnMap = null; //返回结果
        try {
            //银行卡用户名称 RSA加密
            String enctrueName = WechatRsaUtils.encrypt(vo.getEnc_true_name().getBytes("UTF-8"), WechatRsaUtils.loadPublicKey(WECHAT_PUB_KEY));//rsa公钥加密 用户名称
            String encBankNo = WechatRsaUtils.encrypt(vo.getEnc_bank_no().getBytes("UTF-8"), WechatRsaUtils.loadPublicKey(WECHAT_PUB_KEY)); //rsa公钥加密 用户银行卡
            vo.setEnc_true_name(Base64.encode(enctrueName)); //用户名称 base64
            vo.setEnc_bank_no(Base64.encode(encBankNo)); //用户银行卡 base64
            vo.setNonce_str(RandomUtil.randomString(32)); //随机字符串
            //获取签名
            vo.setSign(WechatSginUtils.getWechatPaySignStr(BeanUtil.beanToMap(vo), mchApiKey)); //签名
            //对象转xml
            String apiParamXml = XmlUtils.beanToXml(vo, CashPayBankVo.class, true); //对象转xml
            logger.info("cashPayBank:{}", apiParamXml);
            //提交请求
            String reponseStr = HttpRequest.sendP12PostRequest(WECHAT_PAYBANK_API, WECHAT_CRET_P12, apiParamXml, vo.getMch_id());
            //xml转map
            returnMap = XmlUtils.xml2map(reponseStr, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnMap;
    }
  • 参数实体类
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * 企业付款到银行卡 参数对象
 */
@XmlRootElement(name = "xml")
public class CashPayBankVo {
    private String mch_id; //商户号
    private String partner_trade_no; //商户企业付款单号
    private String nonce_str; //随机字符串
    private String sign; //签名
    private String enc_bank_no; //收款方银行卡号
    private String enc_true_name; //收款方用户名
    private String bank_code; //收款方开户行
    private int amount; //付款金额 单位 分
    private String desc; //付款说明

    @XmlElement(name="sign")
    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    @XmlElement(name="amount")
    public int getAmount() {
        return amount;
    }

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

    @XmlElement(name="desc")
    public String getDesc() {
        return desc;
    }

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

    @XmlElement(name="mch_id")
    public String getMch_id() {
        return mch_id;
    }

    public void setMch_id(String mch_id) {
        this.mch_id = mch_id;
    }

    @XmlElement(name="partner_trade_no")
    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;
    }

    @XmlElement(name="nonce_str")
    public String getNonce_str() {
        return nonce_str;
    }

    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }

    @XmlElement(name="enc_bank_no")
    public String getEnc_bank_no() {
        return enc_bank_no;
    }


    public void setEnc_bank_no(String enc_bank_no) {
        this.enc_bank_no = enc_bank_no;
    }

    @XmlElement(name="enc_true_name")
    public String getEnc_true_name() {
        return enc_true_name;
    }

    public void setEnc_true_name(String enc_true_name) {
        this.enc_true_name = enc_true_name;
    }

    @XmlElement(name="bank_code")
    public String getBank_code() {
        return bank_code;
    }

    public void setBank_code(String bank_code) {
        this.bank_code = bank_code;
    }
}

3.工具类

工具包:Hutool

    cn.hutool
    hutool-all
    5.3.9

  • xml工具类
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.*;

/**
 * xml工具类
 */
public class XmlUtils {

    /**
     * 实体转xml
     * @param obj
     * @param load
     * @param is_fragment 是否去掉默认报文头
     * @return
     * @throws JAXBException
     */
    public static String beanToXml(Object obj, Class load, boolean is_fragment) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(load);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, is_fragment);
        StringWriter writer = new StringWriter();
        marshaller.marshal(obj,writer);
        return writer.toString();
    }

    /**
     * xml字符转对象
     * @param xmlStr
     * @param load
     * @return
     * @throws JAXBException
     */
    public static Object xmlToBean(String xmlStr, Class load) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(load);
        // 进行将Xml转成对象的核心接口
        Unmarshaller unmarshaller = context.createUnmarshaller();
        StringReader sr = new StringReader(xmlStr);
        return unmarshaller.unmarshal(sr);
    }

    /**
     * map 转xml
     * @param map
     * @return
     */
    public static String map2XmlString(Map map) {
        String xmlResult = "";
        StringBuffer sb = new StringBuffer();
        sb.append("");
        for (String key : map.keySet()) {
            String value = "";
            sb.append("<" + key + ">" + value + "");
        }
        sb.append("");
        xmlResult = sb.toString();

        return xmlResult;
    }

    /**
     * xml转map 不带属性
     * @param xmlStr
     * @param needRootKey 是否需要在返回的map里加根节点键
     * @return

     */
    public static Map xml2map(String xmlStr, boolean needRootKey) {
        Map map = null;

        try {
            Document doc = DocumentHelper.parseText(xmlStr);
            Element root = doc.getRootElement();
            map = (Map) xml2map(root);
            if(root.elements().size()==0 && root.attributes().size()==0){
                return map;
            }
            if(needRootKey){
                //在返回的map里加根节点键(如果需要)
                Map rootMap = new HashMap();
                rootMap.put(root.getName(), map);
                return rootMap;
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return map;
    }

    /**
     * xml转map 不带属性
     * @param e
     * @return
     */
    private static Map xml2map(Element e) {
        Map map = new LinkedHashMap();
        List list = e.elements();
        if (list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Element iter = (Element) list.get(i);
                List mapList = new ArrayList();

                if (iter.elements().size() > 0) {
                    Map m = xml2map(iter);
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!(obj instanceof List)) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(m);
                        }
                        if (obj instanceof List) {
                            mapList = (List) obj;
                            mapList.add(m);
                        }
                        map.put(iter.getName(), mapList);
                    } else
                        map.put(iter.getName(), m);
                } else {
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!(obj instanceof List)) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(iter.getText());
                        }
                        if (obj instanceof List) {
                            mapList = (List) obj;
                            mapList.add(iter.getText());
                        }
                        map.put(iter.getName(), mapList);
                    } else
                        map.put(iter.getName(), iter.getText());
                }
            }
        } else
            map.put(e.getName(), e.getText());
        return map;
    }

}
  • 微信签名工具类
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.jeespring.common.security.MD5Tools;
import com.jeespring.common.weike.wechat.config.WechatApiContext;
import com.jeespring.common.weike.wechat.vo.pay.WechatSignVo;

import java.util.*;

public class WechatSginUtils {

    /**
     * 获取微信支付签名
     * @param paramMap
     * @param mchApiKey
     * @return
     * @throws Exception
     */
    public static String getWechatPaySignStr(Map paramMap ,String mchApiKey) throws Exception{
        StringBuffer sbuff = new StringBuffer();
        //字典排序
        List paramsList = new ArrayList<>(paramMap.keySet());
        Collections.sort(paramsList);
        for (int i = 0; i < paramsList.size(); i++){
            String key = paramsList.get(i);
            Object val = paramMap.get(key);
            if (val != null){
                sbuff.append(key);
                sbuff.append("=");
                sbuff.append(val);
                sbuff.append("&");
            }
        }
        //拼接商户APIkey
        sbuff.append("key=".concat(mchApiKey));
        //签名MD5转大写加密
        String sign = MD5Tools.MD5(sbuff.toString()).toUpperCase();
        return sign;
    }

    /**
     * 预支付返回签名
     * @param vo
     * @param mchApiKey
     * @throws Exception
     */
    public static void getWechatReturnSgin(WechatSignVo vo , String mchApiKey) throws Exception{
        StringBuffer sbuff = new StringBuffer();
        //随机字符串
        vo.setNonceStr(RandomUtil.randomString(32));
        //字典排序
        Map paramMap = BeanUtil.beanToMap(vo);
        List paramsList = new ArrayList<>(paramMap.keySet());
        Collections.sort(paramsList);
        for (int i = 0; i < paramsList.size(); i++){
            String key = paramsList.get(i);
            Object val = paramMap.get(key);
            if (val != null){
                if ((WechatApiContext.WECHAT_PAY_SGIN_PACKAGE_SGINSTR.concat("Str")).equals(key)){
                    key = WechatApiContext.WECHAT_PAY_SGIN_PACKAGE_SGINSTR;
                }
                sbuff.append(key);
                sbuff.append("=");
                sbuff.append(val);
                sbuff.append("&");
            }
        }

        //拼接商户APIkey
        sbuff.append("key=".concat(mchApiKey));
        //签名MD5转大写加密
        String sign = MD5Tools.MD5(sbuff.toString()).toUpperCase();
        vo.setPaySign(sign);
    }



}
  • RSA工具类

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import static com.jeespring.common.utils.Encodes.decodeBase64;

public class WechatRsaUtils {

    private static String RSA = "RSA";
    private static final int KEYLENGTH = 2048;
    private static final int RESERVESIZE  = 11;

    /**
     * 指定填充模式
     */
    private static final String CIPHERALGORITHM = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";

    /**
     * 用公钥加密 
* 每次加密的字节数,不能超过密钥的长度值减去11 * * @param plainBytes 需加密数据的byte数据 * @param publicKey 公钥 * @return 加密后的byte型数据 */ public static String encrypt(byte[] plainBytes, PublicKey publicKey) throws Exception { int keyByteSize = KEYLENGTH / 8; int encryptBlockSize = keyByteSize - RESERVESIZE; int nBlock = plainBytes.length / encryptBlockSize; if ((plainBytes.length % encryptBlockSize) != 0) { nBlock += 1; } ByteArrayOutputStream outbuf = null; try { Cipher cipher = Cipher.getInstance(CIPHERALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); outbuf = new ByteArrayOutputStream(nBlock * keyByteSize); for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) { int inputLen = plainBytes.length - offset; if (inputLen > encryptBlockSize) { inputLen = encryptBlockSize; } byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen); outbuf.write(encryptedBlock); } outbuf.flush(); byte[] encryptedData = outbuf.toByteArray(); return Base64.encodeBase64String(encryptedData); } catch (Exception e) { throw new Exception("ENCRYPT ERROR:", e); } finally { try { if (outbuf != null) { outbuf.close(); } } catch (Exception e) { throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e); } } } /** * 从字符串中加载公钥 * * @param publicKeyStr 公钥数据字符串 * @throws Exception 加载公钥时产生的异常 */ public static PublicKey loadPublicKey(String publicKeyStr){ PublicKey publicKey = null; try { byte[] buffer = decodeBase64(publicKeyStr); KeyFactory keyFactory = KeyFactory.getInstance(RSA); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); publicKey = keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } catch (NullPointerException e) { e.printStackTrace(); } return publicKey; } }
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
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.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;

public class HttpRequest {
    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            //Map> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            //for (String key : map.keySet()) {
               // System.out.println(key + "--->" + map.get(key));
            //}
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e.toString());
            result="Down";
            //e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!"+e.toString());
            //e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }

    public static String sendP12PostRequest(String url, String cretCode, String param, String cretkey){
        CloseableHttpClient client = null;
        HttpPost httpPost = null;
        try {
            //解析证书
            byte[] bytes = Hex.decodeHex(cretCode.toCharArray()); //解密出16进制原证书文件内容为字节数组
            ByteArrayInputStream input = new ByteArrayInputStream(bytes); //读取字节数组
            KeyStore clientTrustKeyStore = KeyStore.getInstance("PKCS12"); //获取PKCS12秘钥库实例
            clientTrustKeyStore.load(input, cretkey.toCharArray()); //秘钥解析
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(clientTrustKeyStore, cretkey.toCharArray());

            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("TLSv1");
            sslContext.init(kmf.getKeyManagers(), tm, new java.security.SecureRandom());
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
            client = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            httpPost = new HttpPost(url);
            httpPost.setEntity(new StringEntity(param, "utf-8"));
            CloseableHttpResponse response = client.execute(httpPost);
            StatusLine statusLine = response.getStatusLine();
            HttpEntity entity = response.getEntity();
            if (statusLine.getStatusCode() == 200) {
                return EntityUtils.toString(entity, "utf-8");
            }
        } catch (DecoderException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getParameterMapString(HttpServletRequest request){
        if(request.getQueryString()!=null){
            if(request.getQueryString().length()>0){
                return request.getQueryString();
            }
        }
        Map map = request.getParameterMap();
        java.util.Enumeration enumx = request.getParameterNames();
        String result="";
        while(enumx.hasMoreElements()){
            String  paramName=(String)enumx.nextElement();
            String[]  values=request.getParameterValues(paramName);
            for(int  i=0;i

你可能感兴趣的:(java-微信银行卡提现和零钱提现记录)