Skip to content

Descrição da Conexão do Lado do Servidor

Se o seu jogo possui um servidor próprio e os dados dos jogadores são armazenados e gerenciados por ele, você precisará estabelecer a conexão do lado do servidor da seguinte forma:

MóduloDescriçãoObservações sobre Conexão
Sistema de UsuáriosVocê precisa vincular o sistema de usuários da plataforma Jogos aos usuários no seu servidor. É necessário conectar o sistema de usuários do lado do servidor☑️ Conexão obrigatória
Sistema de Compras In-AppSe o seu jogo possui compras dentro do aplicativo, é necessário conectar o sistema de compras da Jogos para garantir a segurança dos pagamentos e dados do usuário☑️ Jogos com compras in-app devem conectar

Conexão do Sistema de Usuários

1 Obter o token do usuário do lado do cliente

2 Visão Geral

Após receber o token e a publickey da Jogos, envie-os de volta ao servidor do jogo para validar e obter os dados do usuário. Observe que cada verificação de token deve obter a publickey novamente, pois ela pode mudar a qualquer momento.

3 Lógica de Verificação

  • O desenvolvedor do jogo recebe o token da Jogos e envia para o seu servidor.
  • O servidor obtém a publickey (dehttps://www.jogos.com/publicKey.json)
  • Use a publickey em Base64 para criar a chave pública RSA.
  • Use a chave pública RSA para decodificar o token JWT. Você pode verificar o resultado do token decodificado em jwt.io
  • Após a decodificação, obtenha os dados do usuário e vincule ao usuário no servidor do jogo.
  • Se a decodificação falhar, retorne os dados do usuário como nulos.

4 Exemplo de Código

  Adicione JWT ao seu projeto:
  <!--JWT-->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.2</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.2</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.2</version>
    </dependency>
java
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Map;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import com.alibaba.fastjson.JSONObject;

public class JwtUtils {

	
	public static void main(String[] args) {
		/**
		 * Obtenha a publickey e o token do usuário do SDK da Jogos e envie para o servidor.
		  
		  Exemplo de publickey:
		  
		  -----BEGIN PUBLIC KEY-----
		  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhyUrr/W8bSuC+HK8Rk++BDOGDefGMEBa9jekVwVE3oeqi7QbVzZPAuqb1K3GPJjDBfi44IWzb3w8Xa0P1ZeO2Cnbg1LltanlzFv/EcKseCIkOd8Qo78ARPfmlf4WP6MznYGKwNVGFh/s5Y6ar8QgWX1ttkcwYzHu/gUroO+nPOZkU6bfxHjRrJxk3lSQBZWfTSFd2JFwntq3h45UHymjQZiMtW47G2C4VTtTTt1Iz0VQ9rdtWie/+REqQYoFUm04Yns9jyG3TZzio9vsRrxESLQbBIRxto77cQNtEe9j/2EXNwQabRkiS6zo6i2TIN4O6uthWBVud5WXsBWdiyIOHQIDAQAB
		  -----END PUBLIC KEY-----

		E token do usuário:
		  eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIxOTY3NDIzNTM3NjE1NTgxMTg0Iiwic3ViIjoie1wicHJvZmlsZVBpY3R1cmVVcmxcIjpcImh0dHBzOi8vaW1hZ2Uuam9nb3NwcmUuY29tLzBlZTkyZjViZTRhMzQ4NzBhYjY0YWU1N2FjN2I1YmE0LmpwZ1wiLFwiZ2FtZUlkXCI6XCIxMjIwXCIsXCJ1c2VySWRcIjpcIjI1N1wiLFwidXNlcm5hbWVcIjpcIlBsYXllcjI1N1wifSIsImlzcyI6ImNvbTpqb2dvczpzZGsiLCJpYXQiOjE3NTc5MDUyOTgsImV4cCI6MTc2MTUwNTI5OH0.MKBab0XC1o5AYGosbq1l5m9xCLN1-4xfcr7_dHn-_C8Eh2moTuq9TbQutIajB3dViFW0e1KyIg7UhxNk00rdhT2b5UrvO23tyFsgg9FYyAyCZABURxHyI0lTW9V8YA9k4faycK_gCUMXH_IubseDMz1P7cYmPpo8WxJXZq3R-mL8OhhuKCn8DlpP5BVsd0_gYSTvDUD0gjdINLUNTVrZVkETcDVWW8OXQVzJxdTH0VVlDs4cGvIyko8TJ6g1Bvz4VWj4qy1XoQFfRBH8sgBl3oGJtUodhq3b4bOx4Cr_o-2tK54CetDdmmCPbtcbmmDcBqK5EQ51A2Kws-1cYtsFxg
		     
		  Observação: Cada verificação de token deve obter a publickey novamente, pois ela pode mudar.
		 */
		
		String publickey ="sua publickey";
		String token = "token do usuário";
		
		System.out.println("publickey:["+publickey+"]");
		System.out.println("token:["+token+"]");
		Map<String, Object> userMap = verifyToken(token,publickey);
		// Se a verificação do token for bem-sucedida, userMap não será nulo
        if (userMap != null) {
        	System.out.println("Verificação bem-sucedida, dados do usuário:");
        	System.out.println(JSONObject.toJSONString(userMap));
        }else {
        	System.out.println("Falha na verificação JWT");
        }
	}
	
	
	/**
	 * Verifica o token
	 * @param token
	 * @return
	 */
	public static Map<String, Object> verifyToken(String token,String publickey){  
		
		// Tenta decodificar o token, retorna null se falhar
		Map<String, Object> map = null;
        try {
        	map = parseToken(token,publickey);
        } catch (Exception e) {
            
        }
        return map;
         
    }
	
	/**
	 * Decodifica o token
	 * @param token
	 * @return
	 */
	public static Map<String,Object> parseToken(String token,String publickey){
		// Remove cabeçalho e rodapé
		if(publickey.startsWith("-----BEGIN PUBLIC KEY-----")) {
			publickey = publickey.substring(27,publickey.length()-25);
		}
		Claims claims = (Claims) Jwts.parser()
	                .setSigningKey(getPublicKey(publickey))
	                .parse(token)
	                .getBody();
        String parseToken = claims.getSubject();
        
        if (parseToken != null) {
        	Map<String, Object> map = JSONObject.parseObject(parseToken, Map.class);
			return map;
        }
        return null;
    }
	
	 /**
     * Converte Base64 string em chave pública RSA
     * @param key string Base64 da chave pública
     * @return chave pública RSA
     * <p>
     * Observação: Este método decodifica a string em bytes e usa KeyFactory e X509EncodedKeySpec para gerar a PublicKey
     */
    private static PublicKey getPublicKey(String key) {
        byte[] decode = Base64.getDecoder().decode(key);
        PublicKey publicKey;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decode);
            publicKey = keyFactory.generatePublic(keySpec);
        } catch (Exception e) {
 
            throw new RuntimeException(e);
        }
        return publicKey;
    }
}

