Skip to content

Commit 3137918

Browse files
committed
Merge branch 'card-present' of https://github.com/anushr/authorizenet into pr36
Conflicts: src/Message/AIMAbstractRequest.php src/Message/AIMAuthorizeRequest.php src/Message/CIMAuthorizeRequest.php src/Message/SIMAbstractRequest.php
2 parents ff9dc9d + 5d62fc7 commit 3137918

9 files changed

+191
-30
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"psr-4": { "Omnipay\\AuthorizeNet\\" : "src/" }
2929
},
3030
"require": {
31-
"omnipay/common": "~2.2"
31+
"omnipay/common": "~2.5"
3232
},
3333
"require-dev": {
3434
"omnipay/tests": "~2.0"

src/AIMGateway.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function getDefaultParameters()
2929
'hashSecret' => '',
3030
'liveEndpoint' => 'https://api2.authorize.net/xml/v1/request.api',
3131
'developerEndpoint' => 'https://apitest.authorize.net/xml/v1/request.api',
32+
'deviceType' => 1 // Device used to make the transaction. Required for card present. "1" = Unknown.
3233
);
3334
}
3435

@@ -108,6 +109,35 @@ public function setDuplicateWindow($value)
108109
return $this->setParameter('duplicateWindow', $value);
109110
}
110111

112+
public function getDeviceType()
113+
{
114+
return $this->getParameter('deviceType');
115+
}
116+
117+
/**
118+
* Sets the type of device used to collect the credit card data. A device type is required for card present
119+
* transactions.
120+
*
121+
* 1 = Unknown
122+
* 2 = Unattended Terminal
123+
* 3 = Self Service Terminal
124+
* 4 = Electronic Cash Register
125+
* 5 = Personal Computer-Based Terminal
126+
* 6 = AirPay
127+
* 7 = Wireless POS
128+
* 8 = Website
129+
* 9 = Dial Terminal
130+
* 10 = Virtual Terminal
131+
*
132+
* @see http://developer.authorize.net/api/reference/#payment-transactions-charge-a-credit-card
133+
* @param $value
134+
* @return $this
135+
*/
136+
public function setDeviceType($value)
137+
{
138+
return $this->setParameter('deviceType', $value);
139+
}
140+
111141
/**
112142
* @param array $parameters
113143
* @return AIMAuthorizeRequest

src/Message/AIMAbstractRequest.php

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ public function setSolutionId($value)
110110
return $this->setParameter('solutionId', $value);
111111
}
112112

113+
public function getDeviceType()
114+
{
115+
return $this->getParameter('deviceType');
116+
}
117+
118+
public function setDeviceType($value)
119+
{
120+
return $this->setParameter('deviceType', $value);
121+
}
122+
113123
/**
114124
* @return TransactionReference
115125
*/
@@ -325,18 +335,23 @@ protected function addTransactionSettings(\SimpleXMLElement $data)
325335
$i = 0;
326336

327337
// The test mode setting indicates whether or not this is a live request or a test request
328-
$data->transactionRequest->transactionSettings->setting[$i]->settingName = 'testRequest';
329-
$data->transactionRequest->transactionSettings->setting[$i]->settingValue = $this->getTestMode()
330-
? 'true'
331-
: 'false';
338+
$transactionRequest = $data->transactionRequest;
339+
$transactionRequest->transactionSettings->setting[$i]->settingName = 'testRequest';
340+
$transactionRequest->transactionSettings->setting[$i]->settingValue = $this->getTestMode() ? 'true' : 'false';
332341

333342
// The duplicate window setting specifies the threshold for AuthorizeNet's duplicate transaction detection logic
334343
if (!is_null($this->getDuplicateWindow())) {
335344
$i++;
336-
$data->transactionRequest->transactionSettings->setting[$i]->settingName = 'duplicateWindow';
337-
$data->transactionRequest->transactionSettings->setting[$i]->settingValue = $this->getDuplicateWindow();
345+
$transactionRequest->transactionSettings->setting[$i]->settingName = 'duplicateWindow';
346+
$transactionRequest->transactionSettings->setting[$i]->settingValue = $this->getDuplicateWindow();
338347
}
339348

340349
return $data;
341350
}
351+
352+
protected function isCardPresent()
353+
{
354+
// If the credit card has track data, then consider this a "card present" scenario
355+
return ($card = $this->getCard()) && $card->getTracks();
356+
}
342357
}

src/Message/AIMAuthorizeRequest.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public function getData()
2020
$this->addSolutionId($data);
2121
$this->addBillingData($data);
2222
$this->addCustomerIP($data);
23+
$this->addRetail($data);
2324
$this->addTransactionSettings($data);
2425

