Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Product_title
TitleGetting started
Image<>


Este guia explica como configurar seu ambiente para desenvolvimento usando a biblioteca @totvs/Mingle.

A biblioteca Mingle realiza a integração transparente com o servidor do Mingle que esta na nuvem, assim o desenvolvedor não precisa se preocupar com o servidor do Mingle. 

O guia Getting Started inclui informações sobre:

  • Pré-requisitos
  • Cadastro na plataforma Mingle
  • Instalação do pacote Mingle Client
  • Configuração da ferramenta para cada ambiente
  • Criação de um aplicativo inicial e a execução local desse aplicativo para verificar sua configuração.

Seguindo o passo a passo apresentado nos próximos tópicos o desenvolvedor terá um software integrado com a biblioteca Mingle e estará pronto para desenvolver uma aplicação de alta performance.


Expandir
title1- Pré-requisitos

Para começar a utilizar o a biblioteca @totvs/mingle em sua aplicação é necessário possuir: 


Aviso

Para aplicações desenvolvidas com o framework IONIC: 

Você deve executar a instalação dos plugins MIngle-ionic: Mingle Ionic Geolocation Mingle Ionic Device.

Consulte a documentação Pacote @totvs/mingle na plataforma Ionic para maiores detalhes.

Informações

Este guia utiliza o framework Angular para os seus exemplos.

A biblioteca @totvs/mingle é compatível com os frameworks que são baseados no javascript.


Expandir
title2- Criando um projeto do zero

A biblioteca Mingle foi criada para facilitar a comunicação entre os aplicativos e o servidor Mingle. 

Com ela nós teremos a facilidade de realizar login com poucas linhas de código, recursos para geração de métricas, interceptadores de requests entre outros diversos métodos públicos que facilitarão o trabalho do programador.

Instalação do pacote Mingle

Para começar a utilizar o Mingle o primeiro passo é fazer a instalação usando o npm: 

$ npm install --save @totvs/mingle


Acompanhe as próximas páginas deste guia para iniciar o desenvolvimento utilizando o pacote instalado.


Expandir
title3- Configurações iniciais

Neste passo vamos realizar a configuração da classe MingleService que deverá ser instanciada no início da sua aplicação para que possamos tirar proveito de todas as funcionalidades da biblioteca Mingle em seu aplicativo. 

Consideramos este passo o mais importante, aqui é onde iremos configurar uma única instância da classe MingleService e ela funcionará por toda a sua aplicação. 

Utilizando o comando $ "ng generate service appinitservice" do Angular CLI, criamos um serviço AppInitService e nele realizamos a seguinte implementação: 

Bloco de código
languagejs
firstline1
titleappInitService
linenumberstrue
import { Injectable } from '@angular/core';
import { MingleService } from '@totvs/mingle';
@Injectable()
export class AppInitService {
  
 constructor(private mingleService: MingleService) { }
  
 mingleConfiguration(): Promise<any> {
   return new Promise((resolve, reject) => {      
     console.log("Mingle Service Configuration called");
     const server = mingleService.servers.development;
     const appId = 'your_app_id';
     const web = true;
 
     this.mingleService.init(server, appId, web)
      .then( init => {
       resolve('Mingle Service Init');
     }).catch(error => {
       console.log("error" , error);
       
       reject(error);
     }); 
    console.log("Mingle Service configuration completed"); 
   });
 }}




Agora vamos analisar os trechos mais importantes do código acima:

Realize a importação da classe MingleService.

Bloco de código
languagejs
titleappInitService
import { MingleService } from '@totvs/mingle';


Deverão ser passados três parâmetros para a inicialização do Mingle (init):

O primeiro parâmetro que deverá ser passado é o servidor. 

Existem três servidores, sendo eles: 

  1. Development = 'https://dev-mingle.totvs.com.br/api'
  2. Staging = 'https://hom-mingle.totvs.com.br/api'
  3. Production = 'https://mingle.totvs.com.br/api'

Como neste exemplo ainda estamos desenvolvendo, vamos utilizar o ambiente "Mingle Development": 

  • server = this.mingleService.servers.development;

Para utilizar o ambiente Staging

  • server =  this.mingleService.servers.staging;

Para utilizar o ambiente Production

  • server =  this.mingleService.servers.production;

