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,我们的回调接口以及订单状态查询接口测试成功啦

相关文章
|
5月前
|
API
支付系统38-----支付宝支付---统一收单线下交易查询 第一步下单------》发起支付请求,登录,确认支付,查单接口开发,swagger接口全部呈现,
支付系统38-----支付宝支付---统一收单线下交易查询 第一步下单------》发起支付请求,登录,确认支付,查单接口开发,swagger接口全部呈现,
|
7月前
|
前端开发 小程序 JavaScript
电商小程序04实现登录逻辑
电商小程序04实现登录逻辑
|
5月前
|
前端开发 开发工具 数据库
支付系统资料-青戈版沙箱支付,订单编号样式设计,还有七天无理由退款,常与会员系统相搭配,内网穿透客户看到页面,前端展示,直播过程所有都能访问的写法
支付系统资料-青戈版沙箱支付,订单编号样式设计,还有七天无理由退款,常与会员系统相搭配,内网穿透客户看到页面,前端展示,直播过程所有都能访问的写法
支付系统资料-青戈版沙箱支付,订单编号样式设计,还有七天无理由退款,常与会员系统相搭配,内网穿透客户看到页面,前端展示,直播过程所有都能访问的写法
支付系统22------统一收单下单并支付页面接口-----调用支付宝接口,创建订单后期出现异常,能够打印出来的方法
支付系统22------统一收单下单并支付页面接口-----调用支付宝接口,创建订单后期出现异常,能够打印出来的方法
|
5月前
|
数据安全/隐私保护
支付系统18--------支付宝支付,支付调用流程,用时序表进行展示,三大用户用户,商户系统,支付宝,支付宝怎么知道跳转我们商户平台的那个页面,发送支付请求的时候,就携带着功的页面的参数,完整交易流
支付系统18--------支付宝支付,支付调用流程,用时序表进行展示,三大用户用户,商户系统,支付宝,支付宝怎么知道跳转我们商户平台的那个页面,发送支付请求的时候,就携带着功的页面的参数,完整交易流
支付系统42----支付宝支付-定时查单-订单已支付,如果我们在定时查单的状态中,我们明明已经支付的订单,却在本地状态中显示没有支付,这是因我们的异步通知因为种种原因没有接受到,支付宝端成功,本地失败
支付系统42----支付宝支付-定时查单-订单已支付,如果我们在定时查单的状态中,我们明明已经支付的订单,却在本地状态中显示没有支付,这是因我们的异步通知因为种种原因没有接受到,支付宝端成功,本地失败
|
5月前
|
前端开发 Java
支付系统20-----支付宝支付-----统一收单下单并支付页面接口----定义controller,跨域注解,统一收单下单并支付页面接口的创建,打印日志的注解
支付系统20-----支付宝支付-----统一收单下单并支付页面接口----定义controller,跨域注解,统一收单下单并支付页面接口的创建,打印日志的注解
|
5月前
|
API 开发工具
支付系统23-------使用沙箱账号进行支付测试,统一收单并支付页面接口的调用
支付系统23-------使用沙箱账号进行支付测试,统一收单并支付页面接口的调用
支付系统34----支付成功异步通知,处理重复通知,我们在我们程序当中找到处理订单的processOrder方法,我们要在更新订单状态和记录日志之前,先处理重复通知
支付系统34----支付成功异步通知,处理重复通知,我们在我们程序当中找到处理订单的processOrder方法,我们要在更新订单状态和记录日志之前,先处理重复通知
|
5月前
|
API 开发工具
支付系统17------支付宝支付-----API预览以及签名验签说明,出现支付宝扫描二维码的操作,支付完成之后,查询订单的状态,支付成功之后,需要退款调用的接口,退款状态的接口,完成退款之后,通知
支付系统17------支付宝支付-----API预览以及签名验签说明,出现支付宝扫描二维码的操作,支付完成之后,查询订单的状态,支付成功之后,需要退款调用的接口,退款状态的接口,完成退款之后,通知