5dd301cd69
Mirrors the TS SDK 0.2.0 changes (cf c3a57a0 in keysat-client-ts) so
all four language clients have parity on the tiered-purchase surface.
Breaking change on start_purchase: positional `(buyer_email,
redirect_url)` args replaced with a `&StartPurchaseOptions` struct.
Migration is mechanical:
// before
client.start_purchase(slug, None, None).await?;
// after
client.start_purchase(slug, &Default::default()).await?;
// tier-aware
client.start_purchase(slug, &StartPurchaseOptions {
policy_slug: Some("pro"),
buyer_email: Some("buyer@example.com"),
..Default::default()
}).await?;
The struct has fields for buyer_email, buyer_note, redirect_url,
code, and the new policy_slug. New `list_public_policies` method
fetches the buyer-visible tier list (no auth) so an in-app tier
picker can render dynamically.
Lib + tests build clean; the example's anyhow-not-in-deps issue is
pre-existing and unrelated.
49 lines
1.6 KiB
Rust
49 lines
1.6 KiB
Rust
//! Full purchase-and-validate round trip against a running
|
|
//! licensing-service instance.
|
|
//!
|
|
//! cargo run --example online_validate --features online -- <base-url> <product-slug>
|
|
//!
|
|
//! The example will start a purchase, print the BTCPay checkout URL for
|
|
//! you to pay, then poll until a license key is issued and validate it.
|
|
|
|
use licensing_client::online::Client;
|
|
use std::time::Duration;
|
|
use tokio::time::sleep;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
let mut args = std::env::args().skip(1);
|
|
let base_url = args.next().expect("pass base URL, e.g. https://license.example.com");
|
|
let product_slug = args.next().expect("pass product slug");
|
|
|
|
let client = Client::new(&base_url)?;
|
|
|
|
let session = client
|
|
.start_purchase(&product_slug, &Default::default())
|
|
.await?;
|
|
println!("open the checkout in your browser:");
|
|
println!(" {}", session.checkout_url);
|
|
println!("waiting for settlement...");
|
|
|
|
let license = loop {
|
|
sleep(Duration::from_secs(5)).await;
|
|
let p = client.poll_purchase(&session.invoice_id).await?;
|
|
if let Some(k) = p.license_key {
|
|
break k;
|
|
}
|
|
println!(" status: {}", p.status);
|
|
if p.status == "expired" || p.status == "invalid" {
|
|
anyhow::bail!("invoice ended in status {}", p.status);
|
|
}
|
|
};
|
|
|
|
println!("license issued:\n {license}");
|
|
|
|
let validated = client
|
|
.validate(&license, Some(&product_slug), None)
|
|
.await?;
|
|
println!("server says: ok={} reason={:?}", validated.ok, validated.reason);
|
|
|
|
Ok(())
|
|
}
|