merchat.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package merchant
  2. import (
  3. "crypto/md5"
  4. "encoding/hex"
  5. "encoding/json"
  6. "fmt"
  7. "github.com/lin-jim-leon/kuaishou/util"
  8. "net/url"
  9. "sort"
  10. "strings"
  11. "time"
  12. )
  13. const (
  14. 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"
  15. 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"
  16. 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"
  17. )
  18. type Iteminfo struct {
  19. Result int `json:"result"`
  20. ItemId int64 `json:"itemId"`
  21. ErrorMsg string `json:"errorMsg"`
  22. }
  23. type AddItemsres struct {
  24. Result int `json:"result"`
  25. Msg string `json:"msg"`
  26. ErrorMsg string `json:"error_msg"`
  27. Code string `json:"code"`
  28. Data []Iteminfo `json:"data"`
  29. SubMsg string `json:"sub_msg"`
  30. SubCode string `json:"sub_code"`
  31. }
  32. // generateSign 生成签名
  33. func generateSign(appkey, signsecret, accesstoken, param string, timestamp int64, method string) string {
  34. // 将请求参数按照字典顺序排序
  35. params := map[string]string{
  36. "access_token": accesstoken,
  37. "appkey": appkey,
  38. "method": method,
  39. "param": param,
  40. "signMethod": "MD5",
  41. "timestamp": fmt.Sprintf("%d", timestamp),
  42. "version": "1",
  43. }
  44. keys := make([]string, 0, len(params))
  45. for k := range params {
  46. keys = append(keys, k)
  47. }
  48. sort.Strings(keys)
  49. // 构造待签名字符串
  50. var signStr strings.Builder
  51. for _, k := range keys {
  52. signStr.WriteString(fmt.Sprintf("%s=%s&", k, params[k]))
  53. }
  54. signStr.WriteString("signSecret=" + signsecret)
  55. // 计算签名值
  56. hasher := md5.New()
  57. hasher.Write([]byte(signStr.String()))
  58. encrypted := hasher.Sum(nil)
  59. return hex.EncodeToString(encrypted)
  60. }
  61. // 商品加橱窗
  62. func AddItemsToShelf(Appkey string, signsecret string, accesstoken string, itemidlist []string) (Adinfo AddItemsres, err error) {
  63. // 构造请求参数 param
  64. rawParam := fmt.Sprintf(`{"itemIds":[%s]}`, strings.Join(itemidlist, ","))
  65. // 获取当前时间戳(毫秒级)
  66. timestamp := time.Now().UnixNano() / int64(time.Millisecond)
  67. method := "open.distribution.selection.pick"
  68. // 对请求参数进行签名
  69. sign := generateSign(Appkey, signsecret, accesstoken, rawParam, timestamp, method)
  70. // 构造完整的请求 URL
  71. encodedParam := url.QueryEscape(rawParam)
  72. uri := fmt.Sprintf(PickUrl, Appkey, accesstoken, encodedParam, sign, timestamp)
  73. // 发送 HTTP GET 请求
  74. var response []byte
  75. response, err = util.HTTPGet(uri)
  76. if err != nil {
  77. return AddItemsres{}, err
  78. }
  79. // 解析响应数据
  80. var result AddItemsres
  81. err = json.Unmarshal(response, &result)
  82. if err != nil {
  83. return AddItemsres{}, err
  84. }
  85. // 检查是否有错误信息
  86. if result.ErrorMsg != "SUCCESS" {
  87. return AddItemsres{}, fmt.Errorf("AddItemsToShelf error: %s", result.ErrorMsg)
  88. }
  89. return result, nil
  90. }
  91. type SelsetionRes struct {
  92. Code string `json:"code"`
  93. Msg string `json:"msg"`
  94. SubCode string `json:"sub_code"`
  95. SubMsg string `json:"sub_msg"`
  96. Result int `json:"result"`
  97. ErrorMsg string `json:"error_msg"`
  98. ItemList []DistributeSelectionItem `json:"itemList"`
  99. ShopTitle string `json:"shopTitle"`
  100. }
  101. type DistributeSelectionItem struct {
  102. ItemID int64 `json:"itemId"`
  103. ZKFinalPrice int64 `json:"zkFinalPrice"`
  104. ItemImgURL string `json:"itemImgUrl"`
  105. ItemPrice int64 `json:"itemPrice"`
  106. SKUList []DistributeSKU `json:"skuList"`
  107. SoldCountThirtyDays int64 `json:"soldCountThirtyDays"`
  108. ShopTitle string `json:"shopTitle"`
  109. CommissionRate int `json:"commissionRate"`
  110. BrandName string `json:"brandName"`
  111. ItemTitle string `json:"itemTitle"`
  112. ProfitAmount int64 `json:"profitAmount"`
  113. ShopScore string `json:"shopScore"`
  114. ShopStar string `json:"shopStar"`
  115. ItemDesc string `json:"itemDesc"`
  116. ShopType int `json:"shopType"`
  117. CategoryID int `json:"categoryId"`
  118. ItemGalleryURLs []string `json:"itemGalleryUrls"`
  119. ItemDescURLs []string `json:"itemDescUrls"`
  120. MerchantSoldCountThirtyDays int64 `json:"merchantSoldCountThirtyDays"`
  121. ShopID int64 `json:"shopId"`
  122. }
  123. type DistributeSKU struct {
  124. SKUPrice int64 `json:"skuPrice"`
  125. SKUStock int64 `json:"skuStock"`
  126. Specification string `json:"specification"`
  127. SKUID int64 `json:"skuId"`
  128. }
  129. func Queryselectiondetail(Appkey string, signsecret string, accesstoken string, itemidlist []string) (Selectitem SelsetionRes, err error) {
  130. // 构造请求参数 param
  131. rawParam := fmt.Sprintf(`{"itemId":[%s]}`, strings.Join(itemidlist, ","))
  132. // 获取当前时间戳(毫秒级)
  133. timestamp := time.Now().UnixNano() / int64(time.Millisecond)
  134. method := "open.distribution.query.selection.item.detail"
  135. // 对请求参数进行签名
  136. sign := generateSign(Appkey, signsecret, accesstoken, rawParam, timestamp, method)
  137. // 构造完整的请求 URL
  138. encodedParam := url.QueryEscape(rawParam)
  139. uri := fmt.Sprintf(Selectdetail, Appkey, accesstoken, encodedParam, sign, timestamp)
  140. fmt.Println(uri)
  141. // 发送 HTTP GET 请求
  142. var response []byte
  143. response, err = util.HTTPGet(uri)
  144. if err != nil {
  145. return SelsetionRes{}, err
  146. }
  147. fmt.Println(string(response))
  148. // 解析响应数据
  149. var result SelsetionRes
  150. err = json.Unmarshal(response, &result)
  151. if err != nil {
  152. return SelsetionRes{}, err
  153. }
  154. // 检查是否有错误信息
  155. if result.ErrorMsg != "" {
  156. return SelsetionRes{}, fmt.Errorf("Queryselectiondetail error: %s", result.ErrorMsg)
  157. }
  158. return result, nil
  159. }
  160. type OrderlistRes struct {
  161. Code string `json:"code"` // 主返回码
  162. Msg string `json:"msg"` // 主返回信息
  163. SubCode string `json:"sub_code"` // 子返回码
  164. SubMsg string `json:"sub_msg"` // 子返回信息
  165. Result int `json:"result"` // 返回码
  166. ErrorMsg string `json:"error_msg"` // 返回错误信息
  167. Data OrderCursor `json:"data"` // 返回数据
  168. }
  169. type OrderCursor struct {
  170. Cursor string `json:"pcursor"` // 分销订单位点游标(请求透传, "nomore"标识后续无数据)
  171. OrderViews []OrderView `json:"orderView"` // 订单信息
  172. }
  173. type OrderView struct {
  174. DistributorID int64 `json:"distributorId"` // 分销推广者用户ID
  175. OrderID int64 `json:"oid"` // 订单ID
  176. CPSOrderStatus int `json:"cpsOrderStatus"` // 分销订单状态
  177. OrderCreateTime int64 `json:"orderCreateTime"` // 订单创建时间
  178. PayTime int64 `json:"payTime"` // 订单支付时间
  179. OrderTradeAmount int64 `json:"orderTradeAmount"` // 订单交易总金额
  180. CPSOrderProductViews []CPSOrderProductView `json:"cpsOrderProductView"` // 商品信息
  181. CreateTime int64 `json:"createTime"` // 创建时间
  182. UpdateTime int64 `json:"updateTime"` // 更新时间
  183. SettlementSuccessTime int64 `json:"settlementSuccessTime"` // 结算时间
  184. SettlementAmount int64 `json:"settlementAmount"` // 结算金额
  185. SendTime int64 `json:"sendTime"` // 订单发货时间
  186. SendStatus int `json:"sendStatus"` // 订单发货状态
  187. RecvTime int64 `json:"recvTime"` // 订单收货时间
  188. BuyerOpenID string `json:"buyerOpenId"` // 买家唯一识别ID
  189. BaseAmount int64 `json:"baseAmount"` // 计佣基数
  190. ShareRateStr string `json:"shareRateStr"` // 分成比例
  191. SettlementBizType int `json:"settlementBizType"` // 订单业务结算类型
  192. OrderRefundInfo []CPSDistributorOrderRefundInfo `json:"orderRefundInfo"` // 退款信息
  193. OrderChannel string `json:"orderChannel"` // 订单渠道标识
  194. }
  195. type CPSOrderProductView struct {
  196. OrderID int64 `json:"oid"` // 订单ID
  197. ItemID int64 `json:"itemId"` // 商品ID
  198. ItemTitle string `json:"itemTitle"` // 商品标题
  199. ItemPrice int64 `json:"itemPrice"` // 商品单价快照
  200. EstimatedIncome int64 `json:"estimatedIncome"` // 预估收入
  201. CommissionRate int `json:"commissionRate"` // 佣金比率
  202. ServiceRate int `json:"serviceRate"` // 平台服务费率
  203. ServiceAmount int64 `json:"serviceAmount"` // 平台服务费
  204. CPSPID string `json:"cpsPid"` // 推广位id
  205. SellerID int64 `json:"sellerId"` // 商家Id
  206. SellerNickName string `json:"sellerNickName"` // 商家昵称快照
  207. Num int `json:"num"` // 商品数量
  208. StepCondition int `json:"stepCondition"` // 阶梯佣金条件
  209. StepCommissionRate int `json:"stepCommissionRate"` // 阶梯佣金比率
  210. StepCommissionAmount int64 `json:"stepCommissionAmount"` // 阶梯佣金金额
  211. ServiceIncome int64 `json:"serviceIncome"` // 接单服务收入
  212. ExcitationIncome int64 `json:"excitationIncome"` // 奖励收入
  213. }
  214. type CPSDistributorOrderRefundInfo struct {
  215. StartRefundTime int64 `json:"startRefundTime"` // 发起退款时间
  216. EndRefundTime int64 `json:"endRefundTime"` // 完成退款时间
  217. RefundFee int64 `json:"refundFee"` // 退款金额
  218. RefundStatus string `json:"refundStatus"` // 退款状态
  219. }
  220. // 订单列表(游标)
  221. func Corderlist(Appkey string, signsecret string, accesstoken string, cpsOrderStatus int, pageSize int, beginTime int64, endTime int64, pcursor string) (corlist OrderlistRes, err error) {
  222. // 构造请求参数 param
  223. rawParam := fmt.Sprintf(`{"cpsOrderStatus":%d,"pageSize":%d,"sortType":1,"queryType":1,"beginTime":%d,"endTime":%d,"pcursor":"%s"}`, cpsOrderStatus, pageSize, beginTime, endTime, pcursor)
  224. // 获取当前时间戳(毫秒级)
  225. timestamp := time.Now().UnixNano() / int64(time.Millisecond)
  226. method := "open.distribution.cps.distributor.order.cursor.list"
  227. // 对请求参数进行签名
  228. sign := generateSign(Appkey, signsecret, accesstoken, rawParam, timestamp, method)
  229. // 构造完整的请求 URL
  230. encodedParam := url.QueryEscape(rawParam)
  231. uri := fmt.Sprintf(Corderlisturl, Appkey, accesstoken, encodedParam, sign, timestamp)
  232. // 发送 HTTP GET 请求
  233. var response []byte
  234. response, err = util.HTTPGet(uri)
  235. if err != nil {
  236. return OrderlistRes{}, err
  237. }
  238. // 解析响应数据
  239. var result OrderlistRes
  240. err = json.Unmarshal(response, &result)
  241. if err != nil {
  242. return OrderlistRes{}, err
  243. }
  244. // 检查是否有错误信息
  245. if result.ErrorMsg != "SUCCESS" {
  246. return OrderlistRes{}, fmt.Errorf("Corderlist error: %s", result.ErrorMsg)
  247. }
  248. return result, nil
  249. }