O segundo parâmetro que deverá ser utilizado é o appId. Cada ambiente possui um appId por aplicativo, o appId deve ser solicitado para um membro da equipe do Mingle.

O terceiro parâmetro deverá ser a plataforma utilizada.

  • Em aplicações web utilize: web = true; 
  • Em aplicações mobile utilize: web = false; a biblioteca enviará o deviceID e a plataforma do mobile para o registro de métricas e gateways do Mingle Server. 

Em seguida inicie o aplicativo utilizando o método init() da classe mingleService, informando os três parâmetros acima descritos:

Bloco de código
languagejs
firstline1
titleappInitService
linenumberstrue
this.mingleService.init(server, appId, web)
   .then( init => {
    resolve('Mingle Service Init');
})




Agora que você realizou a configuração Mingle e o método init() já está pronto, vamos dizer para o seu aplicativo utilizar a classe AppInitService quando for compilado e iniciado.

Adicione o bloco de código abaixo em seu app.module.ts (pode ser logo após os imports ou então se for de sua preferência pode ser uma função importada de um arquivo externo).

Bloco de código
languagejs
firstline1
titleapp.module.ts
linenumberstrue
export function initializeApp1(appInitService: AppInitService) {
  return (): Promise<any> => {
    return appInitService.mingleConfiguration();
  }
}




No app.module.ts -> Providers: 

 1- Declare  AppInitService e MingleService

 2- Crie um provide para realizar o APP_INITIALIZER que será responsável por executar as configurações realizadas no tópico anterior

3- Realize a importação das classes declaradas em providers

Bloco de código
languagejs
firstline1
titleappInitService
linenumberstrue
providers: [
  AppInitService,
  MingleService,
  { provide: APP_INITIALIZER, useFactory: initializeApp1, deps:[AppInitService], multi: true}
],




Agora basta compilar a aplicação e acompanhar o terminal de logs.

Para essa aplicação utilizamos o comando:  $ "ng serve"

Em caso de compilação e configuração positiva, sem erros, no console do seu navegador será apresentada a mensagem:  "Mingle Service configuration completed".

Acompanhe os próximos tópicos desta documentação para começar a desenvolver a aplicação utilizando o Mingle, como por exemplo realizar uma autenticação ou uma requisição de API  utilizando a segurança que o gateway do Mingle proporciona.

HTML
<style>
div.theme-default .ia-splitter #main {
    margin-left: 0px;
}
.ia-fixed-sidebar, .ia-splitter-left {
    display: none;
}
#main {
    padding-left: 10px;
    padding-right: 10px;
    overflow-x: hidden;
}

.aui-header-primary .aui-nav,  .aui-page-panel {
    margin-left: 0px !important;
}
.aui-header-primary .aui-nav {
    margin-left: 0px !important;
}
</style>






Expandir
title4- Autenticação

Agora que você já conhece o pacote Mingle e sua configuração inicial já está funcionando, vamos utilizar o MingleService para realizar a autenticação do usuário ao backend do cliente (Protheus, Datasul, Logix, Smart).

Métodos de Autenticação

Atualmente, oferecemos dois métodos de autenticação:

  1. Autenticação Clássica (Usuário e Senha)
  2. Autenticação via OIDC (OpenID Connect)

Autenticação Clássica

Pré-requisitos:

  • Usuário e senha de autenticação do backend
  • ALIAS

Implementação:

Considere o arquivo: login.component.ts

Implemente a autenticação utilizando o MingleService

Bloco de código
languagejs
firstline1
linenumberstrue
import { MingleService } from '@totvs/mingle';




Na função login(), utilizamos o método mingleService.auth.login(usuário, senha, alias).

Bloco de código
languagejs
firstline1
titlelogin.component.ts
linenumberstrue
import { MingleService } from '@totvs/mingle';

export class LoginComponent implements OnInit {

 constructor(private mingleService: MingleService) { }
 
 ngOnInit(): void {}
 
 login() {
   this.mingleService.auth.login("login",
     "password",
     "alias")
     .subscribe((dataLogin) => {
       console.log("Login com sucesso - dados do login", dataLogin);
      
       this.route.navigate(['home']);
     }, (authError) => {
       console.log(authError);
       console.error('Falha na autenticação');
     });
    }
}

Observe que os valores "login" e "password" geralmente são preenchidos pelo usuário do aplicativo através de uma página de autenticação.


