فهرست منبع

fix: add client_credentials token flow for manually added ShopRenter stores #79

Claude 5 ماه پیش
والد
کامیت
024769f471
1فایلهای تغییر یافته به همراه65 افزوده شده و 1 حذف شده
  1. 65 1
      supabase/functions/_shared/shoprenter-client.ts

+ 65 - 1
supabase/functions/_shared/shoprenter-client.ts

@@ -59,7 +59,7 @@ export interface ShopRenterOrder {
   }
 }
 
-// Get valid access token (with automatic refresh)
+// Get valid access token (with automatic refresh or client_credentials)
 export async function getValidAccessToken(storeId: string): Promise<string> {
   const supabaseUrl = Deno.env.get('SUPABASE_URL')!
   const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
@@ -77,6 +77,35 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
     throw new Error('ShopRenter store not found')
   }
 
+  // Check if api_key contains a client_id (32 hex chars) instead of a token
+  // Client credentials are typically 32 hex characters
+  const isClientId = store.api_key && /^[a-f0-9]{32}$/i.test(store.api_key)
+
+  if (isClientId && store.api_secret) {
+    console.log('[ShopRenter] Detected client credentials, obtaining access token via client_credentials flow')
+
+    // Use client_credentials flow to get access token
+    const tokenData = await getTokenWithClientCredentials(store.store_name, store.api_key, store.api_secret)
+
+    // Update store with the new access token
+    await supabase
+      .from('stores')
+      .update({
+        api_key: tokenData.access_token,
+        api_secret: tokenData.refresh_token || store.api_secret,
+        alt_data: {
+          ...store.alt_data,
+          expires_at: new Date(Date.now() + (tokenData.expires_in * 1000)).toISOString(),
+          client_id: store.api_key, // Store original client_id for reference
+          client_secret: store.api_secret // Store original client_secret for reference
+        }
+      })
+      .eq('id', storeId)
+
+    console.log('[ShopRenter] Access token obtained and stored successfully')
+    return tokenData.access_token
+  }
+
   // Check if we have tokens in api_key/api_secret (legacy)
   if (store.api_key) {
     const expiresAt = store.alt_data?.expires_at
@@ -117,6 +146,41 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
   throw new Error('No access token found for ShopRenter store')
 }
 
+// Get access token using client_credentials grant
+async function getTokenWithClientCredentials(shopname: string, clientId: string, clientSecret: string) {
+  const tokenUrl = `https://oauth.app.shoprenter.net/${shopname}/app/token`
+
+  console.log(`[ShopRenter] Requesting token for ${shopname} using client_credentials`)
+
+  try {
+    const response = await fetch(tokenUrl, {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+        'Accept': 'application/json'
+      },
+      body: JSON.stringify({
+        grant_type: 'client_credentials',
+        client_id: clientId,
+        client_secret: clientSecret
+      })
+    })
+
+    if (!response.ok) {
+      const errorData = await response.text()
+      console.error('[ShopRenter] Token request error:', errorData)
+      throw new Error(`Failed to get access token: ${response.status} ${errorData}`)
+    }
+
+    const data = await response.json()
+    console.log(`[ShopRenter] Access token obtained for ${shopname}`)
+    return data
+  } catch (error) {
+    console.error('[ShopRenter] Token request error:', error)
+    throw new Error('Failed to get access token via client_credentials')
+  }
+}
+
 // Refresh access token
 async function refreshAccessToken(shopname: string, refreshToken: string) {
   const clientId = Deno.env.get('SHOPRENTER_CLIENT_ID')