package com.iformall.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.pay.*;
import com.iformall.service.*;
import com.iformall.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.*;

@Service
public class WxPayOrderServiceImpl implements WxPayOrderService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxAppinfoMapper wxAppinfoMapper;

    @Autowired
    WxCUserMapper wxCUserMapper;

    @Autowired
    WxCUserService wxCUserService;

    @Autowired
    WxPayAccountMapper wxPayAccountMapper;

    @Autowired
    WxOrderMapper wxOrderMapper;

    @Autowired
    WxOrderService wxOrderService;

    @Autowired
    WxCouponMapper wxCouponMapper;

    @Autowired
    WxPayOrderMapper wxPayOrderMapper;

    @Autowired
    WxTemplateMsgMapper wxTemplateMsgMapper;

    @Autowired
    WxMerchantMapper wxMerchantMapper;

    @Autowired
    WxMerchantBUserMapper wxMerchantBUserMapper;

    @Autowired
    WxProfitSharingReceiverMapper wxProfitSharingReceiverMapper;

    @Autowired
    WxCouponOrderService wxCouponOrderService;

    @Autowired
    WxAppinfoService wxAppinfoService;

    @Autowired
    WxOrderGroupService wxOrderGroupService;

    @Autowired
    WxMerchantSubsidyMapper wxMerchantSubsidyMapper;

    JSONObject errorMap = JSON.parseObject("{" +
            "\"NOAUTH\":{\"detail\":\"商户无此接口权限\",\"reason\":\"商户未开通此接口权限\",\"resolution\":\"请商户前往申请此接口权限\"}," +
            "\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"用户帐号余额不足\",\"resolution\":\"用户帐号余额不足，请用户充值或更换支付卡后再支付\"}," +
            "\"ORDERPAID\":{\"detail\":\"商户订单已支付\",\"reason\":\"商户订单已支付，无需重复操作\",\"resolution\":\"商户订单已支付，无需更多操作\"}," +
            "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"当前订单已关闭，无法支付\",\"resolution\":\"当前订单已关闭，请重新下单\"}," +
            "\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"系统超时\",\"resolution\":\"系统异常，请用相同参数重新调用\"}," +
            "\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"}," +
            "\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"}," +
            "\"APPID_MCHID_NOT_MATCH\":{\"detail\":\"appid和mch_id不匹配\",\"reason\":\"appid和mch_id不匹配\",\"resolution\":\"请确认appid和mch_id是否匹配\"}," +
            "\"LACK_PARAMS\":{\"detail\":\"缺少参数\t\",\"reason\":\"缺少必要的请求参数\",\"resolution\":\"请检查参数是否齐全\"}," +
            "\"OUT_TRADE_NO_USED\":{\"detail\":\"商户订单号重复\",\"reason\":\"同一笔交易不能多次提交\",\"resolution\":\"请核实商户订单号是否重复提交\"}," +
            "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," +
            "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"}," +
            "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," +
            "\"POST_DATA_EMPTY\":{\"detail\":\"post数据为空\",\"reason\":\"post数据不能为空\",\"resolution\":\"请检查post数据是否为空\"}," +
            "\"NOT_UTF8\":{\"detail\":\"编码格式错误\",\"reason\":\"未使用指定编码格式\",\"resolution\":\"请使用UTF-8编码格式\"}}");

    JSONObject errorMapQuery = JSON.parseObject("{" +
            "\"ORDERNOTEXIST\":{\"detail\":\"此交易订单号不存在\",\"reason\":\"查询系统中不存在此交易订单号\",\"resolution\":\"该API只能查提交支付交易返回成功的订单，请商户检查需要查询的订单号是否正确\"},\n" +
            "\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"后台系统返回错误\",\"resolution\":\"系统异常，请再调用发起查询\"}}");

    JSONObject errorMapClose = JSON.parseObject("{" +
            "\"ORDERPAID\":{\"detail\":\"订单已支付\",\"reason\":\"订单已支付，不能发起关单\",\"resolution\":\"订单已支付，不能发起关单，请当作已支付的正常交易\"}," +
            "\"SYSTEMERROR\":{\"detail\":\"系统错误\",\"reason\":\"系统错误\",\"resolution\":\"系统异常，请重新调用该API\"}," +
            "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"订单已关闭，无法重复关闭\",\"resolution\":\"订单已关闭，无需继续调用\"}," +
            "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," +
            "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," +
            "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"reason\":\"请检查XML参数格式是否正确\"}}");

    @Override
    public ResultData createPayOrder(WxAppinfo appInfo, WxCUser user, WxPayOrder record, EnumPayWay payWay) {
        final IdWorker idworker = IdWorker.get();

        EnumPayShare isShare = EnumPayShare.NO;

        try {
            // 1. check 订单
            WxOrder order = wxOrderMapper.selectById(record.getOrderId());
            if (order == null) {
                logger.error("pay order, order not allow, repaymentReq: " + record.toString() + ", payWay: " + payWay.toString());
                throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND);
            }
            if (!order.getOrderGroupId().equals(0L)) {
                if (order.getOrderStatus().equals(EnumOrderStatus.ORDER_STATUS_COOPERATING_COMPLETE.getCode())) {
                    logger.error("支付时拼团已满>>" + order.getOrderGroupId());
                    throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FINISHED);
                }
                WxOrder orderParams = new WxOrder();
                orderParams.setOrderGroupId(order.getOrderGroupId());
                orderParams.setCUserId(user.getId());
                orderParams.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING.getCode());
                int count = wxOrderMapper.selectCount(new QueryWrapper(orderParams));
                if (count > 0) {
                    logger.error("重复的拼团>>>" + order);
                    throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_ATTEND);
                }
            }

            WxCoupon wxCoupon = wxCouponMapper.selectById(order.getProductId());
            if (wxCoupon.getType().equals(EnumCouponType.COUPON_GROUP.getCode()) &&
                    wxCoupon.getStatus().equals(EnumCouponStatus.COUPON_STATUS_TAKE_OFFF.getCode())) {
                logger.error("券已经下架了>>>" + order.getProductId());
                throw new MallinkException(ErrorCode.COUPON_CHANNEL_IS_TAKE_OFF);
            }

            if (!wxCoupon.getType().equals(EnumCouponType.COUPON_GROUP.getCode()) && order.getPressEndDate() == null) {
                // 非砍价券且非拼团券
                if (order.getOrderStatus() == EnumOrderStatus.ORDER_STATUS_PAYMENT_SUCCESS.getCode()) {
                    logger.error("订单已支付: " + order.toString() + " , payWay: " + payWay.toString());
                    throw new MallinkException(ErrorCode.ORDER_HAD_PAY);
                } else if (order.getOrderStatus() == EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL.getCode()) {
                    logger.error("订单已取消: " + order.toString() + " , payWay: " + payWay.toString());
                    throw new MallinkException(ErrorCode.ORDER_HAD_CANCEL);
                } else {
                    if (order.getOrderStatus() != EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()) {
                        logger.error("订单已支付: " + order.toString() + " , payWay: " + payWay.toString());
                        throw new MallinkException(ErrorCode.ORDER_IS_NOT_PAY);
                    }
                }
            } else if (order.getPressEndDate() != null) {
                // 砍价券，只有在过期时无法支付
                // 砍价中，原价购买
                // 砍价完成，低价购买
                if (order.getOrderStatus() == EnumOrderStatus.ORDER_STATUS_PRESS_OVERTIME.getCode()) {
                    logger.error("砍价已过期: " + order.toString() + " , payWay: " + payWay.toString());
                    throw new MallinkException(ErrorCode.ORDER_PRESS_IS_OVERTIME);
                }
            }
            if (order.getPaymentType() != EnumPayType.PAY_PAYMENT.getCode()) {
                return new ResultData(ErrorCode.PAY_ORDER_IS_NOT_PAYMENT);
            }
            WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
            if (payAccount.checkShare()) {
                isShare = EnumPayShare.YES;
            }

            // 1.5 检查是否有已支付订单
            {
                WxPayOrder payOrderParams = new WxPayOrder();
                payOrderParams.setOrderId(order.getId());
                payOrderParams.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode());
                QueryWrapper<WxPayOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.setEntity(payOrderParams);
                int count = wxPayOrderMapper.selectCount(queryWrapper);
                if (count > 0) {
                    logger.error("已支付>>>" + order);
                    throw new MallinkException(ErrorCode.PAY_ORDER_EXIST);
                }
            }

            /*设置进入分账,待分账时再判断是否存在对应的分账账户
            // 1.5 check 分账 receive
            if (isShare == EnumPayShare.YES) {
                WxProfitSharingReceiver receiver = new WxProfitSharingReceiver();
                receiver.setMerchantId(order.getMerchantId());
                List<WxProfitSharingReceiver> merList = wxProfitSharingReceiverMapper.findList(receiver);
                if (merList.size() > 0) {
                    isShare = EnumPayShare.YES;
                } else {
                    isShare = EnumPayShare.NO;
                }
            }
            */

            // 2. check 是否有支付中订单
            Date currentDate = new Date();
            record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode());
            List<WxPayOrder> list = wxPayOrderMapper.findList(record);
            String payOrderNo = "";
            if (list.size() > 0) {
                // 3.0 已有支付订单，关闭之前的
                payOrderClose(appInfo, list.get(0));
            }


            {
                // 3.1 创建支付订单
                Long id = idworker.nextId();
                payOrderNo = String.valueOf(id);
                record.setId(id);
                record.setTenantId(user.getTenantId());
                record.setCUserId(user.getId());
                record.setCreateTime(currentDate);
                record.setUpdateTime(currentDate);
                record.setPayTimeStart(currentDate);
                record.setPayTimeEnd(currentDate);
                // 支付单号
                record.setPayOrderNo(payOrderNo);
                record.setPayAmount(order.getPayment());
                record.setPayVendor(EnumPayWay.PAY_WAY_WEAPP.getCode());
                record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode());
                record.setShare(isShare.getCode());
                if (isShare == EnumPayShare.YES) {
                    // 分账金额
                    int iChargeFee = PayUtils.getPayRate(record.getPayAmount(), payAccount.getRate(), false);
                    Integer share_amount = record.getPayAmount() - iChargeFee;
                    record.setShareAmount(share_amount);
                    if(payAccount.getRealRate() != null) {
                        int iRealChargeFee = PayUtils.getPayRate(record.getPayAmount(), payAccount.getRealRate(), true);
                        if(iChargeFee > iRealChargeFee) {
                            record.setRateAmount(iChargeFee - iRealChargeFee);
                        }
                    }
                }

                int sqlRow = wxPayOrderMapper.insert(record);
                if (sqlRow != 1) {
                    logger.error("pay order insert error: " + record.toString());
                    throw new MallinkException(ErrorCode.DB_FAIL);
                }
            }

            if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
                // 统一下单 普通商户模式
                String noncestr = Utility.generate32UUID();
                WxPayOrderP wxPayOrderP = new WxPayOrderP();
                wxPayOrderP.setOpenid(user.getOpenId());
                wxPayOrderP.setAppid(user.getAppId());
                wxPayOrderP.setMch_id(payAccount.getMchId());
                wxPayOrderP.setNonce_str(noncestr);
                wxPayOrderP.setBody(order.getDetail());
                wxPayOrderP.setOut_trade_no(record.getPayOrderNo());
                wxPayOrderP.setTotal_fee(order.getPayment());
                wxPayOrderP.setSpbill_create_ip(record.getIp());               // 终端IP
                wxPayOrderP.setGoods_tag(String.valueOf(order.getProductId()));
                wxPayOrderP.setNotify_url(payAccount.getPayNotifyUrl());
                wxPayOrderP.setTrade_type(WxPay.TradeType.JSAPI.name());       // 终端类型
                wxPayOrderP.setProduct_id(String.valueOf(order.getId()));      // 订单ID
                wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
                Date futureDate = new Date();
                futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
                wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate));    // 15分钟后结束
                Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderP);
                wxPayOrderP.setSign(WxPayment.createSign(payOrderMap, payAccount.getApiKey()));
                String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderP));
                logger.info("pay order, wechat pushOrder, " + wxPayOrderP.toString() + ", response: " + response.toString());
                Map<String, String> returnMap = WxPayment.xmlToMap(response);
                returnMap.put("payOrderId", payOrderNo);
                String result_code = returnMap.get("result_code");
                if ("SUCCESS".equals(result_code)) {
                    String prepay_id = returnMap.get("prepay_id");
                    // update payOrder with prepay_id
                    record.setPrepayId(prepay_id);
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }

                    String timestamp = String.valueOf(Utility.getCurrentTimeStamp());
                    Map<String, String> sighMap = MapUtil.getOrderMap();
                    sighMap.put("appId", returnMap.get("appid"));
                    sighMap.put("timeStamp", timestamp);
                    sighMap.put("nonceStr", noncestr);
                    sighMap.put("package", "prepay_id=" + prepay_id);
                    sighMap.put("signType", "MD5");
                    String signAgent = WxPayment.createSign(sighMap, payAccount.getApiKey());
                    returnMap.put("timeStamp", timestamp);
                    returnMap.put("nonceStr", noncestr);
                    returnMap.put("package", "prepay_id=" + prepay_id);
                    returnMap.put("paySign", signAgent);
                    logger.info("back to UI: " + returnMap.toString());
                    return new ResultData(Result.SUCCESS, "创建支付订单成功", returnMap);
                } else {
                    String errMsg = "";
                    JSONObject errObj = errorMap.getJSONObject(result_code);
                    if (errObj != null) {
                        errMsg = errObj.toJSONString();
                        record.setFailReason(errMsg);
                    } else {
                        errMsg = returnMap.get("return_msg");
                        record.setFailReason(errMsg);
                    }
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                }
            } else {
                // 统一下单 // 服务商模式
                String noncestr = Utility.generate32UUID();
                WxPayOrderSP wxPayOrderSP = new WxPayOrderSP();
                wxPayOrderSP.setSub_openid(user.getOpenId());
                wxPayOrderSP.setAppid(appInfo.getParentAppId());
                wxPayOrderSP.setMch_id(payAccount.getMchId());
                wxPayOrderSP.setSub_appid(user.getAppId());
                wxPayOrderSP.setSub_mch_id(payAccount.getSubMchId());
                wxPayOrderSP.setNonce_str(noncestr);
                wxPayOrderSP.setBody(order.getDetail());
                wxPayOrderSP.setOut_trade_no(record.getPayOrderNo());
                wxPayOrderSP.setTotal_fee(order.getPayment().toString());
                wxPayOrderSP.setSpbill_create_ip(record.getIp());               // 终端IP
                wxPayOrderSP.setGoods_tag(String.valueOf(order.getProductId())); // 券ID
                wxPayOrderSP.setNotify_url(payAccount.getPayNotifyUrl());
                wxPayOrderSP.setTrade_type(WxPay.TradeType.JSAPI.name());       // 终端类型
                wxPayOrderSP.setProduct_id(String.valueOf(order.getProductId()));      // 券ID
                wxPayOrderSP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
                Date futureDate = new Date();
                futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
                wxPayOrderSP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate));    // 15分钟后结束
                wxPayOrderSP.setSign_type("HMAC-SHA256");
                wxPayOrderSP.setProfit_sharing(null);
                if (isShare == EnumPayShare.YES) {
                    wxPayOrderSP.setProfit_sharing("Y");
                }
                Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderSP);

                wxPayOrderSP.setSign(WxPayment.createSignHMAC(payOrderMap, payAccount.getApiKey()));
                String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderSP));
                logger.info("pay order, wechat pushOrder, " + wxPayOrderSP.toString() + ", response: " + response.toString());
                Map<String, String> returnMap = WxPayment.xmlToMap(response);
                returnMap.put("payOrderId", payOrderNo);
                String result_code = returnMap.get("result_code");
                if ("SUCCESS".equals(result_code)) {
                    String prepay_id = returnMap.get("prepay_id");
                    // update payOrder with prepay_id
                    record.setPrepayId(prepay_id);
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }

                    String timestamp = String.valueOf(Utility.getCurrentTimeStamp());
                    Map<String, String> sighMap = MapUtil.getOrderMap();
                    sighMap.put("appId", appInfo.getAppId());
                    sighMap.put("timeStamp", timestamp);
                    sighMap.put("nonceStr", noncestr);
                    sighMap.put("package", "prepay_id=" + prepay_id);
                    sighMap.put("signType", "HMAC-SHA256");
                    String signAgent = WxPayment.createSignHMAC(sighMap, payAccount.getApiKey());
                    returnMap.put("timeStamp", timestamp);
                    returnMap.put("nonceStr", noncestr);
                    returnMap.put("package", "prepay_id=" + prepay_id);
                    returnMap.put("paySign", signAgent);
                    returnMap.put("signType", "HMAC-SHA256");
                    logger.info("back to UI: " + returnMap.toString());
                    return new ResultData(Result.SUCCESS, "创建支付订单成功", returnMap);
                } else {
                    String errMsg = "";
                    JSONObject errObj = errorMap.getJSONObject(result_code);
                    if (errObj != null) {
                        errMsg = errObj.toJSONString();
                        record.setFailReason(errMsg);
                    } else {
                        errMsg = returnMap.get("return_msg");
                        record.setFailReason(errMsg);
                    }
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                }
            }
        } catch (RuntimeException e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        } catch (Exception e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        }
    }

    @Override
    public ResultData createMicroPayOrder(WxMerchantBUser user, WxPayOrder record, EnumPayWay payWay) {
        final IdWorker idworker = IdWorker.get();

        WxAppinfo appInfo = wxAppinfoService.getCAppInfo(user.getTenantId());

        EnumPayShare isShare = EnumPayShare.NO;

        try {
            // 1. check 订单
            WxOrder order = wxOrderMapper.selectById(record.getOrderId());
            if (order == null) {
                logger.error("pay order, order not allow, repaymentReq: " + record.toString() + ", payWay: " + payWay.toString());
                throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND);
            }
            if (order.getOrderStatus() != EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()) {
                logger.error("pay order, order status not allow, repaymentReq: " + order.toString() + " , payWay: " + payWay.toString());
                throw new MallinkException(ErrorCode.ORDER_IS_NOT_PAY);
            }
            if (order.getPaymentType() != EnumPayType.PAY_PAYMENT.getCode()) {
                return new ResultData(ErrorCode.PAY_ORDER_IS_NOT_PAYMENT);
            }
            WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
            if (payAccount.checkShare()) {
                isShare = EnumPayShare.YES;
            }

            // 2. check 是否有支付订单
            Date currentDate = new Date();
            record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode());
            List<WxPayOrder> list = wxPayOrderMapper.findList(record);
            String payOrderNo = "";
            String orderNo = String.valueOf(order.getId());
            if (list.size() <= 0) {
                // 3. 创建支付订单
                Long id = idworker.nextId();
                payOrderNo = String.valueOf(id);
                record.setId(id);
                record.setTenantId(user.getTenantId());
                record.setBUserId(user.getId());
                record.setCreateTime(currentDate);
                record.setUpdateTime(currentDate);
                record.setPayTimeStart(currentDate);
                record.setPayTimeEnd(currentDate);
                // 支付单号
                record.setPayOrderNo(payOrderNo);
                record.setPayAmount(order.getPayment());
                record.setPayVendor(EnumPayWay.PAY_WAY_WEAPP.getCode());
                record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode());
                record.setShare(isShare.getCode());
                if (isShare == EnumPayShare.YES) {
                    // 分账金额
                    int iChargeFee = PayUtils.getPayRate(record.getPayAmount(), payAccount.getRate(), false);
                    Integer share_amount = record.getPayAmount() - iChargeFee;
                    record.setShareAmount(share_amount);
                    if(payAccount.getRealRate() != null) {
                        int iRealChargeFee = PayUtils.getPayRate(record.getPayAmount(), payAccount.getRealRate(), true);
                        record.setRateAmount(iRealChargeFee);
                    }
                    if (share_amount <= 0) {
                        isShare = EnumPayShare.NO;
                        record.setShare(isShare.getCode());
                    }
                }

                int sqlRow = wxPayOrderMapper.insert(record);
                if (sqlRow != 1) {
                    logger.error("pay order insert error: " + record.toString());
                    throw new MallinkException(ErrorCode.DB_FAIL);
                }
            } else {
                record = list.get(0);
                record.setShare(isShare.getCode());
                payOrderNo = String.valueOf(record.getId());
            }

            if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
                // 刷卡支付 普通商户模式
                String noncestr = Utility.generate32UUID();
                WxMicroPayOrderP wxPayOrderP = new WxMicroPayOrderP();
                wxPayOrderP.setAppid(user.getAppId());
                wxPayOrderP.setMch_id(payAccount.getMchId());
                wxPayOrderP.setDevice_info(user.getPhone());
                wxPayOrderP.setNonce_str(noncestr);
                wxPayOrderP.setBody(order.getDetail());
                wxPayOrderP.setOut_trade_no(record.getPayOrderNo());
                wxPayOrderP.setTotal_fee(order.getPayment());
                wxPayOrderP.setSpbill_create_ip(record.getIp());               // 终端IP
                wxPayOrderP.setAuth_code(record.getAuthCode());
                wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
                Date futureDate = new Date();
                futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
                wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate));    // 15分钟后结束
                Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderP);
                wxPayOrderP.setSign(WxPayment.createSign(payOrderMap, payAccount.getApiKey()));
                String response = WxPay.micropay(BeanUtils.toStringMap(wxPayOrderP));
                logger.info("pay order, wechat micropay, " + wxPayOrderP.toString() + ", response: " + response.toString());
                Map<String, String> returnMap = WxPayment.xmlToMap(response);
                returnMap.put("payOrderId", payOrderNo);
                returnMap.put("orderId", orderNo);
                String return_code = returnMap.get("return_code");
                String result_code = returnMap.get("result_code");
                if ("SUCCESS".equalsIgnoreCase(return_code)) {
                    if ("SUCCESS".equals(result_code)) {
                        String openId = returnMap.get("openid");
                        String isSubscribe = returnMap.get("is_subscribe");
                        String transactionId = returnMap.get("transaction_id");
                        record.setTransactionId(transactionId);
                        record.setUpdateTime(new Date());
                        handleMicroOrderPaySuccess(record, transactionId, openId, isSubscribe);
                        return new ResultData(Result.SUCCESS, "刷卡支付成功", returnMap);
                    } else {
                        String err_code = returnMap.get("err_code");
                        String errMsg = returnMap.get("err_code_des");
                        if (errMsg.length() <= 0) {
                            errMsg = returnMap.get("return_msg");
                        }
                        record.setFailReason(errMsg);
                        record.setUpdateTime(new Date());
                        try {
                            wxPayOrderMapper.updateById(record);
                        } catch (Exception e) {
                            logger.error("pay order update error: " + record.toString());
                            throw new MallinkException(ErrorCode.DB_FAIL);
                        }
                        return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                    }
                } else {
                    String errMsg = returnMap.get("return_msg");
                    record.setFailReason(errMsg);
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                }
            } else {
                // 统一下单 // 服务商模式
                String noncestr = Utility.generate32UUID();
                WxMicroPayOrderSP wxPayOrderSP = new WxMicroPayOrderSP();
                wxPayOrderSP.setAppid(appInfo.getParentAppId());
                wxPayOrderSP.setMch_id(payAccount.getMchId());
                wxPayOrderSP.setSub_appid(appInfo.getAppId());
                wxPayOrderSP.setSub_mch_id(payAccount.getSubMchId());
                wxPayOrderSP.setDevice_info(user.getPhone());
                wxPayOrderSP.setNonce_str(noncestr);
                wxPayOrderSP.setBody(order.getDetail());
                wxPayOrderSP.setOut_trade_no(record.getPayOrderNo());
                wxPayOrderSP.setTotal_fee(order.getPayment());
                wxPayOrderSP.setSpbill_create_ip(record.getIp());
                wxPayOrderSP.setAuth_code(record.getAuthCode());
                wxPayOrderSP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate));
                Date futureDate = new Date();
                futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000);
                wxPayOrderSP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate));    // 15分钟后结束
                wxPayOrderSP.setSign_type("HMAC-SHA256");
                wxPayOrderSP.setProfit_sharing(null);
                if (isShare == EnumPayShare.YES) {
                    wxPayOrderSP.setProfit_sharing("Y");
                }
                Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderSP);

                wxPayOrderSP.setSign(WxPayment.createSignHMAC(payOrderMap, payAccount.getApiKey()));
                String response = WxPay.micropay(BeanUtils.toStringMap(wxPayOrderSP));
                logger.info("pay order, wechat micropay, " + wxPayOrderSP.toString() + ", response: " + response.toString());
                Map<String, String> returnMap = WxPayment.xmlToMap(response);
                returnMap.put("payOrderId", payOrderNo);
                returnMap.put("orderId", orderNo);
                String return_code = returnMap.get("return_code");
                String result_code = returnMap.get("result_code");
                if ("SUCCESS".equalsIgnoreCase(return_code)) {
                    if ("SUCCESS".equals(result_code)) {
                        String openId = returnMap.get("sub_openid");
                        String isSubscribe = returnMap.get("sub_is_subscribe");
                        String transactionId = returnMap.get("transaction_id");
                        record.setTransactionId(transactionId);
                        record.setUpdateTime(new Date());
                        handleMicroOrderPaySuccess(record, transactionId, openId, isSubscribe);
                        return new ResultData(Result.SUCCESS, "刷卡支付成功", returnMap);
                    } else {
                        String err_code = returnMap.get("err_code");
                        String errMsg = returnMap.get("err_code_des");
                        if (errMsg.length() <= 0) {
                            errMsg = returnMap.get("return_msg");
                        }
                        record.setFailReason(errMsg);
                        record.setUpdateTime(new Date());
                        try {
                            wxPayOrderMapper.updateById(record);
                        } catch (Exception e) {
                            logger.error("pay order update error: " + record.toString());
                            throw new MallinkException(ErrorCode.DB_FAIL);
                        }
                        return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                    }
                } else {
                    String errMsg = returnMap.get("return_msg");
                    record.setFailReason(errMsg);
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                }
            }
        } catch (RuntimeException e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        } catch (Exception e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        }
    }


    private String wechatPayOrderQuery(WxAppinfo appInfo, WxPayOrder record) {
        // get payAccount
        WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
        if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
            // 普通商户号模式
            WxPayOrderQ payOrderQ = new WxPayOrderQ();
            String noncestr = Utility.generate32UUID();
            payOrderQ.setAppid(appInfo.getAppId());
            payOrderQ.setMch_id(payAccount.getMchId());
            payOrderQ.setNonce_str(noncestr);
            payOrderQ.setOut_trade_no(record.getPayOrderNo());

            try {
                Map map = BeanUtils.toStringMap(payOrderQ);
                payOrderQ.setSign(WxPayment.createSign(map, payAccount.getApiKey()));
                map = BeanUtils.toStringMap(payOrderQ);
                String response = WxPay.orderQuery(map);
                return response;
            } catch (RuntimeException e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            } catch (Exception e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            }
        } else {
            // 服务商模式
            WxPayOrderSQ payOrderSQ = new WxPayOrderSQ();
            String noncestr = Utility.generate32UUID();
            payOrderSQ.setAppid(appInfo.getParentAppId());
            payOrderSQ.setSub_appid(appInfo.getAppId());
            payOrderSQ.setMch_id(payAccount.getMchId());
            payOrderSQ.setSub_mch_id(payAccount.getSubMchId());
            payOrderSQ.setNonce_str(noncestr);
            payOrderSQ.setOut_trade_no(record.getPayOrderNo());
            payOrderSQ.setSign_type("HMAC-SHA256");

            try {
                Map map = BeanUtils.toStringMap(payOrderSQ);
                payOrderSQ.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey()));
                map = BeanUtils.toStringMap(payOrderSQ);

                String response = WxPay.orderQuery(map);
                return response;
            } catch (RuntimeException e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            } catch (Exception e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            }
        }
    }

    /**
     * 微信订单查询
     */
    @Override
    public ResultData payOrderQuery(WxPayOrder record) {

        try {
            if (StringUtils.isBlank(record.getPayOrderNo())) {
                record.setPayOrderNo(String.valueOf(record.getId()));
            }
            WxPayOrder payOrder = wxPayOrderMapper.selectById(record.getId());
            if (payOrder != null) {
                record.setPayOrderStatus(payOrder.getPayOrderStatus());
            } else {
                return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), "payOrder not found");
            }

            WxOrder order = wxOrderMapper.selectById(record.getOrderId());
            if (order == null) {
                return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), "Order not found");
            }

            WxAppinfo appInfo = wxAppinfoService.getCAppInfo(record.getTenantId());

            String response = wechatPayOrderQuery(appInfo, record);

            logger.info("pay order query, " + record.toString() + ", response: " + response);
            Map<String, String> returnMap = WxPayment.xmlToMap(response);
            String return_code = returnMap.get("return_code");
            String result_code = returnMap.get("result_code");
            if ("SUCCESS".equalsIgnoreCase(return_code)) {
                if ("SUCCESS".equals(result_code)) {
                    String trade_state = returnMap.get("trade_state");
                    //SUCCESS—支付成功
                    //REFUND—转入退款
                    //NOTPAY—未支付
                    //CLOSED—已关闭
                    //REVOKED—已撤销（刷卡支付）
                    //USERPAYING--用户支付中
                    //PAYERROR--支付失败(其他原因，如银行返回失败)
                    if ("SUCCESS".equals(trade_state)) {
                        String openId = returnMap.get("sub_openid");
                        String sub_is_subscribe = returnMap.get("sub_is_subscribe");
                        String transactionId = returnMap.get("transaction_id");
                        String tradeType = returnMap.get("trade_type");
                        if ("MICROPAY".equals(tradeType)) {
                            handleMicroOrderPaySuccess(record, transactionId, openId, sub_is_subscribe);
                        } else {
                            handleOrderPaySuccess(record, transactionId, EnumPayEndFrom.QUERY.getCode());
                        }
                        return new ResultData(Result.SUCCESS, "订单支付成功", returnMap);
                    } else if ("REFUND".equals(trade_state)) {
                        record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_REFUND.getCode());
                        // handlePayOrderStatusUpdate(record);
                        return new ResultData(ErrorCode.PAY_ORDER_REFUND, returnMap);
                    } else if ("NOTPAY".equals(trade_state)) {
                        record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_NOTPAY.getCode());
                        //handlePayOrderStatusUpdate(record);
                        return new ResultData(ErrorCode.PAY_ORDER_NOT_PAY, returnMap);
                    } else if ("CLOSED".equals(trade_state)) {
                        record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_CLOSE.getCode());
                        ///handlePayOrderStatusUpdate(record);
                        return new ResultData(ErrorCode.PAY_ORDER_CLOSED, returnMap);
                    } else if ("REVOKED".equals(trade_state)) {
                        record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_REVERSE.getCode());
                        // handlePayOrderStatusUpdate(record);
                        return new ResultData(ErrorCode.PAY_ORDER_REVERSE, returnMap);
                    } else if ("USERPAYING".equals(trade_state)) {
                        record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode());
                        // handlePayOrderStatusUpdate(record);
                        return new ResultData(ErrorCode.PAY_ORDER_PAYING, returnMap);
                    } else {
                        record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_FAIL.getCode());
                        // handlePayOrderStatusUpdate(record);
                        return new ResultData(ErrorCode.PAY_ORDER_ERROR, returnMap);
                    }
                } else {
                    String errMsg = "";
                    JSONObject errObj = errorMapQuery.getJSONObject(result_code);
                    if (errObj != null) {
                        errMsg = errObj.toJSONString();
                        record.setFailReason(errMsg);
                    } else {
                        errMsg = returnMap.get("return_msg");
                        record.setFailReason(errMsg);
                    }
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                }
            } else {
                String errMsg = returnMap.get("return_msg");
                record.setFailReason(errMsg);
                record.setUpdateTime(new Date());
                try {
                    wxPayOrderMapper.updateById(record);
                } catch (Exception e) {
                    logger.error("pay order update error: " + record.toString());
                    throw new MallinkException(ErrorCode.DB_FAIL);
                }
                return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
            }
        } catch (MallinkException e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        } catch (RuntimeException e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        } catch (Exception e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        }
    }

    private String wechatPayOrderClose(WxAppinfo appInfo, WxPayOrder record) {
        // get payAccount
        WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
        if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
            // 普通商户号模式
            WxPayOrderQ payOrderC = new WxPayOrderQ();
            String noncestr = Utility.generate32UUID();
            payOrderC.setAppid(appInfo.getAppId());
            payOrderC.setMch_id(payAccount.getMchId());
            payOrderC.setNonce_str(noncestr);
            payOrderC.setOut_trade_no(record.getPayOrderNo());

            try {
                Map map = BeanUtils.toStringMap(payOrderC);
                payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey()));
                map = BeanUtils.toStringMap(payOrderC);
                String response = WxPay.closeOrder(map);
                logger.info("request:" + map.toString() + "\nresponse:" + response);
                return response;
            } catch (RuntimeException e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            } catch (Exception e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            }
        } else {
            // 服务商模式
            WxPayOrderSQ payOrderSC = new WxPayOrderSQ();
            String noncestr = Utility.generate32UUID();
            payOrderSC.setAppid(appInfo.getParentAppId());
            payOrderSC.setSub_appid(appInfo.getAppId());
            payOrderSC.setMch_id(payAccount.getMchId());
            payOrderSC.setSub_mch_id(payAccount.getSubMchId());
            payOrderSC.setNonce_str(noncestr);
            payOrderSC.setOut_trade_no(record.getPayOrderNo());
            payOrderSC.setSign_type("HMAC-SHA256");

            try {
                Map map = BeanUtils.toStringMap(payOrderSC);
                payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey()));
                map = BeanUtils.toStringMap(payOrderSC);
                String response = WxPay.closeOrder(map);
                logger.info("request:" + map.toString() + "\nresponse:" + response);
                return response;
            } catch (RuntimeException e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            } catch (Exception e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            }
        }
    }

    /**
     * 微信关闭支付订单
     */
    @Override
    public ResultData payOrderClose(WxAppinfo appInfo, WxPayOrder record) {

        try {
            String response = wechatPayOrderClose(appInfo, record);

            logger.info("pay order close, " + record.toString() + ", response: " + response);
            Map<String, String> returnMap = WxPayment.xmlToMap(response);
            String return_code = returnMap.get("return_code");
            String result_code = returnMap.get("result_code");
            if ("SUCCESS".equalsIgnoreCase(return_code)) {
                if ("SUCCESS".equals(result_code)) {
                    record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_CANCEL.getCode());
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order 关单:{} 成功", record.getId());
                    }
                    return new ResultData(Result.SUCCESS, "支付订单关闭成功", returnMap);
                } else {
                    String errMsg = "";
                    JSONObject errObj = errorMapClose.getJSONObject(result_code);
                    if (errObj != null) {
                        errMsg = errObj.toJSONString();
                    } else {
                        errMsg = returnMap.get("return_msg");
                    }
                    record.setFailReason(errMsg);
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                }
            } else {
                String errMsg = returnMap.get("return_msg");
                record.setFailReason(errMsg);
                record.setUpdateTime(new Date());
                try {
                    wxPayOrderMapper.updateById(record);
                } catch (Exception e) {
                    logger.error("pay order update error: " + record.toString());
                    throw new MallinkException(ErrorCode.DB_FAIL);
                }
                return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
            }
        } catch (RuntimeException e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        } catch (Exception e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        }
    }

    private String wechatPayOrderReverse(WxAppinfo appInfo, WxPayOrder record) {
        // get payAccount
        WxPayAccount payAccount = wxPayAccountMapper.selectById(appInfo.getPayId());
        if (payAccount.getType() == EnumPayMode.MCH.getCode()) {
            // 普通商户号模式
            WxPayOrderQ payOrderC = new WxPayOrderQ();
            String noncestr = Utility.generate32UUID();
            payOrderC.setAppid(appInfo.getAppId());
            payOrderC.setMch_id(payAccount.getMchId());
            payOrderC.setNonce_str(noncestr);
            payOrderC.setOut_trade_no(record.getPayOrderNo());

            try {
                Map map = BeanUtils.toStringMap(payOrderC);
                payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey()));
                map = BeanUtils.toStringMap(payOrderC);
                String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId());
                logger.info("request:" + map.toString() + "\nresponse:" + response);
                return response;
            } catch (RuntimeException e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            } catch (Exception e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            }
        } else {
            // 服务商模式
            WxPayOrderSQ payOrderSC = new WxPayOrderSQ();
            String noncestr = Utility.generate32UUID();
            payOrderSC.setAppid(appInfo.getParentAppId());
            payOrderSC.setSub_appid(appInfo.getAppId());
            payOrderSC.setMch_id(payAccount.getMchId());
            payOrderSC.setSub_mch_id(payAccount.getSubMchId());
            payOrderSC.setNonce_str(noncestr);
            payOrderSC.setOut_trade_no(record.getPayOrderNo());
            payOrderSC.setSign_type("HMAC-SHA256");

            try {
                Map map = BeanUtils.toStringMap(payOrderSC);
                payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey()));
                map = BeanUtils.toStringMap(payOrderSC);
                String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId());
                logger.info("request:" + map.toString() + "\nresponse:" + response);
                return response;
            } catch (RuntimeException e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            } catch (Exception e) {
                throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
            }
        }
    }

    /**
     * 撤销订单 - 刷卡支付
     */
    @Override
    public ResultData payOrderReverse(WxPayOrder record) {

        WxAppinfo appInfo = wxAppinfoService.getCAppInfo(record.getTenantId());

        try {
            String response = wechatPayOrderReverse(appInfo, record);

            logger.info("pay order reverse, " + record.toString() + ", response: " + response);
            Map<String, String> returnMap = WxPayment.xmlToMap(response);
            String return_code = returnMap.get("return_code");
            String result_code = returnMap.get("result_code");
            if ("SUCCESS".equalsIgnoreCase(return_code)) {
                if ("SUCCESS".equals(result_code)) {
                    record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_REVERSE.getCode());
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    WxOrder order = new WxOrder();
                    order.setId(record.getOrderId());
                    order.setType(EnumOrderType.MICROPAY.getCode());
                    order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL.getCode());
                    order.setUpdateDate(new Date());
                    try {
                        wxOrderMapper.updateById(order);
                    } catch (Exception e) {
                        logger.error("order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(Result.SUCCESS, "订单撤销成功", returnMap);
                } else {
                    String errMsg = "";
                    JSONObject errObj = errorMapClose.getJSONObject(result_code);
                    if (errObj != null) {
                        errMsg = errObj.toJSONString();
                    } else {
                        errMsg = returnMap.get("return_msg");
                    }
                    record.setFailReason(errMsg);
                    record.setUpdateTime(new Date());
                    try {
                        wxPayOrderMapper.updateById(record);
                    } catch (Exception e) {
                        logger.error("pay order update error: " + record.toString());
                        throw new MallinkException(ErrorCode.DB_FAIL);
                    }
                    return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
                }
            } else {
                String errMsg = returnMap.get("return_msg");
                record.setFailReason(errMsg);
                record.setUpdateTime(new Date());
                try {
                    wxPayOrderMapper.updateById(record);
                } catch (Exception e) {
                    logger.error("pay order update error: " + record.toString());
                    throw new MallinkException(ErrorCode.DB_FAIL);
                }
                return new ResultData(ErrorCode.PAY_ORDER_ERROR.getCode(), errMsg, returnMap);
            }

        } catch (RuntimeException e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        } catch (Exception e) {
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
        }
    }


    /**
     * 提供微信支付回调调用
     *
     * @param paramMap 异步通知参数
     * @param payWay   支付方式
     * @return
     */
    @Override
    public String notify(Map<String, String> paramMap, EnumPayWay payWay) {
        // how to get wechatAppId, wechatMchId, partnerKey
        String appId = paramMap.get("appid");
        String subAppId = paramMap.get("sub_appid");
        String mchId = paramMap.get("mch_id");
        String subMchId = paramMap.get("sub_mch_id");
        WxAppinfo appinfo = null;
        boolean isNormal = true;
        if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) {
            // 普通商户号
            appinfo = wxAppinfoMapper.findByAppId(appId);
            if (appinfo == null) {
                logger.error("appid not found: " + appId);
                throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND);
            }
            isNormal = true;
        } else {
            // 服务号 现在用hmac-sha256
            appinfo = wxAppinfoMapper.findByAppId(subAppId);
            if (appinfo == null) {
                logger.error("subappid not found: " + subAppId);
                throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND);
            }
            isNormal = false;
        }

        WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId());
        if (payAccount == null) {
            throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND);
        }
        String partnerKey = payAccount.getApiKey();
        try {
            if (payWay == EnumPayWay.PAY_WAY_WEAPP) {
                boolean signVerified = false;
                if (isNormal) {
                    // 普通商户号支付
                    signVerified = WxPayment.verifyNotify(paramMap, partnerKey);
                    if (!signVerified) {
                        logger.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ",  payWay:" + payWay.toString());
                        throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR);
                    }
                } else {
                    // 服务号 现在用hmac-sha256
                    signVerified = WxPayment.verifyNotifyHMAC(paramMap, partnerKey);
                    if (!signVerified) {
                        logger.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ",  payWay:" + payWay.toString());
                        throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR);
                    }
                }

                if (!"SUCCESS".equals(paramMap.get("return_code"))) {
                    logger.warn("notify order, wxpay status not success, paramMap: " + paramMap.toString() + ",  payWay:" + payWay.toString());
                    SortedMap resultMap = new TreeMap();
                    resultMap.put("return_code", "FAIL");
                    resultMap.put("return_msg", "订单状态码非SUCCESS");
                    return XmlUtil.getRequestXml(resultMap);
                }

                String payOrderNo = paramMap.get("out_trade_no");
                String timEndStr = paramMap.get("time_end");
                Long payOrderId = Long.valueOf(payOrderNo);
                WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId);
                if (payOrder == null) {
                    logger.warn("notify order, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ",  payWay:" + payWay.toString());
                    SortedMap resultMap = new TreeMap();
                    resultMap.put("return_code", "FAIL");
                    resultMap.put("return_msg", "订单不存在");
                    return XmlUtil.getRequestXml(resultMap);
                }
                // 验证支付金额
                if (!paramMap.get("total_fee").equals(payOrder.getPayAmount().toString())) {
                    logger.warn("notify order, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ",  payWay:" + payWay.toString());
                    SortedMap resultMap = new TreeMap();
                    resultMap.put("return_code", "FAIL");
                    resultMap.put("return_msg", "订单总金额不一致");
                    return XmlUtil.getRequestXml(resultMap);
                }

                Date timeEnd = null;

                try {
                    timeEnd = Utility.getDateFromString(timEndStr);
                } catch (ParseException e) {
                    logger.error("解析timeEnd失败");
                    timeEnd = new Date();
                }
                payOrder.setPayTimeEnd(timeEnd);
                payOrder.setPayEndFrom(EnumPayEndFrom.CALLBACK.getCode());

                // 处理支付成功
                handleOrderPaySuccess(payOrder, paramMap.get("transaction_id"), EnumPayEndFrom.CALLBACK.getCode());
                logger.info("notify order, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ",  payWay:" + payWay.toString());
                SortedMap resultMap = new TreeMap();
                resultMap.put("return_code", "SUCCESS");
                resultMap.put("return_msg", "OK");
                return XmlUtil.getRequestXml(resultMap);
            }
        } catch (RuntimeException e) {
            logger.warn("notify order, checksign error, paramMap: " + paramMap.toString() + ",  payWay:" + payWay.toString() + ", e:" + e.getMessage());
            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR);
        }

        SortedMap resultMap = new TreeMap();
        resultMap.put("return_code", "FAIL");
        resultMap.put("return_msg", "FAILED");
        return XmlUtil.getRequestXml(resultMap);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void handleOrderPaySuccess(WxPayOrder record, String transactionId, Integer from) { // from 0:callback, 1:query
        Date currentDate = new Date();
        EnumPayStatus payStatus = EnumPayStatus.getEnum(record.getPayOrderStatus());
        // 判断支付状态
        if (payStatus == EnumPayStatus.PAY_STATUS_SUCCESS) {
            // 已经是成功状态，只更新transactionId
            try {
                WxPayOrder updateT = new WxPayOrder();
                updateT.setId(record.getId());
                updateT.setUpdateTime(currentDate);
                updateT.setTransactionId(transactionId);
                wxPayOrderMapper.updateById(record);
            } catch (Exception e) {
                logger.error(e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL);
            }
            return;
        }
        if (payStatus != EnumPayStatus.PAY_STATUS_WAIT) {
            logger.info("pay success handle, payOrder " + record.getPayOrderNo() +
                    "is paid success , orderId : " + record.getOrderId());
            return;
        }
        WxOrder order = wxOrderMapper.selectById(record.getOrderId());
        if (order == null) {
            logger.error("pay success handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo());
            throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND);
        }


        // 修改支付订单状态
        WxPayOrder updateOrder = new WxPayOrder();
        updateOrder.setId(record.getId());
        updateOrder.setTenantId(record.getTenantId());
        updateOrder.setOrderId(record.getOrderId());
        updateOrder.setUpdateTime(currentDate);
        updateOrder.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode());
        updateOrder.setTransactionId(transactionId);
        try {
            wxPayOrderMapper.updateById(updateOrder);
        } catch (Exception e) {
            logger.error("支付订单数据库更新失败: " + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "支付订单数据库更新失败: " + e.getMessage());
        }

        Long productId = order.getProductId();
        WxCoupon wxCoupon = wxCouponMapper.selectById(productId);
        if(wxCoupon != null) {
            if (isOrderGroupCoupon(record, wxCoupon)) {
                // 如果是Coupon是拼团, 创建拼团信息, 不创建COUPON_ORDER
                try {
                    wxOrderGroupService.createOrderGroup(order, wxCoupon);
                } catch (Exception e) {
                    logger.error("参团失败" + e.getMessage());
                    order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_FAILD.getCode());
                    order.setUpdateDate(new Date());
                    wxOrderMapper.updateById(order);
                    throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD);
                }
            } else {
                // 普通券, 修改订单状态
                try {
                    wxOrderService.couponOrderSuccess(order);
                } catch (Exception e) {
                    logger.error(e.getMessage());
                    throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "订单更新");
                }
                // 下订单完成，发送内部消息
                try {
                    wxOrderService.sendOrderSuccessActionMsg(order);
                } catch (Exception e) {
                    logger.error("内部消息发送失败: " + e.getMessage());
                    throw new MallinkException(ErrorCode.MSG_INSIDE_ERROR);
                }
            }
        }
    }

    private boolean isOrderGroupCoupon(WxPayOrder record, WxCoupon wxCoupon) {
        return wxCoupon.getType().equals(EnumCouponType.COUPON_GROUP.getCode()) && wxCoupon.getSalePrice().equals(record.getPayAmount());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void handleMicroOrderPaySuccess(WxPayOrder record, String transactionId, String openId, String isSubscribe) {
        Date currentDate = new Date();
        EnumPayStatus payStatus = EnumPayStatus.getEnum(record.getPayOrderStatus());
        // 判断支付状态
        if (payStatus == EnumPayStatus.PAY_STATUS_SUCCESS) {
            // 已经是成功状态，只更新transactionId
            try {
                record.setUpdateTime(currentDate);
                record.setTransactionId(transactionId);
                record.setFailReason("");
                wxPayOrderMapper.updateById(record);
            } catch (Exception e) {
                logger.error("更新transactionId: " + e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL);
            }
            return;
        }
        if (payStatus != EnumPayStatus.PAY_STATUS_WAIT) {
            logger.info("pay success handle, payOrder " + record.getPayOrderNo() +
                    "is paid success , orderId : " + record.getOrderId());
            return;
        }

        WxOrder order = wxOrderMapper.selectById(record.getOrderId());
        if (order == null) {
            logger.error("pay success handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo());
            throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND);
        }

        WxAppinfo appinfo = wxAppinfoService.getCAppInfo(order.getTenantId());

        // add c_user
        Date curDate = new Date();
        WxCUser userQ = new WxCUser();
        userQ.setOpenId(openId);
        userQ.setAppId(appinfo.getAppId());
        WxCUser user1 = wxCUserMapper.findByOpenId(userQ);
        if (user1 == null) {
            userQ.setCreateDate(curDate);
            userQ.setUpdateDate(curDate);
            if ("N".equalsIgnoreCase(isSubscribe)) {
                userQ.setIsSubscribe(EnumUserIsSubscribe.NO.getCode());
            } else {
                userQ.setIsSubscribe(EnumUserIsSubscribe.YES.getCode());
            }
            wxCUserService.saveOrUpdate(userQ);
        } else {
            userQ.setId(user1.getId());
            userQ.setUpdateDate(curDate);
            userQ.setLoginCount(user1.getLoginCount());
            if ("N".equalsIgnoreCase(isSubscribe)) {
                userQ.setIsSubscribe(EnumUserIsSubscribe.NO.getCode());
            } else {
                userQ.setIsSubscribe(EnumUserIsSubscribe.YES.getCode());
            }
            wxCUserService.saveOrUpdate(userQ);
        }
        record.setCUserId(userQ.getId());

        // 修改支付订单状态
        WxPayOrder updateOrder = new WxPayOrder();
        updateOrder.setId(record.getId());
        updateOrder.setOrderId(record.getOrderId());
        updateOrder.setCUserId(userQ.getId());
        updateOrder.setUpdateTime(currentDate);
        updateOrder.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode());
        updateOrder.setTransactionId(transactionId);
        updateOrder.setFailReason("");
        try {
            wxPayOrderMapper.updateById(updateOrder);
        } catch (Exception e) {
            logger.error("支付订单数据库更新失败: " + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "支付订单数据库更新失败: " + e.getMessage());
        }

        // 修改订单状态
        order.setCUserId(userQ.getId());
        try {
            int _count = wxOrderService.microPayOrderSuccess(order);
            if (_count > 1) {
                logger.error("order micro pay count > 1");
                throw new MallinkException(ErrorCode.ORDER_IS_FAIL);
            }
        } catch (Exception e) {
            logger.error("order status : " + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "订单更新");
        }

        // B端刷卡支付发券
        logger.info("订单刷卡发券 开始");
        try {
            wxCouponOrderService.sendCouponAfterMicroPay(record.getTenantId(), record.getOrderId(), record.getCUserId());
        } catch (Exception e) {
            logger.error("订单刷卡发券失败: orderId: {}, payOrderId: {}", record.getOrderId(), record.getId());
            logger.error("订单刷卡发券失败: " + e.getMessage());
        }
        logger.info("订单刷卡发券 结束");

        if (record.getShare().equals(EnumPayShare.NO.getCode())) {
            //结算记录
            try {
                createMerchantSubsidy(record, order, curDate);
            } catch (Exception e) {
                logger.error("收银台结算记录失败,{}", e.getMessage());
            }
        } else {
            // 延迟10秒后分账
            new Thread(() -> {
                String tenantId = record.getTenantId();
                Long orderId = record.getOrderId();
                Long payOrderId = record.getId();
                try {
                    Thread.currentThread().sleep(10000);
                } catch (Exception e) {
                    logger.error("sleep error: " + e.getMessage());
                }

                // 支付分账
                logger.info("订单分账开始: orderId: {}, payOrderId: {}", orderId, payOrderId);
                try {
                    wxOrderService.shareForMicroPay(tenantId, orderId, payOrderId);
                } catch (MallinkException e) {
                    logger.error("订单分账失败: orderId: {}, payOrderId: {}", orderId, payOrderId);
                    logger.error("订单分账失败: " + e.getMessage());
                }
                logger.info("订单分账结束: orderId: {}, payOrderId: {}", orderId, payOrderId);
            }).start();
        }
    }

    public void createMerchantSubsidy(WxPayOrder record, WxOrder order, Date curDate) {
        final IdWorker idWorker = IdWorker.get();
        WxMerchantSubsidy merchantSubsidy = new WxMerchantSubsidy();
        merchantSubsidy.setId(idWorker.nextId());
        merchantSubsidy.setTenantId(record.getTenantId());
        merchantSubsidy.setOrderId(record.getOrderId());
        merchantSubsidy.setOrderType(EnumOrderType.NATIVEPAY.getCode());
        WxMerchantBUser wxMerchantBUser = wxMerchantBUserMapper.selectById(order.getProductId());
        merchantSubsidy.setMerchantId(wxMerchantBUser.getMerchantId());
        merchantSubsidy.setCouponOrderId(0L);
        merchantSubsidy.setCouponType(0);
        merchantSubsidy.setOrderPayment(record.getPayAmount());
        merchantSubsidy.setReceiverPayment(record.getPayAmount());
        merchantSubsidy.setRealPayment(record.getPayAmount());
        merchantSubsidy.setSubsidy(record.getPayAmount());
        merchantSubsidy.setRealSubsidy(record.getPayAmount());
        merchantSubsidy.setCreateDate(curDate);
        merchantSubsidy.setUpdateDate(curDate);
        merchantSubsidy.setType(EnumMerchantSubsidyType.WECHAT.getCode());
        merchantSubsidy.setSource(EnumMerchantSubsidySource.CASHIER.getCode());
        wxMerchantSubsidyMapper.insert(merchantSubsidy);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class})
    public void handlePayOrderFail(WxPayOrder record, int status) {
        // 判断支付状态
        if (record.getPayOrderStatus() == EnumPayStatus.PAY_STATUS_WAIT.getCode()) {
            logger.error("pay handle, payOrder " + record.getPayOrderNo() +
                    "is complete, orderId : " + record.getOrderId());
            return;
        }
        WxOrder order = wxOrderMapper.selectById(record.getOrderId());
        if (order == null) {
            logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo());
            throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND);
        }
        if (order.getType().equals(EnumOrderType.COUPON.getCode())) {
            WxCUser user = wxCUserMapper.selectById(order.getCUserId());
            if (user == null) {
                logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo());
                throw new MallinkException(ErrorCode.USER_IS_EMPTY);
            }
        }

        if (order.getPayment() > 0) {
            // 订单金额不为0时, 支付订单未创建, 返回异常
            if (!(record.getId() > 0)) {
                logger.error("支付订单未创建, 订单ID:" + order.getId());
                throw new MallinkException(ErrorCode.PAY_ORDER_NOT_FOUND);
            }
        }

        if (record.getId() > 0) {
            // 有价券
            if (EnumPayStatus.PAY_STATUS_FAIL.getCode() == status) {
                // 1. get appinfo
                WxAppinfo appInfo = wxAppinfoService.getCAppInfo(order.getTenantId());
                // 前端支付取消,
                // 回调未返回，主动检查支付订单状态
                try {
                    record.setPayOrderNo(String.valueOf(record.getId()));
                    String response = wechatPayOrderQuery(appInfo, record);

                    logger.info("pay order query, " + record.toString() + ", response: " + response);
                    Map<String, String> returnMap = WxPayment.xmlToMap(response);
                    String result_code = returnMap.get("result_code");
                    if ("SUCCESS".equals(result_code)) {
                        String trade_state = returnMap.get("trade_state");
                        //SUCCESS—支付成功
                        //REFUND—转入退款
                        //NOTPAY—未支付
                        //CLOSED—已关闭
                        //REVOKED—已撤销（刷卡支付）
                        //USERPAYING--用户支付中
                        //PAYERROR--支付失败(其他原因，如银行返回失败)
                        if ("SUCCESS".equals(trade_state)) {
                            // 查询支付订单 -- 已支付
                            // 继续更改状态
                        } else if ("USERPAYING".equals(trade_state)) {
                            // 继续检查状态
                        } else {
                            // 支付订单未成功，返回异常
                            record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_FAIL.getCode());
                            try {
                                wxPayOrderMapper.updateById(record);
                            } catch (Exception e) {
                                logger.error("支付订单失败状态更新异常: " + e.getMessage());
                            }
                            throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "支付订单未成功");
                        }
                    }
                } catch (MallinkException e) {
                    throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
                } catch (RuntimeException e) {
                    throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
                } catch (Exception e) {
                    throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage());
                }
            }
        }

        // 修改订单状态
        if (record.getPayOrderStatus() == EnumPayStatus.PAY_STATUS_SUCCESS.getCode()) {
            /*
            try {
                int _count = wxOrderService.couponOrderSuccess(order);
                if (_count > 1) {
                    throw new MallinkException(ErrorCode.ORDER_IS_FAIL);
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "订单更新");
            }
            */
        } else if (record.getPayOrderStatus() == EnumPayStatus.PAY_STATUS_CANCEL.getCode()) {
            try {
                int _count = wxOrderService.updateOrderStatus(order, EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL);
                if (_count > 1) {
                    throw new MallinkException(ErrorCode.ORDER_IS_FAIL);
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL);
            }
        }
        /*
        Map<String, String> msgMap = new HashMap<>();
        try {
            msgMap.put("name", String.valueOf(order.getCouponId()));
            msgMap.put("orderNo", String.valueOf(order.getId()));
            msgMap.put("createTime", Utility.getDataFormatString3(order.getCreateDate()));
            msgMap.put("standingTime", order.getCreateDate() + "-" + currentDate );
            // 短信 通知 商户
            //smsSenderHandler.sendSms("SMS_18195394", order.getMobile(), msgMap);
        } catch (Exception e) {
            logger.error("pay success handle, sms send exception, payOrderi: " + updatePayOrder+ ", msgMap: " + msgMap.toString() + ", e: " + e.getMessage());
        }
        */
    }

    @Override
    public void handlePayOrderStatusUpdateFree(WxPayOrder record) {
        //检查数据合理性
        WxOrder order = wxOrderMapper.selectById(record.getOrderId());
        if (order == null) {
            logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo());
            throw new MallinkException(ErrorCode.ORDER_IS_NOT_FIND);
        }
        if (order.getType().equals(EnumOrderType.COUPON.getCode())) {
            WxCUser user = wxCUserMapper.selectById(order.getCUserId());
            if (user == null) {
                logger.error("pay handle, order " + record.getOrderId() + " not found , payOrderid : " + record.getPayOrderNo());
                throw new MallinkException(ErrorCode.USER_IS_EMPTY);
            }
        }
    }

    private WxAppinfo getWxAppinfo(Integer orderType, String tenentId) {
        WxAppinfo appInfo = null;
        WxAppinfo appinfoQ = new WxAppinfo();
        appinfoQ.setTenantId(tenentId);
        appinfoQ.setType(EnumAppType.C.getCode());
        List<WxAppinfo> appList = wxAppinfoMapper.selectList(new QueryWrapper(appinfoQ));
        if (appList.size() > 0) {
            appInfo = appList.get(0);
        }
        return appInfo;
    }


    @Override
    public PageInfo<WxPayOrder> listAsPage(WxPayOrder record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxPayOrderMapper.findList(record));
    }

    @Override
    public WxPayOrder getById(Long id) {
        return wxPayOrderMapper.selectById(id);
    }

    @Override
    public WxPayOrder getByObj(WxPayOrder payOrderQ) {
        List<WxPayOrder> list = wxPayOrderMapper.findList(payOrderQ);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public void saveOrUpdate(WxPayOrder record) {
        if (record.getId() == null) {
            //record.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            final IdWorker idWorker = IdWorker.get();
            record.setId(idWorker.nextId());
            wxPayOrderMapper.insert(record);
        } else {
            wxPayOrderMapper.updateById(record);
        }
    }

    @Override
    public void deleteById(Long id) {
        wxPayOrderMapper.deleteById(id);
    }


}
