bazzar/pay_u/README.md

3.2 KiB

Payu REST API

Install

cargo add pay_u

Usage

async fn usage() {
    let client_id = ClientId::new(std::env::var("PAYU_CLIENT_ID").unwrap());
    let client_secret = ClientSecret::new(std::env::var("PAYU_CLIENT_SECRET").unwrap());
    let merchant_id = std::env::var("PAYU_CLIENT_MERCHANT_ID").unwrap().parse::<i32>().map(MerchantPosId::from).unwrap();
    let mut client = Client::new(client_id, client_secret, merchant_id);
    client.authorize().await.expect("Invalid credentials");

    let _res = client.create_order(
        OrderCreateRequest::new(
            Buyer::new("john.doe@example.com", "654111654", "John", "Doe", "pl"),
            "127.0.0.1",
            "PLN",
        )
            // Endpoint which will be requested by PayU with payment status update
            .with_notify_url("https://your.eshop.com/notify")
            // payment description (MANDATORY)
            .with_description("RTV market")
            // add list of products
            .with_products(
                [
                    Product::new("Wireless Mouse for Laptop", 15000, 1),
                    Product::new("HDMI cable", 6000, 1),
                ]
                    .into_iter(),
            )
            // add additional product
            .with_product(Product::new("HDMI cable", 6000, 1)),
    )
        .await;

    // partial refund
    let _res = client
        .refund(
            OrderId::new("H9LL64F37H160126GUEST000P01"),
            RefundRequest::new("Refund", Some(1000)),
        )
        .await;
    // Full refund
    let _res = client
        .refund(
            OrderId::new("H9LL64F37H160126GUEST000P01"),
            RefundRequest::new("Refund", None),
        )
        .await;
    
    // Order details
    let _res = client.order_details(OrderId::new("H9LL64F37H160126GUEST000P01")).await;
    
    // Transactions
    let _res = client.order_transactions(OrderId::new("H9LL64F37H160126GUEST000P01")).await;
}

Actix integration

use actix_web::{*, web::*};

#[post("/checkout")]
async fn checkout(session: Data<Session>, db: Data<Database>, payu: Data<Arc<Mutex<pay_u::Client>>>) -> HttpResponse {
    let user_id = session.user_required()?;
    let payu = payu.into_inner();
    let shopping_cart = db.send(LoadShoppingCart { user_id }).await??;
    let shopping_cart_id = shopping_cart.id;
    let create_order_req: pay_u::OrderCreateRequest = shopping_cart.into();
    let pay_u::res::CreateOrder { redirect_uri, order_id, .. } = payu.create_order(create_order_req).await?;
    db.send(database::CreateOrder { shopping_cart_id, order_id }).await??;
    HttpResponse::SeeOther().append_header((actix_web::http::header::LOCATION, redirect_uri)).body("")
}

#[post("/pay_u/{own_order_id}/notify")]
async fn handle_notification(path: Path<i32>, Json(notify): Json<pay_u::notify::StatusUpdate>) -> HttpResponse {
    let status = notify.status();
    let order_id = path.into_inner();
    match handle_update(order_id, status, notify) {
        Ok(_) => (),
        Err(e) => {
            // ALWAYS SEND OK!
            log::error!("{e:?}");
        }
    };
    HttpResponse::Ok().body("")
}

Bugs

Please report bugs here: https://todo.sr.ht/~tsumanu/payu-rs