package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.*;
import com.alipay.api.domain.*;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import shop.alien.entity.result.R;
import shop.alien.entity.store.AlipayZftCreateRecord;
import shop.alien.entity.store.StorePaymentConfig;
import shop.alien.entity.store.dto.AlipayZftBizRequestDto;
import shop.alien.entity.store.dto.AlipayZftMerchantCreateDto;
import shop.alien.entity.store.dto.AlipayZftMerchantSimplecreateDto;
import shop.alien.mapper.AlipayZftCreateRecordMapper;
import shop.alien.store.service.AlipayZftOnboardingService;
import shop.alien.store.service.StorePaymentConfigService;

import java.lang.reflect.Method;
import java.util.Date;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 使用门店 {@link StorePaymentConfig} 中的证书与密钥，以服务商/平台应用身份调用支付宝进件接口。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AlipayZftOnboardingServiceImpl implements AlipayZftOnboardingService {

    @Value("${payment.aliPay.host}")
    private String aliPayHost;

    private final StorePaymentConfigService storePaymentConfigService;

    private final AlipayZftCreateRecordMapper alipayZftCreateRecordMapper;

    @Override
    public R<String> zftConsult(AlipayZftBizRequestDto request) {
        AntMerchantExpandIndirectZftConsultRequest api = new AntMerchantExpandIndirectZftConsultRequest();
        return invoke(request, api);
    }

    @Override
    public R<String> zftCreate(AntMerchantExpandIndirectZftCreateModel request1, Integer storeId, String type) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());

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

        // 设置商户编号
        model.setExternalId("2088560449225278");

        // 设置商户类型
        model.setMerchantType("01");

        // 设置进件的二级商户名称
        model.setName("爱丽恩(大连)餐饮有限公司");

        // 设置商户别名
        model.setAliasName("爱丽恩(大连)餐饮有限公司");

        // 设置商户类别码 mcc
        model.setMcc("B0002");

        // 设置商户使用服务
        List<String> service = new ArrayList<String>();
        service.add("当面付");
        service.add("app支付");
        model.setService(service);

        // 设置内景照
        List<String> inDoorImages = new ArrayList<String>();
        inDoorImages.add("889493da-4b52-4506-9a25-5dc29b96753b.png");
        model.setInDoorImages(inDoorImages);

        // 设置商户证件编号
        model.setCertNo("91210202MAE7M17B6P");

        // 设置商户证件类型
        model.setCertType("201");

        // 设置商户证件图片url
        model.setCertImage("c2a7a12b-26c1-4eb3-bfcd-2f404fc2ca63.png");

        // 设置证件反面图片
//        model.setCertImageBack("25a10d04-ca9c-41aa-896f-3e0904bec470.jpg");

        // 设置法人名称
        model.setLegalName("唐永顺");

        // 设置法人身份证号
        model.setLegalCertNo("210106196804141555");

        // 设置法人身份证正面url
//        model.setLegalCertFrontImage("25a10d04-ca9c-41aa-896f-3e0904bec470.jpg");

        // 设置法人身份证反面url
//        model.setLegalCertBackImage("25a10d04-ca9c-41aa-896f-3e0904bec470.jpg");

        // 设置经营地址
        AddressInfo businessAddress = new AddressInfo();
        businessAddress.setAddress("大连市中山区港湾街12A号8A-7号");
        businessAddress.setDistrictCode("210202");
//        businessAddress.setLatitude("60.270001");
        businessAddress.setCityCode("210200");
//        businessAddress.setPoiid("B0FFIVU189");
        businessAddress.setProvinceCode("210000");
//        businessAddress.setLongitude("120.760001");
        model.setBusinessAddress(businessAddress);

        // 设置客服电话
//        model.setServicePhone("0571-85022088");

        // 设置商户联系人信息
        List<ContactInfo> contactInfos = new ArrayList<ContactInfo>();
        ContactInfo contactInfos0 = new ContactInfo();
//        contactInfos0.setIdCardNo("110000199001011234");
//        contactInfos0.setPhone("0571-85022088");
        contactInfos0.setName("王骏");
        contactInfos0.setMobile("13352287427");
//        contactInfos0.setEmail("user@domain.com");
        contactInfos.add(contactInfos0);
        model.setContactInfos(contactInfos);

        // 设置结算银行卡
//        List<SettleCardInfo> bizCards = new ArrayList<SettleCardInfo>();
//        SettleCardInfo bizCards0 = new SettleCardInfo();
//        bizCards0.setAccountInstName("招商银行");
//        bizCards0.setBankCode("103290003044");
//        bizCards0.setAccountType("DC");
//        bizCards0.setUsageType("01");
//        bizCards0.setAccountHolderName("张三");
//        bizCards0.setAccountInstCity("杭州市");
//        bizCards0.setAccountInstId("CMB");
//        bizCards0.setAccountNo("6214855710610408");
//        bizCards0.setAccountInstProvince("浙江省");
//        bizCards0.setAccountBranchName("招商银行杭州高新支行");
//        bizCards.add(bizCards0);
//        model.setBizCards(bizCards);

        // 设置商户行业资质
