Mikel Posted September 14, 2025 Posted September 14, 2025 Hey folks, fun fact: this module was already featured in this week’s ProcessWire Weekly – even before we managed to post it here in the forum. So, here we are, finally giving it a proper introduction! 😅 TL;DR: This module connects Stripe Payment Links with ProcessWire and provides a simple checkout integration for sites that don’t need a full shop. 🎯 ✅ Drop a Stripe buy button anywhere ✅ Redirect back to PW thank-you or delivery pages ✅ Buyers get accounts, purchases are logged, access is granted ✅ Access mails are sent automatically ✴️ New in v 1.0.7: Sync existing purchases and buyers from Stripe to PW with test/write option ✴️ New in v 1.0.8: Full Stripe subscription support with real-time webhook updates (cancel, pause, resume, renew) and smarter access control logic ✴️ New in v 1.0.14: Create and send "Magic Links" (access links) to customers for products they've already purchased. First things first: What are Stripe Payment Links? Stripe Payment Links are basically hosted checkout pages that you can create directly in the Stripe Dashboard – no coding required. You define a product (or multiple line items) in Stripe. Stripe gives you a unique URL (the “Payment Link”). You can drop this URL behind any button, on any landing page, newsletter, or social media bio. When a customer clicks the link, they’re taken to a secure Stripe Checkout page (PCI compliant, supports all major payment methods, Apple Pay, etc.). After payment, Stripe redirects them back to your success URL. Super simple. But… on its own, Stripe has no idea about your ProcessWire site, your users, or your gated content. That’s where this module jumps in. 🚀 Why another payment module? We at frameless Media often work on small client projects where setting up a full e-commerce shop would be complete overkill. Think: Coaches selling a few courses or workshops Businesses offering a handful of digital products or subscriptions Creators who just need a buy button on a landing page Stripe Payment Links are perfect for this. But: ProcessWire on its own doesn’t handle redirects, user handling, or gated delivery pages. So we built StripePaymentLinks – a lightweight drop-in module to connect Stripe with PW. What it does Handles the redirect back from Stripe Checkout that contains the session id Creates or updates the buyer’s user account Records purchases in a repeater field Manages access to “delivery pages” (only available after purchase) Auto-sends access mails (configurable: never / new users only / always) Provides Bootstrap-based modals for login, password reset, set-password Usage examples Example 1: Sales page + delivery page Sales page has a “Buy now” button (Stripe Payment Link). After checkout, the user is redirected to the delivery page, which is access-protected. → Module logs them in, grants access, and if they’re new: a set-password modal pops up. → An access mail with product links is sent. Example 2: Product without a delivery page Some products don’t need protected pages (e.g. a consulting slot or voucher). → The success redirect goes to a generic thank-you page. → The module shows an access summary block with purchased products and sends the mail. Example 3: Mixed purchase (thank-you + delivery page) A checkout with multiple items: e.g. a “simple product” plus an addon that has its own delivery page. → Thank-you page shows the addon link(s). → The access mail lists all purchased products. Source & License The module is open-source under the MIT License. 👉 GitHub: https://github.com/frameless-at/StripePaymentLinks 👉 ProcessWire modules directory: https://processwire.com/modules/stripe-payment-links/ So yes: if you or your clients just need a few low-barrier buy buttons, not a full-blown webshop, this might be the module you’ve been looking for. If needed we can provide some screenshots and visual examples next week 😉 Happy to hear your thoughts, ideas, and testing feedback! Cheers, Mike 11 4
Mikel Posted September 15, 2025 Author Posted September 15, 2025 Because this question came up: No, the user does not have to enter any data before checkout. All user data is pulled via Stripes PHP SDK (included with the module). Therefore the only thing needed for the module to work is that the redirect link configured in Stripe contains the session_id param. You configure this directly in the Stripe backend by simply adding ?session_id={CHECKOUT_SESSION_ID} to your desired redirect-URL: Thats all. With this session id the module has access to all data of this specific purchase. Cheers, Mike 3
szabesz Posted September 16, 2025 Posted September 16, 2025 Awesome! Just what I will need in the near future. Thanks @Mikel for sharing! 1
Mikel Posted September 24, 2025 Author Posted September 24, 2025 With new version 1.0.4 it is possible now to set multiple Stripe API Keys in the modules config. This is especially useful for testing. Unfortunatly the module still has the "pending" status, so you will not be able to upgrade via the backend. See: 1
Mikel Posted September 26, 2025 Author Posted September 26, 2025 In case you are using this module and want to sync customers/purchases to Mailchimp – we just released an add-on for this module: 1 2
Mikel Posted October 3, 2025 Author Posted October 3, 2025 New feature in StripePaymentLinks (v 1.0.7) 🎉 Hi, everyone! We’ve just added a sync helper to the modules config screen that can pull past Stripe Checkout Sessions into ProcessWire. Super handy if you want to… backfill older purchases migrate existing users or just double-check what’s in Stripe vs. what’s in PW How it works: Scans Stripe sessions (with date range + email filter if you like) Matches them to PW users by email Creates missing users (optional) Creates/updates purchase repeater items exactly like live checkouts Has a test-run mode so you can preview before writing You get a nice report right on the config screen (below "Sync now") with totals and per-session actions (SKIP, LINKED, UPDATE, CREATE) plus the line items. Makes it a lot easier to keep things in sync — especially if you had sales before installing the module. Note: since each run fetches sessions and line items directly from Stripe’s API, the total duration depends on network + Stripe’s response times. In our tests with ~120 sessions the sync took about 15 seconds. Grab the latest version and give it a spin. We already tested this version on some live projects and everything works fine, but always backup before you mess with data 😉 Feedback welcome! 🙌 Cheers, Mike 3 1
Mikel Posted October 8, 2025 Author Posted October 8, 2025 🎉 Now with Subscriptions & Webhooks! (v 1.0.8) In the past months, several frameless clients asked for an easy way to sell their content as subscriptions — without manually managing access. Think of a coach publishing daily audio files and offering a weekly subscription for them. That’s exactly what this update makes possible. 💡 🆕 What’s new in 1.0.8 Stripe Webhook support The module now listens at /stripepaymentlinks/api/stripe-webhook and reacts in real-time to subscription events — cancel, pause, resume, renew, or failed payment. → Access updates instantly. No cron jobs, no manual actions. Subscription handling Each purchase now stores a period_end_map, so the module knows exactly when access should expire. Pause or cancel a subscription → access is blocked immediately. Resume or renew → access restored automatically. Smarter access logic hasActiveAccess() now distinguishes between: recurring products (time-limited access) one-time purchases (lifetime access) Config update Added a field for the Webhook Signing Secret in module settings. ⚙️ Setup (2 min) In Stripe → Developers → Webhooks → Add endpoint https://yourdomain.com/stripepaymentlinks/api/stripe-webhook Choose either “All events” or only the relevant ones: customer.subscription.updated customer.subscription.deleted customer.subscription.paused customer.subscription.resumed invoice.payment_succeeded invoice.payment_failed Copy your Signing Secret into the module config. Done ✅ — test by pausing, resuming or cancelling a subscription and watch access update live. Short, clean, and 100 % ProcessWire-native. Perfect for creators, coaches, and anyone who wants to sell recurring access without maintaining users manually. Cheers, Mike 5
Mikel Posted October 10, 2025 Author Posted October 10, 2025 Hey folks! We’ve had a bunch of questions about how purchases show up in the backend, so here are the details: By default, every purchase gets its own repeater item on the user’s profile, and every product bought is pulled straight from the checkout session and listed as a line item. The PRODUCT_ID is the mapped page id, and in case the product does not have a product page it shows the Stripe product id prefixed with "0#": The full session always sits in the purchases.meta object. That means you can totally use the ProcessDataTables module to show whatever data you want in a nice table. For example, you could have an customer table with a column that totals up all purchases and pops up a full list of purchases in a table when you click on it: If you're looking to do just that, here’s the column template to make it happen: sales.column.php 1
Mikel Posted October 13, 2025 Author Posted October 13, 2025 [Update] Notify existing buyers and update purchases when products gain gated content (v1.0.10) Hi everyone, we’ve extended StripePaymentLinks based on a customer request. Some products evolve over time and later receive gated content (downloads, course pages, etc.). We now handle that case automatically. What it does: When an existing product is later marked as gated and has a stripe product id the module will: Notify existing users via an access email that new gated content is available for something they already own. Update all relevant purchase entries for those users so the meta object and the purchase_lines reflect the actual delivery page (page ID scope), keeping historical purchases consistent with the current site structure and enabling access control. No manual migration needed; it all happens in the background once the product is flagged as requiring access and the corresponding stripe product id is pasted. Available from now on in v1.0.10. Thanks for the request and feedback that led to this improvement! Cheers, Mike 2
Mikel Posted October 15, 2025 Author Posted October 15, 2025 [Update] More flexible access mails (v 1.0.11) Just pushed a small update to the module — a few quality-of-life improvements for access mails. What’s new Custom intro text for access mails – There’s a new field called Access Mail Intro Text (optional) access_mail_addon_txt added to your product templates. Whatever you put in there gets prepended to the access mail’s lead text — great for short intros, personal notes, or product-specific instructions. Hookable mail variables – PLMailService adds the hookable method ___alterAccessMailVars($vars, $mod, $user, $links) You can now easily tweak mail content in your ready.php, for example "first purchase vs. repeat purchase": wire()->addHookAfter('PLMailService::alterAccessMailVars', function(\ProcessWire\HookEvent $event) { $vars = (array) $event->arguments(0); $user = $event->arguments(2); // check if this is the user's first purchase $purchaseCount = ($user->hasField('spl_purchases') && $user->spl_purchases) ? $user->spl_purchases->count() : 0; $isFirstPurchase = ($purchaseCount <= 1); if ($isFirstPurchase) { $vars['preheader'] = 'Welcome! Your new access is ready.'; } else { $vars['preheader'] = 'New access added to your account.'; } // Hand back the modified variables $event->return = $vars; }); As always, feedback, ideas, and real-world use cases are more than welcome — especially if you’ve built custom hooks for your own onboarding or mail flows. Cheers, Mike 1
Mikel Posted November 11, 2025 Author Posted November 11, 2025 [Update] New Feature: Magic Links (v 1.0.14) We've added a new feature to StripePaymentLinks that allows you to manually send access links to customers for products they've already purchased. Use Case Perfect for situations where customers need fresh access links – whether they lost the original email, changed devices, or you're migrating from another system. How it works Got to the modules config page and open the fields "Send Magic Links" Select one or more products with access control Enter recipient email addresses Set token validity (1-10080 minutes) Test mode first, then send Each recipient automatically receives links only to products they actually own. A detailed report shows what was sent and which users don't have access to the selected products. Feedback welcome! 3
chuckymendoza Posted February 25 Posted February 25 Hello Mikel, First of all, this looks like a great module. We have been looking for a way to sell fonts as easily as possible for a long time, but haven't found a simple solution. I have a question regarding product delivery for multiple digital products. We want to sell digital files, specifically fonts. There are special requirements for fonts, and I would like to know if this is possible with the module. We usually have several product pages for different font families. Here, either the entire family or individual styles can be purchased. We don’t have product pages for single fonts that belong to a font family. Example: The product page “Font Family A” contains 4 purchase options: 1) Font style Regular 2) Bold font style 3) Italic font style 4) Family (includes Regular, Bold, Italic) Of course, there are also cases with font families where we have 15 or more font styles. My question is, if someone buys and pays for Regular and Bold, what does the customer get as the product delivery page? Our idea is, they receive a delivery page showing all fonts purchased to date, including the fonts they have just purchased, which can be downloaded by clicking on one of the font styles. As I understand it, the customer receives one delivery page per product? That would make it quite cumbersome for the customer to download all font styles. Would love to hear about your thoughts. Thomas
Mikel Posted March 10 Author Posted March 10 Hi, @chuckymendoza aka Thomas 😉 Sorry for the delay, we´ve been busy and I did not get to read the forum in the past weeks. To put it short: For your use case I would definitely NOT use the module. What you need is some kind of shop system because you want your customers to be able to buy MORE than 1 font at once, don´t you? This is something the module explicitly is NOT made for. So yeah, maybe you can hang a picture with a nail and a bottle, but I'd still recommend the hammer. 😉 Cheers, Mike
Mikel Posted March 10 Author Posted March 10 [Update] New Feature: Free Product Access (v 1.0.23) Hi, everyone! We just released v1.0.23 with a new feature based on a real client use case: A client using StripePaymentLinks wanted to grant certain high-value customers bonus access to additional products — no Stripe transaction involved, just a manual override. The solution: a new spl_free_access field (AsmSelect, multi-page) on the user template. Pages selectable in the dropdown are automatically restricted to the configured product templates, so editors only see relevant products — every user in the backend gets a "Free Product Access" field where additional products can be assigned directly. Access granted this way is recognized by hasActiveAccess() — the same internal check SPL uses for all content gating — so it integrates transparently with the existing module logic. The field is created and updated automatically by ensureUserFields(), including template restriction syncing when the product template config changes. Thanks for the request and feedback that led to this improvement! Cheers, Mike 1
chuckymendoza Posted March 11 Posted March 11 Hello @Mikel, thanks for your words. Of course I can only report on my experience, but people don't go shopping for fonts. The don't buy different fonts of many font-families. They just stick with one family or some styles of that family. 🙂 I know, at last, it's the same and doesn't change anything since a Stripe Payment Link was just made for one product and not 10. I thought about that limitation a bit and had some research about Stripe, and it’s API possibilities. I thought about to possibly rewrite the module to accept payments via a Checkout‑Session with dynamic line_items and metadata and a bundled download page for the buyer. Goal is that the buyer could just select more than one font style of a font family and then click to buy them. With the click it will be sent to Stripe with a checkout-session with line_items and metadata. A cart system could be added, to. After payment, the data that comes back from stripe is analysed and the buyer get its downloads. Well, I have to think about that. 🙂 I know it’s quite unusual, but we don't need a full e-commerce shop with a cart and anything. So, the bottle would be perfectly adequate for hitting the nail. 😉 Cheers, Thomas 1
szabesz Posted Wednesday at 07:45 PM Posted Wednesday at 07:45 PM (edited) 5 hours ago, chuckymendoza said: With the click it will be sent to Stripe with a checkout-session with line_items and metadata. A cart system could be added, to. After payment, the data that comes back from stripe is analysed and the buyer get its downloads. Well, I have to think about that. Sounds like a pretty good plan. If you were to implement it and Mikel was happy to merge it into his module that would be awesome. Edited Wednesday at 07:45 PM by szabesz typo
Mikel Posted Thursday at 09:26 AM Author Posted Thursday at 09:26 AM Hi Thomas, @chuckymendoza, thanks for thinking this through so carefully — and yes, the bottle analogy is growing on me. 😄 That said, I'd still recommend not rewriting the module for this use case — not because it's technically impossible, but because the wheel has already been invented, and quite well: Option 1 — FormBuilder + Stripe Processor (by @ryan) Ryan's Stripe Processor Action for FormBuilder supports customizable line items via ProcessWire hooks out of the box. You could build a font-family selector form, populate the line items dynamically, and send the whole bundle to Stripe Checkout in one session — exactly what you described. It's not a cart system, but for a single-family "pick your styles" page it could be a very clean fit. Option 2 — RockCommerce (by @bernhard) Released in late 2024, RockCommerce is a modern, lightweight e-commerce module built "the ProcessWire way." It supports cart, checkout, product variations, coupons, payment webhooks, and pluggable payment providers — without the bloat of a full enterprise shop system. Option 3 — Padloper / ProcessWire Commerce (by @kongondo) If you need the most mature, battle-tested solution with a long track record, ProcessWire Commerce is the established open-source choice. Full cart, order management, variants, webhooks — all there. Rolling your own Stripe Checkout Session integration inside this module would mean maintaining webhook handling, session state, download token security, order persistence — all things that are already solved in the tools above. The maintenance burden alone usually kills these side projects. My honest take: for your font-family use case, RockCommerce or FormBuilder + Stripe Processor are the most promising starting points. For anything larger in scope, ProcessWire Commerce has you covered. Cheers, Mike
chuckymendoza Posted Thursday at 01:14 PM Posted Thursday at 01:14 PM That's a good tip, @Mikel Option 1 was new to me. I'll have a closer look at that, thanks! Your module would have been useful, of course, especially in terms of automatically creating buyers in the backend, MagicLinks, etc. 🙂 But anyway, I'll try my luck with one of the options. Cheers, Thomas 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now