10
10
class Management implements LoggerAwareInterface
11
11
{
12
12
const AS2_VERSION = '1.2 ' ;
13
+ const EDIINT_FEATURES = 'CEM ' ; // multiple-attachments,
13
14
const USER_AGENT = 'PHPAS2 ' ;
14
15
15
16
/**
@@ -48,8 +49,12 @@ public function __construct($options = [])
48
49
* @return MimePart
49
50
* @throws \Exception
50
51
*/
51
- public function buildMessageFromFile (MessageInterface $ message , $ filePath , $ contentType = null , $ encoding = 'binary ' )
52
- {
52
+ public function buildMessageFromFile (
53
+ MessageInterface $ message ,
54
+ $ filePath ,
55
+ $ contentType = null ,
56
+ $ encoding = 'binary '
57
+ ) {
53
58
if (! $ contentType ) {
54
59
$ contentType = $ message ->getReceiver ()->getContentType ();
55
60
}
@@ -98,8 +103,8 @@ public function buildMessage(MessageInterface $message, $payload)
98
103
'AS2-To ' => $ receiver ->getAs2Id (),
99
104
'Subject ' => $ receiver ->getSubject () ? $ receiver ->getSubject () : 'AS2 Message ' ,
100
105
'Date ' => date ('r ' ),
101
- 'Recipient-Address ' => $ receiver ->getTargetUrl (),
102
- 'Ediint-Features ' => ' CEM ' ,
106
+ // 'Recipient-Address' => $receiver->getTargetUrl(),
107
+ 'Ediint-Features ' => self :: EDIINT_FEATURES ,
103
108
];
104
109
105
110
if (! ($ payload instanceof MimePart)) {
@@ -148,13 +153,15 @@ public function buildMessage(MessageInterface $message, $payload)
148
153
}
149
154
150
155
// If MDN is to be requested from the partner, set the appropriate headers
151
- if ($ receiver ->getMdnMode ()) {
156
+ if ($ mdnMode = $ receiver ->getMdnMode ()) {
152
157
153
- $ as2headers ['Disposition-Notification-To ' ] = $ sender ->getTargetUrl ();
154
- $ as2headers ['Disposition-Notification-Options ' ] = $ receiver ->getMdnOptions ();
158
+ $ as2headers ['Disposition-Notification-To ' ] = $ sender ->getEmail ();
159
+ if ($ mdnOptions = $ receiver ->getMdnOptions ()) {
160
+ $ as2headers ['Disposition-Notification-Options ' ] = $ mdnOptions ;
161
+ }
155
162
156
163
// PARTNER IS ASYNC MDN
157
- if ($ receiver -> getMdnMode () == PartnerInterface::MDN_MODE_ASYNC ) {
164
+ if ($ mdnMode == PartnerInterface::MDN_MODE_ASYNC ) {
158
165
$ message ->setMdnMode (PartnerInterface::MDN_MODE_ASYNC );
159
166
$ as2headers ['Receipt-Delivery-Option ' ] = $ sender ->getTargetUrl ();
160
167
} else {
@@ -174,7 +181,7 @@ public function buildMessage(MessageInterface $message, $payload)
174
181
175
182
$ message ->setHeaders ($ as2Message ->getHeaderLines ());
176
183
177
- $ this ->getLogger ()->debug ('AS2 message has been built successfully, sending it to the partner ' );
184
+ $ this ->getLogger ()->debug ('AS2 message has been built successfully ' );
178
185
179
186
return $ as2Message ;
180
187
}
@@ -207,7 +214,7 @@ public function setLogger(LoggerInterface $logger)
207
214
* Takes the message as argument and posts the as2 message to the partner.
208
215
*
209
216
* @param MessageInterface $message
210
- * @param MimePart|string $payload
217
+ * @param MimePart $payload
211
218
* @return \Psr\Http\Message\ResponseInterface|false
212
219
* @throws \GuzzleHttp\Exception\GuzzleException
213
220
*/
@@ -223,7 +230,7 @@ public function sendMessage(MessageInterface $message, $payload)
223
230
$ options = [
224
231
'headers ' => $ payload ->getHeaders (),
225
232
'body ' => $ payload ->getBody (),
226
- // 'cert' => '' // TODO: partner https cert ?
233
+ // 'cert' => '' // TODO: partner https cert ?
227
234
];
228
235
229
236
if ($ partner ->getAuthMethod ()) {
@@ -249,6 +256,7 @@ public function sendMessage(MessageInterface $message, $payload)
249
256
250
257
$ body = $ response ->getBody ()->getContents ();
251
258
$ payload = new MimePart ($ response ->getHeaders (), $ body );
259
+ $ response ->getBody ()->rewind ();
252
260
253
261
$ this ->processMdn ($ message , $ payload );
254
262
}
@@ -330,15 +338,13 @@ public function processMdn(MessageInterface $message, $payload)
330
338
$ this ->getLogger ()->debug ('Found MDN report for message ' , [$ messageId ]);
331
339
try {
332
340
$ bodyPayload = MimePart::fromString ($ part ->getBody ());
333
-
334
341
if ($ bodyPayload ->hasHeader ('disposition ' )) {
335
342
$ mdnStatus = $ bodyPayload ->getParsedHeader ('Disposition ' , 0 , 1 );
336
343
if ($ mdnStatus == 'processed ' ) {
337
344
$ this ->getLogger ()->debug ('Message has been successfully processed, verifying the MIC if present. ' );
338
345
// Compare the MIC of the received message
339
346
$ receivedMic = $ bodyPayload ->getHeaderLine ('Received-Content-MIC ' );
340
347
if ($ receivedMic && $ message ->getMic ()) {
341
-
342
348
if (Utils::normalizeMic ($ message ->getMic ()) != Utils::normalizeMic ($ receivedMic )) {
343
349
throw new \Exception (
344
350
sprintf ('The Message Integrity Code (MIC) does not match the sent AS2 message (required: %s, returned: %s) ' ,
@@ -372,7 +378,7 @@ public function processMdn(MessageInterface $message, $payload)
372
378
*
373
379
* @param MessageInterface $message
374
380
* @param string $confirmationText
375
- * @param string $errorMessage
381
+ * @param string $errorMessage // TODO: detailedStatus
376
382
* @return MimePart
377
383
* @throws \InvalidArgumentException
378
384
*/
@@ -397,36 +403,40 @@ public function buildMdn(MessageInterface $message, $confirmationText = null, $e
397
403
398
404
// Parse Message Headers
399
405
$ messageHeaders = MimePart::fromString ($ message ->getHeaders ());
400
- $ notificationOptions = $ messageHeaders ->hasHeader ('disposition-notification-options ' );
406
+ $ isSigned = $ messageHeaders ->hasHeader ('disposition-notification-options ' );
401
407
402
408
// TODO: parse (signed-receipt-protocol, signed-receipt-micalg)
403
409
// $notificationOptions = Utils::parseHeader($notificationOptions);
404
410
405
- $ headers = [
411
+ // Set up the message headers
412
+ $ mdnHeaders = [
406
413
'Message-ID ' => '< ' . Utils::generateMessageID ($ receiver ) . '> ' ,
407
414
'Date ' => date ('r ' ),
408
- 'Ediint-Features ' => 'CEM ' , // multiple-attachments, CEM
409
415
'AS2-From ' => $ receiver ->getAs2Id (),
410
416
'AS2-To ' => $ sender ->getAs2Id (),
411
417
'AS2-Version ' => self ::AS2_VERSION ,
412
418
'User-Agent ' => self ::USER_AGENT ,
413
- 'Connection ' => 'close ' ,
419
+ 'Ediint-Features ' => self ::EDIINT_FEATURES ,
420
+ // 'Connection' => 'close',
414
421
];
415
422
416
- if (! $ notificationOptions ) {
423
+ // TODO: refactory
424
+ if (! $ isSigned ) {
417
425
$ reportHeaders ['Mime-Version ' ] = '1.0 ' ;
418
- $ reportHeaders += $ headers ;
426
+ $ reportHeaders += $ mdnHeaders ;
419
427
}
420
428
429
+ // TODO: partner.mdn_confirm_text
421
430
if (empty ($ confirmationText )) {
422
- $ confirmationText = 'The AS2 message has been received ' ;
431
+ $ confirmationText = 'Your message was successfully received and processed. ' ;
423
432
}
424
433
425
- // Build the text message with confirmation text and add to report
426
434
$ report = new MimePart ($ reportHeaders );
435
+
436
+ // Build the text message with confirmation text and add to report
427
437
$ report ->addPart (new MimePart ([
428
438
'Content-Type ' => 'text/plain ' ,
429
- 'Content-Transfer-Encoding ' => '7bit ' ,
439
+ 'Content-Transfer-Encoding ' => '7bit ' , // TODO: check 8bit
430
440
], $ confirmationText ));
431
441
432
442
// Build the MDN message and add to report
@@ -437,20 +447,25 @@ public function buildMdn(MessageInterface $message, $confirmationText = null, $e
437
447
'Original-Message-ID ' => '< ' . $ message ->getMessageId () . '> ' ,
438
448
'Disposition ' => 'automatic-action/MDN-sent-automatically; processed ' . ($ errorMessage ? '/error: ' . $ errorMessage : '' ),
439
449
];
450
+
440
451
if ($ mic = $ message ->getMic ()) {
441
452
$ mdnData ['Received-Content-MIC ' ] = $ mic ;
442
453
}
454
+
443
455
$ report ->addPart (new MimePart ([
444
456
'Content-Type ' => 'message/disposition-notification ' ,
445
457
'Content-Transfer-Encoding ' => '7bit ' ,
446
458
], Utils::normalizeHeaders ($ mdnData )));
447
459
448
460
// If signed MDN is requested by partner then sign the MDN and attach to report
449
- if ($ notificationOptions ) {
461
+ if ($ isSigned ) {
450
462
$ this ->getLogger ()->debug ('Outbound MDN has been signed. ' );
451
- $ x509 = openssl_x509_read ($ receiver ->getCertificate ());
452
- $ key = openssl_get_privatekey ($ receiver ->getPrivateKey (), $ receiver ->getPrivateKeyPassPhrase ());
453
- $ report = CryptoHelper::sign ($ report , $ x509 , $ key , $ headers );
463
+ // $x509 = openssl_x509_read($receiver->getCertificate());
464
+ // $key = openssl_get_privatekey($receiver->getPrivateKey(), $receiver->getPrivateKeyPassPhrase());
465
+ $ report = CryptoHelper::sign ($ report , $ receiver ->getCertificate (), [
466
+ $ receiver ->getPrivateKey (),
467
+ $ receiver ->getPrivateKeyPassPhrase (),
468
+ ], $ mdnHeaders );
454
469
}
455
470
456
471
$ this ->getLogger ()->debug (sprintf ('Outbound MDN created for AS2 message "%s". ' , $ messageId ));
@@ -464,6 +479,7 @@ public function buildMdn(MessageInterface $message, $confirmationText = null, $e
464
479
$ message ->setMdnStatus (MessageInterface::MDN_STATUS_SENT );
465
480
}
466
481
482
+ // TODO: before sign ?
467
483
$ message ->setMdnPayload ($ report ->toString ());
468
484
469
485
return $ report ;
0 commit comments