Files
server-core/app/pay/config.py
T
Pine f1147dced3 feat(pay): 微信支付V3子应用与算力充值
- app/pay 独立支付子应用(config/wxpay/models/repository/service/routers),便于后期拆分微服务
- 充值订单表 0026_compute_recharge;套餐支持折扣(discount)与上架开关(enabled),DB system_configs 优先、env 兜底
- 统一小程序支付:桌面端出小程序码→扫码进小程序确认页按 openid 发起 JSAPI→回调幂等到账(引擎 adjust_user_quota+镜像回写)
- 内嵌 wechatpayv3(含 async_),响应验签失败降级告警;新增 aiofiles 依赖

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-30 22:29:44 +08:00

69 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""支付子应用配置(微信支付 V3 / 算力充值)。
独立成模块便于后期整体拆分为支付微服务;凭据只放服务器 .env,勿提交。
"""
from __future__ import annotations
import json
import os
from .. import config
# ---------------------------------------------------------------------------
# 微信支付 V3 商户配置(未配置时支付功能整体降级不可用,接口返回 enabled=False
# ---------------------------------------------------------------------------
WECHATPAY_MCHID = os.environ.get("PINEAGENTS_WECHATPAY_MCHID", "")
WECHATPAY_CERT_SERIAL_NO = os.environ.get("PINEAGENTS_WECHATPAY_CERT_SERIAL_NO", "")
WECHATPAY_APIV3_KEY = os.environ.get("PINEAGENTS_WECHATPAY_APIV3_KEY", "")
WECHATPAY_PRIVATE_KEY_PATH = os.environ.get(
"PINEAGENTS_WECHATPAY_PRIVATE_KEY_PATH", str(config.KEYS_DIR / "wechatpay" / "apiclient_key.pem"),
)
# 平台证书目录(微信支付平台证书/公钥自动更新落盘,属运行时数据)
WECHATPAY_CERT_DIR = os.environ.get(
"PINEAGENTS_WECHATPAY_CERT_DIR", str(config.KEYS_DIR / "wechatpay" / "certs"),
)
# 回调通知地址:须为微信可达的公网 HTTPS(如 https://opc.pinesound.cn/opc/pay/notify
WECHATPAY_NOTIFY_URL = os.environ.get("PINEAGENTS_WECHATPAY_NOTIFY_URL", "")
# 微信支付平台公钥(可选:新商户用公钥模式时配置;否则走平台证书自动更新)
WECHATPAY_PUBLIC_KEY_PATH = os.environ.get("PINEAGENTS_WECHATPAY_PUBLIC_KEY_PATH", "")
# 平台公钥 ID(公钥模式时与上面成对配置,如 PUB_KEY_ID_0111...
WECHATPAY_PUBLIC_KEY_ID = os.environ.get("PINEAGENTS_WECHATPAY_PUBLIC_KEY_ID", "")
# 双 appid:Native 扫码用「绑定到商户号的公众号/开放平台 appid」;
# JSAPI(小程序) 下单 appid 必须是小程序 appidwechatpayv3 pay() 支持按单覆盖)。
WECHATPAY_NATIVE_APPID = (
os.environ.get("PINEAGENTS_WECHATPAY_NATIVE_APPID", "") or config.WECHAT_OPEN_APPID
)
WECHATPAY_JSAPI_APPID = (
os.environ.get("PINEAGENTS_WECHATPAY_JSAPI_APPID", "") or config.WECHAT_APPID
)
# ---------------------------------------------------------------------------
# 充值规则
# ---------------------------------------------------------------------------
# 人民币实际计费口径:1 元 = 1,000,000 微元(与引擎 meter 的 QUOTA_PER_YUAN 一致)
QUOTA_PER_YUAN = 1_000_000
RECHARGE_MIN_YUAN = float(os.environ.get("PINEAGENTS_RECHARGE_MIN_YUAN", "1"))
RECHARGE_MAX_YUAN = float(os.environ.get("PINEAGENTS_RECHARGE_MAX_YUAN", "5000"))
RECHARGE_EXPIRE_MINUTES = int(os.environ.get("PINEAGENTS_RECHARGE_EXPIRE_MINUTES", "15"))
# 充值套餐兜底(JSON 数组字符串):DB system_configs 的 recharge_packages 优先
DEFAULT_PACKAGES_JSON = os.environ.get(
"PINEAGENTS_WECHATPAY_PACKAGES",
json.dumps([
{"id": "p10", "amount": 10, "bonus": 0, "label": "10 元"},
{"id": "p50", "amount": 50, "bonus": 5, "label": "50 元"},
{"id": "p100", "amount": 100, "bonus": 15, "label": "100 元"},
], ensure_ascii=False),
)
def pay_enabled() -> bool:
"""商户关键凭据齐备才启用支付。"""
return bool(
WECHATPAY_MCHID and WECHATPAY_CERT_SERIAL_NO and WECHATPAY_APIV3_KEY
and WECHATPAY_PRIVATE_KEY_PATH and WECHATPAY_NOTIFY_URL
)