sophhub 0.4.62 → 0.4.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flight-booking",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"types": [
|
|
5
5
|
"builtin"
|
|
6
6
|
],
|
|
7
7
|
"displayName": "国内机票预定",
|
|
8
8
|
"description": "国内机票查询、下单、出票、退票、改签全流程 skill",
|
|
9
9
|
"changelog": [
|
|
10
|
+
{
|
|
11
|
+
"changes": [
|
|
12
|
+
"修复创建订单/改签时 estimated_total 未计入平台服务费(serviceFee)的Bug",
|
|
13
|
+
"修复验舱验价(check_price)返回 code=10301 时实时价格未更新到 estimated_total 的Bug",
|
|
14
|
+
"新增价格变动提示:验价后票价变动时输出 priceChanged + priceDiff,供 Agent 向用户展示新旧价格对比",
|
|
15
|
+
"cmd_change_order 同步应用上述修复",
|
|
16
|
+
"创建订单/改签输出优先使用 API 返回的 totalAmount"
|
|
17
|
+
],
|
|
18
|
+
"date": "2026-07-23",
|
|
19
|
+
"version": "1.3.0"
|
|
20
|
+
},
|
|
10
21
|
{
|
|
11
22
|
"changes": [
|
|
12
23
|
"search 取消前 15 条截断,返回当日全部航班并在表格末尾新增汇总行",
|
|
@@ -32,5 +43,5 @@
|
|
|
32
43
|
}
|
|
33
44
|
],
|
|
34
45
|
"createdAt": "2026-04-09",
|
|
35
|
-
"updatedAt": "2026-
|
|
46
|
+
"updatedAt": "2026-07-23"
|
|
36
47
|
}
|
|
@@ -82,6 +82,41 @@ python3 {baseDir}/scripts/flight_booking.py create-order --flight-no CA1723 --ca
|
|
|
82
82
|
- 输出:订单号 `orderNo`、PNR、超时取消时间、应付金额等;用于第三步。
|
|
83
83
|
- **重要**:创建订单成功后**不要立即执行 pay-issue**。应先向用户展示上述信息,待用户确认后再执行第三步出票。
|
|
84
84
|
|
|
85
|
+
### 价格变动提示
|
|
86
|
+
|
|
87
|
+
创建订单时,验舱验价(`check_price`)可能发现实时票价与查询时不一致。脚本输出中的 `priceChanged` 字段标识是否发生价格变动:
|
|
88
|
+
|
|
89
|
+
- **`priceChanged: false`**:价格未变动,按正常流程展示订单信息,等待用户确认出票。
|
|
90
|
+
- **`priceChanged: true`**:价格已变动。`priceDiff` 字段包含新旧价格对比:
|
|
91
|
+
|
|
92
|
+
| priceDiff 字段 | 说明 |
|
|
93
|
+
|----------------|------|
|
|
94
|
+
| `originalSalePrice` | 查询时的票价(search 缓存) |
|
|
95
|
+
| `updatedSalePrice` | 实时票价(验价后) |
|
|
96
|
+
| `salePriceDiff` | 票价差额(正数为涨价,负数为降价) |
|
|
97
|
+
| `originalTotal` | 原订单总额(含税费服务费) |
|
|
98
|
+
| `updatedTotal` | 新订单总额(含税费服务费) |
|
|
99
|
+
| `totalDiff` | 总额差额 |
|
|
100
|
+
| `message` | API 返回的价格变动说明原文 |
|
|
101
|
+
|
|
102
|
+
**当 `priceChanged: true` 时,必须将价格变动明细以表格形式展示给用户**,例如:
|
|
103
|
+
|
|
104
|
+
> ⚠️ **价格变动提示**
|
|
105
|
+
>
|
|
106
|
+
> 验舱验价时发现票价已变动:
|
|
107
|
+
>
|
|
108
|
+
> | 项目 | 查询时 | 实时 |
|
|
109
|
+
> |------|--------|------|
|
|
110
|
+
> | 票价 | ¥{originalSalePrice} | ¥{updatedSalePrice} |
|
|
111
|
+
> | 差额 | | {salePriceDiff} |
|
|
112
|
+
> | 订单总额 | ¥{originalTotal} | ¥{updatedTotal} |
|
|
113
|
+
>
|
|
114
|
+
> 是否按新价格继续下单?
|
|
115
|
+
|
|
116
|
+
用户确认新价格后再进入第三步出票流程。若用户不接受新价格,可重新 search 选择其他航班。
|
|
117
|
+
|
|
118
|
+
- **改签同样适用**:`change-order` 输出中同样包含 `priceChanged` 字段,处理方式一致。
|
|
119
|
+
|
|
85
120
|
## 第三步:支付前校验与申请出票
|
|
86
121
|
|
|
87
122
|
**仅在用户明确确认要出票后再执行**(例如用户说「确认出票」「去支付」「可以出票了」等)。不得在创建订单后未经用户确认就自动执行本步骤。
|
|
@@ -800,16 +800,53 @@ def cmd_create_order(args: argparse.Namespace) -> int:
|
|
|
800
800
|
return 1
|
|
801
801
|
|
|
802
802
|
verify_res = check_price(flight, cabin, from_city, to_city)
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
803
|
+
vdata = verify_res.get("data") or {}
|
|
804
|
+
|
|
805
|
+
# 从验价结果中提取实时价格。check_price 返回 code="0"(成功)或 code="10301"(价格变动)
|
|
806
|
+
# 只要 data 中有 salePrice,就使用验价后的实时数据,覆盖 search 缓存的旧价格
|
|
807
|
+
if vdata.get("salePrice") is not None:
|
|
808
|
+
sale_price = float(vdata["salePrice"])
|
|
809
|
+
dep_tax = float(vdata.get("departureTax", flight.get("departureTax", 0)))
|
|
810
|
+
fuel_tax = float(vdata.get("fuelTax", flight.get("fuelTax", 0)))
|
|
807
811
|
shopping_code = vdata.get("shoppingCode", cabin.get("shoppingCode", ""))
|
|
808
812
|
price_info = vdata.get("priceInfo")
|
|
809
813
|
else:
|
|
814
|
+
# 验价失败且无价格数据,回退到 search 缓存值
|
|
815
|
+
sale_price = float(cabin.get("salePrice", 0))
|
|
816
|
+
dep_tax = float(flight.get("departureTax", 0))
|
|
817
|
+
fuel_tax = float(flight.get("fuelTax", 0))
|
|
810
818
|
shopping_code = cabin.get("shoppingCode", "")
|
|
819
|
+
price_info = None
|
|
820
|
+
|
|
821
|
+
# 服务费来源:航班顶层 serviceFee 或舱位层级 serviceFee(两者值相同,优先取 flight)
|
|
822
|
+
service_fee = float(flight.get("serviceFee", 0) or cabin.get("serviceFee", 0) or 0)
|
|
823
|
+
estimated_total = sale_price + dep_tax + fuel_tax + service_fee
|
|
824
|
+
|
|
825
|
+
# 价格变动检测:当 check_price 返回 code=10301 或 isUpdatePrice=true 时,记录新旧价格对比
|
|
826
|
+
price_changed = (
|
|
827
|
+
verify_res.get("code") == "10301"
|
|
828
|
+
or vdata.get("isUpdatePrice") is True
|
|
829
|
+
)
|
|
830
|
+
price_diff = None
|
|
831
|
+
if price_changed:
|
|
832
|
+
orig_sale = float(cabin.get("salePrice", 0))
|
|
833
|
+
orig_total = orig_sale \
|
|
834
|
+
+ float(flight.get("departureTax", 0)) \
|
|
835
|
+
+ float(flight.get("fuelTax", 0)) \
|
|
836
|
+
+ float(flight.get("serviceFee", 0) or cabin.get("serviceFee", 0) or 0)
|
|
837
|
+
price_diff = {
|
|
838
|
+
"originalSalePrice": orig_sale,
|
|
839
|
+
"updatedSalePrice": sale_price,
|
|
840
|
+
"salePriceDiff": round(sale_price - orig_sale, 2),
|
|
841
|
+
"originalTotal": round(orig_total, 2),
|
|
842
|
+
"updatedTotal": round(estimated_total, 2),
|
|
843
|
+
"totalDiff": round(estimated_total - orig_total, 2),
|
|
844
|
+
"departureTax": dep_tax,
|
|
845
|
+
"fuelTax": fuel_tax,
|
|
846
|
+
"serviceFee": service_fee,
|
|
847
|
+
"message": verify_res.get("msg", ""),
|
|
848
|
+
}
|
|
811
849
|
|
|
812
|
-
estimated_total = float(cabin.get("salePrice", 0)) + float(flight.get("departureTax", 0)) + float(flight.get("fuelTax", 0))
|
|
813
850
|
order_res = create_order(
|
|
814
851
|
flight_detail=flight,
|
|
815
852
|
cabin=cabin,
|
|
@@ -829,13 +866,22 @@ def cmd_create_order(args: argparse.Namespace) -> int:
|
|
|
829
866
|
}, ensure_ascii=False))
|
|
830
867
|
return 1
|
|
831
868
|
order_data = order_res.get("data", {})
|
|
832
|
-
|
|
869
|
+
|
|
870
|
+
# 输出:优先使用 API 返回的 totalAmount,否则用自行计算的 estimated_total
|
|
871
|
+
api_total = order_data.get("totalAmount")
|
|
872
|
+
display_total = float(api_total) if api_total is not None else estimated_total
|
|
873
|
+
|
|
874
|
+
output = {
|
|
833
875
|
"ok": True,
|
|
834
876
|
"orderNo": str(order_data.get("orderNo", "")),
|
|
835
877
|
"pnrCode": order_data.get("pnrCode"),
|
|
836
878
|
"expireTime": order_data.get("expireTime"),
|
|
837
|
-
"paymentTotalAmount":
|
|
838
|
-
|
|
879
|
+
"paymentTotalAmount": display_total,
|
|
880
|
+
"priceChanged": price_changed,
|
|
881
|
+
}
|
|
882
|
+
if price_diff:
|
|
883
|
+
output["priceDiff"] = price_diff
|
|
884
|
+
print(json.dumps(output, ensure_ascii=False, indent=2))
|
|
839
885
|
return 0
|
|
840
886
|
|
|
841
887
|
|
|
@@ -1067,16 +1113,49 @@ def cmd_change_order(args: argparse.Namespace) -> int:
|
|
|
1067
1113
|
return 1
|
|
1068
1114
|
|
|
1069
1115
|
verify_res = check_price(flight, cabin, from_city, to_city)
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1116
|
+
vdata = verify_res.get("data") or {}
|
|
1117
|
+
|
|
1118
|
+
# 从验价结果中提取实时价格。check_price 返回 code="0"(成功)或 code="10301"(价格变动)
|
|
1119
|
+
if vdata.get("salePrice") is not None:
|
|
1120
|
+
sale_price = float(vdata["salePrice"])
|
|
1121
|
+
dep_tax = float(vdata.get("departureTax", flight.get("departureTax", 0)))
|
|
1122
|
+
fuel_tax = float(vdata.get("fuelTax", flight.get("fuelTax", 0)))
|
|
1074
1123
|
shopping_code = vdata.get("shoppingCode", cabin.get("shoppingCode", ""))
|
|
1075
1124
|
price_info = vdata.get("priceInfo")
|
|
1076
1125
|
else:
|
|
1126
|
+
sale_price = float(cabin.get("salePrice", 0))
|
|
1127
|
+
dep_tax = float(flight.get("departureTax", 0))
|
|
1128
|
+
fuel_tax = float(flight.get("fuelTax", 0))
|
|
1077
1129
|
shopping_code = cabin.get("shoppingCode", "")
|
|
1130
|
+
price_info = None
|
|
1131
|
+
|
|
1132
|
+
service_fee = float(flight.get("serviceFee", 0) or cabin.get("serviceFee", 0) or 0)
|
|
1133
|
+
estimated_total = sale_price + dep_tax + fuel_tax + service_fee
|
|
1134
|
+
|
|
1135
|
+
price_changed = (
|
|
1136
|
+
verify_res.get("code") == "10301"
|
|
1137
|
+
or vdata.get("isUpdatePrice") is True
|
|
1138
|
+
)
|
|
1139
|
+
price_diff = None
|
|
1140
|
+
if price_changed:
|
|
1141
|
+
orig_sale = float(cabin.get("salePrice", 0))
|
|
1142
|
+
orig_total = orig_sale \
|
|
1143
|
+
+ float(flight.get("departureTax", 0)) \
|
|
1144
|
+
+ float(flight.get("fuelTax", 0)) \
|
|
1145
|
+
+ float(flight.get("serviceFee", 0) or cabin.get("serviceFee", 0) or 0)
|
|
1146
|
+
price_diff = {
|
|
1147
|
+
"originalSalePrice": orig_sale,
|
|
1148
|
+
"updatedSalePrice": sale_price,
|
|
1149
|
+
"salePriceDiff": round(sale_price - orig_sale, 2),
|
|
1150
|
+
"originalTotal": round(orig_total, 2),
|
|
1151
|
+
"updatedTotal": round(estimated_total, 2),
|
|
1152
|
+
"totalDiff": round(estimated_total - orig_total, 2),
|
|
1153
|
+
"departureTax": dep_tax,
|
|
1154
|
+
"fuelTax": fuel_tax,
|
|
1155
|
+
"serviceFee": service_fee,
|
|
1156
|
+
"message": verify_res.get("msg", ""),
|
|
1157
|
+
}
|
|
1078
1158
|
|
|
1079
|
-
estimated_total = float(cabin.get("salePrice", 0)) + float(flight.get("departureTax", 0)) + float(flight.get("fuelTax", 0))
|
|
1080
1159
|
change_res = order_change(
|
|
1081
1160
|
original_order_no=original_order_no,
|
|
1082
1161
|
flight_detail=flight,
|
|
@@ -1097,14 +1176,22 @@ def cmd_change_order(args: argparse.Namespace) -> int:
|
|
|
1097
1176
|
}, ensure_ascii=False))
|
|
1098
1177
|
return 1
|
|
1099
1178
|
change_data = change_res.get("data", {})
|
|
1100
|
-
|
|
1179
|
+
|
|
1180
|
+
api_total = change_data.get("totalAmount")
|
|
1181
|
+
display_total = float(api_total) if api_total is not None else estimated_total
|
|
1182
|
+
|
|
1183
|
+
output = {
|
|
1101
1184
|
"ok": True,
|
|
1102
1185
|
"changeOrderNo": str(change_data.get("orderNo", "")),
|
|
1103
1186
|
"pnrCode": change_data.get("pnrCode"),
|
|
1104
1187
|
"expireTime": change_data.get("expireTime"),
|
|
1105
|
-
"paymentTotalAmount":
|
|
1188
|
+
"paymentTotalAmount": display_total,
|
|
1189
|
+
"priceChanged": price_changed,
|
|
1106
1190
|
**rules,
|
|
1107
|
-
}
|
|
1191
|
+
}
|
|
1192
|
+
if price_diff:
|
|
1193
|
+
output["priceDiff"] = price_diff
|
|
1194
|
+
print(json.dumps(output, ensure_ascii=False, indent=2))
|
|
1108
1195
|
return 0
|
|
1109
1196
|
|
|
1110
1197
|
|