3661 lines
120 KiB
Go
3661 lines
120 KiB
Go
package main
|
||
|
||
/*
|
||
#include <stdlib.h>
|
||
*/
|
||
import "C"
|
||
import (
|
||
"bytes"
|
||
"crypto/md5"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/parnurzeal/gorequest"
|
||
"io"
|
||
"mime/multipart"
|
||
"net/http"
|
||
"net/url"
|
||
"os"
|
||
"path/filepath"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
"unsafe"
|
||
)
|
||
|
||
// ErrorResponse 错误响应结构
|
||
type ErrorResponse struct {
|
||
ErrorMsg string `json:"error_msg"` // 错误信息
|
||
SubMsg string `json:"sub_msg"` // 子错误信息
|
||
SubCode interface{} `json:"sub_code"` // 使用json.RawMessage处理null和不同类型
|
||
ErrorCode int `json:"error_code"` // 错误代码
|
||
RequestID string `json:"request_id"` // 请求ID
|
||
}
|
||
|
||
// ErrorWrapper 最外层错误响应包装
|
||
type ErrorWrapper struct {
|
||
ErrorResponse ErrorResponse `json:"error_response"` // 错误响应
|
||
}
|
||
|
||
/*
|
||
* 生成签名
|
||
* param params[map[string]interface{}] 生成签名需要的map
|
||
* param clientSecret[string] 客户端密钥
|
||
* return 签名
|
||
*/
|
||
func generateSign(params map[string]interface{}, clientSecret string) string {
|
||
// 获取所有键并排序
|
||
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 {
|
||
// 跳过 sign 参数(签名本身不参与签名)
|
||
if strings.ToLower(k) == "sign" {
|
||
continue
|
||
}
|
||
|
||
value := ""
|
||
if params[k] != nil {
|
||
value = fmt.Sprintf("%v", params[k]) // 将任意值转为字符串
|
||
}
|
||
// 按照文档格式:参数名+参数值
|
||
signStr.WriteString(k + value)
|
||
}
|
||
|
||
signString := signStr.String()
|
||
|
||
// 拼接client_secret: client_secret + 参数串 + client_secret
|
||
data := clientSecret + signString + clientSecret
|
||
|
||
// MD5加密并转大写
|
||
hasher := md5.New()
|
||
hasher.Write([]byte(data))
|
||
return strings.ToUpper(hex.EncodeToString(hasher.Sum(nil)))
|
||
}
|
||
|
||
/*
|
||
* 类目预测
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param outerCatId[string] 外部类目ID
|
||
* param outerCatName[string] 外部类目名称
|
||
* param outerGoodsName[string] 外部商品名称
|
||
* return 类目预测响应结构体,错误信息
|
||
*/
|
||
func pddGoodsOuterCatMappingGet(clientId, clientSecret, accessToken,
|
||
outerCatId, outerCatName, outerGoodsName string) (string, error) {
|
||
// API地址
|
||
url := fmt.Sprint("https://gw-api.pinduoduo.com/api/router")
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.goods.outer.cat.mapping.get", // API类型
|
||
"data_type": "JSON", // 数据类型
|
||
"client_id": clientId, // 客户端ID
|
||
"access_token": accessToken, // 访问令牌
|
||
"outer_cat_id": outerCatId, // 外部类目ID
|
||
"outer_cat_name": outerCatName, // 外部类目名称
|
||
"outer_goods_name": outerGoodsName, // 外部商品名称
|
||
"timestamp": timestamp, // 时间戳
|
||
}
|
||
// 生成签名
|
||
sign := generateSign(params, clientSecret)
|
||
// 请求体
|
||
formData := map[string]interface{}{
|
||
"type": "pdd.goods.outer.cat.mapping.get",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"outer_cat_id": outerCatId,
|
||
"outer_cat_name": outerCatName,
|
||
"outer_goods_name": outerGoodsName,
|
||
"timestamp": timestamp,
|
||
"sign": sign, // 签名
|
||
}
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Get(url).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Timeout(30 * time.Second). // 30秒超时
|
||
Send(formData). // 发送表单数据
|
||
End() // 结束请求
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
/*
|
||
* 快递公司查看
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* return 快递公司查看响应结构体,错误信息
|
||
*/
|
||
func pddLogisticsCompaniesGet(clientId, clientSecret string) (string, error) {
|
||
url := fmt.Sprint("https://gw-api.pinduoduo.com/api/router")
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.logistics.companies.get", // API类型:获取物流公司
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"timestamp": timestamp,
|
||
}
|
||
sign := generateSign(params, clientSecret)
|
||
// 请求体
|
||
formData := map[string]interface{}{
|
||
"type": "pdd.logistics.companies.get",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"timestamp": timestamp,
|
||
"sign": sign,
|
||
}
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Get(url).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理:检查是否有错误响应
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
/*
|
||
* erp打单信息同步
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param logisticsId[string] 物流公司编码
|
||
* param orderSn[string] 订单号
|
||
* param orderState[string] 订单状态:1-已打单
|
||
* param waybillNo[string] 运单号
|
||
* return 快递公司查看响应结构体,错误信息
|
||
*/
|
||
func pddErpOrderSync(clientId, clientSecret, accessToken, logisticsId,
|
||
orderSn, orderState, waybillNo string) (string, error) {
|
||
url := fmt.Sprint("https://gw-api.pinduoduo.com/api/router")
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名
|
||
params := map[string]interface{}{
|
||
"type": "pdd.erp.order.sync", // API类型:ERP订单同步
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"logistics_id": logisticsId, // 物流公司ID
|
||
"order_sn": orderSn, // 订单号
|
||
"order_state": orderState, // 订单状态
|
||
"waybill_no": waybillNo, // 运单号
|
||
"timestamp": timestamp,
|
||
}
|
||
sign := generateSign(params, clientSecret)
|
||
// 请求体
|
||
formData := map[string]interface{}{
|
||
"type": "pdd.erp.order.sync",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"logistics_id": logisticsId,
|
||
"order_sn": orderSn,
|
||
"order_state": orderState,
|
||
"waybill_no": waybillNo,
|
||
"timestamp": timestamp,
|
||
"sign": sign,
|
||
}
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Get(url).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
/*
|
||
* 订单发货通知接口
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param logisticsOnlineSendJson[string] 订单发货通知json字符串
|
||
* return 订单发货通知接口响应结构体,错误信息
|
||
*/
|
||
func pddLogisticsOnlineSend(clientId, clientSecret, accessToken string, logisticsOnlineSendJson string) (string, error) {
|
||
url := fmt.Sprint("https://gw-api.pinduoduo.com/api/router")
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名
|
||
params := map[string]interface{}{
|
||
"type": "pdd.logistics.online.send",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(logisticsOnlineSendJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Get(url).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Timeout(30 * time.Second).
|
||
Send(params).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// LogisticsCompany 物流公司信息结构体
|
||
type LogisticsCompany struct {
|
||
Available int `json:"available"` // 是否可用
|
||
Code string `json:"code"` // 物流公司代码
|
||
ID int `json:"id"` // 物流公司ID
|
||
LogisticsCompany string `json:"logistics_company"` // 物流公司名称
|
||
}
|
||
|
||
// LogisticsCompaniesGetResponse 物流公司列表响应结构体
|
||
type LogisticsCompaniesGetResponse struct {
|
||
LogisticsCompanies []LogisticsCompany `json:"logistics_companies"` // 物流公司列表
|
||
}
|
||
|
||
// LogisticsResponse 最外层响应结构体
|
||
type LogisticsResponse struct {
|
||
LogisticsCompaniesGetResponse LogisticsCompaniesGetResponse `json:"logistics_companies_get_response"` // 物流公司响应
|
||
}
|
||
|
||
/*
|
||
* 拼多多订单同步(组合接口:先查物流公司,再同步订单)
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param logisticsCompany[string] 外部类目ID
|
||
* param logisticsOnlineSendJson[string] 拼多多订单同步json字符串
|
||
* return 类目预测响应结构体,错误信息
|
||
*/
|
||
func pddOrderSynchronization(clientId, clientSecret, accessToken, logisticsCompany, logisticsOnlineSendJson string) (string, error) {
|
||
|
||
var logisticsOnlineSendData map[string]interface{}
|
||
err := json.Unmarshal([]byte(logisticsOnlineSendJson), &logisticsOnlineSendData)
|
||
if err != nil {
|
||
return "", fmt.Errorf("logisticsOnlineSendJson JSON解析失败: %v", err)
|
||
}
|
||
|
||
// 1. 获取物流公司列表
|
||
logisticsCompaniesGet, err := pddLogisticsCompaniesGet(clientId, clientSecret)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
// 2. 解析物流公司响应
|
||
var response LogisticsResponse
|
||
if err := json.Unmarshal([]byte(logisticsCompaniesGet), &response); err != nil {
|
||
return "", fmt.Errorf("解析JSON失败: %v", err)
|
||
}
|
||
// 3. 根据物流公司名称查找对应的物流公司ID
|
||
for _, lc := range response.LogisticsCompaniesGetResponse.LogisticsCompanies {
|
||
if lc.LogisticsCompany == logisticsCompany {
|
||
logisticsOnlineSendData["logistics_id"] = fmt.Sprintf("%d", lc.ID)
|
||
break
|
||
}
|
||
}
|
||
// logistics
|
||
fmt.Println(logisticsOnlineSendData)
|
||
|
||
logisticsOnlineSendStr, err := json.Marshal(logisticsOnlineSendData)
|
||
if err != nil {
|
||
return "", fmt.Errorf("logisticsOnlineSendData 序列化失败: %v", err)
|
||
}
|
||
logisticsOnlineSend, err := pddLogisticsOnlineSend(clientId, clientSecret, accessToken, string(logisticsOnlineSendStr))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return logisticsOnlineSend, nil
|
||
}
|
||
|
||
/*
|
||
* 商品图片上传接口
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param filePath[string] 商品图片文件流
|
||
* return 商品图片上传响应结构体,错误信息
|
||
*/
|
||
func pddGoodsImgUpload(clientId, clientSecret, accessToken string, filePath string) (string, error) {
|
||
url := fmt.Sprint("https://gw-upload.pinduoduo.com/api/upload") // 上传专用地址
|
||
|
||
// 1. 打开文件
|
||
file, err := os.Open(filePath)
|
||
if err != nil {
|
||
return "", fmt.Errorf("打开文件失败: %v", err)
|
||
}
|
||
defer file.Close() // 确保文件关闭
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.goods.img.upload", // API类型:商品图片上传
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
sign := generateSign(params, clientSecret)
|
||
|
||
// 创建multipart/form-data请求体
|
||
body := &bytes.Buffer{}
|
||
writer := multipart.NewWriter(body)
|
||
|
||
// 读取文件内容
|
||
fileData, err := os.ReadFile(filePath)
|
||
if err != nil {
|
||
return "", fmt.Errorf("读取文件失败: %v", err)
|
||
}
|
||
|
||
// 添加文件字段
|
||
part, err := writer.CreateFormFile("file", filepath.Base(filePath))
|
||
if err != nil {
|
||
return "", fmt.Errorf("创建表单文件失败: %v", err)
|
||
}
|
||
_, err = io.Copy(part, bytes.NewReader(fileData))
|
||
if err != nil {
|
||
return "", fmt.Errorf("复制文件内容失败: %v", err)
|
||
}
|
||
|
||
// 添加其他参数到multipart表单
|
||
for key, value := range params {
|
||
writer.WriteField(key, fmt.Sprintf("%v", value))
|
||
}
|
||
writer.WriteField("sign", sign) // 添加签名
|
||
writer.Close() // 关闭writer,完成表单构建
|
||
|
||
// 发送POST请求
|
||
request := gorequest.New()
|
||
resp, respBody, errs := request.Post(url).
|
||
Timeout(30*time.Second).
|
||
Set("Content-Type", writer.FormDataContentType()). // 设置Content-Type
|
||
Send(body.String()). // 发送请求体
|
||
End()
|
||
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(respBody), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(respBody), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// GoodsAddRequest 商品添加/编辑请求结构体
|
||
type GoodsAddRequest struct {
|
||
AutoFillSpuProperty bool `json:"auto_fill_spu_property,omitempty"` // 是否自动补充标品属性
|
||
BadFruitClaim int `json:"bad_fruit_claim,omitempty"` // 坏果包赔
|
||
BuyLimit int64 `json:"buy_limit,omitempty"` // 限购次数
|
||
CarouselGallery []string `json:"carousel_gallery"` // 商品轮播图
|
||
CarouselVideo []CarouselVideo `json:"carousel_video,omitempty"` // 商品视频
|
||
CarouselVideoURL string `json:"carousel_video_url,omitempty"` // 轮播视频
|
||
CatID int64 `json:"cat_id"` // 叶子类目ID
|
||
CostTemplateID int64 `json:"cost_template_id"` // 物流运费模板ID
|
||
CountryID int `json:"country_id"` // 地区/国家ID
|
||
CustomerNum int64 `json:"customer_num,omitempty"` // 团购人数
|
||
Customs string `json:"customs,omitempty"` // 海关名称
|
||
DeliveryOneDay int `json:"delivery_one_day,omitempty"` // 是否当日发货
|
||
DeliveryType int `json:"delivery_type,omitempty"` // 发货方式
|
||
DetailGallery []string `json:"detail_gallery"` // 商品详情图
|
||
ElecGoodsAttributes ElecGoodsAttributes `json:"elec_goods_attributes,omitempty"` // 卡券类商品属性
|
||
GoodsDesc string `json:"goods_desc,omitempty"` // 商品描述
|
||
GoodsName string `json:"goods_name"` // 商品标题
|
||
GoodsProperties []GoodsProperty `json:"goods_properties,omitempty"` // 商品属性列表
|
||
GoodsTradeAttr GoodsTradeAttr `json:"goods_trade_attr,omitempty"` // 日历商品交易相关信息
|
||
GoodsTravelAttr GoodsTravelAttr `json:"goods_travel_attr,omitempty"` // 商品出行信息
|
||
GoodsType int `json:"goods_type"` // 商品类型
|
||
IgnoreEditWarn bool `json:"ignore_edit_warn,omitempty"` // 是否获取商品发布警告信息
|
||
ImageURL string `json:"image_url,omitempty"` // 商品主图
|
||
InvoiceStatus bool `json:"invoice_status,omitempty"` // 是否支持开票
|
||
IsCustoms bool `json:"is_customs,omitempty"` // 是否需要上报海关
|
||
IsFolt bool `json:"is_folt"` // 是否支持假一赔十
|
||
IsGroupPreSale int `json:"is_group_pre_sale,omitempty"` // 是否成团预售
|
||
IsPreSale bool `json:"is_pre_sale"` // 是否预售
|
||
IsRefundable bool `json:"is_refundable"` // 是否7天无理由退换货
|
||
IsSkuPreSale int `json:"is_sku_pre_sale,omitempty"` // 是否sku预售
|
||
LackOfWeightClaim int `json:"lack_of_weight_claim,omitempty"` // 缺重包退
|
||
LocalServiceIDList []int `json:"local_service_id_list,omitempty"` // 本地服务id
|
||
MaiJiaZiTi string `json:"mai_jia_zi_ti,omitempty"` // 买家自提模版id
|
||
MarketPrice int64 `json:"market_price"` // 参考价格(分)
|
||
OrderLimit int `json:"order_limit,omitempty"` // 单次限量
|
||
OriginCountryID int `json:"origin_country_id,omitempty"` // 原产地id
|
||
OutGoodsID string `json:"out_goods_id,omitempty"` // 商品外部编码
|
||
OutSourceGoodsID string `json:"out_source_goods_id,omitempty"` // 第三方商品Id
|
||
OutSourceType int `json:"out_source_type,omitempty"` // 第三方商品来源
|
||
OverseaGoods OverseaGoods `json:"oversea_goods,omitempty"` // 海淘商品信息
|
||
OverseaType int `json:"oversea_type,omitempty"` // oversea_type
|
||
PreSaleTime int64 `json:"pre_sale_time,omitempty"` // 预售时间
|
||
PrivacyDelivery int `json:"privacy_delivery,omitempty"` // 保密发货
|
||
QuanGuoLianBao int `json:"quan_guo_lian_bao,omitempty"` // 是否支持全国联保
|
||
SecondHand bool `json:"second_hand"` // 是否二手商品
|
||
ShangMenAnZhuang string `json:"shang_men_an_zhuang,omitempty"` // 上门安装模版id
|
||
ShipmentLimitSecond int64 `json:"shipment_limit_second"` // 承诺发货时间(秒)
|
||
ShopGroupID int64 `json:"shop_group_id,omitempty"` // 门店组id
|
||
SizeSpecID int64 `json:"size_spec_id,omitempty"` // 尺码表id
|
||
SkuList []Sku `json:"sku_list"` // sku对象列表
|
||
SkuType int `json:"sku_type,omitempty"` // 库存方式
|
||
SongHuoAnZhuang string `json:"song_huo_an_zhuang,omitempty"` // 送货入户并安装模版id
|
||
SongHuoRuHu string `json:"song_huo_ru_hu,omitempty"` // 送货入户模版id
|
||
TinyName string `json:"tiny_name,omitempty"` // 短标题
|
||
TwoPiecesDiscount int `json:"two_pieces_discount,omitempty"` // 满2件折扣
|
||
Warehouse string `json:"warehouse,omitempty"` // 保税仓
|
||
WarmTips string `json:"warm_tips,omitempty"` // 水果类目温馨提示
|
||
ZhiHuanBuXiu int `json:"zhi_huan_bu_xiu,omitempty"` // 只换不修的天数
|
||
}
|
||
|
||
// CarouselVideo 轮播视频
|
||
type CarouselVideo struct {
|
||
FileID int64 `json:"file_id,omitempty"` // 商品视频id
|
||
VideoURL string `json:"video_url,omitempty"` // 商品视频url
|
||
}
|
||
|
||
// ElecGoodsAttributes 卡券类商品属性
|
||
type ElecGoodsAttributes struct {
|
||
BeginTime int64 `json:"begin_time,omitempty"` // 开始时间
|
||
DaysTime int `json:"days_time,omitempty"` // 天数内有效
|
||
EndTime int64 `json:"end_time,omitempty"` // 截止时间
|
||
TimeType int `json:"time_type,omitempty"` // 卡券核销类型
|
||
}
|
||
|
||
// GoodsProperty 商品属性
|
||
type GoodsProperty struct {
|
||
GroupID int `json:"group_id,omitempty"` // 属性值分组ID
|
||
ImgURL string `json:"img_url,omitempty"` // 图片url
|
||
Note string `json:"note,omitempty"` // 备注
|
||
ParentSpecID int64 `json:"parent_spec_id,omitempty"` // 父规格ID
|
||
RefPid int64 `json:"ref_pid,omitempty"` // 引用属性id
|
||
SpecID int64 `json:"spec_id,omitempty"` // 规格ID
|
||
TemplatePid int64 `json:"template_pid,omitempty"` // 模板属性id
|
||
Value string `json:"value,omitempty"` // 属性值
|
||
ValueUnit string `json:"value_unit,omitempty"` // 属性单位
|
||
Vid int64 `json:"vid,omitempty"` // 属性值id
|
||
//TableInfo []TableValueList `json:"table_info,omitempty"` // 成分表表单信息
|
||
}
|
||
|
||
//// TableValueList 表单内容列表
|
||
//type TableValueList struct {
|
||
// ColumnType int `json:"column_type,omitempty"` // 列类型 1-材质成分百分比
|
||
// Unit string `json:"unit,omitempty"` // 表单单位,材质成分表时为:%
|
||
// Value string `json:"value,omitempty"` // 表单值,材质成分表时为:占比百分值
|
||
//}
|
||
|
||
// GoodsTradeAttr 日历商品交易相关信息
|
||
type GoodsTradeAttr struct {
|
||
AdvancesDays int `json:"advances_days,omitempty"` // 提前预定天数
|
||
BookingNotes BookingNotes `json:"booking_notes,omitempty"` // 预订须知
|
||
LifeSpan int `json:"life_span,omitempty"` // 卡券有效期
|
||
}
|
||
|
||
// BookingNotes 预订须知
|
||
type BookingNotes struct {
|
||
URL *string `json:"url,omitempty"` // 预定须知图片地址
|
||
}
|
||
|
||
// GoodsTravelAttr 商品出行信息
|
||
type GoodsTravelAttr struct {
|
||
NeedTourist bool `json:"need_tourist,omitempty"` // 出行人是否必填
|
||
Type int `json:"type,omitempty"` // 日历商品类型
|
||
}
|
||
|
||
// OverseaGoods 海淘商品信息
|
||
type OverseaGoods struct {
|
||
BondedWarehouseKey string `json:"bonded_warehouse_key"` // 保税仓唯一标识
|
||
ConsumptionTaxRate int `json:"consumption_tax_rate,omitempty"` // 消费税率
|
||
CustomsBroker string `json:"customs_broker,omitempty"` // 清关服务商
|
||
HsCode string `json:"hs_code,omitempty"` // 海关编号
|
||
ValueAddedTaxRate int `json:"value_added_tax_rate,omitempty"` // 增值税率
|
||
}
|
||
|
||
// Sku SKU信息
|
||
type Sku struct {
|
||
IsOnsale int `json:"is_onsale"` // sku上架状态
|
||
Length int64 `json:"length,omitempty"` // sku送装参数:长度
|
||
LimitQuantity int64 `json:"limit_quantity"` // sku购买限制
|
||
MultiPrice int64 `json:"multi_price"` // 商品团购价格
|
||
OutSkuSn string `json:"out_sku_sn,omitempty"` // 商品sku外部编码
|
||
OutSourceSkuID string `json:"out_source_sku_id,omitempty"` // 第三方sku Id
|
||
OverseaSku OverseaSku `json:"oversea_sku,omitempty"` // 海淘sku信息
|
||
Price int64 `json:"price"` // 商品单买价格
|
||
Quantity int64 `json:"quantity"` // 商品sku库存数量
|
||
SkuPreSaleTime int `json:"sku_pre_sale_time,omitempty"` // sku预售时间戳
|
||
SkuProperties []SkuProperty `json:"sku_properties"` // sku属性
|
||
SpecIDList string `json:"spec_id_list"` // 商品规格列表
|
||
ThumbURL string `json:"thumb_url"` // sku缩略图
|
||
Weight int64 `json:"weight"` // 重量(g)
|
||
}
|
||
|
||
// OverseaSku 海淘SKU信息
|
||
type OverseaSku struct {
|
||
MeasurementCode string `json:"measurement_code"` // 计量单位编码
|
||
Specifications string `json:"specifications"` // 规格
|
||
Taxation int `json:"taxation"` // 税费
|
||
}
|
||
|
||
// SkuProperty SKU属性
|
||
type SkuProperty struct {
|
||
Punit string `json:"punit"` // 属性单位
|
||
RefPid int64 `json:"ref_pid"` // 属性id
|
||
Value string `json:"value"` // 属性值
|
||
Vid int64 `json:"vid"` // 属性值id
|
||
}
|
||
|
||
/*
|
||
* 商品新增接口
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param goodsAddJson[string] 新增商品信息json字符串
|
||
* return 商品新增接口响应结构体,错误信息
|
||
*/
|
||
func pddGoodsAdd(clientId, clientSecret, accessToken string, goodsAddJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.goods.add", // API类型:商品新增接口
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if goodsAddJson == "" {
|
||
return "", fmt.Errorf("goodsAddJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(goodsAddJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
/*
|
||
* 联合拼多多图片上传的商品新增(组合接口)
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param goodsAddJson[string] 新增商品信息json字符串
|
||
* return 商品新增接口响应结构体,错误信息
|
||
*/
|
||
func selfPddGoodsAdd(clientId, clientSecret, accessToken string, filePath string, goodsAddJson string) (string, error) {
|
||
// 1. 上传商品图片
|
||
upload, err := pddGoodsImgUpload(clientId, clientSecret, accessToken, filePath)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
// 2. 解析商品添加请求JSON
|
||
var goodsAddRequest GoodsAddRequest
|
||
if err := json.Unmarshal([]byte(goodsAddJson), &goodsAddRequest); err != nil {
|
||
return "", fmt.Errorf("解析 goodsAddJson 失败: %v", err)
|
||
}
|
||
// 3. 设置图片URL
|
||
goodsAddRequest.ImageURL = upload
|
||
// 4. 重新序列化为JSON
|
||
goodsAddRequestStr, err := json.Marshal(goodsAddRequest)
|
||
if err != nil {
|
||
return "", fmt.Errorf("序列化 goodsAddRequest 失败:%v", err)
|
||
}
|
||
// 5. 调用商品添加接口
|
||
add, err := pddGoodsAdd(clientId, clientSecret, accessToken, string(goodsAddRequestStr))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return add, nil
|
||
}
|
||
|
||
/*
|
||
* 批量数据解密脱敏接口
|
||
* param clientId[string] 客户端ID
|
||
* param clientSecret[string] 客户端密钥
|
||
* param accessToken[string] 访问Token
|
||
* param reqJson[string] 批量数据解密脱敏接口json字符串
|
||
* return 批量数据解密脱敏接口响应结构体,错误信息
|
||
*/
|
||
func pddOpenDecryptMaskBatch(clientId, clientSecret, accessToken string, reqJson string) (string, error) {
|
||
url := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.open.decrypt.mask.batch", // API类型:批量解密脱敏
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
params["data_list"] = reqJson // 添加数据列表
|
||
|
||
sign := generateSign(params, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Get(url).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Timeout(30 * time.Second).
|
||
Send(params).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 生成商家自定义的规格
|
||
func pddGoodsSpecIdGet(clientId, clientSecret, accessToken, parentSpecId, specName string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]string{
|
||
"type": "pdd.goods.spec.id.get", // API类型:批量解密脱敏
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"parent_spec_id": parentSpecId,
|
||
"spec_name": specName,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
sign := generateSign(map[string]interface{}{
|
||
"type": params["type"],
|
||
"data_type": params["data_type"],
|
||
"client_id": params["client_id"],
|
||
"access_token": params["access_token"],
|
||
"parent_spec_id": params["parent_spec_id"],
|
||
"spec_name": params["spec_name"],
|
||
"timestamp": params["timestamp"],
|
||
}, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
formData.Set(key, value)
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()). // 发送编码后的表单数据
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// PddGoodsSkuPriceUpdateRequest 修改价格请求结构体
|
||
type PddGoodsSkuPriceUpdateRequest struct {
|
||
GoodsId int64 `json:"goods_id"`
|
||
IgnoreEditWarn bool `json:"ignore_edit_warn,omitempty"`
|
||
MarketPrice int64 `json:"market_price,omitempty"`
|
||
MarketPriceInYuan string `json:"market_price_in_yuan,omitempty"`
|
||
SkuPriceList []SkuPriceListItem `json:"sku_price_list"`
|
||
SyncGoodsOperate int `json:"sync_goods_operate,omitempty"`
|
||
TwoPiecesDiscount int `json:"two_pieces_discount,omitempty"`
|
||
}
|
||
|
||
// SkuPriceListItem SKU价格列表项
|
||
type SkuPriceListItem struct {
|
||
GroupPrice int64 `json:"group_price"`
|
||
IsOnsale int `json:"is_onsale"`
|
||
SinglePrice int64 `json:"single_price"`
|
||
SkuId int64 `json:"sku_id"`
|
||
}
|
||
|
||
// 修改商品sku价格
|
||
func pddGoodsSkuPriceUpdate(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.goods.sku.price.update",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
req := gorequest.New()
|
||
resp, body, errs := req.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()). // 发送编码后的表单数据
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
fmt.Println("error_response", response)
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d, 详细错误: %v", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode, errorWrapper.ErrorResponse.SubMsg)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// PddGoodsQuantityUpdateRequest 商品库存更新接口请求参数
|
||
type PddGoodsQuantityUpdateRequest struct {
|
||
// 是否强制更新,仅update_type=1(全量更新)时有效
|
||
// 默认值false;force_update=false时,quantity不能小于预扣库存;
|
||
// force_update=true时,代表强制更新,当quantity<预扣库存时,不报错,直接将quantity清0
|
||
ForceUpdate *bool `json:"force_update,omitempty"`
|
||
// 商品id
|
||
GoodsId int64 `json:"goods_id" validate:"required"`
|
||
// sku商家编码
|
||
OuterId *string `json:"outer_id,omitempty"`
|
||
// 库存修改值
|
||
// 当全量更新库存时,quantity必须为大于等于0的正整数;
|
||
// 当增量更新库存时,quantity为整数,可小于等于0。
|
||
// 若增量更新时传入的库存为负数,则负数与实际库存之和不能小于0。
|
||
// 比如当前实际库存为1,传入增量更新quantity=-1,库存改为0
|
||
Quantity int64 `json:"quantity" validate:"required"`
|
||
// sku_id和outer_id必填一个
|
||
SkuId *int64 `json:"sku_id,omitempty"`
|
||
// 库存更新方式,可选。1为全量更新,2为增量更新。
|
||
// 如果不填,默认为全量更新
|
||
UpdateType *int32 `json:"update_type,omitempty"`
|
||
}
|
||
|
||
// 商品库存更新接口
|
||
func pddGoodsQuantityUpdate(clientId, clientSecret, accessToken string, request PddGoodsQuantityUpdateRequest) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
|
||
// 验证必需参数
|
||
if request.GoodsId == 0 {
|
||
return "", fmt.Errorf("goods_id 不能为空")
|
||
}
|
||
|
||
// 验证sku_id和outer_id至少有一个
|
||
if request.SkuId == nil && request.OuterId == nil {
|
||
return "", fmt.Errorf("sku_id 和 outer_id 不能同时为空")
|
||
}
|
||
|
||
// 生成签名参数
|
||
params := map[string]string{
|
||
"type": "pdd.goods.quantity.update", // API类型:批量解密脱敏
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
"goods_id": strconv.FormatInt(request.GoodsId, 10),
|
||
}
|
||
|
||
// 设置可选参数
|
||
if request.UpdateType != nil {
|
||
params["update_type"] = strconv.FormatInt(int64(*request.UpdateType), 10)
|
||
}
|
||
|
||
if request.SkuId != nil {
|
||
params["sku_id"] = strconv.FormatInt(*request.SkuId, 10)
|
||
}
|
||
|
||
if request.OuterId != nil {
|
||
params["outer_id"] = *request.OuterId
|
||
}
|
||
|
||
params["quantity"] = strconv.FormatInt(request.Quantity, 10)
|
||
|
||
if request.ForceUpdate != nil {
|
||
params["force_update"] = strconv.FormatBool(*request.ForceUpdate)
|
||
}
|
||
|
||
// 复制参数用于签名(保持顺序)
|
||
signParams := make(map[string]interface{})
|
||
for k, v := range params {
|
||
signParams[k] = v
|
||
}
|
||
|
||
sign := generateSign(signParams, clientSecret)
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
formData.Set(key, value)
|
||
}
|
||
|
||
req := gorequest.New()
|
||
resp, body, errs := req.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()). // 发送编码后的表单数据
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 商品图片上传接口
|
||
func pddGoodsImageUpload(clientId, clientSecret, accessToken string, fileBase string) (string, error) {
|
||
pddUrl := "http://gw-api.pinduoduo.com/api/router"
|
||
// 准备参数
|
||
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
|
||
params := map[string]string{
|
||
"type": "pdd.goods.image.upload",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
"image": fileBase,
|
||
}
|
||
|
||
sign := map[string]interface{}{
|
||
"type": "pdd.goods.image.upload",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
"image": fileBase,
|
||
}
|
||
|
||
// 生成签名
|
||
params["sign"] = generateSign(sign, clientSecret)
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
formData.Set(key, value)
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()). // 发送编码后的表单数据
|
||
End()
|
||
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 订单基础信息列表查询接口(根据成交时间)
|
||
func pddOrderBasicListGet(clientId, clientSecret, accessToken string, orderBasicListGetJSONStr string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.order.basic.list.get", // API类型:商品新增接口
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if orderBasicListGetJSONStr == "" {
|
||
return "", fmt.Errorf("goodsAddJson 参数为空!")
|
||
}
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(orderBasicListGetJSONStr, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 获取商品提交的商品详情
|
||
func pddGoodsCommitDetailGet(clientId, clientSecret, accessToken string, goodsCommitId, goodsId string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.goods.commit.detail.get", // API类型:商品新增接口
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
"goods_commit_id": goodsCommitId,
|
||
"goods_id": goodsId,
|
||
}
|
||
|
||
sign := generateSign(params, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 获取拼多多系统时间
|
||
func pddTimeGet(clientId, clientSecret, accessToken string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.time.get", // API类型:商品新增接口
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
sign := generateSign(params, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 查询面单服务订购及面单使用情况
|
||
func pddWaybillSearch(clientId, clientSecret, accessToken, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.waybill.search", // API类型:商品新增接口
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 电子面单取号
|
||
func pddFdsWaybillGet(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.fds.waybill.get", // API类型:商品新增接口
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
marshal, _ := json.Marshal(params)
|
||
fmt.Println("params:", string(marshal))
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %d", errorWrapper.ErrorResponse.ErrorMsg, errorWrapper.ErrorResponse.ErrorCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 商家取消获取的电子面单号
|
||
func pddWaybillCancel(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.waybill.cancel", // API类型:商品新增接口
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 商品列表接口
|
||
func pddGoodsListGet(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.goods.list.get",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 电子面单云打印接口
|
||
func pddWaybillGet(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.waybill.get",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
"param_waybill_cloud_print_apply_new_request": requestJson,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
//// 将JSON参数合并到params中
|
||
//toParams, err := addStructToParams(requestJson, params)
|
||
//if err != nil {
|
||
// return "", err
|
||
//}
|
||
|
||
sign := generateSign(params, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
marshal, _ := json.Marshal(params)
|
||
fmt.Println("参数:", string(marshal))
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 通过面单号查询面单信息
|
||
func pddWaybillQueryByWaybillcode(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.waybill.query.by.waybillcode",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
"param_list": requestJson,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
sign := generateSign(params, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 云打印
|
||
func pddCloudPrint(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.cloud.print",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 云打印任务查询
|
||
func pddCloudPrintTaskQuery(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.cloud.print.task.query",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 云打印验证码
|
||
func pddCloudPrintVerifyCode(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.cloud.print.verify.code",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 云打印机绑定
|
||
func pddCloudPrinterBind(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.cloud.printer.bind",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 云打印机设置
|
||
func pddCloudPrinterSetting(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.cloud.printer.setting",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 云打印机状态查询
|
||
func pddCloudPrinterStatusQuery(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.cloud.printer.status.query",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 商品上架状态设置
|
||
func pddGoodsSaleStatusSet(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.goods.sale.status.set",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 删除商品接口
|
||
func pddDeleteGoodsCommit(clientId, clientSecret, accessToken string, requestJson string) (string, error) {
|
||
pddUrl := fmt.Sprint("http://gw-api.pinduoduo.com/api/router")
|
||
|
||
// 当前时间戳
|
||
timestamp := fmt.Sprintf("%d", time.Now().Unix())
|
||
// 生成签名参数
|
||
params := map[string]interface{}{
|
||
"type": "pdd.delete.goods.commit",
|
||
"data_type": "JSON",
|
||
"client_id": clientId,
|
||
"access_token": accessToken,
|
||
"timestamp": timestamp,
|
||
}
|
||
|
||
if requestJson == "" {
|
||
return "", fmt.Errorf("requestJson 参数为空!")
|
||
}
|
||
|
||
// 将JSON参数合并到params中
|
||
toParams, err := addStructToParams(requestJson, params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sign := generateSign(toParams, clientSecret)
|
||
|
||
if sign == "" {
|
||
return "", fmt.Errorf("生成 sign 签名错误!")
|
||
}
|
||
params["sign"] = sign
|
||
|
||
// 将参数编码为 application/x-www-form-urlencoded 格式
|
||
formData := url.Values{}
|
||
for key, value := range params {
|
||
// 将interface{}类型的值转换为字符串
|
||
switch v := value.(type) {
|
||
case string:
|
||
formData.Set(key, v)
|
||
case int, int64, float64:
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
case bool:
|
||
formData.Set(key, fmt.Sprintf("%t", v))
|
||
default:
|
||
// 如果是复杂类型,尝试转换为JSON字符串
|
||
if jsonStr, err := json.Marshal(v); err == nil {
|
||
formData.Set(key, string(jsonStr))
|
||
} else {
|
||
formData.Set(key, fmt.Sprintf("%v", v))
|
||
}
|
||
}
|
||
}
|
||
|
||
request := gorequest.New()
|
||
resp, body, errs := request.Post(pddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8").
|
||
Timeout(30 * time.Second).
|
||
Send(formData.Encode()).
|
||
End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("HTTP状态码异常: %d, 响应: %s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 解析响应
|
||
var response map[string]interface{}
|
||
if err := json.Unmarshal([]byte(body), &response); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
|
||
// 异常处理
|
||
if response["error_response"] != nil {
|
||
var errorWrapper ErrorWrapper
|
||
// 解析响应
|
||
if err := json.Unmarshal([]byte(body), &errorWrapper); err != nil {
|
||
return "", fmt.Errorf("解析 errorWrapper 失败: %v, 响应内容: %s", err, body)
|
||
}
|
||
return "", fmt.Errorf("请求失败: %v, 错误码: %v", errorWrapper.ErrorResponse.SubMsg, errorWrapper.ErrorResponse.SubCode)
|
||
}
|
||
|
||
// 转换成json字符串
|
||
responseJSON, err := json.Marshal(response)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(responseJSON), nil
|
||
}
|
||
|
||
// 获取商品信息
|
||
func outPddAuthGetCommitDetailt(goodsCommitId, goodsId, accessToken string) {
|
||
url := "http://127.0.0.1:4523/m1/6145055-5836942-default/api/pdd/auth/getCommitDetail"
|
||
|
||
// 构建查询参数
|
||
params := map[string]string{
|
||
"goodsCommitId": goodsCommitId,
|
||
"goodsId": goodsId,
|
||
"accessToken": accessToken,
|
||
}
|
||
|
||
// 创建请求对象
|
||
request := gorequest.New()
|
||
|
||
// 发送GET请求
|
||
resp, body, errs := request.Get(url).
|
||
Query(params). // 添加查询参数
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
End() // 发送请求
|
||
|
||
// 检查错误
|
||
if len(errs) > 0 {
|
||
for _, err := range errs {
|
||
fmt.Println("请求错误:", err)
|
||
}
|
||
return
|
||
}
|
||
|
||
// 检查响应状态码
|
||
if resp != nil && resp.StatusCode != http.StatusOK {
|
||
fmt.Printf("HTTP错误: %s\n", resp.Status)
|
||
return
|
||
}
|
||
|
||
// 输出响应体
|
||
fmt.Println(body)
|
||
}
|
||
|
||
/*
|
||
获取商品详情信息
|
||
参数:goodsId:商品ID accessToken:店铺token
|
||
*/
|
||
func outPddAuthGetGoodsDetail(goodsId, accessToken string) (string, error) {
|
||
// 请求路径
|
||
outPddUrl := "http://pdd.buzhiyushu.cn/api/pdd/auth/getGoodsDetail"
|
||
|
||
// 创建 multipart 表单数据
|
||
body := &bytes.Buffer{}
|
||
writer := multipart.NewWriter(body)
|
||
|
||
// 添加表单字段
|
||
_ = writer.WriteField("goodsId", goodsId)
|
||
_ = writer.WriteField("accessToken", accessToken)
|
||
|
||
contentType := writer.FormDataContentType()
|
||
writer.Close()
|
||
|
||
// 发送 GET 请求(实际上是带有表单数据的 GET 请求)
|
||
resp, bodyBytes, errs := gorequest.New().
|
||
Get(outPddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Connection", "keep-alive").
|
||
Set("Content-Type", contentType).
|
||
Send(body.String()).
|
||
End()
|
||
|
||
// 检查错误
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
// 检查响应状态码
|
||
if resp != nil && resp.StatusCode != http.StatusOK {
|
||
return "", fmt.Errorf("HTTP状态码异常:%d,响应内容:%s", resp.StatusCode, bodyBytes)
|
||
}
|
||
|
||
return bodyBytes, nil
|
||
}
|
||
|
||
/*
|
||
生成自定义规格
|
||
参数:specTypeId:规格类型ID specName:规格名称 accessToken:店铺token
|
||
*/
|
||
func outPddAuthSetSpec(specTypeId int, specName, accessToken string) (string, error) {
|
||
outPddUrl := fmt.Sprintf("http://pdd.buzhiyushu.cn/api/pdd/auth/setSpec?specTypeId=%d&specName=%s&accessToken=%s", specTypeId, specName, accessToken)
|
||
|
||
// 创建请求对象
|
||
request := gorequest.New()
|
||
|
||
// 发送GET请求
|
||
resp, body, errs := request.Get(outPddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/json").
|
||
End() // 发送请求
|
||
// 检查错误
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
// 检查响应状态码
|
||
if resp != nil && resp.StatusCode != http.StatusOK {
|
||
return "", fmt.Errorf("HTTP状态码异常:%d,响应内容:%s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 输出响应体
|
||
return body, nil
|
||
}
|
||
|
||
// 获取商品信息
|
||
func outPddAuthGetCats() (string, error) {
|
||
outPddUrl := "http://pdd.buzhiyushu.cn/api/pdd/auth/getCats"
|
||
// 创建请求对象
|
||
request := gorequest.New()
|
||
|
||
// 发送GET请求
|
||
resp, body, errs := request.Get(outPddUrl).
|
||
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
|
||
Set("Accept", "application/json, text/plain, */*").
|
||
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
|
||
Set("Content-Type", "application/json").
|
||
End() // 发送请求
|
||
// 检查错误
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
// 检查响应状态码
|
||
if resp != nil && resp.StatusCode != http.StatusOK {
|
||
return "", fmt.Errorf("HTTP状态码异常:%d,响应内容:%s", resp.StatusCode, body)
|
||
}
|
||
|
||
// 输出响应体
|
||
return body, nil
|
||
}
|
||
|
||
// 修改价格
|
||
func outPddAuthUpdatePrice(jsonData string) (string, error) {
|
||
// 请求url
|
||
outPddUrl := "http://pdd.buzhiyushu.cn/api/pdd/auth/updatePrice"
|
||
|
||
// 创建gorequest代理
|
||
request := gorequest.New()
|
||
|
||
// 发送POST请求,使用form-data格式
|
||
// 注意:gorequest的Send方法会根据传入的类型自动处理
|
||
resp, body, errs := request.Post(outPddUrl).
|
||
Type("multipart").
|
||
Send("jsonData=" + jsonData).
|
||
End()
|
||
|
||
// 处理错误
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
// 检查响应状态码
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("请求返回非200状态码: %d", resp.StatusCode)
|
||
}
|
||
return body, nil
|
||
}
|
||
|
||
// 修改库存
|
||
func outPddAuthUpdateStock(jsonData string) (string, error) {
|
||
// 请求url
|
||
outPddUrl := "http://pdd.buzhiyushu.cn/api/pdd/auth/updateStock"
|
||
|
||
// 创建gorequest代理
|
||
request := gorequest.New()
|
||
|
||
// 发送POST请求,使用form-data格式
|
||
// 注意:gorequest的Send方法会根据传入的类型自动处理
|
||
resp, body, errs := request.Post(outPddUrl).
|
||
Type("multipart").
|
||
Send("jsonData=" + jsonData).
|
||
End()
|
||
|
||
// 处理错误
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("请求失败: %v", errs)
|
||
}
|
||
|
||
// 检查响应状态码
|
||
if resp.StatusCode != 200 {
|
||
return "", fmt.Errorf("请求返回非200状态码: %d", resp.StatusCode)
|
||
}
|
||
return body, nil
|
||
}
|
||
|
||
// =========================== 辅助函数 ============================
|
||
// 将结构体的字段添加到 params 映射中
|
||
func addStructToParams(req string, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 将JSON字符串解析为map
|
||
var tempMap map[string]interface{}
|
||
if err := json.Unmarshal([]byte(req), &tempMap); err != nil {
|
||
return nil, fmt.Errorf("解析 req json失败:%v ", err)
|
||
}
|
||
|
||
//// 合并到params
|
||
//for k, v := range tempMap {
|
||
// vStr, _ := json.Marshal(v)
|
||
// // 只添加非nil的值
|
||
// if v != nil {
|
||
// params[k] = string(vStr)
|
||
// }
|
||
//}
|
||
//合并到params
|
||
for k, v := range tempMap {
|
||
if v != nil {
|
||
// 类型断言,直接处理各种类型
|
||
switch val := v.(type) {
|
||
case string:
|
||
params[k] = val
|
||
case bool:
|
||
params[k] = val
|
||
case nil:
|
||
// 跳过nil
|
||
case []interface{}: // 数组
|
||
vBytes, _ := json.Marshal(val)
|
||
params[k] = string(vBytes)
|
||
case map[string]interface{}: // 对象
|
||
vBytes, _ := json.Marshal(val)
|
||
params[k] = string(vBytes)
|
||
default:
|
||
// 其他类型转换为字符串
|
||
vBytes, _ := json.Marshal(val)
|
||
strValue := string(vBytes)
|
||
// 检查并去掉字符串类型的引号
|
||
if len(strValue) >= 2 && strValue[0] == '"' && strValue[len(strValue)-1] == '"' {
|
||
params[k] = strValue[1 : len(strValue)-1]
|
||
} else {
|
||
params[k] = strValue
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return params, nil
|
||
}
|
||
|
||
// ========================== C 导入函数 ===================
|
||
|
||
// PddGoodsOuterCatMappingGet 类目预测
|
||
//
|
||
//export PddGoodsOuterCatMappingGet
|
||
func PddGoodsOuterCatMappingGet(clientId, clientSecret, accessToken,
|
||
outerCatId, outerCatName, outerGoodsName *C.char) *C.char {
|
||
// 将C字符串转换为Go字符串
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
goAccessToken := C.GoString(accessToken)
|
||
goOuterCatId := C.GoString(outerCatId)
|
||
goOuterCatName := C.GoString(outerCatName)
|
||
goOuterGoodsName := C.GoString(outerGoodsName)
|
||
// 调用Go函数
|
||
info, err := pddGoodsOuterCatMappingGet(goClientId, goClientSecret, goAccessToken, goOuterCatId, goOuterCatName, goOuterGoodsName)
|
||
if err != nil {
|
||
return C.CString(err.Error()) // 返回错误信息
|
||
}
|
||
return C.CString(info) // 返回成功信息
|
||
}
|
||
|
||
// PddLogisticsCompaniesGet 快递公司查看
|
||
//
|
||
//export PddLogisticsCompaniesGet
|
||
func PddLogisticsCompaniesGet(clientId, clientSecret *C.char) *C.char {
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
info, err := pddLogisticsCompaniesGet(goClientId, goClientSecret)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddErpOrderSync erp打单信息同步
|
||
//
|
||
//export PddErpOrderSync
|
||
func PddErpOrderSync(clientId, clientSecret, accessToken, logisticsId,
|
||
orderSn, orderState, waybillNo *C.char) *C.char {
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
goAccessToken := C.GoString(accessToken)
|
||
goLogisticsId := C.GoString(logisticsId)
|
||
goOrderSn := C.GoString(orderSn)
|
||
goOrderState := C.GoString(orderState)
|
||
goWaybillNo := C.GoString(waybillNo)
|
||
info, err := pddErpOrderSync(goClientId, goClientSecret, goAccessToken, goLogisticsId, goOrderSn, goOrderState, goWaybillNo)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddOrderSynchronization 拼多多订单同步
|
||
//
|
||
//export PddOrderSynchronization
|
||
func PddOrderSynchronization(clientId, clientSecret, accessToken, logisticsCompany, logisticsOnlineSendJson *C.char) *C.char {
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
goAccessToken := C.GoString(accessToken)
|
||
goLogisticsCompany := C.GoString(logisticsCompany)
|
||
goLogisticsOnlineSendJson := C.GoString(logisticsOnlineSendJson)
|
||
info, err := pddOrderSynchronization(goClientId, goClientSecret, goAccessToken, goLogisticsCompany, goLogisticsOnlineSendJson)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsImgUpload 商品图片上传接口
|
||
//
|
||
//export PddGoodsImgUpload
|
||
func PddGoodsImgUpload(clientId, clientSecret, accessToken, filePath *C.char) *C.char {
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
goAccessToken := C.GoString(accessToken)
|
||
goFilePath := C.GoString(filePath)
|
||
info, err := pddGoodsImgUpload(goClientId, goClientSecret, goAccessToken, goFilePath)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsAdd 商品新增接口
|
||
//
|
||
//export PddGoodsAdd
|
||
func PddGoodsAdd(clientId, clientSecret, accessToken, goodsAddJson *C.char) *C.char {
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
goAccessToken := C.GoString(accessToken)
|
||
goGoodsAddJson := C.GoString(goodsAddJson)
|
||
info, err := pddGoodsAdd(goClientId, goClientSecret, goAccessToken, goGoodsAddJson)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// SelfPddGoodsAdd 联合拼多多图片上传的商品新增
|
||
//
|
||
//export SelfPddGoodsAdd
|
||
func SelfPddGoodsAdd(clientId, clientSecret, accessToken, filePath, goodsAddJson *C.char) *C.char {
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
goAccessToken := C.GoString(accessToken)
|
||
goFilePath := C.GoString(filePath)
|
||
goGoodsAddJson := C.GoString(goodsAddJson)
|
||
info, err := selfPddGoodsAdd(goClientId, goClientSecret, goAccessToken, goFilePath, goGoodsAddJson)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddOpenDecryptMaskBatch 批量数据解密脱敏接口
|
||
//
|
||
//export PddOpenDecryptMaskBatch
|
||
func PddOpenDecryptMaskBatch(clientId, clientSecret, accessToken, reqJson *C.char) *C.char {
|
||
goClientId := C.GoString(clientId)
|
||
goClientSecret := C.GoString(clientSecret)
|
||
goAccessToken := C.GoString(accessToken)
|
||
goReqJson := C.GoString(reqJson)
|
||
info, err := pddOpenDecryptMaskBatch(goClientId, goClientSecret, goAccessToken, goReqJson)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsSpecIdGet 生成商家自定义的规格
|
||
//
|
||
//export PddGoodsSpecIdGet
|
||
func PddGoodsSpecIdGet(clientId, clientSecret, accessToken, parentSpecId, specName *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
parentSpecIdStr := C.GoString(parentSpecId)
|
||
specNameStr := C.GoString(specName)
|
||
info, err := pddGoodsSpecIdGet(clientIdStr, clientSecretStr, accessTokenStr, parentSpecIdStr, specNameStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsSkuPriceUpdate 修改商品sku价格
|
||
//
|
||
//export PddGoodsSkuPriceUpdate
|
||
func PddGoodsSkuPriceUpdate(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddGoodsSkuPriceUpdate(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsQuantityUpdate 商品库存更新接口
|
||
//
|
||
//export PddGoodsQuantityUpdate
|
||
func PddGoodsQuantityUpdate(clientId, clientSecret, accessToken, request *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestStr := C.GoString(request)
|
||
var pddGoodsQuantityUpdateRequest PddGoodsQuantityUpdateRequest
|
||
if err := json.Unmarshal([]byte(requestStr), &pddGoodsQuantityUpdateRequest); err != nil {
|
||
return C.CString(fmt.Sprintf("解析JSON失败: %s", err))
|
||
}
|
||
info, err := pddGoodsQuantityUpdate(clientIdStr, clientSecretStr, accessTokenStr, pddGoodsQuantityUpdateRequest)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsImageUpload 商品图片上传接口
|
||
//
|
||
//export PddGoodsImageUpload
|
||
func PddGoodsImageUpload(clientId, clientSecret, accessToken, fileBase *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
fileBaseStr := C.GoString(fileBase)
|
||
info, err := pddGoodsImageUpload(clientIdStr, clientSecretStr, accessTokenStr, fileBaseStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddOrderBasicListGet 订单基础信息列表查询接口(根据成交时间)
|
||
//
|
||
//export PddOrderBasicListGet
|
||
func PddOrderBasicListGet(clientId, clientSecret, accessToken, orderBasicListGetJSON *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
orderBasicListGetJSONStr := C.GoString(orderBasicListGetJSON)
|
||
info, err := pddOrderBasicListGet(clientIdStr, clientSecretStr, accessTokenStr, orderBasicListGetJSONStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsCommitDetailGet 获取商品提交的商品详情
|
||
//
|
||
//export PddGoodsCommitDetailGet
|
||
func PddGoodsCommitDetailGet(clientId, clientSecret, accessToken, goodsCommitId, goodsId *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
goodsCommitIdStr := C.GoString(goodsCommitId)
|
||
goodsIdStr := C.GoString(goodsId)
|
||
info, err := pddGoodsCommitDetailGet(clientIdStr, clientSecretStr, accessTokenStr, goodsCommitIdStr, goodsIdStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddTimeGet 获取拼多多系统时间
|
||
//
|
||
//export PddTimeGet
|
||
func PddTimeGet(clientId, clientSecret, accessToken *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
info, err := pddTimeGet(clientIdStr, clientSecretStr, accessTokenStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddWaybillSearch 查询面单服务订购及面单使用情况
|
||
//
|
||
//export PddWaybillSearch
|
||
func PddWaybillSearch(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddWaybillSearch(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddFdsWaybillGet 电子面单取号
|
||
//
|
||
//export PddFdsWaybillGet
|
||
func PddFdsWaybillGet(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddFdsWaybillGet(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// ResponseAPI 统一响应数据结构
|
||
type ResponseAPI struct {
|
||
Success bool `json:"success"`
|
||
Message string `json:"message"`
|
||
Data interface{} `json:"data"`
|
||
}
|
||
|
||
// 生成JSON响应字符串
|
||
func jsonResponse(data interface{}, err error) string {
|
||
resp := ResponseAPI{
|
||
Success: err == nil,
|
||
Message: getErrorMsg(err),
|
||
Data: data,
|
||
}
|
||
bytes, _ := json.Marshal(resp)
|
||
return string(bytes)
|
||
}
|
||
|
||
// 获取错误信息
|
||
func getErrorMsg(err error) string {
|
||
if err != nil {
|
||
return err.Error()
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// PddWaybillCancel 商家取消获取的电子面单号
|
||
//
|
||
//export PddWaybillCancel
|
||
func PddWaybillCancel(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddWaybillCancel(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
return C.CString(jsonResponse(info, err))
|
||
}
|
||
|
||
// PddGoodsListGet 商品列表接口
|
||
//
|
||
//export PddGoodsListGet
|
||
func PddGoodsListGet(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddGoodsListGet(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddWaybillGet 电子面单云打印接口
|
||
//
|
||
//export PddWaybillGet
|
||
func PddWaybillGet(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddWaybillGet(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddWaybillQueryByWaybillcode 通过面单号查询面单信息
|
||
//
|
||
//export PddWaybillQueryByWaybillcode
|
||
func PddWaybillQueryByWaybillcode(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddWaybillQueryByWaybillcode(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddCloudPrint 云打印
|
||
//
|
||
//export PddCloudPrint
|
||
func PddCloudPrint(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddCloudPrint(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddCloudPrintTaskQuery 云打印任务查询
|
||
//
|
||
//export PddCloudPrintTaskQuery
|
||
func PddCloudPrintTaskQuery(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddCloudPrintTaskQuery(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddCloudPrintVerifyCode 云打印验证码
|
||
//
|
||
//export PddCloudPrintVerifyCode
|
||
func PddCloudPrintVerifyCode(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddCloudPrintVerifyCode(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddCloudPrinterBind 云打印机绑定
|
||
//
|
||
//export PddCloudPrinterBind
|
||
func PddCloudPrinterBind(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddCloudPrinterBind(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddCloudPrinterSetting 云打印机设置
|
||
//
|
||
//export PddCloudPrinterSetting
|
||
func PddCloudPrinterSetting(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddCloudPrinterSetting(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddCloudPrinterStatusQuery 云打印机状态查询
|
||
//
|
||
//export PddCloudPrinterStatusQuery
|
||
func PddCloudPrinterStatusQuery(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddCloudPrinterStatusQuery(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddGoodsSaleStatusSet 商品上架状态设置
|
||
//
|
||
//export PddGoodsSaleStatusSet
|
||
func PddGoodsSaleStatusSet(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddGoodsSaleStatusSet(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// PddDeleteGoodsCommit 删除商品接口
|
||
//
|
||
//export PddDeleteGoodsCommit
|
||
func PddDeleteGoodsCommit(clientId, clientSecret, accessToken, requestJson *C.char) *C.char {
|
||
clientIdStr := C.GoString(clientId)
|
||
clientSecretStr := C.GoString(clientSecret)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
requestJsonStr := C.GoString(requestJson)
|
||
info, err := pddDeleteGoodsCommit(clientIdStr, clientSecretStr, accessTokenStr, requestJsonStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// OutPddAuthGetCommitDetailt 获取商品信息
|
||
//
|
||
//export OutPddAuthGetCommitDetailt
|
||
func OutPddAuthGetCommitDetailt(goodsCommitId, goodsId, accessToken *C.char) *C.char {
|
||
goodsCommitIdStr := C.GoString(goodsCommitId)
|
||
goodsIdStr := C.GoString(goodsId)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
outPddAuthGetCommitDetailt(goodsCommitIdStr, goodsIdStr, accessTokenStr)
|
||
return C.CString("")
|
||
}
|
||
|
||
// OutPddAuthGetGoodsDetail 获取商品信息
|
||
//
|
||
//export OutPddAuthGetGoodsDetail
|
||
func OutPddAuthGetGoodsDetail(goodsId, accessToken *C.char) *C.char {
|
||
goodsIdStr := C.GoString(goodsId)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
info, err := outPddAuthGetGoodsDetail(goodsIdStr, accessTokenStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// OutPddAuthSetSpec 生成自定义规格
|
||
//
|
||
//export OutPddAuthSetSpec
|
||
func OutPddAuthSetSpec(specTypeId C.int, specName, accessToken *C.char) *C.char {
|
||
specTypeIdInt := int(specTypeId)
|
||
specNameStr := C.GoString(specName)
|
||
accessTokenStr := C.GoString(accessToken)
|
||
info, err := outPddAuthSetSpec(specTypeIdInt, specNameStr, accessTokenStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// OutPddAuthGetCats 获取商品信息
|
||
//
|
||
//export OutPddAuthGetCats
|
||
func OutPddAuthGetCats() *C.char {
|
||
info, err := outPddAuthGetCats()
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// OutPddAuthUpdatePrice 修改价格
|
||
//
|
||
//export OutPddAuthUpdatePrice
|
||
func OutPddAuthUpdatePrice(jsonData *C.char) *C.char {
|
||
jsonDataStr := C.GoString(jsonData)
|
||
info, err := outPddAuthUpdatePrice(jsonDataStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// OutPddAuthUpdateStock 修改库存
|
||
//
|
||
//export OutPddAuthUpdateStock
|
||
func OutPddAuthUpdateStock(jsonData *C.char) *C.char {
|
||
jsonDataStr := C.GoString(jsonData)
|
||
info, err := outPddAuthUpdateStock(jsonDataStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// FreeCString 释放C字符串内存
|
||
//
|
||
//export FreeCString
|
||
func FreeCString(str *C.char) {
|
||
C.free(unsafe.Pointer(str))
|
||
}
|
||
|
||
// main函数
|
||
func main() {
|
||
|
||
}
|