package com.mcwl.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.common.models.AlipayTradeCancelResponse;
import com.mcwl.common.constant.HttpStatus;
import com.mcwl.common.core.domain.R;
import com.mcwl.common.core.domain.entity.SysUser;
import com.mcwl.common.core.redis.RedisCache;
import com.mcwl.common.exception.ServiceException;
import com.mcwl.common.utils.DateUtils;
import com.mcwl.common.utils.SecurityUtils;
import com.mcwl.common.utils.ShareCodeUtils;
import com.mcwl.common.utils.StringUtils;
import com.mcwl.memberCenter.domain.MemberLevel;
import com.mcwl.memberCenter.service.MemberLevelService;
import com.mcwl.myInvitation.domain.CommissionRatio;
import com.mcwl.myInvitation.domain.Consume;
import com.mcwl.myInvitation.mapper.ConsumeMapper;
import com.mcwl.myInvitation.service.CommissionRatioService;
import com.mcwl.pay.config.AliConfig;
import com.mcwl.pay.domain.OrderTrade;
import com.mcwl.pay.domain.OrderTradeDto;
import com.mcwl.pay.domain.enums.CommissionRationEnum;
import com.mcwl.pay.domain.vo.PayVo;
import com.mcwl.pay.service.AliPayService;
import com.mcwl.pay.service.OrderTradeService;
import com.mcwl.system.domain.SysEmail;
import com.mcwl.system.domain.SysUserPayAccount;
import com.mcwl.system.domain.SysUserPayAccountLog;
import com.mcwl.system.service.ISysEmailService;
import com.mcwl.system.service.ISysUserPayAccountLogService;
import com.mcwl.system.service.ISysUserPayAccountService;
import com.mcwl.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * 支付宝支付
 */
@Component
@Slf4j
public class AliPayServiceImpl implements AliPayService {

    @Autowired
    private Config config;

    @Autowired
    private RedisCache redisCache;


    @Autowired
    private MemberLevelService memberLevelService;


    @Autowired
    private AliConfig aliConfig;

    @Autowired
    private ISysUserPayAccountService sysUserPayAccountService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ISysUserPayAccountLogService sysUserPayAccountLogService;

    @Autowired
    private OrderTradeService orderTradeService;

    @Autowired
    private ConsumeMapper consumeMapper;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private ISysEmailService sysEmailService;

    @Autowired
    private CommissionRatioService commissionRatioService;

    private final int MAX_RETRY = 3; // 最大重试次数


    public AliPayServiceImpl(AliConfig aliConfig) {

        Config config = new Config();
        config.protocol = "https";
        config.signType = "RSA2";
        config.appId = aliConfig.getAppId();
        config.merchantPrivateKey = aliConfig.getPrivateKey();
        config.merchantCertPath = aliConfig.getAppCertPath();
        config.alipayCertPath = aliConfig.getAlipayCertPath();
        config.alipayRootCertPath = aliConfig.getAlipayRootCertPath();
        config.gatewayHost = aliConfig.getGatewayHost();
        config.notifyUrl = aliConfig.getNotifyUrl();

        Factory.setOptions(config);
    }


