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:
Modulo | Descrizione | Suggerimento 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-App | Se 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
- Per i dettagli, consultare la documentazione:
SDK utenti lato 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>
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) owww.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:
javascriptprivate 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:
- Creazione e invio degli ordini dal client.
- Per i dettagli, consultare la documentazione:
SDK acquisti In-App 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 Campo Tipo Obbligatorio Descrizione Authorization string Sì Header di verifica, sha1(body+chiave), dove la chiave è la chiave condivisa del gioco Corpo della richiesta:
Campo Tipo Obbligatorio Descrizione paytype String Sì Tipo notifica: pay = pagamento completato; refund = rimborso completato gameId int Sì ID gioco orderId String Sì Numero ordine arrivedStatus int Sì Stato consegna: 0 = non consegnato, 1 = consegnato productId String Sì ID prodotto createTime long Sì Timestamp creazione ordine (Unix) payTime long Sì Timestamp pagamento ordine (Unix) userId int Sì ID utente refundStatus int No Stato rimborso: 0 = in corso, 1 = riuscito, 2 = fallito, 3 = rifiutato refundTime long No Timestamp 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 mancante40001
Gioco non trovato41007
Verifica fallita500
Errore di sistema
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 Campo Tipo Obbligatorio Descrizione Authorization string Sì Header di verifica, sha1(body+chiave), dove la chiave è la chiave condivisa del gioco Corpo richiesta:
Campo Tipo Obbligatorio Descrizione gameId int Sì ID gioco orderId int Sì Numero ordine Esempio corpo richiesta:
javascript{ "gameId": 9943, "orderId":"gHpGwweTlucXwcM6yIeSMcgKkhFmoO" }
Risposta JSON (code:200 = successo):
json{ "code": "200", "msg": "Success" }
Codici errore:
305
Parametro obbligatorio mancante40001
Gioco non trovato41007
Verifica fallita500
Errore di sistema
3. Il server del gioco consulta la lista ordini per sincronizzare lo stato consegna
URL richiesta: [POST] https://api.jogos.com/api/gamepay/getOrders
Header richiesta:
Nome Campo Tipo Obbligatorio Descrizione Authorization string Sì Header di verifica, sha1(body+chiave), dove la chiave è la chiave condiv
isa del gioco |
Corpo richiesta:
Campo Tipo Obbligatorio Descrizione gameId int Sì ID gioco pageNo int Sì Numero pagina pageSize int Sì Numero elementi per pagina Esempio corpo richiesta:
javascript{ "gameId": 9943, "pageNo":1, "pageSize":20 }
Risposta JSON (code:200 = successo):
Campo Tipo Obbligatorio Descrizione code String Sì Codice stato (es: SUCCESS) message String Sì Messaggio (es: Logout riuscito) total Integer Sì Totale pageSize Integer Sì Numero elementi per pagina currentPage Integer Sì Pagina corrente totalPage Integer Sì Numero totale pagine orderId String Sì Numero ordine arrivedStatus Integer Sì Stato consegna: 0 = non consegnato, 1 = consegnato payTime long Sì Timestamp pagamento (Unix) productId String Sì ID prodotto userId Integer Sì ID utente refundStatus Integer No Stato rimborso: 0 = in corso, 1 = riuscito, 2 = fallito, 3 = rifiutato refundTime long No Timestamp 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 mancante40001
Gioco non trovato41007
Verifica fallita500
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.