Documentation Index
Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
Use this file to discover all available pages before exploring further.
Aviso Importante de Segurança
Princípio de segurança em primeiro lugar: Ao desenvolver e implantar aplicações de terceiros, a segurança é a consideração mais importante. Você deve seguir rigorosamente os princípios de segurança abaixo para garantir a segurança dos dados do usuário e do processo de autorização.
- Nunca exponha
client_secret no código JavaScript do frontend
- A troca do código de autorização OAuth por token deve ser feita no lado do servidor
- Todo acesso a recursos protegidos do usuário deve passar pelo proxy de API do backend
- Toda comunicação OAuth deve ser protegida usando HTTPS
A violação de qualquer um dos princípios de segurança acima pode resultar em sérias vulnerabilidades de segurança!
📋 Sumário
- Visão Geral
- Primeiros Passos
- Fluxo de Autorização OAuth2
- Referência da API
- SDK e Exemplos de Código
- Melhores Práticas de Segurança
- Perguntas Frequentes
- Suporte Técnico
Visão Geral
Fornecemos uma API aberta baseada no padrão OAuth2, permitindo que aplicações de terceiros acessem com segurança as informações básicas dos usuários e seus saldos de conta. Através do nosso serviço OAuth2, sua aplicação pode:
- 🚀 Login com um clique: Os usuários não precisam se registrar novamente, o login concede autorização automaticamente para uma experiência verdadeiramente sem atrito
- 👤 Obter informações do usuário: Acesse o perfil básico dos usuários (nome de usuário, e-mail, etc.)
- 💰 Visualizar saldo da conta: Obtenha o saldo da conta dos usuários em tempo real
- 🔄 Redirecionamento para recarga: Direcione os usuários para nossa página de recarga
- 🔐 Atualização automática de token: Mecanismo de refresh token integrado para renovação contínua, melhorando a experiência do usuário
Primeiros Passos
1. Registrar uma Conta de Desenvolvedor
Primeiro, você precisa registrar uma conta de desenvolvedor em nosso sistema.
2. Criar uma Aplicação OAuth
Crie sua aplicação OAuth no console do desenvolvedor:
curl -X POST https://api.aihubmix.com/api/oauth_apps \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_DEVELOPER_TOKEN" \
-d '{
"name": "My Third-party App",
"description": "App description",
"redirect_uri": "https://yourapp.com/oauth/callback"
}'
Exemplo de resposta:
{
"success": true,
"message": "Application created successfully",
"data": {
"id": 1,
"name": "My Third-party App",
"client_id": "client_abc123def456...",
"client_secret": "secret_xyz789uvw012...",
"redirect_uri": "https://yourapp.com/oauth/callback",
"created_time": 1640995200
}
}
Lembrete de Segurança Importante:
- client_id pode ser usado no frontend (informação pública)
client_secret só pode ser usado no servidor e nunca deve ser exposto ao navegador
- Armazene client_secret em variáveis de ambiente; não faça hardcode em seu código
3. Configurar a URI de Redirecionamento
Certifique-se de que sua URI de redirecionamento atenda aos seguintes requisitos:
- Usa protocolo HTTPS (para produção)
- Aponta para um endpoint do seu servidor (não uma página de frontend)
- O domínio está registrado e acessível
- O caminho é específico para o endpoint da API que trata o callback
Fluxo de Autorização OAuth2
Diagrama do Fluxo Seguro
Instruções Passo a Passo
Passo 1: Direcionar o Usuário para Autorizar
Adicione um botão de login na sua página frontend. Quando clicado, redirecione para o endpoint de autorização do lado do servidor:
Frontend code - only responsible for redirecting
function startLogin() {
// Redirect to your server-side authorization handler
window.location.href = '/auth/oauth/start';
}
Passo 2: Handler de Autorização do Lado do Servidor
Implemente o handler de autorização em seu servidor:
app.get('/auth/oauth/start', (req, res) => {
// Generate and store state parameter
const state = generateSecureRandomString();
req.session.oauth_state = state;
// Build authorization URL
const authUrl = new URL('https://your-domain.com/api/oauth2/authorize');
authUrl.searchParams.append('client_id', process.env.OAUTH_CLIENT_ID);
authUrl.searchParams.append('redirect_uri', process.env.OAUTH_REDIRECT_URI);
authUrl.searchParams.append('response_type', 'code');
authUrl.searchParams.append('scope', 'profile balance');
authUrl.searchParams.append('state', state);
authUrl.searchParams.append('auto_authorize', 'true'); // One-click login
// Redirect to authorization server
res.redirect(authUrl.toString());
});
Passo 3: Tratar o Callback de Autorização (Lado do Servidor)
Server-side authorization callback handler
app.get('/oauth/callback', async (req, res) => {
const { code, state, error } = req.query;
// Error handling
if (error) {
return res.redirect(`/?error=${encodeURIComponent(error)}`);
}
// Parameter validation
if (!code || !state) {
return res.redirect('/?error=missing_parameters');
}
// Validate state parameter (prevent CSRF attacks)
if (state !== req.session.oauth_state) {
return res.redirect('/?error=invalid_state');
}
try {
// Exchange authorization code for access token (server-side)
const tokenResponse = await fetch('https://your-domain.com/api/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: process.env.OAUTH_REDIRECT_URI,
client_id: process.env.OAUTH_CLIENT_ID,
client_secret: process.env.OAUTH_CLIENT_SECRET // Server-side only
})
});
const tokenData = await tokenResponse.json();
if (!tokenResponse.ok) {
throw new Error(tokenData.error || 'Token exchange failed');
}
// Securely store token (server session or database)
req.session.access_token = tokenData.access_token;
req.session.refresh_token = tokenData.refresh_token;
req.session.token_expires_at = Date.now() + (tokenData.expires_in * 1000);
// Clean up temporary state
delete req.session.oauth_state;
// Redirect to frontend page
res.redirect('/?login=success');
} catch (error) {
console.error('OAuth callback error:', error);
res.redirect(`/?error=server_error`);
}
});
Frontend fetches user info via API proxy
async function loadUserInfo() {
try {
const response = await fetch('/api/user/info');
if (!response.ok) {
throw new Error('Failed to fetch user info');
}
const userInfo = await response.json();
displayUserInfo(userInfo);
} catch (error) {
console.error('Failed to load user info:', error);
showLoginButton();
}
}
app.get('/api/user/info', async (req, res) => {
const accessToken = req.session.access_token;
if (!accessToken) {
return res.status(401).json({ error: 'Not authenticated' });
}
try {
// Proxy request to OAuth server
const response = await fetch('https://your-domain.com/api/oauth2/userinfo', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
if (!response.ok) {
throw new Error('User info request failed');
}
const userInfo = await response.json();
res.json(userInfo);
} catch (error) {
console.error('User info proxy error:', error);
res.status(500).json({ error: 'Server error' });
}
});
Referência da API
1. Endpoint de Autorização
GET /api/oauth2/authorize
Conduz o usuário pela autorização OAuth2.
Parâmetros:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|
client_id | string | Sim | ID do cliente da aplicação (pode ser usado no frontend) |
redirect_uri | string | Sim | URI de callback após a autorização (deve apontar para um endpoint do servidor) |
response_type | string | Sim | Fixo: code |
scope | string | Não | Escopo, separado por espaços |
state | string | Sim | String aleatória para prevenir ataques CSRF (gerada no servidor) |
auto_authorize | string | Não | Defina como true para habilitar a autorização automática |
Requisitos de segurança:
redirect_uri deve corresponder exatamente ao endereço registrado
state deve ser uma string aleatória gerada no servidor
- HTTPS deve ser usado (em produção)
Explicação dos escopos:
profile: Acessa informações básicas do usuário (nome de usuário, e-mail)
balance: Acessa o saldo da conta do usuário
2. Endpoint de Token
POST /api/oauth2/token
Aviso de Segurança: Este endpoint só deve ser chamado do lado do servidor, nunca do frontend!
Usado em dois cenários:
- Trocar código de autorização por access token
- Usar refresh token para obter um novo access token
Parâmetros do grant de código de autorização:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|
grant_type | string | Sim | Fixo: authorization_code |
code | string | Sim | Código de autorização |
redirect_uri | string | Sim | Deve corresponder à URI usada na autorização |
client_id | string | Sim | ID do cliente da aplicação |
client_secret | string | Sim | Secret do cliente da aplicação (apenas no servidor) |
Parâmetros do grant de refresh token:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|
grant_type | string | Sim | Fixo: refresh_token |
refresh_token | string | Sim | Refresh token |
client_id | string | Sim | ID do cliente da aplicação |
client_secret | string | Sim | Secret do cliente da aplicação (apenas no servidor) |
Exemplo de resposta:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "refresh_abc123def456...",
"scope": "profile balance"
}
GET /api/oauth2/userinfo
Obtém as informações básicas do usuário e o saldo da conta.
Header da requisição:
Authorization: Bearer {access_token}
Exemplo de resposta:
{
"id": 12345,
"username": "user123",
"email": "user@example.com",
"quota": 1000000,
"used_quota": 250000,
"balance_formatted": "750.00",
"created_time": 1640995200,
"status": 1
}
SDK e Exemplos de Código
SDK JavaScript
Fornecemos um SDK JavaScript completo que você pode usar diretamente:
<!DOCTYPE html>
<html>
<head>
<title>Third-party App Example</title>
<style>
.container { max-width: 800px; margin: 0 auto; padding: 20px; }
.user-info { background: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0; }
.login-section { text-align: center; padding: 40px; }
.btn { padding: 12px 24px; border: none; border-radius: 6px; cursor: pointer; font-size: 16px; }
.btn-primary { background: #007bff; color: white; }
.btn-success { background: #28a745; color: white; }
.btn-secondary { background: #6c757d; color: white; }
.hidden { display: none; }
</style>
</head>
<body>
<div class="container">
<h1>我的第三方应用</h1>
<!-- Loading status -->
<div id="loading">
<p>Checking login status...</p>
</div>
<!-- Logged-in user info -->
<div id="user-info" class="user-info hidden">
<h2>Welcome back!</h2>
<p><strong>Username:</strong> <span id="username"></span></p>
<p><strong>Email:</strong> <span id="email"></span></p>
<p><strong>Account Balance:</strong> <span id="balance"></span></p>
<div style="margin-top: 20px;">
<button class="btn btn-success" onclick="refreshBalance()">Refresh Balance</button>
<button class="btn btn-primary" onclick="goToTopup()">Top Up Account</button>
<button class="btn btn-secondary" onclick="logout()">Log Out</button>
</div>
</div>
<!-- Not logged in status -->
<div id="login-section" class="login-section hidden">
<h2>Please log in to view account info</h2>
<p>Use one-click login for quick access to your account</p>
<button class="btn btn-primary" onclick="oneClickLogin()">
🚀 One-click Login
</button>
</div>
</div>
<script>
// OAuth configuration
const OAUTH_CONFIG = {
authServer: 'https://your-domain.com',
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET', // 生产环境应该在后端处理
redirectUri: window.location.origin + '/oauth/callback.html',
scope: 'profile balance'
};
class OAuthManager {
constructor() {
this.accessToken = localStorage.getItem('oauth_access_token');
this.refreshToken = localStorage.getItem('oauth_refresh_token');
this.tokenExpiresAt = localStorage.getItem('oauth_token_expires_at');
this.isRefreshing = false; // 防止并发刷新
this.init();
}
async init() {
// 检查URL中是否有授权码
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
if (code) {
await this.handleAuthCallback(code, state);
// 清理URL
window.history.replaceState({}, document.title, window.location.pathname);
} else if (this.accessToken) {
try {
// 检查token是否过期,如果过期尝试刷新
if (this.isTokenExpired()) {
await this.refreshTokenIfNeeded();
}
await this.fetchUserInfo();
this.showUserInfo();
} catch (error) {
console.log('Token可能已过期或无效,需要重新登录');
this.clearTokens();
this.showLoginSection();
}
} else {
this.showLoginSection();
}
document.getElementById('loading').classList.add('hidden');
}
// Check if access token is expired
isTokenExpired() {
if (!this.tokenExpiresAt) return false;
const expiryTime = parseInt(this.tokenExpiresAt);
const bufferTime = 5 * 60 * 1000; // 5 minutes buffer
return Date.now() > (expiryTime - bufferTime);
}
// Automatically refresh token
async refreshTokenIfNeeded() {
if (!this.refreshToken || this.isRefreshing) {
return false;
}
this.isRefreshing = true;
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: this.refreshToken,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
})
});
if (response.ok) {
const tokenData = await response.json();
this.updateTokens(tokenData);
return true;
} else {
throw new Error('Token refresh failed');
}
} catch (error) {
console.error('Failed to refresh token:', error);
this.clearTokens();
return false;
} finally {
this.isRefreshing = false;
}
}
// Update token info
updateTokens(tokenData) {
this.accessToken = tokenData.access_token;
this.refreshToken = tokenData.refresh_token;
this.tokenExpiresAt = Date.now() + (tokenData.expires_in * 1000);
localStorage.setItem('oauth_access_token', this.accessToken);
localStorage.setItem('oauth_refresh_token', this.refreshToken);
localStorage.setItem('oauth_token_expires_at', this.tokenExpiresAt.toString());
}
oneClickLogin() {
const state = this.generateState();
localStorage.setItem('oauth_state', state);
const authUrl = `${OAUTH_CONFIG.authServer}/api/oauth2/authorize?` +
`client_id=${OAUTH_CONFIG.clientId}&` +
`redirect_uri=${encodeURIComponent(OAUTH_CONFIG.redirectUri)}&` +
`response_type=code&` +
`scope=${encodeURIComponent(OAUTH_CONFIG.scope)}&` +
`state=${state}&` +
`auto_authorize=true`; // Enable auto-authorization for true one-click login
// Open authorization page in popup
const popup = window.open(authUrl, 'oauth_login', 'width=500,height=600,scrollbars=yes');
// Listen for popup close
const checkClosed = setInterval(() => {
if (popup.closed) {
clearInterval(checkClosed);
// 检查是否获得了授权
setTimeout(() => this.init(), 1000);
}
}, 1000);
}
async handleAuthCallback(code, state) {
const savedState = localStorage.getItem('oauth_state');
if (state !== savedState) {
console.error('State parameter mismatch');
return;
}
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
redirect_uri: OAUTH_CONFIG.redirectUri
})
});
const tokenData = await response.json();
if (tokenData.access_token) {
this.updateTokens(tokenData);
localStorage.removeItem('oauth_state');
await this.fetchUserInfo();
this.showUserInfo();
}
} catch (error) {
console.error('获取访问令牌失败:', error);
}
}
// API request method with auto-refresh
async apiRequest(url, options = {}) {
// Check and refresh token if needed
if (this.isTokenExpired()) {
const refreshed = await this.refreshTokenIfNeeded();
if (!refreshed) {
throw new Error('Unable to refresh token');
}
}
const headers = {
'Authorization': `Bearer ${this.accessToken}`,
...options.headers
};
const response = await fetch(url, {
...options,
headers
});
// If a 401 error is received, try to refresh token and retry once
if (response.status === 401 && !options._retry) {
const refreshed = await this.refreshTokenIfNeeded();
if (refreshed) {
return this.apiRequest(url, { ...options, _retry: true });
}
}
return response;
}
async fetchUserInfo() {
const response = await this.apiRequest(`${OAUTH_CONFIG.authServer}/api/oauth2/userinfo`);
if (!response.ok) {
throw new Error('Failed to get user info');
}
this.userInfo = await response.json();
}
showUserInfo() {
document.getElementById('username').textContent = this.userInfo.username;
document.getElementById('email').textContent = this.userInfo.email;
document.getElementById('balance').textContent = this.userInfo.balance_formatted;
document.getElementById('user-info').classList.remove('hidden');
document.getElementById('login-section').classList.add('hidden');
}
showLoginSection() {
document.getElementById('user-info').classList.add('hidden');
document.getElementById('login-section').classList.remove('hidden');
}
async refreshBalance() {
try {
await this.fetchUserInfo();
document.getElementById('balance').textContent = this.userInfo.balance_formatted;
alert('Balance updated');
} catch (error) {
alert('Refresh failed, please log in again');
this.clearTokens();
this.showLoginSection();
}
}
async goToTopup() {
try {
const response = await this.apiRequest(`${OAUTH_CONFIG.authServer}/api/oauth2/topup`);
const data = await response.json();
if (data.topup_url) {
window.open(data.topup_url, '_blank');
}
} catch (error) {
console.error('Failed to get top-up link:', error);
}
}
logout() {
this.clearTokens();
this.showLoginSection();
}
clearTokens() {
this.accessToken = null;
this.refreshToken = null;
this.tokenExpiresAt = null;
this.userInfo = null;
localStorage.removeItem('oauth_access_token');
localStorage.removeItem('oauth_refresh_token');
localStorage.removeItem('oauth_token_expires_at');
}
generateState() {
return Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
}
// 全局函数
let oauthManager;
function oneClickLogin() {
oauthManager.oneClickLogin();
}
function refreshBalance() {
oauthManager.refreshBalance();
}
function goToTopup() {
oauthManager.goToTopup();
}
function logout() {
oauthManager.logout();
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
oauthManager = new OAuthManager();
});
</script>
</body>
</html>
Página de Callback do OAuth
Crie um arquivo /oauth/callback.html:
<!DOCTYPE html>
<html>
<head>
<title>Logging in...</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
.loading { color: #666; }
.error { color: #dc3545; }
</style>
</head>
<body>
<h2>Logging in, please wait...</h2>
<div id="status" class="loading">Verifying authorization information...</div>
<script>
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
const error = urlParams.get('error');
if (error) {
document.getElementById('status').innerHTML =
`<div class="error">Authorization failed: ${error}</div>`;
setTimeout(() => {
if (window.opener) {
window.close();
} else {
window.location.href = '/';
}
}, 3000);
} else if (code) {
if (window.opener) {
// 如果是弹窗,关闭并让父窗口处理
window.opener.location.href =
window.opener.location.pathname + `?code=${code}&state=${state}`;
window.close();
} else {
// 如果不是弹窗,重定向到主页面
window.location.href = `/?code=${code}&state=${state}`;
}
} else {
document.getElementById('status').innerHTML =
'<div class="error">No valid authorization information received</div>';
setTimeout(() => {
window.location.href = '/';
}, 3000);
}
</script>
</body>
</html>
Exemplo de Backend em Node.js
Para melhor segurança, é recomendado tratar client_secret no backend:
const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');
const app = express();
app.use(cors());
app.use(express.json());
const OAUTH_CONFIG = {
authServer: 'https://your-domain.com',
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET'
};
// Backend handles token exchange
app.post('/api/oauth/exchange-token', async (req, res) => {
const { code, redirectUri, state } = req.body;
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
redirect_uri: redirectUri
})
});
const tokenData = await response.json();
if (response.ok) {
res.json(tokenData);
} else {
res.status(400).json(tokenData);
}
} catch (error) {
res.status(500).json({ error: 'Token exchange failed' });
}
});
// Refresh token endpoint
app.post('/api/oauth/refresh-token', async (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(400).json({ error: 'Missing refresh token' });
}
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
})
});
const tokenData = await response.json();
if (response.ok) {
res.json(tokenData);
} else {
res.status(400).json(tokenData);
}
} catch (error) {
res.status(500).json({ error: 'Token refresh failed' });
}
});
// Proxy user info request (with auto-refresh)
app.get('/api/oauth/userinfo', async (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).json({ error: 'Missing authorization header' });
}
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/userinfo`, {
headers: {
'Authorization': authHeader
}
});
const userData = await response.json();
if (response.ok) {
res.json(userData);
} else {
res.status(response.status).json(userData);
}
} catch (error) {
res.status(500).json({ error: 'Failed to fetch user info' });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Melhores Práticas de Segurança
1. Proteção do Client Secret
- ✅ Recomendado: Armazene
client_secret no servidor backend
- ❌ Evite: Expor
client_secret no JavaScript do frontend
2. Validação do Parâmetro State
// Generate random state
const state = crypto.randomBytes(16).toString('hex');
localStorage.setItem('oauth_state', state);
// Validate state
const savedState = localStorage.getItem('oauth_state');
if (receivedState !== savedState) {
throw new Error('CSRF attack detected');
}
3. Uso de HTTPS
- Deve usar
HTTPS em produção
- A URI de callback deve usar
HTTPS
- Todas as requisições de API usam
HTTPS
4. Armazenamento Seguro do Token
// Set token expiry time
const expiryTime = Date.now() + (tokenData.expires_in * 1000);
localStorage.setItem('oauth_token_expiry', expiryTime);
// Check if token is expired
function isTokenExpired() {
const expiry = localStorage.getItem('oauth_token_expiry');
return !expiry || Date.now() > parseInt(expiry);
}
5. Tratamento de Erros
try {
const response = await fetch('/api/oauth2/userinfo', {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) {
if (response.status === 401) {
// Token expired, need to re-login
clearToken();
showLoginSection();
} else {
throw new Error(`HTTP ${response.status}`);
}
}
const userInfo = await response.json();
return userInfo;
} catch (error) {
console.error('API request failed:', error);
// Handle network errors etc.
}
Perguntas Frequentes
R: Basta adicionar o parâmetro auto_authorize=true à URL de autorização. Após o login do usuário, a autorização será concedida automaticamente, sem etapa adicional de confirmação:
const authUrl = 'https://your-domain.com/api/oauth2/authorize?' +
'client_id=YOUR_CLIENT_ID&' +
'auto_authorize=true&' + // Key parameter
'...other parameters';
Q2: Os tokens serão atualizados automaticamente?
R: Sim, nosso SDK possui refresh automático de token integrado:
- Access token: válido por 2 horas, refresh automático 5 minutos antes de expirar
- Refresh token: válido por 30 dias, usado para obter novos access tokens
- Refresh sem atritos: Todas as chamadas de API verificarão e atualizarão tokens expirados automaticamente
- Retry em caso de falha: Se a API retornar um erro 401, tentará automaticamente refresh do token e nova requisição
// The SDK will handle token refresh automatically, no manual handling needed
const userInfo = await oauthManager.fetchUserInfo(); // token auto-refresh
Somente se o refresh token também expirar é que o usuário precisará fazer login novamente.
R: De acordo com o escopo autorizado, você pode obter:
- Escopo
profile: nome de usuário, e-mail
- Escopo
balance: informações de saldo da conta
Q4: Como testar a integração OAuth?
R:
- Use
HTTP localhost em desenvolvimento para testes
- Use nossas ferramentas de teste fornecidas para verificar o fluxo de autorização
- Verifique as requisições de rede nas ferramentas de desenvolvedor do navegador
Q5: Quais linguagens de programação são suportadas?
R: Nossa API OAuth2 é padrão e suporta todas as principais linguagens de programação:
- JavaScript/Node.js
- Python
- PHP
- Java
- C#/.NET
- Go
- Ruby
Q6: Como um usuário pode revogar a autorização?
R: Os usuários podem revogar a autorização de aplicativos de terceiros na nossa página Central do Usuário > Gerenciamento de Autorização.
Última atualização: 2026-06-01