微信官方支付接口地址:https://pay.weixin.qq.com/wiki/doc/api/index.html

导入WXPayUtil 

<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>

统一支付https://api.mch.weixin.qq.com/pay/unifiedorder

  /**
     *func :微信统一支付接口
     *
      *date:2019-11-11
      *作者:lijinquan
      **//
    public ResultVO&lt;Map&lt;String,String&gt;&gt; wechatProfitSharingPay( WechatPayVo payVo) throws Exception{
        logger.info("微信分账支付请求预订单号===&gt;&gt;&gt;wechatProfitSharingPay");
        Message message = PhaseInterceptorChain.getCurrentMessage();
        HttpServletRequest httpServletRequest = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);
        String realIp =httpServletRequest.getRemoteAddr();
        ResultVO&lt;Map&lt;String,String&gt;&gt; result=new ResultVO&lt;Map&lt;String,String&gt;&gt;();
        Map&lt;String,String&gt; repData = new HashMap&lt;String,String&gt;();
        result.setData(repData);
        //1.参数封装
        Map param=new HashMap();
        //公众账号ID
        param.put("appid", wechatAppId);
        //商户号
        param.put("mch_id", wechatMerchantId);
        //随机字符串
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        param.put("body", imName);
        //交易订单号
        param.put("out_trade_no", outTradeNo.trim());
        //金额(分)
        param.put("total_fee",actualAmount.toString());
        param.put("spbill_create_ip",realIp);
        param.put("notify_url", wechatNotifyUrl);
        //交易类型
        param.put("trade_type", "JSAPI");
 param.put("sign_type", "HMAC-SHA256");//分账必须只支持HMAC-SHA256,不分账可以不设置这个参数默认就为md5
        param.put("profit_sharing","Y");
        //用户标示
        param.put("openid", payVo.getOpenid());
        try {
            //根据接口文档的案例要求,微信服务器接收参数方式是xml格式,所以将参数转换为xml
             //WXPayConstants.SignType.HMACSHA256这个参数不传默认为MD5,可查看源码了解详情
            String xmlParam = WXPayUtil.generateSignedXml(param, wechatApiKey, WXPayConstants.SignType.HMACSHA256);
            logger.info("请求的参数:"+xmlParam);
            xmlParam = new String(xmlParam.getBytes("UTF-8"),"ISO8859-1");
            //2.发送请求
            String xmlResult = HttpClientUtil.PostXml(WXPayConstants.UNIFIEDORDER_URL, xmlParam);
            System.out.println(xmlResult);
            Map&lt;String, String&gt; mapResult = WXPayUtil.xmlToMap(xmlResult);
            logger.info("微信返回结果:"+mapResult);
            //返回前端数据
            if (mapResult.get("return_code").equals("SUCCESS")){
                //返回给APP端的参数,APP端再调起支付接口
                String prepay_id= mapResult.get("prepay_id");
                //签名
                String sign = WXPayUtil.generateSignature(repData,wechatApiKey);
                repData.put("prepayId",prepay_id);
              
                
                result.setData(repData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
//        return new HashMap();
        return result;
    }

请求参数

<xml> ?<br />
<appid>wxa5784a9179cb21b2</appid> ?<br />
<attach>SADA V-196 é?????èé???±??°é? ????¨??é??????è?°????é??? USB???? 3.5mmé?é?è??? é?è?</attach>?<br />
?<body>SADA V-196 é?????èé???±??°é? ????¨??é??????è?°????é??? USB???? 3.5mmé?é?è??? é?è?</body> ?<br />
?<mch_id>16888888</mch_id>?<br />
?<nonce_str>P2iRlOdAaUd8lfmAL8B1OCWYi5ehlwpF</nonce_str> ?<br />
?<notify_url>https://test.com/pay/wechatPayResponse?appKey=e1320097be42c5f7ce86c30552594907</notify_url> ?<out_trade_no>SO7721042273466</out_trade_no>?<br />
?<product_id>V5902B</product_id>?<br />
?<spbill_create_ip>0:0:0:0:0:0:0:1</spbill_create_ip>?<br />
?<total_fee>562</total_fee> ?<trade_type>JSAPI</trade_type>?<br />
?<openid>oLPst42jhg232Wp7bm8mQE3Ugv4</openid>?<br />
?<sign>6A15CDE322C7CA92C79A083529255B</sign></xml>

以上控制台打印的参数看着有乱码,其实不是

是这句代码

xmlParam = new String(xmlParam.getBytes("UTF-8"),"ISO8859-1");

 的作用,因为中文需要处理过微信才能接收,不知其他朋友有没有尝试过中文不做编码处理就能成功调用的

返回结果

<xml><return_code>
<![CDATA[SUCCESS]]>
</return_code><return_msg><![CDATA]>
</return_msg><result_code><![CDATA[SUCCESS]]></result_code>
<mch_id><![CDATA[13332914]]></mch_id>
<appid><![CDATA[wxa2329cb2166]]></appid>
<nonce_str><![CDATA[ZmN238FocCNwiQ]]></nonce_str>
<sign><![CDATA[F38E20CACA4F2FA780E17936021D41BF4036AAB852800FD224E397A88FDEF8A7]]></sign>
<prepay_id><![CDATA[wx241104666660924a55510000]]>
</prepay_id><trade_type><![CDATA[JSAPI]]>
</trade_type></xml>
 

分账

 官方api地址:https://pay.weixin.qq.com/wiki/doc/api/allocation_sl.php?chapter=25_1&amp;index=1

单次分账地址https://api.mch.weixin.qq.com/secapi/pay/profitsharing

按照官方文档

进去按照流程申请得到

上微信单次分账代码,多次及其他可以仿照这个写法可以调通

/**
*@func :微信单次分账
*@data: 2019-11-11
*@auther :lijinquan
*/
 public ResultVO&lt;Map&lt;String,Object&gt;&gt; wechatProfitSharing(WechatPayVo payVo){

        ResultVO&lt;Map&lt;String,Object&gt;&gt; result=new ResultVO&lt;Map&lt;String,Object&gt;&gt;();
        Map&lt;String,Object&gt; m=new HashedMap();
        result.setData(m);
        //1.参数封装
        Map param=new HashMap();
        //公众账号ID
        param.put("appid", wechatAppId);
        //商户号
        param.put("mch_id", wechatMerchantId);
        //微信支付分配的子商户号,即分账的出资商户号。
        param.put("sub_mch_id", wechatMerchantId);
        //随机字符串
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        //签名类型,目前只支持HMAC-SHA256
        param.put("sign_type", "HMAC-SHA256");
        //微信支付订单号
        param.put("transaction_id", "4200001042202104228993583353");
        /**
         * 服务商系统内部的分账单号,在服务商系统内部唯一
         * (单次分账、多次分账、完结分账应使用不同的商户分账单号),
         * 同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@
         */
        param.put("out_order_no", "P001001001");
        /**
         * 分账接收方列表,不超过50个json对象,不能设置出资子商户作为分账接受方
          点击行前的+展开字段详情
         */

        List&lt;Map&gt; receivers=new ArrayList&lt;Map&gt;();
        for(int i=0 ;i&lt;1;i++){
            Map receiver=new HashedMap();

            /**
             * -分账接收方类型
             * MERCHANT_ID:商户号(mch_id或者sub_mch_id)
             PERSONAL_OPENID:个人openid(由父商户APPID转换得到)
             PERSONAL_SUB_OPENID: 个人sub_openid(由子商户APPID转换得到)
             */
            receiver.put("type","PERSONAL_OPENID");
            /**
             * 类型是MERCHANT_ID时,是商户号(mch_id或者sub_mch_id)
             类型是PERSONAL_OPENID时,是个人openid
             类型是PERSONAL_SUB_OPENID时,是个人sub_openid
             */
            receiver.put("account","oLPst4xXiA9m-MVGJBcacj1190ww");
            /**
             * -分账金额
             * 分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额
             */
            receiver.put("amount",1);
            /**
             * -分账描述
             *
             * 分账的原因描述,分账账单中需要体现
             */
            receiver.put("description","微信文档值得吐槽");

            /**
             * -分账个人接收方姓名
             * 可选项,在接收方类型为个人的时可选填,若有值,会检查与 name 是否实名匹配,不匹配会拒绝分账请求
             1、分账接收方类型是PERSONAL_OPENID时,是个人姓名(选传,传则校验)
             */
            receiver.put("name","这人很强");


            receivers.add(receiver);

        }
        param.put("receivers", JSON.toJSONString(receivers));

        try {

            String xmlParam = WXPayUtil.generateSignedXml(param, wechatApiKey, WXPayConstants.SignType.HMACSHA256);

            logger.info("请求的参数:"+xmlParam);
            xmlParam = new String(xmlParam.getBytes("UTF-8"),"ISO8859-1");
            //2.发送请求
//            String xmlResult = HttpClientUtil.PostXml(url, xmlParam);
//            String s = WxUtils.httpPostRequest(url, xmlParam);
//            System.out.println(xmlResult);
            CloseableHttpClient httpClient = null;
            CloseableHttpResponse httpResponse = null;
            KeyStore keyStore = getCertificate(wechatMerchantId);
            SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, wechatMerchantId.toCharArray()).build();
            SSLConnectionSocketFactory sslf = new SSLConnectionSocketFactory(sslContext);
            httpClient = HttpClients.custom().setSSLSocketFactory(sslf).build();
            HttpPost httpPost = new HttpPost(profitsharingUrl);

            StringEntity reqEntity = new StringEntity(xmlParam);
            // 设置类型
            reqEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(reqEntity);
//            String result = null;
            httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            String resultStr = EntityUtils.toString(httpEntity, "UTF-8");
            System.out.println("微信响应报文:"+resultStr);
            EntityUtils.consume(httpEntity);
//            m.put("xmlResult",xmlResult);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }


/**
     *
     * @description: 获取微信证书
     * @param mch_id
     * @auther: lijinquan
     * @date: 2019-11-11
     */
    public static KeyStore getCertificate(String mch_id){
        //try-with-resources 关流
        try{
            FileInputStream inputStream = new FileInputStream(new File("E:\\wxtest\\wxpaySecurKey\\apiclient_cert.p12"));
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(inputStream, mch_id.toCharArray());
            return keyStore;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

问题的记录

问题一:分账接收方列表格式错误,一般情况是分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额

receiver.put("amount",1);//这个金额不能写成“1”,要直接写int类型

如果写“1”会返回以下结果

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[分账接收方列表格式错误]]></return_msg>
</xml>

服务商和分账方无受理关系:返回信息如下

<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<result_code><![CDATA[FAIL]]></result_code>
<err_code><![CDATA[INVALID_REQUEST]]></err_code>
<err_code_des><![CDATA[服务商和分账方无受理关系]]></err_code_des>
<mch_id><![CDATA[1607772914]]></mch_id>
<sub_mch_id><![CDATA[167772914]]></sub_mch_id>
<appid><![CDATA[wxa5784a7779cb2aa2]]></appid>
<nonce_str><![CDATA[05340b4c3533dd6]]></nonce_str>
<sign><![CDATA[163A5EEAEF4340C05AA09323E4FB845ADD74D684A3F80385F8608AB0271760]]></sign>
</xml>

处理办法:需要添加添加分账接收方https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver

注意签名与必填参数

java代码示例:

参数WechatPayVo 可以按照自己的需要添加属性

 /**
     * @function 添加分账账号
     * @auther   lijinuquan
     * @param splitSharings
     * @param wxPayVo
     */
    @Override
    public ResultVO&lt;Map&lt;String, String&gt;&gt; profitSharingAddReceiver(WechatPayVo wxPayVo) throws Exception {
        ResultVO&lt;Map&lt;String, String&gt;&gt; result = new ResultVO&lt;Map&lt;String, String&gt;&gt;();
        Map&lt;String, Object&gt; m = new HashedMap();
        //1.参数封装
        Map param = new HashMap();
        //商户号
        param.put("mch_id", wechatMerchantId);
        //微信支付分配的子商户号,即分账的出资商户号。
        param.put("appid", wechatAppId);
        //随机字符串
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        //签名类型,目前只支持HMAC-SHA256
        param.put("sign_type", "HMAC-SHA256");
        Map receiver = new HashedMap();
        //分账接收方类型:MERCHANT_ID:商户号(mch_id或者sub_mch_id)PERSONAL_OPENID:个人openid
        receiver.put("type", "Y".equals(wxPayVo.getIsMechat()) ? "MERCHANT_ID" : "PERSONAL_OPENID");
        receiver.put("account", wxPayVo.getOpenid());
        //否
//        receiver.put("name", "名字");
        receiver.put("relation_type", WechatConstants.USER);
        //自定义分账关系
//        receiver.put("custom_relation", WechatConstants.USER);
        param.put("receiver", JSON.toJSONString(receiver));
        try {
            String xmlParam = WXPayUtil.generateSignedXml(param, wechatApiKey, WXPayConstants.SignType.HMACSHA256);
            logger.info("请求的参数:" + xmlParam);
            xmlParam = new String(xmlParam.getBytes("UTF-8"), "ISO8859-1");
            //2.发送请求
            String xmlResult = HttpClientUtil.PostXml(profitSharingAddReceiverUrl, xmlParam);
            Map&lt;String, String&gt; mapResult = WXPayUtil.xmlToMap(xmlResult);
            logger.info("返回报文:" + xmlResult);
            //返回前端数据
            if (mapResult.get("return_code").equals("SUCCESS")) {
                //返回前端的参数,APP端再调起支付接口
                String mch_id = mapResult.get("mch_id");
                String appid = mapResult.get("appid");
                String rcer = mapResult.get("receiver");
                String nonce_str = mapResult.get("nonce_str");
                String sign = mapResult.get("sign");
                JSONObject rs = JSONObject.parseObject(rcer);
                if (rs != null) {
                    String type = rs.getString("type");
                    String account = rs.getString("account");
                    String relation_type = rs.getString("relation_type");
                }
                result.setData(mapResult);
            } else {
                result.setErrorMsg(mapResult.get("err_code_des"));
                result.setAck(EnumAck.Failure);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

其他接口地址https://pay.weixin.qq.com/wiki/doc/api/external/declarecustom.php?chapter=18_2

代码可参考以上

最后,感谢https://support.pay.weixin.qq.com/online-service?from=wechatpay

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