收付通-申请二级商户资金账单下载示例

步骤一:下载账单文件,得到账单文件密文ciphertext;
步骤二:使用商户证书私钥解密从接口获取的加密密钥(变量名:encrypt_key)得到密钥明文key;
步骤三:利用步骤一、二中得到的账单密文ciphertext,密钥key和接口返回的随机字符串nonce解密账单,得到账单明文。

步骤四:把明文数据以excel文件返回

*引入基础依赖

<!-- 微信支付SDK 商户平台模式-->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-pay</artifactId>
            <version>4.5.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-java</artifactId>
            <version>0.2.12</version>
        </dependency>
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-apache-httpclient</artifactId>
            <version>0.4.9</version>
        </dependency>
        <!-- 微信支付SDK  END-->

* 下载方法代码

    /**
     * 申请二级商户资金账单
     */
    @PostMapping("getAllSubMchFundFlowBill")
    public void getAllSubMchFundFlowBill(@RequestBody TradeBillVo tradeBillVo, HttpServletResponse response) {
        PmsApplicationServePay config = getConfig();
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        try {
            FundBillRequest request = FundBillRequest.builder()
                    .billDate(tradeBillVo.getBillDate())
                    .accountType(tradeBillVo.getAccountType())
                    .algorithm(tradeBillVo.getAlgorithm()).build();
            FundBillResult result = ecommerceService.applyFundBill(FundBillTypeEnum.SUB_FUND_FLOW_BILL, request);

            if (result.getDownloadBillCount() > 0) {
                JSONArray billList = new JSONArray(result.getDownloadBillList());
                for (Object object : billList) {
                    JSONObject object1 = new JSONObject(object);
                    byte[] ciphertext = downloadUrl(object1.getStr("downloadUrl"));
                    String encryptKey = WxPayUtils.rsaDecryptOAEP(object1.getStr("encryptKey"), config.getPrivateKeyPath());

                    String notifyData = WxPayUtils.decryptToString("",
                            object1.getStr("nonce").getBytes(StandardCharsets.UTF_8),
                            ciphertext,
                            encryptKey.getBytes(StandardCharsets.UTF_8));
                    log.info(notifyData);

                    // TODO 导出为.csv文件
                    List<BillFlowInfoVo> infoVos = WxPayUtils.stringToCsvFile(notifyData);
                    String fileName = new Date().getTime() + ".xlsx";
                    response.setContentType(CONTENT_TYPE);
                    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                    response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
                    EasyExcel.write(response.getOutputStream(), BillFlowInfoVo.class).sheet().doWrite(infoVos);
                }
            }

        }catch (ServiceException e) {
            log.error(e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

*构建配置信息

    private HttpClient httpClient;


    public static final String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

    /**
     * 构建配置
     * @return
     */
    public PmsApplicationServePay getConfig() {
        PmsApplicationServePay servePay = iPmsApplicationServePayService.getServePayEntity();
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(servePay.getMchId())
                .privateKeyFromPath(servePay.getPrivateKeyPath())
                .merchantSerialNumber(servePay.getCertSerialNo())
                .apiV3Key(servePay.getApiV3Key())
                .build();

        httpClient = new DefaultHttpClientBuilder().config(config).build();
        return servePay;
    }

    /**
     * 构建配置信息
     */
    public WxPayService wxService() {
        WxPayConfig payConfig = new WxPayConfig();
        PmsApplicationServePay servePay = iPmsApplicationServePayService.getServePayEntity();
        payConfig.setAppId(StringUtils.trimToNull(servePay.getAppId()));
        payConfig.setMchId(StringUtils.trimToNull(servePay.getMchId()));
        payConfig.setApiV3Key(StringUtils.trimToNull(servePay.getApiV3Key()));
        payConfig.setCertSerialNo(StringUtils.trimToNull(servePay.getCertSerialNo()));
        payConfig.setPrivateKeyPath(servePay.getPrivateKeyPath());
        payConfig.setPrivateCertPath(servePay.getPrivateCertPath());
        payConfig.setNotifyUrl(StringUtils.trimToNull(servePay.getNotifyUrl()));
        payConfig.setTradeType("JSAPI");
        payConfig.setSignType("MD5");
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }

步骤一:下载账单文件,得到账单文件密文ciphertext;

    /**
     * 下载账单转成 byte[]
     * @param downloadUrl
     * @return
     * @throws Exception
     */
    private byte[] downloadUrl(String downloadUrl) throws Exception {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 下载账单
        InputStream inputStream = ecommerceService.downloadBill(downloadUrl);
        byte[] bytes = IOUtils.toByteArray(inputStream);
        return bytes;
    }

获取账单文件密文ciphertext

步骤二:使用商户证书私钥解密从接口获取的加密密钥(变量名:encrypt_key)得到密钥明文key;

/**
     * 敏感信息解密
     * @param message: 加密信息
     * @param privateKeyPath:私钥地址
     * @return
     */
    public static String rsaDecryptOAEP(String message, String privateKeyPath) throws BadPaddingException, IOException {
        try {
            // 加载私钥
            PrivateKey privateKey = getPrivateKey(privateKeyPath);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            byte[] data = Base64.getDecoder().decode(message);
            return new String(cipher.doFinal(data), "utf-8");
        } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException("无效的私钥", e);
        } catch (BadPaddingException | IllegalBlockSizeException e) {
            throw new BadPaddingException("解密失败");
        }
    }


/**
     * 获取私钥
     * @param privateKeyPath 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String privateKeyPath) throws IOException {
        try (FileInputStream inputStream = new FileInputStream(privateKeyPath)) {
            String keyString = IOUtil.toString(inputStream);
            keyString =
                    keyString
                            .replace("-----BEGIN PRIVATE KEY-----", "")
                            .replace("-----END PRIVATE KEY-----", "")
                            .replaceAll("\\s+", "");
            return KeyFactory.getInstance("RSA")
                    .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString)));
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException(e);
        } catch (InvalidKeySpecException e) {
            throw new IllegalArgumentException(e);
        }
    }

* 获取秘钥明文

步骤三:利用步骤一、二中得到的账单密文ciphertext,密钥key和接口返回的随机字符串nonce解密账单,得到账单明文。

解密腾讯文件返回的数据

/**
     * 数据解密
     * @param associatedData
     * @param nonce
     * @param ciphertext
     * @param aesKey
     * @return
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public static String decryptToString(String associatedData, byte[] nonce, byte[] ciphertext, byte[] aesKey)
            throws GeneralSecurityException, IOException {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
            cipher.init(Cipher.DECRYPT_MODE, key, spec);
            cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));

            byte[] bytes;
            try {
                bytes = cipher.doFinal(ciphertext);
            }catch (GeneralSecurityException e) {
                e.printStackTrace();
                throw new IllegalArgumentException(e);
            }

            return new String(bytes, StandardCharsets.UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(e);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new IllegalArgumentException(e);
        }
    }

步骤四:把明文数据以excel文件返回

数据转成实体

/**
     * string 转实体
     */
    public static List<BillFlowInfoVo> stringToCsvFile(String notifyData) {
        List<BillFlowInfoVo> result = new ArrayList<>();
        String[] list = notifyData.split("\r\n");
        IntStream.range(0, list.length).forEach(index -> {
            if (index > 0) {
                String[] valList = list[index].split(",");
                BillFlowInfoVo infoVo = new BillFlowInfoVo();
                if (valList.length == 1) {
                    infoVo.setTime(valList[0]);
                }else {
                    infoVo.setTime(valList[0]);
                    infoVo.setOrderId(valList[1]);
                    infoVo.setOrderSn(valList[2]);
                    infoVo.setBusinessName(valList[3]);
                    infoVo.setBusinessType(valList[4]);
                    infoVo.setSzType(valList[5]);
                    infoVo.setSzMoney(valList[6]);
                    infoVo.setAccount(valList[7]);
                    infoVo.setEditPerson(valList[8]);
                    infoVo.setRemark(valList[9]);
                    infoVo.setBusinessSn(valList[10]);
                    infoVo.setSubMchId(valList[11]);
                    infoVo.setAccountType(valList[12]);
                }
                result.add(infoVo);
            }
        });

        return result;
    }

实体类

@Data
public class BillFlowInfoVo implements Serializable {

    /**
     * 记账时间
     */
    @ExcelProperty("记账时间")
    private String time;

    /**
     * 微信支付业务单号
     */
    @ExcelProperty("微信支付业务单号")
    private String orderId;

    /**
     * 资金流水单号
     */
    @ExcelProperty("资金流水单号")
    private String orderSn;

    /**
     * 业务名称
     */
    @ExcelProperty("业务名称")
    private String businessName;

    /**
     * 业务类型
     */
    @ExcelProperty("业务类型")
    private String businessType;

    /**
     * 收支类型
     */
    @ExcelProperty("收支类型")
    private String szType;

    /**
     * 收支金额
     */
    @ExcelProperty("收支金额")
    private String szMoney;

    /**
     * 账户结余
     */
    @ExcelProperty("账户结余")
    private String account;

    /**
     * 资金变更提交申请人
     */
    @ExcelProperty("资金变更提交申请人")
    private String editPerson;

    /**
     * 备注
     */
    @ExcelProperty("备注")
    private String remark;

    /**
     * 业务凭证号
     */
    @ExcelProperty("业务凭证号")
    private String businessSn;

    /**
     * 电商二级商户号
     */
    @ExcelProperty("电商二级商户号")
    private String subMchId;

    /**
     * 账户类型
     */
    @ExcelProperty("账户类型")
    private String accountType;
}

打开excel文件

package com.equipl.oms.api.wxpay.facilitator;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.equipl.common.consts.SysConst;
import com.equipl.common.consts.WeChatServeConst;
import com.equipl.common.utils.WechatSignUtil;
import com.equipl.common.vo.ResultMsg;
import com.equipl.common.vo.pay.*;
import com.equipl.oms.api.feign.IPmsApplicationServePayService;
import com.equipl.oms.api.feign.ISysEnterpriseApplyTwoPayService;
import com.equipl.oms.api.service.*;
import com.equipl.oms.api.utils.WxPayUtils;
import com.equipl.oms.entity.*;
import com.equipl.pms.entity.PmsApplicationServePay;
import com.github.binarywang.wxpay.bean.applyment.ApplymentStateQueryResult;
import com.github.binarywang.wxpay.bean.applyment.WxPayApplyment4SubCreateRequest;
import com.github.binarywang.wxpay.bean.applyment.WxPayApplymentCreateResult;
import com.github.binarywang.wxpay.bean.ecommerce.*;
import com.github.binarywang.wxpay.bean.ecommerce.enums.FundBillTypeEnum;
import com.github.binarywang.wxpay.bean.ecommerce.enums.SpAccountTypeEnum;
import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.Applyment4SubService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.Applyment4SubServiceImpl;
import com.github.binarywang.wxpay.service.impl.EcommerceServiceImpl;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.qcloud.cos.utils.IOUtils;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.http.*;
import com.wechat.pay.java.core.http.ResponseBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 微信商户服务商支付模式
 *
 * @author MrPing
 * @since 2024/4/23
 */
@Slf4j
@RestController
@RequestMapping("wxPay/service")
public class WeChatServiceController {

    @Autowired
    private IPmsApplicationServePayService iPmsApplicationServePayService;

    @Autowired
    private ISysEnterpriseApplyTwoPayService iSysEnterpriseApplyTwoPayService;

    @Autowired
    private OmsProfitShareLogService omsProfitShareLogService;

    @Autowired
    private OmsProfitShareReturnService omsProfitShareReturnService;

    @Autowired
    private OmsPaymentInfoService omsPaymentInfoService;

    @Autowired
    private OmsServeRefundsLogService omsServeRefundsLogService;

    @Autowired
    private OmsWithdrawMoneyLogService omsWithdrawMoneyLogService;

    private HttpClient httpClient;


    public static final String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

    /**
     * 构建配置
     * @return
     */
    public PmsApplicationServePay getConfig() {
        PmsApplicationServePay servePay = iPmsApplicationServePayService.getServePayEntity();
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(servePay.getMchId())
                .privateKeyFromPath(servePay.getPrivateKeyPath())
                .merchantSerialNumber(servePay.getCertSerialNo())
                .apiV3Key(servePay.getApiV3Key())
                .build();

        httpClient = new DefaultHttpClientBuilder().config(config).build();
        return servePay;
    }

    /**
     * 构建配置信息
     */
    public WxPayService wxService() {
        WxPayConfig payConfig = new WxPayConfig();
        PmsApplicationServePay servePay = iPmsApplicationServePayService.getServePayEntity();
        payConfig.setAppId(StringUtils.trimToNull(servePay.getAppId()));
        payConfig.setMchId(StringUtils.trimToNull(servePay.getMchId()));
        payConfig.setApiV3Key(StringUtils.trimToNull(servePay.getApiV3Key()));
        payConfig.setCertSerialNo(StringUtils.trimToNull(servePay.getCertSerialNo()));
        payConfig.setPrivateKeyPath(servePay.getPrivateKeyPath());
        payConfig.setPrivateCertPath(servePay.getPrivateCertPath());
        payConfig.setNotifyUrl(StringUtils.trimToNull(servePay.getNotifyUrl()));
        payConfig.setTradeType("JSAPI");
        payConfig.setSignType("MD5");
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }

    /**
     * 提交申请单
     */
    @PostMapping("/createApply")
    public ResultMsg createApply(@RequestBody WxPayApplyment4SubCreateRequest request) throws WxPayException {
        // 获取商户配置
        WxPayService wxPayService = wxService();
        // 调用微信API
        Applyment4SubService applyment4SubService = new Applyment4SubServiceImpl(wxPayService);
        WxPayApplymentCreateResult apply = applyment4SubService.createApply(request);
        String applyMentId = apply.getApplymentId(); // 返回申请单ID
        return ResultMsg.success(applyMentId);
    }


    /**
     * 通过申请单号查询申请状态
     */
    @GetMapping("/queryApply")
    public ResultMsg queryApply(@RequestParam(required = true) String applymentId) throws WxPayException {
        // 获取商户配置
        WxPayService wxPayService = wxService();
        // 调用API 查询申请状态
        Applyment4SubService applyment4SubService=new Applyment4SubServiceImpl(wxPayService);
        ApplymentStateQueryResult result = applyment4SubService.queryApplyStatusByApplymentId(applymentId);
        return ResultMsg.success(result);
    }

    /**
     * 发起支付
     * type: 1->JSAPI, 2->小程序,3->H5,4->Native,5->APP
     */
    @PostMapping("/create")
    public ResultMsg createOrder(@RequestBody PartnerTransactionsRequest orderRequest, @RequestParam("type") Integer type) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException, WxPayException {
        TradeTypeEnum typeEnum;
        boolean isAtOnce = false;
        if (type == 1 || type == 2 || type == 5) {
             typeEnum = type == 5 ? TradeTypeEnum.APP : TradeTypeEnum.JSAPI;
        } else {
            isAtOnce = true;
            typeEnum = type == 3 ? TradeTypeEnum.MWEB : TradeTypeEnum.NATIVE;

            if (type == 3) {
                orderRequest.getSceneInfo().setPayerClientIp("127.0.0.1");
            }
        }

        // 获取商户配置
        PmsApplicationServePay wxPayProperties = iPmsApplicationServePayService.getServePayEntity();
        WxPayService wxPayService = wxService();
        //发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 2. 根据订单系统传过来的订单信息组装支付参数,创建支付订单
        //服务商应用ID
        orderRequest.setSpAppid(wxPayProperties.getAppId());
        //服务商户号
        orderRequest.setSpMchid(wxPayProperties.getMchId());
        //设置交易结束时间为2小时后
        long twoHoursInMillis = 2 * 60 * 60 * 1000; // 2小时对应的毫秒数
        orderRequest.setTimeExpire(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date(new Date().getTime() + twoHoursInMillis)));
        //回调地址
        orderRequest.setNotifyUrl(wxPayProperties.getNotifyUrl());
        try {
            //发起下单请求
            TransactionsResult partner = ecommerceService.partner(typeEnum, orderRequest);
            // 返回支付跳转或二维码链接
            if (isAtOnce){
                return ResultMsg.success(partner);
            }
            //生成签名
            WxUnifiedOrderVo tokenJSAPI = WechatSignUtil.getTokenJSAPI(wxPayProperties.getAppId(), partner.getPrepayId(), wxPayProperties.getPrivateKeyPath());
            // 订单号
            tokenJSAPI.setOrderId(Long.valueOf(orderRequest.getOutTradeNo()));

            // TODO 添加支付记录
            OmsPaymentInfo info = new OmsPaymentInfo();
            info.setOrderId(orderRequest.getOutTradeNo());
            info.setTotalAmount(BigDecimal.valueOf(orderRequest.getAmount().getTotal()).divide(new BigDecimal(100)));
            info.setSubject("微信收付通");
            info.setPaymentStatus("0");
            info.setCreateTime(LocalDateTime.now());
            omsPaymentInfoService.save(info);

            return ResultMsg.success(tokenJSAPI);
        }catch (ServiceException e) {
            log.error(e.getErrorMessage());
            return ResultMsg.error(e.getErrorMessage());
        }catch (Exception e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 支付回调通知处理
     * @param resultData
     * @throws WxPayException
     */
    @PostMapping("/notify")
    public void parseOrderNotifyResult(@RequestBody HashMap<String, Object> resultData) throws WxPayException {
        // 获取商户配置
        WxPayService wxPayService = wxService();
        log.info("回调:{}",resultData);
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        PartnerTransactionsNotifyResult notifyResult = ecommerceService.parsePartnerNotifyResult(String.valueOf(resultData), null);
        //此处解析到了回调信息
        log.info("回调:{}",notifyResult.getResult());
        //业务逻辑
    }

    /**
     * 主动查询支付信息
     */
    @GetMapping("/order/select")
    public ResultMsg wxSelectOrderStatus(@RequestParam("orderId") String orderId, @RequestParam("sellerEnterpriseId") String sellerEnterpriseId) throws WxPayException {
        // 获取特约商户id
        ResultMsg query = iSysEnterpriseApplyTwoPayService.query(sellerEnterpriseId);
        if (query.getData() == null || query.getCode() != 0) {
            return ResultMsg.error("订单查询异常,无法获取卖方支付商户号!");
        }
        JSONObject jsonObject = new JSONObject(query.getData());
        // 获取商户配置
        PmsApplicationServePay wxPayProperties = iPmsApplicationServePayService.getServePayEntity();
        WxPayService wxPayService = wxService();
        //构建ecommerceService
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        //构建PartnerTransactionsQueryRequest对象
        PartnerTransactionsQueryRequest queryRequest = new PartnerTransactionsQueryRequest();
        queryRequest.setOutTradeNo(orderId);
        queryRequest.setSpMchid(wxPayProperties.getMchId());
        queryRequest.setSubMchid(jsonObject.getStr("subMchId"));
        PartnerTransactionsResult partnerTransactionsResult=new PartnerTransactionsResult();
        try {
            //普通查询订单API
            partnerTransactionsResult = ecommerceService.queryPartnerTransactions(queryRequest);
            return ResultMsg.success(partnerTransactionsResult);
        } catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }


    /**
     * 请求分账
     */
    @PostMapping("profitSharing")
    public ResultMsg profitSharing(@RequestBody ProFitSharingVo proFitSharingVo) throws WxPayException {
        // 发起分账
        try {
            // 获取分账方信息
            ResultMsg query = iSysEnterpriseApplyTwoPayService.query(proFitSharingVo.getToEnterpriseId());
            if (query.getData() == null || query.getCode() != 0) {
                return ResultMsg.error("请求分账异常,无法获取分账方商户号!");
            }
            JSONObject jsonObject = new JSONObject(query.getData());

            // 获取商户配置
            PmsApplicationServePay wxPayProperties = iPmsApplicationServePayService.getServePayEntity();
            WxPayService wxPayService = wxService();
            //发起V3 服务商发起支付
            EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
            // 根据订单系统传过来的订单信息组装支付参数,创建支付订单
            ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest();
            // 服务商应用ID
            profitSharingRequest.setAppid(wxPayProperties.getAppId());
            // 二级商户号
            profitSharingRequest.setSubMchid(jsonObject.getStr("subMchId"));
            // 微信订单号
            PartnerTransactionsQueryRequest queryRequest = new PartnerTransactionsQueryRequest();
            queryRequest.setOutTradeNo(proFitSharingVo.getOrderId());
            queryRequest.setSpMchid(wxPayProperties.getMchId());
            queryRequest.setSubMchid(jsonObject.getStr("subMchId"));
            //普通查询订单API
            PartnerTransactionsResult partnerTransactionsResult = ecommerceService.queryPartnerTransactions(queryRequest);
            profitSharingRequest.setTransactionId(partnerTransactionsResult.getTransactionId());

            // 生成分账单号
            profitSharingRequest.setOutOrderNo(String.valueOf(IdWorker.getId()));
            // 是否分账完成
            profitSharingRequest.setFinish(proFitSharingVo.getFinish());
            // 分账接收方
            ProfitSharingRequest.Receiver receiver = new ProfitSharingRequest.Receiver();
            // 企业申请时的信息
            JSONObject auditData = jsonObject.getJSONObject("auditData");
            // 分账接收方类型:商户
            receiver.setType("MERCHANT_ID");
            // 分账接收方账号:是商户号(mch_id或者sub_mch_id)
            if (proFitSharingVo.getIsPlatform()){
                // 分账到服务商
                receiver.setReceiverAccount(wxPayProperties.getMchId());
            }else {
                // 分账到二级商户
                ResultMsg twoResult = iSysEnterpriseApplyTwoPayService.query(proFitSharingVo.getFormEnterpriseId());
                JSONObject jsonObject1 = new JSONObject(twoResult.getData());
                receiver.setReceiverAccount(jsonObject1.getStr("subMchId"));
            }
            // 分账金额
            receiver.setAmount(proFitSharingVo.getAmount());
            // 分账描述
            receiver.setDescription(proFitSharingVo.getDescription());

            // 添加分账方信息
            List<ProfitSharingRequest.Receiver> list = new ArrayList<>();
            list.add(receiver);
            profitSharingRequest.setReceivers(list);

            //普通查询订单API
            ProfitSharingResult sharingResult = ecommerceService.profitSharing(profitSharingRequest);

            // TODO 添加到分账记录表
            OmsProfitShareLog shareLog = new OmsProfitShareLog();
            shareLog.setOrderId(proFitSharingVo.getOrderId());
            shareLog.setTransactionId(partnerTransactionsResult.getTransactionId());
            shareLog.setOutOrderNo(profitSharingRequest.getOutOrderNo());
            shareLog.setWxOutOrderNo(sharingResult.getOrderId());
            shareLog.setToEnterpriseId(proFitSharingVo.getToEnterpriseId());
            shareLog.setToSubMchId(profitSharingRequest.getSubMchid());
            shareLog.setIsPlatform(proFitSharingVo.getIsPlatform() ? 1:0);
            shareLog.setFormEnterpriseId(proFitSharingVo.getIsPlatform() ? SysConst.YQ_ENTERPRISE_ID: proFitSharingVo.getFormEnterpriseId());
            shareLog.setFormMchId(receiver.getReceiverAccount());
            shareLog.setAmount(proFitSharingVo.getAmount());
            shareLog.setDescription(receiver.getDescription());
            shareLog.setCreateTime(LocalDateTime.now());
            shareLog.setFinish(proFitSharingVo.getFinish() ? 1:0);
            omsProfitShareLogService.save(shareLog);

            return ResultMsg.success(sharingResult);

        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }


    /**
     * 分账查询
     */
    @GetMapping("profitShare/query")
    public ResultMsg queryShareProfit(@RequestParam("enterpriseId") String enterpriseId, @RequestParam("orderId") String orderId) throws WxPayException {
        // 分账出资的电商平台二级商户
        ResultMsg twoResult = iSysEnterpriseApplyTwoPayService.query(enterpriseId);
        JSONObject jsonObject1 = new JSONObject(twoResult.getData());
        String subMchId = jsonObject1.getStr("subMchId");

        LambdaQueryWrapper<OmsProfitShareLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsProfitShareLog::getToEnterpriseId, enterpriseId)
                .eq(OmsProfitShareLog::getOrderId, orderId);
        List<OmsProfitShareLog> list = omsProfitShareLogService.list(wrapper);
        List<ProfitSharingResult> result = new ArrayList<>();
        // 获取配置
        WxPayService wxPayService = wxService();
        //发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        for (OmsProfitShareLog shareLog : list) {
            ProfitSharingQueryRequest queryRequest = new ProfitSharingQueryRequest();
            queryRequest.setSubMchid(subMchId);
            queryRequest.setTransactionId(shareLog.getTransactionId());
            queryRequest.setOutOrderNo(shareLog.getOutOrderNo());
            try {
                // 查询分账
                ProfitSharingResult sharingResult = ecommerceService.queryProfitSharing(queryRequest);
                result.add(sharingResult);
            }catch (WxPayException e) {
                log.error(e.getMessage());
                return ResultMsg.error(e.getMessage());
            }
        }
        return ResultMsg.success(result);
    }

    /**
     * 请求分账回退
     */
    @PostMapping("returnorders")
    public ResultMsg returnorders(@RequestBody ReturnOrdersRequest request) {
        // 获取配置
        WxPayService wxPayService = wxService();
        //发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        LambdaQueryWrapper<OmsProfitShareLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(request.getOutOrderNo()), OmsProfitShareLog::getOutOrderNo, request.getOutOrderNo());
        OmsProfitShareLog logServiceOne = omsProfitShareLogService.getOne(wrapper, false);

        try {
            // 请求分账回退
            request.setOutReturnNo(String.valueOf(IdWorker.getId()));
            ReturnOrdersResult returnOrders = ecommerceService.returnOrders(request);

            // TODO 插入分账回退记录
            OmsProfitShareReturn shareReturn = new OmsProfitShareReturn();
            shareReturn.setOrderId(logServiceOne.getOrderId());
            shareReturn.setSubMchId(request.getSubMchid());
            shareReturn.setOutOrderNo(request.getOutOrderNo());
            shareReturn.setWxOutOrderNo(logServiceOne.getWxOutOrderNo());
            shareReturn.setOutReturnNo(returnOrders.getOutReturnNo());
            shareReturn.setWxOutReturnNo(returnOrders.getReturnNo());
            shareReturn.setReturnMchId(returnOrders.getReturnMchid());
            shareReturn.setAmount(returnOrders.getAmount());
            shareReturn.setDescription(request.getDescription());
            shareReturn.setStatus(returnOrders.getResult());
            if (StringUtils.isNotBlank(returnOrders.getFailReason())) {
                shareReturn.setFailReason(returnOrders.getFailReason());
            }
            if ("SUCCESS".equals(returnOrders.getResult())){
                shareReturn.setFinishTime(LocalDateTime.now());
            }
            shareReturn.setCreateTime(LocalDateTime.now());
            omsProfitShareReturnService.save(shareReturn);


            return ResultMsg.success(returnOrders);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 查询分账回退结果
     */
    @PostMapping("query/returnorders")
    public ResultMsg queryReturnorders(@RequestBody ReturnOrdersQueryRequest queryRequest) {

        // 获取配置
        WxPayService wxPayService = wxService();
        //发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        // 获取分账回退申请记录
        LambdaQueryWrapper<OmsProfitShareReturn> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsProfitShareReturn::getOutReturnNo, queryRequest.getOutReturnNo());
        OmsProfitShareReturn shareReturn = omsProfitShareReturnService.getOne(wrapper, false);

        try {

            ReturnOrdersResult ordersResult = ecommerceService.queryReturnOrders(queryRequest);
            // TODO 更新分账退款状态已变化
            if(!ordersResult.getResult().equals(shareReturn.getStatus())) {
                ordersResult.setResult(ordersResult.getResult());
                ordersResult.setFailReason(ordersResult.getFailReason());
                if (StringUtils.isNotBlank(ordersResult.getFailReason())) {
                    shareReturn.setFailReason(ordersResult.getFailReason());
                }
                if ("SUCCESS".equals(ordersResult.getResult())){
                    shareReturn.setFinishTime(LocalDateTime.now());
                }
                omsProfitShareReturnService.updateById(shareReturn);
            }

            return ResultMsg.success(ordersResult);

        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }

    }

    /**
     * 完结分账
     */
    @PostMapping("finishOrder")
    public ResultMsg finishOrder(@RequestBody FinishOrderRequest request) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        // 调取完结
        try {
            ProfitSharingResult result = ecommerceService.finishOrder(request);
            return ResultMsg.success(result);

        } catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 查询订单剩余待分金额
     * transactionId: 查询订单接口获取
     */
    @GetMapping("amounts")
    public ResultMsg amounts(@RequestParam("transactionId") String transactionId) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 调取查询
        try {
            ProfitSharingOrdersUnSplitAmountRequest request = new ProfitSharingOrdersUnSplitAmountRequest();
            request.setTransactionId(transactionId);
            ProfitSharingOrdersUnSplitAmountResult result = ecommerceService.queryProfitSharingOrdersUnsplitAmount(request);

            return ResultMsg.success(result);
        } catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 申请退款
     */
    @PostMapping("refunds")
    public ResultMsg refunds(@RequestBody RefundsMoneyVo refundsMoneyVo) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        // 获取分账方信息
        ResultMsg query = iSysEnterpriseApplyTwoPayService.query(refundsMoneyVo.getEnterpriseId());
        if (query.getData() == null || query.getCode() != 0) {
            return ResultMsg.error("申请退款异常,无法获取分账方商户号!");
        }
        JSONObject jsonObject = new JSONObject(query.getData());

        // 获取商户配置
        PmsApplicationServePay wxPayProperties = iPmsApplicationServePayService.getServePayEntity();

        // 调取查询
        try {
            RefundsRequest request = new RefundsRequest();
            request.setSubMchid(jsonObject.getStr("subMchId"));
            request.setSpAppid(wxPayProperties.getAppId());
            request.setOutTradeNo(refundsMoneyVo.getOrderId());
            request.setOutRefundNo(String.valueOf(IdWorker.getId()));
            request.setReason(refundsMoneyVo.getReason());
            request.setNotifyUrl(wxPayProperties.getNotifyUrl());
            RefundsRequest.Amount amount = RefundsRequest.Amount.builder().total(refundsMoneyVo.getTotal()).refund(refundsMoneyVo.getRefund()).currency(refundsMoneyVo.getCurrency()).build();
            request.setAmount(amount);
            // 调用退款
            RefundsResult result = ecommerceService.refunds(request);

            // TODO 添加退款申请记录
            OmsServeRefundsLog refundsLog = new OmsServeRefundsLog();
            refundsLog.setOrderId(refundsMoneyVo.getOrderId());
            refundsLog.setOutRefundNo(request.getOutRefundNo());
            refundsLog.setEnterpriseId(refundsMoneyVo.getEnterpriseId());
            refundsLog.setSubMchId(jsonObject.getStr("subMchId"));
            refundsLog.setTotalMoney(new BigDecimal(refundsMoneyVo.getTotal()).divide(new BigDecimal(100)));
            refundsLog.setRefundMoney(new BigDecimal(refundsMoneyVo.getRefund()).divide(new BigDecimal(100)));
            refundsLog.setReason(refundsMoneyVo.getReason());
            refundsLog.setCreateTime(LocalDateTime.now());
            refundsLog.setWxOutRefundNo(result.getRefundId());
            omsServeRefundsLogService.save(refundsLog);

            return ResultMsg.success(result);
        } catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 退款查询
     */
    @GetMapping("queryRefunds")
    public ResultMsg queryRefunds(@RequestParam("orderId") String orderId) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        // 查询退款申请记录
        LambdaQueryWrapper<OmsServeRefundsLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OmsServeRefundsLog::getOrderId, orderId);
        List<OmsServeRefundsLog> list = omsServeRefundsLogService.list(wrapper);
        List<RefundQueryResult> result = new ArrayList<>();
        for (OmsServeRefundsLog refundsLog : list) {
            try {
                RefundQueryResult queryResult = ecommerceService.queryRefundByOutRefundNo(refundsLog.getSubMchId(), refundsLog.getOutRefundNo());
                result.add(queryResult);

                // TODO 更新状态
                if (StringUtils.isBlank(refundsLog.getStatus()) || !queryResult.getStatus().equals(refundsLog.getStatus())){
                    if ("SUCCESS".equals(queryResult.getStatus())) {
                        refundsLog.setCallbackTime(LocalDateTime.now());
                    }
                    refundsLog.setStatus(queryResult.getStatus());
                    omsServeRefundsLogService.updateById(refundsLog);
                }

            }catch (WxPayException e) {
                log.error(e.getMessage());
                return ResultMsg.error(e.getMessage());
            }
        }

        return ResultMsg.success(result);
    }


    /**
     * 查询二级商户账户实时余额
     */
    @GetMapping("subNowBalance")
    public ResultMsg subNowBalance(@RequestParam("enterpriseId") String enterpriseId) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 获取二级商户信息
        ResultMsg query = iSysEnterpriseApplyTwoPayService.query(enterpriseId);
        if (query.getData() == null || query.getCode() != 0) {
            return ResultMsg.error("该商户未申请二级商户号!");
        }
        JSONObject jsonObject = new JSONObject(query.getData());

        try {
            FundBalanceResult result = ecommerceService.subNowBalance(jsonObject.getStr("subMchId"));
            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 查询电商平台账户实时余额
     */
    @GetMapping("spNowBalance")
    public ResultMsg spNowBalance() {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        try {
            FundBalanceResult result = ecommerceService.spNowBalance(SpAccountTypeEnum.BASIC);
            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 查询二级商户账户日终余额
     * enterpriseId: 商户
     * date: 日期 -> 2019-08-17
     */
    @GetMapping("subDayEndBalance")
    public ResultMsg subDayEndBalance(@RequestParam("enterpriseId") String enterpriseId, @RequestParam("date") String date) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        // 获取二级商户信息
        ResultMsg query = iSysEnterpriseApplyTwoPayService.query(enterpriseId);
        if (query.getData() == null || query.getCode() != 0) {
            return ResultMsg.error("该商户未申请二级商户号!");
        }
        JSONObject jsonObject = new JSONObject(query.getData());
        try {
            FundBalanceResult result = ecommerceService.subDayEndBalance(jsonObject.getStr("subMchId"), date);
            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 查询电商平台账户日终余额
     * date: 日期 -> 2019-08-17
     */
    @GetMapping("spDayEndBalance")
    public ResultMsg spDayEndBalance(@RequestParam("date") String date) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        try {
            FundBalanceResult result = ecommerceService.spDayEndBalance(SpAccountTypeEnum.BASIC, date);
            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 二级商户预约提现
     */
    @PostMapping("subWithdraw")
    public ResultMsg subWithdraw(@RequestBody WithdrawVo withdrawVo) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 获取二级商户信息
        ResultMsg query = iSysEnterpriseApplyTwoPayService.query(withdrawVo.getEnterpriseId());
        if (query.getData() == null || query.getCode() != 0) {
            return ResultMsg.error("该商户未申请二级商户号!");
        }
        JSONObject jsonObject = new JSONObject(query.getData());

        try {
            SubWithdrawRequest request = new SubWithdrawRequest();
            request.setSubMchid(jsonObject.getStr("subMchId"));
            request.setOutRequestNo(String.valueOf(IdWorker.getId()));
            request.setAmount(withdrawVo.getAmount());
            request.setRemark(withdrawVo.getRemark());
            SubWithdrawResult result = ecommerceService.subWithdraw(request);

            // TODO 添加提现申请记录
            OmsWithdrawMoneyLog moneyLog = new OmsWithdrawMoneyLog();
            moneyLog.setOutRequestNo(request.getOutRequestNo());
            moneyLog.setWithdrawId(result.getWithdrawId());
            moneyLog.setEnterpriseId(withdrawVo.getEnterpriseId());
            moneyLog.setMchId(result.getSubMchid());
            moneyLog.setAmount(new BigDecimal(withdrawVo.getAmount()).divide(new BigDecimal(100)));
            moneyLog.setRemark(withdrawVo.getRemark());
            moneyLog.setCreateTime(LocalDateTime.now());
            omsWithdrawMoneyLogService.save(moneyLog);

            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 二级商户查询预约提现状态
     * withdrawMoneyLogId: 预约提现申请记录id
     */
    @GetMapping("querySubWithdrawByOutRequestNo")
    public ResultMsg querySubWithdrawByOutRequestNo(@RequestParam("withdrawMoneyLogId") String withdrawMoneyLogId) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 获取申请记录
        OmsWithdrawMoneyLog moneyLog = omsWithdrawMoneyLogService.getById(withdrawMoneyLogId);
        if (moneyLog == null) return ResultMsg.error("未找到该提现记录申请");
        try {
            SubWithdrawStatusResult result = ecommerceService.querySubWithdrawByOutRequestNo(moneyLog.getMchId(), moneyLog.getOutRequestNo());

            // TODO 更新状态
            if (StringUtils.isBlank(moneyLog.getStatus()) || !result.getStatus().equals(moneyLog.getStatus())) {
                moneyLog.setStatus(result.getStatus());
                moneyLog.setUpdateTime(LocalDateTime.now());
                if (result.getReason() != null) {
                    moneyLog.setReason(result.getReason());
                }
                omsWithdrawMoneyLogService.updateById(moneyLog);
            }

            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        }
    }

    /**
     * 申请下载交易账单
     */
    @PostMapping("tradeBill")
    public ResultMsg tradeBill(@RequestBody TradeBillVo tradeBillVo, HttpServletResponse response) {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        String subMchId = null;

        if (StringUtils.isNotBlank(tradeBillVo.getEnterpriseId())) {
            // 获取二级商户信息
            ResultMsg query = iSysEnterpriseApplyTwoPayService.query(tradeBillVo.getEnterpriseId());
            if (query.getData() == null || query.getCode() != 0) {
                return ResultMsg.error("该商户未申请二级商户号!");
            }
            JSONObject jsonObject = new JSONObject(query.getData());
            subMchId = jsonObject.getStr("subMchId");
        }

        try {
            TradeBillRequest request = TradeBillRequest.builder()
                    .billDate(tradeBillVo.getBillDate())
                    .billType(tradeBillVo.getBillType())
                    .tarType(tradeBillVo.getTarType())
                    .subMchid(subMchId).build();
            TradeBillResult result = ecommerceService.applyBill(request);

            downloadBill(result.getDownloadUrl(), response);

            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 申请资金账单
     */
    @PostMapping("fundFlowBill")
    public ResultMsg fundFlowBill(@RequestBody TradeBillVo tradeBillVo, HttpServletResponse response) {
        // 获取配置
        PmsApplicationServePay config = getConfig();
        // 调用地址
        String urlApi = "";
        if (tradeBillVo.getIsMchQuery()) {
            String url = WeChatServeConst.ECOMMERCE_FUND_FLOW_BILL;
            urlApi = url.replace("{bill_date}",tradeBillVo.getBillDate())
                    .replace("{account_type}", tradeBillVo.getAccountType())
                    .replace("{algorithm}", tradeBillVo.getAlgorithm());
        }else {
            String url = WeChatServeConst.FUND_FLOW_BILL;
            urlApi = url.replace("{bill_date}", tradeBillVo.getBillDate())
                    .replace("{account_type}", tradeBillVo.getAccountType());
        }

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader(Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue());
        headers.addHeader(Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue());
        headers.addHeader(Constant.WECHAT_PAY_SERIAL, config.getPlatformSerialNo());
        HttpRequest httpRequest =
                new HttpRequest.Builder()
                        .httpMethod(HttpMethod.GET)
                        .url(urlApi)
                        .headers(headers)
                        .build();

        try {
            HttpResponse<HttpResponse> resp = httpClient.execute(httpRequest, HttpResponse.class);
            ResponseBody result = resp.getBody();
            JSONObject jsonObject = new JSONObject(result).getJSONObject("body");
            downloadBill(jsonObject.getStr("download_url"), response);
            return ResultMsg.success(result);
        }catch (ServiceException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        } catch (IOException | WxPayException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 申请二级商户资金账单
     */
    @PostMapping("getAllSubMchFundFlowBill")
    public void getAllSubMchFundFlowBill(@RequestBody TradeBillVo tradeBillVo, HttpServletResponse response) {
        PmsApplicationServePay config = getConfig();
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);

        try {
            FundBillRequest request = FundBillRequest.builder()
                    .billDate(tradeBillVo.getBillDate())
                    .accountType(tradeBillVo.getAccountType())
                    .algorithm(tradeBillVo.getAlgorithm()).build();
            FundBillResult result = ecommerceService.applyFundBill(FundBillTypeEnum.SUB_FUND_FLOW_BILL, request);

            if (result.getDownloadBillCount() > 0) {
                JSONArray billList = new JSONArray(result.getDownloadBillList());
                for (Object object : billList) {
                    JSONObject object1 = new JSONObject(object);
                    byte[] ciphertext = downloadUrl(object1.getStr("downloadUrl"));
                    String encryptKey = WxPayUtils.rsaDecryptOAEP(object1.getStr("encryptKey"), config.getPrivateKeyPath());

                    String notifyData = WxPayUtils.decryptToString("",
                            object1.getStr("nonce").getBytes(StandardCharsets.UTF_8),
                            ciphertext,
                            encryptKey.getBytes(StandardCharsets.UTF_8));
                    log.info(notifyData);

                    // TODO 导出为.csv文件
                    List<BillFlowInfoVo> infoVos = WxPayUtils.stringToCsvFile(notifyData);
                    String fileName = new Date().getTime() + ".xlsx";
                    response.setContentType(CONTENT_TYPE);
                    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                    response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
                    EasyExcel.write(response.getOutputStream(), BillFlowInfoVo.class).sheet().doWrite(infoVos);
                }
            }

        }catch (ServiceException e) {
            log.error(e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 申请分账账单
     */
    @PostMapping("profitSharingBill")
    public ResultMsg profitSharingBill(@RequestBody TradeBillVo tradeBillVo, HttpServletResponse response) {
        // 获取配置
        PmsApplicationServePay config = getConfig();
        // 获取二级商户信息
        String subMchId = null;
        if (StringUtils.isNotBlank(tradeBillVo.getEnterpriseId())) {
            ResultMsg query = iSysEnterpriseApplyTwoPayService.query(tradeBillVo.getEnterpriseId());
            if (query.getData() == null || query.getCode() != 0) {
                return ResultMsg.error("该商户未申请二级商户号!");
            }
            JSONObject jsonObject = new JSONObject(query.getData());
            subMchId = jsonObject.getStr("subMchId");
        }

        try {
            String url = "https://api.mch.weixin.qq.com/v3/profitsharing/bills?bill_date=" + tradeBillVo.getBillDate();
            if (subMchId != null) {
                url = url + "&sub_mchid=" + subMchId;
            }
            if (StringUtils.isNotBlank(tradeBillVo.getTarType())) {
                url = url + "&tar_type=" + subMchId;
            }

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.addHeader(Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue());
            headers.addHeader(Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue());
            headers.addHeader(Constant.WECHAT_PAY_SERIAL, config.getPlatformSerialNo());
            HttpRequest httpRequest =
                    new HttpRequest.Builder()
                            .httpMethod(HttpMethod.GET)
                            .url(url)
                            .headers(headers)
                            .build();

            HttpResponse<HttpResponse> resp = httpClient.execute(httpRequest, HttpResponse.class);
            ResponseBody result = resp.getBody();
            JSONObject jsonObject = new JSONObject(result).getJSONObject("body");
            downloadBill(jsonObject.getStr("download_url"), response);

            return ResultMsg.success(result);
        }catch (WxPayException e) {
            log.error(e.getMessage());
            return ResultMsg.error(e.getMessage());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }





    /**
     * 下载账单
     */
    private void downloadBill(String downloadUrl, HttpServletResponse response) throws WxPayException, IOException {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 下载账单
        String fileName = new Date().getTime() + ".xlsx";
        InputStream inputStream = ecommerceService.downloadBill(downloadUrl);
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

        byte[] buffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            response.getOutputStream().write(buffer, 0, bytesRead);
        }

        response.getOutputStream().flush();
        response.getOutputStream().close();
        inputStream.close();
    }

    /**
     * 下载账单转成 byte[]
     * @param downloadUrl
     * @return
     * @throws Exception
     */
    private byte[] downloadUrl(String downloadUrl) throws Exception {
        // 获取配置
        WxPayService wxPayService = wxService();
        // 发起V3 服务商发起支付
        EcommerceServiceImpl ecommerceService = new EcommerceServiceImpl(wxPayService);
        // 下载账单
        InputStream inputStream = ecommerceService.downloadBill(downloadUrl);
        byte[] bytes = IOUtils.toByteArray(inputStream);
        return bytes;
    }

}

文件接口例子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值