You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SMS API投递报告(DLR)数据未在URL展示及存储问题求助

无法接收SMS API投递报告(DLR)数据的排查问题

我正在排查无法接收SMS API投递报告(DLR)数据的问题。我编写了代码用于将DLR数据存储至数据库,并创建了视图供用户查看错误信息,但遇到以下问题:

  • 错误仅在日志中显示,DLR URL无数据返回
  • 访问命名路由sms.delivery.store对应的页面时显示空白,数据既未存入数据库也未在视图中展示

以下是相关代码:

DeliverReport 控制器

<?php

namespace App\Http\Controllers;

use App\DeliveryReport;
use Illuminate\Http\Request;

class DeliveryReportController extends Controller
{
    public function index() {
        $delivery_reports = DeliveryReport::all();
        return view('reports.index', compact('delivery_reports'));
    }

    public function store(Request $request){
        $data = $request->all();
        try {
            $report = [];
            if(!empty($data['custom'])) {
                $report['contact_id'] = $data['contact_id'] ?? "";
                $report['msg'] = $data['msg'] ?? "";
                $report['contact_no'] = $data['contact_no'] ?? "";
            }
            $report['message_id'] = $data['msgId'];
            $report['status'] = $data['event'];
            $report['message'] = $data['errorMessage'] ?? "";
            $report['error_code'] = $data['errorCode'] ?? "";
            DeliveryReport::create($report);
        } catch (\Exception $e) {
            info('something went wrong in webhook');
            info($data);
            info($e->getMessage());
        }
    }
}

CommonTrait 代码

<?php
namespace App\Http\Traits;

use App\SmsHistory;
use SMSGate\Client;
use SMSGate\SMSRequest;
use Carbon\Carbon;
use DB;

trait CommonServices {
    public function sms_gate_request($number, $msg, $contact_id){
        $gate = new Client(env('SMS_GATE_SUBMIT_URL'));
        $sms = new SMSRequest;
        $sms->setType(Client::TYPE_TEXT)
            ->setAuthUsername(env('SMS_GATE_USERNAME'))
            ->setAuthPassword(env('SMS_GATE_PASSWORD'))
            ->setSender(env('SMS_GATE_SENDER'))
            ->setReceiver($number)
            ->setText($msg)
            ->setCustom(['contact_id' => $contact_id, 'msg' => $msg, 'contact_number' => $number])
            ->setDlrUrl(route('sms.delivery.store'))
            ->setDlrMask(Client::DLR_MASK_STANDARD);
        try {
            $gate->send($sms);
            SmsHistory::create([
                'phone_number' => $number,
                'message' => $msg,
                'contact_id' => $contact_id
            ]);
        } catch (\Exception $exc) {
            info("Error sending SMS with code: " . $exc->getCode() . " and message: " . $exc->getMessage());
            return false;
        }

        return true;
    }


    public function checkMessageCooldown($phone_number, $message) {
        $days = env('DUPLICATE_SMS_COOLDOWN_DAYS');
        $last_sent = Carbon::now()->subDays($days)->toDateTimeString();

        $sent_before = DB::table('sms_histories')
            ->where('phone_number', $phone_number)
            ->where('message', $message)
            ->where('created_at', '>', $last_sent)
            ->exists();

        
        return $sent_before;
    }
}

视图代码

@extends('layouts.app')

@section('content')
    <head>
        <meta name="_token" content="{{ csrf_token() }}">
        <title>Kontaktliste</title>
        <link rel="stylesheet" href="//cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js" ></script>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <div class="row">
                        <div class="col-md-6">
                            <h3>Delivery Reports</h3>
                        </div>
                    </div>
                </div>

                <div class="panel-body">
                    <table id="reports-table" class="table table-bordered table-hover">
                        <thead>
                        <tr>
                            <th>Message ID</th>
                            <th>Contact</th>
                            <th>Message</th>
                            <th>Status</th>
                            <th>Reason (if any error)</th>
                        </tr>
                        </thead>
                        <tbody>
                        @foreach($delivery_reports as $report)
                            <tr>
                                <td>{{ $report->message_id }}</td>
                                <td>{{ $report->contact_id }}</td>
                                <td>{{ $report->message }}</td>
                                <td>{{ $report->status }}</td>
                                <td>{{ $report->error_message }}</td>
                            </tr>
                        @endforeach
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
    <script src="//cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js" defer></script>
    <script type="text/javascript">
        $(function () {
            $('#reports-table').DataTable();
        });
    </script>
    <script type="text/javascript">
        $.ajaxSetup({ headers: { 'csrftoken' : '{{ csrf_token() }}' } });
    </script>
    </body>

@endsection

路由配置

Route::get('/delivery_reports/store', 'DeliveryReportController@store')->name('sms.delivery.store');

问题排查与修复建议

  • 修正路由请求方法:SMS API的DLR推送通常使用POST请求,当前配置的GET路由无法正确接收推送数据。修改路由为:
    Route::post('/delivery_reports/store', 'DeliveryReportController@store')->name('sms.delivery.store');
    
    同时,在app/Http/Middleware/VerifyCsrfToken.php的$except数组中添加该路由,关闭CSRF验证:
    protected $except = [
        '/delivery_reports/store',
    ];
    
  • 添加响应返回:当前store方法无任何响应返回,第三方API可能因接收不到确认响应而停止推送或重复请求。在方法末尾添加:
    return response()->json(['status' => 'success'], 200);
    
  • 修正字段名不匹配:Trait中setCustom传入的是contact_number,但控制器中使用contact_no接收,导致该字段数据为空。修改控制器对应代码:
    $report['contact_no'] = $data['contact_number'] ?? "";
    
  • 修正视图字段错误:视图中使用$report->error_message,但控制器存储的是message字段,修改视图对应代码:
    <td>{{ $report->message }}</td>
    
  • 配置模型批量赋值:确保DeliveryReport模型的$fillable属性包含所有需要存入的字段:
    protected $fillable = ['contact_id', 'msg', 'contact_no', 'message_id', 'status', 'message', 'error_code'];
    

内容的提问来源于stack exchange,提问作者Lordp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 04:53:07