package com.czg.service.account.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.czg.constants.ParamCodeCst;
import com.czg.system.service.SysParamsService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;

/**
 * 支付宝通用SDK工具类
 *
 * @author tankaikai
 * @since 2024-09-23 16:15
 */

@Slf4j
@Component
public class AlipayUtil {
    @DubboReference
    private SysParamsService sysParamsService;

    /**
     * 创建支付宝客户端
     *
     * @return AlipayClient
     */
    @SneakyThrows
    public AlipayClient createClient(boolean isAccount) {
        Map<String, String> aliPayKeySet = sysParamsService.getParamsByMap("ali_pay_key_set", ParamCodeCst.ALI_PAY_KEY_SET);

        String serverUrl = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_GATEWAY);
        String appId = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_APP_ID);
        String privateKey = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_PRIVATE_KEY);
        String alipayPublicKey = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_PUBLIC_KEY);
        String accountAppId = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_APP_ID);
        String accountPrivateKey = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY);
        String accountPublicKey = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY);
        AlipayConfig alipayConfig = new AlipayConfig();
        //设置网关地址
        alipayConfig.setServerUrl(serverUrl);
        //设置应用ID
        alipayConfig.setAppId(isAccount ? accountAppId : appId);
        //设置应用私钥
        alipayConfig.setPrivateKey(isAccount ? accountPrivateKey : privateKey);
        //设置支付宝公钥
        alipayConfig.setAlipayPublicKey(isAccount ? accountPublicKey : alipayPublicKey);
        return new DefaultAlipayClient(alipayConfig);
    }


    /**
     * 获取支付宝用户的openId
     *
     * @param code 用户信息授权码
     * @return openId
     */
    public String getOpenId(String code, boolean isAccount) {
        AlipaySystemOauthTokenRequest req = new AlipaySystemOauthTokenRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数
        req.setCode(code);
        req.setGrantType("authorization_code");
        //此次只是参数展示，未进行字符串转义，实际情况下请转义
        //req.setBizContent("  {" + "    \"primary_industry_name\":\"IT科技/IT软件与服务\"," + "    \"primary_industry_code\":\"10001/20102\"," + "    \"secondary_industry_code\":\"10001/20102\"," + "    \"secondary_industry_name\":\"IT科技/IT软件与服务\"" + " }");
        AlipaySystemOauthTokenResponse response;
        try {
            response = createClient(isAccount).execute(req);
        } catch (Exception e) {
            log.error("获取支付宝用户信息失败", e);
            throw new RuntimeException(e);
        }
        log.info("获取支付宝用户信息成功，返回结果：{}", response.getBody());
        //调用失败
        if (!response.isSuccess()) {
            log.error("获取支付宝用户信息失败，错误码：{}，错误信息：{}", response.getSubCode(), response.getSubMsg());
            throw new RuntimeException(StrUtil.format("获取支付宝用户信息失败，错误码：{}，错误信息：{}", response.getSubCode(), response.getSubMsg()));
        }
        //调用成功，则处理业务逻辑，为配合支付系统确定沿用支付宝的老标准使用userId
        return response.getUserId();
    }

    public String getMobile(String encryptedData) {
        if (StrUtil.isEmpty(encryptedData)) {
            throw new RuntimeException("加密数据不能为空");
        }
        try {
            String encryptKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_ENCRYPT_KEY);

            log.info("解密前的数据，返回结果：{}", encryptedData);
            String resp = AlipayEncrypt.decryptContent(encryptedData, "AES", encryptKey, "UTF-8");
            log.info("解密后的数据，返回结果：{}", resp);
            boolean isJson = JSONUtil.isTypeJSON(resp);
            if (!isJson) {
                throw new AlipayApiException("解密后的数据不是json格式");
            }
            JSONObject jsonObject = JSONUtil.parseObj(resp);
            String code = jsonObject.getStr("code");
            String msg = jsonObject.getStr("msg");
            String mobile = jsonObject.getStr("mobile");
            if ("10000".equals(code)) {
                return mobile;
            } else {
                throw new AlipayApiException(code, msg);
            }
        } catch (AlipayApiException e) {
            log.error("获取支付宝用户的手机号码失败，错误码：{}，错误信息：{}", e.getErrCode(), e.getErrMsg());
            throw new RuntimeException(e);
        }
    }
}