2526
return $data;
@@ -40,9 +41,19 @@ protected function addPayment(\SimpleXMLElement $data)
4041
/** @var CreditCard $card */
4142
$card = $this->getCard();
4243
$card->validate();
43-
$data->transactionRequest->payment->creditCard->cardNumber = $card->getNumber();
44-
$data->transactionRequest->payment->creditCard->expirationDate = $card->getExpiryDate('my');
45-
$data->transactionRequest->payment->creditCard->cardCode = $card->getCvv();
44+
if ($card->getTracks()) {
45+
// Card present
46+
if ($track1 = $card->getTrack1()) {
47+
$data->transactionRequest->payment->trackData->track1 = $track1;
48+
} elseif ($track2 = $card->getTrack2()) {
49+
$data->transactionRequest->payment->trackData->track2 = $track2;
50+
}
51+
} else {
52+
// Card not present
53+
$data->transactionRequest->payment->creditCard->cardNumber = $card->getNumber();
54+
$data->transactionRequest->payment->creditCard->expirationDate = $card->getExpiryDate('my');
55+
$data->transactionRequest->payment->creditCard->cardCode = $card->getCvv();
56+
}
4657
}
4758

4859
protected function addCustomerIP(\SimpleXMLElement $data)
@@ -52,4 +63,13 @@ protected function addCustomerIP(\SimpleXMLElement $data)
5263
$data->transactionRequest->customerIP = $ip;
5364
}
5465
}
66+
67+
protected function addRetail(\SimpleXMLElement $data)
68+
{
69+
if ($this->isCardPresent()) {
70+
// Retail element is required for card present transactions
71+
$data->transactionRequest->retail->marketType = 2;
72+
$data->transactionRequest->retail->deviceType = $this->getDeviceType();
73+
}
74+
}
5575
}

src/Message/CIMAuthorizeRequest.php

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,48 @@ class CIMAuthorizeRequest extends AIMAuthorizeRequest
1111
{
1212
protected function addPayment(\SimpleXMLElement $data)
1313
{
14-
$this->validate('cardReference');
14+
if ($this->isCardPresent()) {
15+
// Prefer the track data if present over the payment profile (better rate)
16+
return parent::addPayment($data);
17+
} else {
18+
$this->validate('cardReference');
1519

16-
/** @var mixed $req */
17-
$req = $data->transactionRequest;
20+
/** @var mixed $req */
21+
$req = $data->transactionRequest;
1822

19-
/** @var CardReference $cardRef */
20-
$cardRef = $this->getCardReference(false);
23+
/** @var CardReference $cardRef */
24+
$cardRef = $this->getCardReference(false);
2125

22-
$req->profile->customerProfileId = $cardRef->getCustomerProfileId();
26+
$req->profile->customerProfileId = $cardRef->getCustomerProfileId();
2327

24-
$req->profile->paymentProfile->paymentProfileId = $cardRef->getPaymentProfileId();
28+
$req->profile->paymentProfile->paymentProfileId = $cardRef->getPaymentProfileId();
2529

26-
if ($shippingProfileId = $cardRef->getShippingProfileId()) {
27-
$req->profile->shippingProfileId = $shippingProfileId;
28-
}
30+
if ($shippingProfileId = $cardRef->getShippingProfileId()) {
31+
$req->profile->shippingProfileId = $shippingProfileId;
32+
}
2933

30-
$invoiceNumber = $this->getInvoiceNumber();
31-
if (!empty($invoiceNumber)) {
32-
$req->order->invoiceNumber = $invoiceNumber;
33-
}
34+
$invoiceNumber = $this->getInvoiceNumber();
35+
if (!empty($invoiceNumber)) {
36+
$req->order->invoiceNumber = $invoiceNumber;
37+
}
3438

35-
$description = $this->getDescription();
36-
if (!empty($description)) {
37-
$req->order->description = $description;
39+
$description = $this->getDescription();
40+
if (!empty($description)) {
41+
$req->order->description = $description;
42+
}
43+
44+
return $data;
3845
}
3946

40-
return $data;
4147
}
4248

4349
protected function addBillingData(\SimpleXMLElement $data)
4450
{
45-
// Do nothing since billing information is already part of the customer profile
46-
return $data;
51+
if ($this->isCardPresent()) {
52+
return parent::addBillingData($data);
53+
} else {
54+
// Do nothing since billing information is already part of the customer profile
55+
return $data;
56+
}
4757
}
4858
}

src/Message/SIMAbstractRequest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ public function getInvoiceNumber()
9494
return $this->getParameter('invoiceNumber');
9595
}
9696

97+
public function getDeviceType()
98+
{
99+
return $this->getParameter('deviceType');
100+
}
101+
102+
public function setDeviceType($value)
103+
{
104+
return $this->setParameter('deviceType', $value);
105+
}
106+
97107
/**
98108
* Base data used only for the AIM API.
99109
*/

tests/AIMGatewayIntegrationTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,21 @@ public function testPurchaseRefundAutoVoid()
9393
$response = $request->send();
9494
$this->assertTrue($response->isSuccessful(), 'Automatic void should succeed');
9595
}
96+
97+
public function testPurchaseCardPresent()
98+
{
99+
$amount = rand(10, 100) . '.' . rand(0, 99);
100+
$card = array(
101+
'number' => '4242424242424242',
102+
'expiryMonth' => rand(1, 12),
103+
'expiryYear' => gmdate('Y') + rand(1, 5),
104+
'tracks' => '%B4242424242424242^SMITH/JOHN ^2511126100000000000000444000000?;4242424242424242=25111269999944401?'
105+
);
106+
$request = $this->gateway->purchase(array(
107+
'amount' => $amount,
108+
'card' => $card
109+
));
110+
$response = $request->send();
111+
$this->assertTrue($response->isSuccessful());
112+
}
96113
}

tests/Message/AIMAuthorizeRequestTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public function testGetData()
5858
$setting = $data->transactionRequest->transactionSettings->setting[0];
5959
$this->assertEquals('testRequest', $setting->settingName);
6060
$this->assertEquals('false', $setting->settingValue);
61+
$this->assertObjectNotHasAttribute('trackData', $data->transactionRequest->payment);
62+
$this->assertObjectNotHasAttribute('retail', $data->transactionRequest);
6163
}
6264

6365
public function testGetDataTestMode()
@@ -89,4 +91,46 @@ public function testShouldIncludeDuplicateWindowSetting()
8991
$this->assertEquals('duplicateWindow', $setting->settingName);
9092
$this->assertEquals('0', $setting->settingValue);
9193
}
94+
95+
public function testGetDataCardPresentTrack1()
96+
{
97+
$card = $this->getValidCard();
98+
$card['tracks'] = '%B4242424242424242^SMITH/JOHN ^2511126100000000000000444000000?;4242424242424242=25111269999944401?';
99+
$this->request->initialize(array(
100+
'amount' => '12.12',
101+
'card' => $card,
102+
'deviceType' => 1
103+
));
104+
105+
$data = $this->request->getData();
106+
107+
$this->assertEquals('12.12', $data->transactionRequest->amount);
108+
$this->assertEquals(
109+
'%B4242424242424242^SMITH/JOHN ^2511126100000000000000444000000?',
110+
$data->transactionRequest->payment->trackData->track1);
111+
$this->assertObjectNotHasAttribute('creditCard', $data->transactionRequest->payment);
112+
$this->assertEquals('2', $data->transactionRequest->retail->marketType);
113+
$this->assertEquals('1', $data->transactionRequest->retail->deviceType);
114+
}
115+
116+
public function testGetDataCardPresentTrack2()
117+
{
118+
$card = $this->getValidCard();
119+
$card['tracks'] = ';4242424242424242=25111269999944401?';
120+
$this->request->initialize(array(
121+
'amount' => '12.12',
122+
'card' => $card,
123+
'deviceType' => 1
124+
));
125+
126+
$data = $this->request->getData();
127+
128+
$this->assertEquals('12.12', $data->transactionRequest->amount);
129+
$this->assertEquals(
130+
';4242424242424242=25111269999944401?',
131+
$data->transactionRequest->payment->trackData->track2);
132+
$this->assertObjectNotHasAttribute('creditCard', $data->transactionRequest->payment);
133+
$this->assertEquals('2', $data->transactionRequest->retail->marketType);
134+
$this->assertEquals('1', $data->transactionRequest->retail->deviceType);
135+
}
92136
}

tests/Message/CIMAuthorizeRequestTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,19 @@ public function testGetData()
3333
$this->assertEquals('00001234', $data->transactionRequest->order->invoiceNumber);
3434
$this->assertEquals('Test authorize transaction', $data->transactionRequest->order->description);
3535
}
36+
37+
public function testShouldUseTrackDataIfCardPresent()
38+
{
39+
$card = $this->getValidCard();
40+
$card['tracks'] = '%B4242424242424242^SMITH/JOHN ^2511126100000000000000444000000?;4242424242424242=25111269999944401?';
41+
$this->request->initialize(array(
42+
'card' => $card,
43+
'amount' => 21.00
44+
));
45+
46+
$data = $this->request->getData();
47+
48+
$this->assertObjectNotHasAttribute('profile', $data->transactionRequest);
49+
$this->assertObjectHasAttribute('trackData', $data->transactionRequest->payment);
50+
}
3651
}

0 commit comments

Comments
 (0)