Skip to content

Descripción de las interfaces de integración del lado del servidor

Si su juego tiene su propio servidor de juego y los datos de los jugadores son guardados y administrados por su servidor, se requiere la integración del lado del servidor:

MóduloDescripciónRecomendación de integración
Sistema de usuariosNecesita asociar el sistema de usuarios de la plataforma Jogos con los usuarios de su servidor. Se requiere la integración del sistema de usuarios del lado del servidor.☑️ Integración necesaria
Sistema de compras integradasSi su juego tiene elementos de compras integradas, necesita integrar el sistema de compras integradas de Jogos para garantizar la seguridad de los pagos y datos de los usuarios.☑️ Necesario para juegos con compras integradas

Integración del sistema de usuarios

1 Obtención del token de usuario desde el cliente

2 Resumen

Después de obtener el token de usuario y la publickey de Jogos, transmítalos al servidor del juego para su verificación y obtención de la información del usuario. Nota: obtenga la clave publickey cada vez que valide el token, porque puede cambiar en cualquier momento.

3 Lógica de verificación

  • El desarrollador del juego obtiene el token de usuario de Jogos y lo transmite a su servidor de desarrollo.
  • El servidor obtiene la publickey (a través de https://www.jogos.com/publicKey.json).
  • Obtiene la clave pública RSA a partir de la cadena publickey codificada en Base64.
  • Descifra el token JWT utilizando la clave pública RSA. La decodificación del token devuelto se puede probar en jwt.io.
  • Después de la decodificación, obtiene la información del usuario y la vincula con el usuario de su servidor de juego.
  • Si el descifrado falla, devuelve información de usuario vacía.

4 Ejemplos de código

  Importar jwt en el proyecto:
  <!--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) {
		/**
		 * Obtenga la publickey y el token de usuario del SDK de jogos y transmítalos al servidor, como se muestra a continuación para la publickey:
		  
		  -----BEGIN PUBLIC KEY-----
		  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhyUrr/W8bSuC+HK8Rk++BDOGDefGMEBa9jekVwVE3oeqi7QbVzZPAuqb1K3GPJjDBfi44IWzb3w8Xa0P1ZeO2Cnbg1LltanlzFv/EcKseCIkOd8Qo78ARPfmlf4WP6MznYGKwNVGFh/s5Y6ar8QgWX1ttkcwYzHu/gUroO+nPOZkU6bfxHjRrJxk3lSQBZWfTSFd2JFwntq3h45UHymjQZiMtW47G2C4VTtTTt1Iz0VQ9rdtWie/+REqQYoFUm04Yns9jyG3TZzio9vsRrxESLQbBIRxto77cQNtEe9j/2EXNwQabRkiS6zo6i2TIN4O6uthWBVud5WXsBWdiyIOHQIDAQAB
		  -----END PUBLIC KEY-----

		y el token de usuario:
		  eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIxOTY3NDIzNTM3NjE1NTgxMTg0Iiwic3ViIjoie1wicHJvZmlsZVBpY3R1cmVVcmxcIjpcImh0dHBzOi8vaW1hZ2Uuam9nb3NwcmUuY29tLzBlZT92ZjViZTRhMzQ4NzBhYjY0YWU1N2FjN2I1YmE0LmpwZ1wiLFwiZ2FtZUlkXCI6XCIxMjIwXCIsXCJ1c2VySWRcIjpcIjI1N1wiLFwidXNlcm5hbWVcIjpcIlBsYXllcjI1N1wifSIsImlzcyI6ImNvbTpqb2dvczpzZGsiLCJpYXQiOjE3NTc5MDUyOTgsImV4cCI6MTc2MTUwNTI5OH0.MKBab0XC1o5AYGosbq1l5m9xCLN1-4xfcr7_dHn-_C8Eh2moTuq9TbQutIajB3dViFW0e1KyIg7UhxNk00rdhT2b5UrvO23tyFsgg9FYyAyCZABURxHyI0lTW9V8YA9k4faycK_gCUMXH_IubseDMz1P7cYmPpo8WxJXZq3R-mL8OhhuKCn8DlpP5BVsd0_gYSTvDUD0gjdINLUNTVrZVkETcDVWW8OXQVzJxdTH0VVlDs4cGvIyko8TJ6g1Bvz4VWj4qy1XoQFfRBH8sgBl3oGJtUodhq3b4bOx4Cr_o-2tK54CetDdmmCPbtcbmmDcBqK5EQ51A2Kws-1cYtsFxg
		     
		  Nota: Obtenga la clave publickey cada vez que valide el token, ya que puede cambiar.
		 */
		
		String publickey ="Su publickey";
		String token = "Su token de usuario";
		
		System.out.println("publickey:["+publickey+"]");
		System.out.println("token:["+token+"]");
		Map<String, Object> userMap = verifyToken(token,publickey);
		// Si el token se analiza con éxito, userMap no estará vacío
        if (userMap != null) {
        	System.out.println("Verificación exitosa, información del usuario:");
        	System.out.println(JSONObject.toJSONString(userMap));
        }else {
        	System.out.println("Falló la verificación JWT");
        }
	}
	
	
	/**
	 * Verificar token
	 * @param token
	 * @return
	 */
	public static Map<String, Object> verifyToken(String token,String publickey){  
		
		// Intentar analizar el token, devolver null si falla
		Map<String, Object> map = null;
        try {
        	map = parseToken(token,publickey);
        } catch (Exception e) {
            
        }
        return map;
         
    }
	
	/**
	 * Descifrar token
	 * @param token
	 * @return
	 */
	public static Map<String,Object> parseToken(String token,String publickey){
		//Eliminar partes iniciales y finales 
		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;
    }
	
	 /**
     * Obtener la clave pública RSA a partir de una cadena codificada en Base64
     * @param key Cadena de clave pública codificada en Base64
     * @return Clave pública RSA convertida
     * <p>
     * Nota: Este método utiliza un decodificador Base64 para decodificar la cadena de entrada en una matriz de bytes, luego utiliza KeyFactory y X509EncodedKeySpec
     * para convertir la matriz de bytes en un objeto PublicKey. Si ocurre una excepción durante la conversión, se lanzará una 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;
    }
}

Integración del sistema de compras integradas

Antes de comenzar la integración, confirme:

  • Que está utilizando www.jogospre.com (entorno de prueba) o www.jogos.com (entorno de producción); Las URL de solicitud POST mencionadas a continuación deben cambiarse a la dirección correspondiente. (Por ejemplo, la API de confirmación de entrega en el entorno de prueba: https://api.jogospre.com/api/gamepay/webhook/arrivedorder)

  • Que ha creado una aplicación de juego en la plataforma de desarrolladores y ha generado su clave secreta compartida del juego en "Parámetros del juego".

  • Que en las opciones de su juego, ha marcado "Usar compras integradas" e ingresado la dirección de notificación de callback que recibe su servidor.

  • La comunicación utiliza el cifrado SHA-1, el uso específico es el siguiente:

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

Integración previa del cliente:

Comience la integración del lado del servidor:

1. Después de que el usuario compre un artículo exitosamente en el juego, la plataforma Jogos envía una notificación de pago exitoso

  • La plataforma Jogos enviará información de callback de pago exitoso a su dirección de notificación de callback configurada.

  • Encabezados de la solicitud:

    Nombre del campoTipoPuede estar vacíoDescripción
    AuthorizationstringNoEncabezado de verificación, sha1(body+clave), donde la clave es el secreto compartido del juego establecido en los parámetros del juego
  • El cuerpo de la solicitud contiene los siguientes campos:

    Nombre del campoTipoPuede estar vacíoDescripción
    paytypeStringNoTipo de notificación: pay - notificación de pago exitoso; refund - notificación de reembolso exitoso
    gameIdintNoID del juego
    orderIdStringNoNúmero de pedido
    arrivedStatusintNoEstado de entrega: 0 - no entregado, 1 - entregado
    productIdStringNoID del producto
    createTimelongNoHora de creación del pedido (marca de tiempo Unix)
    payTimelongNoHora de pago exitoso del pedido (marca de tiempo Unix)
    userIdintNoID de usuario
    refundStatusintEstado de reembolso, no vacío cuando ocurre reembolso: 0 - procesando, 1 - exitoso; 2 - fallido; 3 - rechazado
    refundTimelongHora de reembolso (marca de tiempo Unix), no vacío cuando ocurre reembolso

    Ejemplo del cuerpo de la solicitud:

    javascript
    {
        "gameId"9968,
        "orderId""zXhKYRy3genKKh9TgndBpu1gp5tBpA",
        "arrivedStatus"0,
        "productId""1002",
        "createTime"1755657098,
        "payTime"1755657115,
        "userId"278,
        "refundStatus"null,
        "refundTime"null
    }
    • El objeto JSON devuelto contiene los siguientes campos: (code:200 representa éxito)
    {
        "code": "200",
        "msg": "Success"
    }
  • Códigos de error:

    • 305 Parámetro obligatorio vacío
    • 40001 Juego correspondiente no encontrado
    • 41007 Fallo en la verificación
    • 500 Excepción del sistema
    *Recordatorio general*
    • Cuando el servidor del juego no devuelve 200, el servicio de pago reintentará enviar múltiples veces después de 3 horas, hasta 5 veces como máximo.
    • Al recibir una notificación del servidor de pago, es necesario verificar los parámetros de la siguiente manera:
    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); // Omitir "Signature "
        String serverSignature = sha1(body + your_key);//your_key es el secreto compartido específico del juego, establecido en los parámetros del juego
    
        return clientSignature.equals(serverSignature);
    }

2. Después de que el servidor del juego complete el envío, debe llamar a la interfaz "Actualización del estado de entrega" para marcar el pedido como enviado

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

  • Encabezados de la solicitud:

    Nombre del campoTipoPuede estar vacíoDescripción
    AuthorizationstringNoEncabezado de verificación, sha1(body+clave), donde la clave es el secreto compartido del juego establecido en los parámetros del juego
  • Cuerpo de la solicitud:

    Nombre del campoTipoPuede estar vacíoDescripción
    gameIdintNoID del juego
    orderIdintNoNúmero de pedido

    Ejemplo del cuerpo de la solicitud:

    javascript
    {
        "gameId"9943,
        "orderId":"gHpGwweTlucXwcM6yIeSMcgKkhFmoO"
    }
  • El objeto JSON devuelto contiene los siguientes campos: (code:200 representa éxito)

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

    • 305 Parámetro obligatorio vacío
    • 40001 Juego correspondiente no encontrado
    • 41007 Fallo en la verificación
    • 500 Excepción del sistema

3. El servidor del juego consulta la lista de pedidos para sincronizar el estado de los pedidos y las entregas

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

  • Encabezados de la solicitud:

    Nombre del campoTipoPuede estar vacíoDescripción
    AuthorizationstringNoEncabezado de verificación, sha1(body+clave), donde la clave es el secreto compartido del juego establecido en los parámetros del juego
  • Cuerpo de la solicitud:

    Nombre del campoTipoPuede estar vacíoDescripción
    gameIdintNoID del juego
    pageNointNoNúmero de página
    pageSizeintNoTamaño de página

    Ejemplo del cuerpo de la solicitud :

    javascript
    {
        "gameId"9943,
        "pageNo":1,
        "pageSize":20
    }
  • El objeto JSON devuelto contiene los siguientes campos: (code:200 representa éxito)

    Nombre del campoTipoPuede estar vacíoDescripción
    codeStringNoCódigo de estado, indica el resultado de la solicitud (ej: SUCCESS)
    messageStringNoMensaje informativo (ej: Cierre de sesión exitoso)
    totalIntegerNoTotal
    pageSizeIntegerNoNúmero por página
    currentPageIntegerNoPágina actual
    totalPageIntegerNoTotal de páginas
    orderIdStringNoNúmero de pedido
    arrivedStatusIntegerNoEstado de entrega; 0 - no entregado, 1 - entregado
    payTimelongNoHora de pago (marca de tiempo Unix)
    productIdStringNoID del producto
    userIdIntegerNoID de usuario
    refundStatusIntegerEstado de reembolso, no vacío cuando ocurre reembolso: 0 - procesando, 1 - exitoso, 2 - fallido, 3 - rechazado
    refundTimelongHora de reembolso (marca de tiempo Unix), no vacío cuando ocurre reembolso
    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
          }
        ]
      }
    }
  • Códigos de error:

    • 305 Parámetro obligatorio vacío
    • 40001 Juego correspondiente no encontrado
    • 41007 Fallo en la verificación
    • 500 Excepción del sistema

4. Cuando ocurre un reembolso para un usuario, se envía una notificación de reembolso exitoso al servidor del juego

  • La plataforma Jogos enviará información de callback del pedido reembolsado exitosamente por este usuario a su dirección de notificación de callback configurada.
  • El cuerpo de la solicitud es el mismo que el del punto 1 "Notificación de pago exitoso".
  • Se recomienda que los desarrolladores deduzcan o restrinjan los accesorios de recompensa obtenidos por la recarga anterior del jugador, según corresponda, de acuerdo con la información del pedido de reembolso.