微信支付--企业支付到零钱

      最近由于开发需要,进行了微信支付--企业支付到零钱的功能开发,期间也参考了部分网上的开发思路,以及微信支付的开发问题,在这里做一下总结和源码分享。

     腾讯的开发文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1

    主要逻辑代码是这样的:

public class WxPayUtil {

    private static final Logger logger = LoggerFactory.getLogger(WxPayUtil.class);

    // 接口链接
    private static final String URL = WxPayDO.getUrl();

    private static final String appid = WxPayDO.getAppID();

    // 微信支付分配的商户号
    private static final String mchid = WxPayDO.getMch_id();

    public static Map<String, Object> wxPay(String openid, Integer amount,String userName) throws Exception {

        Map<String, Object> map = new HashMap<String, Object>();
//        logger.info("开始微信提现操作");
        //主机ip地址
        String IP = InetAddress.getLocalHost().getHostAddress();
        // 随机获取随机字符串
        String nonce_str = RandCharsUtil.getRandomString(16);
        //商户订单号
        String partner_trade_no = "partner_trade_no"+System.currentTimeMillis();
        //真实姓名
        String re_user_name = userName;

        // 企业付款描述信息
        String desc = "你的描述";
        if (!openid.equals("") || !openid.equals(null)) {

            // 设置支付参数
            SortedMap<Object, Object> signParams = new TreeMap<Object, Object>();
            signParams.put("mch_appid", appid); // 微信分配的公众账号ID
            signParams.put("mchid", mchid);// 微信支付分配的商户号
            signParams.put("nonce_str", nonce_str); // 随机字符串,不长于32位
            signParams.put("partner_trade_no", partner_trade_no); // 商户订单号,需保持唯一性
            signParams.put("openid", openid); // 商户appid下,某用户的openid
            signParams.put("check_name", "FORCE_CHECK"); // 校验真实姓名,也可以选择不做真实姓名校验
            signParams.put("re_user_name",re_user_name);
            signParams.put("amount", amount); // 企业付款金额,单位为分
            signParams.put("desc", desc); // 企业付款操作说明信息。必填。
            signParams.put("spbill_create_ip", IP); // 调用接口的机器Ip地址

            // 生成支付签名,要采用URLENCODER的原始值进行MD5算法!
            String sign = WXSignUtil.createSign("UTF-8", signParams);
//            logger.info("签名:"+sign);
            String data = "<xml><mch_appid>";
            data += appid + "</mch_appid><mchid>"; // APPID
            data += mchid + "</mchid><nonce_str>"; // 商户ID
            data += nonce_str + "</nonce_str><partner_trade_no>"; // 随机字符串
            data += partner_trade_no + "</partner_trade_no><openid>"; // 订单号
            data += openid + "</openid><check_name>FORCE_CHECK</check_name><re_user_name>"; // 是否强制实名验证
            data += re_user_name + "</re_user_name><amount>"; //用户真实姓名
            data += amount + "</amount><desc>"; // 企业付款金额,单位为分
            data += desc + "</desc><spbill_create_ip>"; // 企业付款操作说明信息。必填。
            data += IP + "</spbill_create_ip><sign>";// 调用接口的机器Ip地址
            data += sign + "</sign></xml>";// 签名

//            logger.info("xml数据:"+data);
            // 获取证书,发送POST请求;
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            // 从配置文件里读取证书的路径信息
            FileInputStream instream = new FileInputStream(
                    new File(WxPayDO.getClient().replaceAll("\\\\", "/")));

            keyStore.load(instream, mchid.toCharArray());// 证书密码是商户ID
            instream.close();
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray()).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
                    new String[] { "TLSv1" }, null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            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);
            HttpEntity entity = response.getEntity();

            String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
            logger.info("提现返回的数据为:" + jsonStr);
            EntityUtils.consume(entity);
            // 把返回的字符串解释成DOM节点
            Document dom = DocumentHelper.parseText(jsonStr);
            Element root = dom.getRootElement();
            String returnCode = root.element("result_code").getText(); // 获取返回代码

//            logger.info("返回状态码:"+returnCode);
            if (StringUtils.equals(returnCode, "SUCCESS")) { // 判断返回码为成功还是失败
                String payment_no = root.element("payment_no").getText(); // 获取支付流水号
                String payment_time = root.element("payment_time").getText(); // 获取支付时间
                //返回信息
                map.put("state", true);
                map.put("time", String.valueOf(System.currentTimeMillis()));
                logger.info(payment_no +"  支付成功  "+payment_time);
                return map;
            } else {
                String err_code = root.element("err_code").getText(); // 获取错误代码
                String err_code_des = root.element("err_code_des").getText();// 获取错误描述
                logger.info(err_code+"   支付失败  "+err_code_des);
                //返回错误信息
                map.put("state", false);
    //                        map.put("Message", utils);
                map.put("time", String.valueOf(System.currentTimeMillis()));
                return map;
            }
        } else {
            logger.info("没有获得openid");
            map.put("state", false);
            map.put("message", "抱歉没有获得openid");
            map.put("time", String.valueOf(System.currentTimeMillis()));
            return map;
        }
    }
}

代码有需要调用的类:

public class WXSignUtil {

    private static final Logger logger = LoggerFactory.getLogger(WXSignUtil.class);

    private static final String key = WxPayDO.getKey();

    public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
        StringBuffer sb = new StringBuffer();
        //所有参与传参的参数按照accsii排序(升序)
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object object = entry.getValue();
            if(null != object && !"".equals(object) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + object + "&");
            }
        }
        sb.append("key=").append(key);
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        logger.info("sign >>>> "+sign);
        return sign;
    }
}
public class WxPayDO implements Serializable {

    // 商户API密钥
    public static String key = "商户API密钥";

    private static String appID="appid";

    private static String mch_id="mch_id";

    //1.本地测试 (这里写了3个client 根据你本身的环境来定 这里配置的是你的证书路径 )
    //private static String client =  "\\apiclient_cert.p12";

    //2.这是window环境上的测试路径
//    private static String client =  "F:\\client\\apiclient_cert.p12";

    //3.这是linux环境下测试的路径
    private static String client =  "\\opt\\client\\apiclient_cert.p12";

    private static String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";

    public static String getKey() {
        return key;
    }

    public static void setKey(String key) {
        WxPayDO.key = key;
    }

    public static String getAppID() {
        return appID;
    }

    public static void setAppID(String appID) {
        WxPayDO.appID = appID;
    }

    public static String getMch_id() {
        return mch_id;
    }

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

    public static String getClient() {
        return client;
    }

    public static void setClient(String client) {
        WxPayDO.client = client;
    }

    public static String getUrl() {
        return url;
    }

    public static void setUrl(String url) {
        WxPayDO.url = url;
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值