订单系统 API 文档

支持赛事、住宿、餐饮、景点、商品五种服务类型的下单系统

🛒 创建订单接口

📋 接口基本信息

POST https://hapi.caixiangxiang.com/Order/CreateOrder

功能描述:创建新订单,支持赛事、住宿、餐饮、景点、商品五种服务类型。

请求头:Content-Type: application/x-www-form-urlencoded

认证:需要用户登录,通过会话Cookie或Token认证

📤 请求参数

通用参数(所有服务类型都需要)

参数名 类型 必填 说明
service_type Integer 服务类型:1-赛事,2-住宿,3-餐饮,4-景点,5-商品
service_id Integer 服务ID(关联t_services.id)
quantity Integer 购买数量,默认1
contact_name String 联系人姓名
contact_phone String 联系人电话
contact_email String 联系人邮箱
special_requirements String 特殊要求

服务类型特有参数

赛事 服务类型 1 - 赛事

参数名 类型 必填 说明
event_group_id Integer 赛事组别ID(关联t_service_event_groups.id)
participant_info JSON String 参与者信息,JSON格式数组

住宿 服务类型 2 - 住宿

参数名 类型 必填 说明
room_type_id Integer 房型ID(关联t_service_hotel_room_types.id)
checkin_date Date 入住日期,格式:YYYY-MM-DD
checkout_date Date 离店日期,格式:YYYY-MM-DD
room_count Integer 房间数量,默认1

餐饮 服务类型 3 - 餐饮

参数名 类型 必填 说明
dish_quantity Integer 菜品数量,默认1

景点 服务类型 4 - 景点

参数名 类型 必填 说明
visit_date Date 游览日期,格式:YYYY-MM-DD
ticket_type String 票务类型,如:成人票、儿童票、学生票

商品 服务类型 5 - 商品

参数名 类型 必填 说明
sku_id Integer SKU ID(关联t_service_goods_skus.id)
specifications JSON String 商品规格信息,JSON格式

📥 响应数据

成功响应
错误响应

HTTP状态码:200

{ "statusCode": 200, "message": "下单成功", "data": { "order_id": 123456, "order_sn": "2023121501234567", "payment_amount": "299.00", "expire_time": "2023-12-15 15:30:00", "items": [ { "item_id": 1001, "item_name": "赛事名称", "item_price": "299.00", "quantity": 1, "subtotal": "299.00", "specifications": { "event_group": "男子组5V5" } } ] } }

响应字段说明

字段 类型 说明
statusCode Integer 状态码,200表示成功
message String 操作结果消息
data Object 数据对象
data.order_id Integer 订单ID
data.order_sn String 订单号(业务唯一标识)
data.payment_amount Decimal 实际支付金额
data.expire_time String 订单过期时间,30分钟后过期
data.items Array[Object] 订单明细列表
状态码 错误消息 可能原因
400 服务类型参数错误 service_type不在1-5范围内
400 服务ID参数错误 service_id为空或无效
400 联系人信息不完整 contact_name或contact_phone为空
400 请选择赛事组别 赛事类型缺少event_group_id参数
400 住宿信息不完整 住宿类型缺少必填参数
401 用户未登录 未登录或会话过期
404 服务不存在 service_id对应的服务不存在
403 服务已下架 服务状态为下架
403 报名已截止 赛事报名截止时间已过
400 剩余名额不足 赛事组别名额已满
400 库存不足 商品/门票库存不足
500 下单失败,请稍后重试 服务器内部错误

🔍 使用示例

JavaScript Fetch - 赛事下单

// 赛事下单示例 const params = new URLSearchParams({ service_type: 1, service_id: 1001, event_group_id: 10, quantity: 2, contact_name: '张三', contact_phone: '13800138000', contact_email: 'zhangsan@example.com', special_requirements: '需要安排住宿', participant_info: JSON.stringify([ { name: '张三', id_card: '110101199001011234' }, { name: '李四', id_card: '110101199002022345' } ]) }); fetch('https://hapi.caixiangxiang.com/Order/CreateOrder', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params, credentials: 'include' // 包含Cookie }) .then(response => response.json()) .then(data => { if (data.statusCode === 200) { console.log('下单成功:', data.data); // 跳转到支付页面或显示订单信息 } else { console.error('下单失败:', data.message); } }) .catch(error => { console.error('请求失败:', error); });

