Browse Source

30d销量获取成功

Yankun168 11 months ago
parent
commit
ee53f0b736

+ 1 - 1
.idea/JavaSceneConfigState.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="SmartInputSourceJavaSceneConfigState">
-    <option name="customChineseScenes" value="{&quot;capsLockState&quot;:false,&quot;code&quot;:&quot;;Printf(format);Println(a);TalentHttpResult(Msg)&quot;,&quot;enable&quot;:true,&quot;languageType&quot;:&quot;CHINESE&quot;,&quot;name&quot;:&quot;自定义中文切换&quot;,&quot;tip&quot;:&quot;&quot;}" />
+    <option name="customChineseScenes" value="{&quot;capsLockState&quot;:false,&quot;code&quot;:&quot;;Printf(format);Println(a);TalentHttpResult(Msg);panic(v)&quot;,&quot;enable&quot;:true,&quot;languageType&quot;:&quot;CHINESE&quot;,&quot;name&quot;:&quot;自定义中文切换&quot;,&quot;tip&quot;:&quot;&quot;}" />
   </component>
 </project>

+ 9 - 1
app/api/youngee_talent_api/talent_auth_get_api.go

@@ -87,14 +87,22 @@ func (*talentAuthGetApi) DisplayQrcode(r *ghttp.Request) {
 
 }
 
-// 达人抖音授权二维码展示
+// 轮询用户是否扫码了(数据库中有含tid的数据)
 func (*talentAuthGetApi) CheckAccount(r *ghttp.Request) {
 	res := youngee_talent_service.CheckAccount(r)
 	err := r.Response.WriteJson(res)
 	if err != nil {
 		panic("write response error")
 	}
+}
 
+// 查30天销量(此时已经执行完了/kuaishouauth,在checkaccount的过程中执行此函数)
+func (*talentAuthGetApi) QuerySalesFor30Days(r *ghttp.Request) {
+	res := youngee_talent_service.QuerySalesFor30Days(r)
+	err := r.Response.WriteJson(res)
+	if err != nil {
+		panic("write response error")
+	}
 }
 
 // 判断达人是否登录

+ 18 - 12
app/model/youngee_talent_model/kuaishouAuth.go

@@ -1,18 +1,24 @@
 package youngee_talent_model
 
-import "github.com/gogf/gf/util/gmeta"
+import (
+	"github.com/gogf/gf/os/gtime"
+	"github.com/gogf/gf/util/gmeta"
+)
 
 type KuaishouUserInfo struct {
 	gmeta.Meta   `orm:"table:platform_kuaishou_user_info"`
-	Id           int    `json:"id" orm:"id,primary"`
-	OpenId       string `json:"open_id" orm:"open_id"`
-	TalentId     string `json:"talent_id" orm:"talent_id"`
-	Code         string `json:"code" orm:"code"`
-	AccessToken  string `json:"access_token" orm:"access_token"`
-	RefreshToken string `json:"refresh_token" orm:"refresh_token"`
-	HeadUri      string `json:"head_uri" orm:"head_uri"`
-	Fan          string `json:"fan" orm:"fan"`
-	Expired      bool   `json:"expired" orm:"expired"`
-	SaleNum30day int    `json:"sale_num_30day" orm:"sale_num_30day"`
-	SaleNumTotal int    `json:"sale_num_total" orm:"sale_num_total"`
+	Id           int         `json:"id" orm:"id,primary"`
+	OpenId       string      `json:"open_id" orm:"open_id"`
+	TalentId     string      `json:"talent_id" orm:"talent_id"`
+	Code         string      `json:"code" orm:"code"`
+	AccessToken  string      `json:"access_token" orm:"access_token"`
+	RefreshToken string      `json:"refresh_token" orm:"refresh_token"`
+	NickName     string      `json:"nick_name" orm:"nick_name"`
+	HeadUri      string      `json:"head_uri" orm:"head_uri"`
+	Fan          int         `json:"fan" orm:"fan"`
+	Expired      bool        `json:"expired" orm:"expired"`
+	SaleNum30day int         `json:"sale_num_30day" orm:"sale_num_30day"`
+	SaleNumTotal int         `json:"sale_num_total" orm:"sale_num_total"`
+	CreateTime   *gtime.Time `json:"create_time" orm:"create_time"  ` // 创建时间
+	UpdateTime   *gtime.Time `json:"update_time" orm:"update_time"  ` // 创建时间
 }

