Rust клиент для работы с API платежной системы Tbank (Tinkoff).
- Инициализация платежей
- Подтверждение и отмена платежей
- Работа с сохраненными картами
- Рекуррентные платежи
- 3D Secure аутентификация
- QR-код платежи
- Управление клиентами
- Поддержка чеков (54-ФЗ)
Добавьте в Cargo.toml
:
[dependencies]
tbank-payments = { path = "." }
tokio = { version = "1", features = ["full"] }
use tbank_payments::{TbankClient, Result};
#[tokio::main]
async fn main() -> Result<()> {
// Создание клиента
let client = TbankClient::new(
"YOUR_TERMINAL_KEY".to_string(),
"YOUR_PASSWORD".to_string()
);
// Инициализация платежа
let init_request = client.create_init_request(
100000, // 1000 рублей в копейках
"ORDER-123".to_string(),
Some("Описание платежа".to_string())
);
let response = client.init(init_request).await?;
println!("Payment URL: {:?}", response.payment_url);
Ok(())
}
let mut init_request = client.create_init_request(
100000, // Сумма в копейках
"ORDER-123".to_string(),
Some("Описание".to_string())
);
// Опциональные параметры
init_request.customer_key = Some("CUSTOMER-123".to_string());
init_request.recurrent = Some("Y".to_string()); // Для рекуррентных платежей
init_request.language = Some("ru".to_string());
let response = client.init(init_request).await?;
let state = client.get_state("payment_id".to_string()).await?;
println!("Статус: {}", state.status);
let confirm_response = client.confirm(
"payment_id".to_string(),
Some(50000) // Частичное подтверждение
).await?;
let cancel_response = client.cancel(
"payment_id".to_string(),
Some(50000), // Частичная отмена
None // Без чека
).await?;
// 1. Создание клиента
client.add_customer(
"CUSTOMER-123".to_string(),
Some("email@example.com".to_string()),
Some("+79123456789".to_string())
).await?;
// 2. Запрос на добавление карты
let add_card_response = client.add_card(
"CUSTOMER-123".to_string(),
Some("NO".to_string()), // Тип проверки
Some("Основная карта".to_string())
).await?;
// 3. Пользователь вводит данные карты по URL
println!("URL для ввода карты: {:?}", add_card_response.payment_url);
let cards = client.get_card_list("CUSTOMER-123".to_string()).await?;
for card in cards.cards {
println!("Карта: {} ({})", card.pan, card.status);
}
client.remove_card(
"CUSTOMER-123".to_string(),
"card_id".to_string()
).await?;
// 1. Первый платеж с сохранением карты
let mut init_request = client.create_init_request(
100000,
"ORDER-001".to_string(),
Some("Первый платеж".to_string())
);
init_request.customer_key = Some("CUSTOMER-123".to_string());
init_request.recurrent = Some("Y".to_string());
let init_response = client.init(init_request).await?;
// 2. После успешной оплаты получаем rebill_id
// 3. Последующие платежи
let charge_response = client.charge(
"new_payment_id".to_string(),
"rebill_id".to_string()
).await?;
// 1. Создание платежа
let init_response = client.init(init_request).await?;
// 2. Получение QR-кода
let qr = client.get_qr(
init_response.payment_id.clone(),
Some("PAYLOAD".to_string())
).await?;
println!("QR data: {}", qr.data);
// 3. Проверка статуса
let qr_state = client.get_qr_state(init_response.payment_id).await?;
// 1. Проверка версии 3DS
let version = client.check_3ds_version(
"payment_id".to_string(),
None
).await?;
// 2. Завершение авторизации
let finish_request = FinishAuthorizeRequest {
terminal_key: "terminal_key".to_string(),
payment_id: "payment_id".to_string(),
token: String::new(),
card_data: Some("encrypted_data".to_string()),
amount: Some(100000),
data: None,
route: None,
source: None,
};
let finish_response = client.finish_authorize(finish_request).await?;
// 3. Если требуется 3DS
if let Some(acs_url) = finish_response.acs_url {
// Перенаправить пользователя на acs_url
// После возврата:
// Для 3DS v1:
client.submit_3ds_authorization(
"md".to_string(),
"pa_res".to_string()
).await?;
// Для 3DS v2:
client.submit_3ds_authorization_v2(
"payment_id".to_string(),
"cres".to_string()
).await?;
}
use tbank_payments::models::{Receipt, Item};
let mut init_request = client.create_init_request(
150000,
"ORDER-124".to_string(),
Some("Платеж с чеком".to_string())
);
init_request.receipt = Some(Receipt {
email: Some("customer@example.com".to_string()),
phone: Some("+79123456789".to_string()),
taxation: "osn".to_string(), // Система налогообложения
items: vec![
Item {
name: "Товар 1".to_string(),
price: 50000, // Цена за единицу
quantity: 2.0,
amount: 100000, // Общая сумма
tax: "vat20".to_string(), // НДС 20%
ean13: None,
},
Item {
name: "Товар 2".to_string(),
price: 50000,
quantity: 1.0,
amount: 50000,
tax: "vat10".to_string(), // НДС 10%
ean13: None,
},
],
});
use tbank_payments::TbankError;
match client.init(request).await {
Ok(response) => {
// Успешно
}
Err(TbankError::Api { code, message }) => {
println!("API ошибка {}: {}", code, message);
}
Err(TbankError::Http(e)) => {
println!("HTTP ошибка: {}", e);
}
Err(e) => {
println!("Другая ошибка: {}", e);
}
}
Для тестирования используйте тестовое окружение:
let client = TbankClient::with_api_url(
"TinkoffBankTest".to_string(),
"TinkoffBankTest".to_string(),
"https://rest-api-test.tinkoff.ru/v2".to_string()
);
Полные примеры использования находятся в директории examples/
:
examples/advanced.rs
- расширенные примеры всех возможностей
Запуск примеров:
cargo run --example advanced
- Никогда не храните пароль терминала в коде
- Используйте переменные окружения для хранения секретных данных
- Всегда используйте HTTPS
- Валидируйте входные данные перед отправкой
MIT