Após executar o Login no aplicativo, o retorno de sucesso será parecido com este: 

Bloco de código
languagejs
firstline1
titleJson Login ok
linenumberstrue
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Mug...",
"muser":{"_id":"5ffda7bdaacb0685f34d59e2","login":"exemplo"},
"set":{"_id":"5fbe5712d8ccbf002cf443f3","alias":"TOTVS"},
"params_values":[{"_id":"5fbe5712d8ccbf002cf443f2","key":"EMPRESA","value":"123"}],
"client":{"_id":"5eeb67edeb62740029b1f03f","name":"TOTVS_TDN"},
"wso2":{},
"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoi...","
auth_driver":"protheus"}


A chave access_token é armazenada no storage do navegador pelo mingleService para ser utilizada em outras etapas do aplicativo que requerem comprovação de autenticação, como por exemplo uma chamada de gateway. O access_token tem um prazo de validade de acordo com cada ambiente e requer uma nova autenticação quando expirar. 

Quando se utiliza um access_token expirado, o Mingle retornará para o aplicativo o status 401 do protocolo HTTP.

O desenvolvedor pode seguir dois caminhos para obter um novo access_token:

1- Solicitar ao usuário do aplicativo um novo login.

2- Utilizar a chave refresh_token obtida no login inicial e realizar uma autenticação transparente para o usuário, sem que ele tenha que realizar login novamente. 


Autenticação via OIDC (OpenID Connect)

Pré-requisitos:

  • ALIAS
  • Configuração do servidor OIDC no backend

Implementação:

Este método utiliza OIDC para realizar a autenticação do usuário, eliminando a necessidade de fornecer login e senha manualmente. Em caso de retorno com código HTTP 300, um novo fluxo de autenticação é iniciado utilizando os cabeçalhos fornecidos pelo servidor.


Bloco de código
languagejs
firstline1
titleExemplo de implementação OIDC
linenumberstrue
import { MingleService } from '@totvs/mingle';

export class LoginComponent implements OnInit {

  constructor(private mingleService: MingleService) {}

  ngOnInit(): void {}

  login(formData: any) {
    this.loading = true;
    this.mingleService.auth.login(null, null, 'ALIAS')
      .subscribe(
        (dataLogin: any) => {
          try {
            if (dataLogin && dataLogin.jwks_uri) {
              const options = this.getOptionsFromJwksUri(dataLogin.jwks_uri);

              this.mingleService.auth
                .login(formData.login, formData.password, 'ALIAS', null, options)
                .subscribe(
                  (finalDataLogin) => {
                    this.handleLoginSuccess(finalDataLogin);
                  },
                  (finalAuthError) => {
                    this.handleLoginError(finalAuthError);
                  }
                );
            } else {
              this.handleLoginSuccess(dataLogin);
            }
          } catch (e) {
            console.log(e);
          }
        },
        (authError) => {
          if (authError.response.status === 300) {
            const options = this.getOptionsFromJwksUri(authError.response.jwks_uri);

            this.mingleService.auth
              .login(formData.login, formData.password, 'RENAN SIM02ALIAS', null, options)
              .subscribe(
                (finalDataLogin) => {
                  this.handleLoginSuccess(finalDataLogin);
                },
                (finalAuthError) => {
                  this.handleLoginError(finalAuthError);
                }
              );
          } else {
            console.log(authError);
            this.loading = false;
            const errorMessage = authError.response.data.message;
            if (errorMessage.includes('The request requires authentication')) {
              this.poNotification.error('Senha inválida');
            } else {
              this.poNotification.error(errorMessage);
            }
          }
          this.handleLoginError(authError);
        }
      );
  }

  private getOptionsFromJwksUri(jwksUri: string) {
    return {
      'x_totvs_oidc_token': 'token_oidc',
      'x_totvs_oidc_user': 'renan[email protected].arosariobr'
    };
  }

  private handleLoginSuccess(dataLogin: any) {
    console.log("Login com sucesso", dataLogin);
  }

