175 Commits

Author SHA1 Message Date
53bdd0681f refactor(transfer): move email scan logic to check_transfer method, DSPY only calls provider 2026-07-17 13:39:55 +08:00
0453eed500 fix(transfer): missing closing brace in except block 2026-07-17 13:37:48 +08:00
6d4dace412 feat(wechat): Native payment → generate QR via env.data2qrpath → show Image for scan 2026-07-17 13:33:18 +08:00
24337faa55 fix(transfer): restore tcode param, check done→show msg, matched→do accounting 2026-07-17 13:08:34 +08:00
455d873167 refactor(transfer): transfer_check scans ALL mails for all pending transfers 2026-07-17 13:05:52 +08:00
ba1e649814 fix(transfer): expose PROVIDERS via ServerEnv, use env.PROVIDERS in transfer_check.dspy 2026-07-17 12:08:14 +08:00
7f2607450b bugfix 2026-07-17 12:06:50 +08:00
fd48b8b181 bugfix 2026-07-17 12:04:30 +08:00
8cb6dd9894 bugfix 2026-07-17 11:57:35 +08:00
9a767c2b93 bugfix 2026-07-17 11:54:53 +08:00
9484266b9e fix(transfer): use add_startup for mail poll, add transfer_check.dspy + button for manual check 2026-07-17 11:38:21 +08:00
f87b915cdd bugfix 2026-07-17 11:30:29 +08:00
6e5911ad46 bugfix 2026-07-17 11:21:28 +08:00
befa093a30 bugfix 2026-07-17 11:11:22 +08:00
68eff9086b bugfix 2026-07-17 11:03:42 +08:00
8972085696 bugfix 2026-07-17 10:58:28 +08:00
0b6d5e1695 bugfix 2026-07-17 10:57:52 +08:00
d6aa61795a bugfix 2026-07-17 10:56:39 +08:00
0cebfd140f bugfix 2026-07-17 10:50:51 +08:00
df6aa60006 ui: transfer_info display as flat text rows instead of read-only Form 2026-07-17 10:49:52 +08:00
68ca493840 bugfix 2026-07-17 10:36:15 +08:00
3617403201 bugfix 2026-07-16 18:58:54 +08:00
9d0f9c568e fix(wechat): payload.subject → payment_name fallback, amount ×100 yuan→fen 2026-07-16 18:45:52 +08:00
9939ccf5ef fix: transfer_info.ui 子控件从 options.children 改为 subwidgets 2026-07-16 18:22:26 +08:00
baf84725e0 fix: transfer opens NewWindow like wechat/alipay, not replace main content 2026-07-16 17:52:29 +08:00
2cac8fe4be fix(wechat): revert to H5 payment — h5_url is directly browser-openable, no tenpay conversion needed 2026-07-16 17:49:29 +08:00
d4c9568673 fix(wechat): use wx.tenpay.com/f2f for web payment, weixin:// is not browser-openable 2026-07-16 17:40:20 +08:00
403cdd5de1 revert: 恢复原始支付流程——获取支付URL后直接新窗口跳转,移除QR码 2026-07-16 17:33:46 +08:00
149092a3a0 security: 移除第三方 qrserver.com,改用本地 qrcode 生成 QR 码 2026-07-16 17:25:34 +08:00
e83e8e4d8d fix: 实现转账邮件轮询后台任务,自动匹配转账码并完成入账 2026-07-16 16:32:02 +08:00
abd7b49b79 feat: 转账充值增加收款户名(ACCOUNT_NAME)字段 2026-07-16 15:51:59 +08:00
4ba232805b feat: 添加线下转账充值信息展示页 transfer_info.ui 2026-07-16 15:31:38 +08:00
067510df65 fix(unipay): transfer shows bank info page directly instead of QR code 2026-07-16 15:09:32 +08:00
be119368c5 fix(unipay): register transfer_info.ui in load_path.py RBAC permissions 2026-07-16 12:58:30 +08:00
e64bfe81ea feat(unipay): transfer popup displays bank_name and bank_branch from env vars
- init.py: add BANK_NAME/BANK_BRANCH to CONF_ENV['transfer']
- transfer.py: TransferGateway accepts and forwards bank_name/bank_branch
- transfer_info.ui: conditionally display 收款银行/开户行 rows
2026-07-16 12:06:01 +08:00
a0bd6fb24f revert: QR code is required for Native payment, weixin:// is not a web URL
Native payment code_url uses weixin:// protocol which is a WeChat deep link,
not openable in browsers. QR code is the standard approach - user scans
with WeChat and completes payment within the app.
2026-07-16 11:57:36 +08:00
a95c548f84 feat(wechat): use wx.tenpay.com payment page instead of third-party QR 2026-07-16 10:50:06 +08:00
c96da0af11 feat(transfer): add transfer_info.ui page for bank transfer info 2026-07-15 18:16:57 +08:00
4f61f48cc4 fix(transfer): str+int TypeError in gen_mailcode 2026-07-15 17:58:47 +08:00
526c93ada7 fix(transfer): fix parameter name mismatch in CONF_ENV and TransferGateway
- CONF_ENV had 'mail' but TransferGateway.__init__ expects 'email'
- TransferGateway had 'from_email' typo (undefined NameError) → 'from_mail'
2026-07-15 17:53:40 +08:00
97524da74d fix(wechat): use Response instead of missing json_response in callback
ServerEnv().json_reponse does not exist, causing 'NoneType' object
is not callable. Align with alipay_notify pattern: use aiohttp Response
directly with JSON string body.
2026-07-15 17:43:06 +08:00
7e37b00672 fix(wechat): don't block init on missing WXP_API_V3_KEY
API v3 key is only needed for callback verification, not payment creation.
- Remove init-time validation (was blocking all wechat payments)
- Gracefully degrade: set api_v3_key=None if invalid, warn at startup
- Raise clear error at callback time if key still missing
2026-07-15 17:40:27 +08:00
bf916b98ff fix(wechat): validate WXP_API_V3_KEY at init time
AES-256-GCM requires 32-byte key. 'None' placeholder is only 4 bytes,
causing ValueError during callback decryption instead of at startup.
Now fails fast with clear error if key is missing/invalid.
2026-07-15 17:29:19 +08:00
cae22f84be fix(wechat): convert yuan to fen for WeChat amount (×100)
WeChat amount.total is in fen (分), but user enters yuan (元).
int(0.01) = 0 which fails WeChat's minimum 1 fen validation.
Fix: int(amount * 100)
2026-07-15 17:25:47 +08:00
1a2d8f8f2d feat(wechat): switch from H5 to Native payment (QR code scan)
- Change API endpoint from /v3/pay/transactions/h5 to /v3/pay/transactions/native
- Remove scene_info (not needed for native mode)
- Return code_url instead of h5_url
- recharge.dspy: display QR code image via api.qrserver.com
- user_recharge.dspy: return both code_url and qr_url
2026-07-15 17:22:40 +08:00
0266f9fb65 fix(wechat): handle API errors instead of silently returning null h5_url
- Check HTTP status code, raise exception on non-200
- Raise exception if h5_url missing from response
- Fix description field to use .get() instead of direct key access
- Remove unreachable return None

