You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将BTCPay Server接入MERN应用以创建发票?

在MERN栈中接入BTCPay Server生成发票

1. 后端(Express)配置与接口开发

首先在BTCPay Server后台生成API密钥,权限仅勾选invoices:create,遵循最小权限原则。

安装依赖

在Express项目中安装请求工具:

npm install axios

编写创建发票的后端接口

通过后端中转调用BTCPay API,避免密钥暴露在前端:

const express = require('express');
const axios = require('axios');
const router = express.Router();

// 用环境变量存储敏感配置,禁止硬编码
const BTCPAY_URL = process.env.BTCPAY_URL;
const BTCPAY_API_KEY = process.env.BTCPAY_API_KEY;
const STORE_ID = process.env.BTCPAY_STORE_ID;

router.post('/api/create-invoice', async (req, res) => {
  try {
    const { amount, currency, description } = req.body;

    const invoiceData = {
      amount,
      currency,
      description,
      checkout: {
        redirectURL: `${process.env.FRONTEND_URL}/payment-success`,
        cancelURL: `${process.env.FRONTEND_URL}/payment-cancel`
      }
    };

    const response = await axios.post(
      `${BTCPAY_URL}/api/v1/stores/${STORE_ID}/invoices`,
      invoiceData,
      {
        headers: {
          'Authorization': `token ${BTCPAY_API_KEY}`,
          'Content-Type': 'application/json'
        }
      }
    );

    res.json({
      invoiceId: response.data.id,
      paymentUrl: response.data.checkoutLink,
      qrCodeUrl: response.data.qrCode
    });
  } catch (error) {
    console.error('创建发票失败:', error.response?.data || error.message);
    res.status(500).json({ error: '创建发票失败,请稍后重试' });
  }
});

module.exports = router;

2. 前端(React)调用接口并展示发票

在React组件中实现触发创建发票的逻辑,展示支付链接与二维码:

import { useState } from 'react';
import axios from 'axios';

const PaymentForm = () => {
  const [amount, setAmount] = useState('');
  const [currency, setCurrency] = useState('USD');
  const [description, setDescription] = useState('测试订单');
  const [paymentUrl, setPaymentUrl] = useState('');
  const [qrCodeUrl, setQrCodeUrl] = useState('');

  const handleCreateInvoice = async (e) => {
    e.preventDefault();
    try {
      const response = await axios.post('/api/create-invoice', {
        amount,
        currency,
        description
      });
      setPaymentUrl(response.data.paymentUrl);
      setQrCodeUrl(response.data.qrCodeUrl);
    } catch (error) {
      alert('创建发票失败,请检查输入或稍后重试');
    }
  };

  return (
    <div>
      <form onSubmit={handleCreateInvoice}>
        <div>
          <label>金额:</label>
          <input
            type="number"
            step="0.01"
            value={amount}
            onChange={(e) => setAmount(e.target.value)}
            required
          />
        </div>
        <div>
          <label>货币:</label>
          <select value={currency} onChange={(e) => setCurrency(e.target.value)}>
            <option value="USD">USD</option>
            <option value="BTC">BTC</option>
            <option value="EUR">EUR</option>
          </select>
        </div>
        <div>
          <label>订单描述:</label>
          <input
            type="text"
            value={description}
            onChange={(e) => setDescription(e.target.value)}
          />
        </div>
        <button type="submit">生成支付发票</button>
      </form>

      {paymentUrl && (
        <div className="payment-options">
          <h3>请完成支付:</h3>
          <a href={paymentUrl} target="_blank" rel="noopener noreferrer">
            点击跳转BTCPay支付页面
          </a>
          {qrCodeUrl && <img src={qrCodeUrl} alt="支付二维码" />}
        </div>
      )}
    </div>
  );
};

export default PaymentForm;

3. 额外优化:支付状态回调处理

在BTCPay后台配置Webhook指向后端接口(如/api/webhook/btcpay),实时更新订单状态:

router.post('/api/webhook/btcpay', express.raw({ type: 'application/json' }), async (req, res) => {
  // 必须验证Webhook签名,防止恶意请求
  try {
    const invoiceData = JSON.parse(req.body);
    const invoiceId = invoiceData.id;
    const status = invoiceData.status;

    // 根据invoiceId更新MongoDB中的订单记录
    // 示例:await Order.findOneAndUpdate({ invoiceId }, { status });

    res.sendStatus(200);
  } catch (error) {
    console.error('处理Webhook失败:', error);
    res.sendStatus(500);
  }
});

核心注意事项

  • 敏感配置必须用环境变量存储,禁止暴露在前端代码中。
  • Webhook必须验证签名,参考BTCPay官方文档的签名验证逻辑。
  • 可根据业务需求扩展发票参数,比如自定义元数据、过期时间等。

内容的提问来源于stack exchange,提问作者Jack Hillyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 07:35:26