refactor: move project under backend

这个提交包含在:
cryptocommuniums-afk
2026-02-02 10:12:26 +08:00
父节点 810d0420d6
当前提交 616f9bd8c6
修改 27 个文件,包含 35 行新增16 行删除

5
.gitignore vendored
查看文件

@@ -1,3 +1,2 @@
app/node_modules/ # Local artifacts created before moving into backend/
app/data/ app/
*.log

3
backend/.gitignore vendored 普通文件
查看文件

@@ -0,0 +1,3 @@
app/node_modules/
app/data/
*.log

查看文件

@@ -24,6 +24,7 @@ npm run dev
``` ```
服务默认监听 `:3001`(可在 `app/.env` 修改)。 服务默认监听 `:3001`(可在 `app/.env` 修改)。
通过域名访问时统一前缀为:`https://capay.hao.work/backend`
### 免费套餐低频监控 ### 免费套餐低频监控
`app/.env` 中已设置: `app/.env` 中已设置:
@@ -35,6 +36,7 @@ npm run dev
支持多个 Alchemy 免费 key使用 `ALCHEMY_API_KEYS=key1,key2`,系统会按轮询周期进行轮转调用,降低单 key 的频率。 支持多个 Alchemy 免费 key使用 `ALCHEMY_API_KEYS=key1,key2`,系统会按轮询周期进行轮转调用,降低单 key 的频率。
## API 说明(简化版) ## API 说明(简化版)
域名访问时请在路径前加 `/backend` 前缀(例如:`/backend/payments/orders`)。
### 1) 开通商户 ### 1) 开通商户
`POST /merchants` `POST /merchants`
```json ```json

查看文件

@@ -1,5 +1,5 @@
APP_PORT=3001 APP_PORT=3001
APP_HOST=https://capay.hao.work APP_HOST=https://capay.hao.work/backend
PLAN=free PLAN=free
ADMIN_API_KEY=whoami139 ADMIN_API_KEY=whoami139

查看文件

@@ -21,7 +21,9 @@ const curlTrackTx = document.getElementById('curl-track-tx');
const webhookTip = document.getElementById('webhook-tip'); const webhookTip = document.getElementById('webhook-tip');
const STORAGE_KEY = 'capay_admin_key'; const STORAGE_KEY = 'capay_admin_key';
const baseUrl = window.location.origin; const basePath = window.location.pathname.replace(/\/[^/]*$/, '/').replace(/\/+$/, '');
const apiBase = basePath || '';
const baseUrl = `${window.location.origin}${apiBase}`;
function setStatus(text, ok) { function setStatus(text, ok) {
statusText.textContent = text; statusText.textContent = text;
@@ -43,13 +45,18 @@ function setAdminKey(value) {
localStorage.setItem(STORAGE_KEY, value); localStorage.setItem(STORAGE_KEY, value);
} }
function withBase(path) {
if (!apiBase) return path;
return `${apiBase}${path}`;
}
async function request(path, options = {}) { async function request(path, options = {}) {
const headers = options.headers ? { ...options.headers } : {}; const headers = options.headers ? { ...options.headers } : {};
const adminKey = getAdminKey(); const adminKey = getAdminKey();
if (adminKey) { if (adminKey) {
headers['x-admin-key'] = adminKey; headers['x-admin-key'] = adminKey;
} }
const res = await fetch(path, { ...options, headers }); const res = await fetch(withBase(path), { ...options, headers });
if (!res.ok) { if (!res.ok) {
const text = await res.text(); const text = await res.text();
let message = text; let message = text;

查看文件

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Capay API Docs</title> <title>Capay API Docs</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" /> <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" />
<link rel="stylesheet" href="/styles.css" /> <link rel="stylesheet" href="../styles.css" />
<style> <style>
.docs-header { .docs-header {
max-width: 1180px; max-width: 1180px;
@@ -41,7 +41,7 @@
<h2>Capay API Docs</h2> <h2>Capay API Docs</h2>
<p class="muted">Swagger-style documentation with live requests.</p> <p class="muted">Swagger-style documentation with live requests.</p>
</div> </div>
<a class="pill link" href="/">Back to Admin</a> <a class="pill link" href="../">Back to Admin</a>
</div> </div>
<div id="swagger-ui"></div> <div id="swagger-ui"></div>
@@ -50,7 +50,7 @@
<script> <script>
window.onload = function () { window.onload = function () {
window.ui = SwaggerUIBundle({ window.ui = SwaggerUIBundle({
url: "/openapi.json", url: "../openapi.json",
dom_id: "#swagger-ui", dom_id: "#swagger-ui",
deepLinking: true, deepLinking: true,
presets: [SwaggerUIBundle.presets.apis], presets: [SwaggerUIBundle.presets.apis],

查看文件

@@ -4,7 +4,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Capay 管理后台</title> <title>Capay 管理后台</title>
<link rel="stylesheet" href="/styles.css" /> <link rel="stylesheet" href="styles.css" />
</head> </head>
<body> <body>
<div class="page"> <div class="page">
@@ -16,7 +16,7 @@
<div class="hero-meta"> <div class="hero-meta">
<span class="pill">API Admin</span> <span class="pill">API Admin</span>
<span class="pill" id="status-pill">未连接</span> <span class="pill" id="status-pill">未连接</span>
<a class="pill link" href="/docs/">API Docs</a> <a class="pill link" href="docs/">API Docs</a>
</div> </div>
</header> </header>
@@ -131,6 +131,6 @@
</section> </section>
</div> </div>
<script src="/app.js"></script> <script src="app.js"></script>
</body> </body>
</html> </html>

查看文件

@@ -7,7 +7,7 @@
}, },
"servers": [ "servers": [
{ {
"url": "/" "url": "/backend"
} }
], ],
"tags": [ "tags": [

查看文件

@@ -1,5 +1,5 @@
{ {
"HOST": "https://capay.hao.work", "HOST": "https://capay.hao.work/backend",
"PORT": 8081, "PORT": 8081,
"MONGO_CONNECTION_STRING": "mongodb://localhost:27017", "MONGO_CONNECTION_STRING": "mongodb://localhost:27017",
"MONGO_KEAGATE_DB": "keagate", "MONGO_KEAGATE_DB": "keagate",

查看文件

@@ -13,8 +13,16 @@ server {
# include /etc/letsencrypt/options-ssl-nginx.conf; # include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / { location = / {
proxy_pass http://127.0.0.1:3001; return 302 /backend/;
}
location = /backend {
return 301 /backend/;
}
location /backend/ {
proxy_pass http://127.0.0.1:3001/;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;