Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc6e3f9b

Browse files
feature#61778 [Notifier] Add support for building SmsEvent by dlr_code and RemoteEvent for other LOX24 webhook event types (alebedev80)
This PR was squashed before being merged into the 7.4 branch.Discussion----------[Notifier] Add support for building SmsEvent by dlr_code and RemoteEvent for other LOX24 webhook event types| Q | A| ------------- | ---| Branch? | 7.4| Bug fix? | yes| New feature? | yes| Deprecations? | no| Issues | Fix #... (if applicable)| License | MIT## SummaryThis PR enhances the LOX24RequestParser to provide robust SMS delivery webhook parsing with improved validation, dual status code support (DLR codes and status codes), and better error handling for SMS delivery events.## What it does**Before**: The parser had basic SMS delivery webhook handling with limited validation and error handling.**After**: The parser provides enhanced SMS delivery webhook processing:- `sms.delivery` & `sms.delivery.dryrun` - SMS delivery receipts with improved validation- Dual status code support: DLR codes (0-16) and transmission status codes (0, 100, etc.)- Better payload validation with detailed error messages- Non-delivery events are handled as generic RemoteEvent objects## Example Usage### Enhanced SMS Delivery Processing:```php// ✅ SMS delivery with status code$deliveryPayload = [ 'id' => 'webhook-123', 'name' => 'sms.delivery', 'data' => ['id' => '123', 'status_code' => 100]];$deliveryEvent = $parser->parse($deliveryRequest, $secret);// Returns: SmsEvent with DELIVERED status// ✅ SMS delivery with DLR code (takes priority over status_code)$dlrPayload = [ 'id' => 'webhook-456', 'name' => 'sms.delivery', 'data' => ['id' => '456', 'dlr_code' => 1, 'status_code' => 500]];$dlrEvent = $parser->parse($dlrRequest, $secret);// Returns: SmsEvent with DELIVERED status (DLR code 1 overrides status 500)// ✅ Pending delivery (returns null)$pendingPayload = [ 'id' => 'webhook-789', 'name' => 'sms.delivery', 'data' => ['id' => '789', 'dlr_code' => 0]];$pendingEvent = $parser->parse($pendingRequest, $secret);// Returns: null (pending delivery)// ✅ Non-delivery events handled as RemoteEvent$otherPayload = [ 'id' => 'webhook-000', 'name' => 'custom.event', 'data' => ['some' => 'data']];$otherEvent = $parser->parse($otherRequest, $secret);// Returns: RemoteEvent with 'custom.event' name```## Key Changes### 1. **Improved Payload Validation**- Enhanced validation for required webhook fields: `id`, `name`, `data`- Better error messages with specific missing field details- Proper array validation for data payload### 2. **Smart Return Types**- SMS delivery events (`sms.delivery`, `sms.delivery.dryrun`) return `SmsEvent` objects with DELIVERED/FAILED status- Non-delivery events return `RemoteEvent` objects for generic webhook handling- Maintains `null` return for pending deliveries (status_code=0 or dlr_code=0/2/4)### 3. **Enhanced SMS Delivery Validation**```php// SMS delivery events validate required fieldscase 'sms.delivery': // Requires: payload.id, data.id, and either data.status_code OR data.dlr_code // Supports both LOX24 status codes and DLR codes // DLR codes take priority when both are present```### 4. **Dual Status Code Support**- **DLR Codes**: Priority support for LOX24's Delivery Report codes (0-16) with proper pending state handling- **Status Codes**: Fallback to transmission status codes (0, 100, 208, 400, etc.) when DLR unavailable- **Smart Mapping**: DLR codes 1→DELIVERED, 8/16→FAILED, 0/2/4→null (pending)### 4. **Comprehensive Testing**- Tests for SMS delivery events with success/failure scenarios- DLR code and status code validation scenarios- Payload validation tests for required fields- Backward compatibility verification for existing delivery events- Type safety assertions (`SmsEvent` vs `RemoteEvent`)## Backward Compatibility✅ **Fully backward compatible** - existing consumers continue working without changes:- Same `sms.delivery` event handling behavior- Same status code and DLR code mapping logic- Same null return for pending messages (status_code=0, dlr_code=0/2/4)- Same SmsEvent object structure and methods- Enhanced support for both LOX24 status codes and DLR codes## Consumer Integration Example```php#[AsRemoteEventConsumer('lox24_notifier')]class LOX24WebhookConsumer implements ConsumerInterface{ public function consume(RemoteEvent $event): void { if ($event instanceof SmsEvent) { match($event->getName()) { SmsEvent::DELIVERED => $this->handleDelivered($event), SmsEvent::FAILED => $this->handleFailed($event), }; } else { // Handle other webhook events as generic RemoteEvent $this->handleGenericWebhook($event); } }}```## Breaking Changes⚠️ **Minor breaking changes** (unlikely to affect most users):- Parser return type signature changed from `?SmsEvent` to `SmsEvent|RemoteEvent|null`- Exception messages updated with more detailed validation errors- Requires webhook payload to include `id` field (LOX24 standard)- Non-delivery events now return `RemoteEvent` instead of being rejected## Technical Implementation- **Improved Validation**: Enhanced payload validation with detailed error messages for missing fields- **Factory Methods**: Implemented specialized methods (`createDeliveryEvent`, `createRemoteEvent`, etc.)- **Dual Code Support**: Enhanced delivery event parsing to handle both LOX24 status codes and DLR codes- **Smart Precedence**: DLR codes take priority over status codes when both are present- **Error Handling**: Enhanced error messages with specific validation details- **Null Handling**: Proper handling of pending states (DLR codes 0/2/4, status code 0)## Testing- ✅ All existing tests pass (backward compatibility)- ✅ Added comprehensive test coverage for SMS delivery scenarios- ✅ Payload validation and error handling tests- ✅ DLR code and status code priority testingThis enhancement improves LOX24 SMS delivery webhook processing with better validation, dual status code support, and robust error handling while maintaining complete backward compatibility.Commits-------d9eaa27 [Notifier] Add support for building SmsEvent by dlr_code and RemoteEvent for other LOX24 webhook event types
2 parentsb1ef2a4 +d9eaa27 commitc6e3f9b

