<?php
/* SMS-Bot Whmcs Module
*/
use WHMCS\Database\Capsule;
require_once ROOTDIR . '/includes/modulefunctions.php';
function smsman_MetaData()
{
return [
'DisplayName' => 'sms-man',
'APIVersion' => '1.0'
];
}
function smsman_ConfigOptions()
{
return [
'country_id' => [
'Type' => 'text',
'Description' => '国家ID(如果为0则调用可配置选项)',
'Size' => '5',
'Default' => '0'
],
'application_id' => [
'Type' => 'text',
'Size' => '5',
'Description' => '应用ID(如果为0则调用可配置选项)',
'Default' => '0'
],
];
}
function smsman_CreateAccount($params)
{
$token = $params["serveraccesshash"];
if ($params['configoption1'] != '0' && $params['configoption2'] != '0') {
$country_id = $params['configoption1'];
$application_id = $params['configoption2'];
} else {
$countryRaw = $params['configoptions']['国家'];
preg_match('/\[(\d+)\]/', $countryRaw, $matchCountry);
$country_id = $matchCountry[1];
$applicationRaw = $params['configoptions']['应用'];
preg_match('/\[(\d+)\]/', $applicationRaw, $matchApplication);
$application_id = $matchApplication[1];
}
$url = "https://api.sms-man.com/control/get-number?token={$token}&country_id={$country_id}&application_id={$application_id}";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
if (curl_errno($curl)) {
return 'cURL Error: ' . curl_error($curl);
}
// 检查 HTTP 状态码
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($httpCode != 200) {
return 'HTTP Error: ' . $httpCode;
}
curl_close($curl);
$data = json_decode($response, true);
logModuleCall('sms-man', 'CreateAccount', $url, $response, $data);
if (!is_array($data)) {
return 'Invalid API response';
}
if (isset($data['error_code'])) {
return 'API Error: ' . $data['error_code'] . ' - ' . json_encode($data['error_msg']);
}
if (!isset($data['number'])) {
return 'API Error: Missing number field - ' . json_encode($data);
}
$request_id = $data['request_id'];
$number = $data['number'];
/* 保存手机号 */
Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([
'username' => $number,
'domain' => $request_id, // 使用 domain 字段保存 request_id(WHMCS 默认不使用该字段)
]);
// 可选:记录日志
logModuleCall('sms-man', 'SetUsername', $params['serviceid'], $number, $result);
return "success";
}
function smsman_ClientArea($params)
{
// 获取验证码的后端处理逻辑
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['get_code'])) {
$request_id = $params['domain']; // 之前保存的 request_id
$token = $params['serveraccesshash'];
$getSmsUrl = "https://api.sms-man.com/control/get-sms?token={$token}&request_id={$request_id}";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $getSmsUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$smsData = json_decode($response, true);
if (isset($smsData['sms_code'])) {
$smsCode = $smsData['sms_code'];
// 保存新的手机号和 request_id
Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([
'domain' => 'Received'.$smsCode, // 使用 domain 字段保存验证码
]);
$params["domain"] = 'Received'.$smsCode;
$isCodeReceived = true;
} elseif (isset($smsData['error_msg'])) {
$smsCode = "错误: " . $smsData['error_msg'];
} else {
$smsCode = "未知错误,请稍后重试。";
}
}
// 更换手机号的后端处理逻辑
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['change_number'])) {
$request_id = $params['domain']; // 之前保存的 request_id
$token = $params['serveraccesshash'];
// 将状态改为 reject
$setStatusUrl = "https://api.sms-man.com/control/set-status?token={$token}&request_id={$request_id}&status=reject";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $setStatusUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$statusData = json_decode($response, true);
if (isset($statusData['success']) && $statusData['success']) {
// 成功将状态改为 reject 后,获取新的手机号
if ($params['configoption1'] != '0' && $params['configoption2'] != '0') {
$country_id = $params['configoption1'];
$application_id = $params['configoption2'];
} else {
$countryRaw = $params['configoptions']['国家'];
preg_match('/\[(\d+)\]/', $countryRaw, $matchCountry);
$country_id = $matchCountry[1];
$applicationRaw = $params['configoptions']['应用'];
preg_match('/\[(\d+)\]/', $applicationRaw, $matchApplication);
$application_id = $matchApplication[1];
}
$getNewNumberUrl = "https://api.sms-man.com/control/get-number?token={$token}&country_id={$country_id}&application_id={$application_id}";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $getNewNumberUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response, true);
if (isset($data['request_id']) && isset($data['number'])) {
$newRequestId = $data['request_id'];
$newNumber = $data['number'];
// 保存新的手机号和 request_id
Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([
'username' => $newNumber,
'domain' => $newRequestId, // 使用 domain 字段保存新的 request_id
]);
// 可选:记录日志
logModuleCall('sms-man', 'ChangePhoneNumber', $params['serviceid'], $newNumber, $data);
$smsCode = "手机号已更换!" ;
$params["username"] = $newNumber; // 更新当前手机号
} else {
$smsCode = "获取新的手机号失败,请稍后重试。";
}
} else {
$smsCode = "更换手机号失败: " . json_encode($statusData);
}
}
// 更换手机号的后端处理逻辑
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['reget_number'])) {
$request_id = $params['domain']; // 之前保存的 request_id
$token = $params['serveraccesshash'];
// 将状态改为 reject
$setStatusUrl = "https://api.sms-man.com/control/set-status?token={$token}&request_id={$request_id}&status=reject";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $setStatusUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$statusData = json_decode($response, true);
if (!isset($statusData['success']) && !$statusData['success']) {
// 只有错误reject ,才获取新的手机号
if ($params['configoption1'] != '0' && $params['configoption2'] != '0') {
$country_id = $params['configoption1'];
$application_id = $params['configoption2'];
} else {
$countryRaw = $params['configoptions']['国家'];
preg_match('/\[(\d+)\]/', $countryRaw, $matchCountry);
$country_id = $matchCountry[1];
$applicationRaw = $params['configoptions']['应用'];
preg_match('/\[(\d+)\]/', $applicationRaw, $matchApplication);
$application_id = $matchApplication[1];
}
$getNewNumberUrl = "https://api.sms-man.com/control/get-number?token={$token}&country_id={$country_id}&application_id={$application_id}";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $getNewNumberUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response, true);
if (isset($data['request_id']) && isset($data['number'])) {
$newRequestId = $data['request_id'];
$newNumber = $data['number'];
// 保存新的手机号和 request_id
Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([
'username' => $newNumber,
'domain' => $newRequestId, // 使用 domain 字段保存新的 request_id
]);
// 可选:记录日志
logModuleCall('sms-man', 'ChangePhoneNumber', $params['serviceid'], $newNumber, $data);
$smsCode = "手机号已更换!" ;
$params["username"] = $newNumber; // 更新当前手机号
} else {
$smsCode = "获取新的手机号失败,请稍后重试。";
}
} else {
$smsCode = "更换手机号失败: " . json_encode($statusData);
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['cancel_request'])) {
$request_id = $params['domain']; // 之前保存的 request_id
$token = $params['serveraccesshash'];
// 将状态改为 reject 来取消请求
$setStatusUrl = "https://api.sms-man.com/control/set-status?token={$token}&request_id={$request_id}&status=reject";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $setStatusUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($curl);
curl_close($curl);
$statusData = json_decode($response, true);
if (isset($statusData['success']) && $statusData['success']) {
// 如果取消请求成功,终止服务
// 设置订单为 Completed
$order = Capsule::table('tblorders')
->join('tblhosting', 'tblhosting.orderid', '=', 'tblorders.id')
->where('tblhosting.id', $params['serviceid'])
->select('tblorders.id')
->first();
if ($order) {
Capsule::table('tblorders')
->where('id', $order->id)
->update(['status' => 'Completed']);
}
} else {
$smsCode = "完成请求失败: " . json_encode($statusData);
}
}
$html = '<div class="sms-client-area">
<div class="row">
<!-- 账户概览卡片 -->
<div class="col-md-6 col-sm-12">
<div class="card">
<div class="card-header">
<h3><i class="fas fa-user-circle"></i> 账户概览</h3>
</div>
<div class="card-body">
<div class="account-item">
<span class="item-label">国家</span>
<span class="item-value">' . htmlspecialchars($params["configoptions"]["国家"]) . '</span>
</div>
<div class="account-item">
<span class="item-label">应用</span>
<span class="item-value">' . htmlspecialchars($params["configoptions"]["应用"]) . '</span>
</div>
<div class="account-item">
<span class="item-label">手机号码</span>
<input readonly="readonly" value="+' . htmlspecialchars($params["username"]) . '">
</div>
<div class="account-item">
<span class="item-label">教程</span>
<span class="item-value">
<a href="https://blog.lhl.one/artical/460.html#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">点我传送</a>
</span>
</div>
<div class="account-item">
<span class="item-label">提示</span>
<span class="item-value" style="color:red;">
请在15分钟内发送验证码<br/>发送验证后5分钟内即可收到<br/>
</span>
</div>
</div>
</div>
</div>
<!-- 快捷操作卡片 -->
<div class="col-md-6 col-sm-12">
<div class="card">
<div class="card-header">
<h3><i class="fas fa-tools"></i> 功能操作</h3>
</div>
';
if (strpos($params["domain"], 'Received') === 0 || isset($isCodeReceived)) {
// 去掉开头的 "Received",提取验证码
$smsCode = substr($params["domain"], strlen('Received'));
$html .= '<div class="card-body">
<div class="account-item">
<span class="item-label">验证码</span>
<input readonly="readonly" style="color:darkgray;" value="' . htmlspecialchars($smsCode) . '">
</div>';
}else{
$html .= '<div class="card-body">
<div class="account-item">
<span class="item-label">验证码</span>
<input readonly="readonly" style="color:darkgray;" value="' . htmlspecialchars($smsCode ?? '') . '">
</div>
<div class="action-buttons">
<form method="post">
<input type="hidden" name="get_code" value="1">
<button type="submit" class="btn btn-primary btn-block">
<i class="fas fa-sign-in-alt"></i> 获取验证码
</button>
</form>
';
}
if($smsData['error_msg'] == 'Current request already closed.'){
$html .='<form method="post">
<input type="hidden" name="reget_number" value="1">
<button type="submit" class="btn btn-info btn-block">
<i class="fas fa-phone-alt"></i> 已超时,重新获取手机号
</button>
</form> ';
}else{
$html .='<form method="post">
<input type="hidden" name="change_number" value="1">
<button type="submit" class="btn btn-warning btn-block">
<i class="fas fa-phone-alt"></i> 更换手机号
</button>
</form> ';
}
$html .= '</div>
</div>
</div>
</div>
</div>
<style>
.section {
display: none;
}
.sms-client-area {
font-family: var(--body-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);
margin-bottom: 30px;
}
.sms-client-area .row {
margin-bottom: 20px;
}
.sms-client-area .card {
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
margin-bottom: 20px;
border: 1px solid rgba(0,0,0,0.125);
}
.sms-client-area .card-header {
background-color: #f8f9fa;
padding: 12px 15px;
border-bottom: 1px solid rgba(0,0,0,0.125);
}
.sms-client-area .card-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #333;
}
.sms-client-area .card-header h3 i {
margin-right: 8px;
color: #0c73b8;
}
.sms-client-area .card-body {
padding: 15px;
}
.sms-client-area .account-item {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #f0f0f0;
}
.sms-client-area .account-item:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
.sms-client-area .item-label {
color: #6c757d;
font-weight: 500;
}
.sms-client-area .item-value {
font-weight: 500;
text-align: right;
}
.sms-client-area .status {
display: inline-block;
padding: 3px 8px;
border-radius: 3px;
font-size: 12px;
font-weight: 600;
}
.sms-client-area .status-active {
background-color: #e3f7e8;
color: #28a745;
}
.sms-client-area .status-suspended {
background-color: #fbecec;
color: #dc3545;
}
.sms-client-area .ssl-badge {
display: inline-flex;
align-items: center;
padding: 3px 6px;
border-radius: 3px;
font-size: 12px;
}
.sms-client-area .ssl-active {
background-color: #e3f7e8;
color: #28a745;
}
.sms-client-area .ssl-inactive {
background-color: #f0f0f0;
color: #6c757d;
}
.sms-client-area .ssl-badge i {
margin-right: 4px;
}
.sms-client-area .action-buttons {
display: flex;
flex-direction: column;
gap: 10px;
}
.sms-client-area .btn {
display: inline-flex;
align-items: center;
justify-content: center;
font-weight: 500;
padding: 8px 12px;
transition: all 0.2s;
}
.sms-client-area .btn i {
margin-right: 8px;
}
.sms-client-area .usage-item {
margin-bottom: 15px;
}
.sms-client-area .usage-label {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-weight: 500;
}
.sms-client-area .usage-text {
color: #6c757d;
font-size: 13px;
}
.sms-client-area .progress {
height: 8px;
background-color: #f0f0f0;
border-radius: 10px;
overflow: hidden;
}
.sms-client-area .table {
margin-bottom: 0;
}
.sms-client-area .table td {
vertical-align: middle;
}
/* 响应式调整 */
@media (max-width: 767.98px) {
.sms-client-area .btn-group-sm {
display: flex;
flex-direction: column;
gap: 5px;
}
.sms-client-area .card-body.p-0 {
padding: 0 !important;
}
}
</style>';
return $html;
}