From 764513a257245410bf83649fd565068d674c6993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=85=89=E6=98=A5?= Date: Mon, 16 Aug 2021 23:48:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=B5=E5=BD=B1=E7=A5=A8?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 +- go.mod | 2 +- library.go | 5 ++ library/library.go | 5 -- go_test.go => library_test.go | 3 +- service/movieapi/v2/app.go | 84 +++++++++++++++++++ .../movieapi/v2/movie_info_get_ShowDate.go | 39 +++++++++ .../movieapi/v2/movie_info_get_cinema_list.go | 49 +++++++++++ .../movieapi/v2/movie_info_get_city_area.go | 41 +++++++++ .../movieapi/v2/movie_info_get_city_list.go | 30 +++++++ .../movieapi/v2/movie_info_get_hot_list.go | 54 ++++++++++++ .../v2/movie_info_get_schedule_list.go | 58 +++++++++++++ service/movieapi/v2/movie_info_get_sea.go | 51 +++++++++++ .../movieapi/v2/movie_info_get_show_list.go | 56 +++++++++++++ .../movieapi/v2/movie_info_get_soon_list.go | 54 ++++++++++++ service/movieapi/v2/movie_info_get_version.go | 22 +++++ service/movieapi/v2/sign.go | 52 ++++++++++++ 17 files changed, 599 insertions(+), 10 deletions(-) create mode 100644 library.go delete mode 100644 library/library.go rename go_test.go => library_test.go (53%) create mode 100644 service/movieapi/v2/app.go create mode 100644 service/movieapi/v2/movie_info_get_ShowDate.go create mode 100644 service/movieapi/v2/movie_info_get_cinema_list.go create mode 100644 service/movieapi/v2/movie_info_get_city_area.go create mode 100644 service/movieapi/v2/movie_info_get_city_list.go create mode 100644 service/movieapi/v2/movie_info_get_hot_list.go create mode 100644 service/movieapi/v2/movie_info_get_schedule_list.go create mode 100644 service/movieapi/v2/movie_info_get_sea.go create mode 100644 service/movieapi/v2/movie_info_get_show_list.go create mode 100644 service/movieapi/v2/movie_info_get_soon_list.go create mode 100644 service/movieapi/v2/movie_info_get_version.go create mode 100644 service/movieapi/v2/sign.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb2c719..51386adb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,3 @@ -## v1.0.19 / 2021-07-27 +## v1.0.20 / 2021-08-16 -- 测试版本 +- 增加电影票服务 \ No newline at end of file diff --git a/go.mod b/go.mod index 3ec5a94b..b4a8013c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module gitee.com/dtapps/go-library -go 1.16 +go 1.17 require ( github.com/bitly/go-simplejson v0.5.0 diff --git a/library.go b/library.go new file mode 100644 index 00000000..c69014d9 --- /dev/null +++ b/library.go @@ -0,0 +1,5 @@ +package go_library + +func Version() string { + return "v1.0.20" +} diff --git a/library/library.go b/library/library.go deleted file mode 100644 index 74a417b2..00000000 --- a/library/library.go +++ /dev/null @@ -1,5 +0,0 @@ -package library - -func Version() string { - return "v1.0.19" -} diff --git a/go_test.go b/library_test.go similarity index 53% rename from go_test.go rename to library_test.go index 88277870..a7fc96ff 100644 --- a/go_test.go +++ b/library_test.go @@ -2,10 +2,9 @@ package go_library import ( "fmt" - "gitee.com/dtapps/go-library/library" "testing" ) func TestName(t *testing.T) { - fmt.Println(library.Version()) + fmt.Println(Version()) } diff --git a/service/movieapi/v2/app.go b/service/movieapi/v2/app.go new file mode 100644 index 00000000..517f0c4e --- /dev/null +++ b/service/movieapi/v2/app.go @@ -0,0 +1,84 @@ +package v2 + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "math" + "net/http" + "strconv" + "strings" + "time" +) + +type App struct { + AppKey string + AppSecret string + Timeout time.Duration +} + +type ErrResp struct { + Success bool `json:"success"` + Message string `json:"message"` + Data interface{} `json:"data"` + Code int `json:"code"` +} + +func (app *App) request(url string, params map[string]interface{}) ([]byte, error) { + + // common params + params["time"] = time.Now().Unix() + params["appKey"] = app.AppKey + + // sign params + params["sign"] = app.getSign(app.AppSecret, params) + + var req *http.Request + req, err := http.NewRequest("POST", fmt.Sprintf("https://movieapi2.pintoto.cn/%s", url), strings.NewReader(app.getRequestData(params))) + if err != nil { + return nil, err + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + httpClient := &http.Client{} + httpClient.Timeout = app.Timeout + var response *http.Response + response, err = httpClient.Do(req) + if err != nil { + return nil, nil + } + + // 请求错误 + if response.StatusCode != 200 { + return nil, errors.New(fmt.Sprintf("请求错误:%d", response.StatusCode)) + } + + defer response.Body.Close() + body, err := ioutil.ReadAll(response.Body) + + // 检查错误 + apiErr := ErrResp{} + if err := json.Unmarshal(body, &apiErr); err != nil { + return nil, err + } + + // 接口状态错误 + if apiErr.Code != 200 { + return nil, errors.New(apiErr.Message) + } + return body, nil +} + +func (app *App) GradeToFloat64(i interface{}) float64 { + switch v := i.(type) { + case string: + float, _ := strconv.ParseFloat(v, 64) + return float + case float64: + return v + case int64: + return float64(v) / math.Pow10(0) + default: + return 0 + } +} diff --git a/service/movieapi/v2/movie_info_get_ShowDate.go b/service/movieapi/v2/movie_info_get_ShowDate.go new file mode 100644 index 00000000..c8144a62 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_ShowDate.go @@ -0,0 +1,39 @@ +package v2 + +import ( + "encoding/json" +) + +type GetShowDate struct { + FilmId int `json:"filmId"` // 影片id,由热映/即将上映接口获得 + CityId int `json:"cityId"` // 城市id,由城市列表接口获得 +} + +type GetShowDateResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + DateList []string `json:"dateList"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetShowDate 包含某电影的日期 https://www.showdoc.com.cn/1154868044931571/6091788579441818 +func (app *App) GetShowDate(param GetShowDate) (result GetShowDateResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-show-date", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_cinema_list.go b/service/movieapi/v2/movie_info_get_cinema_list.go new file mode 100644 index 00000000..c0fb707d --- /dev/null +++ b/service/movieapi/v2/movie_info_get_cinema_list.go @@ -0,0 +1,49 @@ +package v2 + +import ( + "encoding/json" +) + +type GetCinemaList struct { + CityId int `json:"cityId"` // 城市id +} + +type GetCinemaListResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + List []struct { + CinemaId int `json:"cinemaId"` // 影院id + CityId int `json:"cityId"` // 城市id + CinemaName string `json:"cinemaName"` // 影院名称 + Address string `json:"address"` // 影院地址 + Latitude float64 `json:"latitude"` // 纬度 + Longitude float64 `json:"longitude"` // 经度 + Phone string `json:"phone"` // 影院电话 + RegionName string `json:"regionName"` // 地区名称 + IsAcceptSoonOrder int `json:"isAcceptSoonOrder"` // 是否支持秒出票,0为不支持,1为支持 + NetPrice int `json:"netPrice"` // 当前影院最低价的排期 + } `json:"list"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetCinemaList 影院列表 https://www.showdoc.com.cn/1154868044931571/5866426126744792 +func (app *App) GetCinemaList(param GetCinemaList) (result GetCinemaListResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-cinema-list", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_city_area.go b/service/movieapi/v2/movie_info_get_city_area.go new file mode 100644 index 00000000..05267909 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_city_area.go @@ -0,0 +1,41 @@ +package v2 + +import ( + "encoding/json" +) + +type GetCityArea struct { + CityId int `json:"cityId"` // 城市id +} + +type GetCityAreaResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + List []struct { + AreaId int `json:"areaId"` // 区域id + AreaName string `json:"areaName"` // 区域名 + } `json:"list"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetCityArea 城市下区域 https://www.showdoc.com.cn/1154868044931571/6243539682553126 +func (app *App) GetCityArea(param GetCityArea) (result GetCityAreaResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-city-area", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_city_list.go b/service/movieapi/v2/movie_info_get_city_list.go new file mode 100644 index 00000000..90b9732e --- /dev/null +++ b/service/movieapi/v2/movie_info_get_city_list.go @@ -0,0 +1,30 @@ +package v2 + +import ( + "encoding/json" +) + +type GetCityListResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + List []struct { + PinYin string `json:"pinYin"` // 城市首字母 + RegionName string `json:"regionName"` // 城市名 + CityId int `json:"cityId"` // 城市id + } `json:"list"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetCityList 城市列表 https://www.showdoc.com.cn/1154868044931571/5865562425538244 +func (app *App) GetCityList() (result GetCityListResult, err error) { + body, err := app.request("movieapi/movie-info/get-city-list", map[string]interface{}{}) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_hot_list.go b/service/movieapi/v2/movie_info_get_hot_list.go new file mode 100644 index 00000000..cbf0e203 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_hot_list.go @@ -0,0 +1,54 @@ +package v2 + +import ( + "encoding/json" +) + +type GetHotList struct { + CityId int `json:"cityId"` // 传入cityId时,会显示当前城市下的相关电影。 如果不传,则默认显示北京的电影 +} + +type GetHotListResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + HasMore int `json:"hasMore"` + List []struct { + Director string `json:"director"` // 导演 + PublishDate string `json:"publishDate"` // 影片上映日期 + VersionTypes string `json:"versionTypes"` // 上映类型 + Language string `json:"language"` // 语言 + ShowStatus int `json:"showStatus"` // 放映状态:1 正在热映。2 即将上映 + Pic string `json:"pic"` // 海报URL地址 + FilmTypes string `json:"filmTypes"` // 影片类型 + LikeNum int `json:"likeNum"` // 想看人数 + Duration int `json:"duration"` // 时长,分钟 + Cast string `json:"cast"` // 主演 + FilmId int `json:"filmId"` // 影片id + Grade interface{} `json:"grade"` // 评分 + Intro string `json:"intro"` // 简介 + Name string `json:"name"` // 影片名 + } `json:"list"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetHotList 正在热映 https://www.showdoc.com.cn/1154868044931571/5866125707634369 +func (app *App) GetHotList(param GetHotList) (result GetHotListResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-hot-list", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_schedule_list.go b/service/movieapi/v2/movie_info_get_schedule_list.go new file mode 100644 index 00000000..d3d70df9 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_schedule_list.go @@ -0,0 +1,58 @@ +package v2 + +import ( + "encoding/json" +) + +type GetScheduleList struct { + CinemaId int `json:"cinemaId"` // 影院id +} + +type GetScheduleListResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + List []struct { + PlanType string `json:"planType"` // 影厅类型 2D 3D + ShowTime string `json:"showTime"` // 放映时间 + NetPrice int `json:"netPrice"` // 参考价,单位:分 + Language string `json:"language"` // 语言 + ShowDate string `json:"showDate"` // + Duration int `json:"duration"` // 时长,分钟 + ShowId string `json:"showId"` // 场次标识 + StopSellTime string `json:"stopSellTime"` // 停售时间 + CinemaId int `json:"cinemaId"` // 影院id + CinemaName string `json:"cinemaName"` // + FilmId int `json:"filmId"` // 影片id + ScheduleArea string `json:"scheduleArea"` // 该排期的分区座位价格信息,当此字段有值的时候,代表座位里面支持分区价格。 如果调用的是秒出票下单, 那价格必须计算正确,才能正确出票成功,即必须处理好座位分区价格 + FilmName string `json:"filmName"` // 影片名字 + HallName string `json:"hallName"` // 影厅名 + ShowVersionType string `json:"showVersionType"` // 场次类型 + } `json:"list"` + DiscountRule struct { + UpDiscountRate float64 `json:"upDiscountRate"` // 影院最高成本折扣,当价格大于等于39元时候,可取此字段 + DownDiscountRate float64 `json:"downDiscountRate"` // 影院最高成本折扣,当价格小于39元时候,可取此字段 + } `json:"discountRule"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetScheduleList 场次排期 https://www.showdoc.com.cn/1154868044931571/5866708808899217 +func (app *App) GetScheduleList(param GetScheduleList) (result GetScheduleListResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-schedule-list", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_sea.go b/service/movieapi/v2/movie_info_get_sea.go new file mode 100644 index 00000000..3f669198 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_sea.go @@ -0,0 +1,51 @@ +package v2 + +import ( + "encoding/json" +) + +type GetSeat struct { + ShowId string `json:"showId"` // 场次标识 +} + +type GetSeatResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + SeatData struct { + Restrictions int `json:"restrictions"` + Seats []GetSeatSeats `json:"seats"` + } `json:"seatData"` + } `json:"data"` + Success bool `json:"success"` +} + +type GetSeatSeats struct { + Area string `json:"area"` // 本座位所在的区域,根据场次排期接口的 scheduleArea 字段, 可得到当前座位的分区价格 + ColumnNo string `json:"columnNo"` // 列 + Lovestatus int `json:"lovestatus"` // 0为非情侣座;1为情侣座左;2为情侣座右 + RowNo string `json:"rowNo"` // 行 + SeatId string `json:"seatId"` // 座位标识符,锁座位和秒出票的时候需要用到 + SeatNo string `json:"seatNo"` // 座位名 + Status string `json:"status"` // N可售,LK不可售 +} + +// GetSeat 座位 https://www.showdoc.com.cn/1154868044931571/5866824368760475 +func (app *App) GetSeat(param GetSeat) (result GetSeatResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-seat", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_show_list.go b/service/movieapi/v2/movie_info_get_show_list.go new file mode 100644 index 00000000..f5852bc2 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_show_list.go @@ -0,0 +1,56 @@ +package v2 + +import ( + "encoding/json" +) + +type GetShowList struct { + Page int `json:"page"` // 页码,默认1 + Limit int `json:"limit"` // 条数,默认 10 + FilmId int `json:"filmId"` // 影片id,由热映/即将上映接口获得 + CityId int `json:"cityId"` // 城市id,由城市列表接口获得 + Area string `json:"area"` // 区域名,由区域列表接口获得 + Date string `json:"date"` // 日期,例:2020-01-01,不传默认当天 + Latitude float64 `json:"latitude"` // 纬度,不传则无距离排序 + Longitude float64 `json:"longitude"` // 经度,不传则无距离排序 +} + +type GetShowListResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + HasMore int `json:"hasMore"` + List []struct { + Address string `json:"address"` + ShowId string `json:"showId"` + Distance string `json:"distance"` + CinemaId int `json:"cinemaId"` + CinemaName string `json:"cinemaName"` + Latitude float64 `json:"latitude"` + ShowTime string `json:"showTime"` + HallName string `json:"hallName"` + Longitude float64 `json:"longitude"` + } `json:"list"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetShowList 包含某电影的影院 https://www.showdoc.com.cn/1154868044931571/6067372188376779 +func (app *App) GetShowList(param GetShowList) (result GetShowListResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-show-list", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_soon_list.go b/service/movieapi/v2/movie_info_get_soon_list.go new file mode 100644 index 00000000..aef8ddf5 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_soon_list.go @@ -0,0 +1,54 @@ +package v2 + +import ( + "encoding/json" +) + +type GetSoonList struct { + CityId int `json:"cityId"` // 传入cityId时,会显示当前城市下的相关电影。 如果不传,则默认显示北京的电影 +} + +type GetSoonListResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + HasMore int `json:"hasMore"` + List []struct { + Director string `json:"director"` // 导演 + PublishDate string `json:"publishDate"` // 影片上映日期 + VersionTypes string `json:"versionTypes"` // 上映类型 + Language string `json:"language"` // 语言 + ShowStatus int `json:"showStatus"` // 放映状态:1 正在热映。2 即将上映 + Pic string `json:"pic"` // 海报URL地址 + FilmTypes string `json:"filmTypes"` // 影片类型 + LikeNum int `json:"likeNum"` // 想看人数 + Duration int `json:"duration"` // 时长,分钟 + Cast string `json:"cast"` // 主演 + FilmId int `json:"filmId"` // 影片id + Grade interface{} `json:"grade"` // 评分 + Intro string `json:"intro"` // 简介 + Name string `json:"name"` // 影片名 + } `json:"list"` + } `json:"data"` + Success bool `json:"success"` +} + +// GetSoonList 即将上映 https://www.showdoc.com.cn/1154868044931571/5866125707634369 +func (app *App) GetSoonList(param GetSoonList) (result GetSoonListResult, err error) { + // api params + params := map[string]interface{}{} + b, _ := json.Marshal(¶m) + var m map[string]interface{} + _ = json.Unmarshal(b, &m) + for k, v := range m { + params[k] = v + } + body, err := app.request("movieapi/movie-info/get-soon-list", params) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/movie_info_get_version.go b/service/movieapi/v2/movie_info_get_version.go new file mode 100644 index 00000000..4e79f178 --- /dev/null +++ b/service/movieapi/v2/movie_info_get_version.go @@ -0,0 +1,22 @@ +package v2 + +import "encoding/json" + +type GetVersionResult struct { + Code int `json:"code"` + Message string `json:"message"` + Data string `json:"data"` + Success bool `json:"success"` +} + +// GetVersion 获取同步版本号 https://www.showdoc.com.cn/1154868044931571/6566701084841699 +func (app *App) GetVersion() (result GetVersionResult, err error) { + body, err := app.request("movieapi/movie-info/get-version", map[string]interface{}{}) + if err != nil { + return + } + if err = json.Unmarshal(body, &result); err != nil { + return + } + return +} diff --git a/service/movieapi/v2/sign.go b/service/movieapi/v2/sign.go new file mode 100644 index 00000000..49b994cd --- /dev/null +++ b/service/movieapi/v2/sign.go @@ -0,0 +1,52 @@ +package v2 + +import ( + "crypto/md5" + "encoding/json" + "fmt" + "net/url" + "sort" + "strconv" +) + +func (app *App) getSign(appSecret string, p map[string]interface{}) string { + var keys []string + for k := range p { + keys = append(keys, k) + } + sort.Strings(keys) + signStr := "" + for _, key := range keys { + signStr += fmt.Sprintf("%s=%s&", key, app.getString(p[key])) + } + signStr += fmt.Sprintf("appSecret=%s", appSecret) + // md5加密 + data := []byte(signStr) + has := md5.Sum(data) + return fmt.Sprintf("%x", has) +} + +func (app *App) getString(i interface{}) string { + switch v := i.(type) { + case string: + return v + case int: + return strconv.Itoa(v) + case bool: + return strconv.FormatBool(v) + default: + bytes, _ := json.Marshal(v) + return string(bytes) + } +} + +// 获取请求数据 +func (app *App) getRequestData(params map[string]interface{}) string { + // 公共参数 + args := url.Values{} + // 请求参数 + for key, val := range params { + args.Set(key, app.getString(val)) + } + return args.Encode() +}