package com.qs.mp.web.controller.api.callback;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qs.mp.common.enums.PayOrderStatusEnum;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.common.utils.WebhookService;
import com.qs.mp.pay.domain.PayOrder;
import com.qs.mp.pay.service.IPayOrderService;
import com.qs.mp.pay.service.IWalletService;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @auther duota
 * @create 2021 2021/9/6 2:54 下午
 * @describe 三方支付平台回调
 */

@RestController
@RequestMapping("/service/notify")
public class PayCallBackController {

  private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
  private String UNKNOWN = "UNKNOWN";

  @Autowired
  private IPayOrderService payOrderService;

  @Autowired
  private IWalletService walletService;

  @RequestMapping(value = "/payCallback", method = RequestMethod.POST)
  public void payCallback(HttpServletRequest request, HttpServletResponse response) {
    // 获取请求的 IP 地址 增加三方服务器IP地址白名单
    String ipAddress = getIpAddr(request);
    logger.info("IP地址:" + ipAddress);
    //IP地址白名单判断 121.196.180.137 三方支付服务器IP白名单
    String orderNo =  request.getParameter("orderNo");
    if(!"121.196.180.137".equalsIgnoreCase(ipAddress)){
      //暂时增加机器人告警，防止三方服务器ip变更信息同步不到位，导致支付故障
      WebhookService.sendLogAlertMsg("【三方支付请求IP异常】{"+ipAddress+"} 订单号:"+orderNo);
    }
    String orderStatus =  request.getParameter("orderStatus");
    String shopOrderNo =  request.getParameter("shopOrderNo");

    String code =  request.getParameter("code");
    String result =  request.getParameter("result");
    String completeDate =  request.getParameter("completeDate");
    String channelNo =  request.getParameter("channelNo");
    String payType =  request.getParameter("payType");
    if(StringUtils.isEmpty(orderNo) ||StringUtils.isEmpty(orderStatus) || StringUtils.isEmpty(shopOrderNo) || StringUtils.isEmpty(code) ){
      LogUtil.error(logger,"参数异常");
      responseWrite(response,"error");
      return;
    }
    int payMoney = Integer.parseInt(request.getParameter("payMoney"));
    logger.info("data: orderNo:"+orderNo +" orderStatus:"+orderStatus +" shopOrderNo:"+shopOrderNo+ "channelNo:"+channelNo+" payType:"+payType);

    //回调金额与订单金额一致性校验
    PayOrder order = payOrderService.getById(shopOrderNo);
    if(order.getTransactionAmount() != payMoney){
      logger.error("回调金额与订单金额不一致");
      responseWrite(response,"error");
      return;
    }
    PayOrder payOrder =  new PayOrder();
    payOrder.setOrderId(shopOrderNo);
    payOrder.setOrderNo(orderNo);
    payOrder.setCompleteDate(completeDate);
    payOrder.setChannelNo(channelNo);
    payOrder.setOrderStatus(orderStatus);

    try {
      // 订单支付状态单独保存
      LambdaUpdateWrapper<PayOrder> updateWrapper = new LambdaUpdateWrapper<>();
      updateWrapper.eq(PayOrder::getOrderStatus, PayOrderStatusEnum.WAIT.getValue());
      updateWrapper.eq(PayOrder::getOrderId, shopOrderNo);
      boolean ret = payOrderService.update(payOrder, updateWrapper);
      if (!ret) {
        throw new ServiceException("支付订单更新失败，orderId:" + shopOrderNo);
      }

      // 更新订单，单个事务处理
      logger.info("支付回调消息更新成功 shopOrderNo："+shopOrderNo);
      walletService.payOrderStatusHandle(payOrder);
      responseWrite(response,"success");
    } catch (Exception e){
      LogUtil.error(logger, e, "支付回调消息更新失败 shopOrderNo："+shopOrderNo);
      responseWrite(response,"error");
    }
  }

  private void responseWrite(HttpServletResponse response,String echostr){
    try {
      response.getWriter().write(echostr);
      response.getWriter().flush();
      response.getWriter().close();
    } catch (IOException e) {
      LogUtil.error(logger, e, "微信公众号设置url回调处理异常");
    }
  }

  /**
   * 获取 IP地址
   * 使用 Nginx等反向代理软件， 则不能通过 request.getRemoteAddr()获取 IP地址
   * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，
   * X-Forwarded-For中第一个非 unknown的有效IP字符串，则为真实IP地址
   */
  private String getIpAddr(HttpServletRequest request) {
    String ip = request.getHeader("x-forwarded-for");
    if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
      ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
      ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
      ip = request.getRemoteAddr();
    }
    return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
  }

}