Previously WeChat API errors (param errors, amount issues, etc.)
would return None, causing the frontend to show:
  https://token.opencomputing.cn/null
Now errors are properly raised and shown to the user.
2026-07-15 17:04:21 +08:00
ccee3ba12b feat: 启用微信支付和转账支付渠道
- recharge.ui: 下拉列表添加微信支付和转账支付选项
- user_recharge.dspy: 扩展provider校验,支持wechat/transfer
- wechat.py: 修复description字段兼容payment_name
- transfer.py: 导入DBPools + 修复tcode拼写错误
2026-07-15 13:45:21 +08:00
7a0e87e735 fix: get_pay_fee 返回 fee_rate 而非 fee_rate*amount,修复双重乘法
get_pay_fee() 返回 fee_rate*amount,但 create_payment()
又把返回值当 feerate 传给 new_log(),new_log() 内部又乘
一次 amount,导致 pay_fee = fee_rate * amount²。

修复:
- get_pay_fee() 改为只返回 fee_rate
- create_payment() 自己计算 fee = feerate * amount
- new_log() 传 feerate 而非 fee
2026-07-01 11:51:20 +08:00
a9c99305fc Revert "fix: sor_get_pay_feerate 加 ORDER BY + LIMIT 1 防非确定性取值"
This reverts commit 4ec1f12396fd2e2b697d473911a8d0f846caaf4d.
2026-07-01 11:49:46 +08:00
4ec1f12396 fix: sor_get_pay_feerate 加 ORDER BY + LIMIT 1 防非确定性取值
无 ORDER BY 时 MySQL 可能返回非确定的行顺序,
两次同参数调用取到不同费率。
2026-06-30 18:29:03 +08:00