JavaScript Fetch - 住宿下单

// 住宿下单示例 const params = new URLSearchParams({ service_type: 2, service_id: 2001, room_type_id: 5, checkin_date: '2025-12-20', checkout_date: '2025-12-22', room_count: 2, contact_name: '李四', contact_phone: '13900139000', contact_email: 'lisi@example.com', special_requirements: '需要无烟房' }); fetch('https://hapi.caixiangxiang.com/Order/CreateOrder', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params, credentials: 'include' }) .then(response => response.json()) .then(data => { // 处理响应 });

cURL - 商品下单

# 商品下单示例 curl -X POST "https://hapi.caixiangxiang.com/Order/CreateOrder" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "service_type=5&service_id=5001&sku_id=1001&quantity=3&contact_name=王五&contact_phone=13700137000" \ --cookie "PHPSESSID=your_session_id"

Python Requests - 景点门票下单

import requests # 景点门票下单示例 data = { 'service_type': 4, 'service_id': 4001, 'visit_date': '2025-12-25', 'ticket_type': '成人票', 'quantity': 4, 'contact_name': '赵六', 'contact_phone': '13600136000' } # 设置会话保持登录状态 session = requests.Session() # 先登录获取session # session.post('https://hapi.caixiangxiang.com/User/Login', data={'username': '...', 'password': '...'}) response = session.post('https://hapi.caixiangxiang.com/Order/CreateOrder', data=data) result = response.json() if result['statusCode'] == 200: print('下单成功,订单号:', result['data']['order_sn']) else: print('下单失败:', result['message'])

📊 订单状态接口

📋 订单状态说明

状态码 状态名称 说明 可操作
1 待支付 订单已创建,等待用户支付 支付、取消
2 已支付 用户已完成支付 查看详情
3 已确认 商户已确认订单 查看详情
4 进行中 服务正在进行中 查看进度
5 已完成 服务已完成 评价、查看
6 已退款 订单已退款 查看详情
7 已取消 订单已取消 重新下单
8 已关闭 订单已关闭 查看详情

支付状态说明

状态码 状态名称 说明
0 未支付 尚未支付
1 支付中 支付流程进行中
2 支付成功 支付成功
3 支付失败 支付失败
4 已退款 已退款

📋 获取订单详情接口

GET https://hapi.caixiangxiang.com/Order/GetOrderDetail

请求参数

参数名 类型 必填 说明
order_id Integer 订单ID

响应示例

{ "statusCode": 200, "message": "获取成功", "data": { "order_id": 123456, "order_sn": "2023121501234567", "user_id": 10001, "service_type": 1, "service_type_name": "赛事", "service_id": 1001, "order_title": "城市马拉松赛事报名", "order_status": 1, "order_status_name": "待支付", "payment_status": 0, "payment_status_name": "未支付", "total_amount": "299.00", "discount_amount": "0.00", "payment_amount": "299.00", "payment_method": null, "payment_time": null, "transaction_id": null, "quantity": 1, "contact_name": "张三", "contact_phone": "13800138000", "contact_email": "zhangsan@example.com", "special_requirements": "需要安排住宿", "event_group_id": 10, "checkin_date": null, "checkout_date": null, "book_date": null, "refund_reason": null, "refund_amount": "0.00", "refund_time": null, "cancel_reason": null, "cancel_time": null, "admin_notes": null, "create_time": "2023-12-15 14:30:00", "update_time": "2023-12-15 14:30:00", "expire_time": "2023-12-15 15:30:00", "items": [ { "item_id": 1001, "item_name": "城市马拉松赛事报名", "item_price": "299.00", "quantity": 1, "subtotal": "299.00", "specifications": { "event_group": "男子组5V5" }, "event_group_id": 10, "participant_info": [ { "name": "张三", "id_card": "110101199001011234" } ] } ], "snapshots": [ { "snapshot_id": 5001, "service_info": { "id": 1001, "title": "城市马拉松赛事", "cover_image": "https://example.com/images/marathon.jpg", "price": "299.00", "short_description": "年度城市马拉松赛事" } } ], "logs": [ { "log_id": 8001, "operator_type": 1, "operator_name": "用户", "action": "create_order", "old_status": null, "new_status": 1, "remark": "用户下单", "create_time": "2023-12-15 14:30:00" } ] } }