    /**
     * 调用支付宝预下订单接口
     *
     * @param orderTradeDto 订单实体
     * @return 二维码url
     * @throws Exception
     */
    @Override
    public PayVo memberPay(OrderTradeDto orderTradeDto) throws Exception {

        // 会员等级id
        Long productId = orderTradeDto.getProductId();

        if (!Optional.ofNullable(productId).isPresent()) {
            throw new ServiceException("memberLevelId不能为空", HttpStatus.SHOW_ERROR_MSG);
        }

        MemberLevel memberLevel = memberLevelService.getById(productId);

        if (!Optional.ofNullable(memberLevel).isPresent()) {
            throw new ServiceException("memberLevel不存在", HttpStatus.SHOW_ERROR_MSG);
        }

        // 设置orderTrade信息
        OrderTrade tradeEntity = new OrderTrade();
        BeanUtil.copyProperties(orderTradeDto, tradeEntity);
        tradeEntity.setCode(UUID.randomUUID().toString(true).substring(0, 30) + "_member");
        tradeEntity.setUserId(SecurityUtils.getUserId());
        tradeEntity.setUserName(SecurityUtils.getLoginUser().getUser().getNickName());
        tradeEntity.setProductId(productId);
        tradeEntity.setProductName(memberLevel.getMemberName());
        tradeEntity.setTotalAmount(orderTradeDto.getAmount());
        tradeEntity.setOrderStatus(1);
        tradeEntity.setPayStatus(1);
        orderTradeService.save(tradeEntity);

        //调用支付宝的接口
//        AlipayTradePrecreateResponse payResponse = Factory.Payment.FaceToFace()
//                .preCreate(memberLevel.getMemberName(),
//                        tradeEntity.getCode(),
//                        orderTradeDto.getAmount().toString());
        AlipayTradePrecreateResponse payResponse = getAlipayTradePrecreateResponse(tradeEntity);
        // 缓存到redis
        if (Objects.nonNull(orderTradeDto.getPromotionId())) {
            redisCache.setCacheObject(tradeEntity.getCode() + "_promotionId", orderTradeDto.getPromotionId(), 15, TimeUnit.MINUTES);
        }
        //参照官方文档响应示例，解析返回结果
        String httpBodyStr = payResponse.getBody();
        JSONObject jsonObject = JSONObject.parseObject(httpBodyStr);

        PayVo payVo = new PayVo();
        payVo.setOrderNo(tradeEntity.getCode());
        payVo.setUrl(jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString());
        return payVo;
    }


    /**
     * 调用支付宝预下订单接口
     *
     * @param paymentAmount 充值积分
     * @return 二维码url
     * @throws Exception
     */
    @Override
    public PayVo pointsPay(Double paymentAmount) throws Exception {
        // 设置orderTrade信息
        OrderTrade tradeEntity = new OrderTrade();
        tradeEntity.setCode(UUID.randomUUID().toString(true).substring(0, 30) + "_points");
        tradeEntity.setUserId(SecurityUtils.getUserId());
        tradeEntity.setProductId(-1L);
        tradeEntity.setProductName("积分充值");
        tradeEntity.setUserName(SecurityUtils.getLoginUser().getUser().getNickName());
        tradeEntity.setTotalAmount(paymentAmount);
        tradeEntity.setOrderStatus(1);
        tradeEntity.setPayStatus(1);
        orderTradeService.save(tradeEntity);
        //调用支付宝的接口
//        AlipayTradePrecreateResponse payResponse = Factory.Payment.FaceToFace()
//                .preCreate(tradeEntity.getProductName(),
//                        tradeEntity.getCode(),
//                        paymentAmount.toString());
        AlipayTradePrecreateResponse payResponse = getAlipayTradePrecreateResponse(tradeEntity);
        //参照官方文档响应示例，解析返回结果
        String httpBodyStr = payResponse.getBody();
        JSONObject jsonObject = JSONObject.parseObject(httpBodyStr);

        String url = jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString();
        PayVo payVo = new PayVo();
        payVo.setOrderNo(tradeEntity.getCode());
        payVo.setUrl(url);

        return payVo;
    }


