Skip to content

Commit fcb76fb

Browse files
committed
Add automatic credit card brand detection. Closes thephpleague#18
commit 2a22884 Author: Ben Swinburne <[email protected]> Date: Thu Feb 21 22:20:05 2013 +0000 Run code through php-cs-fixer commit 918c156 Author: Ben Swinburne <[email protected]> Date: Thu Feb 21 22:17:44 2013 +0000 removed accidental added responsetest commit 4087a03 Author: Ben Swinburne <[email protected]> Date: Thu Feb 21 22:10:29 2013 +0000 Switch to $brand, drop $type, add detection method. Deleted individual validation methods commit 45f1b78 Author: Ben Swinburne <[email protected]> Date: Thu Feb 21 11:11:23 2013 +0000 Fixed non array type bug when no addtional card types added commit e49ad59 Author: Ben Swinburne <[email protected]> Date: Thu Feb 21 10:02:02 2013 +0000 Fixed missing commas causing a parse error commit ecab6ac Author: Ben Swinburne <[email protected]> Date: Thu Feb 21 00:04:01 2013 +0000 Added card validation/determination methods
1 parent 6e07900 commit fcb76fb

File tree

4 files changed

+110
-19
lines changed

4 files changed

+110
-19
lines changed

src/Omnipay/Common/CreditCard.php

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@
1919
*/
2020
class CreditCard
2121
{
22+
const BRAND_VISA = 'visa';
23+
const BRAND_MASTERCARD = 'mastercard';
24+
const BRAND_DISCOVER = 'discover';
25+
const BRAND_AMEX = 'amex';
26+
const BRAND_DINERS_CLUB = 'diners_club';
27+
const BRAND_JCB = 'jcb';
28+
const BRAND_SWITCH = 'switch';
29+
const BRAND_SOLO = 'solo';
30+
const BRAND_DANKORT = 'dankort';
31+
const BRAND_MAESTRO = 'maestro';
32+
const BRAND_FORBRUGSFORENINGEN = 'forbrugsforeningen';
33+
const BRAND_LASER = 'laser';
34+
2235
/**
2336
* @var \Symfony\Component\HttpFoundation\ParameterBag
2437
*/
@@ -34,6 +47,35 @@ public function __construct($parameters = null)
3447
$this->initialize($parameters);
3548
}
3649

50+
/**
51+
* All known/supported card brands, and a regular expression to match them.
52+
*
53+
* The order of the card brands is important, as some of the regular expressions overlap.
54+
*
55+
* Note: The fact that this class knows about a particular card brand does not imply
56+
* that your gateway supports it.
57+
*
58+
* @return array
59+
* @link https://github.com/Shopify/active_merchant/blob/master/lib/active_merchant/billing/credit_card_methods.rb
60+
*/
61+
public function getSupportedBrands()
62+
{
63+
return array(
64+
static::BRAND_VISA => '/^4\d{12}(\d{3})?$/',
65+
static::BRAND_MASTERCARD => '/^(5[1-5]\d{4}|677189)\d{10}$/',
66+
static::BRAND_DISCOVER => '/^(6011|65\d{2}|64[4-9]\d)\d{12}|(62\d{14})$/',
67+
static::BRAND_AMEX => '/^3[47]\d{13}$/',
68+
static::BRAND_DINERS_CLUB => '/^3(0[0-5]|[68]\d)\d{11}$/',
69+
static::BRAND_JCB => '/^35(28|29|[3-8]\d)\d{12}$/',
70+
static::BRAND_SWITCH => '/^6759\d{12}(\d{2,3})?$/',
71+
static::BRAND_SOLO => '/^6767\d{12}(\d{2,3})?$/',
72+
static::BRAND_DANKORT => '/^5019\d{12}$/',
73+
static::BRAND_MAESTRO => '/^(5[06-8]|6\d)\d{10,17}$/',
74+
static::BRAND_FORBRUGSFORENINGEN => '/^600722\d{10}$/',
75+
static::BRAND_LASER => '/^(6304|6706|6709|6771(?!89))\d{8}(\d{4}|\d{6,7})?$/',
76+
);
77+
}
78+
3779
/**
3880
* Initialize the object with parameters.
3981
*
@@ -138,6 +180,22 @@ public function setNumber($value)
138180
return $this->setParameter('number', preg_replace('/\D/', '', $value));
139181
}
140182

183+
/**
184+
* Credit Card Brand
185+
*
186+
* Iterates through known/supported card brands to determine the brand of this card
187+
*
188+
* @return string
189+
*/
190+
public function getBrand()
191+
{
192+
foreach ($this->getSupportedBrands() as $brand => $val) {
193+
if (preg_match($val, $this->getNumber())) {
194+
return $brand;
195+
}
196+
}
197+
}
198+
141199
public function getExpiryMonth()
142200
{
143201
return $this->getParameter('expiryMonth');
@@ -218,16 +276,6 @@ public function setIssueNumber($value)
218276
return $this->setParameter('issueNumber', $value);
219277
}
220278

