feat: connect Tiny through its v3 API with OAuth
All checks were successful
Build and deploy / Validate source (push) Successful in 9s
Build and deploy / Integration suite on a real stack (push) Successful in 2m49s
Build and deploy / Secret scan and release gate (push) Successful in 9s
Build and deploy / Publish images and notify Portainer (push) Has been skipped
All checks were successful
Build and deploy / Validate source (push) Successful in 9s
Build and deploy / Integration suite on a real stack (push) Successful in 2m49s
Build and deploy / Secret scan and release gate (push) Successful in 9s
Build and deploy / Publish images and notify Portainer (push) Has been skipped
Tiny v3 replaces the v2 token adapter. An operator connects Tiny once from the Kanban; the callback is authorised by a single-use state, because Tiny's cross-site redirect does not carry the SameSite=Strict operator cookie. Tokens are kept in provider_tokens, the refresh token rotates under a row lock, and the worker keeps the connection alive while order creation is off. Orders find or create the customer's contact by CNPJ, then POST /pedidos with product ids from TINY_PRODUCT_TEXTIL_FOLHA, _TEXTIL_AVULSA, _UV_FOLHA and _UV_AVULSA and numeroOrdemCompra DTF-<number>; a retry searches the customer's recent orders for that number first. The product settings avoid a _FILE suffix, which the secrets loader reads as a secret file path. Production passes the application credentials through but keeps TINY_ADAPTER fake: Tiny has no sandbox, so creating real orders waits for a supervised test. compose.providers.yaml gives the local API and worker an internet route for provider testing; the default local stack still has none. Verified with the full CI integration sequence locally, including the new tiny_oauth_test against the real database. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -93,7 +93,7 @@ async function load(){
|
||||
moreQuotes={pending:board.pending_total>board.quotes.filter(q=>!q.approved).length,
|
||||
approved:board.approved_total>board.quotes.filter(q=>!!q.approved).length};
|
||||
$('login').hidden=true;
|
||||
$('status').textContent='Atualizado às '+new Date().toLocaleTimeString();
|
||||
$('status').textContent='Atualizado às '+new Date().toLocaleTimeString()+tinyNotice;
|
||||
render();
|
||||
}catch(e){$('status').textContent=e.message;$('login').hidden=false;}
|
||||
}
|
||||
@@ -108,7 +108,24 @@ async function loadMoreQuotes(kind){
|
||||
moreQuotes[kind]=page.has_more;
|
||||
render();
|
||||
}
|
||||
// The one-time authorisation of this system in the client's Tiny. Shown only
|
||||
// when the Tiny application is configured on the server.
|
||||
function tinyStatus(){
|
||||
const box=$('tiny');box.replaceChildren();
|
||||
const tiny=board.tiny||{};
|
||||
if(!tiny.configured)return;
|
||||
box.append(node('span',tiny.connected
|
||||
? 'Tiny conectado'+(tiny.orders_enabled?'':' · envio de pedidos desligado')
|
||||
: 'Tiny não conectado'));
|
||||
box.append(action(tiny.connected?'Reconectar Tiny':'Conectar Tiny',async()=>{
|
||||
const result=await api('/tiny/connect',{});location.href=result.url;
|
||||
}));
|
||||
}
|
||||
const tinyResult=new URLSearchParams(location.search).get('tiny');
|
||||
const tinyNotice=tinyResult?(tinyResult==='connected'?' · Tiny conectado.':' · Não foi possível conectar o Tiny. Tente de novo.'):'';
|
||||
if(tinyResult)history.replaceState(null,'',location.pathname);
|
||||
function render(){
|
||||
tinyStatus();
|
||||
paymentIssues();
|
||||
$('reviews').replaceChildren();
|
||||
if(board.pending_total || board.approved_total)
|
||||
|
||||
Reference in New Issue
Block a user