package cn.pluss.platform.pay.impl;


import cn.pluss.platform.api.Result;
import cn.pluss.platform.api.ResultCode;
import cn.pluss.platform.api.ResultGenerator;
import cn.pluss.platform.appletInfo.AppletInfoService;
import cn.pluss.platform.constants.Constant;
import cn.pluss.platform.device.MercOrderNewService;
import cn.pluss.platform.entitiy.SettleTypeEnum;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.enums.DeviceOrderStatus;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.exception.PayRiskException;
import cn.pluss.platform.ipLocation.IpLocationService;
import cn.pluss.platform.jft.JftMercBaseInfoService;
import cn.pluss.platform.jft.JftReceiptOrderService;
import cn.pluss.platform.mapper.*;
import cn.pluss.platform.mercOrderToken.MercOrderTokenService;
import cn.pluss.platform.merchant.JftMercPaymentChannelService;
import cn.pluss.platform.merchant.MerchantCashPlaceService;
import cn.pluss.platform.merchant.MerchantRateNewService;
import cn.pluss.platform.merchant.MerchantService;
import cn.pluss.platform.merchantChannelStatus.MerchantChannelStatusService;
import cn.pluss.platform.merchantOrder.MerchantOrderService;
import cn.pluss.platform.mswitch.CommonSwitchService;
import cn.pluss.platform.pay.ApiPayService;
import cn.pluss.platform.pay.PayService;
import cn.pluss.platform.refundOrder.MerchantRefundOrderService;
import cn.pluss.platform.ryx.pay.RyxPayService;
import cn.pluss.platform.sxf.pay.SxfPayService;
import cn.pluss.platform.util.*;
import cn.pluss.platform.wx.WxAccessTokenRequest;
import cn.pluss.platform.wx.WxCommonService;
import cn.pluss.platform.wx.WxJumpWxa;
import cn.pluss.platform.wx.WxUrlschemeResponse;
import cn.pluss.platform.yinsheng.YsOldSrcMerchantNo;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.geoip.model.v20200101.DescribeIpv4LocationResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 下游统一支付接口impl
 */
@Service
@Slf4j
public class ApiPayServiceImpl implements ApiPayService {

    /**
     * 先这么做吧 只有一个 以后再换成安商户生成
     */
    private static final String KEY = "4c8d277b0f274604af68e590cc0b3e6b";

    @Resource
    private MerchantStoreMapper merchantStoreMapper;

    @Setter(onMethod_ = {@Autowired,@Lazy})
    private MerchantOrderService merchantOrderService;

    @Resource
    private MerchantBaseInfoMapper merchantBaseInfoMapper;

    @Resource
    private CommonSwitchService commonSwitchService;

    @Resource
    private MerchantService merchantService;

    @Resource
    private MerchantChannelStatusService merchantChannelStatusService;

    @Resource
    private MerchantMenberMapper merchantMenberMapper;

    @Resource
    private RyxPayService ryxPayService;

    @Resource
    private SxfPayService sxfPayService;

    @Setter(onMethod_ = {@Autowired, @Qualifier("ysPayOldService")})
    private PayService ysPayOldService;

    @Resource
    private MerchantRateNewService merchantRateNewService;

    @Autowired
    @Qualifier("ipLocationService")
    private IpLocationService ipLocationService;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Setter(onMethod_ = {@Autowired,@Lazy})
    private MerchantRefundOrderService merchantRefundOrderService;

    @Setter(onMethod_ = {@Autowired,@Lazy})
    private MerchantCashPlaceService merchantCashPlaceService;

    @Setter(onMethod_ = {@Autowired,@Lazy})
    private MercOrderNewService mercOrderNewService;

    @Resource
    private WxCommonService wxCommonService;

    @Resource
    private AppletInfoService appletInfoService;

    @Resource
    private MercOrderTokenService mercOrderTokenService;

    @Resource
    private SubMercCodeYsMapper subMercCodeYsMapper;

    @Resource
    private JftReceiptOrderService jftReceiptOrderService;

    @Resource
    private JftMercBaseInfoService jftMercBaseInfoService;

    @Resource
    private JftMercPaymentChannelService jftMercPaymentChannelService;

    private String currencyParamsCheck(JSONObject jsonObject) {
        Optional.ofNullable(jsonObject.getString("method")).orElseThrow(() -> new MsgException("接口方法参数不能为空"));
        String mercOrderNo = jsonObject.getString("mercOrderNo");
        Optional.ofNullable(mercOrderNo).orElseThrow(() -> new MsgException("商户订单号不能为空"));
        if (mercOrderNo.length() < 10 || mercOrderNo.length() > 50) {
            throw new MsgException("商户订单号长度格式有误，长度介于10到50之间!");
        }
        Optional.ofNullable(jsonObject.getString("sign")).orElseThrow(() -> new MsgException("缺失签名sign参数！"));
        if("trans_pay".equals(jsonObject.getString("method")) ||
                "trans_wap_pay".equals(jsonObject.getString("method")) ||
                "trans_scan_pay".equals(jsonObject.getString("method"))){
            MerchantStore store = null;
            if("trans_pay".equals(jsonObject.getString("method"))){
                checSign(jsonObject,jsonObject.getString("merchantCode"));
                store = checkTransPayParams(jsonObject,jsonObject.getString("merchantCode"));
            }else{
                Optional.ofNullable(jsonObject.getString("merchantCode")).orElseThrow(() -> new MsgException("商户编号不能为空！"));
                checSign(jsonObject,jsonObject.getString("merchantCode"));
                store = checkTransPayParams(jsonObject,jsonObject.getString("merchantCode"));
            }
            String payData = checkMercOrder(store,jsonObject);
            if(StringUtil.isNotEmpty(payData)){
                return payData;
            }
            QueryWrapper<MerchantBaseInfo> queryWrapper = new QueryWrapper<MerchantBaseInfo>().eq("merchantCode", store.getMerchantCode());
            MerchantBaseInfo baseInfo = merchantBaseInfoMapper.selectOne(queryWrapper);
            Optional.ofNullable(baseInfo).orElseThrow(() -> new MsgException("当前商户暂未完成商户认证功能！"));
            // 全局电子围栏和单商户电子围栏判定
            //TODO 先关闭异地支付
//            if (!commonSwitchService.allowEcdemicPay() && !store.allowEcdemicPay()) {
//                // 不允许异地支付的时候需要校验ip和商户所在城市
//                try {
//                    merchantService.checkPayLocation(jsonObject.getString("ip"), baseInfo, jsonObject.getString("province"));
//                } catch (PayRiskException e) {
//                    throw new MsgException(e.getMessage());
//                }
//            }
            MerchantChannelStatus channel = null;
            if("trans_wap_pay".equals(jsonObject.getString("method"))){
                channel = merchantChannelStatusService.getByMerchantCode(baseInfo.getMerchantCode(),4);
            }else{
                channel = merchantChannelStatusService.getValidData(baseInfo.getMerchantCode());
            }
            MsgException.checkNull(channel,"无进件信息，请先提交商户信息进行审核");
            if("4".equals(channel.getChannel()) && StringUtil.isNotEmpty(jsonObject.getString("settleType"))){
                SettleTypeEnum.checkValues(jsonObject.getString("settleType"));
                channel.setSettlementType(jsonObject.getString("settleType"));
            }
            MsgException.check("7".equals(channel.getStatus()),"快付审核中");
            MsgException.check(!channel.isPayment(),"进件未通过请耐心等待或联系客服");
            jsonObject.put("channel", channel);
            jsonObject.put("merchant", baseInfo);
            jsonObject.put("store", store);
        }
        return null;
    }

