use std::error::Error;
use kasapay::iyzico::classic::{Client as Iyzipay, Config as IyzicoConfig};
use kasapay::paytr::{Config as PaytrConfig, Credentials as PaytrCredentials, PayTr};
use kasapay::{
Address, BasketItem, Buyer, ChargeRequest, Currency, ErrorKind, Money, NextAction, OrderRef,
Provider,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let provider: Box<dyn Provider> = match std::env::var("KASAPAY_PROVIDER")?.as_str() {
"iyzico" => Box::new(Iyzipay::new(IyzicoConfig::sandbox(
kasapay::iyzico::Credentials::new(
std::env::var("IYZICO_API_KEY")?,
std::env::var("IYZICO_SECRET_KEY")?,
),
))?),
"paytr" => Box::new(PayTr::new(
PaytrConfig::new(PaytrCredentials::new(
std::env::var("PAYTR_MERCHANT_ID")?,
std::env::var("PAYTR_MERCHANT_KEY")?,
std::env::var("PAYTR_MERCHANT_SALT")?,
))
.test_mode(),
)?),
other => return Err(format!("no provider called {other}").into()),
};
let coffee = Money::parse("74.95", Currency::Try)?;
let request = ChargeRequest::builder(
OrderRef::new("ord-2026-0007"),
Money::parse("149.90", Currency::Try)?,
)
.return_url("https://merchant.example/paid".parse()?)
.failure_url("https://merchant.example/failed".parse()?)
.buyer(
Buyer::new("Ayse", "ayse@example.test")
.surname("Yilmaz")
.identity_number("11111111111")
.phone("+905350000000")
.ip("203.0.113.7")
.address(Address::new("Bagdat Cad. 1", "Istanbul", "Turkey").zip_code("34000")),
)
.item(
BasketItem::new("sku-kahve", "Kahve", coffee)
.category("Icecek")
.quantity(2),
)
.build()?;
let charge = provider.charge(&request).await?;
println!("{} says: {:?}", provider.id(), charge.status);
match &charge.next_action {
Some(NextAction::Redirect { url, .. }) => println!("send the payer to {url}"),
Some(other) => println!("this build does not know how to finish {other:?}"),
None => println!("no redirect: the payment is already decided"),
}
let incomplete = ChargeRequest::builder(
OrderRef::new("ord-2026-0008"),
Money::parse("149.90", Currency::Try)?,
)
.return_url("https://merchant.example/paid".parse()?)
.build()?;
match provider.charge(&incomplete).await {
Ok(_) => return Err("a payment with no buyer should not have opened".into()),
Err(error) => {
assert_eq!(error.kind(), ErrorKind::InvalidRequest);
println!("refused before the network: {error}");
}
}
Ok(())
}