diff --git a/platformapi/tiktok/tiktok_const.go b/platformapi/tiktok/tiktok_const.go index 0970fd10..ebc0ef26 100644 --- a/platformapi/tiktok/tiktok_const.go +++ b/platformapi/tiktok/tiktok_const.go @@ -19,7 +19,6 @@ type API struct { client *http.Client config *platformapi.APIConfig locker sync.RWMutex - - msgToken string - msgKey string + msgToken string // accessToken + expiresIn int64 // 过期时间 } diff --git a/platformapi/tiktok/tiktok_pay.go b/platformapi/tiktok/tiktok_pay.go new file mode 100644 index 00000000..14be4a7c --- /dev/null +++ b/platformapi/tiktok/tiktok_pay.go @@ -0,0 +1,89 @@ +package tiktok + +import ( + "crypto/md5" + "errors" + "fmt" + "git.rosy.net.cn/baseapi/utils" + "sort" + "strings" + "time" +) + +const salt = "@#$!18981810340" + +// 获取支付签名 +func (a *API) Sign(paramsMap map[string]interface{}) string { + var paramsArr []string + for k, v := range paramsMap { + if k == "other_settle_params" { + continue + } + value := strings.TrimSpace(fmt.Sprintf("%v", v)) + if strings.HasPrefix(value, "\"") && strings.HasSuffix(value, "\"") && len(value) > 1 { + value = value[1 : len(value)-1] + } + value = strings.TrimSpace(value) + if value == "" || value == "nil" { + continue + } + switch k { + case "app_id", "thirdparty_id", "sign": + default: + paramsArr = append(paramsArr, value) + } + } + + paramsArr = append(paramsArr, salt) + sort.Strings(paramsArr) + return fmt.Sprintf("%x", md5.Sum([]byte(strings.Join(paramsArr, "&")))) +} + +// 抖音预发单 +func (a *API) CreateOrderByTicktock(param *TickTokCreateOrder) (string, string, error) { + param.Sign = a.Sign(utils.Struct2FlatMap(param)) + data, err := a.AccessAPI2(PayUrl, utils.Struct2FlatMap(param)) + if err != nil { + return "", "", err + } + + result := &PreOrderResult{} + if err := utils.Map2StructByJson(data, result, false); err != nil { + return "", "", err + } + if result.ErrNo != 0 { + return "", "", errors.New(result.ErrTips) + } + return result.Data.OrderId, result.Data.OrderToken, nil +} + +// 获取抖音token +func (a *API) GetTiktokToken() error { + tokenReq := make(map[string]interface{}, 3) + tokenReq["appid"] = a.GetAppID() + tokenReq["secret"] = a.GetSecret() + tokenReq["grant_type"] = "client_credential" + result, err := a.AccessAPI2("https://developer.toutiao.com/api/apps/v2/token", tokenReq) + if err != nil { + return err + } + + accessToken := &AccessToken{} + if err := utils.Map2StructByJson(result, accessToken, false); err != nil { + return err + } + if accessToken.ErrNo != 0 { + return errors.New(accessToken.ErrTips) + } + a.msgToken = accessToken.AccessToken + a.expiresIn = accessToken.ExpiresIn + return nil +} + +// 检查token是否过期 +func (a *API) CheckTokenIsExist() error { + if a.msgToken == "" || time.Now().Unix() > a.expiresIn { + return a.GetTiktokToken() + } + return nil +} diff --git a/platformapi/tiktok/tiktok_pay_model.go b/platformapi/tiktok/tiktok_pay_model.go new file mode 100644 index 00000000..98e6c5d5 --- /dev/null +++ b/platformapi/tiktok/tiktok_pay_model.go @@ -0,0 +1,47 @@ +package tiktok + +const ( + PayUrl = "https://developer.toutiao.com/api/apps/ecpay/v1/create_order" +) + +// 预下单 +type TickTokCreateOrder struct { + AppID string `json:"app_id"` // 小程序APPID + OutOrderNo string `json:"out_order_no"` // 开发者侧的订单号 + TotalAmount int `json:"total_amount"` // 支付价格。 + Subject string `json:"subject"` // 商品描述。 + Body string `json:"body"` // 商品详情 + ValidTime int `json:"valid_time"` // 订单过期时间(秒)。 + Sign string `json:"sign"` // 签名,详见请求加签算法 + CpExtra string `json:"cp_extra"` // 开发者自定义字段,回调原样回传 + NotifyURL string `json:"notify_url"` // 商户自定义回调地址 +} + +// 预发单返回值 +type PreOrderResult struct { + ErrNo int64 `json:"err_no"` // 错误码 + ErrTips string `json:"err_tips"` // 错误信息 + Data *struct { + OrderId string `json:"order_id"` // 抖音侧唯一订单号 + OrderToken string `json:"order_token"` //签名后的订单信息 + } +} + +type AccessToken struct { + AccessToken string `json:"access_token"` //token + ExpiresIn int64 `json:"expires_in"` // 过期时间 + ErrNo int64 `json:"err_no"` // 错误码 + ErrTips string `json:"err_tips"` // 错误信息 +} + +// 退款 +type ReturnMoneyReq struct { + AppID string `json:"app_id"` // 小程序APPID + OutOrderNo string `json:"out_order_no"` //商户分配支付单号,标识进行退款的订单 + OutRefundNo string `json:"out_refund_no"` // 商户分配退款号,保证在商户中唯一 + Reason string `json:"reason"` // 退款原因 + RefundAmount int `json:"refund_amount"` + Sign string `json:"sign"` + CpExtra string `json:"cp_extra"` + NotifyURL string `json:"notify_url"` +} diff --git a/platformapi/tiktok/tiktok_test.go b/platformapi/tiktok/tiktok_test.go index 18703bcd..705454fa 100644 --- a/platformapi/tiktok/tiktok_test.go +++ b/platformapi/tiktok/tiktok_test.go @@ -19,15 +19,15 @@ func init() { } func TestCode(t *testing.T) { - a := New("1e0d98ad7b2e9b1ba5d7529a7e17fa9b9d65380a ", "tta6a1d01c399f264201") - data, err := a.GetTiktokToken("7aK7VOuXnlU2OIiFDFi_ssRX9vQdXtDekgW-yV77Q20rVsw8-8DX4ASbXMTA3Z-gr8tstJcgMgL04OFc-BgXB92DC6otQV6GQUiy-TzhpH109xZfZwhCKjt-OiI") - fmt.Println(err) - fmt.Println(data) + //a := New("1e0d98ad7b2e9b1ba5d7529a7e17fa9b9d65380a ", "tta6a1d01c399f264201") + ////data, err := a.GetTiktokToken("7aK7VOuXnlU2OIiFDFi_ssRX9vQdXtDekgW-yV77Q20rVsw8-8DX4ASbXMTA3Z-gr8tstJcgMgL04OFc-BgXB92DC6otQV6GQUiy-TzhpH109xZfZwhCKjt-OiI") + //fmt.Println(err) + //fmt.Println(data) } func TestCode2(t *testing.T) { a := New("1e0d98ad7b2e9b1ba5d7529a7e17fa9b9d65380a ", "tta6a1d01c399f264201") - data, err := a.GetTiktokToken2("CCRHRLfkl8kSHXuuZTDWQayoqHVXF2Vl4qrt173jxfWhg6Q1pZCbjRO0TzTGNPZd5vTW8UcjRupxfmEIdM06WSmAjwhvr-Ak_Pg9gJfHfrq2KvLH5eYL4C68BXM") + data, err := a.GetTiktokOauth("CCRHRLfkl8kSHXuuZTDWQayoqHVXF2Vl4qrt173jxfWhg6Q1pZCbjRO0TzTGNPZd5vTW8UcjRupxfmEIdM06WSmAjwhvr-Ak_Pg9gJfHfrq2KvLH5eYL4C68BXM") fmt.Println(err) fmt.Println(data) } diff --git a/platformapi/tiktok/tiktok_token.go b/platformapi/tiktok/tiktok_token.go index cb2d9aed..f2395f0b 100644 --- a/platformapi/tiktok/tiktok_token.go +++ b/platformapi/tiktok/tiktok_token.go @@ -1,7 +1,6 @@ package tiktok import ( - "errors" "git.rosy.net.cn/baseapi/utils" ) @@ -42,31 +41,8 @@ type TiktokOauthResone struct { } } -// 获取抖音token -func (a *API) GetTiktokToken(code string) (*OauthAccessTokenRes, error) { - tokenReq := make(map[string]interface{}, 4) - tokenReq["client_secret"] = a.clientSecret - tokenReq["code"] = code - tokenReq["grant_type"] = "authorization_code" - tokenReq["client_key"] = a.clientKey - - result, err := a.AccessAPI2(BaseURL, tokenReq) - if err != nil { - return nil, err - } - - oauthAccessToken := &OauthAccessTokenRes{} - if err := utils.Map2StructByJson(result, oauthAccessToken, false); err != nil { - return nil, err - } - if oauthAccessToken.Data.ErrorCode != 0 { - return nil, errors.New(oauthAccessToken.Data.Description) - } - return oauthAccessToken, nil -} - // 获取抖音登录授权2 -func (a *API) GetTiktokToken2(code string) (*TiktokOauthResone, error) { +func (a *API) GetTiktokOauth(code string) (*TiktokOauthResone, error) { tokenReq := make(map[string]interface{}, 3) tokenReq["appid"] = a.GetAppID() tokenReq["code"] = code