Skip to content

Serverseitige Integrationsschnittstellen

Wenn Ihr Spiel über einen eigenen Spielserver verfügt und die Spieldaten der Spieler auf Ihrem Server gespeichert und verwaltet werden, ist eine serverseitige Integration erforderlich:

ModulBeschreibungIntegrationsvorschlag
BenutzersystemSie müssen das Jogos-Benutzersystem mit den Benutzern Ihres Servers verbinden. Dies erfordert eine serverseitige Integration des Benutzersystems☑️ Notwendige Integration
In-App-Kauf-SystemIhr Spiel enthält In-App-Käufe, daher ist die Integration des Jogos-In-App-Kauf-Systems erforderlich, um die Zahlungssicherheit und Datensicherheit der Benutzer zu gewährleisten☑️ Notwendige Integration für In-App-Käufe

Integration des Benutzersystems

1. Benutzer-Token vom Client abrufen

2. Überblick

Nachdem Sie das Benutzer-Token und den PublicKey von Jogos erhalten haben, senden Sie diese an Ihren Spielserver zur Verifikation und zum Abruf der Benutzerinformationen. Hinweis: Holen Sie bei jeder Token-Verifikation den PublicKey ab, da dieser jederzeit geändert werden kann.

3. Verifikationslogik

  • Der Spieleentwickler sendet das Benutzer-Token von Jogos an den eigenen Server.
  • Der Server ruft den PublicKey ab (über https://www.jogos.com/publicKey.json).
  • Extrahieren des RSA-PublicKeys aus dem Base64-codierten PublicKey-String.
  • JWT-Token mit dem RSA-PublicKey entschlüsseln. Das entschlüsselte Token kann auf jwt.io getestet werden.
  • Nach der Entschlüsselung werden die Benutzerinformationen abgerufen und mit den Benutzern Ihres Spielservers verknüpft.
  • Wenn die Entschlüsselung fehlschlägt, werden leere Benutzerinformationen zurückgegeben.

4. Codebeispiele

JWT ins Projekt einbinden:

  <!--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
// JWT Utilities
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) {
        /**
         * Benutzer-PublicKey und Token vom Jogos SDK abrufen und an den Server senden, z.B.:
         * -----BEGIN PUBLIC KEY-----
         * MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
         * -----END PUBLIC KEY-----
         * Benutzer-Token:
         * eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIxOTY3NDIzNTM3...
         * Hinweis: Holen Sie bei jeder Token-Verifikation den PublicKey ab, da er sich ändern kann.
         */

        String publickey = "Ihr PublicKey";
        String token = "Ihr Benutzer-Token";

        System.out.println("publickey:[" + publickey + "]");
        System.out.println("token:[" + token + "]");
        Map<String, Object> userMap = verifyToken(token, publickey);
        // Wenn Token erfolgreich geparst wurde, ist userMap nicht null
        if (userMap != null) {
            System.out.println("Verifikation erfolgreich, Benutzerinformationen:");
            System.out.println(JSONObject.toJSONString(userMap));
        } else {
            System.out.println("JWT-Verifikation fehlgeschlagen");
        }
    }

    /**
     * Token verifizieren
     */
    public static Map<String, Object> verifyToken(String token, String publickey) {
        Map<String, Object> map = null;
        try {
            map = parseToken(token, publickey);
        } catch (Exception e) {
            // Fehler beim Parsen ignorieren
        }
        return map;
    }

    /**
     * Token entschlüsseln
     */
    public static Map<String, Object> parseToken(String token, String publickey) {
        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;
    }

    /**
     * RSA PublicKey aus Base64-codiertem String extrahieren
     */
    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;
    }
}

Integration des In-App-Kauf-Systems

Vor Beginn bitte sicherstellen:

  • Sie verwenden aktuell www.jogospre.com (Testumgebung) oder www.jogos.com (Produktivumgebung); die im Folgenden genannten POST-URLs müssen auf die entsprechende Adresse angepasst werden. (z.B. Testumgebung Liefer-API: https://api.jogospre.com/api/gamepay/webhook/arrivedorder)
  • Stellen Sie sicher, dass Sie im Entwicklerportal eine Spielanwendung erstellt haben und im Bereich „Spielparameter“ Ihren Shared Key generiert haben.
  • Stellen Sie sicher, dass in Ihren Spieloptionen „In-App-Käufe verwenden“ aktiviert ist und Sie die Callback-URL Ihres Servers eingetragen haben.
  • Die Kommunikation erfolgt verschlüsselt mit SHA-1, Beispiel:
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);
    }
}

Clientseitige Vorintegration:

Serverseitige Integration:

