package com.fdkankan.platform.order.controller.pay;

import com.alibaba.fastjson.JSONObject;
import com.fdkankan.common.controller.BaseController;
import com.fdkankan.pay.paypal.PayPalDefaultConfig;
import com.fdkankan.pay.paypal.sdk.PaypalService;
import com.fdkankan.platform.order.request.RequestPlaceOrder;
import com.fdkankan.platform.user.factory.PayFactory;
import com.fdkankan.platform.user.strategy.OrderStrategyFactory;
import com.paypal.api.payments.Payment;
import com.paypal.base.rest.PayPalRESTException;
import lombok.extern.log4j.Log4j2;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Enumeration;

/**
 * 支付中心-paypal支付模块
 */
@Log4j2
@Controller
@RequestMapping("/service/platform/order/pay")
public class OrderPaypalController extends BaseController {

    @Autowired
    private OrderStrategyFactory orderStrategyFactory;
    @Autowired
    private PayFactory payFactory;
    @Autowired
    private PaypalService paypalService;
    @Autowired
    private PayPalDefaultConfig config;

    @Value("${main.url}")
    private String mainUrl;

    /**
     * Paypal付款
     * orderId      订单id
     * orderType    订单类型，0购买相机，1点数重置，2扩容，3商业版，4增值服务，5场景下载
     * spaceId      0表示国内订单，1表示国外订单
     */
    @RequestMapping(value = "/paypal", method = RequestMethod.POST)
    public String paypal(@RequestBody RequestPlaceOrder order) throws Exception {

        JSONObject jsonObject = payFactory.scanPay("paypal", order);
        if (jsonObject != null && jsonObject.get("redirect") != null){
            return "redirect:" + jsonObject.getString("redirect");
        }
        return  "redirect:" + mainUrl + config.getFailUrl();
    }

    /**
     * Paypal付款
     * orderId      订单id
     * orderType    订单类型，0购买相机，1点数重置，2扩容，3商业版，4增值服务，5场景下载
     * spaceId      0表示国内订单，1表示国外订单
     */
    @RequestMapping(value = "/paypalH5", method = RequestMethod.POST)
    public String paypalH5(RequestPlaceOrder order) throws Exception {
        JSONObject jsonObject = payFactory.h5Pay("paypal", order, null);
        if (jsonObject != null && jsonObject.get("redirect") != null){
            return "redirect:" + jsonObject.getString("redirect");
        }
        return  "redirect:" + mainUrl + config.getH5FailUrl();
    }

    /**
     * 支付成功 Paypal支付通知
     * @param paymentId
     * @param payerId
     * @return
     */
    @RequestMapping(value = "/paypal/callback", method = RequestMethod.GET)
    public String successPay(@RequestParam("paymentId") String paymentId,
                             @RequestParam("PayerID") String payerId) {
        try {
            log.warn("=====paypal支付回调=====\npaymentId:"+paymentId+"\npayerId:"+payerId);
            Payment payment = paypalService.executePayment(paymentId, payerId);
            if (payment.getState().equals("approved")) {
                log.info("paypal支付成功回调");
                String custom = payment.getTransactions().get(0).getCustom();
                String txnId = payment.getTransactions().get(0).getRelatedResources().get(0).getSale().getId();
                String payerEmail  = payment.getTransactions().get(0).getPayee().getEmail();
                log.warn("=====custom:"+custom+"\ntxnId:"+txnId+"\npayerEmail:"+payerEmail);

                String orderSn = custom.split("_")[0];
                if(custom.split("_").length > 2 && custom.split("_")[2].matches("^-?[0-9]+")){
                    orderSn += "_" + custom.split("_")[2];
                }
                orderStrategyFactory.doHandler(orderSn, txnId, payerEmail, custom.split("_")[1], 2);
                return "redirect:" + mainUrl + config.getSuccessUrl();
            }
        } catch (PayPalRESTException e) {
            log.error(e.getMessage());
        } catch (Exception e) {
            log.error("paypal支付回调异常,errorMsg:{}", e.getMessage());
        }
        return "redirect:" + mainUrl + config.getFailUrl();
    }

    /**
     * 支付成功 PaypalH5支付通知
     * @param paymentId
     * @param payerId
     * @return
     */
    @RequestMapping(value = "/paypal/callbackH5", method = RequestMethod.GET)
    public String successPayH5(@RequestParam("paymentId") String paymentId,
                             @RequestParam("PayerID") String payerId) {
        try {
            log.warn("=====paypal支付回调=====\npaymentId:"+paymentId+"\npayerId:"+payerId);
            Payment payment = paypalService.executePayment(paymentId, payerId);
            if (payment.getState().equals("approved")) {
                log.info("paypal支付成功回调");
                String custom = payment.getTransactions().get(0).getCustom();
                String txnId = payment.getTransactions().get(0).getRelatedResources().get(0).getSale().getId();
                String payerEmail  = payment.getTransactions().get(0).getPayee().getEmail();
                log.warn("=====custom:"+custom+"\ntxnId:"+txnId+"\npayerEmail:"+payerEmail);
                String orderSn = custom.split("_")[0];
                if(custom.split("_").length > 2 && custom.split("_")[2].matches("^-?[0-9]+")){
                    orderSn += "_" + custom.split("_")[2];
                }
                orderStrategyFactory.doHandler(orderSn, txnId, payerEmail, custom.split("_")[1], 2);
                return "redirect:" + mainUrl + config.getH5SuccessUrl();
            }
        } catch (PayPalRESTException e) {
            log.error(e.getMessage());
        } catch (Exception e) {
            log.error("paypal支付回调异常,errorMsg:{}", e.getMessage());
        }
        return "redirect:" + mainUrl + config.getH5FailUrl();
    }