//        List<IndustryQualificationInfo> qualifications = new ArrayList<IndustryQualificationInfo>();
//        IndustryQualificationInfo qualifications0 = new IndustryQualificationInfo();
//        qualifications0.setIndustryQualificationImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
//        qualifications0.setIndustryQualificationType("323");
//        qualifications.add(qualifications0);
//        model.setQualifications(qualifications);

        // 设置门头照
        List<String> outDoorImages = new ArrayList<String>();
        outDoorImages.add("64212801-093d-49a8-9769-5e2b288fb858.png");
        model.setOutDoorImages(outDoorImages);

        // 设置授权函
//        model.setLicenseAuthLetterImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");



        // 设置二级商户与服务商的签约时间
//        model.setSignTimeWithIsv("2015-04-15");

        // 设置结算支付宝账号
        model.setAlipayLogonId("ailien@alienyan.cn");

        // 设置sites
        List<SiteInfo> sites = new ArrayList<SiteInfo>();
        SiteInfo sites0 = new SiteInfo();
//        sites0.setIcpOrgName("支付宝（中国）网络技术有限公司");
        sites0.setSiteType("02");
//        sites0.setSiteDomain("www.alipay.com");
//        sites0.setScreenshotImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
//        sites0.setRemark("备注说明");
//        sites0.setAuthLetterImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
        sites0.setSiteName("应用2.0签约2025092468860692");
//        sites0.setMarket("豌豆荚");
//        sites0.setPassword("123456");
//        sites0.setDownload("https://itunes.apple.com/cn/app/id333206289?mt=8");
//        sites0.setTinyAppId("2021004105652035");
//        sites0.setSiteUrl("https://open.alipay.com");
//        sites0.setIcpServiceName("支付宝");
//        sites0.setRemarkImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
//        sites0.setAccount("测试账号");
//        sites0.setIcpNo("沪ICP备15027489号-2");
//        sites0.setStatus("ONLINE");
        sites.add(sites0);
        model.setSites(sites);

        // 设置开票资料信息
//        MerchantInvoiceInfo invoiceInfo = new MerchantInvoiceInfo();
//        invoiceInfo.setMailTelephone("057162288888");
//        invoiceInfo.setTaxPayerQualification("01");
//        invoiceInfo.setAddress("浙江省杭州市西湖区西溪路蚂蚁金服");
//        invoiceInfo.setAcceptElectronic(true);
//        invoiceInfo.setTelephone("057162288888");
//        invoiceInfo.setTitle("蚂蚁金服（杭州）信息技术有限公司");
//        invoiceInfo.setMailName("张三");
//        invoiceInfo.setAutoInvoice(true);
//        invoiceInfo.setTaxPayerValid("19981011");
//        invoiceInfo.setTaxNo("51010482542598631219");
//        invoiceInfo.setBankName("中国银行");
//        AddressInfo mailAddress = new AddressInfo();
//        mailAddress.setAddress("万塘路18号黄龙时代广场B座");
//        mailAddress.setDistrictCode("371002");
//        mailAddress.setLatitude("60.270001");
//        mailAddress.setCityCode("371000");
//        mailAddress.setPoiid("B0FFIVU189");
//        mailAddress.setProvinceCode("370000");
//        mailAddress.setType("BUSINESS_ADDRESS");
//        mailAddress.setLongitude("120.760001");
//        invoiceInfo.setMailAddress(mailAddress);
//        invoiceInfo.setBankAccount("1234567812345678123");
//        model.setInvoiceInfo(invoiceInfo);

        // 设置目前只有个体工商户商户类型要求填入本字段
//        model.setCertName("xxxx小卖铺");

        // 设置签约支付宝账户
        model.setBindingAlipayLogonId("ailien@alienyan.cn");

        // 设置默认可不填
//        model.setLegalCertType("100");

        // 设置默认结算规则
//        DefaultSettleRule defaultSettleRule = new DefaultSettleRule();
//        defaultSettleRule.setDefaultSettleType("alipayAccount");
//        defaultSettleRule.setDefaultSettleTarget("myalipay@alipay.com");
//        model.setDefaultSettleRule(defaultSettleRule);

        // 设置商家性质
