package com.sqx.modules.shopping.controller.app;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.pay.config.AliPayConstants;
import com.sqx.modules.shopping.dao.OrdersJpaRepository;
import com.sqx.modules.shopping.entity.SelfGoods;
import com.sqx.modules.shopping.entity.SelfGoodsVirtual;
import com.sqx.modules.shopping.entity.SelfOrders;
import com.sqx.modules.shopping.service.GoodsService;
import com.sqx.modules.shopping.service.OrdersService;
import com.sqx.modules.shopping.service.SelfGoodsVirtualService;
import com.sqx.modules.shopping.utils.AmountCalUtil;
import com.sqx.modules.shopping.utils.DateUtil;
import com.sqx.modules.shopping.utils.Result;
import com.sqx.modules.shopping.utils.ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
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.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Api(value="自营商城支付宝支付",tags={"自营商城支付宝支付"})
@Slf4j
@RestController
@RequestMapping("/aliPay")
public class AppSelfAliPayController {

    @Autowired
    private CommonInfoService commonRepository;
    @Autowired
    private OrdersService ordersService;
    @Autowired
    private OrdersJpaRepository ordersJpaRepository;
    @Autowired
    private SelfGoodsVirtualService selfGoodsVirtualService;
    @Autowired
    private UserService userService;
    @Autowired
    private GoodsService goodsService;


    @RequestMapping("/notifyApp")
    @Transactional(rollbackFor = Exception.class)
    public void notifyApp(HttpServletRequest request, HttpServletResponse response){
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        try {
            log.info("回调成功！！！");
            boolean flag = AlipaySignature.rsaCheckV1(params, commonRepository.findOne(64).getValue(), AliPayConstants.CHARSET,"RSA2");
            log.info(flag+"回调验证信息");
            if(flag){
                String outTradeNo = params.get("out_trade_no");
                //支付成功，处理业务
                SelfOrders orders = ordersService.findByOrderNum(outTradeNo);
                if (orders.getStatus() != 1){
                    log.info("订单回调重复："+orders.toString());
                    return;
                }
                orders.setPayWay(2); //支付方式为2支付宝
                orders.setStatus(2); //已付款
                orders.setPayTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); //设置支付时间
                //5.虚拟商品处理
                if (orders.getIsExpress() == 2){ //是否需要发货(1需要发货 2无需发货)
                    //虚拟商品发货，发货成功为确认收货，否则不做变化
                    SelfGoodsVirtual v = selfGoodsVirtualService.sendGoods(orders.getGoodsId());
                    if (v != null){
                        orders.setVirtualId(v.getId()); //虚拟商品id
                        orders.setExpressTime(DateUtil.createTime()); //发货时间
                        orders.setFinishTime(DateUtil.createTime()); //收货时间
                        orders.setStatus(4); //确认收货
                        log.info("虚拟商品发货成功，单号："+outTradeNo);
                        System.err.println("虚拟商品发货成功，单号："+outTradeNo);
                    }
                }
                ordersService.updateBody(orders);
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            log.info("回调验证失败！！！");
        }
    }


    @ApiOperation("支付宝回调")
    @RequestMapping("/notifyAppZS")
    @Transactional(rollbackFor = Exception.class)
    public void notifyAppZS(HttpServletRequest request, HttpServletResponse response){
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        try {
            log.info("回调成功！！！");
            CommonInfo urls = commonRepository.findOne(246);
            boolean flag = AlipaySignature.rsaCertCheckV1(params,urls.getValue()+"/alipayCertPublicKey_RSA2.crt", AliPayConstants.CHARSET, "RSA2");
            log.info(flag+"回调验证信息");
            if(flag){
                String tradeStatus = params.get("trade_status");
                if("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){
                    String outTradeNo = params.get("out_trade_no");
                    //支付成功，处理业务
                    SelfOrders orders = ordersService.findByOrderNum(outTradeNo);
                    if (orders.getStatus() != 1){
                        log.info("订单回调重复："+orders.toString());
                        return;
                    }
                    orders.setPayWay(2); //支付方式为2支付宝
                    orders.setStatus(2); //已付款
                    orders.setPayTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); //设置支付时间
                    //5.虚拟商品处理
                    if (orders.getIsExpress() == 2){ //是否需要发货(1需要发货 2无需发货)
                        //虚拟商品发货，发货成功为确认收货，否则不做变化
                        SelfGoodsVirtual v = selfGoodsVirtualService.sendGoods(orders.getGoodsId());
                        if (v != null){
                            orders.setVirtualId(v.getId()); //虚拟商品id
                            orders.setExpressTime(DateUtil.createTime()); //发货时间
                            orders.setFinishTime(DateUtil.createTime()); //收货时间
                            orders.setStatus(4); //确认收货
                            log.info("虚拟商品发货成功，单号："+outTradeNo);
                            System.err.println("虚拟商品发货成功，单号："+outTradeNo);
                        }
                    }
                    ordersService.updateBody(orders);
                }
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            log.info("回调验证失败！！！");
        }
    }




