package com.duowenlvshi.duowenlszp.app.wxPay;

import com.duowenlvshi.duowenlszp.model.Meal.server.MealServer;
import com.duowenlvshi.duowenlszp.model.Order.entity.Order;
import com.duowenlvshi.duowenlszp.model.Order.server.OrderServer;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author yang fang yu
 * @since 2019/9/18 15:38
 */

@Service
@Slf4j
public class WxServiceImpl implements WxService {
    @Autowired
    OrderServer orderServer;
    @Autowired
    MealServer mealServer;

    @Value("${wxPay.url}")
    private String url;
    @Override
    public String payBack(String resXml) {
        WXConfigUtil config = null;
        try {
            config = new WXConfigUtil();
        } catch (Exception e) {
            e.printStackTrace();
        }
        WXPay wxpay = new WXPay(config);
        String xmlBack = "";
        Map<String, String> notifyMap = null;
        try {
            notifyMap = WXPayUtil.xmlToMap(resXml);         // 调用官方SDK转换成map类型数据
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {//验证签名是否有效，有效则进一步处理

                String return_code = notifyMap.get("return_code");//状态
                String out_trade_no = notifyMap.get("out_trade_no");//商户订单号
                String transaction_id = notifyMap.get("transaction_id");//微信支付订单号
                String time_end = notifyMap.get("time_end");//微信支付时间
                if ("SUCCESS".equals(return_code)) {
                    Order order =orderServer.selectByPrimaryKey(out_trade_no);
                    if (order != null) {
                        order.setTradeNo(transaction_id);//设置微信交易单号
                        order.setPaystate(return_code);//设置微信支付状态
                        order.setOrderstate("1");//设置订单结束
                        Date date = new SimpleDateFormat("yyyyMMddHHmmss").parse(time_end);
                        Calendar rightNow = Calendar.getInstance();
                        rightNow.setTime(date);
                        rightNow.add(Calendar.MONTH, order.getDuration());//加上套餐时长 月
                        Date dt1 = rightNow.getTime();
                        order.setEndTime(dt1);//设置套餐结束时间
                        order.setPaydate(date);//设置支付时间
                        int i =orderServer.updateByPrimaryKeySelective(order);
                        Map map2 = new HashMap();
                        int num = mealServer.selectPurchaseNuml(order.getMealId());
                        ++num;
                        map2.put("num",num);
                        map2.put("id",order.getMealId());
                        mealServer.updatePurchaseNuml(map2);
                        if(i<1){
                            log.info("修改订单失败");
                        }
                        log.info("微信手机支付回调成功订单号:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                    } else {
                        log.info("微信手机支付回调失败订单号:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                    }
                }
                return xmlBack;
            } else {
                // 签名错误，如果数据里没有sign字段，也认为是签名错误
                //失败的数据要不要存储？
                log.error("手机支付回调通知签名错误");
                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return xmlBack;
            }
        } catch (Exception e) {
            log.error("手机支付回调通知失败", e);
            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        return xmlBack;
    }

    @Override
    public Map doUnifiedOrder(Map map){
        try {
            WXConfigUtil config = new WXConfigUtil();
            WXPay wxpay = new WXPay(config);
            Map<String, String> data = new HashMap<>();
            //生成商户订单号，不可重复
            data.put("appid", config.getAppID());
            data.put("mch_id", config.getMchID());
            data.put("nonce_str", WXPayUtil.generateNonceStr());
            data.put("body", (String) map.get("body"));
            data.put("out_trade_no",(String) map.get("out_trade_no"));
            data.put("total_fee", map.get("total_fee")+"");
            data.put("spbill_create_ip", WxServiceImpl.getHostIp());
            data.put("notify_url", url);
            data.put("trade_type", "APP");
            data.put("sign", WXPayUtil.generateSignature(data, config.getKey(),WXPayConstants.SignType.MD5));
            //使用官方API请求预付订单
            Map<String, String> response = wxpay.unifiedOrder(data);
            if ("SUCCESS".equals(response.get("return_code"))) {
                Map<String, String> param = new HashMap<>();
                param.put("appid", config.getAppID());
                param.put("partnerid", response.get("mch_id"));
                param.put("prepayid", response.get("prepay_id"));
                param.put("package", "Sign=WXPay");
                param.put("noncestr", WXPayUtil.generateNonceStr());
                param.put("timestamp", System.currentTimeMillis() / 1000 + "");
                param.put("sign", WXPayUtil.generateSignature(param, config.getKey(),WXPayConstants.SignType.MD5));
                return param;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("预下单失败");
        }
        return null;
    }

    private static String getHostIp() {
        Enumeration allNetInterfaces = null;
        String hostIP = "";
        try {
            allNetInterfaces = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        while (allNetInterfaces.hasMoreElements()) {
            NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
            Enumeration addresses = netInterface.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress ip = (InetAddress) addresses.nextElement();
                if (ip != null && ip instanceof Inet4Address) {
                    hostIP = ip.getHostAddress();
                    log.info("本机的IP = " + ip.getHostAddress());
                }
            }
        }
        return hostIP;
    }

}