diff --git a/miniprogram/pages/my/my.js b/miniprogram/pages/my/my.js
index b847e424..9f6d9491 100644
--- a/miniprogram/pages/my/my.js
+++ b/miniprogram/pages/my/my.js
@@ -50,10 +50,14 @@ Page({
withdrawMchId: '',
withdrawAppId: '',
+ // 未登录假资料(展示用)
+ guestNickname: '游客',
+ guestAvatar: '',
+
// 登录弹窗
showLoginModal: false,
isLoggingIn: false,
-
+
// 修改昵称弹窗
showNicknameModal: false,
editingNickname: ''
diff --git a/miniprogram/pages/my/my.wxml b/miniprogram/pages/my/my.wxml
index f967491f..cd06b6ca 100644
--- a/miniprogram/pages/my/my.wxml
+++ b/miniprogram/pages/my/my.wxml
@@ -11,16 +11,36 @@
-
-
-
- 🔐
- 登录 Soul创业实验
- 登录后可购买章节、解锁更多内容
-
+
+
+
+
+
+ --
+ 已读章节
+
+
+ --
+ 推荐好友
+
+
+ --
+ 待领收益
+
@@ -241,9 +261,9 @@
-
+
-
+
✕
🔐
登录 Soul创业实验
@@ -257,6 +277,7 @@
微
{{isLoggingIn ? '登录中...' : '微信快捷登录'}}
+ 取消
登录即表示同意《用户协议》和《隐私政策》
diff --git a/miniprogram/pages/my/my.wxss b/miniprogram/pages/my/my.wxss
index 469d46c0..15b44a5b 100644
--- a/miniprogram/pages/my/my.wxss
+++ b/miniprogram/pages/my/my.wxss
@@ -305,67 +305,24 @@
margin-top: 4rpx;
}
-/* ===== 登录卡片样式 ===== */
-.login-card {
- min-height: 400rpx;
- display: flex;
- align-items: center;
- justify-content: center;
+/* ===== 未登录假资料样式 ===== */
+.avatar-placeholder {
+ cursor: default;
}
-.login-prompt {
- display: flex;
- flex-direction: column;
- align-items: center;
- text-align: center;
- padding: 40rpx 0;
- width: 100%;
+.user-id-guest {
+ color: rgba(255, 255, 255, 0.35) !important;
}
-.login-icon-large {
- font-size: 80rpx;
- margin-bottom: 32rpx;
-}
-
-.login-title {
- font-size: 36rpx;
+.btn-login-inline {
+ flex-shrink: 0;
+ margin-left: 16rpx;
+ padding: 10rpx 24rpx;
+ background: linear-gradient(135deg, #00CED1 0%, #20B2AA 100%);
+ color: #000;
+ font-size: 24rpx;
font-weight: 600;
- color: #ffffff;
- margin-bottom: 16rpx;
-}
-
-.login-desc {
- font-size: 26rpx;
- color: rgba(255, 255, 255, 0.5);
- margin-bottom: 48rpx;
- line-height: 1.6;
-}
-
-.btn-wechat-large {
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 16rpx;
- width: 80%;
- padding: 28rpx 0;
- background: linear-gradient(135deg, #07C160 0%, #06AD56 100%);
- border-radius: 48rpx;
- border: none;
- color: #ffffff;
- font-size: 32rpx;
- font-weight: 600;
-}
-
-.btn-wechat-large .btn-icon {
- width: 48rpx;
- height: 48rpx;
- background: rgba(255, 255, 255, 0.2);
- border-radius: 8rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 28rpx;
- font-weight: 700;
+ border-radius: 24rpx;
}
.user-name {
@@ -1028,6 +985,15 @@
font-size: 32rpx;
}
+/* 登录弹窗内取消按钮 */
+.login-modal-cancel {
+ margin-top: 24rpx;
+ padding: 24rpx;
+ font-size: 28rpx;
+ color: rgba(255, 255, 255, 0.5);
+ text-align: center;
+}
+
.login-notice {
display: block;
margin-top: 32rpx;
diff --git a/soul-admin/src/pages/distribution/DistributionPage.tsx b/soul-admin/src/pages/distribution/DistributionPage.tsx
index 98706602..8c1f5cf7 100644
--- a/soul-admin/src/pages/distribution/DistributionPage.tsx
+++ b/soul-admin/src/pages/distribution/DistributionPage.tsx
@@ -234,12 +234,13 @@ export function DistributionPage() {
async function handleApproveWithdrawal(id: string) {
if (!confirm('确认审核通过并打款?')) return
try {
- const res = await put<{ success?: boolean; error?: string }>('/api/admin/withdrawals', {
- id,
- action: 'approve',
- })
+ const res = await put<{ success?: boolean; error?: string; message?: string }>(
+ '/api/admin/withdrawals',
+ { id, action: 'approve' },
+ )
if (!res?.success) {
- alert(res?.error || '操作失败')
+ const detail = res?.message || res?.error || '操作失败'
+ alert(detail)
return
}
await refreshCurrentTab()
diff --git a/soul-admin/tmp/build-errors.log b/soul-admin/tmp/build-errors.log
new file mode 100644
index 00000000..4660a1c0
--- /dev/null
+++ b/soul-admin/tmp/build-errors.log
@@ -0,0 +1 @@
+exit status 1exit status 1
\ No newline at end of file
diff --git a/soul-api/internal/handler/admin_withdrawals.go b/soul-api/internal/handler/admin_withdrawals.go
index 24807021..270a6695 100644
--- a/soul-api/internal/handler/admin_withdrawals.go
+++ b/soul-api/internal/handler/admin_withdrawals.go
@@ -173,8 +173,10 @@ func AdminWithdrawalsAction(c *gin.Context) {
result, err := wechat.InitiateTransfer(params)
if err != nil {
- // 未初始化转账客户端:仅标记为 success,提示线下打款
- if err.Error() == "转账客户端未初始化" {
+ errMsg := err.Error()
+ fmt.Printf("[AdminWithdrawals] 发起转账失败 id=%s: %s\n", body.ID, errMsg)
+ // 未初始化或未配置转账:仅标记为已打款并提示线下处理(与 transfer 包返回文案一致)
+ if errMsg == "支付/转账未初始化,请先调用 wechat.Init" || errMsg == "转账客户端未初始化" {
_ = db.Model(&w).Updates(map[string]interface{}{
"status": "success",
"processed_at": now,
@@ -185,8 +187,8 @@ func AdminWithdrawalsAction(c *gin.Context) {
})
return
}
- // 其他打款失败:记失败原因
- failMsg := err.Error()
+ // 其他打款失败(含调用腾讯接口失败):记失败原因
+ failMsg := errMsg
_ = db.Model(&w).Updates(map[string]interface{}{
"status": "failed",
"fail_reason": failMsg,
diff --git a/soul-api/tmp/main.exe b/soul-api/tmp/main.exe
new file mode 100644
index 00000000..0f1e9248
Binary files /dev/null and b/soul-api/tmp/main.exe differ
diff --git a/soul-api/wechat/info.log b/soul-api/wechat/info.log
index 338eff6a..7c723259 100644
--- a/soul-api/wechat/info.log
+++ b/soul-api/wechat/info.log
@@ -28,3 +28,33 @@
{"level":"debug","timestamp":"2026-02-09T21:46:31+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 400 Bad Request\r\nContent-Length: 207\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Mon, 09 Feb 2026 13:46:31 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 08B7CAA7CC0610EA0418B3D7BCA80120812028ACD903-268435462\r\nServer: nginx\r\nWechatpay-Nonce: d08926059983e7a83c001572543aa0cc\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: DCqVYlZQVZC7VVTr55VqYFA1OxgJ048FAhYFZ2m2rBuMuRxUEF/JlSe3dZjRZUn9ZSUDzROrF5zBMG2phkxa8Qy2O7+hy/mrWd6BVD778TD6TiL2MqwIsj83DoMtV/yFrwlnhDRc4McKnD+NbrWdplVIYnSt1MyKJU1RQEdofGBKlx3p88bn8dgnNwsnokAp7dJBldQapOUCZc5LWJ2ZGEws5uniob6HIeZlQm7a3rgVzBm9VwJEuVpErZE0O5IvXOcZjGg+D1yiEBxLrIquQyjFyajOui4NN6jfCIG+On0YLRuB3IXGS1eOvgJXCZev//VeNq3IXHobIf1F/H65jg==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1770644791\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"code\":\"PARAM_ERROR\",\"detail\":{\"location\":\"body\",\"value\":41},\"message\":\"输入源“/body/batch_remark”映射到值字段“批次备注”字符串规则校验失败,字符数 41,大于最大值 32\"}"}
{"level":"debug","timestamp":"2026-02-09T21:48:08+08:00","caller":"kernel/baseClient.go:457","content":"POST https://api.mch.weixin.qq.com/v3/transfer/batches request header: { Content-Type:application/jsonAuthorization:WECHATPAY2-SHA256-RSA2048 mchid=\"1318592501\",nonce_str=\"wUX5RqmlbUUTEnuzRiD9FAFTFL9zPXLY\",timestamp=\"1770644888\",serial_no=\"4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5\",signature=\"w1YBlKTIo07vfIJbf4IvFf88QKaWXdOS9ulWxMzguvxb6bfgKNZQ1xLdOWlesI+b5KdJr9rpLDc2/7r6sZcqauKTH2mxxcW48VwPkNTzGfb7pqKsCcOHu3xpn6XR+lSPe/qEL4vyxwS83HLJhlRk32opXOFPp/g457D/DJn8X1QDnW0jngLug4SG/uu8J4vqZNGODPvsRyXQZZzPkGAJ3cVYuqLAywkaVxgwKjcB4dVz6PWm58EOakxN1wIkDUIIxkddFqkTg1z9zy3NoFagqwyNXDJ0K4VumBWt3yNThPA376RBF04noV0mrTXzRpylHGeKPp7TLTcEeJYmQUiRtg==\"Accept:*/*} request body:"}
{"level":"debug","timestamp":"2026-02-09T21:48:08+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 400 Bad Request\r\nContent-Length: 207\r\nCache-Control: no-cache, must-revalidate\r\nConnection: keep-alive\r\nContent-Language: zh-CN\r\nContent-Type: application/json; charset=utf-8\r\nDate: Mon, 09 Feb 2026 13:48:08 GMT\r\nKeep-Alive: timeout=8\r\nRequest-Id: 0898CBA7CC06108803188AD2BCA80120B00B2890DB05-268435462\r\nServer: nginx\r\nWechatpay-Nonce: 28af031c95ea837f0ffb34c27b76c76d\r\nWechatpay-Serial: 5F2543BF58239A4EB68FA4433DF1438A88B34B16\r\nWechatpay-Signature: KtamVaPOVNlk+XuLtBcSUh9sq6B+QVPnupofCmLD95NF3z+uUsu2ia7tOXG6BR8oEOL6z/YVkJ9LmR8sQ/Kmx9/n3wlrQTYzWhesHUNNK/rkzXgefeYofh4LBZKlaaqjJ3PuCafyueBmrW4V6Vqt1XwSbrbLx4MLrR9t2qFrW0xG43Ru0ymA9hN7c0N/XTE/8V8Jl3BB1jJx24NlJr0T+RWEkzDOn54gzRJaGJTdDJYRQCOVterVYQPfMUxPvfIJbRi2/Fh1NXYESrgsq9gKPyc6S/oPgEBGyQXaY8LQDqQgA2NNrn1vVEOiOzvluF2l8CtCNo/RWwfBKmE0jZcj4A==\r\nWechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048\r\nWechatpay-Timestamp: 1770644888\r\nX-Content-Type-Options: nosniff\r\n\r\n{\"code\":\"PARAM_ERROR\",\"detail\":{\"location\":\"body\",\"value\":41},\"message\":\"输入源“/body/batch_remark”映射到值字段“批次备注”字符串规则校验失败,字符数 41,大于最大值 32\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Tue, 10 Feb 2026 02:28:39 GMT\r\n\r\n{\"access_token\":\"100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsPSSjAJASVV\",\"expires_in\":7200}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Tue, 10 Feb 2026 02:28:39 GMT\r\n\r\n{\"access_token\":\"100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsJFCjAJARNK\",\"expires_in\":7200}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Tue, 10 Feb 2026 02:28:39 GMT\r\n\r\n{\"access_token\":\"100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsFHNjAJAMOU\",\"expires_in\":7200}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Tue, 10 Feb 2026 02:28:39 GMT\r\n\r\n{\"access_token\":\"100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsDCAjAJAQPN\",\"expires_in\":7200}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Tue, 10 Feb 2026 02:28:39 GMT\r\n\r\n{\"access_token\":\"100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsMLYjAJAXWJ\",\"expires_in\":7200}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Tue, 10 Feb 2026 02:28:39 GMT\r\n\r\n{\"access_token\":\"100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsUPBjAJALGS\",\"expires_in\":7200}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsPSSjAJASVV&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0f3MqnGa1OW0aL0Go4Ha1nzWzE4MqnGE&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:28:39 GMT\r\n\r\n{\"session_key\":\"CpKNLe0O+AZIOaSznEhU2w==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsJFCjAJARNK&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0e3jJGll2nQW9h4v4nnl2wgWd22jJGla&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:28:40 GMT\r\n\r\n{\"session_key\":\"CpKNLe0O+AZIOaSznEhU2w==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsFHNjAJAMOU&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0a3tY3nl29v18h4yGSkl2Mg4Cf4tY3nv&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:28:40 GMT\r\n\r\n{\"session_key\":\"CpKNLe0O+AZIOaSznEhU2w==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsDCAjAJAQPN&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0d3U7y1w30Qhw63wgj2w3Z7DZg2U7y1n&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:39+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:28:40 GMT\r\n\r\n{\"session_key\":\"CpKNLe0O+AZIOaSznEhU2w==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:40+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsMLYjAJAXWJ&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0b3On6Ga1JTJ9L0kS0Ha1Px9241On6Gn&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:40+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:28:40 GMT\r\n\r\n{\"session_key\":\"CpKNLe0O+AZIOaSznEhU2w==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:40+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsUPBjAJALGS&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0c3UwVGa1XeFbL0v8bGa1BKzkp3UwVGg&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:40+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:28:40 GMT\r\n\r\n{\"session_key\":\"CpKNLe0O+AZIOaSznEhU2w==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:28:40+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_P7g4blBL6WGpiWnpgaOj6g5fofKxJaow-bPXoxC2KpcTQJnGqp1TC4Kam6XU8RJXghMpp0tJkAz9fDxQaP_34XYZq6DHf3lzGH0-j7-YHiSOIuvNAdO7wxX6ovsUPBjAJALGS&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0f3lGpll2gNF9h4B4wnl28WCjd4lGple&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:28:40+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:28:40 GMT\r\n\r\n{\"session_key\":\"CpKNLe0O+AZIOaSznEhU2w==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
+{"level":"debug","timestamp":"2026-02-10T10:39:28+08:00","caller":"kernel/accessToken.go:381","content":"GET https://api.weixin.qq.com/cgi-bin/token?appid=wxb8bbb2b10dec74aa&grant_type=client_credential&neededText=&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:39:28+08:00","caller":"kernel/accessToken.go:383","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 174\r\nConnection: keep-alive\r\nContent-Type: application/json; encoding=utf-8\r\nDate: Tue, 10 Feb 2026 02:39:28 GMT\r\n\r\n{\"access_token\":\"100_O1K3OEKfS5xdLDj3z6g41UuJ8grNWUghMbn1ZZ8PbY1mh_EqTuJQId9K7ZnEB966BoXPGtxZnB6rk8JXK-4pAvWaCkc0sEr-gKN0s1wVDmuB1zrNACtonCTbPGgVFQgAEAOYJ\",\"expires_in\":7200}"}
+{"level":"debug","timestamp":"2026-02-10T10:39:28+08:00","caller":"kernel/baseClient.go:457","content":"GET https://api.weixin.qq.com/sns/jscode2session?access_token=100_O1K3OEKfS5xdLDj3z6g41UuJ8grNWUghMbn1ZZ8PbY1mh_EqTuJQId9K7ZnEB966BoXPGtxZnB6rk8JXK-4pAvWaCkc0sEr-gKN0s1wVDmuB1zrNACtonCTbPGgVFQgAEAOYJ&appid=wxb8bbb2b10dec74aa&grant_type=authorization_code&js_code=0b3I5oGa1Ow0aL0FiSFa1VLWfZ2I5oGx&secret=3c1fb1f63e6e052222bbcead9d07fe0c request header: { Accept:*/*} "}
+{"level":"debug","timestamp":"2026-02-10T10:39:28+08:00","caller":"kernel/baseClient.go:459","content":"------------------response content:HTTP/1.1 200 OK\r\nContent-Length: 82\r\nConnection: keep-alive\r\nContent-Type: text/plain\r\nDate: Tue, 10 Feb 2026 02:39:28 GMT\r\n\r\n{\"session_key\":\"RtzZJRnbC1pTwaJreA1XRw==\",\"openid\":\"ogpTW5fmXRGNpoUbXB3UEqnVe5Tg\"}"}
diff --git a/soul-api/商家转账到零钱说明.txt b/soul-api/商家转账到零钱说明.txt
new file mode 100644
index 00000000..ab4959dd
--- /dev/null
+++ b/soul-api/商家转账到零钱说明.txt
@@ -0,0 +1,59 @@
+# 商家转账到零钱 - 功能位置与打通条件
+
+## 一、入口在哪个页面(唯一入口)
+
+- 管理端(soul-admin):【分销】页 → 左侧 Tab 选【提现审核】→ 某条提现右侧点【通过】按钮。
+- 即:管理后台 → 提现审核列表 → 点击「通过」= 发起「商家转账到零钱」到腾讯。
+
+没有别的页面会发起转账;小程序端只负责「申请提现」(落库待审核),打款只在管理端点「通过」时触发。
+
+---
+
+## 二、后端调用链(代码位置)
+
+1. 接口:PUT /api/admin/withdrawals,body: { "id": "提现记录id", "action": "approve" }
+2. 处理:soul-api/internal/handler/admin_withdrawals.go → AdminWithdrawalsAction,case "approve"
+3. 调微信:wechat.InitiateTransfer(params)
+4. 实现:soul-api/internal/wechat/transfer.go → InitiateTransfer → paymentApp.TransferBatch.Batch()(PowerWeChat 调腾讯「发起转账」API)
+
+---
+
+## 三、为什么「没发起到腾讯」常见原因
+
+1. 启动时 wechat.Init 失败
+ - main.go 里会 log.Fatal,服务起不来;若能正常访问 /health,说明 Init 已成功,paymentApp 非空。
+
+2. 商户号未开通「商家转账到零钱」
+ - 登录 微信支付商户平台 → 产品中心 → 商家转账到零钱,需已开通且生效。
+
+3. 证书/密钥不对
+ - 转账用 API v3,需要:APIv3 密钥、商户证书(apiclient_cert.pem)、商户私钥(apiclient_key.pem)、证书序列号。
+ - .env 里 WECHAT_CERT_PATH、WECHAT_KEY_PATH、WECHAT_APIV3_KEY、WECHAT_SERIAL_NO 必须与商户平台一致,且路径在运行目录下可读(或 OSS 等 URL 可访问)。
+
+4. 环境变量未生效
+ - 若未配置或配错,可能走 config 默认值;部署时务必用实际 .env 覆盖,并重启 soul-api。
+
+---
+
+## 四、必须的 .env 配置(转账相关)
+
+- WECHAT_APPID:小程序 AppID(与商户号已绑定)
+- WECHAT_MCH_ID:商户号
+- WECHAT_APIV3_KEY:商户平台 → API 安全 → APIv3 密钥(32 位)
+- WECHAT_CERT_PATH:商户 API 证书(pem)路径或可访问 URL
+- WECHAT_KEY_PATH:商户 API 私钥(pem)路径或可访问 URL
+- WECHAT_SERIAL_NO:商户 API 证书序列号(商户平台可查)
+- WECHAT_TRANSFER_URL:转账结果回调地址,需 HTTPS、外网可访问,如:https://你的域名/api/payment/wechat/transfer/notify
+
+---
+
+## 五、自检是否打通
+
+1. 管理端点「通过」后:
+ - 若返回「已发起打款,微信处理中」且列表里该条变为「处理中」→ 说明已调通腾讯,等回调或去商户平台查单。
+ - 若返回「发起打款失败」且 message 里是「支付/转账未初始化…」→ 未初始化或未配置,检查 .env 与 wechat.Init。
+ - 若返回「发起打款失败」且 message 里是证书/签名/权限等错误 → 按报错检查商户号开通、证书、APIv3 密钥、序列号。
+
+2. 看 soul-api 启动日志:若 wechat.Init 报错会直接退出;无报错则说明 Payment 初始化成功,问题多在商户开通或单次请求参数。
+
+3. 商户平台:产品中心 → 商家转账到零钱 → 查看是否已开通;可查转账记录/批次号确认是否收到请求。