    @ApiOperation("app支付")
    @GetMapping("/payApp")
    @Transactional(rollbackFor = Exception.class)
    public Result payApp(Long ordersId){
        log.info("开始下单了！！");
        SelfOrders orders = ordersJpaRepository.getOne(ordersId);
        String outTradeNo=orders.getOrderNum();
        //校验金额是否一致
        SelfGoods byId = goodsService.findById(orders.getGoodsId());
        UserEntity userById = userService.selectUserById(orders.getUserId());
        Double aDouble=0.00;
        if(userById.getMember()==null || userById.getMember()!=1){
            aDouble = AmountCalUtil.moneyMul(byId.getPrice(), orders.getNumber());
        }else{
            aDouble = AmountCalUtil.moneyMul(byId.getMemberPrice(), orders.getNumber());
        }
        aDouble= AmountCalUtil.add(aDouble,byId.getPostagePrice());
        if(!orders.getPayMoney().equals(aDouble)){
            ordersJpaRepository.deleteById(ordersId);
            return ResultUtil.error(-100,"订单信息错误，请重新下单！");
        }
        String name = commonRepository.findOne(12).getValue();
        return payApp(name,outTradeNo,orders.getPayMoney());
    }


    @ApiOperation("h5支付")
    @GetMapping(value = "/payH5")
    @Transactional(rollbackFor = Exception.class)
    public Result payH5(Long ordersId) {
        SelfOrders orders = ordersJpaRepository.getOne(ordersId);
        SelfGoods byId = goodsService.findById(orders.getGoodsId());
        UserEntity userById = userService.selectUserById(orders.getUserId());
        Double aDouble=0.00;
        if(userById.getMember()==null || userById.getMember()!=1){
            aDouble = AmountCalUtil.moneyMul(byId.getPrice(), orders.getNumber());
        }else{
            aDouble = AmountCalUtil.moneyMul(byId.getMemberPrice(), orders.getNumber());
        }
        aDouble= AmountCalUtil.add(aDouble,byId.getPostagePrice());
        if(!orders.getPayMoney().equals(aDouble)){
            ordersJpaRepository.deleteById(ordersId);
            return ResultUtil.error(-100,"订单信息错误，请重新下单！");
        }
        String name = commonRepository.findOne(12).getValue();
        CommonInfo one = commonRepository.findOne(19);
        String returnUrl = one.getValue()+"/pages/zysc/my/payment?id="+ordersId;
        return payH5(name,orders.getOrderNum(),orders.getPayMoney(),returnUrl);
    }


