Overview
Icon for BTCPay

BTCPay

Accept Bitcoin payment in your Medusa store

Support the Payment-BitcoinPayServer Provider โ€“ Power the Future of Medusa Commerce!

Dear Developers and E-commerce Pioneers,

Get ready to embrace the world of decentralized finance for your online stores with MedusaJS! We are excited to introduce the Payment-BitcoinPayServer provider โ€“ a community-driven project that brings the powerful Bitcoin PayServer gateway to our MedusaJS commerce stack.

What's in it for You:

๐Ÿ›ก๏ธ Secure & Sovereign Payments: Enable direct Bitcoin Network payments without relying on third-party payment processors.

๐ŸŒ Borderless Transactions: Serve a global audience with permissionless payments that know no borders.

๐Ÿš€ Empower Open Commerce: By sponsoring this provider, you contribute to the Medusa community's growth, independence, and innovation!

Installation Made Simple

Use the package manager npm to install Payment-BitcoinPayServer.

yarn add medusa-plugin-btcpay

Usage

Set up a Bitcoin PayServer instance, either self-hosted or via a trusted host.

In your environment file (Copy to clipboard.env) define:

BTCPAY_URL=https://your-btcpayserver-instance.com
BTCPAY_API_KEY=<your api key>
BTCPAY_STORE_ID=<your store id>
BTCPAY_WEBHOOK_SECRET=<your webhook secret>

You need to add the provider into your Copy to clipboardmedusa-config.ts:

module.exports = defineConfig({
modules: [
...
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
...
{
resolve: "@yourorg/payment-btcpayserver",
id: "btcpayserver",
options: {
url: process.env.BTCPAY_URL,
apiKey: process.env.BTCPAY_API_KEY,
storeId: process.env.BTCPAY_STORE_ID,
webhookSecret: process.env.BTCPAY_WEBHOOK_SECRET,
},
},
...
],

Client Side Configuration

For your Medusa Next.js storefront, follow these steps:

Step 1. Install the Bitcoin Payment Button package

(optional - depends on your design)

yarn add react-btcpay-button

Step 2. Create the Bitcoin Payment Button Component in packages/storefront/src/modules/checkout/components/payment-button/index.tsx

Step 2.1 introduce a state variable to track clicks.

const PaymentButton: React.FC<PaymentButtonProps> = ({
cart,
"data-testid": dataTestId,
}) => {
const [btcClicked, setBtcClicked] = useState(false)
....
}

Step 2.2 Then in the case

case isBtcpay(paymentSession?.provider_id):
return (
<Button disabled={btcClicked} onClick={() => {setBtcClicked(true);
window.open(`${(paymentSession?.data as any).btc_invoice.checkoutLink}`)}}>
Pay with BtcPay
</Button>
)

Step 3. Extend Payment Constants

In Copy to clipboardsrc/lib/constants.tsx:

export const isBtcpay = (providerId?: string) => {
return providerId?.startsWith("pp_btcpay")
}
export const paymentInfoMap: Record<
string,
{ title: string; icon: React.JSX.Element }
> = {
...
pp_btcpay_btcpay: {
title: "BtcPay",
icon: <CurrencyDollarSolid />,
},
...
}

Step 4. Hook Up the Payment Button

In Copy to clipboardpayment-button/index.tsx:

import { BtcpayserverPaymentButton } from "./btcpayserver-payment-button"
...
case "btcpayserver":
return <BtcpayserverPaymentButton session={paymentSession} notReady={notReady} cart={cart} />

step 5 . Create a confirmation page to poll the server --

You can use any mechanism, but i'chosen long polling, coz its just simple. You could use websockets or any other call back mechanism.

processing/page.tsx

"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { useSearchParams } from "next/navigation";
import { sdk } from "@lib/config";
import axios from "axios";
const ProcessingPage = () => {
const router = useRouter();
const searchParams = useSearchParams();
const cart= searchParams.get("cart");
useEffect(() => {
let isCancelled = false;
const fetchData = async () => {

Step 6. Configure Environment Variables in Frontend

Set the following environment variables for your storefront:

NEXT_PUBLIC_SHOP_NAME=<your shop name>
NEXT_PUBLIC_MEDUSA_BACKEND_URL=<your medusa store>

Setting Up BTCPay Server Webhook

In BTCPayServer, add a webhook with this URL:

<your-host-url>/hooks/payment/btcpay_btcpay

Make sure you set the webhook secret to match your Copy to clipboard.env Copy to clipboardBTCPAY_WEBHOOK_SECRET value.

Contributing

Pull requests are welcome! For significant changes, please open an issue first to discuss improvements or new features.

Please ensure tests and documentation are updated appropriately.

License

MIT License

Untested Features

Some features exist but haven't been fully tested in client integration:

  • Refund support
  • Lightning Network (LNURL and other advanced flows)

Disclaimer

This project is community-driven and tested in limited scenarios. Bugs may occur; please raise issues or submit pull requests if you encounter any.

Support the Payment-BitcoinPayServer Provider โ€“ Fuel Open Commerce!

Dear Medusa Enthusiasts,

Thank you for your passion and energy for open e-commerce!
The Payment-BitcoinPayServer provider is an open-source project crafted to connect MedusaJS with the powerful Bitcoin payment ecosystem.

If you find this project useful, consider sponsoring it on GitHub to help maintain and expand it.
Your support makes a world of difference in creating decentralized, open, and innovative commerce for all.

Let's keep building the future together!

With gratitude,
[YourName]
Lead Developer, Payment-BitcoinPayServer Provider

You may also like

Browse all integrations

Build your own

Develop your own custom integraiton

Build your own integration with our API to speed up your processes. Make your integration available via npm for it to be shared in our Library with the broader Medusa community.

gift card interface

Ready to build your custom commerce setup?