26、【支付模块开发】——支付宝回调函数实现和查询用户订单状态接口编写

简介: 1、支付宝回调函数实现我们在调试支付宝沙箱环境的时候,支护宝会有一个回调函数,也就是在支付成功之后,可以调用我们支付之后需要执行的相关方法,从而达到数据库的数据和我们的操作相统一。

1、支付宝回调函数实现

我们在调试支付宝沙箱环境的时候,支护宝会有一个回调函数,也就是在支付成功之后,可以调用我们支付之后需要执行的相关方法,从而达到数据库的数据和我们的操作相统一。
首先我们先在本地将回调函数编写好~
OrderController类中新建我们的支付宝回调函数

img_3ed152d470aba6f200c6188dfcbfce24.png

*Controller:

 //支付宝回调函数
    @RequestMapping("alipay_callback.do")
    @ResponseBody
    public Object alipayCallback(HttpServletRequest request) {
        Map<String, String> params= Maps.newHashMap();

        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]+",";
            }
            params.put(name,valueStr);
        }

        logger.info("支付宝回调, sign:{},trade_status:{},参数:{}",params.get("sign"),params.get("trade_status"),params.toString());

        //!!! 验证回调的正确性,是不是支付宝发了,而且还要避免重复通知

        params.remove("sign_type");

        try {
            boolean alipayRSACheckedV2 = AlipaySignature.rsaCheckV2(params, Configs.getAlipayPublicKey(),"utf-8", Configs.getSignType());
            if(!alipayRSACheckedV2){
                return ServerResponse.createByErrorMessage("非法请求,验证不通过");
            }
        } catch (AlipayApiException e) {
            logger.info("支付宝回调异常",e);
        }

        //TODO  验证各种数据

        ServerResponse serverResponse = iOrderService.aliCallback(params);
        if(serverResponse.isSuccess()){
            return Const.AlipayCallback.RESPONSE_SUCCESS;
        }
        return Const.AlipayCallback.RESPONSE_FAILED;
    }


*Service:

 //支付宝的回调通知接口
    ServerResponse aliCallback(Map<String,String> params);

Const类中新增下面枚举函数:

img_71bcb7b58a32cedfb8d87104f5dc6e07.png
image.png

public enum OrderStatusEnum{
        CANCELED(0,"已取消"),
        NO_PAY(10,"未支付"),
        PAID(20,"已付款"),
        SHIPPED(40,"已发货"),
        ORDER_SUCCESS(50,"订单完成"),
        OEDER_CLOSE(60,"订单关闭");

        OrderStatusEnum(int code,String value){
            this.code=code;
            this.value=value;
        }

  public enum PayPlatformEnum{
        ALIPAY(1,"支付宝");

        PayPlatformEnum(int code,String value){
            this.code=code;
            this.value=value;
        }

        private String value;
        private  int code;

        public String getValue() {
            return value;
        }

        public int getCode() {
            return code;
        }
    }

*ServiceImpl:

//支付宝的回调通知接口
    public ServerResponse aliCallback(Map<String,String> params){

//        System.out.println("支付宝回调");
        //订单号
        Long orderNo = Long.parseLong(params.get("out_trade_no"));

        //交易号
        String tradeNo= params.get("trade_no");

        //交易状态
        String tradeStatus = params.get("trade_status");

//        System.out.println("tradeStatus:"+tradeStatus);
        Order order = orderMapper.selectByOrderNo(orderNo);

        if(order == null){
//            System.out.println("order == null");
            return  ServerResponse.createByErrorMessage("非该商场的订单,回调忽略");

        }
        if(order.getStatus() >= Const.OrderStatusEnum.PAID.getCode()){
//            System.out.println("支付宝重复调用");
            return ServerResponse.createBySuccess("支付宝重复调用");
        }
        String su="TRADE_SUCCESS";
        if(su.equals(tradeStatus)){
//            System.out.println("开始更新为支付完成状态");
            order.setPaymentTime(DateTimeUtil.strToDate(params.get("gmt_payment")));
            order.setStatus(Const.OrderStatusEnum.PAID.getCode());

            orderMapper.updateByPrimaryKeySelective(order);
        }

        PayInfo payInfo =new PayInfo();
        payInfo.setUserId(order.getUserId());
        payInfo.setOrderNo(order.getOrderNo());
        payInfo.setPayPlatform(Const.PayPlatformEnum.ALIPAY.getCode());
        payInfo.setPlatformNumber(tradeNo);
        payInfo.setPlatformStatus(tradeStatus);

        payInfoMapper.insert(payInfo);
        return ServerResponse.createBySuccess();
    }

selectByOrderNo这个方法需要我们自己编写:
*Mapper:

//根据订单号来查询订单是否存在
    Order selectByOrderNo(Long orderNo);

*Mappler.xml:

