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

1、支付宝回调函数实现

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

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

*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类中新增下面枚举函数:

26、【支付模块开发】——支付宝回调函数实现和查询用户订单状态接口编写
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
在图上所示配置我们的回调地址

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

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

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

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


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

对生成的二维码进行支付


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

查询订单状态:


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

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

上一篇:PostgreSQL jdbc 错误代码映射(SQLSTATE)


下一篇:python调用支付宝支付接口