Open the widget
Instead of sending the buyer to the payment page, you can show it on your own site with stablevoy.js. The WooCommerce and Easy Digital Downloads plugins do this when you choose "On this site (widget)" in their settings; on any other site, load the script and open the invoice you created on your server:
<script src="https://stablevoy.com/js/v1/stablevoy.js"></script>
<script>
Stablevoy.open({
invoiceId: '7c3360b5-e8cc-4775-8a13-7324d4f1296e',
onFinal: (outcome) => {
// outcome.status, outcome.paid, outcome.returnUrl
if (outcome.paid) window.location.assign(outcome.returnUrl);
},
onClose: () => {},
});
</script>Stablevoy.open() shows the payment page in a modal (full screen on a phone); Stablevoy.mount(element, options) puts it inside an element of your page instead. Without onFinal, a paid invoice sends the buyer to its return URL, as the payment page does. onStatus receives every status change. Either call returns an object with close(); closing the widget does not cancel the invoice.
Why only on your store website
The payment page runs in a frame served by stablevoy.com, so no other script on your page can read or change the address the buyer pays to. For the same reason it is shown only on your store website: set it in the dashboard, store Settings, exactly as your shop's address (https://shop.example). On any other site the frame shows no payment details. Some browser wallets do not work inside a frame, so the widget always offers a link to the full payment page. The widget only shows the payment: mark the order as paid when the signed webhook arrives, never from the browser.
Content-Security-Policy and pinned versions
If your site sends a Content-Security-Policy, allow https://stablevoy.com in script-src and frame-src. To pin a version, load https://stablevoy.com/js/1.0.3/stablevoy.js with integrity="sha384-8qtaiTsk9ZqWSWTTxKy1pk+tmZXoADqSzrw69yfy6eIIOVtM/wMMWC7grju0xfKr" and crossorigin="anonymous"; the address above always serves the current 1.x version with the same interface.