1. 程式人生 > >26、【支付模組開發】——支付寶回撥函式實現和查詢使用者訂單狀態介面編寫

26、【支付模組開發】——支付寶回撥函式實現和查詢使用者訂單狀態介面編寫

####1、支付寶回撥函式實現
我們在除錯支付寶沙箱環境的時候,支護寶會有一個回撥函式,也就是在支付成功之後,可以呼叫我們支付之後需要執行的相關方法,從而達到資料庫的資料和我們的操作相統一。
首先我們先在本地將回調函式編寫好~
OrderController類中新建我們的支付寶回撥函式

*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類中新增下面列舉函式:
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
在圖上所示配置我們的回撥地址
image.png

由於我們是在本地開發,所以需要將本地IP對映到公網,
這個教程有講怎麼將本地IP對映到公網:https://blog.csdn.net/czjlghndcy/article/details/81130029

對映好公網IP之後,我們就將對應生成的共網IP以及定義的介面訪問地址貼上到沙箱環境中的回撥地址中即可~

測試介面:
支付一個未支付的:
image.png
對生成的二維碼進行支付

查詢訂單狀態:
image.png

顯示已支付,So,我們的回撥介面以及訂單狀態查詢介面測試成功啦