From 6cd1b37981a198dc785aef821150838a2106cb2d Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Wed, 28 Jan 2026 19:46:48 +0400 Subject: [PATCH] feat: Tiktok API version configurable via Super Admin (#13381) Extracted hardcoded TikTok API version (`v1.3`) into a configurable `TIKTOK_API_VERSION` setting, consistent with how Instagram and WhatsApp handle API versions. Fixes https://linear.app/chatwoot/issue/CW-6408/tiktok-api-version-configurable-via-super-admin --- .../super_admin/app_configs_controller.rb | 2 +- app/services/tiktok/auth_client.rb | 14 +++++++++----- app/services/tiktok/client.rb | 12 ++++++++---- config/installation_config.yml | 5 +++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/app/controllers/super_admin/app_configs_controller.rb b/app/controllers/super_admin/app_configs_controller.rb index e9d27c67a..0462af393 100644 --- a/app/controllers/super_admin/app_configs_controller.rb +++ b/app/controllers/super_admin/app_configs_controller.rb @@ -46,7 +46,7 @@ class SuperAdmin::AppConfigsController < SuperAdmin::ApplicationController 'linear' => %w[LINEAR_CLIENT_ID LINEAR_CLIENT_SECRET], 'slack' => %w[SLACK_CLIENT_ID SLACK_CLIENT_SECRET], 'instagram' => %w[INSTAGRAM_APP_ID INSTAGRAM_APP_SECRET INSTAGRAM_VERIFY_TOKEN INSTAGRAM_API_VERSION ENABLE_INSTAGRAM_CHANNEL_HUMAN_AGENT], - 'tiktok' => %w[TIKTOK_APP_ID TIKTOK_APP_SECRET], + 'tiktok' => %w[TIKTOK_APP_ID TIKTOK_APP_SECRET TIKTOK_API_VERSION], 'whatsapp_embedded' => %w[WHATSAPP_APP_ID WHATSAPP_APP_SECRET WHATSAPP_CONFIGURATION_ID WHATSAPP_API_VERSION], 'notion' => %w[NOTION_CLIENT_ID NOTION_CLIENT_SECRET], 'google' => %w[GOOGLE_OAUTH_CLIENT_ID GOOGLE_OAUTH_CLIENT_SECRET GOOGLE_OAUTH_REDIRECT_URI ENABLE_GOOGLE_OAUTH_LOGIN], diff --git a/app/services/tiktok/auth_client.rb b/app/services/tiktok/auth_client.rb index d152d0338..cc2bb47c2 100644 --- a/app/services/tiktok/auth_client.rb +++ b/app/services/tiktok/auth_client.rb @@ -26,8 +26,8 @@ class Tiktok::AuthClient end # https://business-api.tiktok.com/portal/docs?id=1832184159540418 - def obtain_short_term_access_token(auth_code) # rubocop:disable Metrics/MethodLength - endpoint = 'https://business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/token/' + def obtain_short_term_access_token(auth_code) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize + endpoint = "#{api_base_url}/tt_user/oauth2/token/" headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' } body = { client_id: client_id, @@ -56,7 +56,7 @@ class Tiktok::AuthClient end def renew_short_term_access_token(refresh_token) # rubocop:disable Metrics/MethodLength - endpoint = 'https://business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/refresh_token/' + endpoint = "#{api_base_url}/tt_user/oauth2/refresh_token/" headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' } body = { client_id: client_id, @@ -82,7 +82,7 @@ class Tiktok::AuthClient end def webhook_callback - endpoint = 'https://business-api.tiktok.com/open_api/v1.3/business/webhook/list/' + endpoint = "#{api_base_url}/business/webhook/list/" headers = { Accept: 'application/json' } params = { app_id: client_id, @@ -95,7 +95,7 @@ class Tiktok::AuthClient end def update_webhook_callback - endpoint = 'https://business-api.tiktok.com/open_api/v1.3/business/webhook/update/' + endpoint = "#{api_base_url}/business/webhook/update/" headers = { Accept: 'application/json', 'Content-Type': 'application/json' } body = { app_id: client_id, @@ -141,5 +141,9 @@ class Tiktok::AuthClient def base_url ENV.fetch('FRONTEND_URL', 'http://localhost:3000') end + + def api_base_url + "https://business-api.tiktok.com/open_api/#{GlobalConfigService.load('TIKTOK_API_VERSION', 'v1.3')}" + end end end diff --git a/app/services/tiktok/client.rb b/app/services/tiktok/client.rb index 90fd6cef0..dfbe8ba1f 100644 --- a/app/services/tiktok/client.rb +++ b/app/services/tiktok/client.rb @@ -3,7 +3,7 @@ class Tiktok::Client pattr_initialize [:business_id!, :access_token!] def business_account_details - endpoint = 'https://business-api.tiktok.com/open_api/v1.3/business/get/' + endpoint = "#{api_base_url}/business/get/" headers = { 'Access-Token': access_token } params = { business_id: business_id, fields: %w[username display_name profile_image].to_s } response = HTTParty.get(endpoint, query: params, headers: headers) @@ -17,7 +17,7 @@ class Tiktok::Client end def file_download_url(conversation_id, message_id, media_id, media_type = 'IMAGE') - endpoint = 'https://business-api.tiktok.com/open_api/v1.3/business/message/media/download/' + endpoint = "#{api_base_url}/business/message/media/download/" headers = { 'Access-Token': access_token, 'Content-Type': 'application/json', Accept: 'application/json' } body = { business_id: business_id, conversation_id: conversation_id, @@ -45,7 +45,7 @@ class Tiktok::Client def send_message(conversation_id, type, payload, referenced_message_id: nil) # https://business-api.tiktok.com/portal/docs?id=1832184403754242 - endpoint ='https://business-api.tiktok.com/open_api/v1.3/business/message/send/' + endpoint = "#{api_base_url}/business/message/send/" headers = { 'Access-Token': access_token, 'Content-Type': 'application/json' } body = { business_id: business_id, @@ -70,7 +70,7 @@ class Tiktok::Client end def upload_media(file, media_type = 'IMAGE') - endpoint = 'https://business-api.tiktok.com/open_api/v1.3/business/message/media/upload/' + endpoint = "#{api_base_url}/business/message/media/upload/" headers = { 'Access-Token': access_token, 'Content-Type': 'multipart/form-data' } file.open do |temp_file| @@ -86,6 +86,10 @@ class Tiktok::Client end end + def api_base_url + "https://business-api.tiktok.com/open_api/#{GlobalConfigService.load('TIKTOK_API_VERSION', 'v1.3')}" + end + def process_json_response(response, error_prefix) unless response.success? Rails.logger.error "#{error_prefix}. Status: #{response.code}, Body: #{response.body}" diff --git a/config/installation_config.yml b/config/installation_config.yml index 33070357d..946b81e8e 100644 --- a/config/installation_config.yml +++ b/config/installation_config.yml @@ -407,6 +407,11 @@ # ------- End of Instagram Channel Related Config ------- # # ------- TikTok Channel Related Config ------- # +- name: TIKTOK_API_VERSION + display_title: 'TikTok API Version' + description: 'Configure this if you want to use a different TikTok API version. Make sure its prefixed with `v`' + value: 'v1.3' + locked: false - name: TIKTOK_APP_ID display_title: 'TikTok App ID' locked: false