|
|
@@ -282,7 +282,7 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
|
|
|
// Fetch store data
|
|
|
const { data: store, error: storeError } = await supabase
|
|
|
.from('stores')
|
|
|
- .select('store_name, api_key, api_secret, alt_data, token_expires_at')
|
|
|
+ .select('store_name, api_key, api_secret, access_token, refresh_token, alt_data, token_expires_at')
|
|
|
.eq('id', storeId)
|
|
|
.eq('platform_name', 'shoprenter')
|
|
|
.single()
|
|
|
@@ -291,17 +291,17 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
|
|
|
throw new Error('ShopRenter store not found')
|
|
|
}
|
|
|
|
|
|
- // Try to get client credentials from alt_data first (most reliable)
|
|
|
- let clientId = store.alt_data?.client_id
|
|
|
- let clientSecret = store.alt_data?.client_secret
|
|
|
+ // Try to get client credentials from api_key/api_secret first (primary location)
|
|
|
+ let clientId = store.api_key
|
|
|
+ let clientSecret = store.api_secret
|
|
|
|
|
|
- // Check if api_key contains a client_id (32 hex chars) instead of a token
|
|
|
- const isClientId = store.api_key && /^[a-f0-9]{32}$/i.test(store.api_key)
|
|
|
+ // If api_key looks like an access_token (JWT format), get credentials from alt_data
|
|
|
+ const isAccessToken = store.api_key && store.api_key.includes('.')
|
|
|
|
|
|
- // If not in alt_data and api_key looks like client_id, use it
|
|
|
- if (!clientId && isClientId) {
|
|
|
- clientId = store.api_key
|
|
|
- clientSecret = store.api_secret
|
|
|
+ if (isAccessToken) {
|
|
|
+ // api_key contains a token (old bug), try alt_data for client credentials
|
|
|
+ clientId = store.alt_data?.client_id
|
|
|
+ clientSecret = store.alt_data?.client_secret
|
|
|
}
|
|
|
|
|
|
// If still no client credentials, try environment variables (global app credentials)
|
|
|
@@ -326,12 +326,13 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
|
|
|
const expiresAt = new Date(Date.now() + (tokenData.expires_in * 1000)).toISOString()
|
|
|
|
|
|
// Update store with the new access token
|
|
|
- // IMPORTANT: Always preserve client credentials in alt_data for future token renewals
|
|
|
+ // IMPORTANT: Store tokens in access_token/refresh_token columns
|
|
|
+ // Keep client credentials in api_key/api_secret for future token renewals
|
|
|
await supabase
|
|
|
.from('stores')
|
|
|
.update({
|
|
|
- api_key: tokenData.access_token,
|
|
|
- api_secret: tokenData.refresh_token || clientSecret,
|
|
|
+ access_token: tokenData.access_token,
|
|
|
+ refresh_token: tokenData.refresh_token || null,
|
|
|
token_expires_at: expiresAt,
|
|
|
alt_data: {
|
|
|
...store.alt_data,
|
|
|
@@ -349,9 +350,9 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Check if we have tokens in api_key/api_secret (legacy)
|
|
|
- if (store.api_key) {
|
|
|
- const expiresAt = store.token_expires_at // Use dedicated column instead of alt_data
|
|
|
+ // Check if we have an existing access token
|
|
|
+ if (store.access_token) {
|
|
|
+ const expiresAt = store.token_expires_at
|
|
|
if (expiresAt) {
|
|
|
const expiryTime = new Date(expiresAt).getTime()
|
|
|
const now = Date.now()
|
|
|
@@ -359,24 +360,24 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
|
|
|
|
|
|
// Token is still valid
|
|
|
if (expiryTime - now > bufferTime) {
|
|
|
- console.log('[ShopRenter] Using existing valid token, expires at:', expiresAt)
|
|
|
- return store.api_key
|
|
|
+ console.log('[ShopRenter] Using existing valid access_token, expires at:', expiresAt)
|
|
|
+ return store.access_token
|
|
|
}
|
|
|
|
|
|
// Token needs refresh
|
|
|
console.log('[ShopRenter] Token expired or expiring soon, refreshing...')
|
|
|
- if (store.api_secret) {
|
|
|
+ if (store.refresh_token) {
|
|
|
try {
|
|
|
- const newTokenData = await refreshAccessToken(store.store_name, store.api_secret)
|
|
|
+ const newTokenData = await refreshAccessToken(store.store_name, store.refresh_token)
|
|
|
|
|
|
const newExpiresAt = new Date(Date.now() + (newTokenData.expires_in * 1000)).toISOString()
|
|
|
|
|
|
- // Update store with new tokens (use token_expires_at column, not alt_data)
|
|
|
+ // Update store with new tokens
|
|
|
await supabase
|
|
|
.from('stores')
|
|
|
.update({
|
|
|
- api_key: newTokenData.access_token,
|
|
|
- api_secret: newTokenData.refresh_token || store.api_secret,
|
|
|
+ access_token: newTokenData.access_token,
|
|
|
+ refresh_token: newTokenData.refresh_token || store.refresh_token,
|
|
|
token_expires_at: newExpiresAt
|
|
|
})
|
|
|
.eq('id', storeId)
|
|
|
@@ -386,23 +387,22 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
|
|
|
} catch (refreshError) {
|
|
|
console.error('[ShopRenter] Token refresh failed:', refreshError)
|
|
|
|
|
|
- // If we have client credentials stored in alt_data, try using client_credentials flow as fallback
|
|
|
- if (store.alt_data?.client_id && store.alt_data?.client_secret) {
|
|
|
- console.log('[ShopRenter] Attempting fallback to client_credentials flow with stored credentials')
|
|
|
+ // If refresh fails and we have client credentials, try client_credentials flow as fallback
|
|
|
+ if (clientId && clientSecret) {
|
|
|
+ console.log('[ShopRenter] Attempting fallback to client_credentials flow')
|
|
|
const tokenData = await getTokenWithClientCredentials(
|
|
|
store.store_name,
|
|
|
- store.alt_data.client_id,
|
|
|
- store.alt_data.client_secret
|
|
|
+ clientId,
|
|
|
+ clientSecret
|
|
|
)
|
|
|
|
|
|
const expiresAt = new Date(Date.now() + (tokenData.expires_in * 1000)).toISOString()
|
|
|
|
|
|
- // 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,
|
|
|
+ access_token: tokenData.access_token,
|
|
|
+ refresh_token: tokenData.refresh_token || null,
|
|
|
token_expires_at: expiresAt
|
|
|
})
|
|
|
.eq('id', storeId)
|
|
|
@@ -418,8 +418,8 @@ export async function getValidAccessToken(storeId: string): Promise<string> {
|
|
|
}
|
|
|
|
|
|
// No expiration info, just return the token
|
|
|
- console.log('[ShopRenter] No expiration info found, using token as-is')
|
|
|
- return store.api_key
|
|
|
+ console.log('[ShopRenter] No expiration info found, using access_token as-is')
|
|
|
+ return store.access_token
|
|
|
}
|
|
|
|
|
|
throw new Error('No access token found for ShopRenter store')
|