# Payment Integration Guide This guide shows how to sell your encrypted `.smsg` content and deliver license keys (passwords) to customers using popular payment processors. ## Overview The dapp.fm model is simple: ``` 1. Customer pays via Stripe/Gumroad/PayPal 2. Payment processor triggers webhook or delivers digital product 3. Customer receives password (license key) 4. Customer downloads .smsg from your CDN/IPFS 5. Customer decrypts with password - done forever ``` No license servers, no accounts, no ongoing infrastructure. ## Stripe Integration ### Option 1: Stripe Payment Links (Easiest) No code required - use Stripe's hosted checkout: 1. Create a Payment Link in Stripe Dashboard 2. Set up a webhook to email the password on successful payment 3. Host your `.smsg` file anywhere (CDN, IPFS, S3) **Webhook endpoint (Node.js/Express):** ```javascript const express = require('express'); const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); const nodemailer = require('nodemailer'); const app = express(); // Your content passwords (store securely!) const PRODUCTS = { 'prod_ABC123': { name: 'My Album', password: 'PMVXogAJNVe_DDABfTmLYztaJAzsD0R7', downloadUrl: 'https://ipfs.io/ipfs/QmYourCID' } }; app.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; let event; try { event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret); } catch (err) { return res.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'checkout.session.completed') { const session = event.data.object; const customerEmail = session.customer_details.email; const productId = session.metadata.product_id; const product = PRODUCTS[productId]; if (product) { await sendLicenseEmail(customerEmail, product); } } res.json({received: true}); }); async function sendLicenseEmail(email, product) { const transporter = nodemailer.createTransport({ // Configure your email provider service: 'gmail', auth: { user: process.env.EMAIL_USER, pass: process.env.EMAIL_PASS } }); await transporter.sendMail({ from: 'artist@example.com', to: email, subject: `Your License Key for ${product.name}`, html: `

Thank you for your purchase!

Download: ${product.name}

License Key: ${product.password}

How to play:

  1. Download the .smsg file from the link above
  2. Go to demo.dapp.fm
  3. Click "Fan" tab, then "Unlock Licensed Content"
  4. Paste the file and enter your license key

This is your permanent license - save this email!

` }); } app.listen(3000); ``` ### Option 2: Stripe Checkout Session (More Control) ```javascript const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); // Create checkout session app.post('/create-checkout', async (req, res) => { const { productId } = req.body; const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], line_items: [{ price: 'price_ABC123', // Your Stripe price ID quantity: 1, }], mode: 'payment', success_url: 'https://yoursite.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url: 'https://yoursite.com/cancel', metadata: { product_id: productId } }); res.json({ url: session.url }); }); // Success page - show license after payment app.get('/success', async (req, res) => { const session = await stripe.checkout.sessions.retrieve(req.query.session_id); if (session.payment_status === 'paid') { const product = PRODUCTS[session.metadata.product_id]; res.send(`

Thank you!

Download: ${product.name}

License Key: ${product.password}