Conexão do Sistema de Compras In-App

Antes de iniciar a conexão, confirme:

  • Você está usando www.jogospre.com (ambiente de teste) ou www.jogos.com (ambiente real); O URL do POST abaixo deve corresponder ao ambiente correto (Exemplo de API teste: https://api.jogospre.com/api/gamepay/webhook/arrivedorder)

  • Verifique se você criou o jogo na Developer Platform e gerou a Shared Key do jogo em “Game Parameters”

  • Verifique se selecionou o modo “In-App Purchase” e definiu o Callback URL do seu servidor

  • A comunicação utiliza SHA-1 para verificação, exemplo de código:

    javascript
    private String sha1(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] hashInBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
    
            StringBuilder sb = new StringBuilder();
            for (byte b : hashInBytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Algoritmo SHA-1 não encontrado", e);
        }
    }

Conexão do lado cliente:

Conexão do lado servidor:

1. Quando o usuário compra com sucesso, Jogos envia callback de pagamento

  • Jogos envia callback para o Callback URL configurado

  • Header do request:

    CampoTipoObrigatórioDescrição
    AuthorizationstringSimHeader para verificar sha1(body+SecretKey), sendo Shared Key do jogo
  • Corpo do Request:

    CampoTipoObrigatórioDescrição
    paytypeStringSimTipo de notificação: pay (pagamento concluído) / refund (reembolso concluído)
    gameIdintSimID do jogo
    orderIdStringSimNúmero da ordem
    arrivedStatusintSimStatus de entrega: 0 não entregue, 1 entregue
    productIdStringSimID do produto
    createTimelongSimHorário de criação da ordem (Unix timestamp)
    payTimelongSimHorário do pagamento concluído (Unix timestamp)
    userIdintSimID do usuário
    refundStatusintOpcionalStatus do reembolso: 0 em processamento, 1 concluído, 2 falhou, 3 rejeitado
    refundTimelongOpcionalHorário do reembolso (Unix timestamp)

    Exemplo:

    javascript
    {
        "gameId"9968,
        "orderId""zXhKYRy3genKKh9TgndBpu1gp5tBpA",
        "arrivedStatus"0,
        "productId""1002",
        "createTime"1755657098,
        "payTime"1755657115,
        "userId"278,
        "refundStatus"null,
        "refundTime"null
    }
  • Response JSON (code:200 = sucesso)

    json
    {
        "code""200",
        "msg""Success"
    }
  • Códigos de erro:

    • 305 parâmetros obrigatórios ausentes
    • 40001 jogo não encontrado
    • 41007 verificação falhou
    • 500 erro do sistema
    *Aviso*
    • Se o servidor não retornar 200, a plataforma tentará reenviar várias vezes em até 3 horas, máximo 5 tentativas.
    • Sempre verifique os parâmetros assim:
    javascript
    public boolean verifySignature(String body, String authorizationHeader) throws Exception
    {
        if (authorizationHeader == null || !authorizationHeader.startsWith("Signature "))
        {
            throw new Exception("Header \"Authorization\" não encontrado ou inválido no webhook da Jogos.");
        }
    
        String clientSignature = authorizationHeader.substring(10); // remove "Signature "
        String serverSignature = sha1(body + your_key);//your_key é a Shared Key do jogo
    
        return clientSignature.equals(serverSignature);
    }

2. Após a entrega do produto pelo servidor do jogo, atualize o status de entrega

  • URL: [POST] https://api.jogos.com/api/gamepay/webhook/arrivedorder

  • Header:

    CampoTipoObrigatórioDescrição
    AuthorizationstringSimHeader para verificar sha1(body+SecretKey), sendo Shared Key do jogo
  • Corpo do Request:

    CampoTipoObrigatórioDescrição
    gameIdintSimID do jogo
    orderIdintSimNúmero da ordem
  • Response JSON (code:200 = sucesso)

    json
    {
        "code""200",
        "msg""Success"
    }
  • Códigos de erro:

    • 305 parâmetros obrigatórios ausentes
    • 40001 jogo não encontrado
    • 41007 verificação falhou
    • 500 erro do sistema