💰 支付相关接口

📋 获取支付信息接口

POST https://hapi.caixiangxiang.com/Order/GetPaymentInfo

请求参数

参数名 类型 必填 说明
order_id Integer 订单ID
payment_method String 支付方式:wxpay、alipay、unionpay

响应示例

{ "statusCode": 200, "message": "获取成功", "data": { "order_id": 123456, "order_sn": "2023121501234567", "payment_amount": "299.00", "payment_method": "wxpay", "pay_url": "https://pay.weixin.qq.com/xxxxxx", "qrcode_url": "https://pay.weixin.qq.com/qrcode/xxxxxx", "payment_params": { "appId": "wx1234567890", "timeStamp": "1702621800", "nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS", "package": "prepay_id=wx201410272009395522657a690389285100", "signType": "MD5", "paySign": "C380BEC2BFD727A4B6845133519F3AD6" }, "expire_time": "2023-12-15 15:30:00" } }

📋 支付回调接口

POST https://hapi.caixiangxiang.com/Order/PaymentNotify
注意:此接口为支付平台回调接口,由支付平台调用,开发者无需直接调用。

微信支付回调参数示例

{ "appid": "wx1234567890", "mch_id": "1234567890", "nonce_str": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS", "sign": "C380BEC2BFD727A4B6845133519F3AD6", "sign_type": "MD5", "result_code": "SUCCESS", "openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o", "trade_type": "JSAPI", "bank_type": "CFT", "total_fee": 299, "cash_fee": 299, "transaction_id": "1008450740201411110005820873", "out_trade_no": "2023121501234567", "time_end": "20141027235959" }

❌ 取消/退款接口

📋 取消订单接口

POST https://hapi.caixiangxiang.com/Order/CancelOrder

请求参数

参数名 类型 必填 说明
order_id Integer 订单ID
cancel_reason String 取消原因

响应示例

{ "statusCode": 200, "message": "订单取消成功", "data": { "order_id": 123456, "order_status": 7, "cancel_time": "2023-12-15 14:35:00", "refund_amount": "299.00" } }

📋 申请退款接口

POST https://hapi.caixiangxiang.com/Order/ApplyRefund

请求参数

参数名 类型 必填 说明
order_id Integer 订单ID
refund_reason String 退款原因
refund_amount Decimal 退款金额,默认全额退款

响应示例

{ "statusCode": 200, "message": "退款申请已提交", "data": { "order_id": 123456, "refund_amount": "299.00", "refund_status": "processing", "estimated_time": "1-3个工作日" } }

🔍 订单查询接口

📋 获取订单列表接口

GET https://hapi.caixiangxiang.com/Order/GetOrderList

请求参数

参数名 类型 必填 说明
page Integer 页码,默认1
pageSize Integer 每页数量,默认10,最大100
order_status Integer 订单状态筛选,1-8
service_type Integer 服务类型筛选,1-5
start_date Date 开始日期,格式:YYYY-MM-DD
end_date Date 结束日期,格式:YYYY-MM-DD
keyword String 关键词搜索(订单号、标题)

响应示例

{ "statusCode": 200, "message": "获取成功", "data": { "list": [ { "order_id": 123456, "order_sn": "2023121501234567", "service_type": 1, "service_type_name": "赛事", "order_title": "城市马拉松赛事报名", "order_status": 1, "order_status_name": "待支付", "payment_amount": "299.00", "quantity": 1, "create_time": "2023-12-15 14:30:00", "expire_time": "2023-12-15 15:30:00" }, { "order_id": 123457, "order_sn": "2023121501234568", "service_type": 2, "service_type_name": "住宿", "order_title": "豪华大床房预订", "order_status": 2, "order_status_name": "已支付", "payment_amount": "588.00", "quantity": 1, "create_time": "2023-12-14 10:20:00", "expire_time": null } ], "pagination": { "totalCount": 25, "pageSize": 10, "currentPage": 1, "pageCount": 3 }, "summary": { "total_orders": 25, "total_amount": "12500.00", "pending_payment": 3, "completed": 18 } } }

💡 最佳实践

1. 错误处理

建议在调用订单API时添加完善的错误处理机制:

async function createOrder(orderData) { try { const response = await fetch('https://hapi.caixiangxiang.com/Order/CreateOrder', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams(orderData), credentials: 'include' }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const result = await response.json(); if (result.statusCode === 200) { return { success: true, data: result.data, message: result.message }; } else { // 根据不同的错误码进行相应处理 switch(result.statusCode) { case 400: // 处理参数错误 console.error('参数错误:', result.message); break; case 401: // 处理未登录情况,跳转到登录页面 window.location.href = '/login'; break; case 403: // 处理权限不足或服务不可用 alert('服务不可用: ' + result.message); break; case 404: // 处理服务不存在 alert('您选择的项目不存在'); break; case 500: // 处理服务器错误 alert('服务器繁忙,请稍后重试'); break; default: alert(result.message || '下单失败'); } return { success: false, message: result.message, code: result.statusCode }; } } catch (error) { console.error('下单失败:', error); return { success: false, message: '网络错误,请检查网络连接', error: error.message }; } }

2. 订单过期处理

订单创建后30分钟过期,前端需要处理过期逻辑:

// 检查订单是否过期 function checkOrderExpiry(expireTime) { const now = new Date(); const expiryDate = new Date(expireTime); if (now > expiryDate) { // 订单已过期,显示提示并刷新页面 alert('订单已过期,请重新下单'); window.location.reload(); return false; } // 计算剩余时间(毫秒) const remainingTime = expiryDate - now; // 更新倒计时显示 updateCountdown(remainingTime); return true; } // 更新倒计时显示 function updateCountdown(milliseconds) { const minutes = Math.floor(milliseconds / 60000); const seconds = Math.floor((milliseconds % 60000) / 1000); document.getElementById('countdown').textContent = `支付剩余时间: ${minutes}:${seconds.toString().padStart(2, '0')}`; if (milliseconds <= 0) { clearInterval(countdownTimer); alert('订单已过期'); } } // 使用示例 const orderExpireTime = '2023-12-15 15:30:00'; checkOrderExpiry(orderExpireTime); // 每秒更新一次倒计时 const countdownTimer = setInterval(() => { const now = new Date(); const expiryDate = new Date(orderExpireTime); const remainingTime = expiryDate - now; updateCountdown(remainingTime); }, 1000);

3. 库存检查

在下单前建议先检查库存,避免用户下单后才发现库存不足:

// 检查库存 async function checkInventory(serviceType, serviceId, quantity, extraParams = {}) { const params = new URLSearchParams({ service_type: serviceType, service_id: serviceId, quantity: quantity, ...extraParams }); try { const response = await fetch(`https://hapi.caixiangxiang.com/Service/CheckInventory?${params}`); const result = await response.json(); if (result.statusCode === 200) { return { available: true, stock: result.data.stock_available }; } else { return { available: false, message: result.message }; } } catch (error) { console.error('检查库存失败:', error); return { available: false, message: '检查库存失败,请稍后重试' }; } } // 使用示例 - 检查赛事名额 const inventoryCheck = await checkInventory(1, 1001, 2, { event_group_id: 10 }); if (!inventoryCheck.available) { alert('名额不足: ' + inventoryCheck.message); return; }