※ Lagom

Demo Example

This page will demonstrate how we implemented Lagom on our Demo webpage. This webpage runs on a Fastly Compute at Edge service, fully stateless. We will show you how to add a payment link to the page, and how to verify the payment on the server side.

The full code of this demo is available on our Integration Example github repository

Initial Setup

First, we need to serve the landing page, which is in this example the snippet of an article.

fn main(req: Request) -> Result<Response, Error> {
    let article = include_str!("article.html").to_string();
	let body = article.as_bytes()
    Ok(Response::from_status(StatusCode::OK)
        .with_content_type(mime::TEXT_HTML_UTF_8)
        .with_body(body))
}

We will now add the payment link to the article snippet. This link will redirect the user to the Lagom payout page. We used the same inlined Javascript function as in the Recommended Implementation.

<a href="#" onclick="(function a(event) { location.href = 'https://lagom.org/payout?amount=100&provider=test-provider&cb=' + btoa(location.href) })()">
    This is a paid article, click here to read with Lagom
</a>

Verifying the payment

The payment link has been added to the snippet webpage, we can now verify the payment.

fn main(req: Request) -> Result<Response, Error> {
	let article = include_str!("article.html").to_string();
	let full_article = include_str!("full/article.html").to_string();

	let body = match lagom_verify(&req, "/", 100) {
		Ok(_) => full_article,
		Err(_) => article,
	};

	Ok(Response::from_status(StatusCode::OK)
		.with_content_type(mime::TEXT_HTML_UTF_8)
		.with_body(body))
}

The lagom_verify function will perform the payment verification. This function will verify the signature, and check the timestamp to ensure the payment is valid and recent (within 10 seconds).

fn lagom_verify(req: &Request, page: &str, amount: i64) -> Result<(), Error> {
    //  extract callback params from URL, decode and parse
    let lguid = req.get_query_parameter("lguid").unwrap_or_default();
    let lgts = req.get_query_parameter("lgts").unwrap_or_default();
    let lgsig = req.get_query_parameter("lgsig").unwrap_or_default();
    let lgid = req.get_query_parameter("lgid").unwrap_or_default();
    let lgamt = req.get_query_parameter("lgamt").unwrap_or_default();

    // verify timestamp freshness
    if chrono::Utc::now().timestamp() > lgts.parse::<i64>()? + 10 {
        return err("This link has expired");
    }

    // check amount and page
    if lgamt.parse::<i64>()? != amount || req.get_path() != page {
        return err("This link is not valid");
    }

    // verify signature with pre shared secret
    let verif = lguid.to_string() + lgid + lgts + page + lgamt;
    let good = hmac_sha256::HMAC::mac(&verif.as_bytes(), SECRET);
    if lgsig != hex::encode(good) {
        return err("This link is not valid");
    }

    Ok(())
}

Conclusion

This example demonstrates how to implement Lagom on a Fastly Compute at Edge service. This minimal example runs in a completely stateless environment on the Fastly Edge servers.