Tokenização

Permite substituir os dados de cartão de forma segura por um cartão virtual de uso controlado.

Feito para:  Estabelecimentos ComerciaisEmissoresAdquirentesFacilitadores

Como funciona

Primeiros passos

  1. Leia Introdução ao GraphQL, com exemplos reais da nossa API.

  2. Crie um usuário no portal do desenvolvedor.

  3. Cadastre sua primeira aplicação.

  4. Utilize o dashboard para acessar suas configurações de acesso.

  5. Para explorar rapidamente as APIs aqui na página de documentação, use o console de GraphQL, na seção de referências. Nele, você pode ver as consultas de exemplo, executá-las e alterá-las.

Primeiros passos na plataforma de Desenvolvedores Elo

Jaydson GomesDesenvolvedor Evangelista

O cartão físico que conhecemos, também referido como "cartão real", é composto pelo número (PAN - Primary Account Number), um código de segurança (CSC - Card Security Code) e data de validade. Com apenas estes dados é possível realizar compras e caso estes dados sejam copiados, podem gerar prejuízo ao portador, ao comerciante ou aos emissores.

Com o aumento das fraudes, criou-se o conceito de Token, que se comporta como um cartão virtual, na maioria das vezes tem um número (PAN), código de segurança (CSC) e data de validade que podem ser utilizados em sistemas legados de forma transparente. Com uma grande diferença: o Token pode ser parametrizado e ter um escopo de atuação reduzido, consequentemente eliminando ou reduzindo o potencial de fraudes.

Por exemplo, podemos Tokenizar (criar um Token) para um cartão real e especificar restrições de uso CardUsageConstraints:

  • Número de usos permitido. Por exemplo, maxUsage: 1 para um token que só pode ser utilizado uma única vez.

  • Data de expiração. Por exemplo, expiry: 2017-10-01 limita o uso do token a uma data específica, que pode ser diferente da validade do cartão real.

  • Limites de transação por moeda. Por exemplo, allowedTxAmount: [{currency: "USD", max: 100}] limitaria o token a transacionar no máximo USD$100.

  • Restrição de Comerciantes. Por exemplo, allowedIdCodes:[123, 456] permite o token ser utilizado em apenas dois lojistas, com identificadores 123 e 456.

  • Restrição de Categorias de Comerciantes. Por exemplo, allowedMerchantCategories para limitar o uso a apenas algumas categorias de comerciantes e deniedMerchantCategories para proibir categorias.

No caso de vazamento de dados, seja por perder um telefone celular ou hackers invadirem o servidor do comerciante, apenas o Token seria exposto e então limitado ao seu escopo de atuação.

O processo de Tokenização é util a diversas entidades:

  • Emissores (Bancos): integram com seus aplicativos e permitem o portador criar um Token, como para uso em lojas virtuais na qual o portador não confia;

  • Portadores: aplicativo da própria Elo ou terceiros poderiam criar Tokens para serem usados em compras. Um exemplo são aplicativos que fazem transações via NFC, Bluetooth ou QRCode, ao invés de divulgarem os dados do cartão real criam um token com escopo reduzido para o propósito da transação;

  • Comerciantes: ao invés de guardarem dados sensíveis do usuário em suas bases de dados, tornando-se alvo de hackers, o comerciante troca os dados sensíveis por um Token de uso exclusivo para si próprio (usageConstraints { allowedIdCodes: [1234] }), e se possível com mais restrições. Uma vez que seu servidor seja comprometido, os tokens não terão utilidade a terceiros e também poderão ser cancelados sem impactar o portador do cartão.

Para melhor segurança os dados sensíveis (PAN, CSC e data de validade) nunca são trafegados de forma aberta, mesmo que o transporte (HTTPS) seja seguro. Utilizamos JSON Web Encryption - JWE e JSON Web Signature - JWS da seguinte forma (pseudo código):