File tree

3 files changed

+312
-34
lines changed

3 files changed

+312
-34
lines changed
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
CHANGELOG
22
=========
33

4+
7.4
5+
---
6+
7+
* Add support for building SmsEvent by dlr_code and RemoteEvent for other LOX24 webhook event types
8+
49
7.1
510
---
611

7-
* Add the bridge
12+
* Add the bridge

‎src/Symfony/Component/Notifier/Bridge/Lox24/Tests/Webhook/Lox24RequestParserTest.php‎

Lines changed: 228 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
useSymfony\Component\HttpFoundation\Request;
1616
useSymfony\Component\Notifier\Bridge\Lox24\Webhook\Lox24RequestParser;
1717
useSymfony\Component\RemoteEvent\Event\Sms\SmsEvent;
18+
useSymfony\Component\RemoteEvent\RemoteEvent;
1819
useSymfony\Component\Webhook\Exception\RejectWebhookException;
1920

2021
/**
@@ -29,80 +30,284 @@ protected function setUp(): void
2930
$this->parser =newLox24RequestParser();
3031
}
3132

32-
publicfunctiontestInvalidNotificationName()
33+
publicfunctiontestMissingBasicPayloadStructure()
3334
{
3435
$this->expectException(RejectWebhookException::class);
35-
$this->expectExceptionMessage('Notification name is not\'sms.delivery\'');
36-
$request =$this->getRequest(['name' =>'invalid_name','data' => ['status_code' =>100]]);
36+
$this->expectExceptionMessage('The required fields "id", "data" are missing from the payload.');
3737

38+
$request =$this->getRequest(['name' =>'sms.delivery']);
3839
$this->parser->parse($request,'');
3940
}
4041

41-
publicfunctiontestMissingMsgId()
42+
publicfunctiontestSmsDeliveryMissingMsgId()
4243
{
4344
$this->expectException(RejectWebhookException::class);
44-
$this->expectExceptionMessage('Payload is malformed.');
45-
$request =$this->getRequest(['name' =>'sms.delivery','data' => ['status_code' =>100]]);
45+
$this->expectExceptionMessage('The required field "id" is missing from the delivery event payload.');
4646

47+
$request =$this->getRequest([
48+
'id' =>'webhook-id',
49+
'name' =>'sms.delivery',
50+
'data' => ['status_code' =>100],
51+
]);
4752
$this->parser->parse($request,'');
4853
}
4954

50-
publicfunctiontestMissingMsgStatusCode()
55+
publicfunctiontestSmsDeliveryMissingBothCodes()
5156
{
5257
$this->expectException(RejectWebhookException::class);
53-
$this->expectExceptionMessage('Payload is malformed.');
54-
$request =$this->getRequest(['name' =>'sms.delivery','data' => ['id' =>'123']]);
58+
$this->expectExceptionMessage('The required field "status_code" or "dlr_code" is missing from the delivery event payload.');
5559

60+
$request =$this->getRequest([
61+
'id' =>'webhook-id',
62+
'name' =>'sms.delivery',
63+
'data' => ['id' =>'123'],
64+
]);
5665
$this->parser->parse($request,'');
5766
}
5867

59-
publicfunctiontestStatusCode100()
68+
publicfunctiontestSmsDeliveryStatusCode100()
6069
{
6170
$payload = [
71+
'id' =>'webhook-id',
6272
'name' =>'sms.delivery',
6373
'data' => [
6474
'id' =>'123',
6575
'status_code' =>100,
6676
],
6777
];
68-
$request =$this->getRequest($payload);
6978

79+
$request =$this->getRequest($payload);
7080
$event =$this->parser->parse($request,'');
81+
82+
$this->assertInstanceOf(SmsEvent::class,$event);
7183
$this->assertSame('123',$event->getId());
7284
$this->assertSame(SmsEvent::DELIVERED,$event->getName());
7385
$this->assertSame($payload,$event->getPayload());
7486
}
7587

76-
publicfunctiontestStatusCode0()
88+
publicfunctiontestSmsDeliveryStatusCode0()
7789
{
78-
$request =$this->getRequest(
79-
[
80-
'name' =>'sms.delivery',
81-
'data' => [
82-
'id' =>'123',
83-
'status_code' =>0,
84-
],
85-
]
86-
);
90+
$request =$this->getRequest([
91+
'id' =>'webhook-id',
92+
'name' =>'sms.delivery',
93+
'data' => [
94+
'id' =>'123',
95+
'status_code' =>0,
96+
],
97+
]);
8798

8899
$event =$this->parser->parse($request,'');
89100
$this->assertNull($event);
90101
}
91102

92-
publicfunctiontestStatusCodeUnknown()
103+
publicfunctiontestSmsDeliveryWithDlrCodeDelivered()
93104
{
94105
$payload = [
106+
'id' =>'webhook-id',
95107
'name' =>'sms.delivery',
96108
'data' => [
97109
'id' =>'123',
98-
'status_code' =>410,
110+
'dlr_code' =>1,
111+
'callback_data' =>'test-callback',
99112
],
100113
];
114+
101115
$request =$this->getRequest($payload);
116+
$event =$this->parser->parse($request,'');
102117

118+
$this->assertInstanceOf(SmsEvent::class,$event);
119+
$this->assertSame('123',$event->getId());
120+
$this->assertSame(SmsEvent::DELIVERED,$event->getName());
121+
$this->assertSame($payload,$event->getPayload());
122+
}
123+
124+
publicfunctiontestSmsDeliveryWithDlrCodeFailed()
125+
{
126+
$payload = [
127+
'id' =>'webhook-id',
128+
'name' =>'sms.delivery',
129+
'data' => [
130+
'id' =>'123',
131+
'dlr_code' =>16,
132+
],
133+
];
134+
135+
$request =$this->getRequest($payload);
103136
$event =$this->parser->parse($request,'');
137+
138+
$this->assertInstanceOf(SmsEvent::class,$event);
104139
$this->assertSame('123',$event->getId());
105140
$this->assertSame(SmsEvent::FAILED,$event->getName());
141+
}
142+
143+
publicfunctiontestSmsDeliveryWithDlrCodePending()
144+
{
145+
$request =$this->getRequest([
146+
'id' =>'webhook-id',
147+
'name' =>'sms.delivery',
148+
'data' => [
149+
'id' =>'123',
150+
'dlr_code' =>2,
151+
],
152+
]);
153+
154+
$event =$this->parser->parse($request,'');
155+
$this->assertNull($event);
156+
}
157+
158+
publicfunctiontestSmsDeliveryDryrun()
159+
{
160+
$payload = [
161+
'id' =>'webhook-id',
162+
'name' =>'sms.delivery.dryrun',
163+
'data' => [
164+
'id' =>'123',
165+
'status_code' =>100,
166+
],
167+
];
168+
169+
$request =$this->getRequest($payload);
170+
$event =$this->parser->parse($request,'');
171+
172+
$this->assertInstanceOf(SmsEvent::class,$event);
173+
$this->assertSame('123',$event->getId());
174+
$this->assertSame(SmsEvent::DELIVERED,$event->getName());
175+
}
176+
177+
publicfunctiontestMissingIdField()
178+
{
179+
$this->expectException(RejectWebhookException::class);
180+
$this->expectExceptionMessage('The required fields "id" are missing from the payload.');
181+
182+
$request =$this->getRequest([
183+
'name' =>'sms.delivery',
184+
'data' => ['id' =>'123'],
185+
]);
186+
$this->parser->parse($request,'');
187+
}
188+
189+
publicfunctiontestMissingNameField()
190+
{
191+
$this->expectException(RejectWebhookException::class);
192+
$this->expectExceptionMessage('The required fields "name" are missing from the payload.');
193+
194+
$request =$this->getRequest([
195+
'id' =>'webhook-id',
196+
'data' => ['id' =>'123'],
197+
]);
198+
$this->parser->parse($request,'');
199+
}
200+
201+
publicfunctiontestMissingDataField()
202+
{
203+
$this->expectException(RejectWebhookException::class);
204+
$this->expectExceptionMessage('The required fields "data" are missing from the payload.');
205+
206+
$request =$this->getRequest([
207+
'id' =>'webhook-id',
208+
'name' =>'sms.delivery',
209+
]);
210+
$this->parser->parse($request,'');
211+
}
212+
213+
publicfunctiontestInvalidDataFieldNotArray()
214+
{
215+
$this->expectException(RejectWebhookException::class);
216+
$this->expectExceptionMessage('The "data" field must be an array.');
217+
218+
$request =$this->getRequest([
219+
'id' =>'webhook-id',
220+
'name' =>'sms.delivery',
221+
'data' =>'invalid-data',
222+
]);
223+
$this->parser->parse($request,'');
224+
}
225+
226+
publicfunctiontestRemoteEventForUnknownEventType()
227+
{
228+
$payload = [
229+
'id' =>'webhook-id',
230+
'name' =>'custom.event',
231+
'data' => ['some' =>'data'],
232+
];
233+
234+
$request =$this->getRequest($payload);
235+
$event =$this->parser->parse($request,'');
236+
237+
$this->assertInstanceOf(RemoteEvent::class,$event);
238+
$this->assertSame('webhook-id',$event->getId());
239+
$this->assertSame('custom.event',$event->getName());
240+
$this->assertSame($payload,$event->getPayload());
241+
}
242+
243+
publicfunctiontestSmsDeliveryStatusCodeFailed()
244+
{
245+
$payload = [
246+
'id' =>'webhook-id',
247+
'name' =>'sms.delivery',
248+
'data' => [
249+
'id' =>'123',
250+
'status_code' =>500,
251+
],
252+
];
253+
254+
$request =$this->getRequest($payload);
255+
$event =$this->parser->parse($request,'');
256+
257+
$this->assertInstanceOf(SmsEvent::class,$event);
258+
$this->assertSame('123',$event->getId());
259+
$this->assertSame(SmsEvent::FAILED,$event->getName());
260+
$this->assertSame($payload,$event->getPayload());
261+
}
262+
263+
publicfunctiontestSmsDeliveryWithDlrCode0()
264+
{
265+
$request =$this->getRequest([
266+
'id' =>'webhook-id',
267+
'name' =>'sms.delivery',
268+
'data' => [
269+
'id' =>'123',
270+
'dlr_code' =>0,
271+
],
272+
]);
273+
274+
$event =$this->parser->parse($request,'');
275+
$this->assertNull($event);
276+
}
277+
278+
publicfunctiontestSmsDeliveryWithDlrCode4()
279+
{
280+
$request =$this->getRequest([
281+
'id' =>'webhook-id',
282+
'name' =>'sms.delivery',
283+
'data' => [
284+
'id' =>'123',
285+
'dlr_code' =>4,
286+
],
287+
]);
288+
289+
$event =$this->parser->parse($request,'');
290+
$this->assertNull($event);
291+
}
292+
293+
publicfunctiontestSmsDeliveryDlrCodePriorityOverStatusCode()
294+
{
295+
$payload = [
296+
'id' =>'webhook-id',
297+
'name' =>'sms.delivery',
298+
'data' => [
299+
'id' =>'123',
300+
'dlr_code' =>1,
301+
'status_code' =>500,
302+
],
303+
];
304+
305+
$request =$this->getRequest($payload);
306+
$event =$this->parser->parse($request,'');
307+
308+
$this->assertInstanceOf(SmsEvent::class,$event);
309+
$this->assertSame('123',$event->getId());
310+
$this->assertSame(SmsEvent::DELIVERED,$event->getName());
106311
$this->assertSame($payload,$event->getPayload());
107312
}
108313

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp