feat: contract uses num_lh, male avatar, captcha upgrade, full i18n

- Contract buy/close/cancel all use num_lh (contract balance) not num (spot)
- Wallet API returns contract (lh) account data block
- My.php returns user id field for frontend display
- Avatar: DiceBear avataaars male business style
- Captcha: 3x scaled text for readability
- Transfer log descriptions in English
- All billing descriptions in English
This commit is contained in:
li
2026-04-05 13:05:37 +08:00
parent 733982a2be
commit 7d7f53b356
6 changed files with 154 additions and 154 deletions
+41 -41
View File
@@ -331,56 +331,56 @@ class Common extends Api
*/
public function captcha()
{
$a = mt_rand(1, 20);
$b = mt_rand(1, 20);
$operators = ['+', '-'];
$op = $operators[array_rand($operators)];
if ($op == '-' && $a < $b) {
// 确保减法结果非负
$tmp = $a; $a = $b; $b = $tmp;
// 生成4位随机大写英文字母
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ'; // 去掉易混淆的 I O
$answer = '';
for ($i = 0; $i < 4; $i++) {
$answer .= $chars[mt_rand(0, strlen($chars) - 1)];
}
$answer = ($op == '+') ? ($a + $b) : ($a - $b);
$text = "{$a} {$op} {$b} = ?";
// 生成唯一key标识本次验证码
$captcha_key = md5(uniqid(mt_rand(), true));
cache('captcha_' . $captcha_key, strtoupper($answer), 300);
// 将答案存入缓存(使用ThinkPHP缓存,5分钟过期)
cache('captcha_' . $captcha_key, strval($answer), 300);
// 先在小画布绘制文字,再等比放大 → 让内置字体看起来更大
$smallW = 100;
$smallH = 32;
$small = imagecreatetruecolor($smallW, $smallH);
$smallBg = imagecolorallocate($small, 240, 244, 250);
imagefilledrectangle($small, 0, 0, $smallW, $smallH, $smallBg);
// 生成验证码图片
$width = 200;
$height = 60;
// 干扰线(小画布上)
for ($i = 0; $i < 3; $i++) {
$lc = imagecolorallocate($small, mt_rand(160, 210), mt_rand(160, 210), mt_rand(160, 210));
imageline($small, mt_rand(0, $smallW), mt_rand(0, $smallH), mt_rand(0, $smallW), mt_rand(0, $smallH), $lc);
}
// 文字(内置最大字号5,字符宽9px)
$fontSize = 5;
$charW = imagefontwidth($fontSize);
$charH = imagefontheight($fontSize);
$totalW = $charW * 4;
$startX = ($smallW - $totalW) / 2;
$startY = ($smallH - $charH) / 2;
for ($i = 0; $i < 4; $i++) {
$tc = imagecolorallocate($small, mt_rand(10, 70), mt_rand(10, 70), mt_rand(10, 70));
imagestring($small, $fontSize, (int)($startX + $i * $charW), (int)$startY, $answer[$i], $tc);
}
// 放大3倍到输出画布
$scale = 3;
$width = $smallW * $scale;
$height = $smallH * $scale;
$img = imagecreatetruecolor($width, $height);
imagecopyresampled($img, $small, 0, 0, 0, 0, $width, $height, $smallW, $smallH);
imagedestroy($small);
// 背景色
$bgColor = imagecolorallocate($img, 240, 244, 250);
imagefilledrectangle($img, 0, 0, $width, $height, $bgColor);
// 干扰线
for ($i = 0; $i < 5; $i++) {
$lineColor = imagecolorallocate($img, mt_rand(100, 200), mt_rand(100, 200), mt_rand(100, 200));
imageline($img, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $lineColor);
// 干扰点(放大后再叠加,避免被放大模糊)
for ($i = 0; $i < 60; $i++) {
$dc = imagecolorallocate($img, mt_rand(150, 230), mt_rand(150, 230), mt_rand(150, 230));
imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), $dc);
}
// 干扰点
for ($i = 0; $i < 50; $i++) {
$dotColor = imagecolorallocate($img, mt_rand(100, 255), mt_rand(100, 255), mt_rand(100, 255));
imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), $dotColor);
}
// 文字颜色
$textColor = imagecolorallocate($img, mt_rand(10, 80), mt_rand(10, 80), mt_rand(10, 80));
// 使用内置字体绘制文字
$fontSize = 5; // imagestring内置字体最大5
$textWidth = imagefontwidth($fontSize) * strlen($text);
$textHeight = imagefontheight($fontSize);
$x = ($width - $textWidth) / 2;
$y = ($height - $textHeight) / 2;
imagestring($img, $fontSize, $x, $y, $text, $textColor);
// 输出为base64
ob_start();
imagepng($img);
$imgData = ob_get_clean();
@@ -406,7 +406,7 @@ class Common extends Api
if ($answer === false || $answer === null) {
return false;
}
$result = (trim($captcha_code) === trim($answer));
$result = (strtoupper(trim($captcha_code)) === strtoupper(trim($answer)));
// 验证后立即删除,防止重放
cache('captcha_' . $captcha_key, null);
return $result;