diff --git a/application/admin/controller/fc/Withdraw.php b/application/admin/controller/fc/Withdraw.php index 0fa9f11..b5698d5 100644 --- a/application/admin/controller/fc/Withdraw.php +++ b/application/admin/controller/fc/Withdraw.php @@ -3,6 +3,7 @@ namespace app\admin\controller\fc; use app\common\controller\Backend; +use app\common\library\WithdrawText; use think\Db; /** @@ -131,6 +132,8 @@ class Withdraw extends Backend 'totalWithdrawn' => round($totalWithdrawn, 2), 'withdrawable' => round($withdrawable, 2), 'rejectReasons' => $rejectReasons, + 'failReasonText' => WithdrawText::fail($row['fail_reason']), + 'reasonText' => WithdrawText::reason($row['reason']), ]); return $this->view->fetch(); @@ -293,7 +296,7 @@ class Withdraw extends Backend if ($latest['status'] === 'paid') { $this->success('微信转账已完成,单据已更新为「已成功到账」'); } elseif ($latest['status'] === 'failed') { - $this->error('微信转账已失败/已撤销:' . ($latest['fail_reason'] ?: '未知原因')); + $this->error('微信转账已失败/已撤销:' . (WithdrawText::fail($latest['fail_reason']) ?: '未知原因')); } else { $this->success('已同步微信最新状态:' . $stText . '(微信已受理,需收款人在微信完成确认方可到账)'); } diff --git a/application/admin/view/fc/withdraw/edit.html b/application/admin/view/fc/withdraw/edit.html index 9561bfe..cbaf9f6 100644 --- a/application/admin/view/fc/withdraw/edit.html +++ b/application/admin/view/fc/withdraw/edit.html @@ -186,15 +186,15 @@ {/if} - {if condition="!empty($row.fail_reason)"} + {if condition="!empty($failReasonText)"}
- 打款失败说明:{$row.fail_reason|htmlentities} + 打款失败说明:{$failReasonText|htmlentities}
{/if} - {if condition="!empty($row.reason)"} + {if condition="!empty($reasonText)"}
- 拒绝/驳回原因:{$row.reason|htmlentities} + 拒绝/驳回原因:{$reasonText|htmlentities}
{/if} diff --git a/application/api/controller/AdminDist.php b/application/api/controller/AdminDist.php index 6aeb342..0f207d9 100644 --- a/application/api/controller/AdminDist.php +++ b/application/api/controller/AdminDist.php @@ -2,6 +2,7 @@ namespace app\api\controller; +use app\common\library\WithdrawText; use think\Db; /** @@ -105,7 +106,7 @@ class AdminDist extends V1 'status' => (string)$row['status'], 'channel' => (string)$row['channel'], 'transferStatus' => (string)(isset($row['transfer_status']) ? $row['transfer_status'] : ''), - 'failReason' => (string)(isset($row['fail_reason']) ? $row['fail_reason'] : ''), + 'failReason' => WithdrawText::fail(isset($row['fail_reason']) ? $row['fail_reason'] : ''), 'createdAt' => $this->iso($row['createtime']), ]; } diff --git a/application/api/controller/Distribution.php b/application/api/controller/Distribution.php index 25cd89d..3097d9b 100644 --- a/application/api/controller/Distribution.php +++ b/application/api/controller/Distribution.php @@ -2,6 +2,7 @@ namespace app\api\controller; +use app\common\library\WithdrawText; use think\Db; /** @@ -366,7 +367,7 @@ class Distribution extends V1 'status' => (string)$row['status'], 'transferStatus' => (string)(isset($row['transfer_status']) ? $row['transfer_status'] : ''), 'packageInfo' => (string)(isset($row['package_info']) ? $row['package_info'] : ''), - 'failReason' => (string)(isset($row['fail_reason']) ? $row['fail_reason'] : ''), + 'failReason' => WithdrawText::fail(isset($row['fail_reason']) ? $row['fail_reason'] : ''), 'createdAt' => $this->iso($row['createtime']), 'transferMchId' => $mchId, 'transferAppId' => $appId, @@ -413,12 +414,12 @@ class Distribution extends V1 'amount' => round((float)$row['amount'], 2), 'channel' => (string)$row['channel'], 'status' => (string)$row['status'], - 'reason' => (string)$row['reason'], + 'reason' => WithdrawText::reason($row['reason']), 'outBillNo' => (string)$row['out_bill_no'], 'transferStatus' => (string)$row['transfer_status'], 'transferId' => (string)$row['transfer_id'], 'packageInfo' => (string)$row['package_info'], - 'failReason' => (string)$row['fail_reason'], + 'failReason' => WithdrawText::fail($row['fail_reason']), 'createdAt' => $this->iso($row['createtime']), 'payTime' => !empty($row['paytime']) ? $this->iso($row['paytime']) : '', 'transferTime' => !empty($row['transfer_time']) ? $this->iso($row['transfer_time']) : '', diff --git a/application/common/library/WithdrawText.php b/application/common/library/WithdrawText.php new file mode 100644 index 0000000..425561d --- /dev/null +++ b/application/common/library/WithdrawText.php @@ -0,0 +1,100 @@ + '商户转账账户余额不足', + 'ACCOUNT_ERROR' => '收款账户状态异常', + 'V2_ACCOUNT_SIMPLE_BAN' => '收款账户被限制收款', + 'V3_ACCOUNT_NOT_EXIST' => '收款微信账户不存在', + 'NAME_NOT_MATCH' => '收款人姓名与微信实名不一致', + 'USER_NAME_NOT_MATCH' => '收款人姓名与微信实名不一致', + 'REAL_NAME_CHECK_FAIL' => '收款人微信实名核验未通过', + 'INVALID_OPENID' => '收款人微信标识无效', + 'OPENID_ERROR' => '收款人微信标识异常', + 'AMOUNT_EXCEED' => '超出单笔转账限额', + 'DAILY_LIMIT_EXCEED' => '超出当日转账限额', + 'MCH_CANCEL' => '商户主动撤销转账', + 'MCH_REVOKE' => '商户主动撤销转账', + 'TRANSFER_FAILED' => '微信转账未成功', + 'FAIL' => '微信转账未成功', + 'CANCEL' => '转账已撤销', + 'CANCELLED' => '转账已撤销', + 'PARAM_ERROR' => '转账参数有误,请联系客服', + 'SYSTEM_ERROR' => '微信系统繁忙,请稍后重试', + 'FREQUENCY_LIMITED' => '操作过于频繁,请稍后重试', + 'RULE_LIMIT' => '触发微信风控限制', + 'ACCOUNT_FROZEN' => '收款账户已被冻结', + 'NO_AUTH' => '商户无转账接口权限', + 'APPID_MCHID_NOT_MATCH' => '小程序与商户号不匹配', + 'SIGN_ERROR' => '商户签名错误', + 'IP_NOT_ALLOWED' => '服务器IP未加入微信白名单', + 'IP_FORBIDDEN' => '服务器IP未加入微信白名单', + ]; + + /** 未识别码值的兜底文案 */ + const FAIL_FALLBACK = '微信转账未成功,请稍后重试或联系客服'; + const REASON_FALLBACK = '审核未通过,请联系客服了解详情'; + + /** + * 转账失败原因翻译 + * + * @param string $raw 数据库原始 fail_reason + * @return string 可读中文 + */ + public static function fail($raw) + { + $text = trim((string)$raw); + if ($text === '') { + return ''; + } + + // 去掉「微信转账失败:」这类前缀,只留原因本体 + $text = preg_replace('/^微信转账(失败|撤销)[::]\s*/u', '', $text); + $text = trim((string)$text); + + $code = strtoupper($text); + if (isset(self::$failMap[$code])) { + return self::$failMap[$code]; + } + + // 纯码值(如 V3_XXX / ERR_123):翻译不出就兜底,不把码抛给用户 + if (preg_match('/^[A-Z0-9_\-\.\/]{2,60}$/i', $text)) { + return self::FAIL_FALLBACK; + } + + // 已是中文(微信返回的描述)则直接展示 + return $text; + } + + /** + * 驳回原因翻译 + * + * @param string $raw 数据库原始 reason + * @return string 可读中文 + */ + public static function reason($raw) + { + $text = trim((string)$raw); + if ($text === '') { + return ''; + } + + // 数字编码或纯码值(早期数据)→ 兜底文案 + if (preg_match('/^[0-9]+$/', $text) || preg_match('/^[A-Z0-9_\-\.\/]{2,60}$/i', $text)) { + return self::REASON_FALLBACK; + } + + return $text; + } +} diff --git a/public/assets/js/backend/fc/withdraw.js b/public/assets/js/backend/fc/withdraw.js index a8cb6d7..70950bc 100644 --- a/public/assets/js/backend/fc/withdraw.js +++ b/public/assets/js/backend/fc/withdraw.js @@ -33,6 +33,70 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'backend/format'], fu ''; } + /** + * 微信转账失败/撤销错误码 → 中文说明 + * 与 application/common/library/WithdrawText.php 保持同一份字典 + */ + var FAIL_TEXT = { + NOT_ENOUGH: '商户转账账户余额不足', + ACCOUNT_ERROR: '收款账户状态异常', + V2_ACCOUNT_SIMPLE_BAN: '收款账户被限制收款', + V3_ACCOUNT_NOT_EXIST: '收款微信账户不存在', + NAME_NOT_MATCH: '收款人姓名与微信实名不一致', + USER_NAME_NOT_MATCH: '收款人姓名与微信实名不一致', + REAL_NAME_CHECK_FAIL: '收款人微信实名核验未通过', + INVALID_OPENID: '收款人微信标识无效', + OPENID_ERROR: '收款人微信标识异常', + AMOUNT_EXCEED: '超出单笔转账限额', + DAILY_LIMIT_EXCEED: '超出当日转账限额', + MCH_CANCEL: '商户主动撤销转账', + MCH_REVOKE: '商户主动撤销转账', + TRANSFER_FAILED: '微信转账未成功', + FAIL: '微信转账未成功', + CANCEL: '转账已撤销', + CANCELLED: '转账已撤销', + PARAM_ERROR: '转账参数有误,请联系客服', + SYSTEM_ERROR: '微信系统繁忙,请稍后重试', + FREQUENCY_LIMITED: '操作过于频繁,请稍后重试', + RULE_LIMIT: '触发微信风控限制', + ACCOUNT_FROZEN: '收款账户已被冻结', + NO_AUTH: '商户无转账接口权限', + APPID_MCHID_NOT_MATCH: '小程序与商户号不匹配', + SIGN_ERROR: '商户签名错误', + IP_NOT_ALLOWED: '服务器IP未加入微信白名单', + IP_FORBIDDEN: '服务器IP未加入微信白名单' + }; + var FAIL_FALLBACK = '微信转账未成功,请稍后重试或联系客服'; + var REASON_FALLBACK = '审核未通过,请联系客服了解详情'; + + /** + * 失败原因码值转中文 + * + * @param {string} raw 数据库原始 fail_reason + * @return {string} 可读中文 + */ + function failText(raw) { + var text = $.trim(raw || ''); + if (!text) return ''; + text = $.trim(text.replace(/^微信转账(失败|撤销)[::]\s*/, '')); + if (FAIL_TEXT[text.toUpperCase()]) return FAIL_TEXT[text.toUpperCase()]; + if (/^[A-Z0-9_\-.\/]{2,60}$/i.test(text)) return FAIL_FALLBACK; + return text; + } + + /** + * 驳回原因码值转中文 + * + * @param {string} raw 数据库原始 reason + * @return {string} 可读中文 + */ + function reasonText(raw) { + var text = $.trim(raw || ''); + if (!text) return ''; + if (/^[0-9]+$/.test(text) || /^[A-Z0-9_\-.\/]{2,60}$/i.test(text)) return REASON_FALLBACK; + return text; + } + var Controller = { /** * 提现列表页初始化 @@ -115,10 +179,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'backend/format'], fu return value && m[value] ? m[value] : (value || '-'); } }, - {field: 'reason', title: '拒绝原因', operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'reason', title: '拒绝原因', operate: 'LIKE', table: table, class: 'autocontent', formatter: function (value) { + return reasonText(value) || '-'; + }}, {field: 'fail_reason', title: '转账失败原因', operate: 'LIKE', table: table, class: 'autocontent', formatter: function (value) { - if (!value) return '-'; - return '' + value + ''; + var text = failText(value); + if (!text) return '-'; + return '' + text + ''; }}, {field: 'paytime', title: __('Paytime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, {field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},