221-
public function getType()
222-
{
223-
return $this->getParameter('type');
224-
}
225-
226-
public function setType($value)
227-
{
228-
return $this->setParameter('type', $value);
229-
}
230-
231279
public function getBillingAddress1()
232280
{
233281
return $this->getParameter('billingAddress1');

src/Omnipay/PayPal/Message/ProAuthorizeRequest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ public function getData()
3232
$data[$prefix.'DESC'] = $this->getDescription();
3333

3434
// add credit card details
35-
$data['CREDITCARDTYPE'] = $this->getCard()->getType();
3635
$data['ACCT'] = $this->getCard()->getNumber();
36+
$data['CREDITCARDTYPE'] = $this->getCard()->getBrand();
3737
$data['EXPDATE'] = $this->getCard()->getExpiryMonth().$this->getCard()->getExpiryYear();
3838
$data['STARTDATE'] = $this->getCard()->getStartMonth().$this->getCard()->getStartYear();
3939
$data['CVV2'] = $this->getCard()->getCvv();
4040
$data['ISSUENUMBER'] = $this->getCard()->getIssueNumber();
41-
$data['IPADDRESS'] = '';
41+
$data['IPADDRESS'] = $this->getClientIp();
4242
$data['FIRSTNAME'] = $this->getCard()->getFirstName();
4343
$data['LASTNAME'] = $this->getCard()->getLastName();
4444
$data['EMAIL'] = $this->getCard()->getEmail();

src/Omnipay/SagePay/Message/DirectAuthorizeRequest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function getData()
6666
$data['CardNumber'] = $this->getCard()->getNumber();
6767
$data['CV2'] = $this->getCard()->getCvv();
6868
$data['ExpiryDate'] = $this->getCard()->getExpiryDate('my');
69-
$data['CardType'] = $this->getCard()->getType();
69+
$data['CardType'] = $this->getCard()->getBrand();
7070

7171
if ($this->getCard()->getStartMonth() and $this->getCard()->getStartYear()) {
7272
$data['StartDate'] = $this->getCard()->getStartDate('my');

tests/Omnipay/Common/CreditCardTest.php

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ public function testValidateNumber()
131131
$this->card->validate();
132132
}
133133

134+
public function testGetSupportedBrands()
135+
{
136+
$brands = $this->card->getSupportedBrands();
137+
$this->assertInternalType('array', $brands);
138+
$this->assertArrayHasKey(CreditCard::BRAND_VISA, $brands);
139+
}
140+
134141
public function testFirstName()
135142
{
136143
$this->card->setFirstName('Bob');
@@ -183,6 +190,48 @@ public function testSetNumberStripsNonDigits()
183190
$this->assertEquals('4000000000000000', $this->card->getNumber());
184191
}
185192

193+
public function testGetBrandDefault()
194+
{
195+
$card = new CreditCard;
196+
$this->assertNull($card->getBrand());
197+
}
198+
199+
public function testGetBrandVisa()
200+
{
201+
$card = new CreditCard(array('number' => '4242424242424242'));
202+
$this->assertSame(CreditCard::BRAND_VISA, $card->getBrand());
203+
}
204+
205+
public function testGetBrandMasterCard()
206+
{
207+
$card = new CreditCard(array('number' => '5555555555554444'));
208+
$this->assertSame(CreditCard::BRAND_MASTERCARD, $card->getBrand());
209+
}
210+
211+
public function testGetBrandAmex()
212+
{
213+
$card = new CreditCard(array('number' => '378282246310005'));
214+
$this->assertSame(CreditCard::BRAND_AMEX, $card->getBrand());
215+
}
216+
217+
public function testGetBrandDiscover()
218+
{
219+
$card = new CreditCard(array('number' => '6011111111111117'));
220+
$this->assertSame(CreditCard::BRAND_DISCOVER, $card->getBrand());
221+
}
222+
223+
public function testGetBrandDinersClub()
224+
{
225+
$card = new CreditCard(array('number' => '30569309025904'));
226+
$this->assertSame(CreditCard::BRAND_DINERS_CLUB, $card->getBrand());
227+
}
228+
229+
public function testGetBrandJcb()
230+
{
231+
$card = new CreditCard(array('number' => '3530111333300000'));
232+
$this->assertSame(CreditCard::BRAND_JCB, $card->getBrand());
233+
}
234+
186235
public function testExpiryMonth()
187236
{
188237
$this->card->setExpiryMonth(9);
@@ -243,12 +292,6 @@ public function testIssueNumber()
243292
$this->assertSame('12', $this->card->getIssueNumber());
244293
}
245294

246-
public function testType()
247-
{
248-
$this->card->setType('visa');
249-
$this->assertEquals('visa', $this->card->getType());
250-
}
251-
252295
public function testBillingAddress1()
253296
{
254297
$this->card->setBillingAddress1('31 Spooner St');

0 commit comments

Comments
 (0)