Skip to content

Server-Side Integration API Documentation

If your game has its own game server, and the player data is stored and managed by your server, then server-side integration is required:

ModuleDescriptionIntegration Recommendation
User SystemYou need to link the Jogos platform user system with your server users. This requires server-side integration of the user system☑️ Required Integration
In-App PurchaseIf your game includes in-app purchase items, you need to integrate with the Jogos in-app purchase system to ensure user payment and data security☑️ Required for IAP Games

User System Integration

1. Obtain User Token from Client

2. Overview

After obtaining the user token and public key from Jogos, send them to your game server for verification and to retrieve user information. Note: always retrieve the public key when verifying the token, as it may change at any time.

3. Verification Logic

  • Game developers send the user token obtained from Jogos to their game server.
  • The server fetches the public key (from https://www.jogos.com/publicKey.json).
  • Convert the Base64-encoded public key string into an RSA public key.
  • Decrypt the JWT token using the RSA public key. The decoded token can be tested at jwt.io.
  • Retrieve the user information from the decoded token and bind it to your game server's user.
  • If decryption fails, return empty user information.

4. Code Examples

::: tabs key:server

== JAVA Server

  Import jwt in your project:
  <!--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) {
		/**
		 * Obtain publickey and user token from Jogos SDK and send them to the server, e.g., the publickey below:
		  
		  -----BEGIN PUBLIC KEY-----
		  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhyUrr/W8bSuC+HK8Rk++BDOGDefGMEBa9jekVwVE3oeqi7QbVzZPAuqb1K3GPJjDBfi44IWzb3w8Xa0P1ZeO2Cnbg1LltanlzFv/EcKseCIkOd8Qo78ARPfmlf4WP6MznYGKwNVGFh/s5Y6ar8QgWX1ttkcwYzHu/gUroO+nPOZkU6bfxHjRrJxk3lSQBZWfTSFd2JFwntq3h45UHymjQZiMtW47G2C4VTtTTt1Iz0VQ9rdtWie/+REqQYoFUm04Yns9jyG3TZzio9vsRrxESLQbBIRxto77cQNtEe9j/2EXNwQabRkiS6zo6i2TIN4O6uthWBVud5WXsBWdiyIOHQIDAQAB
		  -----END PUBLIC KEY-----

		and the user token:
		  eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIxOTY3NDIzNTM3NjE1NTgxMTg0Iiwic3ViIjoie1wicHJvZmlsZVBpY3R1cmVVcmxcIjpcImh0dHBzOi8vaW1hZ2Uuam9nb3NwcmUuY29tLzBlZTkyZjViZTRhMzQ4NzBhYjY0YWU1N2FjN2I1YmE0LmpwZ1wiLFwiZ2FtZUlkXCI6XCIxMjIwXCIsXCJ1c2VySWRcIjpcIjI1N1wiLFwidXNlcm5hbWVcIjpcIlBsYXllcjI1N1wifSIsImlzcyI6ImNvbTpqb2dvczpzZGsiLCJpYXQiOjE3NTc5MDUyOTgsImV4cCI6MTc2MTUwNTI5OH0.MKBab0XC1o5AYGosbq1l5m9xCLN1-4xfcr7_dHn-_C8Eh2moTuq9TbQutIajB3dViFW0e1KyIg7UhxNk00rdhT2b5UrvO23tyFsgg9FYyAyCZABURxHyI0lTW9V8YA9k4faycK_gCUMXH_IubseDMz1P7cYmPpo8WxJXZq3R-mL8OhhuKCn8DlpP5BVsd0_gYSTvDUD0gjdINLUNTVrZVkETcDVWW8OXQVzJxdTH0VVlDs4cGvIyko8TJ6g1Bvz4VWj4qy1XoQFfRBH8sgBl3oGJtUodhq3b4bOx4Cr_o-2tK54CetDdmmCPbtcbmmDcBqK5EQ51A2Kws-1cYtsFxg
		     
		  Note: Always retrieve the publickey when verifying the token as it may change  
		 */
		
		String publickey ="your publickey";
		String token = "your user token";
		
		System.out.println("publickey:["+publickey+"]");
		System.out.println("token:["+token+"]");
		Map<String, Object> userMap = verifyToken(token,publickey);
		// If token parsing succeeds, userMap is not null
        if (userMap != null) {
        	System.out.println("Verification succeeded, user information:");
        	System.out.println(JSONObject.toJSONString(userMap));
        }else {
        	System.out.println("JWT verification failed");
        }
	}
	
	
	/**
	 * Verify token
	 * @param token
	 * @return
	 */
	public static Map<String, Object> verifyToken(String token,String publickey){  
		
		// Try parsing the token; if parsing fails, return null
		Map<String, Object> map = null;
        try {
        	map = parseToken(token,publickey);
        } catch (Exception e) {
            
        }
        return map;
         
    }
	
	/**
	 * Decrypt token
	 * @param token
	 * @return
	 */
	public static Map<String,Object> parseToken(String token,String publickey){
		// Remove header and footer
		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;
    }
	
	 /**
     * Get RSA public key from Base64-encoded string
     * @param key Base64-encoded public key string
     * @return Converted RSA public key
     * <p>
     * Note: This method decodes the input string into bytes using Base64, then uses KeyFactory and X509EncodedKeySpec
     * to convert the byte array into a PublicKey object. RuntimeException is thrown if conversion fails.
     */
    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;
    }
}

