package com.younike.merchant;


import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.younike.common.core.domain.AjaxResult;
import com.younike.framework.config.AnonymousAccess;
import com.younike.wxpay.pojo.WechatPay;
import com.younike.wxpay.sdk.StreamUtils;
import com.younike.wxpay.sdk.WXPayUtil;
import com.younike.wxpay.service.WechatPayService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @Author: maol
 * @Date: 2018/12/26 13:28
 */
@RestController
@Scope("prototype")
@RequestMapping(value = "/wxAppPay")
public class WeChatAppPayController {

    @Resource
    private WechatPayService payService;

    @Value("${wechatpay.appid}")
    private String appid;

    @Value("${wechatpay.mchid}")
    private String mchid;

    @Value("${wechatpay.key}")
    private String key;

    @Value("${wechatpay.notify-url}")
    private String notifyUrl;

    @Value("${wechatpay.trade-type-app}")
    private String tradeTypeApp;

    @Value("${wechatpay.body}")
    private String body;

    @Value("${wechatpay.choise}")
    private int choise;

    /**
     * @Description: 普通商户模式：微信统一下单接口
     * @param: [request, response, payInfo]
     * @return: com.gd.activiti.frame.pojo.APIResult
     * @Author: maol
     * @Date: 2019/2/2 13:29
     */
    @PostMapping("orderPayment")
    public AjaxResult payment(HttpServletRequest request, HttpServletResponse response, @RequestBody WechatPay payInfo) throws Exception {
        BigDecimal payMoney = null;
        if(0 == choise){
            payMoney = new BigDecimal("0.01");
        }else{
            payMoney = BigDecimal.valueOf(Double.parseDouble(payInfo.getTotal_fee()));
        }

        // 微信订单金额(需要*100)
        int pricenew = payMoney.multiply(new BigDecimal(100)).intValue();

        //拼接统一下单地址参数
        Map<String, String> paraMap = new HashMap<String, String>();
        //获取请求ip地址
        String nonceStr = WXPayUtil.generateNonceStr(); // 随机字符串
        String tradeNo = String.valueOf(System.currentTimeMillis()); // 支付的订单的orderId
        String IP = request.getRemoteAddr();
        String bodystr = body;
        //paraMap 数组用于生成sign签名
        paraMap.put("appid", appid); // 应用ID
        paraMap.put("mch_id", mchid); //微信支付分配的商户号
        paraMap.put("nonce_str", nonceStr); //不重复随机数
        paraMap.put("body", bodystr); //订单名称
        paraMap.put("out_trade_no", tradeNo);//订单号
        paraMap.put("total_fee", String.valueOf(pricenew)); //付款金额 100 是1分
        paraMap.put("spbill_create_ip", IP); //终端IP地址
        paraMap.put("notify_url", notifyUrl);// 此路径是微信服务器调用支付结果通知路径
        paraMap.put("trade_type",tradeTypeApp); //交易类型APP
        String sign = WXPayUtil.generateSignature(paraMap, key);  //商户key  sign签名
        paraMap.put("sign", sign);

        // wechatPay对象转义为xml格式
        WechatPay wechatPay = new WechatPay();
        wechatPay.setAppid(appid);
        wechatPay.setMch_id(mchid);
        wechatPay.setNonce_str(nonceStr);
        wechatPay.setBody(bodystr);
        wechatPay.setOut_trade_no(tradeNo);
        wechatPay.setTotal_fee(String.valueOf(pricenew));
        wechatPay.setSpbill_create_ip(IP);
        wechatPay.setNotify_url(notifyUrl);
        wechatPay.setTrade_type(tradeTypeApp);
        wechatPay.setSign(sign);

        XStream xstream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));
        xstream.alias("xml", WechatPay.class);
        String xml = xstream.toXML(wechatPay);
        System.out.println(xml);
        //统一下单请求地址
        String res = payService.unifiedorder(xml);
        //xml转Map
        Map<String, String> resp = WXPayUtil.xmlToMap(res);

        //以下内容是返回前端页面的数据
        String prepay_id = "";//预支付id
        prepay_id = resp.get("prepay_id");
        if ("SUCCESS".equals(resp.get("return_code"))) {
            Map<String, String> payMap = new HashMap<String, String>();

            payMap.put("appid", appid);
            payMap.put("noncestr", WXPayUtil.generateNonceStr());
            payMap.put("package", "Sign=WXPay");
            payMap.put("partnerid", mchid);
            payMap.put("prepayid", prepay_id);
            payMap.put("timestamp", WXPayUtil.getCurrentTimestamp() + "");
            String paySign = WXPayUtil.generateSignature(payMap, key);
            payMap.put("sign", paySign);
            return AjaxResult.success(payMap);
        }
        return AjaxResult.error();
    }

    /**
     * @Description: 接收微信支付成功通知、修改订单状态
     * @param: [request, response]
     * @return: void
     * @Author: maol
     * @Date: 2019/02/14 11:41
     */
    @RequestMapping(value = "callback")
    @ResponseBody
    @AnonymousAccess
    public void callback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String resXml = "";
        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("return_code", "FAIL");
        returnMap.put("return_msg", "");
        resXml = WXPayUtil.mapToXml(returnMap);
        response.setContentType("text/xml");

        System.out.println("微信支付回调");
        ServletInputStream inputStream = request.getInputStream();
        String result = StreamUtils.inputStream2String(inputStream, "utf-8");
        System.out.println("1微信支付通知结果：" + result);
        Map<String, String> map = null;
        try {
            //解析微信通知返回的信息
            map = WXPayUtil.xmlToMap(result);
        } catch (Exception e) {
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        }
//        判断微信支付是否成功
        if (map.get("return_code").equals("SUCCESS") && map.get("result_code").equals("SUCCESS")) {
            if (map.get("out_trade_no") != null && !"".equals(map.get("out_trade_no"))) {
                System.out.println("3成功out_trade_no: " + map.get("out_trade_no"));
                String tradeNo = map.get("out_trade_no");
                // 查询合单信息
                try{
                    // TODO: 此处更新保证金
                    int flag = 1;
                    if(flag == 1 || flag == 2){
                        returnMap.put("return_code", "SUCCESS");
                        returnMap.put("return_msg", "OK");
                        resXml = WXPayUtil.mapToXml(returnMap);
                        response.setContentType("text/xml");
                    }
                }catch (Exception e){
                    BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                    out.write(resXml.getBytes());
                    out.flush();
                    out.close();
                }

            }
        }
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }

}
