package com.ruoyi.web.controller.api;


import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.ApiResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.weiXin.WeiXinParamConfig;
import com.ruoyi.common.weiXin.WeiXinUtils;
import com.ruoyi.common.weiXin.domain.WxMessageDataDto;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * 验证消息的确来自微信服务器 2、接收微信服务器推送的时间信息
 *
 * @author LCL
 * @date 2024-04-17
 */
@RestController
@RequestMapping("/api/wxauth")
@ApiOperation("验证消息的确来自微信服务器 2、接收微信服务器推送的时间信息")
public class ApiWXAuthWebServiceController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 验证消息是否来自微信服务器
     * signature:微信加密签名
     * timestamp:时间戳
     * nonce:随机数
     * echostr:随机字符串
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "checkToken", method = RequestMethod.GET)
    public void checkToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        //验证
        String newStr = checkToken(signature, timestamp, nonce, echostr);
        if (!echostr.equals(newStr)) {
            logger.error("消息不是来自微信服务器！");
        } else {
            response.getOutputStream().println(echostr);
        }

    }

        public String checkToken(
            String signature,
            String timestamp,
            String nonce,
            String echostr) {
        //调用所有接口前都需要获取accessToken
        String accessToken = getAccessToken();
        if(StringUtils.isBlank(accessToken)){
            return "";
        }
        String token = "hvnSAf40490Qmw72tcMTrU";
        //放入数组，进行字典排序后组成一个字符串。
        String[] arr = new String[]{token, timestamp, nonce};
        Arrays.sort(arr);
        String str = arr[0] + arr[1] + arr[2];
        //sha1加密，这里可以手写也可以用jar包，我选择用jar包，具体的maven依赖在该系列文章的第一章里。
        //如果选择手写，可以参考第三段的代码段。
        String resultMsg = DigestUtils.sha1Hex(str);
        if (!resultMsg.equals(signature)) {
            return "";
        }
        return echostr;

    }

    @Resource
    private RedisCache redisCache;

    /**
     * 获取access_token
     */
    public String getAccessToken() {
        JSONObject jsonObject = new JSONObject();
        String accessToken = "";
        String redisKey = "xcx:access_token";
        try {
            if (redisCache.hasKey(redisKey)) {
                return redisCache.getCacheObject(redisKey).toString();
            }
            String url = "https://api.weixin.qq.com/cgi-bin/token";
            String result = HttpUtils.sendGet(url, "" +
                    "grant_type=client_credential&" +
                    "appid=" + "wxd6fbe722d11e00f5" + "&" +
                    "secret=" + "84396e677785af5d3905784d36db8d73");
            jsonObject = JSONObject.parseObject(result);
            // 有效期(s)
            Integer expiresIn = 0;
            if (ObjectUtils.isNotEmpty(jsonObject)) {
                accessToken = jsonObject.getString("access_token");
                expiresIn = jsonObject.getInteger("expires_in");
            }
            if (StringUtils.isBlank(accessToken)){
                logger.error("小程序获取access_token失败 -> {"+ DateUtils.getTime()+": "+jsonObject+"}");
            }else {
                redisCache.setCacheObject(redisKey, accessToken, expiresIn, SECONDS);
            }
        } catch (Exception e) {
            logger.error("小程序获取access_token异常 -> {"+DateUtils.getTime()+": "+e.getMessage()+"}");
        }
        return accessToken;
    }

    @Resource
    private WeiXinUtils weiXinUtils;

    /**
     * （测试发送服务通知）
     *
     * @param params   orderId 订单ID
     * @return ok
     */
    @GetMapping("/sendSubscribeMessage")
    public ApiResult sendSubscribeMessage(@RequestParam Map<String, Object> params) {
        try {
            String openId = params.get("openId").toString();
            String characterString2 = params.get("characterString2").toString();
            String amount1 = params.get("amount1").toString();
            String thing26 = params.get("thing26").toString();
            String thing20 = params.get("thing20").toString();

            Map<String, Object> data = new HashMap<>();
            data.put("character_string2", new WxMessageDataDto(characterString2));
            data.put("amount1", new WxMessageDataDto(amount1));
            data.put("thing26", new WxMessageDataDto(thing26));
            data.put("thing20", new WxMessageDataDto(thing20));
            // 服务通知
            int code = weiXinUtils.sendSubscribeMessage(WeiXinParamConfig.ORDER_PAY_TEMPLATE_ID, openId, data, "");

            return ApiResult.ok().put("data", code);
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResult.error("测试发送服务通知异常");
        }

    }

}
