Initial public commit

This commit is contained in:
Keysat
2026-05-07 10:40:53 -05:00
commit 50952b631a
12 changed files with 1157 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
//! Minimum-viable license check, entirely offline.
//!
//! Run with:
//!
//! cargo run --example offline_verify --no-default-features --features offline -- <LIC1-...>
//!
//! In real life you'd embed the public key with `include_str!` — here we
//! read it from an env var so the example has zero build-time coupling.
use licensing_client::{PublicKeyPem, Verifier};
use std::env;
fn main() {
let pem = env::var("LICENSING_PUBKEY_PEM").expect("set LICENSING_PUBKEY_PEM to your issuer's public key");
let key = env::args()
.nth(1)
.expect("pass a license key as the first argument");
let verifier = Verifier::new(PublicKeyPem::from_str(&pem).expect("parse pubkey"));
match verifier.verify(&key) {
Ok(ok) => {
println!("license OK");
println!(" license_id = {}", ok.license_id);
println!(" product_id = {}", ok.product_id);
println!(" issued_at = {}", ok.payload.issued_at);
}
Err(e) => {
eprintln!("license REJECTED: {e}");
std::process::exit(1);
}
}
}
+48
View File
@@ -0,0 +1,48 @@
//! 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, None, None)
.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(())
}