1. Benachrichtigung bei erfolgreichem Kauf

  • Die Jogos-Plattform sendet eine Zahlungsbestätigung an Ihre konfigurierte Callback-URL.

  • Request Header:

    FeldnameTypPflichtBeschreibung
    AuthorizationstringJaAuthentifizierung, sha1(body+SecretKey), SecretKey ist der für dieses Spiel konfigurierte Shared Key
  • Request Body:

    FeldnameTypPflichtBeschreibung
    paytypeStringJaBenachrichtigungstyp: pay = Zahlungsbestätigung; refund = Rückerstattung
    gameIdintJaSpiel-ID
    orderIdStringJaBestellnummer
    arrivedStatusintJaLieferstatus: 0 = nicht geliefert, 1 = geliefert
    productIdStringJaProdukt-ID
    createTimelongJaErstellzeit der Bestellung (Unix Timestamp)
    payTimelongJaZahlungszeit (Unix Timestamp)
    userIdintJaBenutzer-ID
    refundStatusintNeinRückerstattungsstatus: 0 = in Bearbeitung, 1 = erfolgreich, 2 = fehlgeschlagen, 3 = abgelehnt
    refundTimelongNeinRückerstattungszeit (Unix Timestamp)

    Beispiel:

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

    • 305 Pflichtparameter fehlt
    • 40001 Spiel nicht gefunden
    • 41007 Verifikation fehlgeschlagen
    • 500 Systemfehler
*Hinweis*
  • Wenn der Spielserver nicht 200 zurückgibt, versucht der Zahlungsservice innerhalb von 3 Stunden bis zu 5 Mal erneut.
  • Beim Empfang der Benachrichtigung müssen die Parameter validiert werden:
javascript
public boolean verifySignature(String body, String authorizationHeader) throws Exception
{
    if (authorizationHeader == null || !authorizationHeader.startsWith("Signature "))
    {
        throw new Exception("\"Authorization\" Header im Jogos Webhook nicht gefunden oder ungültig.");
    }

    String clientSignature = authorizationHeader.substring(10); // "Signature " überspringen
    String serverSignature = sha1(body + your_key);//your_key = Shared Key des Spiels

    return clientSignature.equals(serverSignature);
}

2. Lieferstatus-Update durch Spielserver

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

  • Header:

    FeldnameTypPflichtBeschreibung
    AuthorizationstringJasha1(body+SecretKey), SecretKey = Shared Key des Spiels
  • Request Body:

    FeldnameTypPflichtBeschreibung
    gameIdintJaSpiel-ID
    orderIdintJaBestellnummer

    Beispiel:

javascript
{
    "gameId": 9943,
    "orderId":"gHpGwweTlucXwcM6yIeSMcgKkhFmoO"
}
  • Erfolgsantwort JSON:
json
{
    "code": "200",
    "msg": "Success"
}
  • Fehlercodes:

    • 305 Pflichtparameter fehlt
    • 40001 Spiel nicht gefunden
    • 41007 Verifikation fehlgeschlagen
    • 500 Systemfehler

3. Bestellliste abfragen und Status synchronisieren

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

  • Header:

    FeldnameTypPflichtBeschreibung
    AuthorizationstringJasha1(body+SecretKey), SecretKey = Shared Key des Spiels
  • Request Body:

    FeldnameTypPflichtBeschreibung
    gameIdintJaSpiel-ID
    pageNointJaSeitenzahl
    pageSizeintJaAnzahl pro Seite

    Beispiel:

javascript
{
    "gameId": 9943,
    "pageNo":1,
    "pageSize":20
}
  • Erfolgsantwort JSON:

    FeldnameTypPflichtBeschreibung
    codeStringJaStatuscode (z.B. SUCCESS)
    messageStringJaMitteilung (z.B. Logout erfolgreich)
    totalIntegerJaGesamtanzahl
    pageSizeIntegerJaAnzahl pro Seite
    currentPageIntegerJaAktuelle Seite
    totalPageIntegerJaGesamtseiten
    orderIdStringJaBestellnummer
    arrivedStatusIntegerJaLieferstatus 0 = nicht geliefert, 1 = geliefert
    payTimelongJaZahlungszeit (Unix Timestamp)
    productIdStringJaProdukt-ID
    userIdIntegerJaBenutzer-ID
    refundStatusIntegerNeinRückerstattungsstatus, falls Rückerstattung erfolgt: 0 = in Bearbeitung, 1 = erfolgreich, 2 = fehlgeschlagen, 3 = abgelehnt
    refundTimelongNeinRückerstattungszeit (Unix Timestamp)
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
      }
    ]
  }
}
  • Fehlercodes:

    • 305 Pflichtparameter fehlt
    • 40001 Spiel nicht gefunden
    • 41007 Verifikation fehlgeschlagen
    • 500 Systemfehler

4. Rückerstattungsbenachrichtigung an den Spielserver

  • Die Jogos-Plattform sendet die Rückerstattungsbenachrichtigung an Ihre konfigurierte Callback-URL.
  • Request Body ist identisch mit Punkt 1 „Zahlung erfolgreich“.
  • Es wird empfohlen, die Belohnungen oder Items des Spielers basierend auf der Rückerstattung entsprechend zu reduzieren oder zu sperren.