Skip to content

Commit 8ccce31

Browse files
authored
Merge pull request #129 from thephpleague/pr128
PR128 additions
2 parents 1c2c341 + bf5412b commit 8ccce31

19 files changed

+382
-177
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ php:
55
- 7.0
66
- 7.1
77
- 7.2
8+
- 7.3
89

910
# This triggers builds to run on the new TravisCI infrastructure.
1011
# See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,16 @@ $data = $response->getData();
111111

112112
$data['paymentProfile']['customerProfileId'];
113113
$data['paymentProfile']['customerPaymentProfileId'];
114-
//Now you can use these 2 fields to reference this customer and this payment profile for later use with
115-
//the rest of the CIM driver features as usual.
114+
115+
// Now you can use these 2 fields to reference this customer and this payment profile for later use with
116+
// the rest of the CIM driver features as usual.
116117
```
117118

118119
## DPM and SIM Signatures
119120

120121
DPM and SIM used to sign their requests with the `transactionKey` using the mdh HMAC algorithm.
121122
From early 2019, this algorithm is being removed completely.
122-
Instead, the SHA-512 HMAC algorithm is used to sign the DPM and SIM requsts,
123+
Instead, the SHA-512 HMAC algorithm is used to sign the DPM and SIM requests,
123124
and to validate the received notifications.
124125

125126
To start using the SHA-512 signing, set your `signatureKey` in the gateway:

src/Message/DPMAuthorizeRequest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Authorize.Net DPM Authorize Request.
77
* Takes the data that will be used to create the direct-post form.
88
*/
9+
910
class DPMAuthorizeRequest extends SIMAuthorizeRequest
1011
{
1112
protected $action = 'AUTH_ONLY';

src/Message/DPMCompleteRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/**
66
* Authorize.Net DPM Complete Authorize Request
77
*/
8-
class DPMCompleteRequest extends SIMCompleteAuthorizeRequest
8+
class DPMCompleteRequest extends SIMCompleteRequest
99
{
1010
public function sendData($data)
1111
{

src/Message/DPMCompleteResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
/**
66
* SIM and DPM both have identical needs when handling the notify request.
77
*/
8-
class DPMCompleteResponse extends SIMCompleteAuthorizeResponse
8+
class DPMCompleteResponse extends SIMCompleteResponse
99
{
1010
}

src/Message/SIMAbstractRequest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
namespace Omnipay\AuthorizeNet\Message;
44

5-
use Omnipay\Common\Message\AbstractRequest;
6-
75
/**
86
* Authorize.Net SIM Abstract Request
97
*/
8+
9+
use Omnipay\Common\Message\AbstractRequest;
10+
1011
abstract class SIMAbstractRequest extends AbstractRequest
1112
{
1213
/**

src/Message/SIMAuthorizeRequest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ public function getData()
5454
}
5555

5656
$data = array_merge($data, $this->getBillingData());
57-
$data['x_fp_hash'] = $this->getHash($data);
57+
58+
$data['x_fp_hash'] = $this->createHash($data);
5859

5960
return $data;
6061
}
@@ -64,10 +65,11 @@ public function getData()
6465
* modified en-route.
6566
* It uses the TransactionKey, which is a shared secret between the merchant
6667
* and Authorize.Net The sequence and timestamp provide additional salt.
68+
*
6769
* @param $data
6870
* @return string
6971
*/
70-
public function getHash($data)
72+
public function createHash($data)
7173
{
7274
$fingerprint = implode(
7375
'^',
@@ -77,7 +79,7 @@ public function getHash($data)
7779
$data['x_fp_timestamp'],
7880
$data['x_amount']
7981
)
80-
).'^';
82+
) . '^';
8183

8284
// If x_currency_code is specified, then it must follow the final trailing carat.
8385

src/Message/SIMAuthorizeResponse.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ public function getRedirectData()
4444
{
4545
return $this->getData();
4646
}
47+
48+
public function getTransactionId()
49+
{
50+
return isset($this->data[SIMAbstractRequest::TRANSACTION_ID_PARAM])
51+
? $this->data[SIMAbstractRequest::TRANSACTION_ID_PARAM]
52+
: null;
53+
}
4754
}

src/Message/SIMCompleteAuthorizeRequest.php

Lines changed: 0 additions & 86 deletions
This file was deleted.

src/Message/SIMCompleteRequest.php

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
namespace Omnipay\AuthorizeNet\Message;
4+
5+
use Omnipay\Common\Exception\InvalidRequestException;
6+
7+
/**
8+
* Authorize.Net SIM Complete Authorize Request
9+
*/
10+
class SIMCompleteRequest extends SIMAbstractRequest
11+
{
12+
/**
13+
* Get the transaction ID passed in through the custom field.
14+
* This is used to look up the transaction in storage.
15+
*/
16+
public function getTransactionId()
17+
{
18+
return $this->httpRequest->request->get(static::TRANSACTION_ID_PARAM);
19+
}
20+
21+
public function getData()
22+
{
23+
// The hash sent in the callback from the Authorize.Net gateway.
24+
$hashPosted = $this->getPostedHash();
25+
26+
// Calculate the hash locally, using the shared "hash secret" and login ID.
27+
$hashCalculated = $this->getHash();
28+
29+
if ($hashPosted !== $hashCalculated) {
30+
// If the hash is incorrect, then we can't trust the source nor anything sent.
31+
// Throwing exceptions here is probably a bad idea. We are trying to get the data,
32+
// and if it is invalid, then we need to be able to log that data for analysis.
33+
// Except we can't, baceuse the exception means we can't get to the data.
34+
// For now, this is consistent with other OmniPay gateway drivers.
35+
36+
throw new InvalidRequestException('Incorrect hash');
37+
}
38+
39+
// The hashes have passed, but the amount should also be validated against the
40+
// amount in the stored and retrieved transaction. If the application has the
41+
// ability to retrieve the transaction (using the transaction_id sent as a custom
42+
// form field, or perhaps in an otherwise unused field such as x_invoice_id.
43+
44+
$amount = $this->getAmount();
45+
$postedAmount = $this->httpRequest->request->get('x_amount');
46+
47+
if (isset($amount) && $amount != $postedAmount) {
48+
// The amounts don't match. Someone may have been playing with the
49+
// transaction references.
50+
51+
throw new InvalidRequestException('Incorrect amount');
52+
}
53+
54+
return $this->httpRequest->request->all();
55+
}
56+
57+
/**
58+
* @return string
59+
*/
60+
public function getHash()
61+
{
62+
if ($this->getSignatureKey()) {
63+
return $this->getSha512Hash();
64+
} else {
65+
return $this->getMd5Hash();
66+
}
67+
}
68+
69+
/**
70+
* Generate md5 hash.
71+
*
72+
* @param $transaction_reference
73+
* @param $amount
74+
* @return string
75+
*/
76+
public function getMd5Hash()
77+
{
78+
$transactionReference = $this->httpRequest->request->get('x_trans_id');
79+
$amount = $this->httpRequest->request->get('x_amount');
80+
81+
$key = array(
82+
$this->getHashSecret(),
83+
$this->getApiLoginId(),
84+
$transactionReference,
85+
$amount,
86+
);
87+
88+
return md5(implode('', $key));
89+
}
90+
91+
/**
92+
* Generate sha512 hash.
93+
* Required fields are provided in Table 18 in
94+
* https://www.authorize.net/content/dam/authorize/documents/SIM_guide.pdf#page=73
95+
*
96+
* @return string hash generated from server request transformed to upper case
97+
*/
98+
public function getSha512Hash()
99+
{
100+
$signatureKey = $this->getSignatureKey();
101+
$request = $this->httpRequest->request;
102+
103+
$hashData = '^' . implode('^', [
104+
$request->get('x_trans_id'),
105+
$request->get('x_test_request'),
106+
$request->get('x_response_code'),
107+
$request->get('x_auth_code'),
108+
$request->get('x_cvv2_resp_code'),
109+
$request->get('x_cavv_response'),
110+
$request->get('x_avs_code'),
111+
$request->get('x_method'),
112+
$request->get('x_account_number'),
113+
$request->get('x_amount'),
114+
$request->get('x_company'),
115+
$request->get('x_first_name'),
116+
$request->get('x_last_name'),
117+
$request->get('x_address'),
118+
$request->get('x_city'),
119+
$request->get('x_state'),
120+
$request->get('x_zip'),
121+
$request->get('x_country'),
122+
$request->get('x_phone'),
123+
$request->get('x_fax'),
124+
$request->get('x_email'),
125+
$request->get('x_ship_to_company'),
126+
$request->get('x_ship_to_first_name'),
127+
$request->get('x_ship_to_last_name'),
128+
$request->get('x_ship_to_address'),
129+
$request->get('x_ship_to_city'),
130+
$request->get('x_ship_to_state'),
131+
$request->get('x_ship_to_zip'),
132+
$request->get('x_ship_to_country'),
133+
$request->get('x_invoice_num'),
134+
]) . '^';
135+
$hash = hash_hmac('sha512', $hashData, hex2bin($signatureKey));
136+
137+
return strtoupper($hash);
138+
}
139+
140+
/**
141+
* Get posted hash from the callback from the Authorize.Net gateway.
142+
*
143+
* @return string|null
144+
*/
145+
public function getPostedHash()
146+
{
147+
if ($signatureKey = $this->getSignatureKey()) {
148+
return strtoupper($this->httpRequest->request->get('x_SHA2_Hash'));
149+
}
150+
151+
return strtolower($this->httpRequest->request->get('x_MD5_Hash'));
152+
}
153+
154+
public function sendData($data)
155+
{
156+
return $this->response = new SIMCompleteResponse($this, $data);
157+
}
158+
}

src/Message/SIMCompleteAuthorizeResponse.php renamed to src/Message/SIMCompleteResponse.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
namespace Omnipay\AuthorizeNet\Message;
44

5+
/**
6+
* Authorize.Net SIM Complete Authorize Response
7+
*/
8+
59
use Omnipay\Common\Message\AbstractResponse;
610
use Omnipay\Common\Message\RedirectResponseInterface;
711
use Symfony\Component\HttpFoundation\Response as HttpResponse;
812

9-
/**
10-
* Authorize.Net SIM Complete Authorize Response
11-
*/
12-
class SIMCompleteAuthorizeResponse extends AbstractResponse implements RedirectResponseInterface
13+
class SIMCompleteResponse extends AbstractResponse implements RedirectResponseInterface
1314
{
1415
// Response codes returned by Authorize.Net
1516

src/SIMGateway.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function authorize(array $parameters = array())
6060

6161
public function completeAuthorize(array $parameters = array())
6262
{
63-
return $this->createRequest('\Omnipay\AuthorizeNet\Message\SIMCompleteAuthorizeRequest', $parameters);
63+
return $this->createRequest('\Omnipay\AuthorizeNet\Message\SIMCompleteRequest', $parameters);
6464
}
6565

6666
public function capture(array $parameters = array())

tests/Message/DPMAuthorizeRequestTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public function testGetHash()
8181

8282
$expected = hash_hmac('md5', 'user^a^b^c^', 'key');
8383

84-
$this->assertSame($expected, $this->request->getHash($data));
84+
$this->assertSame($expected, $this->request->createHash($data));
8585
}
8686

8787
public function testSend()

0 commit comments

Comments
 (0)