JWE.Encrypt(recipient=ChaveDoServidor, format=compact,
    JWS.Sign(issuer=ChaveDoUsuario, format=compact,
        JSON.Stringify(DadosSensiveis)
    )
)

Ao consultar dados sensíveis deve-se registrar a chave com o servidor e então enviar o identificador da chave, fazendo o processo reverso no valor retornado:

JSON.Parse(payload of
    JWS.Verify(payload of
        JWE.Decrypt(sensitive)
    )
)

Chaves

A chave pública do servidor (ChaveDoServidor) esta disponível a partir da consulta abaixo:

query {
    serverPublicKey {
        key
    }
}

Já as chaves públicas do usuário (i.e: referente à ChaveDoUsuario) deverão ser geradas nos dispositivos dos clientes e associadas ao usuário na plataforma atraves da mutation addPublicKeyToUser().

mutation {
    addPublicKeyToUser(input:{
        clientMutationId:"012", 
        userId:"bdc89491-f1f4-32f7-bad2-f44ae3b88aa6", 
        key:"{\"kty\":\"EC\", \"kid\":\"my-public-key-id-1\", \"x\":\"g_Sr4WwVDt5Qy3KonZyXqFwWykTR9KVMCt8Sx-dXSB8\",\"y\":\"ydSE-mUMtuhBTI_txDpd2ivb7e6FNzxq4e_18iHFZ2U\",\"crv\":\"P-256\"}",
        format:JWK
}) {
        clientMutationId, 
        user{
            id,
            firstName
            ,lastName
        }, 
        publicKey{
            key
        }
    }
}

Para a realização do processo de criação do token (e de todo o processo de tokenização), é necessário ter um usuário criado e tê-lo associado a um Comerciante, a um Emissor ou a um Portador de Cartão, de acordo com a operação que será feita, como descrito abaixo.

O token pode ser criado a partir de um cardId (id de cartão previamente cadastrado) ou dos dados sensiveis do cartão (PAN, CSC e data de validade) assinados e cifrados conforme a seção anterior.

Para criar um token a partir das informações de um cartão previamente cadastrado utilize o campo cardId na mutation createCardToken como demonstrado abaixo.

NOTA: Se você não possui o cardId do cartão cadastrado, é preciso consultá-lo ou cadastrá-lo utilizando a mutation createCard.

mutation {
  createCardToken(input: {
    cardId: "fd5c9b0a-5d2d-4b9a-957e-62c2415c0a0c", 
    tokenRequestorId: "00000000000", 
    origin: {
      ip: "200.123.1.2", 
      geolocation: {
        lat: 1.2345, 
        lon: -1.2345, 
        source: USER 
      }, 
      device: {
        userAgent: "Xpto", 
        brand: "Apple", 
        model: "iPhone 7", 
        type: SMARTPHONE
      }
    }, 
    usageConstraints: {
      maxUsage: 1, 
      allowedTxAmounts: [
        {
          currency: "BRL", 
          min: 10, 
          max: 1000
        }
      ]
    }
  }) 
  {
    cardToken {
      id
      last4
      expiry {
        month
        year
      }
    }
  }
}

Caso queira criar um cardToken a partir do sensitive de um cartão utilize o campo sensitive na mesma mutation createCardToken:

mutation {
  createCardToken(input: {
    sensitive: "dados sensiveis criptografados", 
    tokenRequestorId: "00000000000", 
    origin: {
      ip: "200.123.1.2", 
      geolocation: {
        lat: 1.2345, 
        lon: -1.2345, 
        source: CELLULAR
      }, 
      device: {
        userAgent: "Xpto", 
        brand: "Apple", 
        model: "iPhone 7", 
        type: SMARTPHONE
      }
    }, 
    usageConstraints: {
      maxUsage: 1, 
      allowedTxAmounts: [
        {
          currency: "BRL", 
          min: 10, 
          max: 1000
        }
      ]
    }
  }) 
  {
    cardToken {
      id
      last4
      expiry {
        month
        year
      }
    }
  }
}

