酒店

创建订单更新时间:2019/11/07 10:26

涉及接口 hotel.order.create、hotel.order.detail
demo语言: Java
开发环境:
前端  jQuery类库、layui、 bootstrap
后端  jdk1.7以上、 tomcat8以上、 springmvc + spring + mybatis


下单前rp相关数据校验之后创建订单,本地保存订单数据,之后调用订单详情接口回显订单数据

注意

  • 1. 艺龙下单接口的超时时间为30s,建议代理也设置为30s,不然如果这边返回时间较长,代理接收为null

  • 2. 代理不能通过接收结果为null或空字符串判断下单失败,应该根据返回码是否错误判断

  • 3. 如果返回null,则应该隔30秒左右重新用相同参数下单,最多重试5次即可,如果之前下单成功,则返回之前的订单。


请求url

下单页面,选择rateplan和房间数量、填写联系人,手机号等参数
var createUrl = "/api/order/createOrder"; // 下单请求controller

var createReq = {
    "userName": $('#inputUser').val(),
    "arrivalDate": arrivalDate,
    "departureDate": $("#inputDepartureDate").val(),
    "hotelId": $("#inputHotelId").val(),
    "roomTypeId": $("#inputRoomTypeId").val(),
    "ratePlanId": $("#inputRatePlanId").val(),
    "earliestArrivalTime": (nextHour.substring(0,1) == "0" 
        ? arrivalNextDate: arrivalDate) + " " + nextHour + ":00",
    "latestArrivalTime": ($('#btnArrivalTime').attr("value").substring(0,1) == "0"
        ? arrivalNextDate: arrivalDate) + " " + $('#btnArrivalTime').attr("value"),
    "paymentType": $('#inputPaymentType').val(),
    "numberOfRooms": $("#btnRoomNum").attr("value"),
    "currencyCode": $('#inputTotalRate').attr("currencyCode"),
    "totalPrice": parseFloat($('#inputTotalRate').val()),
    "needInvoice": needInvoice,
    "invoice": invoice,
    "customerType": $('#inputCustomerType').val(),
    "customers": customerString,
    "contactName": $('#inputContactName').val(),
    "contactPhone": $('#inputContactPhone').val()
};


js请求后端

提交后端后返回下单结果,如果下单成功,调整到订单详情页面,如果显示失败原因
// 请求下单参数
var createResult = ajaxCommonForJson(createUrl, "POST", createReq);

// 处理下单结果
if (createResult != null) {
    if (createResult.success) {
        window.location.href = '/view/order/detail?user=' + $('#inputUser').val() + '&orderId=' + createResult.orderId;
    } else {
        alert(createResult.errorMessage);
    }
}


创建订单

后端通过http协议调用艺龙的hotel.order.create接口
public class HotelOrderCreateApi {
    private static double version = 1.50;
    private static EnumLocal locale = EnumLocal.zh_CN;
    private static boolean isHttps = true; // 测试环境换为false
    ...
    ...
    
    /**
     * 通过http工具类调用艺龙接口,将前端参数拼接为URL
     */
    public OrderCreateResult createOrder(CreateOrderCondition condition,
        String userName, String appKey, String secretKey) {
        OrderCreateResult result = new OrderCreateResult();
        String url = "";
        String responseData = "";
        try{
            //产生签名
            Long epoch = System.currentTimeMillis()/1000;
            if (condition.getCreditCard() != null) {
                condition.getCreditCard().setNumber(CipherUtil.desEncrypt(epoch.toString()
                +"#"+condition.getCreditCard().getNumber(), 
                appKey.substring(appKey.length()-8)));
            }
        
            BaseRequest<CreateOrderCondition> req = new BaseRequest<CreateOrderCondition>();
            req.Version = version;
            req.Local = locale;
            req.Request = condition;
            
            //请求参数转换为Json字符串
            String str = JsonUtil.entity2Json(req);
            String sig = Tool.md5(epoch + Tool.md5(str + appKey) + secretKey);
            
            //产生请求链接
            url = "http"+(this.isHttps ? "s": "")+ "://" 
                + serverHost + "/rest?format=json&method=hotel.order.create";
            url += "&user="+ userName +"&timestamp=";
            url += epoch;
            url += "&signature=";
            url += sig;
            url += "&data=" + Tool.encodeUri(str);
            
            log.info(url);
            //发送请求
            responseData = HttpUtil.Send("GET", url, "", "application/json");
            
            //返回值处理
            result = JsonUtil.jsonToObject(responseData, OrderCreateResult.class);
        } catch (Exception e) {
            log.info("[HotelOrderCreateApi] 异常: " + e);
            log.info("发送的url: " + url);
            log.info("返回值: " + responseData);
        }
        return result;
    }
    ...
    ...
}