    /**
     * Paypal取消支付
     * @return
     */
    @RequestMapping(value = "/paypal/cancel", method = RequestMethod.GET)
    public String cancelPay(){
        return "redirect:" + mainUrl + config.getFailUrl();
    }

    /**
     * PaypalH5取消支付
     * @return
     */
    @RequestMapping(value = "/paypal/cancelH5", method = RequestMethod.GET)
    public String cancelPayH5(){
        return "redirect:" + mainUrl + config.getH5FailUrl();
    }

    /**
     *  Paypal支付回调
     *  Paypal的INP异步通知服务器, 需要修改Paypal官网即时付款通知IPN通告URL
     */
    @RequestMapping(value = "/paypal/notify", method = RequestMethod.POST)
    public void callback() {
        Enumeration en = request.getParameterNames();
        String str = "cmd=_notify-validate";
        while (en.hasMoreElements()) {
            String paramName = (String) en.nextElement();
            String paramValue = request.getParameter(paramName);
            try {
                str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue, "utf-8");
            } catch (UnsupportedEncodingException e) {
                StringWriter trace=new StringWriter();
                e.printStackTrace(new PrintWriter(trace));
                log.error(trace.toString());
            }
            //此处的编码一定要和自己的网站编码一致，不然会出现乱码，paypal回复的通知为‘INVALID’
        }
        final String itemName = request.getParameter("item_name");//商品名
        final String itemNumber = request.getParameter("item_number");//购买数量
        final String paymentDate = request.getParameter("payment_date");//交易时间
        final String receiverEmail = request.getParameter("receiver_email");//收款人email
        final String payerEmail = request.getParameter("payer_email");//付款人email
        final String paymentAmount = request.getParameter("mc_gross");//交易钱数
        final String paymentCurrency = request.getParameter("mc_currency");//货币种类
        final String paymentStatus = request.getParameter("payment_status");//交易状态
        final String txnId = request.getParameter("txn_id");//交易id
        String custom = request.getParameter("custom");//发送payment请求时候自定义的业务服务器订单号

        log.info("itemName:"+itemName);
        log.info("itemNumber:"+itemNumber);
        log.info("paymentDate:"+paymentDate);
        log.info("receiverEmail:"+receiverEmail);
        log.info("payerEmail:"+payerEmail);
        log.info("paymentAmount:"+paymentAmount);
        log.info("paymentCurrency:"+paymentCurrency);
        log.info("paymentStatus:"+paymentStatus);
        log.info("txnId:"+txnId);
        log.info("custom:"+custom);
        String orderSn = custom.split("_")[0];
        try {
            //构建post请求给paypal，将信息 POST 回给 PayPal 进行验证
            //String url = "https://www.sandbox.paypal.com/cgi-bin/webscr";//沙箱环境
            //String url = new URL("https://www.paypal.com/cgi-bin/webscr");//正式环境
            String url = "https://www.paypal.com/cgi-bin/webscr";//正式环境
            //http框架用的是okhttp，okhttp也依赖okio的jar包
            OkHttpClient client = new OkHttpClient();
            okhttp3.RequestBody body = okhttp3.RequestBody.create(MediaType.parse("text/plain; charset=utf-8"), str);
            Request req = new Request.Builder().post(body).url(url).build();
            client.newCall(req).enqueue(new Callback() {
                @Override
                public void onFailure(Call arg0, IOException arg1) {
                    log.error("构建post请求给paypal时候发生了错误:" + custom);
                }
                @Override
                public void onResponse(Call arg0, Response arg1) throws IOException {
                    String str = arg1.body().string();
                    //验证通过
                    if ("VERIFIED".equals(str)) {
//	                    StringBuilder sb = new StringBuilder();
//	                    sb.append("付款成功参数：itemName=").append(itemName).append(",itemNumber=").append(itemNumber).
//	                    append("付款成功参数：paymentStatus=").append(paymentStatus).append(",paymentDate=").append(paymentDate).
//	                    append("付款成功参数：paymentAmount=").append(paymentAmount).append(",paymentCurrency=").append(paymentCurrency).
//	                    append("付款成功参数：txnId=").append(txnId).append(",receiverEmail=").append(receiverEmail).
//	                    append("付款成功参数：payerEmail=").append(payerEmail);
//	                    log.info(sb.toString());

                        //1.确认“payment_status”为“Completed”，因为系统也会为其他结果（如“Pending”或“Failed”）发送 IPN。
                        //2.检查“txn_id”是否未重复，以防止欺诈者重复使用旧的已完成的交易
                        //3.验证“receiver_email”是已在您的PayPal账户中注册的电子邮件地址，以防止将付款发送到欺诈者的账户
                        if ("Completed".equals(paymentStatus)) {
                            //根据自己业务进行处理（修改订单状态，支付时间等等操作）
                            try {
                                log.info("paypal支付成功回调");
                                //表示续费，有消费记录id
                                if(custom.split("_").length > 2 && custom.split("_")[2].matches("^-?[0-9]+")){
                                    orderStrategyFactory.doHandler(custom.split("_")[0] + "_" + custom.split("_")[2], txnId, payerEmail, custom.split("_")[1], 2);
                                }else {
                                    orderStrategyFactory.doHandler(orderSn, txnId, payerEmail, custom.split("_")[1], 2);
                                }
                            } catch (Exception e) {
                                log.error("paypal支付回调异常,errorMsg:{}", e.getMessage());
                            }
                        }
                    } else if ("VERIFIED".equals(str)) {
                        log.error("付款失败回调VERIFIED,订单号=" + orderSn);
                    } else {
                        log.error("付款无效回调VERIFIED,订单号=" + orderSn);
                    }
                }
            });
        } catch (Exception e) {
            log.error("paypal支付回调异常,errorMsg:{}", e.getMessage());
        }
    }


}