    public Result payApp(String name, String generalOrder, Double money) {
        CommonInfo one = commonRepository.findOne(19);
        String url = one.getValue() + "/sqx_fast/aliPay/notifyApp";
        String result = "";
        CommonInfo payWay = commonRepository.findOne(201);
        try {
            if ("1".equals(payWay.getValue())) {
                //构造client
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                //设置网关地址
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
                //设置应用Id
                certAlipayRequest.setAppId(commonRepository.findOne(63).getValue());
                //设置应用私钥
                certAlipayRequest.setPrivateKey(commonRepository.findOne(65).getValue());
                //设置请求格式，固定值json
                certAlipayRequest.setFormat("json");
                //设置字符集
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);
                //设置签名类型
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);
                CommonInfo urls = commonRepository.findOne(200);
                certAlipayRequest.setCertPath(urls.getValue() + "/appCertPublicKey.crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(urls.getValue() + "/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(urls.getValue() + "/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                //构造client
                AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

                //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                model.setBody(name);
                model.setSubject(name);
                model.setOutTradeNo(generalOrder);
                model.setTimeoutExpress("30m");
                model.setTotalAmount(money +"");
                model.setProductCode("QUICK_MSECURITY_PAY");
                request.setBizModel(model);
                request.setNotifyUrl(url);
                //这里和普通的接口调用不同，使用的是sdkExecute
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                if (response.isSuccess()) {
                    result = response.getBody();
                } else {
                    return ResultUtil.error(500,"获取订单失败！");
                }
                return ResultUtil.success(result);
            } else {
                //实例化客户端
                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", commonRepository.findOne(63).getValue(), commonRepository.findOne(65).getValue(), "json", AliPayConstants.CHARSET, commonRepository.findOne(64).getValue(), "RSA2");
                //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                model.setBody(name);
                model.setSubject(name);
                model.setOutTradeNo(generalOrder);
                model.setTimeoutExpress("30m");
                model.setTotalAmount(String.valueOf(money));
                model.setProductCode("QUICK_MSECURITY_PAY");
                request.setBizModel(model);
                request.setNotifyUrl(url);
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                if (response.isSuccess()) {
                    result = response.getBody();
                } else {
                    return ResultUtil.error(500,"获取订单失败！");
                }
                return ResultUtil.success(result);
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return ResultUtil.error(-100, "获取订单失败！");
    }

    public Result payH5(String name, String generalOrder, Double money, String returnUrl) {
        CommonInfo payWay = commonRepository.findOne(201);
        CommonInfo one = commonRepository.findOne(19);
        String url = one.getValue() + "/sqx_fast/aliPay/notifyApp";
        try {
            if ("1".equals(payWay.getValue())) {
                //构造client
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                //设置网关地址
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
                //设置应用Id
                certAlipayRequest.setAppId(commonRepository.findOne(63).getValue());
                //设置应用私钥
                certAlipayRequest.setPrivateKey(commonRepository.findOne(65).getValue());
                //设置请求格式，固定值json
                certAlipayRequest.setFormat("json");
                //设置字符集
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);
                //设置签名类型
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);
                CommonInfo urls = commonRepository.findOne(200);
                certAlipayRequest.setCertPath(urls.getValue() + "/appCertPublicKey.crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(urls.getValue() + "/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(urls.getValue() + "/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                //构造client
                AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
                AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
                JSONObject order = new JSONObject();
                order.put("out_trade_no", generalOrder); //订单号
                order.put("subject", name); //商品标题
                order.put("product_code", "QUICK_WAP_WAY");
                order.put("body", name);//商品名称
                order.put("total_amount", money + ""); //金额
                alipayRequest.setBizContent(order.toString());
                alipayRequest.setNotifyUrl(url); //在公共参数中设置回跳和通知地址
                alipayRequest.setReturnUrl(returnUrl); //线上通知页面地址
                String result = alipayClient.pageExecute(alipayRequest).getBody();
                return ResultUtil.success(result);
            } else {
                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", commonRepository.findOne(63).getValue(), commonRepository.findOne(65).getValue(), "json", AliPayConstants.CHARSET, commonRepository.findOne(64).getValue(), "RSA2");
                AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
                JSONObject order = new JSONObject();
                order.put("out_trade_no", generalOrder); //订单号
                order.put("subject", name); //商品标题
                order.put("product_code", "QUICK_WAP_WAY");
                order.put("body", name);//商品名称
                order.put("total_amount", money); //金额
                alipayRequest.setBizContent(order.toString());
                //在公共参数中设置回跳和通知地址
                alipayRequest.setNotifyUrl(url);
                //通知页面地址
                alipayRequest.setReturnUrl(returnUrl);
                String form = alipayClient.pageExecute(alipayRequest).getBody();
                return ResultUtil.success(form);
            }
        } catch (AlipayApiException e) {
            log.error("CreatPayOrderForH5", e);
        }
        return ResultUtil.error(500,"获取订单信息错误！");
    }





}