    /**
     * 调用支付宝预下订单接口
     *
     * @param paymentAmount 充值金币
     * @return 二维码url
     * @throws Exception
     */
    @Override
    public PayVo walletPay(Double paymentAmount) throws Exception {
        // 设置orderTrade信息
        OrderTrade tradeEntity = new OrderTrade();
        tradeEntity.setCode(UUID.randomUUID().toString(true).substring(0, 30) + "_wallet");
        tradeEntity.setUserId(SecurityUtils.getUserId());
        tradeEntity.setProductId(-1L);
        tradeEntity.setProductName("金币充值");
        tradeEntity.setUserName(SecurityUtils.getLoginUser().getUser().getNickName());
        tradeEntity.setTotalAmount(paymentAmount);
        tradeEntity.setOrderStatus(1);
        tradeEntity.setPayStatus(1);
        orderTradeService.save(tradeEntity);
        //调用支付宝的接口
//        AlipayTradePrecreateResponse payResponse = Factory.Payment.FaceToFace()
//                .preCreate(tradeEntity.getProductName(),
//                        tradeEntity.getCode(),
//                        paymentAmount.toString());
        AlipayTradePrecreateResponse payResponse = getAlipayTradePrecreateResponse(tradeEntity);

        //参照官方文档响应示例，解析返回结果
        String httpBodyStr = payResponse.getBody();
        JSONObject jsonObject = JSONObject.parseObject(httpBodyStr);

        String url = jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString();
        PayVo payVo = new PayVo();
        payVo.setOrderNo(tradeEntity.getCode());
        payVo.setUrl(url);

        return payVo;
    }

    /**
     * 查询支付宝账户绑定状态
     *
     * @return 0：未绑定，1：已绑定
     */
    @Override
    public R<Object> queryBindStatus() {

        // 查询redis中支付宝绑定状态
        String bindStatus = redisCache.getCacheObject("alipay:bind:user:status:" + SecurityUtils.getUserId());

        if (Objects.nonNull(bindStatus)) {
            return R.ok(bindStatus);
        }

        SysUserPayAccount sysUserPayAccount = sysUserPayAccountService.lambdaQuery()
                .eq(SysUserPayAccount::getUserId, SecurityUtils.getUserId())
                .eq(SysUserPayAccount::getAppId, aliConfig.getAppId())
                .eq(SysUserPayAccount::getType, 0)
                .one();

        if (Objects.isNull(sysUserPayAccount)) {
            redisCache.setCacheObject("alipay:bind:user:status:" + SecurityUtils.getUserId(), "0", 4, TimeUnit.SECONDS);
            return R.ok("0");
        }
        redisCache.setCacheObject("alipay:bind:user:status:" + SecurityUtils.getUserId(), "1", 4, TimeUnit.SECONDS);
        return R.ok("1");
    }

