package com.yida.data.common.core.utils;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.yida.data.common.core.entity.constant.FebsConstant;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.constant.UnionPayConstant;
import com.yida.data.common.core.exception.FebsException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

/**
 * 银联云闪付公用工具类
 *
 * @author ZYJ
 * @date 2022/6/14
 */
@Slf4j
@Component
public class UnionPayPublicUtil {

    @Resource
    private RedisService redisService;

    /**
     * AccessToken获取接口成功状态码
     */
    private static final String TOKEN_SUCCESS_CODE = "0000";

    /**
     * AccessToken获取接口信息名称
     */
    private static final String MSG_NAME = "errInfo";

    /**
     * 获取accessToken
     * 请求方式: HTTP(S) + JSON
     *
     * @param appId  开发者ID
     * @param appKey 开发者key
     * @return java.lang.String
     * @author ZYJ
     * @date 2022/6/16 16:13
     */
    public String getAccessToken(String appId, String appKey) {
        String resultToken;
        // 获取是否有缓存信息
        Object accessToken = redisService.get(FebsConstant.UNION_PAY_ACCESS_TOKEN + appId + StringConstant.DOT + appKey);
        if (Objects.isNull(accessToken)) {
            // 封装参数
            JSONObject param = new JSONObject();
            param.set("appId", appId);
            // 时间戳. yyyyMMddHHmmss
            String timestamp = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
            param.set("timestamp", timestamp);
            // 随机数. 小于128字符
            String nonce = RandomUtil.randomString(64);
            param.set("nonce", nonce);
            // 签名方法
            param.set("signMethod", "SHA256");
            // 签名. SHA256_hex(appId+timestamp+nonce+appKey)
            param.set("signature", DigestUtil.sha256Hex(appId + timestamp + nonce + appKey));

            HttpResponse httpResponse = HttpRequest.post(UnionPayConstant.GET_ACCESS_TOKEN)
                    .body(param.toString())
                    .execute();
            log.info("银联云闪付获取accessToken接口返回数据: {}", httpResponse.body());
            // 返回数据
            JSONObject jsonObject = JSONUtil.parseObj(httpResponse.body());
            if (jsonObject.containsKey(UnionPayConstant.CODE_NAME)
                    && !TOKEN_SUCCESS_CODE.equals(jsonObject.getStr(UnionPayConstant.CODE_NAME))) {
                log.error("获取银联云闪付access_token失败，code: {}, msg: {}", jsonObject.getStr(UnionPayConstant.CODE_NAME), jsonObject.getStr(MSG_NAME));
                throw new FebsException("验证失败");
            }
            resultToken = jsonObject.getStr("accessToken");
            // 保存accessToken到缓存. 1小时
            redisService.set(FebsConstant.UNION_PAY_ACCESS_TOKEN + appId + StringConstant.DOT + appKey,
                    resultToken, 3600L);
        } else {
            resultToken = String.valueOf(accessToken);
        }
        return resultToken;
    }
}
