package com.supplier.controller;

import com.github.wxpay.sdk.WXPayUtil;
import com.supplier.vx.pay.*;
import org.jdom2.JDOMException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 微信支付
 */
@RestController
@RequestMapping("/wxpay")
public class WxpayController extends WxPayUtils {
    /**
     * 微信支付请求
     * @param price 金额
     */
    @GetMapping("qrcode")
    public Map<String, Object> wxpayPay(String price) throws Exception {
        //当前时间
        String currTime = PayToolUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = String.valueOf(PayToolUtil.buildRandom(4));
        String nonce_str = strTime + strRandom;
        //订单号
        String out_trade_no = getOrderNo();
        // 获取订单信息
        WxpayVo vo = new WxpayVo()
                .setOut_trade_no(out_trade_no)
                .setApp_id(APPID)
                .setMch_id(MCHID)
                .setKey(KEY)
                .setCurrTime(currTime)
                .setStrTime(strTime)
                .setStrRandom(strRandom)
                .setNonce_str(nonce_str)
                .setSpbill_create_ip(CREATE_IP)
                .setNotify_url(NOTIFY_URL)
                .setTrade_type("NATIVE")
                .setTotal_fee(getMoney(price));

//        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        Map<String,String> packageParams = new HashMap<>();

        packageParams.put("appid", APPID);//公众账号ID
        System.out.println(MCHID);
        packageParams.put("mch_id", MCHID);//商户号
        packageParams.put("body", "途丫-" + out_trade_no);//商品描述
        packageParams.put("out_trade_no", out_trade_no);//商户订单号
        packageParams.put("nonce_str", nonce_str);//随机字符串
//        //订单金额信息
//        Map<String, Object> mapAmount = new HashMap<>();
//        mapAmount.put("total", getMoney(price)); //订单总金额，单位为分
//        mapAmount.put("currency", "CNY"); //货币类型
        packageParams.put("total_fee", getMoney(price)); //订单金额信息
        packageParams.put("spbill_create_ip", CREATE_IP);//终端IP APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP
        packageParams.put("notify_url", NOTIFY_URL);//通知地址 异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数
        packageParams.put("trade_type", "NATIVE");//交易类型 NATIVE 扫码支付

        // 签名
        String sign = PayToolUtil.createSign("UTF-8", packageParams, KEY);

//        String sign = WXPayUtil.generateSignedXml(packageParams, KEY);
        System.out.println(packageParams);
        packageParams.put("sign", sign);

        // 将请求参数转换为xml格式的string
        String requestXML = PayToolUtil.getRequestXml(packageParams);
        System.out.println("requestXML:{}");
        System.out.println(requestXML);
        System.out.println("----------------------------");

        // 调用微信支付统一下单接口
        String resXml = HttpUtil.postData("https://api.mch.weixin.qq.com/pay/unifiedorder", requestXML);
        System.out.println("resXml: {}");
        System.out.println(resXml);
        System.out.println("----------------------------");

        // 解析微信支付结果
        Map map = null;
        try {
            map = doXMLParse.doXMLParse(resXml);
            System.out.println("map: {}");
            System.out.println(map);
            System.out.println("----------------------------");
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //返回前端生成二维码
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("out_trade_no", out_trade_no);//订单编号
        resultMap.put("price", price);//金额
        resultMap.put("result_code", map.get("result_code"));//订单状态
        resultMap.put("code_url", map.get("code_url"));//支付路径
        System.out.println(resultMap);
        return resultMap;

    }

    /**
     * 生成订单号
     * @return
     */
    public static String getOrderNo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String newDate = sdf.format(new Date());
        String result = "";
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            result += random.nextInt(10);
        }
        return newDate + result;
    }

    /**
     * 元转换成分
     * @param amount
     * @return
     */
    public static String getMoney(String amount) {
        if(amount==null){
            return "";
        }
        // 金额转化为分为单位
        // 处理包含, ￥ 或者$的金额
        String currency =  amount.replaceAll("\\$|\\￥|\\,", "");
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0l;
        if(index == -1){
            amLong = Long.valueOf(currency+"00");
        }else if(length - index >= 3){
            amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));
        }else if(length - index == 2){
            amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);
        }else{
            amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");
        }
        return amLong.toString();
    }

    /**
     * 支付回调接口
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/notify")
    public String wxpayNotify(HttpServletRequest request, HttpServletResponse response) {
        //读取参数
        InputStream inputStream ;
        StringBuffer sb = null;
        try {
            sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s ;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null){
                sb.append(s);
            }
            in.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //解析xml成map
        Map<String, String> map = new HashMap<String, String>();
        try {
            map = doXMLParse.doXMLParse(sb.toString());
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //过滤空 设置 TreeMap
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        Iterator it = map.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = map.get(parameter);
            String v = "";
            if(null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        //判断签名是否正确
        if(PayToolUtil.isTenpaySign("UTF-8", packageParams, KEY)) {
            //------------------------------
            //处理业务开始
            //------------------------------
            String resXml = "";
            if("SUCCESS".equals((String)packageParams.get("result_code"))){
                // 这里是支付成功
                //执行自己的业务逻辑
                String mch_id = (String)packageParams.get("mch_id");
                String openid = (String)packageParams.get("openid");
                String is_subscribe = (String)packageParams.get("is_subscribe");
                String out_trade_no = (String)packageParams.get("out_trade_no");

                String total_fee = (String)packageParams.get("total_fee");

                //执行自己的业务逻辑
                //暂时使用最简单的业务逻辑来处理：只是将业务处理结果保存到session中
                //（根据自己的实际业务逻辑来调整，很多时候，我们会操作业务表，将返回成功的状态保留下来）
                request.getSession().setAttribute("_PAY_RESULT", "OK");

                System.out.println("支付成功");

                //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

            } else {
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return ("fail");
            }
            //------------------------------
            //处理业务完毕
            //------------------------------
            try {
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else{
            System.out.println("通知签名验证失败");
        }
        return ("success");
    }
}