    /**
     * 支付宝转账方法
     *
     * @param amount 转账金额
     * @return 返回支付宝转账响应的内容
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<String> fetch(String amount) throws AlipayApiException, FileNotFoundException {
        String lock = redisCache.getCacheObject("alipay:fetch:user:" + SecurityUtils.getUserId());
        if (!StrUtil.isEmpty(lock)) {
            return R.fail(HttpStatus.SHOW_ERROR_MSG, "请勿频繁点击");
        }
        try {
            redisCache.setCacheObject("alipay:fetch:user:" + SecurityUtils.getUserId(), "1");

            Long userId = SecurityUtils.getUserId();


            SysUser sysUser = sysUserService.selectUserById(userId);
            if (sysUser.getWallet() < Double.parseDouble(amount)) {
                return R.fail(HttpStatus.SHOW_ERROR_MSG, "钱包余额不足");
            }

            // 提现抽取比例
            String CommissionRationMerchant = redisCache.getCacheObject("CommissionRationFetch");
            if (Objects.isNull(CommissionRationMerchant)) {
                CommissionRatio commissionRatio = commissionRatioService.lambdaQuery()
                        .eq(CommissionRatio::getType, 3)
                        .one();
                CommissionRationMerchant = commissionRatio.getRatio().toString();
                redisCache.setCacheObject("CommissionRationFetch", CommissionRationMerchant);
            }
            BigDecimal amountBigDecimal = new BigDecimal(amount);
            BigDecimal fetchBigDecimal = amountBigDecimal
                    .multiply(new BigDecimal("1").subtract(new BigDecimal(CommissionRationMerchant)));
            amount = fetchBigDecimal.setScale(2, RoundingMode.HALF_UP).toString();

            // 查询用户支付宝账户
            SysUserPayAccount sysUserPayAccount = sysUserPayAccountService
                    .lambdaQuery()
                    .eq(SysUserPayAccount::getUserId, userId)
                    .eq(SysUserPayAccount::getType, 0)
                    .one();
            if (Objects.isNull(sysUserPayAccount)) {
                return R.fail(HttpStatus.SHOW_ERROR_MSG, "请先绑定支付宝账号");
            }

            // 添加提现记录和修改用户钱包
            this.addLogAndUpdateUserWallet(sysUser, amount);

            // 证书用：certificateExecute(request)，密钥用：execute(request)
            AlipayFundTransUniTransferResponse response = getAlipayFundTransUniTransferResponse(amount, sysUserPayAccount.getOpenId());
            System.out.println(response.getBody());

            if (response.isSuccess()) {

                return R.ok("提现成功");
            }

            if (response.getSubCode().equals("BALANCE_IS_NOT_ENOUGH")) {

                ArrayList<String> tos = new ArrayList<>();
                for (SysEmail sysEmail : sysEmailService.list()) {
                    tos.add(sysEmail.getRecipientEmail());
                }

                // 账户余额不足，发送邮件通知
//                ArrayList<String> tos = CollUtil.newArrayList("2119157836@qq.com");

                String content = String.format("账户余额不足：用户%s提现：%s", sysUser.getNickName(), amount);
                MailUtil.send(tos, "魔创未来", content, false);
                throw new ServiceException("网络异常,请稍后再试", HttpStatus.SHOW_ERROR_MSG);
            }
            System.out.println("用户" + SecurityUtils.getLoginUser().getUser().getNickName() + "提现失败：" + response.getSubMsg());
            throw new ServiceException("提现失败", HttpStatus.SHOW_ERROR_MSG);
        } finally {
            redisCache.deleteObject("alipay:fetch:user:" + SecurityUtils.getUserId());
        }

    }

    @Override
    public R<Object> queryTradeStatus(String outTradeNo) throws Exception {

        // 查询redis中订单信息
        String orderTradeJson = redisCache.getCacheObject(outTradeNo);
        OrderTrade orderTrade = null;
        if (StringUtils.isNotBlank(orderTradeJson)) {
            orderTrade = JSONUtil.toBean(orderTradeJson, OrderTrade.class);
        }
        // 如果redis中存在该订单, 则直接返回该订单的支付状态
        if (Objects.nonNull(orderTrade)) {
            return R.ok(orderTrade.getOrderStatus());
        }

        // 查询支付宝订单
        orderTrade = orderTradeService.lambdaQuery()
                .eq(OrderTrade::getCode, outTradeNo)
                .one();

        // 如果数据库中不存在该订单, 则返回订单不存在
        if (Objects.isNull(orderTrade)) {
            return R.fail(HttpStatus.SHOW_ERROR_MSG, "订单不存在");
        }


        if (orderTrade.getPayStatus() == 1) {
            // 查询支付宝订单
            AlipayTradeQueryResponse tradStatus;
            try {
                tradStatus = this.getTradStatus(outTradeNo);
            } catch (Exception e) {
                log.error("支付状态获取失败，原始内容: {}", e.getMessage());
                return R.ok(0);
            }

            // 返回交易结果, 是否交易成功需要根据该对象中的 trade_status 来确定
            // trade_status 的枚举值如下, 请见 https://opendocs.alipay.com/apis/api_1/alipay.trade.query
            // WAIT_BUYER_PAY（交易创建，等待买家付款）
            // TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）
            // TRADE_SUCCESS（交易支付成功）
            // TRADE_FINISHED（交易结束，不可退款）
            // 当 trade_status 等于 TRADE_SUCCESS 或 TRADE_FINISHED 时, 表示支付成功

            String tradeStatus = tradStatus.getTradeStatus();
            if (Objects.nonNull(tradeStatus) && tradeStatus.equals("TRADE_SUCCESS")) {
                Map<String, String> params = new HashMap<>();
                params.put("buyer_pay_amount", tradStatus.getBuyerPayAmount());
                params.put("out_trade_no", tradStatus.getOutTradeNo());
                params.put("gmt_payment", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, tradStatus.getSendPayDate()));
                params.put("total_amount", tradStatus.getTotalAmount());
                params.put("trade_no", tradStatus.getTradeNo());
                String code = orderTrade.getCode();
                // 获取订单后缀
                String suffix = code.substring(code.lastIndexOf("_") + 1);
                orderTradeService.orderHandler(orderTrade, suffix, params);
                return R.ok(orderTrade.getOrderStatus());
            }
            long time = (System.currentTimeMillis() - orderTrade.getCreateTime().getTime()) / 1000 / 60;
            // time 超过15分钟，则删除redis中订单信息
            if (time >= 1) {

                this.cancelTrade(orderTrade);

            }
        }

        redisCache.setCacheObject(outTradeNo, JSONUtil.toJsonStr(orderTrade), 4, TimeUnit.SECONDS);
        return R.ok(orderTrade.getOrderStatus());
    }

    @Override
    public String bindingCallback(String authCode, String state) throws FileNotFoundException {
        try {
            Long userId = ShareCodeUtils.codeToId(state);
            if (Objects.isNull(userId)) {
                return "fail";
            }
            AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            request.setCode(authCode);
            request.setGrantType("authorization_code");
            AlipaySystemOauthTokenResponse response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                // 支付宝用户唯一ID
                String openId = response.getOpenId();
                String uid = response.getUserId();
                // 判断是否已经绑定过
                SysUserPayAccount sysUserPayAccount = sysUserPayAccountService.lambdaQuery()
                        .eq(SysUserPayAccount::getUserId, userId)
                        .eq(SysUserPayAccount::getAppId, aliConfig.getAppId())
                        .eq(SysUserPayAccount::getOpenId, StrUtil.isEmpty(openId) ? uid : openId)
                        .eq(SysUserPayAccount::getType, 0)
                        .one();
                if (Objects.nonNull(sysUserPayAccount)) {
                    // 已经绑定过，直接返回
                    return "success";
                }
                System.out.println("绑定成功！openId/uid：" + (StrUtil.isEmpty(openId) ? uid : openId));
                // 将openId与当前商城用户绑定（保存到数据库）
                SysUserPayAccount userPayAccount = new SysUserPayAccount();
                userPayAccount.setUserId(userId);
                userPayAccount.setAppId(aliConfig.getAppId());
                userPayAccount.setOpenId(StrUtil.isEmpty(openId) ? uid : openId);
                userPayAccount.setType(0);
                sysUserPayAccountService.save(userPayAccount);
                redisCache.setCacheObject("alipay:bind:user:status:" + userId, "1", 4, TimeUnit.SECONDS);
                return "success";
            } else {
                System.out.println("绑定失败：" + response.getSubMsg());
                redisCache.setCacheObject("alipay:bind:user:status:" + userId, "0", 4, TimeUnit.SECONDS);
                return "fail";
            }
        } catch (AlipayApiException e) {
            return "fail";
        }

    }

    private AlipayFundTransUniTransferResponse getAlipayFundTransUniTransferResponse(String amount, String identity) throws FileNotFoundException, AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());

        // 构造请求参数以调用接口
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
        // 设置商家侧唯一订单号
        model.setOutBizNo(UUID.fastUUID().toString(true));

        // 设置订单总金额
        model.setTransAmount(amount);

        // 设置描述特定的业务场景
        model.setBizScene("DIRECT_TRANSFER");

        // 设置业务产品码
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");

        // 设置转账业务的标题
        model.setOrderTitle("提现");

        // 收款方信息
        Participant payeeInfo = new Participant();

        payeeInfo.setIdentity(identity);
        payeeInfo.setIdentityType(aliConfig.getIdentityType());
        model.setPayeeInfo(payeeInfo);

        request.setBizModel(model);

        // 证书用：certificateExecute(request)，密钥用：execute(request)
        return alipayClient.certificateExecute(request);
    }


    private void cancelTrade(OrderTrade orderTrade) throws Exception {

        threadPoolTaskExecutor.execute(() -> {
            try {
                for (int i = 0; i < MAX_RETRY; i++) {
                    // 撤销交易
                    AlipayTradeCancelResponse cancel = Factory.Payment.Common().cancel(orderTrade.getCode());
                    if (cancel.getMsg().equals("Success")) {
                        orderTrade.setOrderStatus(4);
                        orderTradeService.updateById(orderTrade);
                        redisCache.deleteObject(orderTrade.getCode() + "promotionId");
                        break;
                    } else {
                        // 检查是否需要继续重试
                        if (!"Y".equals(cancel.getRetryFlag())) {
                            break;
                        }
                    }
                    Thread.sleep(2000); // 间隔2秒重试
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });

    }

    private AlipayTradeQueryResponse getTradStatus(String outTradeNo) throws Exception {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());

        // 构造请求参数以调用接口
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();

        // 设置订单支付时传入的商户订单号
        model.setOutTradeNo(outTradeNo);

        request.setBizModel(model);

        AlipayTradeQueryResponse response = alipayClient.certificateExecute(request);
        return response;
    }

    private void addLogAndUpdateUserWallet(SysUser sysUser, String amount) {
        BigDecimal wallet = new BigDecimal(sysUser.getWallet().toString());
        BigDecimal amountBigDecimal = new BigDecimal(amount);
        sysUser.setWallet(wallet.subtract(amountBigDecimal).setScale(2, RoundingMode.HALF_UP).doubleValue());
        sysUserService.updateUser(sysUser);

        Consume consume = new Consume();
        consume.setUserId(SecurityUtils.getUserId());
        consume.setAmount(-Double.parseDouble(amount));
        consume.setType(6);
        consume.setWallet(sysUser.getWallet());
        consumeMapper.insert(consume);

        // 添加记录
        SysUserPayAccountLog sysUserPayAccountLog = new SysUserPayAccountLog();
        sysUserPayAccountLog.setUserId(sysUser.getUserId());
        sysUserPayAccountLog.setAmount(Double.valueOf(amount));
        sysUserPayAccountLog.setAccount("支付宝");
        sysUserPayAccountLog.setWallet(sysUser.getWallet());
        sysUserPayAccountLogService.save(sysUserPayAccountLog);
    }

    public AlipayTradePrecreateResponse getAlipayTradePrecreateResponse(OrderTrade tradeEntity) throws Exception {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());

        // 构造请求参数以调用接口
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();

        // 设置商户订单号
        model.setOutTradeNo(tradeEntity.getCode());

        // 设置订单总金额
        model.setTotalAmount(tradeEntity.getTotalAmount().toString());

        // 设置订单标题
        model.setSubject(tradeEntity.getProductName());

        // 设置产品码
        model.setProductCode("QR_CODE_OFFLINE");

        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        return alipayClient.certificateExecute(request);
    }

    public AlipayConfig getAlipayConfig() throws FileNotFoundException {

        AlipayConfig config = new AlipayConfig();

        // 设置网关地址
        config.setServerUrl(aliConfig.getGatewayUrl());

        // 设置应用ID
        config.setAppId(aliConfig.getAppId());

        // 设置应用私钥
        config.setPrivateKey(aliConfig.getPrivateKey());

        // 设置支付宝公钥，因为配置了证书，所以不需要设置支付宝公钥
//        config.setAlipayPublicKey(aliConfig.getPublicKey());

        // 设置应用公钥证书路径
        config.setAppCertPath(aliConfig.getAppCertPath());

        // 设置支付宝公钥证书路径
        config.setAlipayPublicCertPath(aliConfig.getAlipayCertPath());

        // 设置支付宝根证书路径
        config.setRootCertPath(aliConfig.getAlipayRootCertPath());

        // 设置字符编码格式
        config.setCharset("UTF-8");

        // 设置签名类型
        config.setSignType("RSA2");

        return config;
    }
}
