RuStore. url для получения токена авторизации
В инструкции по работе с API RuStore указаны параметры взаимодействия для получения токена авторизации, https://help.rustore.ru/rustore/for_developers/worki_with_RuStore_API/authorization_token_RuStore_API
По данной инструкции есть два вопроса:
1 не указано на какой url нужно отправлять POST запрос

2 что значит "Только для запросов, подписанных приватным ключом, публичная часть которого загружена соответствующим владельцем в систему RuStore Консоль" ?

(в системе зарегистрирован, заявление на монетизацию подписано с помощью ЭЦП и получен статус "одобрено". Приватный ключ в личном кабинете сгенерирован).
Кто-нибудь проходил этот "квест" до конца ? )
Ответы (6 шт):
После продолжительной переписки с поддержкой (номер тикета запроса [VKS-19386]) найден правильный ответ.
<?PHP
//https://help.rustore.ru/rustore/for_developers/worki_with_RuStore_API/authorization_token_RuStore_API
$tnow = time();
$company_id = 1234567890;//id компании в магазине rustore
$year_month_day = date("Y-m-d");
$hour_minute_seconds = date("H:i:s");
$clock_belt = '+03:00';//на странице поддержки указан часовой пояс +3
//на нашем сервере часовой пояс тоже +3. У Вас может быть другой.
//собираем строку которую будем подписывать
$string_to_sign = $company_id;
$times = $year_month_day;
$times .= 'T';
$times .= $hour_minute_seconds;
$times .= $clock_belt;
$string_to_sign .= $times;
//получаем строку формата 2023-07-08T13:24:41+03:00
//private_key сгенерированный в личном кабинете магазина rustore.
$private_key = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgАБВГД
-----END RSA PRIVATE KEY-----
EOD;
//все доступные методы подписи заносим в массив
$Array_allowed_crypt_method = openssl_get_md_methods(true);
//выбираем метод шифрования
//var_dump($Array_allowed_crypt_method);
//var_dump($Array_allowed_crypt_method[48]);//"sha512WithRSAEncryption"
//этот метод подписи соответствует указанному в RuStore SHA512withRSA, //но на разных серверах номер этого метода может отличаться (у нас это [48]);
//При неверно выбранном методе формирования подписи сервер RuStore будет выдавать ошибку "signature_encode_error"!
$algo = $Array_allowed_crypt_method[48];//"sha512WithRSAEncryption"
//формируем подпись
$make_signature = openssl_sign($string_to_sign, $binary_signature, $private_key, $algo);//
if($make_signature < 1)
{
echo "ошибка при формировании подписи";
die();
}
//подпись $binary_signature содержит символы не входящие в кодировку UTF-8;
//$binary_signature невозможно конвертировать в JSON для передачи в body
//конвертируем $binary_signature в base64
$signature_64 = base64_encode($binary_signature);
//POST запрос в магазин//
$url = 'https://public-api.rustore.ru/public/auth';
//вариант сборки JSON из массива для тела запроса
$Array_body = Array();
$Array_body['companyId'] = "$company_id";
$Array_body['timestamp'] = "$times";
$Array_body['signature'] = $signature_64;//
$JSON_for_body = json_encode($Array_body);
//echo "Есть ли ошибка при формировании JSON ? \n";
//print_r(json_last_error_msg());
//опции потока запроса
$options = array('http' =>
array(
'method' => 'POST',
'header' => "Content-Type: application/json\r\n".
"Accept: application/json\r\n",
'content' => $JSON_for_body,
'timeout' => 60,
'ignore_errors' => true
)
);
// ! опция 'ignore_errors' => true нужна чтоб увидеть ответ сервера RuStore если Error_Code не 200.
//формируем поток с опциями
$context = stream_context_create($options);
//выполняем запрос
$otvet = file_get_contents($url, false, $context, -1, 40000);
$otvet = json_decode($otvet);
var_dump($otvet);
?>
Написал модуль Rustore Api на C#. Вот ссылка на github https://github.com/deniszhigalov/rustore-api. Можно установить пакет с nuget.org https://www.nuget.org/packages/RustoreApi/
Следующий этап работы с API - получения от сервера RuStore данных платежа клиента по subscription_token.
Справка описана здесь
https://help.rustore.ru/rustore/for_developers/worki_with_RuStore_API/public_api_1

но не указан URL на который нужно направлять запрос GET /public/purchases/{subscription_token}
Правильный URL https://pay-backapi.rustore.ru/public/purchases/{subscription_token}
Может поможет кому-нибудь )
Может быть кому-то потребуется код для получения подписи на python (слегка измененный вариант, полученный от разработчиков VKS-27749). Для корректной работы нужно подключить модуль pycryptodome
import base64
import json
from datetime import datetime
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA512
from Crypto.PublicKey import RSA
secret_private = b'MIIEvgIBADANBgk' # сюда занести сгенерированный в консоли privatekey
company_id = "тут идентификатор компании, полученный из консоли rustore"
def generate():
key = RSA.import_key(base64.b64decode(secret_private))
# формируем строку для подписи
sdt = datetime.now().isoformat()+"+03:00"
to_sign = company_id + sdt
print("Get hash from: " + to_sign)
# формируем хеш
hash = SHA512.new(to_sign.encode())
# формируем подпись
binary_signature = pkcs1_15.new(key).sign(hash)
signature = base64.b64encode(binary_signature).decode('utf-8')
print("SIGN: " + signature)
# формируем результат в формате JSON
result = {
"companyId": company_id,
"timestamp": sdt,
"signature": signature
}
return json.dumps(result)
Реализация авторизации на typescript. Сохраню для тех, кто придет сюда с этим вопросом)
import * as moment from 'moment';
import { createSign } from 'node:crypto';
import axios from 'axios';
const API_URL = 'https://public-api.rustore.ru';
enum Path {
Auth = '/public/auth/',
}
export class RSAuth {
private readonly privateKey: string =
'-----BEGIN PRIVATE KEY-----\n' +
'MIIEvgIBADANBgkq...\n' +
'-----END PRIVATE KEY-----';
private readonly companyId = 123;
// constructor() {} // private readonly companyId: string, // private readonly privateKey: string,
public async auth() {
const dateStr = moment().format();
const str = `${this.companyId}${dateStr}`;
const sign = createSign('RSA-SHA512');
sign.write(str);
sign.end();
const signature = sign.sign(this.privateKey, 'base64');
console.log('Sign: ', signature);
try {
const result = await axios.post(`${API_URL}${Path.Auth}`, {
timestamp: dateStr,
companyId: this.companyId,
signature,
});
console.log('result :>> ', result);
} catch (e) {
console.log(e);
}
}
}
Внесу свой вклад, вот мой код для получение токена под Laravel.
$companyId = env('RU_STORE_COMPANY_ID'); // Код компании в RuStore
$time = now()->toIso8601String();
$privateKey = file_get_contents(base_path(env('RU_STORE_PRIVATE_KEY'))); // Секретный ключ
// Вместо openssl_get_md_methods, можно сразу использовать OPENSSL_ALGO_SHA512
if (!openssl_sign($companyId . $time, $signatureBinary, $privateKey, OPENSSL_ALGO_SHA512)) {
return sendResponse(__(''), false, 400);
}
// Формирование запроса через Illuminate\Support\Facades\Http
$requestBody = [
'companyId' => $companyId,
'timestamp' => $time,
'signature' => base64_encode($signatureBinary)
];
$http = Http::withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
])
->timeout(60)
->post('https://public-api.rustore.ru/public/auth', $requestBody);
$response = $http->json();
// Выводим полученный результат
dd($response);