  private handleLoginError(authError: any) {
    console.error('Falha na autenticação', authError);
  }
}
Bloco de código
languagejs
firstline1
titleExemplo de retorno 300 do login via OIDC
linenumberstrue
{
  "_set": "66a937e86a4b265d10caa21c",
  "_host": {
    "_id": "66a90cfb49a29209b343b0e4",
    "needIuser": false,
    "ip": "imexsolutions143214.protheus.cloudtotvs.com.br",
    "port": 2107,
    "authType": "protheus_oidc",
    "protocol": "http",
    "endpoint": "rest",
    "useWso2": false
  },
  "jwks_uri": "http://imexsolutions143214.protheus.cloudtotvs.com.br/rest/api/oauth2/v1/jwks"
}
Bloco de código
languagejs
firstline1
titleExemplo de segundo envio após obter o JWKS_URI:
linenumberstrue
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNjZhOTNhODI1OGVlMTY2YTRhZjBlYzdjIiwic2V0X2lkIjoiNjZhOTM3ZTg2YTRiMjY1ZDEwY2FhMjFjIiwiY2xpZW50X2lkIjoiNjI3YWEyZjUzNDMwMDIwMDMxMGJmZDcyIiwiYXBwX2lkIjoiNjYzMGRiODViYWYwZTBjZmM4ODMyYmVkIiwib3JpZ2luIjoibW9iaWxlIiwidXR5cGUiOiJQcm94eVVzZXIiLCJ0dHlwZSI6ImEiLCJpYXQiOjE3MjQxNjI1OTUsImV4cCI6MTcyNDI2MjU5NSwiYXVkIjoibWluZ2xlIiwiaXNzIjoid2VidGVzdGluZzogTGludXggeDg2XzY0In0.5K5hPFYHG_iwpYQ8MY7v-I0HIwE7oSBTA_SUtk3gKKY",
  "muser": {"_id": "66a93a8258ee166a4af0ec7c","login": "[email protected]"},
  "set": {"_id": "66a937e86a4b265d10caa21c","alias": "PREFIX SUFIX"},
  "params_values": [],
  "client": {"_id": "627aa2f534300200310bfd72","name": "TOTVS"},
  "wso2": {},
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNjZhOTNhODI1OGVlMTY2YTRhZjBlYzdjIiwic2V0X2lkIjoiNjZhOTM3ZTg2YTRiMjY1ZDEwY2FhMjFjIiwiY2xpZW50X2lkIjoiNjI3YWEyZjUzNDMwMDIwMDMxMGJmZDcyIiwiYXBwX2lkIjoiNjYzMGRiODViYWYwZTBjZmM4ODMyYmVkIiwib3JpZ2luIjoibW9iaWxlIiwidXR5cGUiOiJQcm94eVVzZXIiLCJ0dHlwZSI6InIiLCJpYXQiOjE3MjQxNjI1OTUsImV4cCI6MTcyNDI2MjU5NSwiYXVkIjoibWluZ2xlIiwiaXNzIjoid2VidGVzdGluZzogTGludXggeDg2XzY0In0.MelJuzSl0CNbahysx-now0KBKT2Hu15EhdHSLxC6jO8",
  "auth_driver": "protheus_oidc"
}


A chave access_token é armazenada no storage do navegador pelo mingleService para ser utilizada em outras etapas do aplicativo que requerem comprovação de autenticação, como por exemplo uma chamada de gateway. O access_token tem um prazo de validade de acordo com cada ambiente e requer uma nova autenticação quando expirar. 

Quando se utiliza um access_token expirado, o Mingle retornará para o aplicativo o status 401 do protocolo HTTP.

O desenvolvedor pode seguir dois caminhos para obter um novo access_token:

1- Solicitar ao usuário do aplicativo um novo login.

2- Utilizar a chave refresh_token obtida no login inicial e realizar uma autenticação transparente para o usuário, sem que ele tenha que realizar login novamente. 




Refresh Token

Para obter os dados de autenticação atualizados, você pode utilizar o serviço Refresh Token do Mingle.

Considere o código de exemplo abaixo:

Bloco de código
languagejs
firstline1
titleRefresh Token
linenumberstrue
 refreshToken(){
    const bodyRefreshToken = this.mingleService.getBodyToRefreshTokenAPI();
    const urlRefreshTOken = this.mingleService.getRefreshTokenURL();
    
    this.http.post(urlRefreshTOken, bodyRefreshToken).subscribe(resultAuth => console.log(resultAuth))
  }

O MingleService prepara o body que deve ser enviado para o serviço Refresh Token através do método mingleService.getBodyToRefreshTokenAPI();

Logo após obter o body que deve ser enviado para o Mingle, obtenha a URL do serviço através do método mingleService.getRefreshTokenURL();

