no28-爱旅行第八次课后作业

飞一样的编程
飞一样的编程
擅长邻域:Java,MySQL,Linux,nginx,springboot,mongodb,微信小程序,vue

分类: ssm 专栏: 爱旅行项目 标签: 支付宝支付和微信支付

2023-02-23 20:10:49 722浏览

支付宝支付和微信支付

支付宝相关功能

1.支付宝支付确认页

这个页面是确认页面,可以用demo里的页面直接操作。

Api路径

/trade/api/prepay/{orderNo}

方法

GET

响应

HTML

参考代码:

 @GetMapping("/api/prepay/{orderNo}")
    public String prepay(@PathVariable String orderNo, Model model) {
        try {
            ItripHotelOrder order = orderService.loadItripHotelOrder(orderNo);
            if (!EmptyUtils.isEmpty(order)) {
                model.addAttribute("order", order);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "pay";
    }

2.向支付宝提交支付请求接口

客户在支付确认页面点击付款后form表单提交过来。经过一系列操作(可以直接复制demo里的代码)封装好数据给支付宝那边(他们那边要一个form表单的html代码)。然后就会跳到支付宝那边的页面(这个时候已经脱离了咱们的平台)

参考代码如下:

 @PostMapping("/api/orderPay")
    @ResponseBody
    public void orderPay(HttpServletRequest request, HttpServletResponse response) {

        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getGatewayUrl(), alipayConfig.getApp_id(), alipayConfig.getMerchant_private_key(), "json", alipayConfig.getCharset(), alipayConfig.getAlipay_public_key(), alipayConfig.getSign_type());

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(alipayConfig.getReturn_url());
        alipayRequest.setNotifyUrl(alipayConfig.getNotify_url());
        String result = null;
        try {
            //商户订单号,商户网站订单系统中唯一订单号,必填
            String out_trade_no = request.getParameter("WIDout_trade_no");
            //付款金额,必填
            String total_amount = request.getParameter("WIDtotal_amount");
            //订单名称,必填
            String subject =request.getParameter("WIDsubject");
            //商品描述,可空
            String body = request.getParameter("WIDbody");

            alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                    + "\"total_amount\":\""+ total_amount +"\","
                    + "\"subject\":\""+ subject +"\","
                    + "\"body\":\""+ body +"\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

            result = alipayClient.pageExecute(alipayRequest).getBody(); //输出

            response.setContentType("text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            System.out.println(result);
            response.getWriter().write(result);// 直接将完整的表单html输出到页面
            response.getWriter().flush();
            response.getWriter().close();



        } catch (Exception e) {
            e.printStackTrace();
        }


    }

页面展示:

3.同步通知

支付宝给我们这边发通知:告诉我们客户把这个单子支付成功与否。这个是get请求, 浏览器如果关闭的或者网络中断的情况下,会导致同步通知没发出哦(所以支付宝加了一个异步通知双保险),另外就是同步通知里可以设置重定向到支付成功的页面或者支付失败的页面。

参考代码:

 @GetMapping("/returnPay")
    public String returnPay(HttpServletRequest request) {
        Map parameterMap = request.getParameterMap();

        String orderNO = request.getParameter("out_trade_no");
        String id = null;
        try {
            id = orderService.loadItripHotelOrder(orderNO).getId().toString();
            Boolean flag = alipayService.returnPay(parameterMap);
            if (flag) {

                return "redirect:" + String.format(alipayConfig.getPaymentSuccessUrl(), orderNO, id);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "redirect:" + String.format(alipayConfig.getPaymentFailureUrL(), orderNO, id);

    }

同步通知结束后页面,假设是支付成功的话

4.异步通知

支付宝给我们这边发通知:告诉我们客户把这个单子支付成功与否。(异步通知的话是为了双保险,万一同步通知没收到的情况下,不至于订单状态没给改掉,这个异步通知会重复调用多次的哦)

参考代码

@PostMapping("/notifyPay")
    @ResponseBody
    public String notifyPay(HttpServletRequest request) {
        try {
            Map parameterMap = request.getParameterMap();
            String flag = alipayService.notify(parameterMap);
            return flag;
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        }

    }

微信支付相关功能

1.生成微信支付二维码接口

Api路径

/trade/api/wxpay/createqccode/{orderNo}

方法

GET

响应

{"data":

{"codeUrl":"weixin://wxpay/bizpayurl?pr=0MPWA9Ozz",

"payAmount":1928.00,

"count":1,

"hotelName":"比佛利山庄洛杉矶世纪城洲际酒店",

"roomId":106},

"errorCode":"0",

"msg":null,

"success":"true"}

参考代码如下:

 /**
     * 拿到生成二维码的codeUrl   微信统一下单的接口
     * @param orderNo
     * @return
     */
    @ResponseBody
    @GetMapping("/api/wxpay/createqccode/{orderNo}")
    public Dto<Object> createqccode(@PathVariable String orderNo) {

        try {
            ItripHotelOrder order = orderService.loadItripHotelOrder(orderNo);

            Map<String,String> map= new HashMap<>();

            //body商品描述
            map.put("body","爱旅行预订酒店微信下单");
            //out_trade_no商户订单号
            map.put("out_trade_no",order.getOrderNo());
            //total_fee	标价金额   单位是1
            map.put("total_fee","1");
            //spbill_create_ip终端IP
            map.put("spbill_create_ip","127.0.0.1");
            //notify_url通知地址
            map.put("notify_url",wxConfig.getNotifyUrl());
            //trade_type交易类型
            map.put("trade_type",wxConfig.getTrade_type());

            //调用统一下单接口

            WXPay  wxPay = new WXPay(wxConfig);
            Map<String, String> stringStringMap = wxPay.unifiedOrder(map);
            Map<String,Object> resultMap = new HashMap<>();
            if (stringStringMap.get("return_code").equals("SUCCESS") && stringStringMap.get("result_code").equals("SUCCESS")) {
                //调用微信支付统一下单成功了。可以拿到code_url

                resultMap.put("hotelName", order.getHotelName());
                resultMap.put("roomId", order.getRoomId());
                resultMap.put("count", order.getCount());
                resultMap.put("payAmount", order.getPayAmount());
                resultMap.put("codeUrl", stringStringMap.get("code_url"));
                return DtoUtil.returnDataSuccess(resultMap);

            }else{
                return DtoUtil.returnFail( stringStringMap.get("err_code_des"),"50000");
            }


        } catch (Exception e) {
            e.printStackTrace();
            return DtoUtil.returnFail("订单支付异常","50000");
        }

    }

前端页面效果

2.异步回调接口

客户扫码究竟支付成功还是失败,要微信那边告诉我爱旅行项目。然后修改订单状态 改实时库存表等操作

参考代码如下:

 //异步通知

    @PostMapping("/api/wxpay/notify")
    @ResponseBody
    public void notify(HttpServletRequest request,HttpServletResponse response){
        Map<String,String> returnMap = new HashMap<>();
        String returnMapXml = "";
       //用流的方式接受前端传过来的数据,  因为是xml
        try {

            WXPayRequest wxPayRequest = new WXPayRequest(wxConfig);
            StringBuffer callXml=new StringBuffer();
            ServletInputStream inputStream = request.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));//字符流
            String line = "";
            while ( (line = in.readLine())!= null ){
                callXml.append(line);
            }
            in.close();
            inputStream.close();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(callXml.toString());
            log.info("1.notify-params>>>>>>>>>>>:" + resultMap);
            if(resultMap.get("return_code").equals("SUCCESS")){
                //开始操作库存,修改订单等
                synchronized(this){
                    if(! orderService.processed(resultMap.get("out_trade_no")))
                    {
                        orderService.paySuccess(resultMap.get("out_trade_no"), 2,resultMap.get("transaction_id"));

                    }

                }
                //告诉微信这边已经收到通知了'
                returnMap.put("return_code","SUCCESS");
                returnMap.put("return_msg","OK");
                returnMapXml = WXPayUtil.mapToXml(returnMap);
                response.getWriter().write(returnMapXml);
                response.getWriter().flush();
                response.getWriter().close();



            }else{
                returnMap.put("return_code","FAIL");
                returnMap.put("return_msg","支付失败");
                response.getWriter().write(returnMapXml);

                response.getWriter().flush();
                response.getWriter().close();
                log.info("支付失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }


    }

3.微信扫码检测接口(前端自动调用)

这个接口的目的是为了跳转页面,不然用户扫码支付成功后一直停在二维码的页面不动的话对方会造成误解,以为自己没付成功呢。

Api路径

/trade/api/wxpay/queryorderstatus/{orderNo}

方法

GET

响应

注意:订单状态2为支付成功,页面会自动刷新

{"data":{"bookType":0,

"bookingDays":1,

"checkInDate":1648771200000,

"checkOutDate":1648857600000,

"count":1,"createdBy":29,

"creationDate":1648800212000,

"hotelId":25,"hotelName":"比佛利山庄洛杉矶世纪城洲际酒店",

"id":169,

"invoiceHead":null,

"invoiceType":1,

"isNeedInvoice":null,

"linkUserName":"111",

"modifiedBy":null,

"modifyDate":null,

"noticeEmail":"aa@aa.com",

"noticePhone":"13333333333",

"orderNo":"D1000001202204011603328f872b",

"orderStatus":0,

"orderType":1,

"payAmount":1928.00,

"payType":null,

"roomId":106,

"specialRequirement":"",

"tradeNo":null,

"userId":29},

"errorCode":"0",

"msg":null,

"success":"true"}

参考代码如下:

//微信支付轮询订单,查看订单是否支付成功
    @RequestMapping(value = "/api/wxpay/queryorderstatus/{orderNo}", method = RequestMethod.GET)
    @ResponseBody
    public Dto<ItripHotelOrder> queryOrderIsSuccess(@PathVariable String orderNo) {
        ItripHotelOrder order = null;
        try {
            order = orderService.loadItripHotelOrder(orderNo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return DtoUtil.returnDataSuccess(order);
    }

到店付相关功能

这个相对很简单,到店付的话,一点击支付就修改订单状态就行了。这个功能写到biz模块就行了,不要写在trade交易模块了。

参考代码如下:

    //到店付修改订单状态和库存
    @PostMapping("/api/hotelorder/updateorderstatusandpaytype")
    public Dto<Map<String, Boolean>> updateOrderStatusAndPayType(@RequestBody ItripModifyHotelOrderVO itripModifyHotelOrderVO, HttpServletRequest request) {
        String tokenString = request.getHeader("token");
        String userJson = redisAPI.get(tokenString);
        ItripUser currentUser = JSON.parseObject(userJson, ItripUser.class);
        if (null != currentUser && null != itripModifyHotelOrderVO) {
            try {
                ItripHotelOrder itripHotelOrder = new ItripHotelOrder();
                itripHotelOrder.setId(itripModifyHotelOrderVO.getId());
                //设置支付状态为:支付成功
                itripHotelOrder.setOrderStatus(2);
                itripHotelOrder.setPayType(3);//支付方式:1:支付宝 2:微信 3:到店付
                itripHotelOrder.setModifiedBy(currentUser.getId());
                itripHotelOrder.setModifyDate(new Date(System.currentTimeMillis()));
                hotelorderService.itriptxModifyItripHotelOrder(itripHotelOrder);
            } catch (Exception e) {
                e.printStackTrace();
                return DtoUtil.returnFail("修改订单失败", "100522");
            }
            return DtoUtil.returnSuccess("修改订单成功");
        } else if (null != currentUser && null == itripModifyHotelOrderVO) {
            return DtoUtil.returnFail("不能提交空,请填写订单信息", "100523");
        } else {
            return DtoUtil.returnFail("token失效,请重新登录", "100000");
        }
    }

好博客就要一起分享哦!分享海报

此处可发布评论

评论(1展开评论

蓝色妖姬 能力:10

2023-02-24 16:06:29

实训56班尹志文实名狗叫:"我无敌,我眼高手低,我就是狂,怎么了,我尹志文就是世界第一眼高手低,我叫尹志文"
点击查看更多评论

展开评论

您可能感兴趣的博客

客服QQ 1913284695