`); } else { res.send('Payment not completed'); } }); ``` ## Gumroad Integration Gumroad is perfect for artists - handles payments, delivery, and customer management. ### Setup 1. Create a Digital Product on Gumroad 2. Upload a text file or PDF containing the password 3. Set your `.smsg` download URL in the product description 4. Gumroad delivers the password file on purchase ### Product Setup **Product Description:** ``` My Album - Encrypted Digital Download After purchase, you'll receive: 1. A license key (in the download) 2. Download link for the .smsg file How to play: 1. Download the .smsg file: https://ipfs.io/ipfs/QmYourCID 2. Go to https://demo.dapp.fm 3. Click "Fan" → "Unlock Licensed Content" 4. Enter your license key from the PDF ``` **Delivered File (license.txt):** ``` Your License Key: PMVXogAJNVe_DDABfTmLYztaJAzsD0R7 Download your content: https://ipfs.io/ipfs/QmYourCID This is your permanent license - keep this file safe! The content works offline forever with this key. Need help? Visit https://demo.dapp.fm ``` ### Gumroad Ping (Webhook) For automated delivery, use Gumroad's Ping feature: ```javascript const express = require('express'); const app = express(); app.use(express.urlencoded({ extended: true })); // Gumroad sends POST to this endpoint on sale app.post('/gumroad-ping', (req, res) => { const { seller_id, product_id, email, full_name, purchaser_id } = req.body; // Verify it's from Gumroad (check seller_id matches yours) if (seller_id !== process.env.GUMROAD_SELLER_ID) { return res.status(403).send('Invalid seller'); } const product = PRODUCTS[product_id]; if (product) { // Send custom email with password sendLicenseEmail(email, product); } res.send('OK'); }); ``` ## PayPal Integration ### PayPal Buttons + IPN ```html
``` **IPN Handler:** ```javascript const express = require('express'); const axios = require('axios'); app.post('/paypal-ipn', express.urlencoded({ extended: true }), async (req, res) => { // Verify with PayPal const verifyUrl = 'https://ipnpb.paypal.com/cgi-bin/webscr'; const verifyBody = 'cmd=_notify-validate&' + new URLSearchParams(req.body).toString(); const response = await axios.post(verifyUrl, verifyBody); if (response.data === 'VERIFIED' && req.body.payment_status === 'Completed') { const email = req.body.payer_email; const itemNumber = req.body.item_number; const product = PRODUCTS[itemNumber]; if (product) { await sendLicenseEmail(email, product); } } res.send('OK'); }); ``` ## Ko-fi Integration Ko-fi is great for tips and single purchases. ### Setup 1. Enable "Commissions" or "Shop" on Ko-fi 2. Create a product with the license key in the thank-you message 3. Link to your .smsg download **Ko-fi Thank You Message:** ``` Thank you for your purchase! Your License Key: PMVXogAJNVe_DDABfTmLYztaJAzsD0R7 Download: https://ipfs.io/ipfs/QmYourCID Play at: https://demo.dapp.fm (Fan → Unlock Licensed Content) ``` ## Serverless Options ### Vercel/Netlify Functions No server needed - use serverless functions: ```javascript // api/stripe-webhook.js (Vercel) import Stripe from 'stripe'; import { Resend } from 'resend'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); const resend = new Resend(process.env.RESEND_API_KEY); export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).end(); } const sig = req.headers['stripe-signature']; const event = stripe.webhooks.constructEvent( req.body, sig, process.env.STRIPE_WEBHOOK_SECRET ); if (event.type === 'checkout.session.completed') { const session = event.data.object; await resend.emails.send({ from: 'artist@yoursite.com', to: session.customer_details.email, subject: 'Your License Key', html: `

Download: My Album

License Key: PMVXogAJNVe_DDABfTmLYztaJAzsD0R7

` }); } res.json({ received: true }); } export const config = { api: { bodyParser: false } }; ``` ## Manual Workflow (No Code) For artists who don't want to set up webhooks: ### Using Email 1. **Gumroad/Ko-fi**: Set product to require email 2. **Manual delivery**: Check sales daily, email passwords manually 3. **Template**: ``` Subject: Your License for [Album Name] Hi [Name], Thank you for your purchase! Download: [IPFS/CDN link] License Key: [password] How to play: 1. Download the .smsg file 2. Go to demo.dapp.fm 3. Fan tab → Unlock Licensed Content 4. Enter your license key Enjoy! This license works forever. [Artist Name] ``` ### Using Discord/Telegram 1. Sell via Gumroad (free tier) 2. Require customers join your Discord/Telegram 3. Bot or manual delivery of license keys 4. Community building bonus! ## Security Best Practices ### 1. One Password Per Product Don't reuse passwords across products: ```javascript const PRODUCTS = { 'album-2024': { password: 'unique-key-1' }, 'album-2023': { password: 'unique-key-2' }, 'single-summer': { password: 'unique-key-3' } }; ``` ### 2. Environment Variables Never hardcode passwords in source: ```bash # .env ALBUM_2024_PASSWORD=PMVXogAJNVe_DDABfTmLYztaJAzsD0R7 STRIPE_SECRET_KEY=sk_live_... ``` ### 3. Webhook Verification Always verify webhooks are from the payment provider: ```javascript // Stripe stripe.webhooks.constructEvent(body, sig, secret); // Gumroad if (seller_id !== MY_SELLER_ID) reject(); // PayPal verify with IPN endpoint ``` ### 4. HTTPS Only All webhook endpoints must use HTTPS. ## Pricing Strategies ### Direct Sale (Perpetual License) - Customer pays once, owns forever - Single password for all buyers - Best for: Albums, films, books ### Time-Limited (Streaming/Rental) Use dapp.fm Re-Key feature: 1. Encrypt master copy with master password 2. On purchase, re-key with customer-specific password + expiry 3. Deliver unique password per customer ```javascript // On purchase webhook const customerPassword = generateUniquePassword(); const expiry = Date.now() + (24 * 60 * 60 * 1000); // 24 hours // Use WASM or Go to re-key const customerVersion = await rekeyContent(masterSmsg, masterPassword, customerPassword, expiry); // Deliver customer-specific file + password ``` ### Tiered Access Different passwords for different tiers: ```javascript const TIERS = { 'preview': { password: 'preview-key', expiry: '30s' }, 'rental': { password: 'rental-key', expiry: '7d' }, 'own': { password: 'perpetual-key', expiry: null } }; ``` ## Example: Complete Stripe Setup ```bash # 1. Create your content go run ./cmd/mkdemo album.mp4 album.smsg # Password: PMVXogAJNVe_DDABfTmLYztaJAzsD0R7 # 2. Upload to IPFS ipfs add album.smsg # QmAlbumCID # 3. Create Stripe product # Dashboard → Products → Add Product # Name: My Album # Price: $9.99 # 4. Create Payment Link # Dashboard → Payment Links → New # Select your product # Get link: https://buy.stripe.com/xxx # 5. Set up webhook # Dashboard → Developers → Webhooks → Add endpoint # URL: https://yoursite.com/api/stripe-webhook # Events: checkout.session.completed # 6. Deploy webhook handler (Vercel example) vercel deploy # 7. Share payment link # Fans click → Pay → Get email with password → Download → Play forever ``` ## Resources - [Stripe Webhooks](https://stripe.com/docs/webhooks) - [Gumroad Ping](https://help.gumroad.com/article/149-ping) - [PayPal IPN](https://developer.paypal.com/docs/ipn/) - [Resend (Email API)](https://resend.com/) - [Vercel Functions](https://vercel.com/docs/functions)