E para obter os novos dados de autenticação, realize um POST com os parâmetros encontrados anteriormente. 



LOGOUT

Para realizar o logout utilize o nosso método mingleService.auth.logout();

Bloco de código
languagejs
firstline1
titleLogout
linenumberstrue
this.mingleService.auth.logout().subscribe(() => {
     console.log("Usuário deslogado");
     this.route.navigate(['login']);
})


CHANGEPWDPROTHEUS

Para realizar a troca de senha da API Protheus conforme documentação (https://tdn.totvs.com/display/public/framework/Troca+de+senha+no+REST+2.0), utilize nosso método mingleService.auth.changePwdProtheus();


Bloco de código
languagejs
firstline1
titleCHANGEPWDPROTHEUS
linenumberstrue
this.mingleService.auth.changePwdProtheus(event.currentPassword, event.newPassword).subscribe((response) =>{
      if (response.status === 201) {
		console.log("Troca realizada com sucesso");
        this.route.navigate(['login']);
      	}
    })  




PASSWORDRECOVERY

Para realizar a recuperação de senha via API cadastrada no APP, utilize nosso método mingleService.auth.passwordRecovery();

No BODY da solicitação, devem constar as informações obrigatórias do APP_ID, ALIAS e USERLOGIN. Quanto ao restante do BODY da requisição, este será passado conforme as necessidades específicas da API cadastrada no aplicativo, uma vez que o BODY da requisição é repassado diretamente para a API.

Este método estará disponível apenas para hosts que utilizam o usuário integrador.

Bloco de código
languagejs
firstline1
titlePASSWORDRECOVERY
linenumberstrue
const body = {
    			app_id: "6l51a56po975de0028e0oae7",
    			alias: "PREFIX SUFIX",
    			userLogin: "customer.testcase",
			 }

this.mingleService.auth.passwordRecovery(body).subscribe((response) => {
    if (response.status === 201) {
        console.log("Recuperação de Senha realizada com sucesso");
        this.route.navigate(['login']);
    	}
	})

Expandir
title5- Gateway

O Mingle tem o serviço API Gateway para produtos que precisam de exposição de API para internet, garantindo canal único de liberação da rede do cliente para a nuvem e a segurança de não precisar expor o endereço completo do servidor do cliente. 

Nesta etapa você será capaz de realizar requisições ao servidor usando a segurança e simplicidade do mingleService.


Vamos imaginar que você desenvolvedor precise criar uma funcionalidade que busque uma lista de produtos do seu backend através do endereço  

http://servidor-exemplo.com.br/listaProdutos


Com o Mingle Gateway, você não precisa comprometer a segurança do seu host ao informar o endereço rest completo, basta informar o endpoint desejado.

Veja o bloco de código abaixo: 

Bloco de código
languagejs
firstline1
titleGateway GET
linenumberstrue
getProducts() {
   return this.mingleService.gateway.get('listaProdutos').subscribe(response => {
     return JSON.stringify(response);
   }, error => {
	console.error("Error in gateway endpoint 'listaProdutos'");
     return error ;
   }
   );
}

Dessa forma o resultado do endereço para o request é "https://dev-mingle.totvs.com.br/listaProdutos" e através do seu ALIAS o Mingle identifica qual é o endereço final do servidor para realizar a chamada GET no endpoint listaProdutos. 

Ao utilizar a classe mingleService.gateway você substitui o request http padrão do typescript e garante a segurança da informação.

O Mingle aceita apenas requisições com conteúdo JSON, objeto ou formData no body.


Headers customizados

É possível enviar headers customizados de acordo com a sua implementação para o seu host.

Neste exemplo, vamos adicionar o header "x-totvs-header-customizado" ao request:

Bloco de código
languagejs
firstline1
titleHeaders Customizados
linenumberstrue
getProducts() {
   const options = {headers: {"x-totvs-header-customizado": "123456"}};
 
return this.mingleService.gateway.get('listaProdutos', options).subscribe(response=>{
     return JSON.stringify(response);
   }, error => {
     console.error("Error in gateway endpoint 'listaProdutos'");
     return error ;
   })
}



Query Params customizados

É possível enviar queryParams customizados de acordo com a sua implementação para o seu host.

Neste exemplo, vamos adicionar o queryParams "filial e id" ao request, conforme exemplo abaixo:

Bloco de código
languagejs
firstline1
titleHeaders Customizados
linenumberstrue
getProducts() {
   const queryParams = { "filial": "D MG", "id": "FIN501" }; 

return this.mingleService.gateway.get('listaProdutos', {}, queryParams).subscribe(response=>{
     return JSON.stringify(response);
   }, error => {
     console.error("Error in gateway endpoint 'listaProdutos'");
     return error ;
   })
}




Classe mingleService.Gateway

A classe mingleService.gateway está pronta para realizar as seguintes ações:

Os métodos get, post,put, delete e patch são responsáveis pela comunicação http entre o aplicativo e o servidor do Mingle conforme apresentado nos tópicos anteriores desse documento. 

O método getHeaders retorna os headers padrões do MingleService.

O método getUrl retorna a URL padrão do MingleService. 

Envio de arquivos

Para saber mais sobre envio de arquivos com o gateway do Mingle, acesse: Transferência de arquivos



Expandir
title6- Registrar métricas

Com o registro de métricas personalizadas, você pode registrar os comportamentos da sua aplicação. 

Informações
titleAtenção

 Aplicações desenvolvidas com o framework IONIC: 

Para o registro de métricas funcionar corretamente você deve executar a instalação dos plugins MIngle-ionic: Mingle Ionic GeolocationMingle Ionic Device.

Consulte a documentação Pacote @totvs/mingle na plataforma Ionic para maiores detalhes.

Uma função core do Mingle é permitir que o app registre métricas de uso de suas funcionalidades, como por exemplo, quando o app é inicializado automaticamente é registrada uma métrica com uma série de informações sobre este evento. Todas essas métricas podem ser consultadas no portal do Mingle na sessão Monitor > Métricas de Uso.

As métricas podem ser de dois tipos:

  • Métricas identificadas: são aquelas que registram o usuário que está autenticado no app no momento do registro, e por definição só serão possíveis com a existência desse usuário autenticado.

  • Métricas anônimas: podem ser registradas sem a necessidade de um usuário autenticado.

Toda métrica contém as seguintes informações:

  • Tipo: tipo da métrica gerada.
  • Aplicativo: identificador do aplicativo.
  • Dispositivo: identificador do dispositivo.
  • Data: data no formato da RFC2822.
  • Local (opcional): coordenadas (latitude x longitude).
  • Set (opcional): identificador do set cadastrado.
  • Cliente (opcional): identificador do cliente cadastrado.
  • Usuário (opcional): identificador do usuário.
  • Identificador da execução: identificador da execução, muda a cada nova execução do aplicativo, o que permite filtrar cada jornada do usuário dentro dele.

Os campos usuário, cliente e set são opcionais justamente nas métricas anônimas, já o local pode ou não existir caso o app não envie essa informação (exemplo: GPS desabilitado)

Além desses campos, cada métrica pode, arbitrariamente, armazenar informações customizadas de acordo com a necessidade do aplicativo, implementação útil para futuros relatórios e controles de logs.


Utilizando a classe MingleService da biblioteca, implemente o seguinte trecho de código na sua aplicação para gerar métricas personalizadas. 

Bloco de código
languagejs
firstline1
titleMétricas
linenumberstrue
this.mingleService.registerMetric('Métrica personalizada', {Valor: "10"});

A string 'Métrica personalizada'  é uma ilustração para este exemplo, podendo ser alterada para o nome que for mais adequado para o seu aplicativo. 



Product_title
Title Veja Também
Image: )




Button
Cor#00CED1
TextoTransferência de arquivos
Linkhttps://tdn.totvs.com/pages/viewpage.action?pageId=594156585

Button
Cor#00CED1
TextoConfigurar default headers
Linkhttps://tdn.totvs.com/display/MIN/Configurar+default+headers

Button
Cor#00CED1
TextoMétodos @totvs/mingle
Linkhttps://tdn.totvs.com/pages/viewpage.action?pageId=605012146

Button
Cor#00CED1
TextoPacote @totvs/mingle na plataforma Ionic
Linkhttps://tdn.totvs.com/pages/viewpage.action?pageId=605010214

Button
Cor#00CED1
TextoCodificações de caracteres suportados pelo Mingle (charset)
Linkhttps://tdn.totvs.com/pages/viewpage.action?pageId=651945582