diff --git a/miniprogram/analysis/analysis.go b/miniprogram/analysis/analysis.go index 11e1de1..d3ca02c 100644 --- a/miniprogram/analysis/analysis.go +++ b/miniprogram/analysis/analysis.go @@ -125,7 +125,7 @@ func (analysis *Analysis) GetAnalysisDailySummary(beginDate, endDate string) (re if err != nil { return } - fmt.Println(string(response)) + err = json.Unmarshal(response, &result) if err != nil { return diff --git a/officialaccount/datacube/broadcast.go b/officialaccount/datacube/broadcast.go new file mode 100644 index 0000000..2fd980b --- /dev/null +++ b/officialaccount/datacube/broadcast.go @@ -0,0 +1,270 @@ +package datacube + +import ( + "fmt" + "github.com/silenceper/wechat/v2/util" +) + +const ( + getArticleSummary = "https://api.weixin.qq.com/datacube/getarticlesummary" + getArticleTotal = "https://api.weixin.qq.com/datacube/getarticletotal" + getUserRead = "https://api.weixin.qq.com/datacube/getuserread" + getUserReadHour = "https://api.weixin.qq.com/datacube/getuserreadhour" + getUserShare = "https://api.weixin.qq.com/datacube/getusershare" + getUserShareHour = "https://api.weixin.qq.com/datacube/getusersharehour" +) + +//ResArticleSummary 获取图文群发每日数据响应 +type ResArticleSummary struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + MsgID string `json:"msgid"` + Title string `json:"title"` + IntPageReadUser int `json:"int_page_read_user"` + IntPageReadCount int `json:"int_page_read_count"` + OriPageReadUser int `json:"ori_page_read_user"` + OriPageReadCount int `json:"ori_page_read_count"` + ShareUser int `json:"share_user"` + ShareCount int `json:"share_count"` + AddToFavUser int `json:"add_to_fav_user"` + AddToFavCount int `json:"add_to_fav_count"` + } `json:"list"` +} + +//ResArticleTotal 获取图文群发总数据响应 +type ResArticleTotal struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + MsgID string `json:"msgid"` + Title string `json:"title"` + Details []ArticleTotalDetails `json:"details"` + } `json:"list"` +} + +//ArticleTotalDetails 获取图文群发总数据响应文字详情 +type ArticleTotalDetails struct { + StatDate string `json:"stat_date"` + TargetUser int `json:"target_user"` + IntPageReadUser int `json:"int_page_read_user"` + IntPageReadCount int `json:"int_page_read_count"` + OriPageReadUser int `json:"ori_page_read_user"` + OriPageReadCount int `json:"ori_page_read_count"` + ShareUser int `json:"share_user"` + ShareCount int `json:"share_count"` + AddToFavUser int `json:"add_to_fav_user"` + AddToFavCount int `json:"add_to_fav_count"` + IntPageFromSessionReadUser int `json:"int_page_from_session_read_user"` + IntPageFromSessionReadCount int `json:"int_page_from_session_read_count"` + IntPageFromHistMsgReadUser int `json:"int_page_from_hist_msg_read_user"` + IntPageFromHistMsgReadCount int `json:"int_page_from_hist_msg_read_count"` + IntPageFromFeedReadUser int `json:"int_page_from_feed_read_user"` + IntPageFromFeedReadCount int `json:"int_page_from_feed_read_count"` + IntPageFromFriendsReadUser int `json:"int_page_from_friends_read_user"` + IntPageFromFriendsReadCount int `json:"int_page_from_friends_read_count"` + IntPageFromOtherReadUser int `json:"int_page_from_other_read_user"` + IntPageFromOtherReadCount int `json:"int_page_from_other_read_count"` + FeedShareFromSessionUser int `json:"feed_share_from_session_user"` + FeedShareFromSessionCnt int `json:"feed_share_from_session_cnt"` + FeedShareFromFeedUser int `json:"feed_share_from_feed_user"` + FeedShareFromFeedCnt int `json:"feed_share_from_feed_cnt"` + FeedShareFromOtherUser int `json:"feed_share_from_other_user"` + FeedShareFromOtherCnt int `json:"feed_share_from_other_cnt"` +} + +//ResUserRead 获取图文统计数据响应 +type ResUserRead struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + UserSource int `json:"user_source"` + IntPageReadUser int `json:"int_page_read_user"` + IntPageReadCount int `json:"int_page_read_count"` + OriPageReadUser int `json:"ori_page_read_user"` + OriPageReadCount int `json:"ori_page_read_count"` + ShareUser int `json:"share_user"` + ShareCount int `json:"share_count"` + AddToFavUser int `json:"add_to_fav_user"` + AddToFavCount int `json:"add_to_fav_count"` + } `json:"list"` +} + +//ResUserReadHour 获取图文统计分时数据 +type ResUserReadHour struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + RefHour int `json:"ref_hour"` + UserSource int `json:"user_source"` + IntPageReadUser int `json:"int_page_read_user"` + IntPageReadCount int `json:"int_page_read_count"` + OriPageReadUser int `json:"ori_page_read_user"` + OriPageReadCount int `json:"ori_page_read_count"` + ShareUser int `json:"share_user"` + ShareCount int `json:"share_count"` + AddToFavUser int `json:"add_to_fav_user"` + AddToFavCount int `json:"add_to_fav_count"` + } `json:"list"` +} + +//ResUserShare 获取图文分享转发数据 +type ResUserShare struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + ShareScene int `json:"share_scene"` + ShareCount int `json:"share_count"` + ShareUser int `json:"share_user"` + } `json:"list"` +} + +//ResUserShareHour 获取图文分享转发分时数据 +type ResUserShareHour struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + RefHour int `json:"ref_hour"` + ShareScene int `json:"share_scene"` + ShareCount int `json:"share_count"` + ShareUser int `json:"share_user"` + } `json:"list"` +} + +//GetArticleSummary 获取图文群发每日数据 +func (cube *DataCube) GetArticleSummary(s string, e string) (resArticleSummary ResArticleSummary, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getArticleSummary, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resArticleSummary, "GetArticleSummary") + return +} + +//GetArticleTotal 获取图文群发总数据 +func (cube *DataCube) GetArticleTotal(s string, e string) (resArticleTotal ResArticleTotal, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getArticleTotal, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resArticleTotal, "GetArticleTotal") + return +} + +//GetUserRead 获取图文统计数据 +func (cube *DataCube) GetUserRead(s string, e string) (resUserRead ResUserRead, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUserRead, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUserRead, "GetUserRead") + return +} + +//GetUserReadHour 获取图文统计分时数据 +func (cube *DataCube) GetUserReadHour(s string, e string) (resUserReadHour ResUserReadHour, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUserReadHour, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUserReadHour, "GetUserReadHour") + return +} + +//GetUserShare 获取图文分享转发数据 +func (cube *DataCube) GetUserShare(s string, e string) (resUserShare ResUserShare, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUserShare, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUserShare, "GetUserShare") + return +} + +//GetUserShareHour 获取图文分享转发分时数据 +func (cube *DataCube) GetUserShareHour(s string, e string) (resUserShareHour ResUserShareHour, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUserShareHour, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUserShareHour, "GetUserShareHour") + return +} diff --git a/officialaccount/datacube/datacube.go b/officialaccount/datacube/datacube.go new file mode 100644 index 0000000..22e593d --- /dev/null +++ b/officialaccount/datacube/datacube.go @@ -0,0 +1,22 @@ +package datacube + +import ( + "github.com/silenceper/wechat/v2/officialaccount/context" +) + +type reqDate struct { + BeginDate string `json:"begin_date"` + EndDate string `json:"end_date"` +} + +//DataCube 数据统计 +type DataCube struct { + *context.Context +} + +//NewCube 数据统计 +func NewCube(context *context.Context) *DataCube { + dataCube := new(DataCube) + dataCube.Context = context + return dataCube +} diff --git a/officialaccount/datacube/interface.go b/officialaccount/datacube/interface.go new file mode 100644 index 0000000..23046df --- /dev/null +++ b/officialaccount/datacube/interface.go @@ -0,0 +1,82 @@ +package datacube + +import ( + "fmt" + "github.com/silenceper/wechat/v2/util" +) + +const ( + getInterfaceSummary = "https://api.weixin.qq.com/datacube/getinterfacesummary" + getInterfaceSummaryHour = "https://api.weixin.qq.com/datacube/getinterfacesummaryhour" +) + +//ResInterfaceSummary 接口分析数据响应 +type ResInterfaceSummary struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + CallbackCount int `json:"callback_count"` + FailCount int `json:"fail_count"` + TotalTimeCost int `json:"total_time_cost"` + MaxTimeCost int `json:"max_time_cost"` + } `json:"list"` +} + +//ResInterfaceSummaryHour 接口分析分时数据响应 +type ResInterfaceSummaryHour struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + RefHour int `json:"ref_hour"` + CallbackCount int `json:"callback_count"` + FailCount int `json:"fail_count"` + TotalTimeCost int `json:"total_time_cost"` + MaxTimeCost int `json:"max_time_cost"` + } `json:"list"` +} + +//GetInterfaceSummary 获取接口分析数据 +func (cube *DataCube) GetInterfaceSummary(s string, e string) (resInterfaceSummary ResInterfaceSummary, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getInterfaceSummary, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resInterfaceSummary, "GetInterfaceSummary") + return +} + +//GetInterfaceSummaryHour 获取接口分析分时数据 +func (cube *DataCube) GetInterfaceSummaryHour(s string, e string) (resInterfaceSummaryHour ResInterfaceSummaryHour, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getInterfaceSummaryHour, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resInterfaceSummaryHour, "GetInterfaceSummaryHour") + return +} diff --git a/officialaccount/datacube/message.go b/officialaccount/datacube/message.go new file mode 100644 index 0000000..eccad61 --- /dev/null +++ b/officialaccount/datacube/message.go @@ -0,0 +1,252 @@ +package datacube + +import ( + "fmt" + "github.com/silenceper/wechat/v2/util" +) + +const ( + getUpstreamMsg = "https://api.weixin.qq.com/datacube/getupstreammsg" + getUpstreamMsgHour = "https://api.weixin.qq.com/datacube/getupstreammsghour" + getUpstreamMsgWeek = "https://api.weixin.qq.com/datacube/getupstreammsgweek" + getUpstreamMsgMonth = "https://api.weixin.qq.com/datacube/getupstreammsgmonth" + getUpstreamMsgDist = "https://api.weixin.qq.com/datacube/getupstreammsgdist" + getUpstreamMsgDistWeek = "https://api.weixin.qq.com/datacube/getupstreammsgdistweek" + getUpstreamMsgDistMonth = "https://api.weixin.qq.com/datacube/getupstreammsgdistmonth" +) + +//ResUpstreamMsg 获取消息发送概况数据响应 +type ResUpstreamMsg struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + MsgType int `json:"msg_type"` + MsgUser int `json:"msg_user"` + MsgCount int `json:"msg_count"` + } `json:"list"` +} + +//ResUpstreamMsgHour 获取消息分送分时数据响应 +type ResUpstreamMsgHour struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + RefHour int `json:"ref_hour"` + MsgType int `json:"msg_type"` + MsgUser int `json:"msg_user"` + MsgCount int `json:"msg_count"` + } `json:"list"` +} + +//ResUpstreamMsgWeek 获取消息发送周数据响应 +type ResUpstreamMsgWeek struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + MsgType int `json:"msg_type"` + MsgUser int `json:"msg_user"` + MsgCount int `json:"msg_count"` + } `json:"list"` +} + +//ResUpstreamMsgMonth 获取消息发送月数据响应 +type ResUpstreamMsgMonth struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + MsgType int `json:"msg_type"` + MsgUser int `json:"msg_user"` + MsgCount int `json:"msg_count"` + } `json:"list"` +} + +//ResUpstreamMsgDist 获取消息发送分布数据响应 +type ResUpstreamMsgDist struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + CountInterval int `json:"count_interval"` + MsgUser int `json:"msg_user"` + } `json:"list"` +} + +//ResUpstreamMsgDistWeek 获取消息发送分布周数据响应 +type ResUpstreamMsgDistWeek struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + CountInterval int `json:"count_interval"` + MsgUser int `json:"msg_user"` + } `json:"list"` +} + +//ResUpstreamMsgDistMonth 获取消息发送分布月数据响应 +type ResUpstreamMsgDistMonth struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + CountInterval int `json:"count_interval"` + MsgUser int `json:"msg_user"` + } `json:"list"` +} + +//GetUpstreamMsg 获取消息发送概况数据 +func (cube *DataCube) GetUpstreamMsg(s string, e string) (resUpstreamMsg ResUpstreamMsg, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUpstreamMsg, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUpstreamMsg, "GetUpstreamMsg") + return +} + +//GetUpstreamMsgHour 获取消息分送分时数据 +func (cube *DataCube) GetUpstreamMsgHour(s string, e string) (resUpstreamMsgHour ResUpstreamMsgHour, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUpstreamMsgHour, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUpstreamMsgHour, "GetUpstreamMsgHour") + return +} + +//GetUpstreamMsgWeek 获取消息发送周数据 +func (cube *DataCube) GetUpstreamMsgWeek(s string, e string) (resUpstreamMsgWeek ResUpstreamMsgWeek, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUpstreamMsgWeek, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUpstreamMsgWeek, "GetUpstreamMsgWeek") + return +} + +//GetUpstreamMsgMonth 获取消息发送月数据 +func (cube *DataCube) GetUpstreamMsgMonth(s string, e string) (resUpstreamMsgMonth ResUpstreamMsgMonth, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUpstreamMsgMonth, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUpstreamMsgMonth, "GetUpstreamMsgMonth") + return +} + +//GetUpstreamMsgDist 获取消息发送分布数据 +func (cube *DataCube) GetUpstreamMsgDist(s string, e string) (resUpstreamMsgDist ResUpstreamMsgDist, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUpstreamMsgDist, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUpstreamMsgDist, "GetUpstreamMsgDist") + return +} + +//GetUpstreamMsgDistWeek 获取消息发送分布周数据 +func (cube *DataCube) GetUpstreamMsgDistWeek(s string, e string) (resUpstreamMsgDistWeek ResUpstreamMsgDistWeek, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUpstreamMsgDistWeek, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUpstreamMsgDistWeek, "GetUpstreamMsgDistWeek") + return +} + +//GetUpstreamMsgDistMonth 获取消息发送分布月数据 +func (cube *DataCube) GetUpstreamMsgDistMonth(s string, e string) (resUpstreamMsgDistMonth ResUpstreamMsgDistMonth, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUpstreamMsgDistMonth, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUpstreamMsgDistMonth, "GetUpstreamMsgDistMonth") + return +} diff --git a/officialaccount/datacube/publisher.go b/officialaccount/datacube/publisher.go new file mode 100644 index 0000000..29a4075 --- /dev/null +++ b/officialaccount/datacube/publisher.go @@ -0,0 +1,306 @@ +package datacube + +import ( + "encoding/json" + "fmt" + "github.com/silenceper/wechat/v2/util" + "net/url" + "strconv" +) + +//AdSlot 广告位类型 +type AdSlot string + +const ( + //SlotIDBizBottom 公众号底部广告 + SlotIDBizBottom AdSlot = "SLOT_ID_BIZ_BOTTOM" + //SlotIDBizMidContext 公众号文中广告 + SlotIDBizMidContext AdSlot = "SLOT_ID_BIZ_MID_CONTEXT" + //SlotIDBizVideoEnd 公众号视频后贴 + SlotIDBizVideoEnd AdSlot = "SLOT_ID_BIZ_VIDEO_END" + //SlotIDBizSponsor 公众号互选广告 + SlotIDBizSponsor AdSlot = "SLOT_ID_BIZ_SPONSOR" + //SlotIDBizCps 公众号返佣商品 + SlotIDBizCps AdSlot = "SLOT_ID_BIZ_CPS" + //SlotIDWeappBanner 小程序banner + SlotIDWeappBanner AdSlot = "SLOT_ID_WEAPP_BANNER" + //SlotIDWeappRewardVideo 小程序激励视频 + SlotIDWeappRewardVideo AdSlot = "SLOT_ID_WEAPP_REWARD_VIDEO" + //SlotIDWeappInterstitial 小程序插屏广告 + SlotIDWeappInterstitial AdSlot = "SLOT_ID_WEAPP_INTERSTITIAL" + //SlotIDWeappVideoFeeds 小程序视频广告 + SlotIDWeappVideoFeeds AdSlot = "SLOT_ID_WEAPP_VIDEO_FEEDS" + //SlotIDWeappVideoBegin 小程序视频前贴 + SlotIDWeappVideoBegin AdSlot = "SLOT_ID_WEAPP_VIDEO_BEGIN" + //SlotIDWeappBox 小程序格子广告 + SlotIDWeappBox AdSlot = "SLOT_ID_WEAPP_BOX" +) + +const ( + publisherURL = "https://api.weixin.qq.com/publisher/stat" +) + +const ( + actionPublisherAdPosGeneral = "publisher_adpos_general" + actionPublisherCpsGeneral = "publisher_cps_general" + actionPublisherSettlement = "publisher_settlement" +) + +//BaseResp 错误信息 +type BaseResp struct { + ErrMsg string `json:"err_msg"` + Ret int `json:"ret"` +} + +//ResPublisherAdPos 公众号分广告位数据响应 +type ResPublisherAdPos struct { + util.CommonError + BaseResp + + Base BaseResp `json:"base_resp"` + List []ResAdPosList `json:"list"` + Summary ResAdPosSummary `json:"summary"` + TotalNum int `json:"total_num"` +} + +//ResAdPosList 公众号分广告位列表 +type ResAdPosList struct { + SlotID int64 `json:"slot_id"` + AdSlot string `json:"ad_slot"` + Date string `json:"date"` + ReqSuccCount int `json:"req_succ_count"` + ExposureCount int `json:"exposure_count"` + ExposureRate float64 `json:"exposure_rate"` + ClickCount int `json:"click_count"` + ClickRate float64 `json:"click_rate"` + Income int `json:"income"` + Ecpm float64 `json:"ecpm"` +} + +//ResAdPosSummary 公众号分广告位概览 +type ResAdPosSummary struct { + ReqSuccCount int `json:"req_succ_count"` + ExposureCount int `json:"exposure_count"` + ExposureRate float64 `json:"exposure_rate"` + ClickCount int `json:"click_count"` + ClickRate float64 `json:"click_rate"` + Income int `json:"income"` + Ecpm float64 `json:"ecpm"` +} + +//ResPublisherCps 公众号返佣商品数据响应 +type ResPublisherCps struct { + util.CommonError + BaseResp + + Base BaseResp `json:"base_resp"` + List []ResCpsList `json:"list"` + Summary ResCpsSummary `json:"summary"` + TotalNum int `json:"total_num"` +} + +//ResCpsList 公众号返佣商品列表 +type ResCpsList struct { + Date string `json:"date"` + ExposureCount int `json:"exposure_count"` + ClickCount int `json:"click_count"` + ClickRate float64 `json:"click_rate"` + OrderCount int `json:"order_count"` + OrderRate float64 `json:"order_rate"` + TotalFee int `json:"total_fee"` + TotalCommission int `json:"total_commission"` +} + +//ResCpsSummary 公众号返佣概览 +type ResCpsSummary struct { + ExposureCount int `json:"exposure_count"` + ClickCount int `json:"click_count"` + ClickRate float64 `json:"click_rate"` + OrderCount int `json:"order_count"` + OrderRate float64 `json:"order_rate"` + TotalFee int `json:"total_fee"` + TotalCommission int `json:"total_commission"` +} + +//ResPublisherSettlement 公众号结算收入数据及结算主体信息响应 +type ResPublisherSettlement struct { + util.CommonError + BaseResp + + Base BaseResp `json:"base_resp"` + Body string `json:"body"` + PenaltyAll int `json:"penalty_all"` + RevenueAll int64 `json:"revenue_all"` + SettledRevenueAll int64 `json:"settled_revenue_all"` + SettlementList []SettlementList `json:"settlement_list"` + TotalNum int `json:"total_num"` +} + +//SettlementList 结算单列表 +type SettlementList struct { + Date string `json:"date"` + Zone string `json:"zone"` + Month string `json:"month"` + Order int `json:"order"` + SettStatus int `json:"sett_status"` + SettledRevenue int `json:"settled_revenue"` + SettNo string `json:"sett_no"` + MailSendCnt string `json:"mail_send_cnt"` + SlotRevenue []SlotRevenue `json:"slot_revenue"` +} + +//SlotRevenue 产生收入的广告 +type SlotRevenue struct { + SlotID string `json:"slot_id"` + SlotSettledRevenue int `json:"slot_settled_revenue"` +} + +//ParamsPublisher 拉取数据参数 +type ParamsPublisher struct { + Action string `json:"action"` + StartDate string `json:"start_date"` + EndDate string `json:"end_date"` + Page int `json:"page"` + PageSize int `json:"page_size"` + AdSlot AdSlot `json:"ad_slot"` +} + +// fetchData 拉取统计数据 +func (cube *DataCube) fetchData(params ParamsPublisher) (response []byte, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + v := url.Values{} + v.Add("action", params.Action) + v.Add("access_token", accessToken) + v.Add("page", strconv.Itoa(params.Page)) + v.Add("page_size", strconv.Itoa(params.PageSize)) + v.Add("start_date", params.StartDate) + v.Add("end_date", params.EndDate) + if params.AdSlot != "" { + v.Add("ad_slot", string(params.AdSlot)) + } + + uri := fmt.Sprintf("%s?%s", publisherURL, v.Encode()) + + response, err = util.HTTPGet(uri) + if err != nil { + return + } + return +} + +//GetPublisherAdPosGeneral 获取公众号分广告位数据 +func (cube *DataCube) GetPublisherAdPosGeneral(startDate, endDate string, page, pageSize int, adSlot AdSlot) (resPublisherAdPos ResPublisherAdPos, err error) { + params := ParamsPublisher{ + Action: actionPublisherAdPosGeneral, + StartDate: startDate, + EndDate: endDate, + Page: page, + PageSize: pageSize, + AdSlot: adSlot, + } + + response, err := cube.fetchData(params) + if err != nil { + return + } + + err = json.Unmarshal(response, &resPublisherAdPos) + if err != nil { + return + } + + if resPublisherAdPos.CommonError.ErrCode != 0 { + err = fmt.Errorf("GetPublisherAdPosGeneral Error , errcode=%d , errmsg=%s", resPublisherAdPos.CommonError.ErrCode, resPublisherAdPos.CommonError.ErrMsg) + return + } + + if resPublisherAdPos.BaseResp.Ret != 0 { + err = fmt.Errorf("GetPublisherAdPosGeneral Error , errcode=%d , errmsg=%s", resPublisherAdPos.BaseResp.Ret, resPublisherAdPos.BaseResp.ErrMsg) + return + } + + if resPublisherAdPos.Base.Ret != 0 { + err = fmt.Errorf("GetPublisherAdPosGeneral Error , errcode=%d , errmsg=%s", resPublisherAdPos.Base.Ret, resPublisherAdPos.Base.ErrMsg) + return + } + return +} + +//GetPublisherCpsGeneral 获取公众号返佣商品数据 +func (cube *DataCube) GetPublisherCpsGeneral(startDate, endDate string, page, pageSize int) (resPublisherCps ResPublisherCps, err error) { + params := ParamsPublisher{ + Action: actionPublisherCpsGeneral, + StartDate: startDate, + EndDate: endDate, + Page: page, + PageSize: pageSize, + } + + response, err := cube.fetchData(params) + if err != nil { + return + } + + err = json.Unmarshal(response, &resPublisherCps) + if err != nil { + return + } + + if resPublisherCps.CommonError.ErrCode != 0 { + err = fmt.Errorf("GetPublisherCpsGeneral Error , errcode=%d , errmsg=%s", resPublisherCps.CommonError.ErrCode, resPublisherCps.CommonError.ErrMsg) + return + } + + if resPublisherCps.BaseResp.Ret != 0 { + err = fmt.Errorf("GetPublisherCpsGeneral Error , errcode=%d , errmsg=%s", resPublisherCps.BaseResp.Ret, resPublisherCps.BaseResp.ErrMsg) + return + } + + if resPublisherCps.Base.Ret != 0 { + err = fmt.Errorf("GetPublisherCpsGeneral Error , errcode=%d , errmsg=%s", resPublisherCps.Base.Ret, resPublisherCps.Base.ErrMsg) + return + } + + return +} + +//GetPublisherSettlement 获取公众号结算收入数据及结算主体信息 +func (cube *DataCube) GetPublisherSettlement(startDate, endDate string, page, pageSize int) (resPublisherSettlement ResPublisherSettlement, err error) { + params := ParamsPublisher{ + Action: actionPublisherSettlement, + StartDate: startDate, + EndDate: endDate, + Page: page, + PageSize: pageSize, + } + + response, err := cube.fetchData(params) + if err != nil { + return + } + + err = json.Unmarshal(response, &resPublisherSettlement) + if err != nil { + return + } + + if resPublisherSettlement.CommonError.ErrCode != 0 { + err = fmt.Errorf("GetPublisherSettlement Error , errcode=%d , errmsg=%s", resPublisherSettlement.CommonError.ErrCode, resPublisherSettlement.CommonError.ErrMsg) + return + } + + if resPublisherSettlement.BaseResp.Ret != 0 { + err = fmt.Errorf("GetPublisherSettlement Error , errcode=%d , errmsg=%s", resPublisherSettlement.BaseResp.Ret, resPublisherSettlement.BaseResp.ErrMsg) + return + } + + if resPublisherSettlement.Base.Ret != 0 { + err = fmt.Errorf("GetPublisherSettlement Error , errcode=%d , errmsg=%s", resPublisherSettlement.Base.Ret, resPublisherSettlement.Base.ErrMsg) + return + } + return +} diff --git a/officialaccount/datacube/user.go b/officialaccount/datacube/user.go new file mode 100644 index 0000000..63ad0b1 --- /dev/null +++ b/officialaccount/datacube/user.go @@ -0,0 +1,77 @@ +package datacube + +import ( + "fmt" + "github.com/silenceper/wechat/v2/util" +) + +const ( + getUserSummary = "https://api.weixin.qq.com/datacube/getusersummary" + getUserAccumulate = "https://api.weixin.qq.com/datacube/getusercumulate" +) + +//ResUserSummary 获取用户增减数据响应 +type ResUserSummary struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + UserSource int `json:"user_source"` + NewUser int `json:"new_user"` + CancelUser int `json:"cancel_user"` + } `json:"list"` +} + +//ResUserAccumulate 获取累计用户数据响应 +type ResUserAccumulate struct { + util.CommonError + + List []struct { + RefDate string `json:"ref_date"` + CumulateUser int `json:"cumulate_user"` + } `json:"list"` +} + +//GetUserSummary 获取用户增减数据 +func (cube *DataCube) GetUserSummary(s string, e string) (resUserSummary ResUserSummary, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUserSummary, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUserSummary, "GetUserSummary") + return +} + +//GetUserAccumulate 获取累计用户数据 +func (cube *DataCube) GetUserAccumulate(s string, e string) (resUserAccumulate ResUserAccumulate, err error) { + accessToken, err := cube.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", getUserAccumulate, accessToken) + reqDate := &reqDate{ + BeginDate: s, + EndDate: e, + } + + response, err := util.PostJSON(uri, reqDate) + if err != nil { + return + } + + err = util.DecodeWithError(response, &resUserAccumulate, "GetUserAccumulate") + return +} diff --git a/officialaccount/device/qrcode.go b/officialaccount/device/qrcode.go index 51cf91a..c77d659 100644 --- a/officialaccount/device/qrcode.go +++ b/officialaccount/device/qrcode.go @@ -60,7 +60,7 @@ func (d *Device) VerifyQRCode(ticket string) (res ResVerifyQRCode, err error) { req := map[string]interface{}{ "ticket": ticket, } - fmt.Println(req) + var response []byte if response, err = util.PostJSON(uri, req); err != nil { return diff --git a/officialaccount/officialaccount.go b/officialaccount/officialaccount.go index bf581af..99283ee 100644 --- a/officialaccount/officialaccount.go +++ b/officialaccount/officialaccount.go @@ -1,6 +1,7 @@ package officialaccount import ( + "github.com/silenceper/wechat/v2/officialaccount/datacube" "net/http" "github.com/silenceper/wechat/v2/credential" @@ -101,3 +102,8 @@ func (officialAccount *OfficialAccount) GetDevice() *device.Device { func (officialAccount *OfficialAccount) GetBroadcast() *broadcast.Broadcast { return broadcast.NewBroadcast(officialAccount.ctx) } + +//GetDataCube 数据统计 +func (officialAccount *OfficialAccount) GetDataCube() *datacube.DataCube { + return datacube.NewCube(officialAccount.ctx) +}