    private void checSign(JSONObject jsonObject,String merchantCode) {
        String sign = jsonObject.getString("sign");
        jsonObject.remove("sign");
        String md5Key = KEY;
        Integer storeId = jsonObject.getInteger("storeId");
        if(StringUtil.isNotEmpty(storeId)){
            MerchantStore store = merchantStoreMapper.selectById(storeId);
            MsgException.checkNull(store,"门店信息异常");
            merchantCode = store.getMerchantCode();
        }
        String phone = jsonObject.getString("phone");
        Integer sId = null;
        if(StringUtil.isNotEmpty(merchantCode)){
            MerchantBaseInfo baseInfo = merchantBaseInfoMapper.queryByMerchantCode(merchantCode);
            MsgException.checkNull(baseInfo,"商户号不存在");
            if(baseInfo != null && StringUtil.isNotEmpty(baseInfo.getMd5Key())){
                md5Key = baseInfo.getMd5Key();
            }
        }else if(StringUtil.isNotEmpty(phone)){
            UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>().eq("loginName", phone));
            MsgException.checkNull(userInfo,"手机号有误！");
            List<MerchantBaseInfo> lists = merchantBaseInfoMapper.selectListByUserId(userInfo.getId());
            if(lists.isEmpty()){
                MsgException.throwException("商户信息异常！");
            }
            merchantCode = lists.get(0).getMerchantCode();
            MerchantStore store = merchantStoreMapper.getStoreByMerchantCode(merchantCode);
            MsgException.checkNull(store,"门店信息异常！");
            sId = store.getId();
        }
        String signContent = SignUtils.getSignContent(jsonObject) + "&key=" + md5Key;
        log.info("============>签名源串:{}<==============", signContent);
        String ckeckSign = MD5Util.MD5Encode(signContent, "UTF-8");
        if (!sign.equalsIgnoreCase(ckeckSign)) {
            log.info("============>签名校验失败,我方生成签名串:{}，下游签名串：{}", ckeckSign, sign);
            throw new MsgException("签名校验失败!");
        }
        if(StringUtil.isNotEmpty(sId)){
            jsonObject.put("storeId",sId);
        }
    }

    private String checkMercOrder(MerchantStore store,JSONObject jsonObject) {
        QueryWrapper<MerchantOrder> queryMercWrapper = new QueryWrapper<MerchantOrder>().eq("mercOrderNo", jsonObject.getString("mercOrderNo"));
        List<MerchantOrder> list = merchantOrderService.list(queryMercWrapper);
        if (!list.isEmpty()) {
            MerchantOrder order = list.get(0);
            if(StringUtil.isNotEmpty(order.getPayData())){
                return order.getPayData();
            }
            throw new MsgException("订单号重复!");
        }
        if ("0".equals(store.getStatus())) {
            throw new MsgException("店铺已经打烊!");
        }
        if ("2".equals(store.getStatus())) {
            throw new MsgException("店铺已被禁用!");
        }
        return null;
    }

    private MerchantStore checkTransPayParams(JSONObject jsonObject,String merchantCode) {
        Integer id = jsonObject.getInteger("storeId");
        MerchantStore store = new MerchantStore();
        if(StringUtil.isNotEmpty(merchantCode)){
            store.setMerchantCode(merchantCode);
        }else{
            store.setId(id);
        }
        if(StringUtil.isEmpty(merchantCode) && id == null){
            MsgException.throwException("缺失商户编号[merchantCode]参数！");
        }
        MerchantStore storeInfo = merchantStoreMapper.selectOne(new QueryWrapper<>(store));
        Optional.ofNullable(storeInfo).orElseThrow(() -> new MsgException("店铺数据异常！"));
        String payAmt = jsonObject.getString("payAmt");
        Optional.ofNullable(payAmt).orElseThrow(() -> new MsgException("付款金额不能为空！"));
        if(StringUtil.isEmpty(storeInfo.getPayEcdemicSwitch()) || "0".equals(storeInfo.getPayEcdemicSwitch())){
            String ip = jsonObject.getString("ip");
            Optional.ofNullable(ip).orElseThrow(() -> new MsgException("付款人ip地址不能为空!"));
        }
        if (!StringUtil.isNumber(payAmt)) {
            throw new MsgException("交易金额格式不正确，单位(元)!");
        }
        if (Double.parseDouble(payAmt) < 0.01d) {
            throw new MsgException("交易金额最少为0.01!");
        }
        Optional.ofNullable(jsonObject.getString("notifyUrl"))
                .orElseThrow(() -> new MsgException("异步通知地址不能为空！"));
        String method = jsonObject.getString("method");
        if(!"trans_scan_pay".equals(method)){
            Optional.ofNullable(jsonObject.getString("payWay"))
                    .orElseThrow(() -> new MsgException("支付渠道不能为空！"));
        }
        if(StringUtil.isEmpty(merchantCode)){
            Optional.ofNullable(jsonObject.getString("payType"))
                    .orElseThrow(() -> new MsgException("支付方式不能为空！"));
            Optional.ofNullable(jsonObject.getString("userId"))
                    .orElseThrow(() -> new MsgException("付款用户不能为空！"));
        }
        Optional.ofNullable(jsonObject.getString("subject"))
                .orElseThrow(() -> new MsgException("订单标题不能为空！"));

        return storeInfo;
    }


    @Override
    public JSONObject pay(String json,String cip) {
        Optional.ofNullable(json).orElseThrow(() -> new MsgException("请求参数为空"));
        JSONObject jsonObject;
        try {
            jsonObject = JSONObject.parseObject(json);
        } catch (JSONException e) {
            throw new MsgException("JSON字符串有误，请检查!");
        }
        String res = currencyParamsCheck(jsonObject);
        if(StringUtil.isNotEmpty(res)){
            return ResultGenerator.genSuccessJsonResult("处理成功",JSONObject.parseObject(res));
        }
        String ip = jsonObject.getString("ip");
        if(StringUtil.isEmpty(ip)){
            ip = cip;
        }
        jsonObject.put("ip",ip);
        String cityName = jsonObject.getString("cityName");
        String provinceName = jsonObject.getString("provinceName");
        if(StringUtil.isNotEmpty(cityName)){
            jsonObject.put("ipAddress",provinceName + "-" + cityName);
            SubMercCodeYs ysCode = subMercCodeYsMapper.getSubMercCodeYsByCity(cityName);
            if(ysCode != null){
                jsonObject.put("pCode",ysCode.getPCode());
                jsonObject.put("cCode",ysCode.getCode());
            }
        }else{
            if(StringUtil.isNotEmpty(ip)){
                DescribeIpv4LocationResponse location = ipLocationService.getLocation(ip);
                if(location != null && StringUtil.isNotEmpty(location.getCity())){
                    SubMercCodeYs ysCode = subMercCodeYsMapper.getSubMercCodeYsByCity(location.getCity());
                    if(ysCode != null){
                        jsonObject.put("pCode",ysCode.getPCode());
                        jsonObject.put("cCode",ysCode.getCode());
                    }
                    jsonObject.put("ipAddress",location.getProvince() + "-" + location.getCity());
                }else{
                    String ipAddress = IpUtils.getIpLoactionAddress(location);
                    jsonObject.put("ipAddress",ipAddress);
                }
            }
        }
        switch (jsonObject.getString("method")) {
            case "trans_query":
                return tradeQuery(jsonObject);
            default:
                return tradePay(jsonObject);
        }

    }

    public JSONObject tradePay(JSONObject jsonObject) {
        MerchantStore store = jsonObject.getObject("store", MerchantStore.class);
        MerchantChannelStatus channel = jsonObject.getObject("channel", MerchantChannelStatus.class);
        String isMember = jsonObject.getString("isMember");
        if (StringUtil.isNotEmpty(isMember) && "1".equals(isMember)) {
            return vipTradePay(jsonObject, store);
        } else {
            try {
                JSONObject result = new JSONObject(10);
                //构建订单
                MerchantBaseInfo merchant = jsonObject.getObject("merchant", MerchantBaseInfo.class);
                if("trans_scan_pay".equals(jsonObject.getString("method")) && StringUtil.isEmpty(jsonObject.get("payWay"))){
                    String payAmt = jsonObject.getString("payAmt");
                    String mercOrderNo = jsonObject.getString("mercOrderNo");
                    MercOrderToken token = new MercOrderToken(merchant,payAmt,channel,mercOrderNo,jsonObject);
                    mercOrderTokenService.save(token);
                    String payUrl = ParametersUtil.domain + "/wap/merchant/scanPayAuth?tk="+token.getToken();
                    result.put("payUrl",payUrl);
                    result.put("mercOrderNo",mercOrderNo);
                    result.put("orderNumber",token.getOrderNumber());
                    result.put("channel",channel.getChannel());
                    result.put("payAmt",token.getOrderAmt());
                    return ResultGenerator.genSuccessJsonResult("下单成功", result);
                }
                MerchantOrder order = getMerchantOrder(jsonObject);
                if("trans_wap_pay".equals(jsonObject.getString("method"))){
                    if(Constant.PAY_TYPE_ALIPAY.equals(order.getPayTypeCode())){
                        String paySource = jsonObject.getString("paySource");
                        //小程序付款方式
                        if(StringUtil.isNotEmpty(paySource) && paySource.equals("01")){
                            String payUrl = "alipays://platformapi/startapp?appId=2021003101623191&page=pages/pay/index?orderNumber="+order.getOrderNumber();
                            result.put("payUrl",payUrl);
                        }else{
                            String payUrl = ParametersUtil.domain + "/wap/aliPay/returnUrl?orderNumber="+order.getOrderNumber();
                            String pUrl = URLDecoder.decode(payUrl, "UTF-8");
                            result.put("payUrl",Constant.ALIPAY_H5_PAY_URL_PRIFIX + pUrl);
                        }
                    }else if (Constant.PAY_TYPE_WECHAT.equals(order.getPayTypeCode())){
                        String subAppId = YsOldSrcMerchantNo.getSubAppIdByValue(channel.getSrcMerchantNo());
                        AppletInfo applet = appletInfoService.getAppletInfoByAppId(subAppId);
                        if(applet == null){
                            return ResultGenerator.genFailJsonResult("商户subAppid信息配置异常,下单失败！");
                        }
                        WxAccessTokenRequest request = WxAccessTokenRequest.buidWxToken(subAppId, applet.getSecret());
                        WxJumpWxa wxJumpWxa = new WxJumpWxa(order.getOrderNumber(),WxJumpWxa.ENV_VERSION_RELEASE);
                        WxUrlschemeResponse urlecheme = wxCommonService.getUrlecheme(request, wxJumpWxa);
                        result.put("payUrl",urlecheme.getOpenlink());
                    }
                    return ResultGenerator.genSuccessJsonResult("下单成功", result);
                }
                if("trans_pay".equals(jsonObject.getString("method"))
                        && StringUtil.isEmpty(jsonObject.get("userId"))
                        && Constant.PAY_TYPE_WECHAT.equals(order.getPayTypeCode())){
                    String ghId = YsOldSrcMerchantNo.getGhIdByValue(channel.getSrcMerchantNo());
                    result.put("gh_Id",ghId);
                    result.put("path","pages/pay/index?orderId="+order.getOrderNumber());
                    result.put("mercOrderNo",order.getMercOrderNo());
                    result.put("orderNumber",order.getOrderNumber());
                    result.put("payAmt",order.getConsumeFee().toString());

                    System.out.println("下单测试");

                    return ResultGenerator.genSuccessJsonResult("下单成功", result);
                }
                if (channel.getChannel() == 1) {
                    JSONObject res = sxfPayService.tradePay(order, channel,merchant);
                    return assemblePayRresultParam(res, order);
                } else if (channel.getChannel() == 2) {
                    MsgException.throwException("当前通道已关闭");
                } else if (channel.getChannel() == 3) {
                    JSONObject res = ryxPayService.tradePay(order, channel,merchant);
                    return assemblePayRresultParam(res, order);
                }else if (channel.getChannel() == 4) {
                    JSONObject res = ysPayOldService.tradePay(order, channel,merchant);
                    return assemblePayRresultParam(res, order);
                }
                return ResultGenerator.genFailJsonResult("未知的通道！");
            } catch (Exception e) {
                e.printStackTrace();
                return ResultGenerator.genFailJsonResult(e.getMessage());
            }
        }

    }

    private JSONObject assemblePayRresultParam(JSONObject result, MerchantOrder order) {

        if (ResultCode.SUCCESS.code() != result.getInteger("code")) {
            return ResultGenerator.genFailJsonResult(result.getString("msg"));
        }
        JSONObject payData = result.getJSONObject("payData");
        order.setPayData(payData.toJSONString());
        merchantOrderService.save(order);
        payData.put("payAmt",order.getConsumeFee().toString());
        return ResultGenerator.genSuccessJsonResult("处理成功", payData);
    }

    /**
     * 构建订单
     *
     * @param jsonObject
     * @return
     */
    private MerchantOrder getMerchantOrder(JSONObject jsonObject) {

        String payAmt = jsonObject.getString("payAmt");
        String nickName = jsonObject.getString("nickName");
        String avatar = jsonObject.getString("avatar");

        MerchantBaseInfo baseInfo = jsonObject.getObject("merchant", MerchantBaseInfo.class);
        MerchantStore storeInfo = jsonObject.getObject("store", MerchantStore.class);
        MerchantChannelStatus channel = jsonObject.getObject("channel", MerchantChannelStatus.class);


        MerchantOrder merchantOrder = new MerchantOrder();
        merchantOrder.setMercOrderNo(jsonObject.getString("mercOrderNo"));
        merchantOrder.setMercNotifyUrl(jsonObject.getString("notifyUrl"));
        merchantOrder.setMercReturnUrl(jsonObject.getString("returnUrl"));
        merchantOrder.setMercUserId(jsonObject.getString("userId"));
        merchantOrder.setMercNotifyStatus("0");

        merchantOrder.setIp(jsonObject.getString("ip"));
        merchantOrder.setIpAddress(jsonObject.getString("ipAddress"));

        merchantOrder.setSnNo(jsonObject.getString("snNo"));
        merchantOrder.setMerchantCode(baseInfo.getMerchantCode());
        merchantOrder.setStoreId(storeInfo.getStoreId());
        merchantOrder.setStoreName(storeInfo.getStoreName());
        merchantOrder.setMerchantName(baseInfo.getAlias());

        merchantOrder.setAlias(baseInfo.getMerchantName());

        merchantOrder.setRemark(jsonObject.getString("remark"));

        merchantOrder.setMercRemark(jsonObject.getString("subject"));
        if (StringUtil.isNotEmpty(nickName)) {
            merchantOrder.setNickName(EmojiUtil.emojiConvert1(nickName));
        }
        if (StringUtil.isNotEmpty(avatar)) {
            merchantOrder.setUserImg(avatar);
        }
        merchantOrder.setConsumeFee(Double.valueOf(payAmt));
        Date date = new Date();
        merchantOrder.setCreateDt(date);
        merchantOrder.setUpdateTime(date);
        merchantOrder.setStatus("5");
        if(StringUtil.isNotEmpty(jsonObject.getString("subject"))){
            merchantOrder.setSubject(jsonObject.getString("subject"));
            merchantOrder.setMercRemark(jsonObject.getString("subject"));
        }
        if(StringUtil.isNotEmpty(jsonObject.getString("pCode"))){
            merchantOrder.setProvince(jsonObject.getString("pCode"));
        }
        if(StringUtil.isNotEmpty(jsonObject.getString("cCode"))){
            merchantOrder.setCity(jsonObject.getString("cCode"));
        }

        String orderSource = jsonObject.getString("orderSource");
        if("trans_scan_pay".equals(jsonObject.getString("method"))){
            merchantOrder.setOrderType("2");
            merchantOrder.setScanType("01");
        }else{
            if("02".equals(jsonObject.getString("payType"))){
                merchantOrder.setOrderType("2");
            }else{
                if(StringUtil.isNotEmpty(orderSource) && !"undefined".equals(orderSource)){
                    merchantOrder.setOrderType(orderSource);
                }else{
                    merchantOrder.setOrderType("9");
                }
            }
        }
//        log.info("============插入订单数据为======================" + JSONObject.toJSONString(merchantOrder));
        Map<String, Object> params = new HashMap<>(2);
        params.put("payWay", jsonObject.getString("payWay"));
        params.put("orderNum", "MERC");
        if("trans_wap_pay".equals(jsonObject.getString("method"))){
            params.put("orderNum", "MERC_WAP");
        }
        if("trans_pay".equals(jsonObject.getString("method")) && StringUtil.isEmpty(merchantOrder.getMercUserId())){
            params.put("orderNum", "MERC_APP");
        }
//        if("trans_wap_pay".equals(jsonObject.getString("method"))){
//            merchantOrder.setApiOrderType("wap");
//        }
//        if("trans_pay".equals(jsonObject.getString("method")) && StringUtil.isEmpty(merchantOrder.getMercUserId())){
//            merchantOrder.setApiOrderType("app");
//        }
        //获取设备绑定的收银点信息
        String snNo = jsonObject.getString("snNo");
        merchantCashPlaceService.setOrderPlaceInfo(merchantOrder,snNo);
        merchantOrderService.constOrderPayCodeAndName(merchantOrder,params,channel);
        merchantOrder.isAllowBankLarge(baseInfo);
        //获取商户费率
        BigDecimal rate = merchantRateNewService.getMchRate(baseInfo.getMerchantCode(),merchantOrder.getPayTypeCode(), merchantOrder.getConsumeFee());
        merchantOrder.calcRateAndFee(rate);
        if("trans_wap_pay".equals(jsonObject.getString("method"))){
            merchantOrderService.save(merchantOrder);
        }
        if("trans_pay".equals(jsonObject.getString("method"))
                && StringUtil.isEmpty(merchantOrder.getMercUserId())){
            merchantOrderService.save(merchantOrder);
        }
        return merchantOrder;
    }

    private JSONObject vipTradePay(JSONObject jsonObject, MerchantStore store) {
        log.info("===========>会员卡支付<=================");
        JSONObject params = new JSONObject(10);
        QueryWrapper<MerchantMenber> menberQueryWrapper = new QueryWrapper<MerchantMenber>()
                .eq("merchantCode", store.getMerchantCode()).eq("storeId", store.getStoreId())
                .eq("appOpenId", jsonObject.getString("userId"));
        MerchantMenber menber = merchantMenberMapper.selectOne(menberQueryWrapper);
        Optional.ofNullable(menber).orElseThrow(() -> new MsgException("会员信息异常！"));
        params.put("comsumeMoney", jsonObject.getString("payAmt"));
        params.put("merchantCode", store.getMerchantCode());
        params.put("storeId", store.getStoreId());
        params.put("isMember", "1");
        params.put("radioPay", "memberPay");
        params.put("appOpenId", jsonObject.getString("userId"));
        params.put("nickName", StringUtil.isNotEmpty(menber.getNickName()) ? menber.getNickName() : menber.getMemberName());
        params.put("userImg", menber.getLogo());
        params.put("ip", jsonObject.getString("ip"));
        params.put("snNo", jsonObject.getString("snNo"));

        try {
            Result<Map<String, Object>> mapResult = merchantService.tradePay(params);
            if (mapResult.getCode() != ResultCode.SUCCESS.code()) {
                return ResultGenerator.genFailJsonResult(mapResult.getMessage());
            } else {
                return ResultGenerator.genSuccessJsonResult(mapResult.getMessage(), mapResult.getData());
            }
        } catch (Exception e) {
            log.info("=============>会员卡支付失败，异常信息为:{}<===============", e);
            return ResultGenerator.genFailJsonResult("支付失败！");
        }
    }

    public JSONObject tradeQuery(JSONObject jsonObject) {
        log.info("==============>调用交易查询接口<====================");
        String mercOrderNo = jsonObject.getString("mercOrderNo");
        QueryWrapper<MerchantOrder> orderQuery = new QueryWrapper<MerchantOrder>().eq("mercOrderNo", mercOrderNo);
        MerchantOrder order = merchantOrderService.getOne(orderQuery);
        Optional.ofNullable(order).orElseThrow(() -> new MsgException("未找到该商户订单号的付款信息！"));
        JSONObject result = new JSONObject(10);
        result.put("mercOrderNo", mercOrderNo);
        result.put("payAmt", order.getConsumeFee());
        if (StringUtil.isNotEmpty(order.getTransDt())) {
            result.put("payTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(order.getTransDt()));
        }
        result.put("payWay", order.getPayTypeCode().contains("0") ? "ZFBZF" : "WXZF");
        result.put("orderNumber", order.getOrderNumber());
        result.put("mercUserId",order.getMercUserId());
        switch (order.getStatus()) {
            case "0":
            case "1":
                result.put("status", order.getStatus());
                break;
            case "5":
                result.put("status", "2");
                break;
            default:
                result.put("status", "3");
                break;
        }
        String key = KEY;
        if(StringUtil.isNotEmpty(jsonObject.getString("md5Key"))){
            key = jsonObject.getString("md5Key");
        }
        String signStr = SignUtils.getSignContent(result) + "&key=" + key;
        String nSign = MD5Util.MD5Encode(signStr, "UTF-8");
        result.put("sign", nSign);
        return result;
    }

    @Override
    public Result<Object> orderPay(String userId, String orderNumber) {
        if(StringUtil.isEmpty(userId)){
            return ResultGenerator.genFailResult("缺失参数！");
        }
        if(StringUtil.isEmpty(orderNumber)){
            return ResultGenerator.genFailResult("缺失订单号参数！");
        }
        //缴费通订单
        if(orderNumber.contains("JFT")){
            JftReceiptOrder order = jftReceiptOrderService.getOrderByNo(orderNumber);
            if(order == null){
                return ResultGenerator.genFailResult("当前订单号有误！");
            }
            if(JftReceiptOrder.PAY_STATUS_YES.equals(order.getStatus())){
                return ResultGenerator.genFailResult("当前订单已支付，请勿重复支付！");
            }
            if(StringUtil.isNotEmpty(order.getPayData())){
                return ResultGenerator.genSuccessResult("获取成功",JSONObject.parseObject(order.getPayData()));
            }
            Long cTime = order.getCreateTime().getTime();
            Long nowTime = System.currentTimeMillis();
            if(nowTime - cTime >= 1000 * 60 * 10){
                return ResultGenerator.genFailResult("订单已超时，请重新下单！");
            }
            order.setPayUserId(userId);
            JftMercBaseInfo jfrMerc = jftMercBaseInfoService.getMercBaseInfo(order.getUserId());
            JftMercPaymentChannel jftChannel = jftMercPaymentChannelService.getByUserId(order.getUserId());
            JSONObject result = ysPayOldService.jftPay(order, jfrMerc, jftChannel);
            if(ResultCode.SUCCESS.code() != result.getInteger("code")){
                return ResultGenerator.genFailResult(result.getString("msg"));
            }
            JSONObject payData = result.getJSONObject("payData");
            order.setPayData(payData.toJSONString());
            order.setTransNo(order.getTransNo());
            order.setPayData(payData.toJSONString());
            order.setCreateDate(null);
            jftReceiptOrderService.updateById(order);
            return ResultGenerator.genSuccessResult("获取成功",payData);
        }else{
            MerchantOrder order = new MerchantOrder();
            MercOrderNew mercOrderNew = null;
            try {
                mercOrderNew = devicePay(userId, orderNumber, order);
                if(mercOrderNew == null){
                    order = oldPay(userId,orderNumber,order);
                }
                Long cTime = order.getCreateDt().getTime();
                Long nowTime = System.currentTimeMillis();
                if(nowTime - cTime >= 1000 * 60 * 10){
                    return ResultGenerator.genFailResult("订单已超时，请重新下单！");
                }
                if(StringUtil.isNotEmpty(order.getPayData())){
                    return ResultGenerator.genSuccessResult("获取成功",JSONObject.parseObject(order.getPayData()));
                }
                MerchantBaseInfo merchant = merchantBaseInfoMapper.queryByMerchantCode(order.getMerchantCode());
                if(merchant == null){
                    return ResultGenerator.genFailResult("商户信息异常！");
                }
                MerchantStore store = merchantStoreMapper.getStoreByMerchantCode(order.getMerchantCode());
                if(store == null){
                    return ResultGenerator.genFailResult("门店信息异常！");
                }
                if("2".equals(store.getStatus())){
                    return ResultGenerator.genFailResult("商户已被禁用！");
                }
                MerchantChannelStatus channel = merchantChannelStatusService.getByMerchantCode(order.getMerchantCode(), Integer.valueOf(order.getAisleSwitch()));
                if(channel == null){
                    return ResultGenerator.genFailResult("当前商户暂未进件通过！");
                }
                if(!channel.isPayment()){
                    return ResultGenerator.genFailResult("进件未通过请耐心等待或联系客服！");
                }
                order.setMercUserId(userId);
                order.setAlias(merchant.getMerchantName());
                try {
                    JSONObject result = ysPayOldService.tradePay(order, channel,merchant);
                    if(ResultCode.SUCCESS.code() != result.getInteger("code")){
                        return ResultGenerator.genFailResult(result.getString("msg"));
                    }
                    JSONObject payData = result.getJSONObject("payData");
                    order.setPayData(payData.toJSONString());
                    if(mercOrderNew == null){
                        merchantOrderService.updateById(order);
                    }else{
                        MercOrderNew update = new MercOrderNew();
                        update.setId(mercOrderNew.getId());
                        update.setTransNo(order.getTransNo());
                        update.setPayData(payData.toJSONString());
                        mercOrderNewService.updateById(update);
                    }
                    return ResultGenerator.genSuccessResult("获取成功",payData);
                }catch (Exception e){
                    e.printStackTrace();
                    return ResultGenerator.genFailResult(e.getMessage());
                }
            }catch (Exception e){
                return ResultGenerator.genFailResult(e.getMessage());
            }
        }
    }

    private MercOrderNew devicePay(String userId, String orderNumber, MerchantOrder order) {
        MercOrderNew newOrder = mercOrderNewService.getOrderByNo(orderNumber);
        if(newOrder == null){
            return null;
        }
        MsgException.check(!DeviceOrderStatus.WAIT_PAY.getStatus().equals(newOrder.getStatus()),"当前订单状态有误!");
        newOrder.setPayUserId(userId);
        newOrder.convert(order,null);
        return newOrder;
    }
    private MerchantOrder oldPay(String userId, String orderNumber,MerchantOrder order) {
        QueryWrapper<MerchantOrder> queryWrapper = new QueryWrapper<MerchantOrder>().eq("orderNumber",orderNumber).eq("status","5");
        MerchantOrder qOrder = merchantOrderService.getOne(queryWrapper);
        if(qOrder == null){
            return order;
        }
        order = qOrder;
        MsgException.check(!"4".equals(order.getAisleSwitch()),"当前订单不是实时到账的订单!");
        order.setMercUserId(userId);
        return order;
    }

    /**
     * @description:退款
     * @date: 2021/11/22 10:00
     * @param params:
     * @return cn.pluss.platform.api.Result<com.alibaba.fastjson.JSONObject>
     */
    @Override
    public Result<JSONObject> refund(JSONObject params) {
        String refundReason = params.getString("refundReason");
        String orderNumber = Optional.ofNullable(params.getString("orderNumber")).orElseThrow(() -> new MsgException("订单编号不能为空"));
        QueryWrapper<MerchantOrder> orderQueryWrapper = new QueryWrapper<MerchantOrder>().eq("orderNumber",orderNumber)
                .eq("status","1");
        List<MerchantOrder> list = merchantOrderService.list(orderQueryWrapper);
        if(list.isEmpty()){
            return ResultGenerator.genFailResult("订单号异常！");
        }
        MerchantOrder merchantOrder = list.get(0);
        QueryWrapper<MerchantRefundOrder> queryWrapper = new QueryWrapper<MerchantRefundOrder>()
                .eq("orderNumber",merchantOrder.getOrderNumber()).in("status","1","2");
        MerchantRefundOrder refundOrder = merchantRefundOrderService.getOne(queryWrapper);
        if(refundOrder != null){
            return ResultGenerator.genFailResult("订单已退款，请勿重复操作！");
        }
        merchantOrderService.returnOrder(merchantOrder.getOrderNumber(),refundReason,"wxapp", null);
        return ResultGenerator.genSuccessResult("退款成功",null);
    }

    /**
     * @description:退款订单查询
     * @date: 2021/11/22 10:03
     * @param params:
     * @return cn.pluss.platform.api.Result<java.lang.Object>
     */
    @Override
    public Result<Object> refundQuery(JSONObject params) {
        String orderNumber = Optional.ofNullable(params.getString("orderNumber")).orElseThrow(() -> new MsgException("订单编号不能为空"));
        QueryWrapper<MerchantRefundOrder> queryWrapper = new QueryWrapper<MerchantRefundOrder>()
                .eq("orderNumber",orderNumber);
        MerchantRefundOrder refundOrder = merchantRefundOrderService.getOne(queryWrapper);
        if(refundOrder != null){
            return ResultGenerator.genSuccessResult("订单获取成功",refundOrder);
        }
        return ResultGenerator.genFailResult("订单号有误，退款订单不存在！");
    }
    
    /**
     * @description:api退款功能
     * @date: 2021/11/22 10:49
     * @param params:  
     * @return cn.pluss.platform.api.Result<com.alibaba.fastjson.JSONObject>
     */
    @Override
    public Result<JSONObject> apiRefund(JSONObject params) {
        checkRefundCommonParam(params);
        String method = params.getString("method");
        JSONObject result = new JSONObject();
        switch (method){
            case "syb.refund.pay":
                MsgException.checkBlank(params.getString("mercOrderNo"),"原交易商户交易订单号不能为空！");
                MsgException.checkBlank(params.getString("notifyUrl"),"异步通知地址不能为空！");
                MsgException.checkBlank(params.getString("refundAmt"),"退款金额不能为空");
                MsgException.check(!StringUtil.isNumber(params.getString("refundAmt")),"退款金额格式有误，小数点保留后两位");
                result = apiRefundPay(params);
                break;
            case "syb.refund.query":
                result = apiRefundQuery(params);
                break;
            default:
                MsgException.throwException("未知操作");
                break;
        }
        return ResultGenerator.genSuccessResult("操作成功",result);
    }

    /**
     * @description:退款订单查询
     * @date: 2021/11/22 16:29
     * @param params:
     * @return com.alibaba.fastjson.JSONObject
     */
    private JSONObject apiRefundQuery(JSONObject params) {
        MerchantBaseInfo merchant = params.getObject("merchant", MerchantBaseInfo.class);
        MerchantRefundOrder refund = merchantRefundOrderService.apiRefundQuery(params);
        return setChannelParam(refund,merchant);
    }

    //退款操作
    private JSONObject apiRefundPay(JSONObject params) {
        MerchantBaseInfo merchant = params.getObject("merchant", MerchantBaseInfo.class);
        String refundReason = StringUtil.isEmpty(params.getString("refundReason")) ? "订单退款" : params.getString("refundReason");
        String mercOrderNo = params.getString("mercOrderNo");
        BigDecimal refundAmt = params.getBigDecimal("refundAmt");
        QueryWrapper<MerchantOrder> queryWrapper = new QueryWrapper<MerchantOrder>().eq("mercOrderNo",mercOrderNo).eq("status","1");
        MerchantOrder order = merchantOrderService.getOne(queryWrapper);
        MsgException.checkNull(order,"原交易单号有误！");
        MsgException.check(!"1".equals(order.getStatus()),"原交易订单未支付或订单状态有误！");
        Double consumeFee = order.getConsumeFee();
        if(refundAmt.compareTo(BigDecimal.valueOf(consumeFee)) > 0){
            MsgException.throwException("退款金额超过原订单交易金额！");
        }
        order.setRefundAmt(refundAmt);
        String mercRefundNo = params.getString("mercRefundNo");
        QueryWrapper<MerchantRefundOrder> refundWrapper = new QueryWrapper<MerchantRefundOrder>().eq("mercRefundNo",mercRefundNo);
        MerchantRefundOrder refundOrder = merchantRefundOrderService.getOne(refundWrapper);
        MsgException.check(refundOrder != null ,"退款单号不可重复");
        QueryWrapper<MerchantRefundOrder> refundOrderNumberWrapper = new QueryWrapper<MerchantRefundOrder>()
                .eq("orderNumber",order.getOrderNumber());
        List<MerchantRefundOrder> list = merchantRefundOrderService.list(refundOrderNumberWrapper);
        order.setUseRefundAmt(BigDecimal.ZERO);
        try {
            if(list.isEmpty()){
                if(refundAmt.compareTo(BigDecimal.valueOf(consumeFee)) == 0){
                    //全额退款
                    order.setRefundType(1);
                }else{
                    //部分退款
                    order.setRefundType(2);
                }
            }else{
                //已退款了一部分
                BigDecimal useRefundAmt = BigDecimal.ZERO;
                for (MerchantRefundOrder r:list) {
                    BigDecimal useAmt = StringUtil.isEmpty(r.getRefundAmt()) ? BigDecimal.ZERO : r.getRefundAmt();
                    useRefundAmt = useRefundAmt.add(useAmt);
                }
                if(refundAmt.compareTo(BigDecimal.valueOf(order.getConsumeFee()).subtract(useRefundAmt)) > 0){
                    //超出退款的金额
                    MsgException.throwException("超出剩余可退款金额！");
                }
                order.setRefundType(2);
                order.setUseRefundAmt(useRefundAmt);
            }
            order.setRemark(refundReason);
            MerchantRefundOrder refund = merchantRefundOrderService.apiRefundOrder(params,order);
            return setChannelParam(refund,merchant);
        }catch (Exception e){
            log.error("api退款失败,退款原单号：{}，失败描述：{}",order.getOrderNumber(),e.getMessage());
            MsgException.throwException(e.getMessage());
        }
        return null;
    }

    private JSONObject setChannelParam(MerchantRefundOrder refund,MerchantBaseInfo merchant) {
        JSONObject result = new JSONObject();
        result.put("refundNo",refund.getRefundNo());
        result.put("orderNumber",refund.getOrderNumber());
        result.put("mercRefundNo",refund.getMercRefundNo());
        result.put("oPayAmt",refund.getPayAmt().toString());
        result.put("refundAmt",refund.getRefundAmt().toString());
        result.put("status",refund.getStatus());
        if(StringUtil.isNotEmpty(refund.getRefundTime())){
            result.put("refundTime",DateUtils.formatDateDefault(refund.getRefundTime(),"yyyy-MM-dd HH:mm:ss"));
        }
        String key = KEY;
        if(StringUtil.isNotEmpty(merchant.getMd5Key())){
            key = merchant.getMd5Key();
        }
        String signStr = SignUtils.getSignContent(result) + "&key=" + key;
        String sign = MD5Util.MD5Encode(signStr, "UTF-8");
        result.put("sign",sign);
        return result;
    }

    /**
     * @description:检查通用退款参数
     * @date: 2021/11/22 10:52
     * @param params:
     */
    private void checkRefundCommonParam(JSONObject params) {

        String phone = params.getString("phone");
        String merchantCode = params.getString("merchantCode");
        if(StringUtil.isBlank(merchantCode) && StringUtil.isBlank(phone)){
            MsgException.throwException("缺失手机号或商编");
        }
        String sign = Optional.ofNullable(params.getString("sign")).orElseThrow(() -> new MsgException("缺失sign！"));
        Optional.ofNullable(params.getString("method")).orElseThrow(() -> new MsgException("请求接口名称method不能为空！"));
        String mercRefundNo = Optional.ofNullable(params.getString("mercRefundNo")).orElseThrow(() -> new MsgException("商户退款单号不能为空！"));
        if(mercRefundNo.length() < 10 || mercRefundNo.length() > 50){
            MsgException.throwException("退款单号长度为10~50位之间！");
        }
        MerchantBaseInfo baseInfo = null;
        if(StringUtil.isNotEmpty(phone)){
            QueryWrapper<UserInfo> queryUser = new QueryWrapper<UserInfo>().eq("loginName",phone);
            UserInfo userInfo = userInfoMapper.selectOne(queryUser);
            MsgException.checkNull(userInfo,"用户信息异常！");
            List<MerchantBaseInfo> merchantList = merchantBaseInfoMapper.selectListByUserId(userInfo.getId());
            MsgException.check(merchantList.isEmpty(),"商户信息异常！");
            baseInfo = merchantList.get(0);
        }else{
            baseInfo = merchantBaseInfoMapper.queryByMerchantCode(merchantCode);
        }
        MsgException.checkNull(baseInfo,"商户信息异常!");
        MerchantStore store = merchantStoreMapper.getStoreByMerchantCode(baseInfo.getMerchantCode());
        MsgException.checkNull(store,"门店信息异常！");
        MsgException.check("2".equals(store.getStatus()),"商户已被禁用！");
        String key = KEY;
        if(StringUtil.isNotEmpty(baseInfo.getMd5Key())){
            key = baseInfo.getMd5Key();
        }
        String signContent = SignUtils.getSignContent(params) + "&key=" + key;
        log.info("============>签名源串:{}<==============", signContent);
        String ckeckSign = MD5Util.MD5Encode(signContent, "UTF-8");
        if (!sign.equalsIgnoreCase(ckeckSign)) {
           MsgException.throwException("签名校验失败!");
        }
        params.put("merchant",baseInfo);
        params.put("store",store);
    }

    /**
     * 内部微信小程序支付
     * @date: 2021/12/24 13:35
     * @param params:
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject wxappPay(JSONObject params) {
        Integer storeId = params.getInteger("storeId");
        MsgException.checkNull(storeId,"缺少店铺ID");
        MerchantStore store = merchantStoreMapper.selectById(storeId);
        MsgException.checkNull(store,"店铺信息异常");
        MsgException.check("2".equals(store.getStatus()),"店铺已被禁用");
        MerchantBaseInfo merchant = merchantBaseInfoMapper.queryByMerchantCode(store.getMerchantCode());
        MsgException.checkNull(merchant,"商户信息异常");
        MerchantChannelStatus channel = merchantChannelStatusService.getValidData(store.getMerchantCode());
        MsgException.checkNull(channel,"进件信息异常");
        String isMember = params.getString("isMember");
        if (StringUtil.isNotEmpty(isMember) && "1".equals(isMember)) {
            return vipTradePay(params, store);
        }
         MerchantOrder order = getWxAppOrder(store,merchant,channel,params);
        if (channel.getChannel() == 1) {
            JSONObject result = sxfPayService.tradePay(order, channel,merchant);
            return assemblePayRresultParam(result, order);
        } else if (channel.getChannel() == 2) {
            MsgException.throwException("当前通道已关闭");
        } else if (channel.getChannel() == 3) {
            JSONObject result = ryxPayService.tradePay(order, channel,merchant);
            return assemblePayRresultParam(result, order);
        }else if (channel.getChannel() == 4) {
            JSONObject result = ysPayOldService.tradePay(order, channel,merchant);
            return assemblePayRresultParam(result, order);
        }else{
            MsgException.throwException("未知通道");
        }
        return null;
    }

    private MerchantOrder getWxAppOrder(MerchantStore store, MerchantBaseInfo merchant,MerchantChannelStatus channel,JSONObject params) {

        MerchantOrder order = new MerchantOrder();
        order.setUserImg(params.getString("avatar"));
        order.setNickName(params.getString("nickName"));
        order.setOrderType("9");
        order.setMerchantCode(merchant.getMerchantCode());
        order.setMerchantName(merchant.getAlias());
        order.setStoreId(store.getStoreId());
        order.setStoreName(store.getStoreName());
        order.setConsumeFee(params.getDouble("payAmt"));
        order.setCreateDt(new Date());
        order.setStatus("5");
        order.setRemark(params.getString("remark"));
        order.setUpdateTime(new Date());
        order.setAlias(merchant.getMerchantName());
        order.setMercOrderNo("ME100"+StringUtil.getBillno());
        order.setMercUserId(params.getString("userId"));
        order.setIp("127.0.0.1");
        String snNo = params.getString("snNo");
        order.setSnNo(snNo);
        merchantOrderService.constOrderPayCodeAndName(order,params,channel);
        merchantCashPlaceService.setOrderPlaceInfo(order,snNo);
        order.isAllowBankLarge(merchant);
        BigDecimal rate = merchantRateNewService.getMchRate(merchant.getMerchantCode(), order.getPayTypeCode(), params.getDouble("payAmt"));
        order.calcRateAndFee(rate);
        return order;
    }
}
