diff --git a/miniprogram/app.js b/miniprogram/app.js index 83d2ad6a..cc86b263 100644 --- a/miniprogram/app.js +++ b/miniprogram/app.js @@ -6,7 +6,8 @@ App({ globalData: { // API基础地址 - 连接真实后端 - baseUrl: 'https://soulapi.quwanzhi.com', + // baseUrl: 'https://soulapi.quwanzhi.com', + baseUrl: 'https://souldev.quwanzhi.com', // baseUrl: 'http://localhost:3006', // baseUrl: 'http://localhost:8080', diff --git a/soul-admin/.env.development b/soul-admin/.env.development index 7cff8a7b..e808fead 100644 --- a/soul-admin/.env.development +++ b/soul-admin/.env.development @@ -2,6 +2,5 @@ # 宝塔部署:若 API 站点开启了强制 HTTPS,这里必须用 https,否则预检请求会被重定向导致 CORS 报错 # VITE_API_BASE_URL=http://localhost:3006 # VITE_API_BASE_URL=http://localhost:8080 -# VITE_API_BASE_URL=https://soulapi.quwanzhi.com -VITE_API_BASE_URL=https://soul.quwanzhi.com +VITE_API_BASE_URL=https://souldev.quwanzhi.com diff --git a/soul-api/internal/config/config.go b/soul-api/internal/config/config.go index 5fb7ff6a..f9cd50b9 100644 --- a/soul-api/internal/config/config.go +++ b/soul-api/internal/config/config.go @@ -156,24 +156,24 @@ func Load() (*Config, error) { } return &Config{ - Port: port, - Mode: mode, - DBDSN: dsn, - TrustedProxies: []string{"127.0.0.1", "::1"}, - CORSOrigins: parseCORSOrigins(), - Version: version, - WechatAppID: wechatAppID, - WechatAppSecret: wechatAppSecret, - WechatMchID: wechatMchID, - WechatMchKey: wechatMchKey, - WechatNotifyURL: wechatNotifyURL, - WechatAPIv3Key: wechatAPIv3Key, - WechatCertPath: wechatCertPath, - WechatKeyPath: wechatKeyPath, - WechatSerialNo: wechatSerialNo, - WechatTransferURL: wechatTransferURL, - AdminUsername: adminUsername, - AdminPassword: adminPassword, + Port: port, + Mode: mode, + DBDSN: dsn, + TrustedProxies: []string{"127.0.0.1", "::1"}, + CORSOrigins: parseCORSOrigins(), + Version: version, + WechatAppID: wechatAppID, + WechatAppSecret: wechatAppSecret, + WechatMchID: wechatMchID, + WechatMchKey: wechatMchKey, + WechatNotifyURL: wechatNotifyURL, + WechatAPIv3Key: wechatAPIv3Key, + WechatCertPath: wechatCertPath, + WechatKeyPath: wechatKeyPath, + WechatSerialNo: wechatSerialNo, + WechatTransferURL: wechatTransferURL, + AdminUsername: adminUsername, + AdminPassword: adminPassword, AdminSessionSecret: adminSessionSecret, }, nil } diff --git a/分销提现流程图.md b/分销提现流程图.md new file mode 100644 index 00000000..45835765 --- /dev/null +++ b/分销提现流程图.md @@ -0,0 +1,127 @@ +# 分销提现流程图 + +## 一、整体流程 + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 小 程 序 端 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + [用户] 推广中心 → 可提现金额 ≥ 最低额 → 点击「申请提现」 + │ + ▼ + POST /api/miniprogram/withdraw (WithdrawPost) + │ 校验:可提现余额、最低金额、用户 openId + ▼ + 写入 withdrawals:status = pending + │ + ▼ + 提示「提现申请已提交,审核通过后将打款至您的微信零钱」 + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 管 理 端 (soul-admin) │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + [管理员] 分销 / 提现审核 → GET /api/admin/withdrawals 拉列表 + │ + ├── 点「拒绝」 → PUT /api/admin/withdrawals { action: "reject" } + │ ▼ + │ status = failed,写 error_message + │ + └── 点「通过」 → PUT /api/admin/withdrawals { action: "approve" } + │ + ▼ + 调 wechat.InitiateTransferByFundApp (FundApp 单笔) + │ + ┌───────────────┼───────────────┐ + ▼ ▼ ▼ + [微信报错] [未返回单号] [成功受理] + │ │ │ + ▼ ▼ ▼ + status=failed status=failed status=processing + 返回报错信息 返回提示 写 detail_no,batch_no,batch_id + 返回「已发起打款,微信处理中」 + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 微 信 侧 与 回 调 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + 微信异步打款 + │ + ▼ + 打款结果 → POST /api/payment/wechat/transfer/notify (PaymentWechatTransferNotify) + │ 验签、解密,得到 out_bill_no / transfer_bill_no / state / fail_reason + │ 用 detail_no = out_bill_no 找到提现记录,且仅当 status 为 processing / pending_confirm 时更新 + ▼ + state=SUCCESS → status = success + state=FAIL/CANCELLED → status = failed,写 fail_reason + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 可 选:主 动 同 步 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + 管理端 POST /api/admin/withdrawals/sync(可带 id 同步单条,或不带 id 同步所有) + │ 只处理 status IN (processing, pending_confirm) + │ FundApp 单笔:用 detail_no 调 QueryTransferByOutBill + ▼ + 按微信返回的 state 更新 status = success / failed(与回调逻辑一致) + +───────────────────────────────────────────────────────────────────────────────── + +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 小 程 序「我 的」- 待 确 认 收 款 │ +└─────────────────────────────────────────────────────────────────────────────────┘ + + [用户] 我的页 → 仅登录显示「待确认收款」区块 + │ + ▼ + GET /api/miniprogram/withdraw/pending-confirm?userId=xxx (WithdrawPendingConfirm) + │ 只返回 status IN (processing, pending_confirm) 的提现(审核通过后的) + ▼ + 展示列表:金额、日期、「确认收款」按钮 + │ + ▼ + 点击「确认收款」→ 需要 item.package + mchId + appId 调 wx.requestMerchantTransfer + │ 当前后端 list 里 package 为空,故会提示「请稍后刷新再试」 + └─ 若后续接入微信返回的 package,可在此完成「用户确认收款」闭环 +``` + +## 二、状态流转 + +| 阶段 | 状态 (status) | 含义 | +|--------------|----------------|------| +| 用户申请 | **pending** | 待审核,已占可提现额度 | +| 管理员通过 | **processing** | 已发起打款,微信处理中 | +| 微信回调成功 | **success** | 打款成功(已到账) | +| 微信回调失败/拒绝 | **failed** | 打款失败,写 fail_reason | +| 预留 | **pending_confirm** | 待用户确认收款(当前流程未改此状态,仅接口可返回) | + +## 三、可提现与待确认口径 + +- **可提现** = 累计佣金 − 已提现 − 待审核金额 + 待审核金额 = 所有 status 为 `pending`、`processing`、`pending_confirm` 的提现金额之和。 +- **待确认收款列表**:仅包含 **审核已通过** 的提现,即 status 为 `processing` 或 `pending_confirm`,不包含 `pending`。 + +## 四、主要接口与代码位置 + +| 环节 | 接口/行为 | 代码位置 | +|------------|-----------|----------| +| 用户申请 | POST `/api/miniprogram/withdraw` | soul-api `internal/handler/withdraw.go` WithdrawPost | +| 可提现计算 | referral/data、withdraw 校验 | `withdraw.go` computeAvailableWithdraw;`referral.go` 提现统计 | +| 管理端列表 | GET `/api/admin/withdrawals` | `internal/handler/admin_withdrawals.go` AdminWithdrawalsList | +| 管理端通过/拒绝 | PUT `/api/admin/withdrawals` | `admin_withdrawals.go` AdminWithdrawalsAction | +| 微信打款 | FundApp 单笔 | soul-api `internal/wechat/transfer.go` InitiateTransferByFundApp | +| 微信回调 | POST `/api/payment/wechat/transfer/notify` | `internal/handler/payment.go` PaymentWechatTransferNotify | +| 管理端同步 | POST `/api/admin/withdrawals/sync` | `admin_withdrawals.go` AdminWithdrawalsSync | +| 待确认列表 | GET `/api/miniprogram/withdraw/pending-confirm` | `withdraw.go` WithdrawPendingConfirm | + +## 五、说明 + +- 当前实现:审核通过后直接调微信 FundApp 单笔打款,最终由**微信回调**或**管理端同步**把状态更新为 success/failed。 +- 「待确认收款」列表只展示已审核通过的记录;点击「确认收款」需后端下发的 `package` 才能调起 `wx.requestMerchantTransfer`,目前该字段为空,前端会提示「请稍后刷新再试」。若后续接入微信返回的 package,可在此完成用户确认收款闭环。