分享一些微信支付/分账后端代码及问题收录

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

导入WXPayUtil 


com.github.wxpay
wxpay-sdk
0.0.3

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

分享一些微信支付/分账后端代码及问题收录_第1张图片

  /**
     *func :微信统一支付接口
     *
      *date:2019-11-11
      *作者:lijinquan
      **//
    public ResultVO<Map<String,String>> wechatProfitSharingPay( WechatPayVo payVo) throws Exception{
        logger.info("微信分账支付请求预订单号===>>>wechatProfitSharingPay");
        Message message = PhaseInterceptorChain.getCurrentMessage();
        HttpServletRequest httpServletRequest = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);
        String realIp =httpServletRequest.getRemoteAddr();
        ResultVO<Map<String,String>> result=new ResultVO<Map<String,String>>();
        Map<String,String> repData = new HashMap<String,String>();
        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<String, String> 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;
    }

请求参数

?

wxa5784a9179cb21b2 ?

SADA V-196 é?????èé???±??°é? ????¨??é??????è?°????é??? USB???? 3.5mmé?é?è??? é?è??

?SADA V-196 é?????èé???±??°é? ????¨??é??????è?°????é??? USB???? 3.5mmé?é?è??? é?è? ?

?16888888?

?P2iRlOdAaUd8lfmAL8B1OCWYi5ehlwpF ?

?https://test.com/pay/wechatPayResponse?appKey=e1320097be42c5f7ce86c30552594907 ?SO7721042273466?

?V5902B?

?0:0:0:0:0:0:0:1?

?562 ?JSAPI?

?oLPst42jhg232Wp7bm8mQE3Ugv4?

?6A15CDE322C7CA92C79A083529255B

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

是这句代码

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

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

返回结果












 

分账

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

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

按照官方文档

分享一些微信支付/分账后端代码及问题收录_第2张图片

进去按照流程申请得到

分享一些微信支付/分账后端代码及问题收录_第3张图片

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

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

        ResultVO<Map<String,Object>> result=new ResultVO<Map<String,Object>>();
        Map<String,Object> 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<Map> receivers=new ArrayList<Map>();
        for(int i=0 ;i<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”会返回以下结果




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











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

分享一些微信支付/分账后端代码及问题收录_第4张图片

注意签名与必填参数

java代码示例:

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

 /**
     * @function 添加分账账号
     * @auther   lijinuquan
     * @param splitSharings
     * @param wxPayVo
     */
    @Override
    public ResultVO<Map<String, String>> profitSharingAddReceiver(WechatPayVo wxPayVo) throws Exception {
        ResultVO<Map<String, String>> result = new ResultVO<Map<String, String>>();
        Map<String, Object> 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<String, String> 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

分享一些微信支付/分账后端代码及问题收录_第5张图片

代码可参考以上

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

你可能感兴趣的:(java,小程序,小程序,java)