#malaysia #payment #fpx

billplz

Rust SDK for the Billplz payment gateway API

1 unstable release

0.1.0 Feb 25, 2026

#1774 in Web programming

MIT license

31KB
733 lines

billplz-rs

Rust SDK for the Billplz API.

Installation

Add to your Cargo.toml:

[dependencies]
billplz = { git = "https://github.com/qhkm/billplz-rs" }
tokio = { version = "1", features = ["full"] }

Setup

use billplz::{BillplzClient, Environment};

// Production
let client = BillplzClient::new(Environment::Production, "your-api-key");

// Staging / Sandbox
let client = BillplzClient::new(Environment::Staging, "your-api-key");

Usage

Collections

Get Collection

let collection = client.get_collection("ei3a6mdl").await?;
println!("Title: {}", collection.title);
println!("Status: {}", collection.status);

Create Collection

let collection = client
    .create_collection("My Collection")
    .send()
    .await?;
println!("ID: {}", collection.id);

Create Collection with Split Payments

let collection = client
    .create_collection("Split Collection")
    .split_header(true)
    .split_payment_with_fixed_cut("partner@example.com", 100, 0)
    .split_payment_with_variable_cut("partner2@example.com", "20", 1)
    .send()
    .await?;

Bills

Create Bill

let bill = client
    .create_bill(
        "collection_id",
        "customer@example.com",
        "John Doe",
        10000, // amount in cents (RM 100.00)
        "https://example.com/callback",
        "Invoice #123",
        "2024-12-31",
    )
    .mobile("60191234567")
    .redirect_url("https://example.com/redirect")
    .reference_1_label("Reference")
    .reference_1("INV-123")
    .send()
    .await?;
println!("Bill URL: {:?}", bill.url);

Get Bill

let bill = client.get_bill("bill_id").await?;
println!("Paid: {}", bill.paid);
println!("State: {}", bill.state);

Banks

Get FPX Banks

Returns the list of Malaysian FPX banks. Staging environment includes test banks.

let banks = client.get_fpx_banks();
for bank in &banks {
    println!("{}: {}", bank.bank_code, bank.bank_name);
}

Verify Bank Account

let result = client.get_bank_verification("999988887777").await?;
println!("{}", result);

Create Bank Verification

Required for mass payment (payout) recipients.

let result = client
    .create_bank_verification("John Doe", "91234567890", "999988887777", "MBBEMYKL")
    .organization(true)
    .send()
    .await?;

Payout Collections

Create Payout Collection

let result = client
    .create_payout_collection("Salary Payments")
    .send()
    .await?;

Get Payout Collection

let result = client.get_payout_collection("payout_collection_id").await?;

Payouts (Mass Payment Instructions)

Create Payout

let result = client
    .create_payout(
        "payout_collection_id",
        "MBBEMYKL",
        "999988887777",
        "91234567890",
        "John Doe",
        "Salary for January",
        50000, // RM 500.00
    )
    .send()
    .await?;

Get Payout

let result = client.get_payout("payout_id").await?;

Error Handling

All methods return Result<T, BillplzError>. The error enum covers three cases:

use billplz::BillplzError;

match client.get_bill("invalid").await {
    Ok(bill) => println!("Got bill: {}", bill.id),
    Err(BillplzError::Api { error_type, message }) => {
        // Billplz API returned an error (e.g. unauthorized, not found)
        eprintln!("API error ({}): {}", error_type, message);
    }
    Err(BillplzError::Http(e)) => {
        // Network / HTTP error
        eprintln!("HTTP error: {}", e);
    }
    Err(BillplzError::Parse(e)) => {
        // JSON parsing error
        eprintln!("Parse error: {}", e);
    }
}

Reference

Dependencies

~6–21MB
~232K SLoC