Configuration de l’authentification par lien profond
Les liens profonds permettent à l’utilisateur de s’authentifier dans le Web Shop via le jeu en un seul clic, contournant ainsi le processus d’authentification par ID utilisateur ou via Xsolla Login.
Si le jeu est déjà installé sur l’appareil mobile de l’utilisateur, il sera automatiquement redirigé vers le jeu via un lien profond pour obtenir un jeton d’autorisation.
Flux utilisateur
Dans l'application mobile
- Un utilisateur non autorisé du Web Shop clique sur le bouton de connexion ou sur le bouton d'achat. Une fenêtre modale permettant de saisir l'ID utilisateur ou de se connecter via le jeu mobile s'affiche.
- L'utilisateur clique sur le bouton de connexion via le jeu.
- L'utilisateur est redirigé vers le jeu où, il est automatiquement redirigé vers le Web Shop en tant qu'utilisateur autorisé.
Dans la version de bureau
- Un utilisateur non autorisé du Web Shop clique sur le bouton de connexion ou sur le bouton d'achat. Une fenêtre modale permettant de saisir l'ID utilisateur ou de se connecter à la version mobile du jeu à l'aide d'un code QR s'affiche.
- L'utilisateur scanne le code QR à l'aide de son appareil mobile, après quoi le Web Shop s'ouvre sur celui-ci.
- La version mobile du jeu s'ouvre sur l'appareil de l'utilisateur.
- L'utilisateur est automatiquement redirigé vers le Web Shop sur son appareil mobile en tant qu'utilisateur autorisé.
Flux d'interaction des services
Comment configurer
Côté jeu
- Dans les paramètres de l'application mobile de votre jeu, enregistrez un schéma d'URL pour ouvrir le jeu via un lien profond :
- dans les applications Android — dans le fichier
AndroidManifest.xml
; - dans les applications iOS — dans le fichier
Info.plist
.
- dans les applications Android — dans le fichier
gamename://authorize
, où :gamename
— nom de votre jeu qui doit s’ouvrir sur un appareil mobile pour l’authentification de l’utilisateur ;authorize
— exemple de nom d’action à effectuer après l’ouverture du jeu gamename. Utilisez le nom d’action qui correspond aux actions du système d’exploitation de votre application.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>gamename</string>
</array>
</dict>
</array>
Exemple d’enregistrement d’un schéma d’URL dans les applications Android :
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="gamename" android:host="authorize" />
</intent-filter>
- Implémentez la génération d'un jeton d'autorisation au format JWT en utilisant l'ID utilisateur dans le jeu.
Paramètre | Type | Description |
---|---|---|
loginId | string | ID de la méthode d’autorisation du Compte éditeur. Obligatoire. |
webhookUrl | string | URL pour recevoir le webhook Validation utilisateur dans le Web Shop. L’URL doit correspondre à l’adresse spécifiée lors de la configuration de l’authentification par ID utilisateur. Xsolla attend un code HTTP 200 en réponse au webhook pour autoriser l’utilisateur du Web Shop. En cas de réception d’une réponse avec un code HTTP 404 ou d’absence de réponse, l’utilisateur ne sera pas autorisé.Pour désactiver les webhooks lors de l’authentification par lien profond, spécifiez la valeur "webhookUrl": "https://nowebhook.com" . Dans ce cas, Xsolla ne vérifie pas l’existence de l’utilisateur, assurez-vous donc que dans le paramètre user.id vous passez l’ID d’un utilisateur qui existe dans le jeu.Obligatoire. |
settings.projectId | string | L’ID du projet se trouve dans le Compte éditeur, à côté du nom de votre projet ou dans la barre d’adresse du navigateur. L’URL présente le format suivant : https://publisher.xsolla.com/merchant ID/Publisher Account section . Obligatoire. |
user.id | string | ID utilisateur dans le jeu. Obligatoire. |
user.name | string | Nom d’utilisateur. Obligatoire. |
Exemple d’appel à la méthode API de génération de jeton utilisateur à l’aide de curl :
- curl
curl --location 'https://sb-user-id-service.xsolla.com/api/v1/user-id' \
--header 'Content-Type: application/json' \
--data '{
"loginId": "000001aa-001a-0ab0-00001-01a01a01a01a",
"webhookUrl": "https://nowebhook.com",
"settings": {
"projectId": 123456,
"merchantId": 123456
},
"user": {
"id": "123",
"name": "a-user-name"
}
}'
Vous obtiendrez une réponse du type {token=“JWT_TOKEN”}
.
- Ajoutez une fenêtre contextuelle avec une notification d'autorisation réussie (facultatif).
- Implémentez l'ouverture du Web Shop dans le navigateur à l'aide du jeton utilisateur obtenu.
Exemple de création d’une URL pour ouvrir le Web Shop dans le navigateur d’un utilisateur autorisé :
https://example.com/?token={token}
, si vous utilisez un domaine personnaliséhttps://example.xsollasitebuilder.com/?token={token}
, si vous utilisez un domaine Xsolla
{token}
est le jeton d’autorisation de l’utilisateur.Dans Site Builder
Vous pouvez effectuer vous-même les réglages du côté du Site Builder en utilisant les exemples de code fournis ci-dessous.Pour obtenir de l’aide pour la configuration, contactez votre responsable de la réussite client ou envoyez un e-mail à csm@xsolla.com.
- Ouvrez le projet dans le Compte éditeur.
- Dans le menu latéral, cliquez sur Site Builder.
- Cliquez sur Configure sur la carte du site de votre Web Shop avec authentification par ID utilisateur.
- Ajoutez l’authentification par lien profond à l’aide d’un bloc Custom code.
- Dans le bloc Custom code de l’onglet JavaScript, ajoutez le code personnalisé ci-dessous, qui implémente l’authentification par lien profond pour les versions mobiles et de bureau.
- Remplacez les valeurs des constantes dans le code par vos valeurs, où :
DEEPLINK_URL
— schéma d'URL pour ouvrir le jeu via le lien profond ;QR_CODE
— code QR pour ouvrir le jeu au format SVG. Le code QR doit contenir un lien vers le Web Shop avec le paramètresource = pc
;deeplink__description
— description affichée sous le bouton d'authentification du jeu dans l'application mobile ;qr-code-auth__description
— description affichée sous le code QR dans la version de bureau du jeu.
- js
{
const DEEPLINK_URL = 'gamename://authorize';
const QR_CODE = `YOUR_SVG_WITH_QR_CODE`;
handleQRCodeRedirect();
// Event handlers are set up for opening the authentication modal or for successful authentication.
// If the event of opening the authentication modal occurs, the handler is triggered and a button or QR code is added to this window.
// If the event of successful authentication occurs, the handler is triggered and the successful authentication modal is opened.
window.addEventListener('custom-event:modal:render', updateLoginModal);
window.addEventListener('custom-event:authorization:login', showLoginSuccessPopup);
let getToken;
const searchParams = new URLSearchParams(window.location.search);
const tokenParam = searchParams.get('token');
if (tokenParam) {
showLoginSuccessPopup(tokenParam);
}
window.SB.subscribe(api => {
getToken = api.getToken;
});
// Customization of the authentication modal window (adding a QR code for the desktop version of the game or a login button for the mobile version of the game).
function updateLoginModal({detail}) {
const {name, element} = detail;
if (name !== 'user-id' || element.dataset.isQrAdded === 'true') return;
const isMobile = checkMobileDevice();
const ModalBody = element.querySelector('.ui-site-modal-window__body');
const ModulInput = ModalBody.querySelector('.user-id-modal__input');
element.classList.toggle('mobile-layout', isMobile);
ModalBody.append(getTemplate(isMobile));
element.dataset.isQrAdded = true;
}
// Function to display the successful authentication modal window.
function showLoginSuccessPopup(t) {
let username = 'Gamer';
try {
const token = getToken?.() || t;
if (token) {
const jwtData = parseJwt(token);
const payload = JSON.parse(jwtData.payload);
if (payload.userInfo.name) {
username = payload.userInfo.name;
} else if (jwtData.username) {
username = jwtData.username;
} else if (jwtData.server_custom_id) {
username = jwtData.server_custom_id;
}
}
} catch (e) {
console.log('error', e);
}
const Modal = document.querySelector('.deeplink-auth');
const ModalTitle = Modal.querySelector('.deeplink-auth__title');
ModalTitle.textContent = ModalTitle.textContent.replace(/\{username}/g, username);
Modal.classList.add('_visible');
Modal.querySelector('.deeplink-auth__button').addEventListener('click', closeModal);
function closeModal() {
Modal.classList.remove('_visible');
}
}
// Function that displays a QR code for the desktop version of the game or a login button for the mobile version of the game. Your_game should be replaced with the actual name of your game. To continue with the authentication, the game has to be installed on the user's phone.
function getTemplate(isMobile) {
const Deeplink = document.createElement('div');
if (isMobile) {
Deeplink.innerHTML = `
<div class="deeplink__title"><span class="deeplink__title-text">or login via game</span></div>
<a href="${DEEPLINK_URL}" class="deeplink__button" rel="noopener">Login via Mobile Game</a>
<div class="deeplink__description">
You need to have the Your_game installed on your phone in order to proceed with authorization and purchase
</div>
`;
return Deeplink;
}
Deeplink.innerHTML = `
<div class="separator">
<span class="separator__text">or login via game</span>
</div>
<div class="qr-code-auth">
<div class="qr-code-auth__image">${QR_CODE}</div>
<span class="qr-code-auth__description">
Scan the QR code with your phone and you will continue purchasing on your mobile device
</span>
</div>
`;
return Deeplink;
}
function checkMobileDevice() {
return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
}
// Function that decodes the JWT token and returns its payload as a JavaScript object.
function parseJwt(token) {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
}
// Function to verify the vent occurred when the user scanned the QR code.
function handleQRCodeRedirect() {
const url = new URL(window.location.href);
const source = url.searchParams.get('source');
if (source === 'pc') {
if (checkMobileDevice()) {
const button = document.getElementById("deeplink-redirect");
button.click();
}
setTimeout(function () {
url.searchParams.delete('source');
window.history.pushState({}, '', url);
}, 2000);
}
}
}
- Dans le bloc Custom code de l'onglet HTML, ajoutez le code pour une fenêtre modale indiquant une authentification réussie dans le Web Shop. Vous pouvez définir vos propres valeurs de texte.
- html
<div class="ui-site-modal-window deeplink-auth">
<div class="deeplink-auth__body">
<div class="deeplink-auth__image"></div>
<div class="deeplink-auth__title">Hi, {username}!</div>
<div class="deeplink-auth__description">You’ve successfully logged in to the Web Shop</div>
<button class="deeplink-auth__button">Continue</button>
</div>
</div>
<a href="gamename://authorize" id="deeplink-redirect" style="display: none;"></a>
- Dans le bloc Custom code de l'onglet CSS, ajoutez les styles pour les nouveaux composants d'interface. Les styles recommandés sont suggérés ci-dessous. Spécifiez l'URL de votre propre image affichée lors d'une authentification réussie.
- css
--deeplink-success-image-url: url("Successful_authorization_image_url");
.html-v2:has(.deeplink-auth._visible) {
z-index: var(--modalsZIndex);
}
.user-id-modal__content {
padding: 0 16px !important;
}
@media (min-width: 768px) {
.user-id-modal__content {
max-width: 460px !important;
padding: 0 3.8rem 4rem !important;
overflow: auto;
justify-content: center;
}
}
.mobile-layout .user-id-modal__close {
right: 8px;
top: 16px;
}
.user-id-modal__logo {
width: 109px;
height: 38px;
margin: 4rem auto 2rem;
}
.user-id-modal.mobile-layout .user-id-modal__logo {
margin: 3rem auto 2.5rem;
}
.user-id-modal__wrapper {
margin-top: 0;
}
.user-id-modal__title {
margin-bottom: 3rem;
}
.user-id-modal__input-wrapper .ui-site-input {
height: 41px;
}
.user-id-modal__input {
margin-top: 0;
border-radius: var(--border-radius-16);
}
.user-id-modal__button {
height: auto;
margin: 12px auto 0;
padding: 1.25rem;
border-radius: var(--border-radius-16);
}
.user-id-modal__button .simple-button__text {
font-size: 1.8rem;
font-weight: 500;
line-height: 2.5rem;
letter-spacing: 0.5px;
}
.user-id-modal .ui-site-instruction-cut__title .ui-site-description {
margin-bottom: 3rem;
font-size: 1.2em;
}
.user-id-modal .ui-site-instruction-cut__steps {
overflow-y: visible;
}
.user-id-modal .ui-site-instruction-card:first-child {
margin-top: 0;
}
.user-id-modal .ui-site-instruction-card:last-child {
padding-bottom: 4rem;
}
.user-id-modal .separator {
display: flex;
margin-bottom: 3.8rem;
align-items: center;
}
.user-id-modal .separator__text {
padding: 0 1.5rem;
font-family: var(--main-font);
font-size: 1.8rem;
font-weight: 500;
line-height: 2.5rem;
letter-spacing: 0.8px;
}
.user-id-modal .separator::before,
.user-id-modal .separator::after {
content: "";
background-color: #797979;
height: 1px;
flex-grow: 1;
}
.user-id-modal .qr-code-auth__image {
display: block;
width: 160px;
height: 160px;
margin: 0 auto 20px;
}
.user-id-modal .qr-code-auth__image svg {
display: block;
width: 100%;
height: 100%;
}
.user-id-modal .qr-code-auth__description {
display: inline-block;
font-family: var(--main-font);
font-size: 1.5rem;
font-weight: 400;
line-height: 2.5rem;
text-align: center;
color: rgba(255, 255, 255, 0.7);
}
.deeplink__title {
display: flex;
margin-bottom: 3.8rem;
align-items: center;
}
.deeplink__title-text {
padding: 0 1.5rem;
font-family: var(--main-font);
font-size: 1.8rem;
font-weight: 500;
line-height: 2.5rem;
letter-spacing: 0.8px;
}
.user-id-modal .deeplink__title::before,
.user-id-modal .deeplink__title::after {
content: "";
background-color: #797979;
height: 1px;
flex-grow: 1;
}
.deeplink__button {
display: block;
margin-bottom: 2.2rem;
padding: 1.3rem;
font-family: var(--main-font);
font-size: 1.8rem;
font-weight: 500;
line-height: 2.5rem;
letter-spacing: 0.5px;
text-align: center;
color: var(--button-text-color);
background: var(--accent-color);
border-radius: var(--border-radius-16);
text-decoration: none;
transition: transform .2s cubic-bezier(.509, .001, .25, 1);
}
.deeplink__button:hover {
transform: scale(.95);
}
.deeplink__description {
margin-bottom: 2rem;
font-family: var(--main-font);
font-size: 1.6rem;
line-height: 2.3rem;
text-align: center;
color: rgba(255, 255, 255, 0.7);
letter-spacing: 0.5px;
}
.deeplink__cta-wrapper {
display: flex;
flex-direction: row;
gap: 1.8rem;
padding: 0 1.2rem;
}
.deeplink__cta-wrapper .ui-site-calltoaction__item {
margin: 0;
flex-grow: 2;
}
.deeplink__cta-wrapper .ui-site-calltoaction {
width: 100%;
min-width: auto;
height: auto;
min-height: auto;
padding-bottom: 36%;
background-size: contain;
border-radius: 0;
}
.deeplink-auth {
display: none;
}
.deeplink-auth._visible {
display: flex;
}
.deeplink-auth__body {
position: relative;
width: 100%;
max-width: 336px;
padding: 16px;
border-radius: 12px;
background-color: var(--colors-core-background-secondary-rgb);
border: var(--border-size) solid var(--border-color);
font-family: var(--main-font);
color: var(--colors-core-text-primary);
}
@media (min-width: 768px) {
.deeplink-auth__body {
max-width: 460px;
padding: 24px 30px;
}
}
.deeplink-auth__image {
margin-bottom: 20px;
padding-bottom: 49%;
border-radius: 12px;
background-image: var(--deeplink-success-image-url);
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
@media (min-width: 768px) {
.deeplink-auth__image {
padding-bottom: 37%;
}
}
.deeplink-auth__title {
margin-bottom: 10px;
font-size: 20px;
font-weight: 500;
line-height: 24px;
text-align: center;
letter-spacing: 0.7px;
}
@media (min-width: 768px) {
.deeplink-auth__title {
margin-bottom: 20px;
font-size: 24px;
line-height: 30px;
}
}
.deeplink-auth__description {
margin-bottom: 20px;
font-size: 13px;
font-weight: 400;
line-height: 18px;
text-align: center;
letter-spacing: 0.5px;
color: rgba(255, 255, 255, 0.7);
}
.deeplink-auth__button {
display: block;
width: 100%;
padding: 1.3rem;
font-family: var(--main-font);
font-size: 1.8rem;
font-weight: 500;
line-height: 2.5rem;
letter-spacing: 0.5px;
text-align: center;
color: var(--button-text-color);
background: var(--accent-color);
border-radius: var(--border-radius-16);
text-decoration: none;
transition: transform .2s cubic-bezier(.509, .001, .25, 1);
}
@media (min-width: 768px) {
.deeplink-auth__button {
padding: 12px;
font-size: 16px;
line-height: 24px;
}
}
.deeplink-auth__button:hover {
transform: scale(.95);
}
Cet article vous a été utile ?
Évaluer cette page
Préfère ne pas répondre
Merci pour votre commentaire !
Faute de frappe ou autre erreur dans le texte ? Sélectionnez le texte concerné et appuyez sur Ctrl+Entée.