保存订单信息

下单成功后,将订单保存到数据库中, 数据库表见sdk

// 创建数据库插入对象
OrderDo orderDo = new OrderDo();
orderDo.setOrderId(createResult.getResult().getOrderId());
orderDo.setAffiliateConfirmationId(affiliateConfirmationId);
orderDo.setUserId(request.getUserName());
orderDo.setBookingTime(new Date());
orderDo.setHotelId(request.getHotelId());
orderDo.setRoomTypeId(request.getRoomTypeId());
orderDo.setRatePlanId(request.getRatePlanId());
...
...
// 需要请求订单详情才能得知的信息 
// 获取订单详情
OrderIdCondition orderIdCondition = new OrderIdCondition();
orderIdCondition.setOrderId(createResult.getResult().getOrderId());
try {
    OrderInfoResult orderInfoResult = hotelOrderDetailApi.Invoke(orderIdCondition);
    if (orderInfoResult != null) {
        if (orderInfoResult.getCode().equals("0")) {
            OrderDetailResult orderDetail = orderInfoResult.getResult();
            orderDo.setStatus(orderDetail.getStatus());
            orderDo.setShowStatus(orderDetail.getShowStatus());
            orderDo.setHotelName(orderDetail.getHotelName());
            orderDo.setRoomName(orderDetail.getRoomTypeName());
            orderDo.setRatePlanName(orderDetail.getRatePlanName());
            orderDo.setCancelTime(orderDetail.getCancelTime());
        } else {
            logger.error(orderInfoResult.getCode());
        }
    } else {
        logger.error("请求订单详情超时或网络错误");
    }
} catch (Exception e) {
    // 捕获异常,以免影响正常的数据库操作
    logger.error(e);
}
...
...
// 调用dao对象将数据存入数据库
try {
    if (orderDao.addOrder(orderDo) < 1) {
        logger.error("【数据库操作失败,订单信息:】" + JsonUtil.entity2Json(orderDo));
    }
} catch (Exception e) {
    // 捕获异常,以免影响正常的返回操作
    logger.error("【数据库操作异常,订单信息:】" + JsonUtil.entity2Json(orderDo));
}
...


订单详情

后端通过http协议调用艺龙的hotel.order.detail接口,进行订单详情回显
public class HotelOrderDetailApi {
    private static double version = 1.50;
    private static EnumLocal locale = EnumLocal.zh_CN;
    private static boolean isHttps = true; // 测试环境换为false
    ...
    ...
    
    /**
     * 通过http工具类调用艺龙接口,将前端参数拼接为URL
     */
    public HotelOrderDetailResult getOrderDetail(OrderIdCondition condition, 
        String userName, String appKey, String secretKey) {
                
        HotelOrderDetailResult result = new HotelOrderDetailResult();
        String url = "";
        String responseData = "";
        try{
            BaseRequest<OrderIdCondition> req = new BaseRequest<OrderIdCondition>();
            req.Version = version;
            req.Local = locale;
            req.Request = condition;
        
            //请求参数转换为Json字符串
            String str = JsonUtil.entity2Json(req);
            
            //产生签名
            long epoch = System.currentTimeMillis()/1000;
            String sig = Tool.md5(epoch + Tool.md5(str + appKey) + secretKey);
            
            //产生请求链接
            url = "http"+(this.isHttps ? "s": "")+ "://" 
                + serverHost + "/rest?format=json&method=hotel.order.detail";
            url += "&user="+ userName +"&timestamp=";
            url += epoch;
            url += "&signature=";
            url += sig;
            url += "&data=" + Tool.encodeUri(str);
        
            //发送请求
            responseData = HttpUtil.Send("GET", url, "", "application/json");
            
            //返回值处理
            result = JsonUtil.jsonToObject(responseData, HotelOrderDetailResult.class);
        } catch (Exception e) {
            log.info("[HotelOrderDetailNgApi] 异常: " + e);
            log.info("发送的url: " + url);
            log.info("返回值: " + responseData);
        }
        return result;
    }
    ...
    ...
}


效果展示

下单成功后,跳转到订单详情页面
image.png