== Node.js

typescript
import * as jwt from 'jsonwebtoken';

export interface JogosTokenPayload {
  userId: string;
  username: string;
  gameId: string;
  profilePictureUrl: string;
}

export const decodeUserToken = async (token: string): Promise<JogosTokenPayload> => { 
  try {
        const resp = await axios.get("https://www.jogos.com/publicKey.json");
        key = resp.data["data"];
    } 
  catch (e) {
        console.error("Failed to fetch JogosGames public key", e);
    }

    if (!key) {
        throw new Error("Key is empty when decoding JogosGames token");
    }

    const payload = jwt.verify(token, key, { algorithms: ["RS256"] });
    return payload as JogosTokenPayload;
};

:::

In-App Purchase System Integration

Before Starting Integration:

  • Ensure you are using either www.jogospre.com (test environment) or www.jogos.com (production environment); all POST request URLs below must be updated to the corresponding environment. (e.g., test webhook API:https://api.jogospre.com/api/gamepay/webhook/arrivedorder)

  • Make sure your game app is created in the developer platform and a shared key has been generated under "Game Parameters".

  • Ensure the "Use In-App Purchase" option is checked in your game settings and the callback notification URL for your server is provided.

  • Communications use SHA-1 encryption as follows:

    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);
        }
    }

Client-Side Integration:

Server-Side Integration:

1. Payment Success Notification from Jogos Platform

  • The Jogos platform will send a payment success callback to your configured callback notification URL.

  • Request headers:

    FieldTypeRequiredDescription
    AuthorizationstringYesVerification header: sha1(body + shared key), where the key is your game's shared key set in game parameters
  • Request body fields:

    FieldTypeRequiredDescription
    paytypeStringYesNotification type: pay = payment success; refund = refund success
    gameIdintYesGame ID
    orderIdStringYesOrder ID
    arrivedStatusintYesDelivery status: 0 = not delivered, 1 = delivered
    productIdStringYesProduct ID
    createTimelongYesOrder creation time (Unix timestamp)
    payTimelongYesOrder payment time (Unix timestamp)
    userIdintYesUser ID
    refundStatusintNoRefund status if applicable: 0 = refunding, 1 = refunded, 2 = refund failed, 3 = refund rejected
    refundTimelongNoRefund time (Unix timestamp), if applicable

    Example request body:

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

    • 305 Required parameter is missing
    • 40001 Game not found
    • 41007 Verification failed
    • 500 System error
    *General Reminder*
    • If your game server does not return 200, the payment service will retry sending multiple times within 3 hours, up to 5 times.
    • When receiving payment notifications, validate the parameters as follows:
    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 is the game's shared key set in game parameters
    
        return clientSignature.equals(serverSignature);
    }

2. Update Order Delivery Status

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

  • Request headers:

    FieldTypeRequiredDescription
    AuthorizationstringYesVerification header: sha1(body + shared key), where the key is your game's shared key
  • Request body:

    FieldTypeRequiredDescription
    gameIdintYesGame ID
    orderIdintYesOrder ID

    Example request body:

    javascript
    {
        "gameId"9943,
        "orderId":"gHpGwweTlucXwcM6yIeSMcgKkhFmoO"
    }
  • Response JSON fields (code:200 means success):

    json
    {
        "code""200",
        "msg""Success"
    }
  • Error codes:

    • 305 Required parameter is missing
    • 40001 Game not found
    • 41007 Verification failed
    • 500 System error

3. Query Orders and Synchronize Delivery Status

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

  • Request headers:

    FieldTypeRequiredDescription
    AuthorizationstringYesVerification header: sha1(body + shared key), where the key is your game's shared key
  • Request body:

    FieldTypeRequiredDescription
    gameIdintYesGame ID
    pageNointYesPage number
    pageSizeintYesPage size

    Example request body:

    javascript
    {
        "gameId"9943,
        "pageNo":1,
        "pageSize":20
    }
  • Response JSON fields (code:200 means success):

    FieldTypeRequiredDescription
    codeStringYesStatus code, e.g., SUCCESS
    messageStringYesMessage, e.g., Logout successful
    totalIntegerYesTotal count
    pageSizeIntegerYesItems per page
    currentPageIntegerYesCurrent page
    totalPageIntegerYesTotal pages
    orderIdStringYesOrder ID
    arrivedStatusIntegerYesDelivery status: 0 = not delivered, 1 = delivered
    payTimelongYesPayment time (Unix timestamp)
    productIdStringYesProduct ID
    userIdIntegerYesUser ID
    refundStatusIntegerNoRefund status if applicable: 0 = refunding, 1 = refunded, 2 = refund failed, 3 = refund rejected
    refundTimelongNoRefund time (Unix timestamp), if applicable
    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 } ] } }


- Error codes:
- `305` Required parameter is missing
- `40001` Game not found
- `41007` Verification failed
- `500` System error

### <span style="color:rgb(255, 196, 34);">4. Refund Notification</span>

- The Jogos platform will send refund success callbacks to your configured **callback notification URL** for refunded orders.
- Request body is the same as in section 1 “Payment Success Notification”.
- Developers are advised to deduct or restrict rewards previously granted to the player as appropriate based on the refund order.