Skip to content

Descrizione delle API di integrazione lato server

Se il tuo gioco dispone di un proprio server di gioco e i dati dei giocatori sono salvati e gestiti dal tuo server, è necessario un'integrazione lato server:

ModuloDescrizioneSuggerimento di integrazione
Sistema UtenteÈ necessario collegare il sistema utenti di Jogos con gli utenti del tuo server. Richiede integrazione lato server☑️ Integrazione necessaria
Sistema Acquisti In-AppSe il tuo gioco ha oggetti acquistabili, è necessario integrare il sistema acquisti di Jogos per garantire la sicurezza dei pagamenti e dei dati degli utenti☑️ Necessario per giochi con acquisti In-App

Integrazione del sistema utenti

1 Ottenere il token utente dal client

2 Panoramica

Dopo aver ottenuto il token utente e la publickey da Jogos, inviarli al server di gioco per la verifica e ottenere le informazioni dell'utente. Nota: ogni volta che si verifica il token, recuperare la publickey perché può cambiare in qualsiasi momento.

3 Logica di verifica

  • Lo sviluppatore del gioco riceve il token utente da Jogos e lo invia al server del gioco.
  • Il server ottiene la publickey tramite https://www.jogos.com/publicKey.json
  • Ottenere la chiave RSA dalla stringa Base64 della publickey.
  • Decifrare il token JWT usando la chiave RSA. Il token decifrato può essere testato su jwt.io
  • Dopo la decodifica, ottenere le informazioni utente e collegarle agli utenti del tuo server di gioco.
  • Se la decodifica fallisce, restituire informazioni utente vuote.

4 Esempio di codice

  Importare JWT nel progetto:
  <!--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) {
		/**
		 * Ottenere publickey e token utente dallo SDK Jogos e inviarli al server, ad esempio la seguente publickey:
		  
		  -----BEGIN PUBLIC KEY-----
		  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhyUrr/W8bSuC+HK8Rk++BDOGDefGMEBa9jekVwVE3oeqi7QbVzZPAuqb1K3GPJjDBfi44IWzb3w8Xa0P1ZeO2Cnbg1LltanlzFv/EcKseCIkOd8Qo78ARPfmlf4WP6MznYGKwNVGFh/s5Y6ar8QgWX1ttkcwYzHu/gUroO+nPOZkU6bfxHjRrJxk3lSQBZWfTSFd2JFwntq3h45UHymjQZiMtW47G2C4VTtTTt1Iz0VQ9rdtWie/+REqQYoFUm04Yns9jyG3TZzio9vsRrxESLQbBIRxto77cQNtEe9j/2EXNwQabRkiS6zo6i2TIN4O6uthWBVud5WXsBWdiyIOHQIDAQAB
		  -----END PUBLIC KEY-----

		e il token utente:
		  eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIxOTY3NDIzNTM3NjE1NTgxMTg0Iiwic3ViIjoie1wicHJvZmlsZVBpY3R1cmVVcmxcIjpcImh0dHBzOi8vaW1hZ2Uuam9nb3NwcmUuY29tLzBlZTkyZjViZTRhMzQ4NzBhYjY0YWU1N2FjN2I1YmE0LmpwZ1wiLFwiZ2FtZUlkXCI6XCIxMjIwXCIsXCJ1c2VySWRcIjpcIjI1N1wiLFwidXNlcm5hbWVcIjpcIlBsYXllcjI1N1wifSIsImlzcyI6ImNvbTpqb2dvczpzZGsiLCJpYXQiOjE3NTc5MDUyOTgsImV4cCI6MTc2MTUwNTI5OH0.MKBab0XC1o5AYGosbq1l5m9xCLN1-4xfcr7_dHn-_C8Eh2moTuq9TbQutIajB3dViFW0e1KyIg7UhxNk00rdhT2b5UrvO23tyFsgg9FYyAyCZABURxHyI0lTW9V8YA9k4faycK_gCUMXH_IubseDMz1P7cYmPpo8WxJXZq3R-mL8OhhuKCn8DlpP5BVsd0_gYSTvDUD0gjdINLUNTVrZVkETcDVWW8OXQVzJxdTH0VVlDs4cGvIyko8TJ6g1Bvz4VWj4qy1XoQFfRBH8sgBl3oGJtUodhq3b4bOx4Cr_o-2tK54CetDdmmCPbtcbmmDcBqK5EQ51A2Kws-1cYtsFxg
		     
		  Nota: ogni volta che si verifica il token, recuperare la publickey perché potrebbe cambiare  
		 */
		
		String publickey ="La tua publickey";
		String token = "Il tuo token utente";
		
		System.out.println("publickey:["+publickey+"]");
		System.out.println("token:["+token+"]");
		Map<String, Object> userMap = verifyToken(token,publickey);
		// Se il token viene decifrato correttamente, userMap non sarà nullo
        if (userMap != null) {
        	System.out.println("Verifica riuscita, informazioni utente:");
        	System.out.println(JSONObject.toJSONString(userMap));
        }else {
        	System.out.println("Verifica JWT fallita");
        }
	}
	
	
	/**
	 * Verifica token
	 * @param token
	 * @return
	 */
	public static Map<String, Object> verifyToken(String token,String publickey){  
		
		// Prova a decodificare il token, se fallisce restituisce null
		Map<String, Object> map = null;
        try {
        	map = parseToken(token,publickey);
        } catch (Exception e) {
            
        }
        return map;
         
    }
	
	/**
	 * Decodifica token
	 * @param token
	 * @return
	 */
	public static Map<String,Object> parseToken(String token,String publickey){
		// Rimuove la parte iniziale e finale 
		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;
    }
	
	 /**
     * Ottiene la chiave RSA dalla stringa codificata in Base64
     * @param key stringa della chiave pubblica codificata Base64
     * @return chiave RSA convertita
     * <p>
     * Nota: il metodo decodifica la stringa in byte array, poi usa KeyFactory e X509EncodedKeySpec
     * per convertire i byte in oggetto PublicKey. Se avviene un errore, viene sollevata un'eccezione RuntimeException.
     */
    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;
    }
}