//        model.setMerchantNature("01");

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

        Date now = new Date();
        AlipayZftCreateRecord record = new AlipayZftCreateRecord();
        record.setType(type);
        record.setStoreId(storeId);
        record.setExternalId(request1 != null ? request1.getExternalId() : null);
        record.setMerchantName(request1 != null ? request1.getName() : null);
        record.setRequestJson(request1 != null ? JSON.toJSONString(request1) : "{}");
        record.setCreatedTime(now);
        record.setUpdatedTime(now);

        AntMerchantExpandIndirectZftCreateResponse response;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            record.setInvokeSuccess(false);
            record.setSubMsg(StringUtils.isNotBlank(e.getErrMsg()) ? e.getErrMsg() : e.getMessage());
            alipayZftCreateRecordMapper.insert(record);
            throw e;
        }
        record.setResponseBody(response != null ? response.getBody() : null);
        record.setInvokeSuccess(response != null && response.isSuccess());
        if (response != null) {
            record.setSubCode(response.getSubCode());
            record.setSubMsg(response.getSubMsg());
            record.setOrderId(request1 != null ? response.getOrderId() : null);
        }
        alipayZftCreateRecordMapper.insert(record);

        if (response.isSuccess()) {
            return R.data("调用成功", response.getBody());
        } else {
            return R.fail("调用失败：" + response.getBody());
        }
    }

    private static AlipayConfig getAlipayConfig() {

        String privateKey  = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBTOvScNrk0mw+WbR6Qtx2+HrPxB5IU/V2HSPGZUTDNiCiSU9UZcuXlo0UNwMksFYR43btk4BHW9OsZETdr3uJzbEEko4jQPrY49V6V8d3yFUiexcbLKf9W2X+h7EwdPDahHk6wmM73Lm500xzv8JxdGeo/d2uGTh+qD66HcPW+QYj1YbjRV1JyCOiJ2OiwLcb28arNNLOgj6PktQ69FPSWS4hWrM7nl6DLRr6SdOlyfBT47gwPtW0BQ96/2b9O+qxKBPfrcqdRDH323HvrGFDwa8GoWTdchnKwFjmfIFHMvf+eq3tzilFi8H7vQRtzVRrndwrNa0z+1ss07fcWFDRAgMBAAECggEAItgU0OAizPk7vE22SiBMgy8RAX5rXrhpdIwDwQo3Tpf+kV1KKIdKJy6mFCWDDlcKysVOnlVag2BmmZVnzYnls8wfgQjxjuSK9Pno5JBVK51r+9/J6UPOfYMs6Duu700EPw7mEISj81TXJBGiD6tEfgiNisfm/mzDgbZbORKeXQbaTyrtB+GZn6FNSyyHA1vraARMrgfMEGNzQ4AbtfcUxGO+mejdTFs0PxAq6lovHBY3fYYHI1Nx6kf9iPoom/G4UrcMO67W6QU+1tOCZCXjy4bD2y421z/8XD73+WDyYp+Tjy0hTLqVZc7TpYAOximo1vMIUe23EdJJngdlkdpDFQKBgQDFyETL0knwBSakLfAe2BmFb2x++B4YXUnt4dGbCFBnVooxf5i06GVt/CrfkJhYK6hBSowOScIRf8P6BOSQptRZb2/I1ngQm4vcpAZw6EjUTlgOj/J3XJ+ApUNQnRqE28jDrE4m2RHg4BkQo6yA3DizJAluPCtFoCYDm1a7dV7u7wKBgQCnXEH5sD8VSxURv02/gn80g/uZIP/EOU3ycjBEqZdRGkNINwXT+zqrlZIGYb+bxLvU/R2OqKC5vhcyAL3T1A8ORYqPu5KLnAxg7C+rHuVilUWwCEH7POpCk+ETPXCZwcNvLNa5PIqBH/gdV9Y9PBTef6J4rN6V6TDFgosf5by8PwKBgDpVG71Fk1sAGep4RgbC05wgRc6Y3T9wXDqVzJ098YDY7D83E9HfbPLoWbjAS75Nef1vwCkCpgNFPIbD5KmpGp4aGM0SPC0hwzlbAy9PwxMi3CPHXsrHfZ+SnmzrOQQQUoErk40vnm9FiP74VwtWaD6llUZ25ohNeIi9yvHU5x/vAoGAdU2d1JOq85LHtsO+i9+8pyNnAsJ1YqTDtI5CtK2lqKvewswGIrlxOvi//AchVN3ExZmP0QDyfp31BhAs/T8iOl+Vqf7PzVjX+Eszch5aqwlzadmv3ZepnnamCGVE+hAsmkz0R6tebPjqYC7Ds/HbssQFLc4EyVBD5fwE5ZuR+OMCgYAvGHUYpi0dY9uMHXzL721tIopiwUfKCgLAn3yhSH3p7644NxHBqLLaBLVT2q7JAZQUaZUvXlwiyxU1zvo0xmvcbnB/Vd2qp8KbEUkvHyIYVJkM6Fn+9xBosorcrHv+7B2V1XR9WQcXvppxbN/8farWGuAA0anBD+UGrxd8B0/hHg==";
        String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnxevClLpYc6c8A9lwmnftPO2BeU+X6aZ/+b/n1Cvq096VJKiHmqcsRgRbrnSlmPDHRrQpDti4en2Ys0L2lx7CObIr/2xP/jJVwjIO1iWHUj/w/NAbjv7dLW/FFY4SeNp8rU+hlgGgviyUxzonfNfr3v+o8grFqQq27/hiZJAofsQRMQu1dEQqoKdJj7eQLkTstiK5miJMyQ+Y3tLztrEUMBz/zRgaCEfGqmFmRZ2diy2X+1dGaX6H4+0QJ2u50eY2QTBkNuvREGbAn6/lttAgvg/+CywPYKGeC4xOfnl5wP8iA1QXYbXrVJRkZjU097nyOmSNhLy9KvJH2BNpojS1QIDAQAB";
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId("2021005196608960");
        alipayConfig.setPrivateKey(privateKey);
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(alipayPublicKey);
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        return alipayConfig;
    }



    @Override
    public R<String> zftSimplecreate(AlipayZftMerchantSimplecreateDto request) {
        if (request == null) {
            return R.fail("请求体不能为空");
        }
        if (request.getStoreId() == null) {
            return R.fail("门店ID不能为空");
        }
        R<StorePaymentConfig> cfgCheck = loadConfigByStoreId(request.getStoreId());
        if (R.isNotSuccess(cfgCheck) || cfgCheck.getData() == null) {
            return R.fail(cfgCheck.getMsg());
        }
        try {
            AntMerchantExpandIndirectZftSimplecreateRequest api = new AntMerchantExpandIndirectZftSimplecreateRequest();
            api.setBizModel(toSimplecreateModel(request));
            if (StringUtils.isNotBlank(request.getNotifyUrl())) {
                api.setNotifyUrl(request.getNotifyUrl());
            }
            applyAlipayCommonParams(api, request.getAppAuthToken(), request.getApiVersion());
            String appId = resolveAppId(cfgCheck.getData(), request.getAppId());
            if (StringUtils.isBlank(appId)) {
                return R.fail("app_id 不能为空，请传 app_id 或在门店支付配置中维护应用 ID");
            }
            AlipayClient client = new DefaultAlipayClient(buildAlipayConfig(cfgCheck.getData(), appId));
            AntMerchantExpandIndirectZftSimplecreateResponse response = client.certificateExecute(api);
            if (response == null) {
                return R.fail("支付宝返回为空");
            }
            if (!response.isSuccess()) {
                String sub = response.getSubMsg();
                String msg = StringUtils.isNotBlank(sub) ? sub : "调用失败";
                log.warn("支付宝 simplecreate 失败 subCode={} subMsg={}", response.getSubCode(), response.getSubMsg());
                return R.fail(msg);
            }
            return R.data(response.getBody());
        } catch (ReflectiveOperationException e) {
            log.error("支付宝 simplecreate 公共参数设置失败", e);
            return R.fail("构建请求失败：" + e.getMessage());
        } catch (AlipayApiException e) {
            log.error("支付宝 simplecreate 异常", e);
            return R.fail(StringUtils.isNotBlank(e.getErrMsg()) ? e.getErrMsg() : e.getMessage());
        }
    }

    @Override
    public R<String> orderQuery(String orderId) {

        if (StringUtils.isBlank(orderId)) {
            return R.fail("orderId 不能为空");
        }
//        R<StorePaymentConfig> cfgCheck = loadConfigByStoreId(storeId);
//        if (R.isNotSuccess(cfgCheck) || cfgCheck.getData() == null) {
//            return R.fail(cfgCheck.getMsg());
//        }
        try {
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
            AntMerchantExpandIndirectZftorderQueryRequest request = new AntMerchantExpandIndirectZftorderQueryRequest();
            AntMerchantExpandIndirectZftorderQueryModel model = new AntMerchantExpandIndirectZftorderQueryModel();
            model.setOrderId(orderId.trim());
            request.setBizModel(model);
//            String appId = resolveAppId(cfgCheck.getData(), null);
//            if (StringUtils.isBlank(appId)) {
//                return R.fail("app_id 不能为空，请在门店支付配置中维护应用 ID");
//            }
            AntMerchantExpandIndirectZftorderQueryResponse response = alipayClient.execute(request);
//            AntMerchantExpandIndirectZftorderQueryResponse response = client.certificateExecute(request);
            if (response == null) {
                return R.fail("支付宝返回为空");
            }
            if (!response.isSuccess()) {
                String sub = response.getSubMsg();
                String msg = StringUtils.isNotBlank(sub) ? sub : "调用失败";
                log.warn("支付宝 order.query 失败 subCode={} subMsg={}", response.getSubCode(), response.getSubMsg());
                return R.fail(msg);
            }
            return R.data(response.getBody());
        } catch (AlipayApiException e) {
            log.error("支付宝 order.query 异常 orderId={}", orderId, e);
            return R.fail(StringUtils.isNotBlank(e.getErrMsg()) ? e.getErrMsg() : e.getMessage());
        }
    }

    @Override
    public R<String> zftModify(AlipayZftBizRequestDto request1) throws AlipayApiException {

                AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
// 直付通二级商户作废接口：ant.merchant.expand.indirect.zft.delete
        AntMerchantExpandIndirectZftDeleteRequest request = new AntMerchantExpandIndirectZftDeleteRequest();
        request.setBizContent("{"
                + "\"smid\":\"2088480335620690\"," // 二级商户号
                + "\"external_id\":\"你的平台商户ID\"" // 可选，平台内部商户标识
                + "}");
        AntMerchantExpandIndirectZftDeleteResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            return R.data("调用成功", response.getBody());
        } else {
            return R.data("调用失败", response.getBody());
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
    }

    @Override
    public R<String> supplementCreate(AlipayZftBizRequestDto request) {
        AntMerchantExpandIndirectSupplementCreateRequest api = new AntMerchantExpandIndirectSupplementCreateRequest();
        return invoke(request, api);
    }

    @Override
    public R<String> imageUpload(Integer storeId, String imageType, MultipartFile imageContent,
                                 String appId, String appAuthToken, String apiVersion) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
