package com.liquidnet.service.platform.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * <p>
 * 顺丰
 * </p>
 *
 * @author jiangxiulong
 * @since 2021-06-24 8:00 下午
 */
@Component
@Slf4j
public class ShunfengSignUtils {
    /**
     * sk
     */
    @Value("${liquidnet.shunfeng.sk}")
    private String SK;
    /**
     * 签名有效期（可根据实际业务设定）单位：毫秒
     */
    private final static Long CHECK_TIME = 600000L;

    /**
     * 生成签名
     * @param timestamp 时间戳
     * @param body 请求body
     * @return
     */
    private String genSign(String timestamp, String body) {
        if (StringUtils.isEmpty(body)) {
            body = "";
        }

        StringBuffer sb = new StringBuffer();
        sb.append(body);
        sb.append("&sk=").append(SK);
        sb.append("&timestamp=").append(timestamp);

        byte[] bytes = DigestUtils.sha512(sb.toString());
        return Base64.encodeBase64URLSafeString(bytes);
    }



    /**
     * 接收请求且验签(可在控制层调用此方法)
     * @param params 接收请求参数
     * @param request 接收请求
     * @return
     */
    public boolean receiveRequestAndCheckSign(String params, HttpServletRequest request) {
        log.debug("params {}", params);
        // 请求方APPID
        String sendAppId = request.getHeader("sendAppId");
        // 请求方时间戳
        String timestamp = request.getHeader("timestamp");
        // 请求方签名
        String sign = request.getHeader("sign");

        if (StringUtils.isBlank(sendAppId)) {
            log.error("参数sendAppId不能为空");
            return false;
        }
        if (StringUtils.isBlank(timestamp)) {
            log.error("参数timestamp不能为空");
            return false;
        }
        if (StringUtils.isBlank(sign)) {
            log.error("参数sign不能为空");
            return false;
        }
        // 校验签名是否过期
        long requestTime = Long.parseLong(timestamp);
        long now = System.currentTimeMillis();
        if (Math.abs(now - requestTime) > CHECK_TIME) {
            log.error("签名过期");
            return false;
        }
        // 请求方参数+请求方时间戳+SK 生成签名
        String thisSign = genSign(timestamp, params);
        // 获取的签名和请求方签名比较是否一致
        if (!thisSign.equals(sign)) {
            log.error("签名错误");
            return false;
        }
        return true;
    }
}