Integrazione del sistema Acquisti In-App

Prima di iniziare, confermare:

  • Stai utilizzando www.jogospre.com (ambiente di test) o www.jogos.com (ambiente di produzione); gli URL POST seguenti devono essere modificati con l'indirizzo corretto. (Esempio: API test per ordini arrivati: https://api.jogospre.com/api/gamepay/webhook/arrivedorder)

  • Assicurati di aver creato l'applicazione gioco sulla piattaforma sviluppatori e di aver generato la chiave condivisa nei parametri del gioco.

  • Assicurati che l'opzione "Usa acquisti In-App" sia selezionata e che l'indirizzo di callback del server sia impostato.

  • La comunicazione utilizza SHA-1, esempio di utilizzo:

    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("SHA-1 algorithm is not available", e);
        }
    }

Integrazione lato client:

Integrazione lato server:

1. Dopo l'acquisto riuscito, Jogos invia la notifica di pagamento completato

  • Jogos invierà un callback al tuo URL di callback configurato

  • Header della richiesta:

    Nome CampoTipoObbligatorioDescrizione
    AuthorizationstringHeader di verifica, sha1(body+chiave), dove la chiave è la chiave condivisa del gioco
  • Corpo della richiesta:

    CampoTipoObbligatorioDescrizione
    paytypeStringTipo notifica: pay = pagamento completato; refund = rimborso completato
    gameIdintID gioco
    orderIdStringNumero ordine
    arrivedStatusintStato consegna: 0 = non consegnato, 1 = consegnato
    productIdStringID prodotto
    createTimelongTimestamp creazione ordine (Unix)
    payTimelongTimestamp pagamento ordine (Unix)
    userIdintID utente
    refundStatusintNoStato rimborso: 0 = in corso, 1 = riuscito, 2 = fallito, 3 = rifiutato
    refundTimelongNoTimestamp rimborso (Unix), presente se avvenuto

    Esempio corpo richiesta:

    javascript
    {
        "gameId"9968,
        "orderId""zXhKYRy3genKKh9TgndBpu1gp5tBpA",
        "arrivedStatus"0,
        "productId""1002",
        "createTime"1755657098,
        "payTime"1755657115,
        "userId"278,
        "refundStatus"null,
        "refundTime"null
    }
    • Risposta JSON (code:200 = successo):
    json
    {
        "code""200",
        "msg""Success"
    }
  • Codici errore:

    • 305 Parametro obbligatorio mancante
    • 40001 Gioco non trovato
    • 41007 Verifica fallita
    • 500 Errore di sistema
    *Promemoria*
    • Se il server del gioco non restituisce 200, il servizio di pagamento ritenterà fino a 5 volte in 3 ore.
    • Quando si riceve il callback dal servizio di pagamento, verificare i parametri come segue:
    javascript
    public boolean verifySignature(String body, String authorizationHeader) throws Exception
    {
        if (authorizationHeader == null || !authorizationHeader.startsWith("Signature "))
        {
            throw new Exception("\"Authorization\" header not found or invalid in Jogos webhook request.");
        }
    
        String clientSignature = authorizationHeader.substring(10); // Skip "Signature "
        String serverSignature = sha1(body + your_key);//your_key è la chiave condivisa del gioco impostata nei parametri
    
        return clientSignature.equals(serverSignature);
    }

