微信支付--商家转账到零钱

/**
 * 微信接口请求参数对象
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class TransfersVO {

    private byte[] certData;


    /**
     * 与商户号关联应用(如微信公众号/小程序)的APPID
     */
    private String mchAppid;

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

    /**
     * 商户名称, 如'XXX服务号'
     */
    private String mchName;

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

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

    /**
     * NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名
     */
    private String checkName = "NO_CHECK";

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

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

    /**
     * 企业付款备注
     */
    private String desc;

    private String appKey;

    private String sceneId;

    /**
     * 发起者IP地址+该IP可传用户端或者服务端的IP。
     */
    private String spbillCreateIp = "127.0.0.1";

    @Transient
    public Map<String, String> map()
    {
        Map<String, String> map = new HashMap<String, String>();
        map.put("mch_appid", this.mchAppid);
        map.put("mchid", this.mchId);
        map.put("mch_name", this.mchName);
        map.put("openid", this.openid);
        map.put("amount", String.valueOf(this.amount));
        map.put("desc", this.desc);
        map.put("appkey", this.appKey);
        map.put("nonce_str", this.nonceStr);
        map.put("partner_trade_no", this.partnerTradeNo);
        map.put("spbill_create_ip", this.spbillCreateIp);
        return map;
    }

	/**
     * 获取证书流
     * @param certPath 证书路径
     */
    public InputStream getCertStream(String certPath) throws IOException {
        File file = new File(certPath);
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();
        ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
        return certBis;
    }



}

/**
 * 微信工具类
 */
@Component
@Slf4j
public class WxUtils {
	
	

/**
     * 付款
     *
     * @param mchKey   商户密钥
     * @param certPath 证书路径
     * @param model    微信接口请求参数对象
     */
    public static void doTransfers(String mchKey, String certPath, TransfersVO model) {
        
        // 微信商户证书路径
        try {

            // 1.计算参数签名
           String paramStr = WxUtils.createLinkString(model,mchKey);
       
            String sign = DigestUtils.md5Hex(paramStr).toUpperCase();
            // 2.封装请求参数
            StringBuilder reqXmlStr = new StringBuilder();

            reqXmlStr.append("<xml>");
            reqXmlStr.append("<mchid>" + model.getMchId() + "</mchid>");
            reqXmlStr.append("<mch_appid>" + model.getMchAppid() + "</mch_appid>");
            reqXmlStr.append("<nonce_str>" + model.getNonceStr() + "</nonce_str>");
            reqXmlStr.append("<check_name>" + model.getCheckName() + "</check_name>");
            reqXmlStr.append("<openid>" + model.getOpenid() + "</openid>");
            reqXmlStr.append("<amount>" + model.getAmount().intValue() + "</amount>");
            reqXmlStr.append("<desc>" + model.getDesc() + "</desc>");
            reqXmlStr.append("<sign>" + sign + "</sign>");
            reqXmlStr.append("<partner_trade_no>" + model.getPartnerTradeNo() + "</partner_trade_no>");
            //reqXmlStr.append("<spbill_create_ip>" + model.getSpbillCreateIp() + "</spbill_create_ip>");
            reqXmlStr.append("</xml>");

            // 3.加载证书请求接口
            String result = WxPayRequestUtils.httpsRequest(TRANS_URL, reqXmlStr.toString(),
                    model, certPath);

            if (result.contains("CDATA[FAIL]")) {
                log.info("领取红包结果:"+result); //领取失败

                throw new ServiceException(ResultCodeEnum.BUSINESS_ERROR.getCode(), "领取红包失败");
            } else {
                //领取成功
            }
        } catch (Exception e) {
            log.error("领取红包出现异常:{}", e); //领取失败
        }
    }

    private static String createLinkString(TransfersVO model,String mchKey) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("mch_appid", model.getMchAppid());
        paramMap.put("mchid", model.getMchId());
        paramMap.put("openid", model.getOpenid());
        paramMap.put("amount", model.getAmount().intValue());
        paramMap.put("check_name", model.getCheckName());
        paramMap.put("desc", model.getDesc());
        paramMap.put("partner_trade_no", model.getPartnerTradeNo());
        paramMap.put("nonce_str", model.getNonceStr());
        List<String> keys = new ArrayList(paramMap.keySet());
        Collections.sort(keys);
        StringBuilder preStr = new StringBuilder();
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            Object value = paramMap.get(key);
            if (i == keys.size() - 1) {
                // 拼接时,不包括最后一个&字符
                preStr.append(key).append("=").append(value);
            } else {
                preStr.append(key).append("=").append(value).append("&");
            }
        }
        preStr.append("&key="+mchKey);
        return preStr.toString();
    }
}

@Component
public class WxPayRequestUtils {
	
 // 连接超时时间,默认10秒
    private int socketTimeout = 10000;

    // 传输超时时间,默认30秒
    private int connectTimeout = 30000;

    // 请求器的配置
    private static RequestConfig requestConfig;

    // HTTP请求器
    private static CloseableHttpClient httpClient;



    /**
     * 加载证书
     * @param path
     * @param transfer
     * @throws Exception
     */
    private static void initCert(String path, TransfersVO transfer) throws Exception {
        BasicHttpClientConnectionManager connManager;
        // 拼接证书的路径
        char[] password = transfer.getMchId().toCharArray();
        InputStream certStream = transfer.getCertStream(path);
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(certStream, password);

        // 实例化密钥库 & 初始化密钥工厂
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password);
        // 创建 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslContext,
                new DefaultHostnameVerifier());

        connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", sslConnectionSocketFactory)
                        .build(),
                null,
                null,
                null
        );
        httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        /**if (CommonUtils.isPro()){
            // 代理
            HttpHost httpHost = new HttpHost("代理", 80);
            // 根据默认超时限制初始化requestConfig
            requestConfig = RequestConfig.custom()
                    .setSocketTimeout(10000)
                    .setConnectTimeout(30000)
                    .setProxy(httpHost)
                    .build();
        }*/

    }

    /**
     * 通过Https往API post xml数据
     *
     * @param url    API地址
     * @param xmlObj 要提交的XML数据对象
     * @param path   当前目录,用于加载证书
     * @return 支付结果
     * @throws Exception 异常
     */
    public static String httpsRequest(String url, String xmlObj, TransfersVO model, String path) throws Exception {
        // 加载证书
        initCert(path, model);
        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);
         /**if (CommonUtils.isPro()){
            // 设置请求器的配置
            httpPost.setConfig(requestConfig);
        }*/
        HttpResponse response = httpClient.execute(httpPost);

        HttpEntity entity = response.getEntity();

        result = EntityUtils.toString(entity, "UTF-8");

        httpPost.abort();
        return result;
    }
}
@Test
    public void testReward() throws Exception {
        TransfersVO model = new TransfersVO();
        model.setMchId("");
        model.setMchAppid("");
        model.setMchName("");
        model.setOpenid("");
        model.setAmount(40.0);
        model.setDesc("红包");
        model.setSceneId("PRODUCT_4");
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 15; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        model.setNonceStr(sb.toString());
        String partnerTradeNo = model.getMchId()
                + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
                + (int) ((Math.random() * 9 + 1) * 1000);
        model.setPartnerTradeNo(partnerTradeNo);
        WxUtils.doTransfers("商户密钥","证书路径",model);

    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值