package com.ruoyi.web.work.wxpay;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.AuthTypeEnum;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
import com.ijpay.wxpay.model.v3.Amount;
import com.ijpay.wxpay.model.v3.Payer;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.work.api.config.BaseController;
import com.ruoyi.web.work.domain.dto.PayDto;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.Transient;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/app/wxPay")
public class WxPayController extends BaseController {
    @Resource
    WxPayBean wxPayV3Bean;



    private String serialNo;

    /**
     * PC扫码支付
     *
     * @param dto
     * @return
     */
    @Log(title = "在线捐赠", businessType = BusinessType.PAY)
    @PostMapping("/pay")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult pay(@Validated @RequestBody PayDto dto) {
        try {
     /*       Project project = projectService.getById(dto.getProjectId());
            if (project == null) {
                return AjaxResult.error("捐赠项目不存在");
            }*/
            String orderNum = PayKit.generateStr();
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel();
            unifiedOrderModel.setAppid(wxPayV3Bean.getAppId());
            unifiedOrderModel.setMchid(wxPayV3Bean.getMchId());
            unifiedOrderModel.setDescription("测试支付");
            unifiedOrderModel.setOut_trade_no(orderNum);
            unifiedOrderModel.setTime_expire(DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3));
            unifiedOrderModel.setAttach("爱心捐款");
            unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/payNotify"));
            unifiedOrderModel.setAmount(new Amount().setTotal(1));
            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.NATIVE_PAY.toString(), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel), AuthTypeEnum.RSA.getCode());
            boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
            if (response.getStatus() == 200 && verifySignature) {
                //保存订单信息
               /* Donate donate = new Donate();
                BeanUtils.copyProperties(dto, donate);
                donate.setState(0);
                donate.setOrderNum(orderNum);
                donateService.save(donate);*/
                return AjaxResult.success("成功", response.getBody());
            }
            return AjaxResult.error("系统异常");
        } catch (Exception e) {
            throw new ServiceException("系统异常");
        }
    }
    /**
     * 公众号或者订阅号支付
     *
     * @param dto
     * @return
     */
    @PostMapping("/jsApiPay")
    @Transient
    public AjaxResult jsApiPay() {
        try {
/*            if (StringUtils.isEmpty(dto.getOpenId())) {
                return AjaxResult.error("openId不能为空");
            }
            Project project = projectService.getById(dto.getProjectId());
            if (project == null) {
                return AjaxResult.error("捐赠项目不存在");
            }*/
            String orderNum = PayKit.generateStr();
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel();
            unifiedOrderModel.setAppid(wxPayV3Bean.getAppId());
            unifiedOrderModel.setMchid(wxPayV3Bean.getMchId());
            unifiedOrderModel.setDescription("测试支付");
            unifiedOrderModel.setOut_trade_no(orderNum);
            unifiedOrderModel.setTime_expire(DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3));
            unifiedOrderModel.setAttach("爱心捐款");
            unifiedOrderModel.setAmount(new Amount().setTotal(1));
            unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/payNotify"));
            unifiedOrderModel.setPayer(new Payer().setOpenid(getUser().getOpenId()));
            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.JS_API_PAY.toString(), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel));
            System.out.println("统一下单响应：" + response);
            if (response.getStatus() == 200) {
                String body = response.getBody();
                JSONObject jsonObject = JSONObject.parseObject(body);
                Map<String, String> map = WxPayKit.jsApiCreateSign(wxPayV3Bean.getAppId(), jsonObject.getString("prepay_id"), wxPayV3Bean.getKeyPath());
                //保存支付订单
               /* Donate donate = new Donate();
                BeanUtils.copyProperties(dto, donate);
                donate.setState(0);
                donate.setOrderNum(orderNum);
                donateService.save(donate);*/
                return AjaxResult.success(map);
            }
            return AjaxResult.error("系统异常222");
        } catch (Exception e) {
            System.out.println("asd:"+e.getMessage());
            e.printStackTrace();
            throw new ServiceException("系统异常");
        }
    }

    @Log(title = "在线捐赠通知", businessType = BusinessType.PAY)
    @PostMapping(value = "/payNotify")
    public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String> map = new HashMap<>(12);
        try {
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce = request.getHeader("Wechatpay-Nonce");
            String serialNo = request.getHeader("Wechatpay-Serial");
            String signature = request.getHeader("Wechatpay-Signature");
            String result = HttpKit.readData(request);
            // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
            JSONObject res = JSONObject.parseObject(WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath()));
            System.out.println("支付通知明文：" + res.toJSONString());
            if (res != null && res.getString("trade_state").equals("SUCCESS")) {
/*               Donate donate = donateService.selectByOrderNum(res.getString("out_trade_no"));
                if (donate != null) {
                    donate.setState(1);
                    donateService.clearCache();
                    donateService.updateById(donate);
                    response.setStatus(200);
                    map.put("code", "SUCCESS");
                    map.put("message", "SUCCESS");
                }*/
            } else {
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "签名错误");
            }
            response.setHeader("Content-type", ContentType.JSON.toString());
            response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
            response.flushBuffer();
        } catch (Exception e) {
            throw new ServiceException("系统异常");
        }
    }

    /**
     * 获取证书序列号
     *
     * @return
     */
    private String getSerialNumber() {
        if (StrUtil.isEmpty(serialNo)) {
            X509Certificate certificate = PayKit.getCertificate(wxPayV3Bean.getCertPath());
            if (certificate != null) {
                serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
            }
        }
        return serialNo;
    }
}
