Laravel项目中SMPP协议认证失败问题求助
Laravel中SMPP协议认证失败问题排查与解决
我在Laravel项目中使用SMPP协议发送短信,已成功与服务器建立Socket连接,但使用正确信息认证时失败。服务器返回过两种错误:
- 一种是:
Authentication failed. Server response: � - 另一种是:
Server response:\x00\x00\x00\x10€\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00"
我使用php-smpp库,以下是负责创建Socket和服务器认证的控制器代码:
<?php namespace App\Http\Controllers; use SMPP; use Exception; use GsmEncoder; use SmppClient; use SmppAddress; use SocketTransport; use Illuminate\Support\Facades\Log; class apiSmsSmppController extends Controller { function sendSmsSmpp($message, $to) { $host = 'xxx.xxx.xx.xx'; $port = xxxx; $from = "Net4Work"; $systemId = "xxxxxx"; $password = "xxxxxx"; // Création de la socket $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($socket === false) { // Gestion de l'erreur $error = socket_strerror(socket_last_error()); die("Failed to create socket: $error"); } // Connexion à la socket du serveur $result = socket_connect($socket, $host, $port); if ($result === false) { // Gestion de l'erreur $error = socket_strerror(socket_last_error($socket)); die("Failed to connect to $host:$port: $error"); } // La connexion a réussi //echo "Connected to $host:$port"; // Envoi des informations d'authentification au serveur $authData = pack('a'.strlen($systemId).'ca'.strlen($password).'ca1', $systemId, 0x02, $password, 0x00, 0x00); $result = socket_write($socket, $authData, strlen($authData)); if ($result === false) { // Gestion de l'erreur $error = socket_strerror(socket_last_error($socket)); die("Failed to send authentication data: $error"); } // Réception de la réponse du serveur $response = socket_read($socket, 1024); if ($response === false) { // Gestion de l'erreur $error = socket_strerror(socket_last_error($socket)); die("Failed to receive server response: $error"); } // Vérification de la réponse du serveur pour confirmer l'authentification $commandStatus = unpack('N', substr($response, 4, 4))[1]; if ($commandStatus !== 0x00000000) { // L'authentification a échoué die("Authentication failed. Server response: $response"); } // L'authentification a réussi dd("Authentication successful. Server response: $response"); } }
问题根源
你手动封装认证数据包的方式不符合SMPP协议规范,bind请求有严格的结构定义,手动pack的格式错误导致服务器无法解析认证信息。另外,你已经引入了php-smpp库的封装类,却手动操作Socket,完全浪费了库的封装能力,也容易出错。
修正后的代码
直接使用php-smpp库提供的标准方法建立连接和认证:
<?php namespace App\Http\Controllers; use Exception; use SmppClient; use SmppAddress; use SocketTransport; use Illuminate\Support\Facades\Log; class apiSmsSmppController extends Controller { function sendSmsSmpp($message, $to) { $host = 'xxx.xxx.xx.xx'; $port = xxxx; $from = "Net4Work"; $systemId = "xxxxxx"; $password = "xxxxxx"; // 使用库的SocketTransport创建连接 $transport = new SocketTransport([$host], $port); $transport->setRecvTimeout(10000); // 设置超时时间(毫秒) $transport->open(); // 初始化SmppClient $smpp = new SmppClient($transport); $smpp->setDebug(true); // 开启调试,便于排查问题 try { // 执行认证(根据服务器要求选择bind类型:transmitter/receiver/transceiver) $smpp->bindTransmitter($systemId, $password); // 认证成功后发送短信 $fromAddress = new SmppAddress($from, SMPP::TON_ALPHANUMERIC); $toAddress = new SmppAddress($to, SMPP::TON_INTERNATIONAL, SMPP::NPI_E164); $smpp->sendSMS($fromAddress, $toAddress, $message); // 关闭连接 $smpp->close(); dd("认证成功,短信发送完成"); } catch (Exception $e) { Log::error("SMPP操作失败: " . $e->getMessage()); dd("认证或发送失败: " . $e->getMessage()); } } }
额外排查点
- 确认SMPP版本:部分服务器要求特定版本(如v3.4),可在bind时指定:
$smpp->bindTransmitter($systemId, $password, null, null, null, SMPP::VERSION_3_4); - 编码检查:确保
systemId和password的编码与服务器要求一致(通常为ASCII) - 调试日志:开启
setDebug(true)后会输出详细交互日志,可查看原始数据包定位问题 - 绑定类型与端口:确认服务器端口正确,以及应使用的绑定类型(transmitter/receiver/transceiver)
内容的提问来源于stack exchange,提问作者le prince
相关产品推荐
相关产品推荐

