| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- <?php
- namespace App\Services;
- use SimpleSoftwareIO\QrCode\Facades\QrCode;
- use Endroid\QrCode\Builder\Builder;
- use Endroid\QrCode\Writer\PngWriter;
- use Telegram\Bot\Api;
- use App\Models\Config;
- use Telegram\Bot\FileUpload\InputFile;
- use Illuminate\Support\Facades\Log;
- use App\Jobs\SendTelegramMessageJob;
- use App\Jobs\SendTelegramGroupMessageJob;
- class BaseService
- {
- const YES = 1;
- const NOT = 0;
- /**
- * @description: 生成充值二维码
- * @param {*} $address 充值地址
- * @return {*}
- */
- public static function createRechargeQrCode($address = '')
- {
- $content = $address;
- $qrSize = 300;
- $font = 4;
- $textHeight = 20;
- $padding = 10;
- // 生成二维码图像对象
- $result = Builder::create()
- ->writer(new PngWriter())
- ->data($content)
- ->size($qrSize)
- ->margin(0)
- ->build();
- $qrImage = imagecreatefromstring($result->getString());
- // 创建画布(加上下方文字区和边距)
- $canvasWidth = $qrSize + $padding * 2;
- $canvasHeight = $qrSize + $textHeight + $padding * 2;
- $image = imagecreatetruecolor($canvasWidth, $canvasHeight);
- // 背景白色
- $white = imagecolorallocate($image, 255, 255, 255);
- imagefill($image, 0, 0, $white);
- // 黑色字体
- $black = imagecolorallocate($image, 0, 0, 0);
- // 合并二维码图像
- imagecopy($image, $qrImage, $padding, $padding, 0, 0, $qrSize, $qrSize);
- // 写文字
- $textWidth = imagefontwidth($font) * strlen($content);
- $x = ($canvasWidth - $textWidth) / 2;
- $y = $qrSize + $padding + 5;
- imagestring($image, $font, $x, $y, $content, $black);
- // 生成文件名
- $filename = $address. '.png';
- $relativePath = 'recharge/' . $filename;
- $storagePath = storage_path('app/public/' . $relativePath);
- // 确保目录存在
- @mkdir(dirname($storagePath), 0777, true);
- // 保存图片到文件
- imagepng($image, $storagePath);
- // 清理
- imagedestroy($qrImage);
- imagedestroy($image);
- // 返回 public 存储路径(可用于 URL)
- return 'storage/'.$relativePath; // 或返回 Storage::url($relativePath);
- }
- /**
- * 判断指定地址的二维码是否已生成(已存在文件)
- *
- * @param string $address 充值地址
- * @return
- */
- public static function rechargeQrCodeExists(string $address)
- {
- $filename = $address . '.png';
- $relativePath = 'recharge/' . $filename;
- $storagePath = storage_path('app/public/' . $relativePath);
- $path = '';
- if(file_exists($storagePath)){
- $path = 'storage/'.$relativePath;
- }
- return $path;
- }
- /**
- * @description: 转成树形数据
- * @param {*} $list 初始数据
- * @param {*} $pid 父id
- * @param {*} $level 层级
- * @param {*} $pid_name pid字段名称 默认pid
- * @param {*} $id_name 主键id 名称
- * @return {*}
- */
- public static function toTree($list,$pid=0,$level=0,$pid_name='pid',$id_name='id')
- {
- $arr=[];
- $level++;
- foreach($list as $k => $v){
- if($pid==$v[$pid_name]){
- $v['level']=$level;
- $v['children']=self::toTree($list,$v[$id_name],$level,$pid_name,$id_name);
- $arr[]=$v;
- }
- }
- return $arr;
- }
- /**
- * @description: 实例化TG
- * @return {*}
- */
- public static function telegram()
- {
- return app(Api::class);
- }
- // /**
- // * @description: 群组通知(自动分段发送,支持中文与多字节字符)
- // * @param string $text 通知内容
- // * @param array $keyboard 操作按钮
- // * @param string $image 图片路径(可选)
- // * @param bool $isTop 是否置顶第一条消息
- // */
- // public static function bettingGroupNotice($text, $keyboard = [], $image = '', $isTop = false)
- // {
- // $bettingGroup = Config::where('field', 'betting_group')->first()->val;
- // $telegram = self::telegram();
- //
- // $maxLen = 1024; // Telegram 限制:最多 1024 个字符
- // $textParts = [];
- // $textLength = mb_strlen($text, 'UTF-8');
- // for ($i = 0; $i < $textLength; $i += $maxLen) {
- // $textParts[] = mb_substr($text, $i, $maxLen, 'UTF-8');
- // }
- //
- // $firstMessageId = null;
- //
- // foreach ($textParts as $index => $partText) {
- // $botMsg = [
- // 'chat_id' => "@{$bettingGroup}",
- // 'text' => $partText,
- // ];
- //
- // if (count($keyboard) > 0 && $index === 0) {
- // $botMsg['reply_markup'] = json_encode(['inline_keyboard' => $keyboard]);
- // }
- //
- // if (!empty($image) && $index === 0) {
- // // 第一条带图片
- // $botMsg['photo'] = InputFile::create($image);
- // $botMsg['caption'] = $partText;
- // $botMsg['protect_content'] = true;
- // $response = $telegram->sendPhoto($botMsg);
- // } else {
- // $response = $telegram->sendMessage($botMsg);
- // }
- //
- // if ($isTop && $index === 0 && $response && $response->get('message_id')) {
- // $firstMessageId = $response->get('message_id');
- // }
- //
- // // 防止限流(可选)
- // usleep(300000);
- // }
- //
- // if ($isTop && $firstMessageId) {
- // $telegram->pinChatMessage([
- // 'chat_id' => "@{$bettingGroup}",
- // 'message_id' => $firstMessageId
- // ]);
- // }
- // }
- /**
- * @description: 群组通知
- * @param {string} $text 通知内容
- * @param {array} $keyboard 操作按钮
- * @param {*string} $image 图片
- * @return {*}
- */
- public static function bettingGroupNotice($text ,$keyboard = [], $image = '' ,$isTop = false)
- {
- $bettingGroup = Config::where('field', 'betting_group')->first()->val;
- $botMsg = [
- 'chat_id' => "@{$bettingGroup}",
- 'text' => $text
- ];
- if(count($keyboard)>0){
- $botMsg['reply_markup'] = json_encode(['inline_keyboard' => $keyboard]);
- }
- if(!empty($image)){
- $botMsg['photo'] = InputFile::create($image);
- $botMsg['caption'] = $text;
- $botMsg['protect_content'] = true; // 防止转发
- $response = self::telegram()->sendPhoto($botMsg);
- }else{
- $response = self::telegram()->sendMessage($botMsg);
- }
- if($isTop == true){
- // 获取消息ID
- $messageId = $response->get('message_id');
- // 置顶消息
- self::telegram()->pinChatMessage([
- 'chat_id' => "@{$bettingGroup}",
- 'message_id' => $messageId
- ]);
- }
- }
- /**
- * @description: 异步群组通知
- * @param {string} $text 通知内容
- * @param {array} $keyboard 操作按钮
- * @param {*string} $image 图片
- * @return {*}
- */
- public static function asyncBettingGroupNotice($text ,$keyboard = [], $image = '' ,$isTop = false)
- {
- SendTelegramGroupMessageJob::dispatch($text ,$keyboard ,$image ,$isTop);
- }
- /**
- * @description: 发送消息
- * @param {string} $chatId 聊天ID
- * @param {string} $text 消息内容
- * @param {array} $keyboard 操作按钮
- * @param {*string} $image 图片
- * @return {*}
- */
- public static function sendMessage($chatId ,$text ,$keyboard = [] ,$image = '')
- {
- $botMsg = [
- 'chat_id' => $chatId,
- ];
- if(count($keyboard)>0){
- $botMsg['reply_markup'] = json_encode(['inline_keyboard' => $keyboard]);
- }
- if($image != ''){
- $botMsg['photo'] = InputFile::create($image);
- $botMsg['caption'] = $text;
- $botMsg['protect_content'] = true; // 防止转发
- self::telegram()->sendPhoto($botMsg);
- }else{
- $botMsg['text'] = $text;
- self::telegram()->sendMessage($botMsg);
- }
- }
- /**
- * @description: 异步发送消息
- * @param {string} $chatId 聊天ID
- * @param {string} $text 消息内容
- * @param {array} $keyboard 操作按钮
- * @param {*string} $image 图片
- * @return {*}
- */
- public static function asyncSendMessage($chatId ,$text ,$keyboard = [] ,$image = '')
- {
- SendTelegramMessageJob::dispatch($chatId ,$text ,$keyboard ,$image);
- }
- /**
- * @description: 弹窗提示
- * @param {*} $memberId
- * @param {*} $address
- * @return {*}
- */
- public static function alertNotice($callbackId ,$text)
- {
- self::telegram()->answerCallbackQuery([
- 'callback_query_id' => $callbackId,
- 'text' => $text,
- 'show_alert' => true // 显示为弹窗
- ]);
- }
- public static function log($message, $context = [])
- {
- Log::error($message, $context);
- }
- /**
- * @description: 获取操作按钮
- * @return {*}
- */
- public static function getOperateButton()
- {
- $replyInfo = KeyboardService::findOne(['button' => '投注菜单']);
- if($replyInfo && $replyInfo->buttons){
- $buttons = json_decode($replyInfo->buttons, true);
- foreach ($buttons as $row) {
- $inlineButton[] = [];
- foreach ($row as $button) {
- $btn = ['text' => $button['text']];
- if(strpos($button['url'], 'http') === 0){
- $btn['url'] = $button['url'];
- }else{
- $btn['callback_data'] = $button['url'];
- }
- $inlineButton[count($inlineButton) - 1][] = $btn;
- // if (isset($button['text'])) {
- // $btn = ['text' => $button['text']];
- // if (isset($button['callback_data'])) {
- // $btn['callback_data'] = $button['callback_data'];
- // }
- // if (isset($button['url'])) {
- // $btn['url'] = $button['url'];
- // }
- // $inlineButton[count($inlineButton) - 1][] = $btn;
- // }
- }
- }
- $inlineButton = array_values($inlineButton);
- return $inlineButton;
- }
- // $username = config('services.telegram.username');
- // $serviceAccount = Config::where('field', 'service_account')->first()->val??'';
- // $officialChannel = Config::where('field', 'official_channel')->first()->val??'';
- $inlineButton = [];
- // $inlineButton[] = [
- // ['text' => "查看余额", 'callback_data' => 'balanceAlert'],
- // ['text' => "✅唯一财务", 'url' => "https://t.me/{$serviceAccount}"]
- // ];
- // $inlineButton[] = [
- // ['text' => "近期注单", 'callback_data' => 'betsAlert'],
- // ['text' => "今日流水", 'callback_data' => 'todayFlowAlert']
- // ];
- // $inlineButton[] = [
- // ['text' => "私聊下注", 'url' => "https://t.me/{$username}"]
- // ];
- // $inlineButton[] = [
- // ['text' => "官方频道", 'url' => "https://t.me/{$officialChannel}"]
- // ];
- return $inlineButton;
- }
- // 获取字符串最后几个字符
- public static function getLastChar($str,$num = 1)
- {
- $length = mb_strlen($str, 'UTF-8');
- $lastChar = mb_substr($str, $length - 1, $num, 'UTF-8');
- return $lastChar;
- }
- public static function generateRandomString($length = 8) {
- $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- $randomString = '';
- for ($i = 0; $i < $length; $i++) {
- $randomString .= $characters[rand(0, strlen($characters) - 1)];
- }
- return $randomString;
- }
- public static function generateRandomNumber($length = 8) {
- $characters = '0123456789';
- $randomString = '';
- for ($i = 0; $i < $length; $i++) {
- $randomString .= rand(1, 9);
- }
- return $randomString;
- }
- public static function hideMiddleDigits($number, $hideCount = 4) {
- $length = strlen($number);
- if ($length <= $hideCount) {
- // 数字太短,全部隐藏
- return str_repeat("*", $length);
- }
- // 计算中间开始隐藏的位置
- $startLen = floor(($length - $hideCount) / 2);
- $endLen = $length - $hideCount - $startLen;
- $start = substr($number, 0, $startLen);
- $end = substr($number, -$endLen);
- return $start . str_repeat("*", $hideCount) . $end;
- }
- // 生成订单号
- public static function createOrderNo($prefix = 'pc28_',$memberId = null)
- {
- // 处理会员ID,获取后四位
- if ($memberId) {
- $memberSuffix = str_pad(substr($memberId, -4), 4, '0', STR_PAD_LEFT);
- } else {
- $memberSuffix = '0000'; // 默认值
- }
- // 时间部分
- $timePart = date('YmdHis');
- // 随机部分增加唯一性
- $randomPart = mt_rand(1000, 9999);
- return $prefix . $timePart . $randomPart . $memberSuffix;
- }
- /**
- * @description: 生成支付二维码
- * @param {*} $address 支付地址
- * @return {*}
- */
- public static function createPaymentQrCode($address = '')
- {
- // $content = $address;
- $content = '';
- $qrSize = 300;
- $font = 4;
- $textHeight = 20;
- $padding = 10;
- // 生成二维码图像对象
- $result = Builder::create()
- ->writer(new PngWriter())
- ->data($address)
- ->size($qrSize)
- ->margin(0)
- ->build();
- $qrImage = imagecreatefromstring($result->getString());
- // 创建画布(加上下方文字区和边距)
- $canvasWidth = $qrSize + $padding * 2;
- $canvasHeight = $qrSize + $textHeight + $padding * 2;
- $image = imagecreatetruecolor($canvasWidth, $canvasHeight);
- // 背景白色
- $white = imagecolorallocate($image, 255, 255, 255);
- imagefill($image, 0, 0, $white);
- // 黑色字体
- $black = imagecolorallocate($image, 0, 0, 0);
- // 合并二维码图像
- imagecopy($image, $qrImage, $padding, $padding, 0, 0, $qrSize, $qrSize);
- // 写文字
- $textWidth = imagefontwidth($font) * strlen($content);
- $x = ($canvasWidth - $textWidth) / 2;
- $y = $qrSize + $padding + 5;
- imagestring($image, $font, $x, $y, $content, $black);
- $address_name = self::generateRandomString(20).time();
- // 生成文件名
- $filename = $address_name. '.png';
- $relativePath = 'payment/' . $filename;
- $storagePath = storage_path('app/public/' . $relativePath);
- // 确保目录存在
- @mkdir(dirname($storagePath), 0777, true);
- // 保存图片到文件
- imagepng($image, $storagePath);
- // 清理
- imagedestroy($qrImage);
- imagedestroy($image);
- // 返回 public 存储路径(可用于 URL)
- return 'storage/'.$relativePath; // 或返回 Storage::url($relativePath);
- }
- }
|