美文网首页
java-微信银行卡提现和零钱提现记录

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

作者: 每天都是奥利给 | 来源:发表于2020-07-16 15:52 被阅读0次

    背景

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


    准备

    • 获取微信商户证书

    获取方式:微信商户后台-》账户中心-》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.企业付款到零钱

    官方文档

    • 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<String,Object> cashTransfers(TransfresParamsVo vo, String mchApiKey){
    
            Map<String,Object> returnMap = null; //返回结果
            try {
                //计算签名
                vo.setNonce_str(RandomUtil.randomString(32)); //随机字符串
                //实体类转map 工具包 hutool
                Map<String,Object> 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<String, Object> 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<String, Object> 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<String, Object> cashPayBank(CashPayBankVo vo, String mchApiKey){
            Map<String, Object> 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
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.3.9</version>
    </dependency>
    
    • 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<String, Object> map) {
            String xmlResult = "";
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");
            for (String key : map.keySet()) {
                String value = "<![CDATA[" + map.get(key) + "]]>";
                sb.append("<" + key + ">" + value + "</" + key + ">");
            }
            sb.append("</xml>");
            xmlResult = sb.toString();
    
            return xmlResult;
        }
    
        /**
         * xml转map 不带属性
         * @param xmlStr
         * @param needRootKey 是否需要在返回的map里加根节点键
         * @return
    
         */
        public static Map xml2map(String xmlStr, boolean needRootKey) {
            Map<String, Object> map = null;
    
            try {
                Document doc = DocumentHelper.parseText(xmlStr);
                Element root = doc.getRootElement();
                map = (Map<String, Object>) xml2map(root);
                if(root.elements().size()==0 && root.attributes().size()==0){
                    return map;
                }
                if(needRootKey){
                    //在返回的map里加根节点键(如果需要)
                    Map<String, Object> rootMap = new HashMap<String, Object>();
                    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<String,Object> paramMap ,String mchApiKey) throws Exception{
            StringBuffer sbuff = new StringBuffer();
            //字典排序
            List<String> 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<String,Object> paramMap = BeanUtil.beanToMap(vo);
            List<String> 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";
    
        /**
         * 用公钥加密 <br>
         * 每次加密的字节数,不能超过密钥的长度值减去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<String, List<String>> 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<values.length;i++){
                    result+=paramName+"="+values[i]+"&";
                }
            }
            return result;
        }
    
    
        private static class MyX509TrustManager implements X509TrustManager {
    
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
            }
    
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:java-微信银行卡提现和零钱提现记录

          本文链接:https://www.haomeiwen.com/subject/hvlphktx.html