'data'
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
# 可用 ngrok 等隧道:BASE_URL=https://xxx.ngrok.io
|
# 可用 ngrok 等隧道:BASE_URL=https://xxx.ngrok.io
|
||||||
# 或直接使用生产地址测试回调(需 payjsapi 已部署到公网)
|
# 或直接使用生产地址测试回调(需 payjsapi 已部署到公网)
|
||||||
PORT=8007
|
PORT=8007
|
||||||
BASE_URL=https://api.hackrobot.cn
|
BASE_URL=https://api.nomadyt.com
|
||||||
|
|
||||||
# 支付渠道:zpay | xorpay
|
# 支付渠道:zpay | xorpay
|
||||||
PAYMENT_PROVIDER=zpay
|
PAYMENT_PROVIDER=zpay
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -17,7 +17,7 @@
|
|||||||
## 环境
|
## 环境
|
||||||
|
|
||||||
本地调试:`BASE_URL` 需为 ZPAY 可访问地址(如 ngrok 暴露 8700 端口)
|
本地调试:`BASE_URL` 需为 ZPAY 可访问地址(如 ngrok 暴露 8700 端口)
|
||||||
线上部署:`BASE_URL=https://api.hackrobot.cn`
|
线上部署:`BASE_URL=https://api.nomadyt.com`
|
||||||
|
|
||||||
## 模块结构
|
## 模块结构
|
||||||
|
|
||||||
@@ -73,11 +73,11 @@ python run.py
|
|||||||
|
|
||||||
## 线上部署
|
## 线上部署
|
||||||
|
|
||||||
域名:`https://api.hackrobot.cn`
|
域名:`https://api.nomadyt.com`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# .env 中设置
|
# .env 中设置
|
||||||
BASE_URL=https://api.hackrobot.cn
|
BASE_URL=https://api.nomadyt.com
|
||||||
PAYMENT_PROVIDER=zpay
|
PAYMENT_PROVIDER=zpay
|
||||||
# 其他 ZPAY、PocketBase、Memos 配置见 .env.example
|
# 其他 ZPAY、PocketBase、Memos 配置见 .env.example
|
||||||
```
|
```
|
||||||
@@ -86,9 +86,9 @@ PAYMENT_PROVIDER=zpay
|
|||||||
|
|
||||||
本地正常、Ubuntu 部署后 api.hackrobot.cn 调用支付失败,常见原因:
|
本地正常、Ubuntu 部署后 api.hackrobot.cn 调用支付失败,常见原因:
|
||||||
|
|
||||||
1. **BASE_URL 配置错误**:必须为 ZPAY 可公网访问的地址。错误示例:`http://127.0.0.1:8700`、`http://localhost`。正确:`https://api.hackrobot.cn`(域名需解析到本机,nginx 反向代理对应端口)。
|
1. **BASE_URL 配置错误**:必须为 ZPAY 可公网访问的地址。错误示例:`http://127.0.0.1:8700`、`http://localhost`。正确:`https://api.nomadyt.com`(域名需解析到本机,nginx 反向代理对应端口)。
|
||||||
|
|
||||||
2. **服务器无法访问 zpayz.cn**:防火墙、DNS 或网络限制。访问 `https://api.hackrobot.cn/health?check_zpay=1` 自检:
|
2. **服务器无法访问 zpayz.cn**:防火墙、DNS 或网络限制。访问 `https://api.nomadyt.com/health?check_zpay=1` 自检:
|
||||||
- `zpayz_reachable: false` → 开放出站或检查网络
|
- `zpayz_reachable: false` → 开放出站或检查网络
|
||||||
- `zpayz_error` 含 "SSL" → 执行 `apt install ca-certificates` 后重启
|
- `zpayz_error` 含 "SSL" → 执行 `apt install ca-certificates` 后重启
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ MEMOS_TOKEN = os.getenv(
|
|||||||
"eyJhbGciOiJIUzI1NiIsImtpZCI6InYxIiwidHlwIjoiSldUIn0.eyJuYW1lIjoiaGFja3JvYm90IiwiaXNzIjoibWVtb3MiLCJzdWIiOiIxIiwiYXVkIjpbInVzZXIuYWNjZXNzLXRva2VuIl0sImlhdCI6MTc1NzQwNTE0OX0.Idn7kBlxE-CoSOXwWuZ1tHGIRKHAIeDyXSafGS5OHsg",
|
"eyJhbGciOiJIUzI1NiIsImtpZCI6InYxIiwidHlwIjoiSldUIn0.eyJuYW1lIjoiaGFja3JvYm90IiwiaXNzIjoibWVtb3MiLCJzdWIiOiIxIiwiYXVkIjpbInVzZXIuYWNjZXNzLXRva2VuIl0sImlhdCI6MTc1NzQwNTE0OX0.Idn7kBlxE-CoSOXwWuZ1tHGIRKHAIeDyXSafGS5OHsg",
|
||||||
)
|
)
|
||||||
|
|
||||||
# 回调地址(用于生成 notify_url)
|
# 回调地址(用于生成 notify_url)。salon 线上部署 api.nomadyt.com
|
||||||
BASE_URL = os.getenv("BASE_URL", "https://api.hackrobot.cn")
|
BASE_URL = os.getenv("BASE_URL", "https://api.nomadyt.com")
|
||||||
|
|
||||||
# MinIO 对象存储
|
# MinIO 对象存储
|
||||||
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "minioweb.hackrobot.cn")
|
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "minioweb.hackrobot.cn")
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
- common: /submit_meetup_application、/create_user
|
- common: /submit_meetup_application、/create_user
|
||||||
|
|
||||||
本地调试:BASE_URL 需为 ZPAY 可访问地址(如 ngrok)
|
本地调试:BASE_URL 需为 ZPAY 可访问地址(如 ngrok)
|
||||||
线上部署:BASE_URL=https://api.hackrobot.cn(必须为 ZPAY 可公网访问的地址)
|
线上部署:BASE_URL=https://api.nomadyt.com(必须为 ZPAY 可公网访问的地址)
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
@@ -108,7 +108,7 @@ def _check_base_url():
|
|||||||
return
|
return
|
||||||
if "localhost" in url or "127.0.0.1" in url or url.startswith("http://192.168.") or url.startswith("http://10."):
|
if "localhost" in url or "127.0.0.1" in url or url.startswith("http://192.168.") or url.startswith("http://10."):
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"BASE_URL=%s 疑似内网地址,ZPAY 无法回调!线上部署请设置 BASE_URL 为公网地址,如 https://api.hackrobot.cn",
|
"BASE_URL=%s 疑似内网地址,ZPAY 无法回调!线上部署请设置 BASE_URL 为公网地址,如 https://api.nomadyt.com",
|
||||||
BASE_URL,
|
BASE_URL,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -246,4 +246,5 @@ class ZPayProvider(PaymentProvider):
|
|||||||
status = int(result.get("status", 0))
|
status = int(result.get("status", 0))
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
status = 0
|
status = 0
|
||||||
return {"paid": status == 1, "status": status}
|
money = result.get("money", "")
|
||||||
|
return {"paid": status == 1, "status": status, "money": money}
|
||||||
|
|||||||
@@ -246,18 +246,67 @@ def _decode_pending_email(user_id: str) -> str | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _query_zpay_paid(order_id: str) -> bool:
|
def _query_zpay_order(order_id: str) -> dict | None:
|
||||||
|
"""查询 ZPAY 订单状态,返回 {paid, money}"""
|
||||||
try:
|
try:
|
||||||
from ..payment import get_payment_provider
|
from ..payment import get_payment_provider
|
||||||
from ..payment.zpay import ZPayProvider
|
from ..payment.zpay import ZPayProvider
|
||||||
provider = get_payment_provider()
|
provider = get_payment_provider()
|
||||||
if not isinstance(provider, ZPayProvider):
|
if not isinstance(provider, ZPayProvider):
|
||||||
return False
|
return None
|
||||||
result = provider.query_order_status(order_id, timeout=10)
|
result = provider.query_order_status(order_id, timeout=10)
|
||||||
return bool(result.get("paid"))
|
return result if result.get("paid") else None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.warning(f"salon complete-order zpay query failed: {e}")
|
logging.warning(f"salon complete-order zpay query failed: {e}")
|
||||||
return False
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _query_xorpay_paid(order_id: str) -> tuple[bool, str]:
|
||||||
|
"""查询 XorPay 是否已支付,返回 (paid, pay_price)"""
|
||||||
|
try:
|
||||||
|
from ..payment import get_payment_provider
|
||||||
|
from ..payment.xorpay import XorPayProvider
|
||||||
|
provider = get_payment_provider()
|
||||||
|
if not isinstance(provider, XorPayProvider):
|
||||||
|
return False, ""
|
||||||
|
result = provider.query_order_status(order_id, timeout=8)
|
||||||
|
if result.get("paid"):
|
||||||
|
return True, str(result.get("pay_price", "") or "")
|
||||||
|
return False, ""
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f"salon complete-order xorpay query failed: {e}")
|
||||||
|
return False, ""
|
||||||
|
|
||||||
|
|
||||||
|
def _update_solan_red_on_payment(token: str, user_id: str, order_id: str, amount_cents: int) -> None:
|
||||||
|
"""支付成功后兜底更新 solanRed:order_id、amount、vip"""
|
||||||
|
base = (PB_URL or "").rstrip("/")
|
||||||
|
try:
|
||||||
|
r = requests.get(
|
||||||
|
f"{base}/api/collections/solanRed/records",
|
||||||
|
params={"filter": f'user_id = "{user_id}"', "sort": "-created", "perPage": 1},
|
||||||
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
if r.status_code != 200:
|
||||||
|
return
|
||||||
|
data = r.json()
|
||||||
|
items = data.get("items") or []
|
||||||
|
if not items:
|
||||||
|
return
|
||||||
|
rec_id = items[0].get("id")
|
||||||
|
if not rec_id:
|
||||||
|
return
|
||||||
|
patch = {"order_id": order_id, "amount": amount_cents, "vip": True}
|
||||||
|
requests.patch(
|
||||||
|
f"{base}/api/collections/solanRed/records/{rec_id}",
|
||||||
|
json=patch,
|
||||||
|
headers={"Content-Type": "application/json", "Authorization": f"Bearer {token}"},
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
logging.info(f"salon complete-order 兜底更新 solanRed - user_id: {user_id}, amount: {amount_cents}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f"salon complete-order 兜底更新 solanRed 失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
@router.post("/complete-order")
|
@router.post("/complete-order")
|
||||||
@@ -288,13 +337,46 @@ async def complete_order(item: dict):
|
|||||||
total = (r.json().get("totalItems") or 0) if r.status_code == 200 else 0
|
total = (r.json().get("totalItems") or 0) if r.status_code == 200 else 0
|
||||||
if total > 0:
|
if total > 0:
|
||||||
break
|
break
|
||||||
if attempt < max_retries - 1 and _query_zpay_paid(order_id):
|
if attempt < max_retries - 1:
|
||||||
time.sleep(2)
|
paid_via = None
|
||||||
continue
|
pay_price = ""
|
||||||
|
zpay_result = _query_zpay_order(order_id)
|
||||||
|
if zpay_result:
|
||||||
|
paid_via = "zpay"
|
||||||
|
pay_price = str(zpay_result.get("money", "") or zpay_result.get("pay_price", ""))
|
||||||
|
if not paid_via:
|
||||||
|
xorpay_paid, xorpay_price = _query_xorpay_paid(order_id)
|
||||||
|
if xorpay_paid:
|
||||||
|
paid_via = "xorpay"
|
||||||
|
pay_price = xorpay_price
|
||||||
|
if paid_via:
|
||||||
|
from ..services.payment import handle_payment_success
|
||||||
|
price = pay_price if pay_price and float(pay_price or 0) > 0 else "1"
|
||||||
|
try:
|
||||||
|
handle_payment_success(
|
||||||
|
order_id,
|
||||||
|
price,
|
||||||
|
f"salon-{paid_via}-poll",
|
||||||
|
use_memos=False,
|
||||||
|
site_id=SITE_ID,
|
||||||
|
)
|
||||||
|
time.sleep(1)
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f"salon complete-order 手动触发支付处理失败: {e}")
|
||||||
|
time.sleep(2)
|
||||||
|
continue
|
||||||
resp_preview = r.text[:200] if r.ok else f"status={r.status_code}"
|
resp_preview = r.text[:200] if r.ok else f"status={r.status_code}"
|
||||||
logging.warning(f"salon complete-order 未找到订单: order_id={order_id}, attempt={attempt + 1}, pb_resp={resp_preview}")
|
logging.warning(f"salon complete-order 未找到订单: order_id={order_id}, attempt={attempt + 1}, pb_resp={resp_preview}")
|
||||||
raise HTTPException(status_code=400, detail="订单不存在或未支付成功")
|
raise HTTPException(status_code=400, detail="订单不存在或未支付成功")
|
||||||
|
|
||||||
|
# 兜底更新 solanRed:回调可能未到,确保 order_id、amount、vip 正确(按 user_id 查找,pending_ 用户记录存的是 pending_xxx)
|
||||||
|
zpay_result = _query_zpay_order(order_id)
|
||||||
|
money_yuan = float(zpay_result.get("money", 0) or 0) if zpay_result else 0
|
||||||
|
amount_cents = int(money_yuan * 100) if money_yuan > 0 else 100
|
||||||
|
lookup_user_id = user_id
|
||||||
|
_update_solan_red_on_payment(token, lookup_user_id, order_id, amount_cents)
|
||||||
|
|
||||||
if user_id.startswith("pending_"):
|
if user_id.startswith("pending_"):
|
||||||
email = _decode_pending_email(user_id)
|
email = _decode_pending_email(user_id)
|
||||||
if not email:
|
if not email:
|
||||||
@@ -314,7 +396,28 @@ async def complete_order(item: dict):
|
|||||||
"is_new": True,
|
"is_new": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
return {"ok": True, "token": None, "record": None, "is_new": False}
|
# 非 pending 用户:返回 solanRed 记录供前端显示微信号
|
||||||
|
record = None
|
||||||
|
try:
|
||||||
|
esc = lookup_user_id.replace("\\", "\\\\").replace('"', '\\"')
|
||||||
|
r = requests.get(
|
||||||
|
f"{base}/api/collections/solanRed/records",
|
||||||
|
params={"filter": f'user_id = "{esc}"', "sort": "-created", "perPage": 1},
|
||||||
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
|
timeout=5,
|
||||||
|
)
|
||||||
|
if r.status_code == 200:
|
||||||
|
items = r.json().get("items") or []
|
||||||
|
if items:
|
||||||
|
rec = items[0]
|
||||||
|
record = {
|
||||||
|
"wechatId": rec.get("wechatId"),
|
||||||
|
"nickname": rec.get("nickname"),
|
||||||
|
"media": rec.get("media"),
|
||||||
|
}
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return {"ok": True, "token": None, "record": record, "is_new": False}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/vip/check")
|
@router.get("/vip/check")
|
||||||
@@ -368,10 +471,15 @@ async def join_by_wechat(wechat_id: str = ""):
|
|||||||
record_dict = None
|
record_dict = None
|
||||||
if rec:
|
if rec:
|
||||||
record_dict = {
|
record_dict = {
|
||||||
|
"id": _get(rec, "id"),
|
||||||
"user_id": _get(rec, "user_id"),
|
"user_id": _get(rec, "user_id"),
|
||||||
|
"wechatId": _get(rec, "wechatId"),
|
||||||
|
"nickname": _get(rec, "nickname"),
|
||||||
|
"media": _get(rec, "media"),
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"order_id": _get(rec, "order_id"),
|
"order_id": _get(rec, "order_id"),
|
||||||
"vip": vip,
|
"vip": vip,
|
||||||
|
"is_volunteer": bool(_get(rec, "is_volunteer")),
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
"hasRecord": has_record,
|
"hasRecord": has_record,
|
||||||
@@ -387,6 +495,47 @@ async def join_by_wechat(wechat_id: str = ""):
|
|||||||
return {"hasRecord": False, "record": None, "isComplete": False, "isWechatFriend": False, "isApproved": False, "isRejected": False, "vip": False}
|
return {"hasRecord": False, "record": None, "isComplete": False, "isWechatFriend": False, "isApproved": False, "isRejected": False, "vip": False}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/join/volunteers")
|
||||||
|
async def join_volunteers():
|
||||||
|
"""获取志愿者列表 - solanRed 中 is_volunteer=true && is_approved=true"""
|
||||||
|
token, err = _get_admin_token()
|
||||||
|
if not token:
|
||||||
|
return {"volunteer": None}
|
||||||
|
base = (PB_URL or "").rstrip("/")
|
||||||
|
if not base:
|
||||||
|
return {"volunteer": None}
|
||||||
|
try:
|
||||||
|
r = requests.get(
|
||||||
|
f"{base}/api/collections/solanRed/records",
|
||||||
|
params={
|
||||||
|
"filter": 'is_volunteer = true && is_approved = true',
|
||||||
|
"sort": "-created",
|
||||||
|
"perPage": 1,
|
||||||
|
},
|
||||||
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
if r.status_code != 200:
|
||||||
|
return {"volunteer": None}
|
||||||
|
data = r.json()
|
||||||
|
items = data.get("items") or []
|
||||||
|
volunteer = None
|
||||||
|
if items:
|
||||||
|
rec = items[0]
|
||||||
|
nickname = str(rec.get("xiaohongshu_nickname") or rec.get("nickname") or "").strip() or "志愿者"
|
||||||
|
media = str(rec.get("media") or "").strip() or None
|
||||||
|
xiaohongshu_url = str(rec.get("xiaohongshu_url") or "").strip() or None
|
||||||
|
volunteer = {
|
||||||
|
"nickname": nickname,
|
||||||
|
"avatar": media if media else None,
|
||||||
|
"xiaohongshu_url": xiaohongshu_url if xiaohongshu_url else None,
|
||||||
|
}
|
||||||
|
return {"volunteer": volunteer}
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f"salon join volunteers 查询失败: {e}")
|
||||||
|
return {"volunteer": None}
|
||||||
|
|
||||||
|
|
||||||
class XiaohongshuProfileRequest(BaseModel):
|
class XiaohongshuProfileRequest(BaseModel):
|
||||||
url: str
|
url: str
|
||||||
|
|
||||||
@@ -1151,6 +1300,7 @@ async def submit_join(item: dict):
|
|||||||
# PocketBase type 仅接受 session-1/session-2 等,digital-nomad/volunteer 映射为空
|
# PocketBase type 仅接受 session-1/session-2 等,digital-nomad/volunteer 映射为空
|
||||||
pb_type = raw_type if raw_type in ("session-1", "session-2") else ""
|
pb_type = raw_type if raw_type in ("session-1", "session-2") else ""
|
||||||
|
|
||||||
|
qualify = bool(item.get("qualify", False)) # 女性且小红书帖子>10 时自动通过
|
||||||
pb_data = {
|
pb_data = {
|
||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
"nickname": item.get("nickname", ""),
|
"nickname": item.get("nickname", ""),
|
||||||
@@ -1169,6 +1319,7 @@ async def submit_join(item: dict):
|
|||||||
"xiaohongshu_url": item.get("xiaohongshu_url", ""),
|
"xiaohongshu_url": item.get("xiaohongshu_url", ""),
|
||||||
"is_volunteer": bool(item.get("is_volunteer", False)),
|
"is_volunteer": bool(item.get("is_volunteer", False)),
|
||||||
"is_wechat_friend": bool(item.get("is_wechat_friend", False)),
|
"is_wechat_friend": bool(item.get("is_wechat_friend", False)),
|
||||||
|
"is_approved": qualify, # 符合条件时自动通过审核
|
||||||
"age_range": item.get("age_range", ""),
|
"age_range": item.get("age_range", ""),
|
||||||
"first_time": item.get("first_time", ""),
|
"first_time": item.get("first_time", ""),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ def handle_payment_success(
|
|||||||
if not user_id:
|
if not user_id:
|
||||||
return
|
return
|
||||||
|
|
||||||
# meetup/salon 新用户:支付成功后才创建用户
|
# meetup/salon 新用户:支付成功后才创建用户。solanRed 记录创建时用的是 pending_xxx,查找需用原值
|
||||||
|
solan_lookup_user_id = user_id
|
||||||
if pay_type in ("meetup", "salon") and user_id.startswith("pending_"):
|
if pay_type in ("meetup", "salon") and user_id.startswith("pending_"):
|
||||||
email = _decode_pending_email(user_id)
|
email = _decode_pending_email(user_id)
|
||||||
if email:
|
if email:
|
||||||
@@ -151,25 +152,30 @@ def handle_payment_success(
|
|||||||
solan_collection = None
|
solan_collection = None
|
||||||
|
|
||||||
if solan is not None:
|
if solan is not None:
|
||||||
|
update_payload = {
|
||||||
|
"order_id": order_id,
|
||||||
|
"amount": amount_cents,
|
||||||
|
}
|
||||||
|
if pay_type == "salon":
|
||||||
|
update_payload["vip"] = True
|
||||||
|
elif pay_type == "meetup":
|
||||||
|
update_payload["type"] = pay_type
|
||||||
existing = solan.get_list(1, 1, {
|
existing = solan.get_list(1, 1, {
|
||||||
"filter": f'user_id = "{user_id}"',
|
"filter": f'user_id = "{solan_lookup_user_id}"',
|
||||||
"sort": "-created",
|
"sort": "-created",
|
||||||
})
|
})
|
||||||
if existing.items:
|
if existing.items:
|
||||||
record_id = existing.items[0].id
|
record_id = existing.items[0].id
|
||||||
solan.update(record_id, {
|
patch = dict(update_payload)
|
||||||
"type": pay_type,
|
if solan_lookup_user_id != user_id:
|
||||||
"order_id": order_id,
|
patch["user_id"] = user_id
|
||||||
"amount": amount_cents,
|
solan.update(record_id, patch)
|
||||||
})
|
|
||||||
logging.info(f"{solan_collection} 支付字段补齐成功 - user_id: {user_id}, record_id: {record_id}")
|
logging.info(f"{solan_collection} 支付字段补齐成功 - user_id: {user_id}, record_id: {record_id}")
|
||||||
else:
|
else:
|
||||||
solan.create({
|
create_payload = {"user_id": user_id, **update_payload}
|
||||||
"user_id": user_id,
|
if pay_type == "salon":
|
||||||
"type": pay_type,
|
create_payload["type"] = ""
|
||||||
"order_id": order_id,
|
solan.create(create_payload)
|
||||||
"amount": amount_cents,
|
|
||||||
})
|
|
||||||
logging.info(f"{solan_collection} 完整记录创建(兜底) - user_id: {user_id}")
|
logging.info(f"{solan_collection} 完整记录创建(兜底) - user_id: {user_id}")
|
||||||
elif pay_type not in ("meetup", "salon"):
|
elif pay_type not in ("meetup", "salon"):
|
||||||
existing = pb_client.collection("payments").get_list(1, 1, {
|
existing = pb_client.collection("payments").get_list(1, 1, {
|
||||||
|
|||||||
2
run.py
2
run.py
@@ -16,7 +16,7 @@ if __name__ == "__main__":
|
|||||||
port = int(os.getenv("PORT", "8007"))
|
port = int(os.getenv("PORT", "8007"))
|
||||||
reload_enabled = os.getenv("UVICORN_RELOAD", "0").strip().lower() in ("1", "true", "yes")
|
reload_enabled = os.getenv("UVICORN_RELOAD", "0").strip().lower() in ("1", "true", "yes")
|
||||||
try:
|
try:
|
||||||
sys.stderr.write(f"\n[payjsapi] startup http://0.0.0.0:{port}\n")
|
sys.stderr.write(f"\n[salonapi] startup http://0.0.0.0:{port}\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
except (OSError, ValueError):
|
except (OSError, ValueError):
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user