深入支付宝支付扫描支付-跳转支付宝二维码页面支付与自定义生成二维码支付-2跳转固定的支付宝页面进行扫码支付

1、前端-使用window.location.href来请求接口不要使用ajax,我们请求后台支付接口后要跳转到支付宝的支付页面,安全起见,这里入参传订单ID就够了,使用订单ID从后台拿订单数据

2、控制器

 @ApiOperation("根据订单ID生成支付宝支付二维码")
    @GetMapping("/alipay")
    public String alipay(String orderId, HttpServletResponse response) throws AlipayApiException {
       return orderService.alipay(orderId, response);

    }

3、支付业务,支付宝接口文档参考“电脑网址支付——alipay.trade.page.pay(统一收单下单并支付页面接口)”

    @Override
    public String alipay(String orderId, HttpServletResponse servletResponse) throws AlipayApiException {
        ServiceOrder order = orderMapper.selectById(orderId);//订单校验?如剔除订单项中已被置为删除的
        AlipayVo vo = new AlipayVo();
        vo.setOut_trade_no(order.getOrderNo());
        vo.setTotal_amount(String.valueOf(order.getPayPrice()));
        vo.setSubject("jwolf测试");
        vo.setProduct_code("FAST_INSTANT_TRADE_PAY"); //这个是固定的
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setBizContent(JSON.toJSONString(vo));
        request.setReturnUrl(alipayReturnUrl);
        request.setNotifyUrl(alipayNotifyUrl);
        // 执行支付宝请求,其实就是httpclient请求
        // 注意这里使用的是AlipayTradePagePayRequest,返回的是response.getBody(),与自定义二维码不同
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        if (!response.isSuccess()) {
            throw new CommonException("支付异常");
        }  
        return response.getBody();
    }

4、返回给页面的是如下字符串,就是一个表单,表单会立即提交然后生成二维码到支付宝的固定页面,下面的form表单是带有returnURL的。支付宝扫描支付成功后进入显示支付宝支付成功,然后页面定时器重定向到商户定义的returnURL接口。这就是同步回调。支付宝还会调用配置给它的异步回调接口告知商户后台,商户后台接收到回调请求开始处理自身业务,然后返回给支付宝“SUCCESS”,如果支付宝一直没有及时收到响应会进行衰减请求

深入支付宝支付扫描支付-跳转支付宝二维码页面支付与自定义生成二维码支付-2跳转固定的支付宝页面进行扫码支付_第1张图片

深入支付宝支付扫描支付-跳转支付宝二维码页面支付与自定义生成二维码支付-2跳转固定的支付宝页面进行扫码支付_第2张图片

5、同步通知。前后端分离需要自己拼接HTML页面,比较麻烦,然后response响应回去,没分离则直接跳视图填充数据就OK了

    public void alipayReturnUrl(HttpServletRequest request, HttpServletResponse response) throws IOException, AlipayApiException {
        log.info("支付宝同步回调");
        //获取支付宝GET过来反馈信息
        Map params = new HashMap();
        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);
        }
        boolean signVerified = AlipaySignature.rsaCheckV1(params, zfbPublicKey, AlipayClientConfiguration.charset, AlipayClientConfiguration.signType);
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        if (!signVerified) {
            out.println("验签失败");
        }
        //商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        //支付宝交易号
        String tradeNo = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        String totalAmount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
        String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        ServiceOrder order = orderMapper.selectOne(new QueryWrapper().eq("order_no", out_trade_no));
        String msg = tradeStatus.equals("TRADE_SUCCESS") ? "支付成功" : "支付失败";
        msg += JSON.toJSONString(order);
        //前后端分离需要自己拼接HTML页面,比较麻烦,然后response响应回去,没分离则直接跳视图就可以了
        out.println("" + msg + "");

    }

6、异步通知,请求参数处理和验签都和同步通知一样,不同的是同步通知是返回一个页面,这里要修改订单状态,即支付后续逻辑,注意幂等,不要出现两次“发货”。商户的自身业务最好异步执行,可以避免执行失败或超时导致支付宝再次回调,可能会有幂等问题。最好是异步处理支付成功后的业务。异步业务最好多打印日志以备对账使用,这时的订单状态应该是支付成功与订单完成中间的一个“发货”过渡状态,异步业务正常执行完就修改订单状态为完成,而处理失败了可采取人工干预等

  @Override
    public String alipayNotifyUrl(HttpServletRequest request) throws AlipayApiException {
        log.info("支付宝异步回调");
        Map params = new HashMap();
        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);
        }
        boolean flag = AlipaySignature.rsaCheckV1(params, zfbPublicKey, AlipayClientConfiguration.charset, AlipayClientConfiguration.signType);
        // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        if (flag == true) {// 验证成功
            String trade_status = request.getParameter("trade_status"); // 交易状态
            String out_trade_no = request.getParameter("out_trade_no"); // 获取订单号
            log.info("回调过程获取的订单编号:{},订单状态:{}", out_trade_no, trade_status);        
            if (!"TRADE_SUCCESS".equals(trade_status)) {
                return "";
            }
            log.info("支付宝订单支付成功!开始本地支付成功后业务");
            int update = orderMapper.update(new ServiceOrder().setStatus(Constants.OrderStatus.PAY_OK.getOrderStatus()), new QueryWrapper().eq("order_no", out_trade_no).eq("status", Constants.OrderStatus.NO_PAY.getOrderStatus()));
            if (update != 1) {
                log.error("支付成功,但跟新订单状态为处理出现失败,订单号:{}", out_trade_no);
                return "";
            } else {
                //异步处理该订单。收了钱不能退款,告诉用户成功。异步处理订单如有错误需要人工处理。
                asyncProcessOrder(out_trade_no);
                return "SUCCESS";
            }
        }
        return "";
    }

 

你可能感兴趣的:(深入支付宝支付扫描支付-跳转支付宝二维码页面支付与自定义生成二维码支付-2跳转固定的支付宝页面进行扫码支付)