Перейти к основному содержимому

Интеграция автоматического входа (кнопка «Играть»)

Когда пользователь нажимает кнопку «Играть» на карточке мерчанта в Kukuruku, система автоматически создаёт и оплачивает ордер, затем перенаправляет пользователя на платформу мерчанта с параметрами аутентификации. Это обеспечивает бесшовный опыт в один клик.

Предварительные требования

Для поддержки автоматического входа необходимо настроить:

  1. Платёжную интеграцию (для получения callback'ов)
  2. KukurukuID OAuth 2.0 (для аутентификации пользователей)

Как это работает

Пользователь нажимает «Играть» на Kukuruku
|
v
Kukuruku создаёт ордер (POST /api/v1/orders/payins)
|
v
Kukuruku оплачивает ордер из баланса KukuPay пользователя
|
v
Пользователь перенаправляется на вашу платформу с параметрами:
https://your-site.com/?auto_login=true&custom4=...&order_id=...
|
v
Ваша платформа обнаруживает auto_login=true
|
v
Ваша платформа инициирует OAuth вход через issuer из custom4
|
v
Пользователь аутентифицирован, баланс зачислен через callback

Параметры редиректа

При перенаправлении пользователя на вашу платформу URL включает следующие параметры:

Параметры аутентификации

ПараметрЗначениеОписание
auto_logintrueУказывает, что это автоматический вход
joker_logintrueПодтверждает, что редирект от Kukuruku
custom4https://auth.kukuruku.win/realms/publicURL издателя KukurukuID — используйте для OAuth аутентификации

Параметры ордера

ПараметрЗначениеОписание
order_idUUIDИдентификатор ордера в KukuPay
custom2UUIDТо же, что order_id (дубликат для совместимости)

Параметры трекинга

ПараметрОписание
sub_id1Идентификатор аффилиата
sub_id2Источник трафика
sub_id3Идентификатор ссылки
sub_id4Идентификатор креатива
sub_id5UUID пользователя
aff_click_idИдентификатор клика аффилиата
custom1Тестовый флаг
custom3Всегда true

Пример URL

https://your-site.com/login?
auto_login=true&
joker_login=true&
custom3=true&
custom4=https%3A%2F%2Fauth.kukuruku.win%2Frealms%2Fpublic&
order_id=550e8400-e29b-41d4-a716-446655440000&
custom2=550e8400-e29b-41d4-a716-446655440000&
sub_id5=7e77c7af-50a1-411d-8e3c-5eeda15891fc

Руководство по реализации

Шаг 1: Обнаружение автовхода

Проверяйте параметр auto_login=true на вашей целевой странице:

const params = new URLSearchParams(window.location.search);

if (params.get('auto_login') === 'true') {
const issuerUrl = params.get('custom4');
const orderId = params.get('order_id');

// Инициировать OAuth вход
initiateKukurukuLogin(issuerUrl, orderId);
}

Шаг 2: Аутентификация через KukurukuID

Используйте параметр custom4 как URL издателя OAuth для инициации Authorization Code Flow:

function initiateKukurukuLogin(issuerUrl, orderId) {
const state = JSON.stringify({ orderId });
const authUrl = `${issuerUrl}/protocol/openid-connect/auth` +
`?client_id=${YOUR_CLIENT_ID}` +
`&redirect_uri=${encodeURIComponent(YOUR_CALLBACK_URL)}` +
`&response_type=code` +
`&scope=openid+profile+email` +
`&state=${encodeURIComponent(state)}`;

window.location.href = authUrl;
}

Шаг 3: Обработка OAuth callback

Обменяйте код авторизации на токены и идентифицируйте пользователя:

app.get('/callback', async (req, res) => {
const { code, state } = req.query;
const { orderId } = JSON.parse(state);

// Обмен кода на токены
const tokens = await exchangeCodeForTokens(code);

// Получение профиля пользователя
const user = await getUserProfile(tokens.access_token);

// Найти или создать пользователя по email
const localUser = await findOrCreateUser(user.data.email);

// Сохранить контекст ордера для сопоставления с callback'ом
await storeOrderContext(orderId, localUser.id);

// Перенаправить на платформу
res.redirect('/dashboard');
});

Шаг 4: Обработка callback оплаты

Kukuruku асинхронно отправляет callback оплаты. При получении:

app.post('/kukuruku/callback', (req, res) => {
// 1. Проверить подпись
const isValid = verifySignature(req.body, req.headers.signature);
if (!isValid) return res.status(401).json({ success: false });

// 2. Найти пользователя по email из callback'а
const user = findUserByEmail(req.body.user_email);

// 3. Зачислить баланс
if (req.body.status === 'paid') {
creditUserBalance(user.id, req.body.amount, req.body.currency);
}

res.json({ success: true });
});
Важно

Callback оплаты и редирект пользователя могут прийти в любом порядке. Ваша реализация должна обрабатывать оба сценария:

  1. Пользователь приходит первым, callback позже — создать сессию, зачислить баланс при получении callback'а
  2. Callback приходит первым, пользователь позже — зачислить баланс, создать сессию при появлении пользователя

Используйте user_email из callback'а для сопоставления с пользователем, аутентифицированным через OAuth.

Настройка URL мерчанта

URL вашей платформы настраивается в системе Kukuruku. Каждый мерчант может иметь несколько URL (для A/B тестирования или балансировки нагрузки). Система выбирает один случайным образом при каждом редиректе.

Свяжитесь с командой Kukuruku для регистрации или обновления URL вашей платформы.

Полный пример (Express.js)

const express = require('express');
const axios = require('axios');
const sha512 = require('js-sha512').sha512;

const AUTH_URL = 'https://auth.kukuruku.win/realms/public';
const API_URL = 'https://api.kukuruku.win';
const CLIENT_ID = 'your-client-id';
const CLIENT_SECRET = 'your-client-secret';
const SECRET_KEY = 'your-merchant-secret-key';
const CALLBACK_URL = 'https://your-site.com/auth/callback';

const app = express();
app.use(express.json());

// Целевая страница — обнаружение автовхода
app.get('/', (req, res) => {
if (req.query.auto_login === 'true') {
const issuer = req.query.custom4;
const orderId = req.query.order_id;
const state = Buffer.from(JSON.stringify({ orderId })).toString('base64');

return res.redirect(
`${issuer}/protocol/openid-connect/auth` +
`?client_id=${CLIENT_ID}` +
`&redirect_uri=${encodeURIComponent(CALLBACK_URL)}` +
`&response_type=code` +
`&scope=openid+profile+email` +
`&state=${state}`
);
}
res.render('home');
});

// OAuth callback
app.get('/auth/callback', async (req, res) => {
const { code, state } = req.query;
const { orderId } = JSON.parse(
Buffer.from(state, 'base64').toString()
);

// Обмен кода на токены
const { data: tokens } = await axios.post(
`${AUTH_URL}/protocol/openid-connect/token`,
new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'authorization_code',
code,
redirect_uri: CALLBACK_URL,
})
);

// Получение профиля из API Kukuruku
const { data: profile } = await axios.get(`${API_URL}/api/v1/me`, {
headers: { Authorization: `Bearer ${tokens.access_token}` },
});

// Найти или создать пользователя
const user = await findOrCreateUser({
kukurukuId: profile.data.id,
name: profile.data.first_name,
});

// Создать сессию
req.session.userId = user.id;
req.session.orderId = orderId;
res.redirect('/dashboard');
});

// Callback оплаты от Kukuruku
app.post('/kukuruku/callback', (req, res) => {
// Проверка HMAC-SHA512 подписи
const expectedSignature = sha512.hmac(
SECRET_KEY, JSON.stringify(req.body)
);
if (expectedSignature !== req.headers.signature) {
return res.status(401).json({ success: false });
}

// Обработка платежа
if (req.body.status === 'paid') {
creditBalance(req.body.user_email, req.body.amount, req.body.currency);
}

res.json({ success: true });
});