//        if (storeId == null) {
//            return R.fail("门店ID不能为空");
//        }
        if (StringUtils.isBlank(imageType)) {
            return R.fail("imageType 不能为空");
        }
        if (imageContent == null || imageContent.isEmpty()) {
            return R.fail("imageContent 不能为空");
        }
        if (imageContent.getSize() > 10L * 1024 * 1024) {
            return R.fail("图片大小不能超过10MB");
        }
//        R<StorePaymentConfig> cfgCheck = loadConfigByStoreId(storeId);
//        if (R.isNotSuccess(cfgCheck) || cfgCheck.getData() == null) {
//            return R.fail(cfgCheck.getMsg());
//        }
        try {
            AntMerchantExpandIndirectImageUploadRequest request = new AntMerchantExpandIndirectImageUploadRequest();
            request.setImageType(imageType.trim().toLowerCase());
            String fileName = StringUtils.defaultIfBlank(imageContent.getOriginalFilename(), "image_upload.bin");
            request.setImageContent(new FileItem(fileName, imageContent.getBytes()));
            applyAlipayCommonParams(request, appAuthToken, apiVersion);
//            String resolvedAppId = resolveAppId(cfgCheck.getData(), appId);
//            if (StringUtils.isBlank(resolvedAppId)) {
//                return R.fail("app_id 不能为空，请传 app_id 或在门店支付配置中维护应用 ID");
//            }
//            AlipayClient client = new DefaultAlipayClient(buildAlipayConfig(cfgCheck.getData(), resolvedAppId));
            AntMerchantExpandIndirectImageUploadResponse response = alipayClient.execute(request);
            if (response == null) {
                return R.fail("支付宝返回为空");
            }
            if (!response.isSuccess()) {
                String sub = response.getSubMsg();
                return R.fail(StringUtils.isNotBlank(sub) ? sub : "图片上传失败");
            }
            return R.data(response.getBody());
        } catch (ReflectiveOperationException e) {
            log.error("支付宝图片上传公共参数设置失败 storeId={}", storeId, e);
            return R.fail("构建请求失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("支付宝图片上传异常 storeId={}", storeId, e);
            if (e instanceof AlipayApiException) {
                AlipayApiException ex = (AlipayApiException) e;
                return R.fail(StringUtils.isNotBlank(ex.getErrMsg()) ? ex.getErrMsg() : ex.getMessage());
            }
            return R.fail("图片上传失败：" + e.getMessage());
        }
    }

    private <T extends AlipayResponse> R<String> invoke(AlipayZftBizRequestDto dto, AlipayRequest<T> apiRequest) {
        if (dto == null) {
            return R.fail("请求体不能为空");
        }
        R<StorePaymentConfig> cfgCheck = loadConfig(dto);
        if (R.isNotSuccess(cfgCheck) || cfgCheck.getData() == null) {
            return R.fail(cfgCheck.getMsg());
        }
        Map<String, Object> biz = dto.getBizContent();
        String bizJson = (biz == null || biz.isEmpty()) ? "{}" : JSON.toJSONString(biz);
        // 各 *Request 类实现 AlipayRequest 接口，自带 bizContent/notifyUrl 字段与 setter，并非继承 AlipayObject
        try {
            applyBizContentAndNotify(dto, apiRequest, bizJson);
            applyAlipayCommonParams(apiRequest, dto.getAppAuthToken(), dto.getApiVersion());
        } catch (ReflectiveOperationException e) {
            log.error("设置支付宝请求参数失败", e);
            return R.fail("构建请求失败：" + e.getMessage());
        }
        try {
            String appId = resolveAppId(cfgCheck.getData(), dto.getAppId());
            if (StringUtils.isBlank(appId)) {
                return R.fail("app_id 不能为空，请传 app_id 或在门店支付配置中维护应用 ID");
            }
            AlipayClient client = new DefaultAlipayClient(buildAlipayConfig(cfgCheck.getData(), appId));
            T response = client.certificateExecute(apiRequest);
            if (response == null) {
                return R.fail("支付宝返回为空");
            }
            if (!response.isSuccess()) {
                String sub = response.getSubMsg();
                String msg = StringUtils.isNotBlank(sub) ? sub : "调用失败";
                log.warn("支付宝进件接口失败 method={} subCode={} subMsg={}",
                        apiRequest.getApiMethodName(), response.getSubCode(), response.getSubMsg());
                return R.fail(msg);
            }
            return R.data(response.getBody());
        } catch (AlipayApiException e) {
            log.error("支付宝进件接口异常 method={}", apiRequest.getApiMethodName(), e);
            return R.fail(StringUtils.isNotBlank(e.getErrMsg()) ? e.getErrMsg() : e.getMessage());
        }
    }

    private R<StorePaymentConfig> loadConfig(AlipayZftBizRequestDto dto) {
        if (dto == null || dto.getStoreId() == null) {
            return R.fail("门店ID不能为空");
        }
        return loadConfigByStoreId(dto.getStoreId());
    }

    private R<StorePaymentConfig> loadConfigByStoreId(Integer storeId) {
        StorePaymentConfig config = storePaymentConfigService.getByStoreId(storeId);
        if (config == null) {
            return R.fail("该门店未配置支付参数");
        }
        if (StringUtils.isBlank(config.getAppSecretCert())
                || config.getAppPublicCert() == null || config.getAppPublicCert().length == 0
                || config.getAlipayPublicCert() == null || config.getAlipayPublicCert().length == 0
                || config.getAlipayRootCert() == null || config.getAlipayRootCert().length == 0) {
            return R.fail("门店支付配置不完整（缺少应用私钥或证书）");
        }
        return R.data(config);
    }

    /**
     * @param appId 已解析出的应用 ID（请求覆盖或门店配置）
     */
    private com.alipay.api.AlipayConfig buildAlipayConfig(StorePaymentConfig config, String appId) {
        com.alipay.api.AlipayConfig alipayConfig = new com.alipay.api.AlipayConfig();
        alipayConfig.setServerUrl(aliPayHost);
        alipayConfig.setAppId(appId);
        alipayConfig.setPrivateKey(config.getAppSecretCert());
        alipayConfig.setFormat("json");
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        if (config.getAppPublicCert() != null && config.getAppPublicCert().length > 0) {
            alipayConfig.setAppCertContent(new String(config.getAppPublicCert(), StandardCharsets.UTF_8));
        }
        if (config.getAlipayPublicCert() != null && config.getAlipayPublicCert().length > 0) {
            alipayConfig.setAlipayPublicCertContent(new String(config.getAlipayPublicCert(), StandardCharsets.UTF_8));
        }
        if (config.getAlipayRootCert() != null && config.getAlipayRootCert().length > 0) {
            alipayConfig.setRootCertContent(new String(config.getAlipayRootCert(), StandardCharsets.UTF_8));
        }
        return alipayConfig;
    }

    /**
     * 请求体中的 app_id 优先，否则使用门店支付配置中的应用 ID。
     */
    private static String resolveAppId(StorePaymentConfig config, String overrideFromRequest) {
        if (StringUtils.isNotBlank(overrideFromRequest)) {
            return overrideFromRequest.trim();
        }
        if (config != null && StringUtils.isNotBlank(config.getAppId())) {
            return config.getAppId().trim();
        }
        return null;
    }

    /**
     * 支付宝 OpenAPI 的 Request 类均提供 {@code setBizContent(String)}、{@code setNotifyUrl(String)}，
     * 但声明在各自类上，接口 {@link AlipayRequest} 未包含这些方法，故用反射统一设置。
     */
    private void applyBizContentAndNotify(AlipayZftBizRequestDto dto, Object apiRequest, String bizJson)
            throws ReflectiveOperationException {
        Class<?> clazz = apiRequest.getClass();
        Method setBiz = clazz.getMethod("setBizContent", String.class);
        setBiz.invoke(apiRequest, bizJson);
        if (StringUtils.isNotBlank(dto.getNotifyUrl())) {
            Method setNotify = clazz.getMethod("setNotifyUrl", String.class);
            setNotify.invoke(apiRequest, dto.getNotifyUrl());
        }
    }

    /**
     * 支付宝开放平台公共参数中需业务侧显式传入的部分：<br/>
     * - {@code app_auth_token}：第三方代调用时通过 {@code putOtherTextParam} 追加；<br/>
     * - {@code api_version}：若请求类支持 {@code setApiVersion} 则设置。<br/>
     * 其余如 {@code app_id}、{@code method}、{@code format}、{@code charset}、{@code sign_type}、签名、{@code timestamp}、{@code version}
     * 由 {@link DefaultAlipayClient} 与 {@link com.alipay.api.AlipayConfig} 自动处理。
     */
    private void applyAlipayCommonParams(Object apiRequest, String appAuthToken, String apiVersion)
            throws ReflectiveOperationException {
        if (apiRequest == null) {
            return;
        }
        Class<?> clazz = apiRequest.getClass();
        if (StringUtils.isNotBlank(appAuthToken)) {
            Method put = clazz.getMethod("putOtherTextParam", String.class, String.class);
            put.invoke(apiRequest, "app_auth_token", appAuthToken.trim());
        }
        if (StringUtils.isNotBlank(apiVersion)) {
            try {
                Method setVer = clazz.getMethod("setApiVersion", String.class);
                setVer.invoke(apiRequest, apiVersion.trim());
            } catch (NoSuchMethodException ignored) {
                log.debug("当前请求类无 setApiVersion：{}", clazz.getName());
            }
        }
    }

    /**
     * @return 错误文案；null 表示校验通过
     */
    private String validateZftCreateRequest(AlipayZftMerchantCreateDto dto) {
        if (dto == null) {
            return "请求体不能为空";
        }
        if (dto.getStoreId() == null) {
            return "门店ID不能为空";
        }
        Map<String, Object> biz = buildZftCreateBizContent(dto);
        return validateZftCreateBizMap(biz);
    }

    /**
     * 校验合并后的 biz_content（字段可全部来自 biz_content，或来自顶层 + extraBiz）。
     */
    private static String validateZftCreateBizMap(Map<String, Object> biz) {
        if (biz == null || biz.isEmpty()) {
            return "biz_content 不能为空：请提供 biz_content，或提供 external_id、merchant_type、name、alias_name、mcc、service 等顶层字段";
        }
        String externalId = bizString(biz, "external_id");
        if (StringUtils.isBlank(externalId)) {
            return "external_id 不能为空";
        }
        if (externalId.length() > 64) {
            return "external_id 长度不能超过64";
        }
        String merchantType = bizString(biz, "merchant_type");
        if (StringUtils.isBlank(merchantType)) {
            return "merchant_type 不能为空";
        }
        if (merchantType.length() > 20) {
            return "merchant_type 长度不能超过20";
        }
        String name = bizString(biz, "name");
        if (StringUtils.isBlank(name)) {
            return "name 不能为空";
        }
        if (name.length() > 128) {
            return "name 长度不能超过128";
        }
        String aliasName = bizString(biz, "alias_name");
        if (StringUtils.isBlank(aliasName)) {
            return "alias_name 不能为空";
        }
        if (aliasName.length() > 128) {
            return "alias_name 长度不能超过128";
        }
        String mcc = bizString(biz, "mcc");
        if (StringUtils.isBlank(mcc)) {
            return "mcc 不能为空";
        }
        if (mcc.length() > 10) {
            return "mcc 长度不能超过10";
        }
        if (!bizHasNonEmptyService(biz)) {
            return "service 不能为空";
        }
        return null;
    }

    private static String bizString(Map<String, Object> biz, String key) {
        Object v = biz == null ? null : biz.get(key);
        if (v == null) {
            return null;
        }
        if (v instanceof String) {
            return ((String) v).trim();
        }
        return String.valueOf(v).trim();
    }

    private static boolean bizHasNonEmptyService(Map<String, Object> biz) {
        Object v = biz.get("service");
        if (v == null) {
            return false;
        }
        if (v instanceof List) {
            return !((List<?>) v).isEmpty();
        }
        if (v instanceof String) {
            return StringUtils.isNotBlank((String) v);
        }
        if (v instanceof String[]) {
            return ((String[]) v).length > 0;
        }
        return true;
    }

    /**
     * 合并顺序：biz_content → extraBiz → 非空顶层字段（后者覆盖同名键）。
     */
    private Map<String, Object> buildZftCreateBizContent(AlipayZftMerchantCreateDto dto) {
        Map<String, Object> biz = new LinkedHashMap<>();
        if (dto.getBizContent() != null && !dto.getBizContent().isEmpty()) {
            biz.putAll(dto.getBizContent());
        }
        if (dto.getExtraBiz() != null && !dto.getExtraBiz().isEmpty()) {
            biz.putAll(dto.getExtraBiz());
        }
        if (StringUtils.isNotBlank(dto.getExternalId())) {
            biz.put("external_id", dto.getExternalId().trim());
        }
        if (StringUtils.isNotBlank(dto.getMerchantType())) {
            biz.put("merchant_type", dto.getMerchantType().trim());
        }
        if (StringUtils.isNotBlank(dto.getName())) {
            biz.put("name", dto.getName().trim());
        }
        if (StringUtils.isNotBlank(dto.getAliasName())) {
            biz.put("alias_name", dto.getAliasName().trim());
        }
        if (StringUtils.isNotBlank(dto.getMcc())) {
            biz.put("mcc", dto.getMcc().trim());
        }
        if (dto.getService() != null && !dto.getService().isEmpty()) {
            biz.put("service", dto.getService());
        }
        return biz;
    }

    private AntMerchantExpandIndirectZftSimplecreateModel toSimplecreateModel(AlipayZftMerchantSimplecreateDto d) {
        AntMerchantExpandIndirectZftSimplecreateModel m = new AntMerchantExpandIndirectZftSimplecreateModel();
        m.setExternalId(d.getExternalId());
        m.setBindingAlipayLogonId(d.getBindingAlipayLogonId());
        m.setAliasName(d.getAliasName());
        m.setServicePhone(d.getServicePhone());
        m.setName(d.getName());
        m.setMcc(d.getMcc());
        m.setService(d.getService());
        m.setAlipayLogonId(d.getAlipayLogonId());
        m.setOutDoorImages(d.getOutDoorImages());
        m.setInDoorImages(d.getInDoorImages());
        m.setLicenseAuthLetterImage(d.getLicenseAuthLetterImage());
        if (d.getContactInfos() != null) {
            m.setContactInfos(toContactInfo(d.getContactInfos()));
        }
        if (d.getDefaultSettleRule() != null) {
            m.setDefaultSettleRule(toDefaultSettleRule(d.getDefaultSettleRule()));
        }
        if (d.getBizCards() != null) {
            m.setBizCards(toSettleCardInfo(d.getBizCards()));
        }
        if (d.getBusinessAddress() != null) {
            m.setBusinessAddress(toAddressInfo(d.getBusinessAddress()));
        }
        return m;
    }

    private static ContactInfo toContactInfo(AlipayZftMerchantSimplecreateDto.ContactPart p) {
        ContactInfo c = new ContactInfo();
        c.setName(p.getName());
        c.setMobile(p.getMobile());
        c.setIdCardNo(p.getIdCardNo());
        c.setPhone(p.getPhone());
        c.setEmail(p.getEmail());
        return c;
    }

    private static DefaultSettleRule toDefaultSettleRule(AlipayZftMerchantSimplecreateDto.DefaultSettleRulePart p) {
        DefaultSettleRule r = new DefaultSettleRule();
        r.setDefaultSettleType(p.getDefaultSettleType());
        r.setDefaultSettleTarget(p.getDefaultSettleTarget());
        return r;
    }

    private static SettleCardInfo toSettleCardInfo(AlipayZftMerchantSimplecreateDto.SettleCardPart p) {
        SettleCardInfo s = new SettleCardInfo();
        s.setAccountInstName(p.getAccountInstName());
        s.setBankCode(p.getBankCode());
        s.setAccountType(p.getAccountType());
        s.setUsageType(p.getUsageType());
        s.setAccountHolderName(p.getAccountHolderName());
        s.setAccountInstCity(p.getAccountInstCity());
        s.setAccountInstId(p.getAccountInstId());
        s.setAccountNo(p.getAccountNo());
        s.setAccountBranchName(p.getAccountBranchName());
        s.setAccountInstProvince(p.getAccountInstProvince());
        return s;
    }

    private static AddressInfo toAddressInfo(AlipayZftMerchantSimplecreateDto.AddressPart p) {
        AddressInfo a = new AddressInfo();
        a.setAddress(p.getAddress());
        a.setDistrictCode(p.getDistrictCode());
        a.setLatitude(p.getLatitude());
        a.setCityCode(p.getCityCode());
        a.setPoiid(p.getPoiid());
        a.setProvinceCode(p.getProvinceCode());
        a.setLongitude(p.getLongitude());
        a.setType(p.getType());
        return a;
    }
}