2. Dopo la consegna lato server, aggiornare lo stato ordine a "consegnato"

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

  • Header richiesta:

    Nome CampoTipoObbligatorioDescrizione
    AuthorizationstringHeader di verifica, sha1(body+chiave), dove la chiave è la chiave condivisa del gioco
  • Corpo richiesta:

    CampoTipoObbligatorioDescrizione
    gameIdintID gioco
    orderIdintNumero ordine

    Esempio corpo richiesta:

    javascript
    {
        "gameId"9943,
        "orderId":"gHpGwweTlucXwcM6yIeSMcgKkhFmoO"
    }
  • Risposta JSON (code:200 = successo):

    json
    {
        "code""200",
        "msg""Success"
    }
  • Codici errore:

    • 305 Parametro obbligatorio mancante
    • 40001 Gioco non trovato
    • 41007 Verifica fallita
    • 500 Errore di sistema

3. Il server del gioco consulta la lista ordini per sincronizzare lo stato consegna

isa del gioco |

  • Corpo richiesta:

    CampoTipoObbligatorioDescrizione
    gameIdintID gioco
    pageNointNumero pagina
    pageSizeintNumero elementi per pagina

    Esempio corpo richiesta:

    javascript
    {
        "gameId"9943,
        "pageNo":1
        "pageSize":20
    }
  • Risposta JSON (code:200 = successo):

    CampoTipoObbligatorioDescrizione
    codeStringCodice stato (es: SUCCESS)
    messageStringMessaggio (es: Logout riuscito)
    totalIntegerTotale
    pageSizeIntegerNumero elementi per pagina
    currentPageIntegerPagina corrente
    totalPageIntegerNumero totale pagine
    orderIdStringNumero ordine
    arrivedStatusIntegerStato consegna: 0 = non consegnato, 1 = consegnato
    payTimelongTimestamp pagamento (Unix)
    productIdStringID prodotto
    userIdIntegerID utente
    refundStatusIntegerNoStato rimborso: 0 = in corso, 1 = riuscito, 2 = fallito, 3 = rifiutato
    refundTimelongNoTimestamp rimborso (Unix), presente se avvenuto
    json
    {
      "code": "200",
      "msg": "Success",
      "page": {
        "total": 31,
        "totalPage": 7,
        "currentPage": 1,
        "pageSize": 5,
        "content": [
          {
            "orderId": "gHpGwweTlucXwcM6yIeSMcgKkhFmoO",
            "arrivedStatus": 1,
            "payTime": 1112211221,
            "productId": "game_pro1",
            "userId": 278,
            "refundStatus": null,
            "refundTime": null
          }
        ]
      }
    }
  • Codici errore:

    • 305 Parametro obbligatorio mancante
    • 40001 Gioco non trovato
    • 41007 Verifica fallita
    • 500 Errore di sistema

4. Quando l'utente effettua un rimborso, inviare notifica di rimborso completato al server del gioco

  • Jogos invierà il callback dell'ordine rimborsato al tuo URL di callback configurato
  • Il corpo della richiesta è uguale al punto 1 "Notifica pagamento completato"
  • Si consiglia di aggiornare o limitare eventuali oggetti ricompensa precedentemente ottenuti dall'utente tramite ricarica.