  <select id="selectByOrderNo" resultMap="BaseResultMap" parameterType="long" >
    select
    <include refid="Base_Column_List"/>
    from mmall_order
    where  order_no=#{orderNo}
  </select>

2、查询用户订单状态接口

*Controller:

//查询用户订单状态接口
    @RequestMapping("query_order_pay_status.do")
    @ResponseBody
    public ServerResponse<Boolean> queryOrderPayStatus(HttpSession session,Long orderNo){
        User user = (User) session.getAttribute(Const.CURRENT_USER);
        if (user == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        ServerResponse serverResponse = iOrderService.queryOrderPayStatus(user.getId(), orderNo);
        if(serverResponse.isSuccess()){
            return ServerResponse.createBySuccess(true);
        }
        return ServerResponse.createBySuccess(false);
    }

*Service:

  //查询订单状态的接口实现
    ServerResponse queryOrderPayStatus(Integer userId,Long orderNo);

*ServiceImpl:


    //查询订单状态的接口实现
    public ServerResponse queryOrderPayStatus(Integer userId,Long orderNo){
        Order order = orderMapper.selectByUserIdAndOrderNo(userId,orderNo);
        if(order == null){
            return ServerResponse.createByErrorMessage("用户没有该订单");
        }
        if(order.getStatus()>=Const.OrderStatusEnum.PAID.getCode()){
            return ServerResponse.createBySuccess();
        }
            return ServerResponse.createByError();
    }
 

selectByUserIdAndOrderNo是重用上面的方法,所以不再贴出来~

3、接口测试

1、给沙箱环境配置我们的回调地址:
打开沙箱环境:https://openhome.alipay.com/platform/appDaily.htm
在图上所示配置我们的回调地址

img_7ab6b923bb295283dd36848c0c5bd641.png
image.png

由于我们是在本地开发,所以需要将本地IP映射到公网,
这个教程有讲怎么将本地IP映射到公网:https://blog.csdn.net/czjlghndcy/article/details/81130029

映射好公网IP之后,我们就将对应生成的共网IP以及定义的接口访问地址粘贴到沙箱环境中的回调地址中即可~

测试接口:
支付一个未支付的:


img_7c1b4c34ef301748e67301fe667353cf.png
image.png

对生成的二维码进行支付


img_07dc63e349818d30797acf8b379bddc8.png

查询订单状态:


img_b54f03e11931667ec593e844a40a9003.png
image.png

显示已支付,So,我们的回调接口以及订单状态查询接口测试成功啦

相关文章
|
2月前
|
API
支付系统38-----支付宝支付---统一收单线下交易查询 第一步下单------》发起支付请求,登录,确认支付,查单接口开发,swagger接口全部呈现,
支付系统38-----支付宝支付---统一收单线下交易查询 第一步下单------》发起支付请求,登录,确认支付,查单接口开发,swagger接口全部呈现,
支付系统22------统一收单下单并支付页面接口-----调用支付宝接口,创建订单后期出现异常,能够打印出来的方法
支付系统22------统一收单下单并支付页面接口-----调用支付宝接口,创建订单后期出现异常,能够打印出来的方法
支付系统34----支付成功异步通知,处理重复通知,我们在我们程序当中找到处理订单的processOrder方法,我们要在更新订单状态和记录日志之前,先处理重复通知
支付系统34----支付成功异步通知,处理重复通知,我们在我们程序当中找到处理订单的processOrder方法,我们要在更新订单状态和记录日志之前,先处理重复通知
|
2月前
|
数据安全/隐私保护
支付系统18--------支付宝支付,支付调用流程,用时序表进行展示,三大用户用户,商户系统,支付宝,支付宝怎么知道跳转我们商户平台的那个页面,发送支付请求的时候,就携带着功的页面的参数,完整交易流
支付系统18--------支付宝支付,支付调用流程,用时序表进行展示,三大用户用户,商户系统,支付宝,支付宝怎么知道跳转我们商户平台的那个页面,发送支付请求的时候,就携带着功的页面的参数,完整交易流
|
2月前
|
前端开发 Java
支付系统20-----支付宝支付-----统一收单下单并支付页面接口----定义controller,跨域注解,统一收单下单并支付页面接口的创建,打印日志的注解
支付系统20-----支付宝支付-----统一收单下单并支付页面接口----定义controller,跨域注解,统一收单下单并支付页面接口的创建,打印日志的注解
|
2月前
|
API 开发工具
支付系统23-------使用沙箱账号进行支付测试,统一收单并支付页面接口的调用
支付系统23-------使用沙箱账号进行支付测试,统一收单并支付页面接口的调用
|
4月前
|
移动开发 前端开发 程序员
支付功能在app中的实现及支付功能模块化调用流程图
支付功能在app中的实现及支付功能模块化调用流程图
41 0
|
JSON API 数据安全/隐私保护
如何调用API接口获取商品数据
在当今数字化的时代,电子商务的崛起使得网购成为了人们生活中不可或缺的一部分。作为电子商务中最为熟知和流行的平台之一,拥有大量的商品资源和用户群体。如果你是一名开发者或者是对数据分析感兴趣的人,你可能会想要获取的商品数据以便进行商业分析或者开发自己的应用程序。那么,如何调用API接口来获取商品数据呢?本文将为你详细介绍这个过程。
|
10月前
|
存储 人工智能 API
调用API接口获取淘宝商品数据:详细指南与代码实践
在电子商务领域,淘宝作为中国最大的电商平台之一,其商品数据量庞大且丰富。对于开发者来说,如何有效地获取并利用这些数据,是一个重要的问题。本文将详细介绍如何使用API接口来获取淘宝商品数据,包括请求方式、参数设置、数据处理等内容,并通过代码实践来加深理解。
|
JSON 搜索推荐 API
如何调用api接口获取到商品数据
要调用API接口获取商品数据,需要进行以下步骤: 1. 确定API接口 首先需要确定要使用的API接口,可以通过搜索引擎或者相关文档来查找适合的API接口。以淘宝开放平台为例,可以使用淘宝的商品信息查询API接口来获取商品数据。 2. 注册API账号并获取API密钥 要使用API接口,需要先在API平台上注册一个账号,并获取相应的API密钥,例如淘宝的App Key和App Secret。