O campo tokenRequestorId é obrigatório e identifica a bandeira de cartão, gateway de pagamento e Estabelecimento Comercial:

  • tokenRequestorId: os 3 primeiros dígitos identificam a bandeira, os próximos 3 dígitos identificam o gateway, e por fim, os últimos 5 dígitos identificam o Estabelecimento Comercial (Merchant).

Usuários CardIssuers ou Merchants muitas vezes precisam tokenizar cartões de outros usuários.
Para isto é possível utilizar a mutation CreateCardTokenForUser demonstrada a seguir:

mutation {
  createCardTokenForUser(input: {
    clientMutationId: "1334",
    sensitive: "dados sensiveis criptografados",  
    tokenRequestorId: "00000000000", 
    user: {
      name: "name", 
      legalIds: {
        cpf: "123456789", 
        rg: {
          number: "0978654322", 
          issuerOrganization: "SSP", 
          issuerState: "SP", 
          issueDate: "2018-04-24"
        }
      }, 
      birthday: "1993-08-09", 
      gender: MALE, 
      maritalStatus: SINGLE, 
      contacts: {
        type: PHONE, 
        context: "context", 
        value: "+5527999365103"
      }
    }, 
    origin: {
      ip: "200.123.1.2", 
      geolocation: {
        lat: 1.2345, 
        lon: -1.2345, 
        source: CELLULAR
      }, 
      device: {
        userAgent: "Xpto", 
        brand: "Apple", 
        model: "iPhone 7", 
        type: SMARTPHONE
      }
    }, 
    usageConstraints: {
      maxUsage: 1, 
      allowedTxAmounts: [
        {
          currency: "BRL", 
          min: 10, 
          max: 1000
        }
      ]
    }
  }) 
  {
    cardToken {
      id
      last4
      expiry {
        month
        year
      }
    }
  }
}

Esta mutation se difere das mutations acima em apenas um campo:

  • user Objeto com dados cadastrais do usuário do cartão tokenizado (name, address, contacts, legalIds, etc).

Caso o Token não seja mais necessário ou tenha sido comprometido, deve-se suspendê-lo:

mutation {
  suspendCardToken(input: {
    cardTokenId: "67F47F96-3D36-4199-8C7E-67ADC6DEC58C", 
    permanent: true, 
    reason: ISSUER
  }) 
  {
    cardToken {
      id
    }
  }
}

Um Token suspendido com a mutation acima pode ser ativado novamente:

mutation {
  activateCardToken(input: {
    clientMutationId: "123", 
    cardTokenId: "c7d555e0-b86e-4994-9ee9-79891d42cb05"
  }) 
  {
    cardToken {
      id
    }
  }
}

NOTA: para suspendCardToken e activateCardToken os dados sensíveis e o identificador global único são referências ao Token e não ao cartão real o qual foi utilizado em createCardToken!

Existem casos onde é necessário atualizar o cartão original relacioando ao token, pois o mesmo pode ter sido cancelado por algum motivo e trocado por um cartão novo. Logo, para não perder os tokens que já foram criados para o cartão antigo, é necessário atualizar o cartão original dos tokens.

Para isso, deve-se utilizar a mutation updateCardOriginToToken, enviando os dados sensíveis originais do cartão, e os novos dados sensíveis, contendo as informações atualizadas:

mutation {
  updateCardOriginToToken(input: {
    clientMutationId: "123", 
    cardOriginToTokens: {
      updateCardOriginId: "326f7e99-17af-44c8-82ca-848eab4fac89", 
      sensitiveCurrent: "dados sensiveis criptografados", 
      sensitiveNew: "dados sensiveis criptografados"
    }
  }) 
  {
    cardOriginToTokens {
      bin {
        number
      }
      last4
    }
  }
}

Nessa mutation, sensitiveCurrent contém os dados sensíveis do cartão original que foi tokenizado, enquanto sensitiveNew contém as novas informações atualizadas.