亚航app航班价格爬虫
条件:去程日期、回程日期、成人数、儿童数、婴儿数、出发机场、到达机场
结果:符合行程的所有航班信息( 主要包括价格、航班号、起飞机场、到达机场、起飞时间、降落时间、舱位等)
抓包分析
从上面的Headers和Form视图中可以得知,亚航采用的是https post 请求,请求及响应报文是加密的,请求头中wToken也是一个密文。
解密wToken及报文体
通过jeb反编译客户端,搜索wToken关键字,找到位于
ConstantHelper.ॱˋ(r2);
方法已经经过混淆处理过,可读性并不友好。
可以通过标记的方法,对相应变量作注释,还原涉及的功能函数。
经过分析及标记得知:
1):报文体的加解密位于MCrypt类中
2):wToken的计算位于IJAQAVMPSignComponent的avmpSign方法中
还原关键代码
出于对目标app的安全考虑,MCrypt及IJAQAVMPSignComponent的具体实现代码就不公开了,以免对其造成不良影响
编写调用客户端测试
//请求userSession,后续接口中需要此参数
public static String requestSession(String wTokenServerURL, String deviceID) throws Exception {
byte[] reqParams = createUserSessionData(deviceID);
String rs = request(wTokenServerURL, "103", deviceID, reqParams);
System.out.println("rs---> " + rs);
return (String) ((Map) (JSON.parseObject(rs).get("data"))).get("userSession");
}
//请求航班价格搜索
public static String requestFlightSearch(String wTokenServerURL, String userSession, String deviceID, int adultPax, int childPax, int infantPax, String departureStation, String arrivalStation, String departureDate, String returnDate) throws Exception {
byte[] reqParams = createFlightSearchData(userSession, deviceID, adultPax, childPax, infantPax, departureStation, arrivalStation, departureDate, returnDate);
return request(wTokenServerURL, "302", deviceID, reqParams);
}
写一个main方法执行一下
获取 清迈(CNX) - 武汉(WUH) 2020-01-08 1位成人的价格列表:
public static void main(String[] args) throws Exception {
String deviceID = "b20be1e49f423119";
String wTokenServerURL = "http://[ip]:[port]";
String userSession = requestSession(wTokenServerURL, deviceID);
System.out.println("userSession:" + userSession);
int adultPax = 1;
int childPax = 0;
int infantPax = 0;
String departureStation = "CNX";
String arrivalStation = "WUH";
String departureDate = DateFormatUtils.format(DateUtils.addDays(new Date(), 2), "yyyy-MM-dd");
String returnDate = "";
String rate = requestFlightSearch(wTokenServerURL, userSession, deviceID, adultPax, childPax, infantPax, departureStation, arrivalStation, departureDate, returnDate);
System.out.println("rs ---> " + rate);
}
解密后的返回结果报文:
{
"response": {
"responseTime": "2020-01-06 14:22:45",
"responseCode": 1000,
"responseMessage": "Success"
},
"meta": {
"cultureCode": "zh-CN",
"iosVersion": 1,
"androidVersion": 1,
"iosCompulsory": 1,
"androidCompulsory": 1,
"countryCacheVersion": 0,
"ssrCacheVersion": 0,
"stationCacheVersion": 0,
"routeCacheVersion": 0
},
"data": {
"SpecialNote": [
[
""
],
[
""
]
],
"SpecialNote2": [
[
""
],
[
""
]
],
"FlightSearch": [
[
{
"IsDirectFlight": true,
"JourneySellKey": "FD~ 570~ ~~DMK~01\/08\/2020 07:10~WUH~01\/08\/2020 11:35~~",
"LowestJourneyFare": 1,
"JourneyDiscount": 0,
"FlightStatus": 1,
"ValuePackAvailable": 1,
"HaveLowFare": 1,
"HavePremiumFare": 1,
"ValuePackageTotal": 830,
"ValuePackageTotalOffset": -86,
"LessThan24Hrs": 0,
"LessThan2Hrs": 0,
"ValuePackageSsrList": {
"Baggage": [
[
{
"SSRCode": "PBAB",
"Amount": 670,
"SsrCodeType": 0
},
{
"SSRCode": "VBPB",
"Amount": -68.8,
"SsrCodeType": 1
}
]
],
"Snack": [
[
{
"SSRCode": "VBPM",
"Amount": 0,
"SsrCodeType": 1
},
{
"SSRCode": "VPML",
"Amount": 120,
"SsrCodeType": 0
},
{
"SSRCode": "VGML",
"Amount": 120,
"SsrCodeType": 0
}
]
],
"Seat": [
[
{
"SSRCode": "DUSE",
"Amount": 99,
"SsrCodeType": 0
},
{
"SSRCode": "VBPS",
"Amount": -17.2,
"SsrCodeType": 1
}
]
],
"Insurance": [
[
{
"SSRCode": "INSV",
"Amount": 27,
"SsrCodeType": 0
},
{
"SSRCode": "VBIN",
"Amount": 0,
"SsrCodeType": 1
}
]
]
},
"CityIslandTransfer": false,
"TotalSegment": 1,
"HaveThruflightSegment": false,
"RouteAllowOfferValuepack": true,
"HaveComplimentaryInsuranceVP": true,
"HaveComplimentaryInsurancePremium": true,
"HaveVegetarianVP": true,
"HaveNonVegetarianVP": true,
"IsIndiaBooking": false,
"HaveInflightEntertainment": false,
"DepartureStation": "DMK",
"ArrivalStation": "WUH",
"DepartureDate": "2020-01-08T00:00:00",
"TotalJourneyAmount": {
"FareType": {
"1": {
"MinAvailableSeats": "7",
"MobileExclusive": null,
"ReservedDisplay1": null,
"ReservedDisplay2": null,
"MobilePromo": null,
"FareStatus": 1,
"FareUniqueID": "ID_2_0_1",
"ADT": {
"OriginalFare": 9044,
"FinalFare": 9044,
"CurrencyCode": "THB"
}
},
"0": {
"MinAvailableSeats": "7",
"MobileExclusive": null,
"ReservedDisplay1": null,
"ReservedDisplay2": null,
"MobilePromo": null,
"FareStatus": 1,
"FareUniqueID": "ID_2_0_0",
"ADT": {
"OriginalFare": 7964,
"FinalFare": 7964,
"CurrencyCode": "THB"
}
}
}
},
"TransitInfo": null,
"Segment": [
{
"AirlineCompany": "Thai AirAsia",
"ArrivalStation": "WUH",
"DepartureStation": "DMK",
"SegmentSellKey": "FD~ 570~ ~~DMK~01\/08\/2020 07:10~WUH~01\/08\/2020 11:35~~",
"STA": "2020-01-08T11:35:00",
"STD": "2020-01-08T07:10:00",
"International": "true",
"CarrierCode": "FD",
"FlightNumber": " 570",
"OpSuffix": " ",
"SegmentType": 0,
"IsThruflightSegment": false,
"DepartureCountryCode": "TH",
"ArrivalCountryCode": "CN",
"DepartureTimeZone_UtcOffset": "+0700",
"ArrivalTimeZone_UtcOffset": "+0800",
"STD_UTC": "2020-01-08 00:10:00",
"STA_UTC": "2020-01-08 03:35:00",
"EstimatedTime": "3 \u5c0f\u65f6 25 \u5206\u949f ",
"Fare": [
{
"ClassOfService": "P",
"RuleNumber": "AAB1",
"FareBasisCode": "P01H00",
"FareSequence": "53",
"FareClassOfService": "P",
"FareApplicationType": "Route",
"ProductClass": "EC",
"FareSellKey": "0~P~ ~AK~P01H00~AAB1~~0~53~~X",
"AvailableCount": "7",
"Status": "Active",
"PaxFare": {
"ADT": {
"PaxType": "ADT",
"PaxDiscountCode": "",
"FareDiscountCode": "",
"TotalFare": 7964,
"ServiceCharges": [
{
"CurrencyCode": "THB",
"Amount": "7214.0000",
"ChargeCode": "",
"ChargeType": "FarePrice",
"TicketCode": ""
},
{
"CurrencyCode": "THB",
"Amount": "750.0000000",
"ChargeCode": "",
"ChargeType": "Tax",
"TicketCode": ""
}
]
}
}
},
{
"ClassOfService": "PF",
"RuleNumber": "AAB1",
"FareBasisCode": "PF1F00",
"FareSequence": "52",
"FareClassOfService": "PF",
"FareApplicationType": "Route",
"ProductClass": "HF",
"FareSellKey": "0~PF~ ~AK~PF1F00~AAB1~~0~52~~X",
"AvailableCount": "7",
"Status": "Active",
"PaxFare": {
"ADT": {
"PaxType": "ADT",
"PaxDiscountCode": "",
"FareDiscountCode": "",
"TotalFare": 9044,
"ServiceCharges": [
{
"CurrencyCode": "THB",
"Amount": "8294.0000",
"ChargeCode": "",
"ChargeType": "FarePrice",
"TicketCode": ""
},
{
"CurrencyCode": "THB",
"Amount": "750.0000000",
"ChargeCode": "",
"ChargeType": "Tax",
"TicketCode": ""
}
]
}
}
}
],
"Legs": [
{
"DepartureStation": "DMK",
"ArrivalStation": "WUH",
"STD": "2020-01-08T07:10:00",
"STA": "2020-01-08T11:35:00",
"CarrierCode": "FD",
"FlightNumber": " 570",
"DepartureStationName": "\u66fc\u8c37 - \u5eca\u66fc",
"ArrivalStationName": "\u6b66\u6c49",
"LegsEstimatedTime": "3H25M"
}
],
"StationDisplay": [
"DMK",
"WUH"
],
"InftAvailability": 10
}
],
"FareProductClassList": {
"lowfare": 0,
"premiumflex": 1
}
},
{
"IsDirectFlight": true,
"JourneySellKey": "FD~ 572~ ~~DMK~01\/08\/2020 15:55~WUH~01\/08\/2020 20:20~~",
"LowestJourneyFare": 0,
"JourneyDiscount": 0,
"FlightStatus": 1,
"ValuePackAvailable": 1,
"HaveLowFare": 1,
"HavePremiumFare": 1,
"ValuePackageTotal": 830,
"ValuePackageTotalOffset": -86,
"LessThan24Hrs": 0,
"LessThan2Hrs": 0,
"ValuePackageSsrList": {
"Baggage": [
[
{
"SSRCode": "PBAB",
"Amount": 670,
"SsrCodeType": 0
},
{
"SSRCode": "VBPB",
"Amount": -68.8,
"SsrCodeType": 1
}
]
],
"Snack": [
[
{
"SSRCode": "VBPM",
"Amount": 0,
"SsrCodeType": 1
},
{
"SSRCode": "VPML",
"Amount": 120,
"SsrCodeType": 0
},
{
"SSRCode": "VGML",
"Amount": 120,
"SsrCodeType": 0
}
]
],
"Seat": [
[
{
"SSRCode": "DUSE",
"Amount": 99,
"SsrCodeType": 0
},
{
"SSRCode": "VBPS",
"Amount": -17.2,
"SsrCodeType": 1
}
]
],
"Insurance": [
[
{
"SSRCode": "INSV",
"Amount": 27,
"SsrCodeType": 0
},
{
"SSRCode": "VBIN",
"Amount": 0,
"SsrCodeType": 1
}
]
]
},
"CityIslandTransfer": false,
"TotalSegment": 1,
"HaveThruflightSegment": false,
"RouteAllowOfferValuepack": true,
"HaveComplimentaryInsuranceVP": true,
"HaveComplimentaryInsurancePremium": true,
"HaveVegetarianVP": true,
"HaveNonVegetarianVP": true,
"IsIndiaBooking": false,
"HaveInflightEntertainment": false,
"DepartureStation": "DMK",
"ArrivalStation": "WUH",
"DepartureDate": "2020-01-08T00:00:00",
"TotalJourneyAmount": {
"FareType": {
"1": {
"MinAvailableSeats": "7",
"MobileExclusive": null,
"ReservedDisplay1": null,
"ReservedDisplay2": null,
"MobilePromo": null,
"FareStatus": 1,
"FareUniqueID": "ID_2_1_1",
"ADT": {
"OriginalFare": 11774,
"FinalFare": 11774,
"CurrencyCode": "THB"
},
"INF": {
"CurrencyCode": null,
"FinalFare": null,
"OriginalFare": null
}
},
"0": {
"MinAvailableSeats": "7",
"MobileExclusive": null,
"ReservedDisplay1": null,
"ReservedDisplay2": null,
"MobilePromo": null,
"FareStatus": 1,
"FareUniqueID": "ID_2_1_0",
"ADT": {
"OriginalFare": 10694,
"FinalFare": 10694,
"CurrencyCode": "THB"
},
"INF": {
"CurrencyCode": null,
"FinalFare": null,
"OriginalFare": null
}
}
}
},
"TransitInfo": null,
"Segment": [
{
"AirlineCompany": "Thai AirAsia",
"ArrivalStation": "WUH",
"DepartureStation": "DMK",
"SegmentSellKey": "FD~ 572~ ~~DMK~01\/08\/2020 15:55~WUH~01\/08\/2020 20:20~~",
"STA": "2020-01-08T20:20:00",
"STD": "2020-01-08T15:55:00",
"International": "true",
"CarrierCode": "FD",
"FlightNumber": " 572",
"OpSuffix": " ",
"SegmentType": 0,
"IsThruflightSegment": false,
"DepartureCountryCode": "TH",
"ArrivalCountryCode": "CN",
"DepartureTimeZone_UtcOffset": "+0700",
"ArrivalTimeZone_UtcOffset": "+0800",
"STD_UTC": "2020-01-08 08:55:00",
"STA_UTC": "2020-01-08 12:20:00",
"EstimatedTime": "3 \u5c0f\u65f6 25 \u5206\u949f ",
"Fare": [
{
"ClassOfService": "U",
"RuleNumber": "AAB1",
"FareBasisCode": "U01H00",
"FareSequence": "53",
"FareClassOfService": "U",
"FareApplicationType": "Route",
"ProductClass": "EC",
"FareSellKey": "0~U~ ~AK~U01H00~AAB1~~0~53~~X",
"AvailableCount": "7",
"Status": "Active",
"PaxFare": {
"ADT": {
"PaxType": "ADT",
"PaxDiscountCode": "",
"FareDiscountCode": "",
"TotalFare": 10694,
"ServiceCharges": [
{
"CurrencyCode": "THB",
"Amount": "9944.0000",
"ChargeCode": "",
"ChargeType": "FarePrice",
"TicketCode": ""
},
{
"CurrencyCode": "THB",
"Amount": "750.0000000",
"ChargeCode": "",
"ChargeType": "Tax",
"TicketCode": ""
}
]
},
"INF": {
"ServiceCharges": null
}
}
},
{
"ClassOfService": "UF",
"RuleNumber": "AAB1",
"FareBasisCode": "UF1F00",
"FareSequence": "52",
"FareClassOfService": "UF",
"FareApplicationType": "Route",
"ProductClass": "HF",
"FareSellKey": "0~UF~ ~AK~UF1F00~AAB1~~0~52~~X",
"AvailableCount": "7",
"Status": "Active",
"PaxFare": {
"ADT": {
"PaxType": "ADT",
"PaxDiscountCode": "",
"FareDiscountCode": "",
"TotalFare": 11774,
"ServiceCharges": [
{
"CurrencyCode": "THB",
"Amount": "11024.0000",
"ChargeCode": "",
"ChargeType": "FarePrice",
"TicketCode": ""
},
{
"CurrencyCode": "THB",
"Amount": "750.0000000",
"ChargeCode": "",
"ChargeType": "Tax",
"TicketCode": ""
}
]
},
"INF": {
"ServiceCharges": null
}
}
}
],
"Legs": [
{
"DepartureStation": "DMK",
"ArrivalStation": "WUH",
"STD": "2020-01-08T15:55:00",
"STA": "2020-01-08T20:20:00",
"CarrierCode": "FD",
"FlightNumber": " 572",
"DepartureStationName": "\u66fc\u8c37 - \u5eca\u66fc",
"ArrivalStationName": "\u6b66\u6c49",
"LegsEstimatedTime": "3H25M"
}
],
"StationDisplay": [
"DMK",
"WUH"
],
"InftAvailability": 10
}
],
"FareProductClassList": {
"lowfare": 0,
"premiumflex": 1
}
}
]
],
"LowestFareArr": [
{
"2020-01-09": 10694,
"2020-01-07": 5759,
"2020-01-08": 7964
}
],
"JourneyDisplay": [
[
"DMK",
"WUH"
]
],
"FareDiscountAvailable": 0,
"MemberDiscountApply": false,
"userCurrencyCode": "CNY",
"displayCurrencyCode": "CNY",
"exchangeRate": "0.242372000000000000",
"departureCurrencyCode": "THB",
"AustraliaSpecialNote": [],
"IsUSBooking": false,
"IsPHBooking": false,
"IsPHDomestic": false,
"captchaVerification": 0
}
}
来源:CSDN
作者:super19911115
链接:https://blog.csdn.net/super19911115/article/details/103856044