+ 112 - 0
app/service/youngee_talent_service/talent_ks_auth.go

@@ -6,6 +6,7 @@ import (
 	"github.com/chromedp/chromedp"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/net/ghttp"
+	"github.com/lin-jim-leon/kuaishou/open/merchant"
 	"log"
 	"time"
 	"youngmini_server/app/model/youngee_talent_model"
@@ -75,3 +76,114 @@ func CheckAccount(r *ghttp.Request) *TalentHttpResult {
 	// 查询成功,返回成功结果和数据
 	return &TalentHttpResult{Code: 0, Msg: "success", Data: userInfo}
 }
+
+func QuerySalesFor30Days(r *ghttp.Request) *TalentHttpResult {
+	fmt.Println("into querySalesFor30Days")
+	ClientKey := "ks651333097154138217"
+	//ClientSecret := "dBt0rVRhTpUqcrOYGGpv0A"
+	SignSecret := "bf6393dce0a2b669ee348bebb837b0da"
+	tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	// 创建一个 KuaishouUserInfo 结构体的实例
+	userInfo := &youngee_talent_model.KuaishouUserInfo{}
+
+	// 查询数据库中的 access_token 字段
+	// 使用 g.DB() 获取数据库连接,并执行查询
+	key, err := g.DB().Model(userInfo).Fields("access_token").Where("talent_id = ?", tid).Value()
+	AccessToken := key.String()
+	if err != nil {
+		// 处理错误
+		fmt.Println("Error querying access_token:", err)
+	}
+
+	// 输出查询到的 access_token 值
+	fmt.Println("Access Token:", AccessToken)
+
+	//循环使用接口
+	//
+	// 获取当前时间的时间戳(毫秒)
+	currentTime := time.Now().UnixNano() / int64(time.Millisecond)
+	// 30天前的时间戳(毫秒)
+	beginTime30DaysAgo := currentTime - 30*24*60*60*1000
+	// 定义每段查询的天数
+	intervalDays := 7
+	intervalMillis := int64(intervalDays * 24 * 60 * 60 * 1000)
+
+	// 初始化 beginTime 和 endTime
+	beginTime := beginTime30DaysAgo
+	endTime := beginTime + intervalMillis
+	saleNum := 0 //30天总销量
+	// 循环查询,先处理四个7天的时间段
+	for i := 0; i < 4; i++ {
+		// 调整 endTime,确保不会超过当前时间
+		if endTime > currentTime {
+			endTime = currentTime
+		}
+		saleNum += GetSaleNumByDayInterval(ClientKey, SignSecret, AccessToken, beginTime, endTime)
+		// 更新时间段
+		beginTime = endTime
+		endTime = beginTime + intervalMillis
+	}
+
+	// 最后处理剩余的2天时间段
+	endTime = currentTime
+	saleNum += GetSaleNumByDayInterval(ClientKey, SignSecret, AccessToken, beginTime, endTime)
+	// 查询成功,返回成功结果和数据
+	return &TalentHttpResult{Code: 0, Msg: "获取30天销售量成功", Data: saleNum}
+}
+
+func GetSaleNumByDayInterval(ClientKey string, SignSecret string, AccessToken string, beginTime int64, endTime int64) int {
+	pageSize := 100
+	totalSaleNum := 0
+
+	// 定义要查询的订单状态
+	statuses := []int{30, 50, 60}
+
+	// 遍历所有订单状态并调用 Corderlist 函数
+	for _, status := range statuses {
+		// 初始化 pcursor
+		pcursor := ""
+
+		for {
+			// 调用 Corderlist 函数获取订单列表
+			response, err := merchant.Corderlist(ClientKey, SignSecret, AccessToken, status, pageSize, beginTime, endTime, pcursor)
+			fmt.Println("response********", response)
+			if err != nil {
+				fmt.Printf("Error calling Corderlist: %v\n", err)
+				break
+			}
+
+			// 检查响应代码
+			if response.Code != "1" {
+				fmt.Printf("Corderlist response error: %s\n", response.Msg)
+				break
+			}
+
+			// 累加订单中商品的数量
+			for _, order := range response.Data.OrderViews {
+				for _, product := range order.CPSOrderProductViews {
+					totalSaleNum += product.Num
+				}
+			}
+
+			// 检查分页指针 pcursor
+			//100个订单以内的情况
+			if response.Data.Cursor == "nomore" {
+				break
+			}
+			//大于等于100个订单
+			// 更新 pcursor 以获取下一页数据
+			pcursor = response.Data.Cursor
+
+			// 处理分页后的数据
+			// 如果 pcursor 不是 "nomore",我们需要累加最后一条订单的数量
+			if len(response.Data.OrderViews) > 0 {
+				lastOrder := response.Data.OrderViews[len(response.Data.OrderViews)-1]
+				if len(lastOrder.CPSOrderProductViews) > 0 {
+					lastProduct := lastOrder.CPSOrderProductViews[len(lastOrder.CPSOrderProductViews)-1]
+					totalSaleNum += lastProduct.Num
+				}
+			}
+		}
+	}
+	return totalSaleNum
+}

BIN
bin/main.exe


BIN
bin/main.exe~


BIN
bin/v3.3.4/linux_amd64/youngmini_server


BIN
bin/v3.3.4/windows_amd64/youngmini_server.exe


+ 1 - 1
config/config.toml

@@ -19,7 +19,7 @@ name = "youngmini_server"
 output = "./bin"
 pack = ""
 system = "linux,windows"
-version = "v3.3.3"
+version = "v3.3.4"
 [gfcli.gen.dao]
 jsonCase = "Snake"
 link = "mysql:talent:talentDB_123@tcp(139.9.53.143:3306)/youngmini"

+ 4 - 1
go.mod

@@ -1,11 +1,14 @@
 module youngmini_server
 
-go 1.17
+go 1.22.1
+
+//toolchain go1.22.3
 
 require (
 	github.com/chromedp/chromedp v0.9.5
 	github.com/gogf/gcache-adapter v0.1.2
 	github.com/gogf/gf v1.16.6
+	github.com/lin-jim-leon/kuaishou v0.3.0
 	github.com/wechatpay-apiv3/wechatpay-go v0.2.18
 	github.com/wxnacy/wgo v1.0.4
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df

+ 2 - 0
go.sum

@@ -47,6 +47,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
 github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
+github.com/lin-jim-leon/kuaishou v0.3.0 h1:Gb0DRc62K51/78680Pq+zupOXTnd1CN1Lfv5NrqRIHo=
+github.com/lin-jim-leon/kuaishou v0.3.0/go.mod h1:BFbAhNC3PUIhAaA9YDSi6WDB0UcRMPS9C7dpFAtENaY=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=

+ 59 - 6
router/router.go

@@ -3,6 +3,12 @@ package router
 import (
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/net/ghttp"
+	"github.com/gogf/gf/os/gtime"
+	_ "github.com/lin-jim-leon/kuaishou/open/merchant"
+	"github.com/lin-jim-leon/kuaishou/open/oauth"
+	_ "github.com/lin-jim-leon/kuaishou/open/oauth"
+	"github.com/lin-jim-leon/kuaishou/open/user"
+	_ "github.com/lin-jim-leon/kuaishou/open/user"
 	youngeetalentapi "youngmini_server/app/api/youngee_talent_api"
 	"youngmini_server/app/model/youngee_talent_model"
 	"youngmini_server/app/system/assignment"
@@ -77,18 +83,65 @@ func init() {
 		group.Middleware(middleware.ErrorHandler)
 		//group.GET("/ping", func(r *ghttp.Request)才表示/youngee/c/ping生效
 
-		//nignx转发含code的请求到此处
-		s.BindHandler("/hello", func(r *ghttp.Request) {
+		//s.BindHandler("/hello", func(r *ghttp.Request) {
+		//	ClientKey := "ks651333097154138217"
+		//	//ClientSecret := "dBt0rVRhTpUqcrOYGGpv0A"
+		//	SignSecret := "bf6393dce0a2b669ee348bebb837b0da"
+		//	access_token := "ChFvYXV0aC5hY2Nlc3NUb2tlbhJg3bHg2fx4q7DC3NDjTerISLTMV8M3OSj8lZMVG3oF37XapgezRims_9gq8pkNKlTRi3Vtwjd7tGbUbBN8pLNVBZaJbkig2IPKHswsuGZwC4uHMwiVkAFeSJRt7gJwec4jGhI4jxc1xH1K15kfx1GQn1SwLvsiID1v9alK2K-YywCzsIW3v7WIjFLGRfEqyt9s2m3VOaGXKAUwAQ"
+		//	// 计算七天前的时间戳(毫秒)
+		//	DaysAgo := time.Now().AddDate(0, 0, -7)                    // 91天前
+		//	beginTime := DaysAgo.UnixNano() / int64(time.Millisecond)  // 转换为毫秒
+		//	endTime := time.Now().UnixNano() / int64(time.Millisecond) // 转换为毫秒
+		//	// 计算当前时间戳(毫秒)
+		//	cpsOrderStatus := 0 // 假设的值
+		//	pageSize := 10      // 假设的值
+		//	corlist, _ := merchant.Corderlist(ClientKey, SignSecret, access_token, cpsOrderStatus, pageSize, beginTime, endTime)
+		//	err := r.Response.WriteJson(corlist)
+		//	if err != nil {
+		//		panic("write response error")
+		//	}
+		//})
 
-		})
+		//nignx转发含code的请求到此处
 		s.BindHandler("/kuaishouauth", func(r *ghttp.Request) {
+			ClientKey := "ks651333097154138217"
+			ClientSecret := "dBt0rVRhTpUqcrOYGGpv0A"
+			//SignSecret := "bf6393dce0a2b669ee348bebb837b0da"
 			code := r.GetString("code")
 			state := r.GetString("state")
+			//获取accesstoken
+			res_auth, _ := oauth.GetAccessToken(ClientKey, ClientSecret, code)
+			AccessToken := res_auth.AccessToken
+			//获取基本信息
+			res_info, _ := user.GetUserinfo(ClientKey, AccessToken)
+			//30天销量获取需要单独开一个接口QuerySalesFor30Days,前端调用并且传参数为订单处于30+50+60的
+
+			err_auth := r.Response.WriteJson(res_auth)
+			err_info := r.Response.WriteJson(res_info)
+			if err_auth != nil {
+				panic("write auth_response error")
+			}
+			if err_info != nil {
+				panic("write auth_response error")
+			}
+			if res_auth.Result != 1 {
+				panic("授权结果出错了")
+			}
+			if res_info.Result != 1 {
+				panic("获取用户信息出错了")
+			}
 			//auth中含有最终信息
-			//todo:调用accesstoken以及用户信息api
 			authInfo := &youngee_talent_model.KuaishouUserInfo{
-				Code:     code,
-				TalentId: state,
+				Code:         code,
+				TalentId:     state,
+				AccessToken:  AccessToken,
+				OpenId:       res_auth.OpenId,
+				RefreshToken: res_auth.RefreshToken,
+				HeadUri:      res_info.Data.Head,
+				NickName:     res_info.Data.Name,
+				Fan:          res_info.Data.Fan,
+				UpdateTime:   gtime.Now(),
+				CreateTime:   gtime.Now(),
 			}
 			if _, err := g.DB().Model("platform_kuaishou_user_info").Save(authInfo); err != nil {
 				r.Response.WriteJson(g.Map{

+ 277 - 0
vendor/github.com/lin-jim-leon/kuaishou/open/merchant/merchat.go

@@ -0,0 +1,277 @@
+package merchant
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"github.com/lin-jim-leon/kuaishou/util"
+	"net/url"
+	"sort"
+	"strings"
+	"time"
+)
+
+const (
+	PickUrl       = "https://openapi.kwaixiaodian.com/open/distribution/selection/pick?appkey=%s&access_token=%s&method=open.distribution.selection.pick&param=%s&sign=%s&version=1&signMethod=MD5&timestamp=%d"
+	Selectdetail  = "https://openapi.kwaixiaodian.com/open/distribution/query/selection/item/detail?appkey=%s&access_token=%s&method=open.distribution.query.selection.item.detail&param=%s&sign=%s&version=1&signMethod=MD5&timestamp=%d"
+	Corderlisturl = "https://openapi.kwaixiaodian.com/open/distribution/cps/distributor/order/cursor/list?appkey=%s&access_token=%s&method=open.distribution.cps.distributor.order.cursor.list&param=%s&sign=%s&version=1&signMethod=MD5&timestamp=%d"
+)
+
+type Iteminfo struct {
+	Result   int    `json:"result"`
+	ItemId   int64  `json:"itemId"`
+	ErrorMsg string `json:"errorMsg"`
+}
+
+type AddItemsres struct {
+	Result   int        `json:"result"`
+	Msg      string     `json:"msg"`
+	ErrorMsg string     `json:"error_msg"`
+	Code     string     `json:"code"`
+	Data     []Iteminfo `json:"data"`
+	SubMsg   string     `json:"sub_msg"`
+	SubCode  string     `json:"sub_code"`
+}
+
+// generateSign 生成签名
+func generateSign(appkey, signsecret, accesstoken, param string, timestamp int64, method string) string {
+	// 将请求参数按照字典顺序排序
+	params := map[string]string{
+		"access_token": accesstoken,
+		"appkey":       appkey,
+		"method":       method,
+		"param":        param,
+		"signMethod":   "MD5",
+		"timestamp":    fmt.Sprintf("%d", timestamp),
+		"version":      "1",
+	}
+	keys := make([]string, 0, len(params))
+	for k := range params {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+
+	// 构造待签名字符串
+	var signStr strings.Builder
+	for _, k := range keys {
+		signStr.WriteString(fmt.Sprintf("%s=%s&", k, params[k]))
+	}
+	signStr.WriteString("signSecret=" + signsecret)
+
+	// 计算签名值
+	hasher := md5.New()
+	hasher.Write([]byte(signStr.String()))
+	encrypted := hasher.Sum(nil)
+	return hex.EncodeToString(encrypted)
+}
+
+// 商品加橱窗
+func AddItemsToShelf(Appkey string, signsecret string, accesstoken string, itemidlist []string) (Adinfo AddItemsres, err error) {
+	// 构造请求参数 param
+	rawParam := fmt.Sprintf(`{"itemIds":[%s]}`, strings.Join(itemidlist, ","))
+	// 获取当前时间戳(毫秒级)
+	timestamp := time.Now().UnixNano() / int64(time.Millisecond)
+
+	method := "open.distribution.selection.pick"
+	// 对请求参数进行签名
+	sign := generateSign(Appkey, signsecret, accesstoken, rawParam, timestamp, method)
+	// 构造完整的请求 URL
+	encodedParam := url.QueryEscape(rawParam)
+	uri := fmt.Sprintf(PickUrl, Appkey, accesstoken, encodedParam, sign, timestamp)
+
+	// 发送 HTTP GET 请求
+	var response []byte
+	response, err = util.HTTPGet(uri)
+	if err != nil {
+		return AddItemsres{}, err
+	}
+	// 解析响应数据
+	var result AddItemsres
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return AddItemsres{}, err
+	}
+
+	// 检查是否有错误信息
+	if result.ErrorMsg != "SUCCESS" {
+		return AddItemsres{}, fmt.Errorf("AddItemsToShelf error: %s", result.ErrorMsg)
+	}
+
+	return result, nil
+}
+
+type SelsetionRes struct {
+	Code      string                    `json:"code"`
+	Msg       string                    `json:"msg"`
+	SubCode   string                    `json:"sub_code"`
+	SubMsg    string                    `json:"sub_msg"`
+	Result    int                       `json:"result"`
+	ErrorMsg  string                    `json:"error_msg"`
+	ItemList  []DistributeSelectionItem `json:"itemList"`
+	ShopTitle string                    `json:"shopTitle"`
+}
+
+type DistributeSelectionItem struct {
+	ItemID                      int64           `json:"itemId"`
+	ZKFinalPrice                int64           `json:"zkFinalPrice"`
+	ItemImgURL                  string          `json:"itemImgUrl"`
+	ItemPrice                   int64           `json:"itemPrice"`
+	SKUList                     []DistributeSKU `json:"skuList"`
+	SoldCountThirtyDays         int64           `json:"soldCountThirtyDays"`
+	ShopTitle                   string          `json:"shopTitle"`
+	CommissionRate              int             `json:"commissionRate"`
+	BrandName                   string          `json:"brandName"`
+	ItemTitle                   string          `json:"itemTitle"`
+	ProfitAmount                int64           `json:"profitAmount"`
+	ShopScore                   string          `json:"shopScore"`
+	ShopStar                    string          `json:"shopStar"`
+	ItemDesc                    string          `json:"itemDesc"`
+	ShopType                    int             `json:"shopType"`
+	CategoryID                  int             `json:"categoryId"`
+	ItemGalleryURLs             []string        `json:"itemGalleryUrls"`
+	ItemDescURLs                []string        `json:"itemDescUrls"`
+	MerchantSoldCountThirtyDays int64           `json:"merchantSoldCountThirtyDays"`
+	ShopID                      int64           `json:"shopId"`
+}
+
+type DistributeSKU struct {
+	SKUPrice      int64  `json:"skuPrice"`
+	SKUStock      int64  `json:"skuStock"`
+	Specification string `json:"specification"`
+	SKUID         int64  `json:"skuId"`
+}
+
+func Queryselectiondetail(Appkey string, signsecret string, accesstoken string, itemidlist []string) (Selectitem SelsetionRes, err error) {
+	// 构造请求参数 param
+	rawParam := fmt.Sprintf(`{"itemId":[%s]}`, strings.Join(itemidlist, ","))
+	// 获取当前时间戳(毫秒级)
+	timestamp := time.Now().UnixNano() / int64(time.Millisecond)
+	method := "open.distribution.query.selection.item.detail"
+	// 对请求参数进行签名
+	sign := generateSign(Appkey, signsecret, accesstoken, rawParam, timestamp, method)
+	// 构造完整的请求 URL
+	encodedParam := url.QueryEscape(rawParam)
+	uri := fmt.Sprintf(Selectdetail, Appkey, accesstoken, encodedParam, sign, timestamp)
+	fmt.Println(uri)
+	// 发送 HTTP GET 请求
+	var response []byte
+	response, err = util.HTTPGet(uri)
+	if err != nil {
+		return SelsetionRes{}, err
+	}
+	fmt.Println(string(response))
+	// 解析响应数据
+	var result SelsetionRes
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return SelsetionRes{}, err
+	}
+
+	// 检查是否有错误信息
+	if result.ErrorMsg != "" {
+		return SelsetionRes{}, fmt.Errorf("Queryselectiondetail error: %s", result.ErrorMsg)
+	}
+
+	return result, nil
+}
+
+type OrderlistRes struct {
+	Code     string      `json:"code"`      // 主返回码
+	Msg      string      `json:"msg"`       // 主返回信息
+	SubCode  string      `json:"sub_code"`  // 子返回码
+	SubMsg   string      `json:"sub_msg"`   // 子返回信息
+	Result   int         `json:"result"`    // 返回码
+	ErrorMsg string      `json:"error_msg"` // 返回错误信息
+	Data     OrderCursor `json:"data"`      // 返回数据
+}
+
+type OrderCursor struct {
+	Cursor     string      `json:"pcursor"`   // 分销订单位点游标(请求透传, "nomore"标识后续无数据)
+	OrderViews []OrderView `json:"orderView"` // 订单信息
+}
+
+type OrderView struct {
+	DistributorID         int64                           `json:"distributorId"`         // 分销推广者用户ID
+	OrderID               int64                           `json:"oid"`                   // 订单ID
+	CPSOrderStatus        int                             `json:"cpsOrderStatus"`        // 分销订单状态
+	OrderCreateTime       int64                           `json:"orderCreateTime"`       // 订单创建时间
+	PayTime               int64                           `json:"payTime"`               // 订单支付时间
+	OrderTradeAmount      int64                           `json:"orderTradeAmount"`      // 订单交易总金额
+	CPSOrderProductViews  []CPSOrderProductView           `json:"cpsOrderProductView"`   // 商品信息
+	CreateTime            int64                           `json:"createTime"`            // 创建时间
+	UpdateTime            int64                           `json:"updateTime"`            // 更新时间
+	SettlementSuccessTime int64                           `json:"settlementSuccessTime"` // 结算时间
+	SettlementAmount      int64                           `json:"settlementAmount"`      // 结算金额
+	SendTime              int64                           `json:"sendTime"`              // 订单发货时间
+	SendStatus            int                             `json:"sendStatus"`            // 订单发货状态
+	RecvTime              int64                           `json:"recvTime"`              // 订单收货时间
+	BuyerOpenID           string                          `json:"buyerOpenId"`           // 买家唯一识别ID
+	BaseAmount            int64                           `json:"baseAmount"`            // 计佣基数
+	ShareRateStr          string                          `json:"shareRateStr"`          // 分成比例
+	SettlementBizType     int                             `json:"settlementBizType"`     // 订单业务结算类型
+	OrderRefundInfo       []CPSDistributorOrderRefundInfo `json:"orderRefundInfo"`       // 退款信息
+	OrderChannel          string                          `json:"orderChannel"`          // 订单渠道标识
+}
+
+type CPSOrderProductView struct {
+	OrderID              int64  `json:"oid"`                  // 订单ID
+	ItemID               int64  `json:"itemId"`               // 商品ID
+	ItemTitle            string `json:"itemTitle"`            // 商品标题
+	ItemPrice            int64  `json:"itemPrice"`            // 商品单价快照
+	EstimatedIncome      int64  `json:"estimatedIncome"`      // 预估收入
+	CommissionRate       int    `json:"commissionRate"`       // 佣金比率
+	ServiceRate          int    `json:"serviceRate"`          // 平台服务费率
+	ServiceAmount        int64  `json:"serviceAmount"`        // 平台服务费
+	CPSPID               string `json:"cpsPid"`               // 推广位id
+	SellerID             int64  `json:"sellerId"`             // 商家Id
+	SellerNickName       string `json:"sellerNickName"`       // 商家昵称快照
+	Num                  int    `json:"num"`                  // 商品数量
+	StepCondition        int    `json:"stepCondition"`        // 阶梯佣金条件
+	StepCommissionRate   int    `json:"stepCommissionRate"`   // 阶梯佣金比率
+	StepCommissionAmount int64  `json:"stepCommissionAmount"` // 阶梯佣金金额
+	ServiceIncome        int64  `json:"serviceIncome"`        // 接单服务收入
+	ExcitationIncome     int64  `json:"excitationIncome"`     // 奖励收入
+}
+
+type CPSDistributorOrderRefundInfo struct {
+	StartRefundTime int64  `json:"startRefundTime"` // 发起退款时间
+	EndRefundTime   int64  `json:"endRefundTime"`   // 完成退款时间
+	RefundFee       int64  `json:"refundFee"`       // 退款金额
+	RefundStatus    string `json:"refundStatus"`    // 退款状态
+}
+
+// 订单列表(游标)
+func Corderlist(Appkey string, signsecret string, accesstoken string, cpsOrderStatus int, pageSize int, beginTime int64, endTime int64, pcursor string) (corlist OrderlistRes, err error) {
+	// 构造请求参数 param
+	rawParam := fmt.Sprintf(`{"cpsOrderStatus":%d,"pageSize":%d,"sortType":1,"queryType":1,"beginTime":%d,"endTime":%d,"pcursor":"%s"}`, cpsOrderStatus, pageSize, beginTime, endTime, pcursor)
+	// 获取当前时间戳(毫秒级)
+	timestamp := time.Now().UnixNano() / int64(time.Millisecond)
+
+	method := "open.distribution.cps.distributor.order.cursor.list"
+	// 对请求参数进行签名
+	sign := generateSign(Appkey, signsecret, accesstoken, rawParam, timestamp, method)
+	// 构造完整的请求 URL
+	encodedParam := url.QueryEscape(rawParam)
+	uri := fmt.Sprintf(Corderlisturl, Appkey, accesstoken, encodedParam, sign, timestamp)
+
+	// 发送 HTTP GET 请求
+	var response []byte
+	response, err = util.HTTPGet(uri)
+	if err != nil {
+		return OrderlistRes{}, err
+	}
+	// 解析响应数据
+	var result OrderlistRes
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return OrderlistRes{}, err
+	}
+
+	// 检查是否有错误信息
+	if result.ErrorMsg != "SUCCESS" {
+		return OrderlistRes{}, fmt.Errorf("Corderlist error: %s", result.ErrorMsg)
+	}
+
+	return result, nil
+}

+ 73 - 0
vendor/github.com/lin-jim-leon/kuaishou/open/oauth/oauth.go

@@ -0,0 +1,73 @@
+package oauth
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/lin-jim-leon/kuaishou/util"
+)
+
+const (
+	accessTokenUrl  = "https://open.kuaishou.com/oauth2/access_token?grant_type=authorization_code&app_id=%s&app_secret=%s&code=%s"
+	refreshTokenURL = "https://open.kuaishou.com/oauth2/refresh_token?grant_type=refresh_token&app_id=%s&app_secret=%s&refresh_token=%s"
+)
+
+// accesstoken信息
+type AccessTokenRes struct {
+	Result                int      `json:"result"`
+	AccessToken           string   `json:"access_token"`
+	ExpiresIn             int      `json:"expires_in"`
+	RefreshToken          string   `json:"refresh_token"`
+	RefreshTokenExpiresIn int      `json:"refresh_token_expires_in"`
+	OpenId                string   `json:"open_id"`
+	Scopes                []string `json:"scopes"`
+	ErrorMsg              string   `json:"error_msg"`
+}
+
+// GetAccessToken 通过网页授权的code 换取access_token
+func GetAccessToken(ClientKey string, ClientSecret string, code string) (accessToken AccessTokenRes, err error) {
+	uri := fmt.Sprintf(accessTokenUrl, ClientKey, ClientSecret, code)
+	var response []byte
+	response, err = util.HTTPGet(uri)
+	if err != nil {
+		return AccessTokenRes{}, err
+	}
+	var result AccessTokenRes
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return AccessTokenRes{}, err
+	}
+	if len(result.ErrorMsg) > 0 {
+		return AccessTokenRes{}, fmt.Errorf("GetAccessToken error: error_msg=%s", result.ErrorMsg)
+	}
+	return result, nil
+}
+
+type RefreshTokenRes struct {
+	Result                int      `json:"result"`
+	AccessToken           string   `json:"access_token"`
+	ExpiresIn             int      `json:"expires_in"`
+	RefreshToken          string   `json:"refresh_token"`
+	RefreshTokenExpiresIn int      `json:"refresh_token_expires_in"`
+	Scopes                []string `json:"scopes"`
+	ErrorMsg              string   `json:"error_msg"`
+}
+
+// RefreshAccessToken 刷新AccessToken.
+// 当access_token过期(过期时间2天)后,可以通过该接口使用refresh_token(过期时间180天)进行刷新
+func RefreshAccessToken(refreshkey string, clientkey string, clientsecret string) (accessToken RefreshTokenRes, err error) {
+	uri := fmt.Sprintf(refreshTokenURL, clientkey, clientsecret, refreshkey)
+	var response []byte
+	response, err = util.HTTPGet(uri)
+	if err != nil {
+		return RefreshTokenRes{}, err
+	}
+	var result RefreshTokenRes
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return RefreshTokenRes{}, err
+	}
+	if len(result.ErrorMsg) > 0 {
+		return RefreshTokenRes{}, fmt.Errorf("RefreshAccessToken error: error_msg=%s", result.ErrorMsg)
+	}
+	return result, nil
+}

+ 46 - 0
vendor/github.com/lin-jim-leon/kuaishou/open/user/user.go

@@ -0,0 +1,46 @@
+package user
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/lin-jim-leon/kuaishou/util"
+)
+
+const (
+	UserinfoUrl = "https://open.kuaishou.com/openapi/user_info?app_id=%s&access_token=%s"
+)
+
+type Info struct {
+	Name    string `json:"name"`
+	Sex     string `json:"sex"`
+	Fan     int    `json:"fan"`
+	Follow  int    `json:"follow"`
+	Head    string `json:"head"`
+	BigHead string `json:"bigHead"`
+	City    string `json:"city"`
+}
+
+type Userresponse struct {
+	Result   int    `json:"result"`
+	ErrorMsg string `json:"error_msg"`
+	Data     Info   `json:"user_info"`
+}
+
+// GetUserinfo 获取用户信息
+func GetUserinfo(appid string, accesstoken string) (info Userresponse, err error) {
+	uri := fmt.Sprintf(UserinfoUrl, appid, accesstoken)
+	var response []byte
+	response, err = util.HTTPGet(uri)
+	if err != nil {
+		return Userresponse{}, err
+	}
+	var result Userresponse
+	err = json.Unmarshal(response, &result)
+	if err != nil {
+		return Userresponse{}, err
+	}
+	if len(result.ErrorMsg) > 0 {
+		return Userresponse{}, fmt.Errorf("GetUserinfo error: error_msg=%s", result.ErrorMsg)
+	}
+	return result, nil
+}

+ 21 - 0
vendor/github.com/lin-jim-leon/kuaishou/util/http.go

@@ -0,0 +1,21 @@
+package util
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http"
+)
+
+// get请求
+func HTTPGet(uri string) ([]byte, error) {
+	response, err := http.Get(uri)
+	if err != nil {
+		return nil, err
+	}
+
+	defer response.Body.Close()
+	if response.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, response.StatusCode)
+	}
+	return ioutil.ReadAll(response.Body)
+}

+ 6 - 0
vendor/modules.txt

@@ -185,6 +185,12 @@ github.com/grokify/html-strip-tags-go
 # github.com/josharian/intern v1.0.0
 ## explicit; go 1.5
 github.com/josharian/intern
+# github.com/lin-jim-leon/kuaishou v0.3.0
+## explicit; go 1.22.1
+github.com/lin-jim-leon/kuaishou/open/merchant
+github.com/lin-jim-leon/kuaishou/open/oauth
+github.com/lin-jim-leon/kuaishou/open/user
+github.com/lin-jim-leon/kuaishou/util
 # github.com/mailru/easyjson v0.7.7
 ## explicit; go 1.12
 github.com/mailru/easyjson