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ódulo | Descripción | Recomendación de integración |
---|---|---|
Sistema de usuarios | Necesita 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 integradas | Si 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
- Para más detalles, consulte primero la documentación:
Integración del SDK de usuario del lado del 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>
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) owww.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:
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); } }
Integración previa del cliente:
- La creación y inicio de pedidos se realiza desde el cliente.
- Para más detalles, consulte la documentación:
Integración del SDK de compras integradas del lado 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 campo Tipo Puede estar vacío Descripción Authorization string No Encabezado 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 campo Tipo Puede estar vacío Descripción paytype String No Tipo de notificación: pay - notificación de pago exitoso; refund - notificación de reembolso exitoso gameId int No ID del juego orderId String No Número de pedido arrivedStatus int No Estado de entrega: 0 - no entregado, 1 - entregado productId String No ID del producto createTime long No Hora de creación del pedido (marca de tiempo Unix) payTime long No Hora de pago exitoso del pedido (marca de tiempo Unix) userId int No ID de usuario refundStatus int Sí Estado de reembolso, no vacío cuando ocurre reembolso: 0 - procesando, 1 - exitoso; 2 - fallido; 3 - rechazado refundTime long Sí Hora 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ío40001
Juego correspondiente no encontrado41007
Fallo en la verificación500
Excepción del sistema
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 campo Tipo Puede estar vacío Descripción Authorization string No Encabezado 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 campo Tipo Puede estar vacío Descripción gameId int No ID del juego orderId int No Nú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ío40001
Juego correspondiente no encontrado41007
Fallo en la verificación500
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 campo Tipo Puede estar vacío Descripción Authorization string No Encabezado 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 campo Tipo Puede estar vacío Descripción gameId int No ID del juego pageNo int No Número de página pageSize int No Tamañ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 campo Tipo Puede estar vacío Descripción code String No Código de estado, indica el resultado de la solicitud (ej: SUCCESS) message String No Mensaje informativo (ej: Cierre de sesión exitoso) total Integer No Total pageSize Integer No Número por página currentPage Integer No Página actual totalPage Integer No Total de páginas orderId String No Número de pedido arrivedStatus Integer No Estado de entrega; 0 - no entregado, 1 - entregado payTime long No Hora de pago (marca de tiempo Unix) productId String No ID del producto userId Integer No ID de usuario refundStatus Integer Sí Estado de reembolso, no vacío cuando ocurre reembolso: 0 - procesando, 1 - exitoso, 2 - fallido, 3 - rechazado refundTime long Sí Hora 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ío40001
Juego correspondiente no encontrado41007
Fallo en la verificación500
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.