Ebook download
This flow keeps payment, download ownership, and optional email delivery as separate durable facts.
import { Billing, DownloadEmails, Downloads, Offer, Purchase, authorizeDownload, createCheckout, processPaymentNotification, registerOffers,} from "@byfungsi/sapa";import { Effect } from "effect";
const ebookDownload = yield * Downloads.download({ asset: { key: "ebook.effect.pdf", revision: 1 }, duration: "perpetual", });const ebookEmail = yield * DownloadEmails.customer({ asset: { key: "ebook.effect.pdf", revision: 1 }, });const ebookPurchase = yield * Purchase.parse({ key: "ebook.effect.benefits", revision: 1, provides: [ebookDownload, ebookEmail], });const ebookBilling = yield * Billing.oneTime({ price: { currency: "IDR", amount: 99_000n }, });const ebook = yield * Offer.parse({ key: "ebook.effect", revision: 1, purchase: ebookPurchase, billing: ebookBilling, });
yield * registerOffers([ebook]);
const checkout = yield * createCheckout({ type: "offer", offerKey: ebook.key, offerRevision: ebook.revision, quantity: null, provider: "midtrans", customer: { externalId: "customer-42", email: "buyer@example.com", name: "Example Buyer", }, successUrl: "https://merchant.example/orders/success", cancelUrl: "https://merchant.example/orders/canceled", clientIp: null, idempotencyKey: "ebook-order-42", });
// Redirect the browser to checkout.url. Later, in the webhook handler:const settlement = yield * processPaymentNotification({ provider: "midtrans", payload: rawProviderPayload, });
if (settlement.status === "settled") { // Run the deployment's fulfillment/email worker independently.}
// In a later authenticated customer request:const download = yield * authorizeDownload({ externalCustomerId: "customer-42", asset: { key: "ebook.effect.pdf", revision: 1 }, });Install asset revision ebook.effect.pdf@1 before registration. Return
download.url only after your host authenticates that the caller owns
customer-42. The URL is bounded by both the configured link lifetime and the
historical eligibility end. A refund makes subsequent authorization fail even
if email delivery is still retrying.
See Downloads for asset adapter and signed-link requirements.