Skip to content

Commit

Permalink
OctopusDeploy release: 3.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
securesubmit-buildmaster committed Jan 27, 2022
1 parent 8d313a9 commit a4febbe
Show file tree
Hide file tree
Showing 19 changed files with 499 additions and 63 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@

## Latest version

#### Enhancements:
- Add fingerprint feature (GP-API)
- Add Payment Link Id in the request for authorize (GP-API)
- Add new unit tests on DCC CNP (GP-API)

#### Bug Fixes:
- Fix issue for Fleet cards (GP-ECOM)
- Fix issue for Diners card type (GP-ECOM)

## v3.0.0 (12/16/2021)

- Add Dynamic Currency Conversion feature for GP-API
- Show exceptions on updateTokenExpiry() & deleteToken()
- DOMDocument data encoded before serialization
Expand Down
2 changes: 1 addition & 1 deletion metadata.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<xml>
<releaseNumber>3.0.0</releaseNumber>
<releaseNumber>3.0.1</releaseNumber>
</xml>
9 changes: 9 additions & 0 deletions src/Builders/AuthorizationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,9 @@ class AuthorizationBuilder extends TransactionBuilder
/** @var PhoneNumber */
public $shippingPhone;

/** string */
public $paymentLinkId;

/**
* {@inheritdoc}
*
Expand Down Expand Up @@ -1432,4 +1435,10 @@ public function withPhoneNumber($phoneCountryCode, $number, $type)
}
return $this;
}

public function withPaymentLinkId($paymentLinkId)
{
$this->paymentLinkId = $paymentLinkId;
return $this;
}
}
1 change: 1 addition & 0 deletions src/Entities/GpApi/DTO/PaymentMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class PaymentMethod
public $bank_transfer;
/** @var array */
public $apm;
public $fingerprint_mode;

const PAYMENT_METHOD_TOKEN_PREFIX = 'PMT_';
}
15 changes: 14 additions & 1 deletion src/Entities/GpApi/GpApiAuthorizationRequestBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public function buildRequest(BaseBuilder $builder, $config)
$requestData['reference'] = $builder->clientTransactionId ?
$builder->clientTransactionId : GenerationUtils::generateOrderId();
$requestData['usage_mode'] = $builder->paymentMethodUsageMode;
$requestData['fingerprint_mode'] =
(!empty($builder->customerData) & !empty($builder->customerData->deviceFingerPrint) ?
$builder->customerData->deviceFingerPrint : null);
$card = new Card();
$builderCard = $builder->paymentMethod;
$card->number = $builderCard->number;
Expand Down Expand Up @@ -159,6 +162,12 @@ private function createFromAuthorizationBuilder($builder, GpApiConfig $config)
$requestBody['cashback_amount'] = StringUtils::toNumeric($builder->cashBackAmount);
$requestBody['ip_address'] = $builder->customerIpAddress;
$requestBody['payment_method'] = $this->createPaymentMethodParam($builder, $config);
if (!empty($builder->paymentLinkId)) {
$requestBody['link'] = [
'id' => $builder->paymentLinkId
];
}

if (
$builder->paymentMethod instanceof ECheck ||
$builder->paymentMethod instanceof AlternativePaymentMethod
Expand Down Expand Up @@ -286,8 +295,12 @@ private function createPaymentMethodParam($builder, $config)
$paymentMethod->name = $paymentMethodContainer instanceof AlternativePaymentMethod ?
$paymentMethodContainer->accountHolderName : (!empty($paymentMethodContainer->cardHolderName) ?
$paymentMethodContainer->cardHolderName : null);

switch (get_class($paymentMethodContainer)) {
case CreditCardData::class;
$paymentMethod->fingerprint_mode =
(!empty($builder->customerData) & !empty($builder->customerData->deviceFingerPrint) ?
$builder->customerData->deviceFingerPrint : null);
$secureEcom = $paymentMethodContainer->threeDSecure;
if (!empty($secureEcom)) {
$paymentMethod->authentication = ['id' => $secureEcom->serverTransactionId];
Expand Down Expand Up @@ -411,7 +424,7 @@ private function getEciCode($paymentMethod)
return $paymentMethod->eci;
}
$eciCode = null;
switch ($paymentMethod->getCardType())
switch (CardUtils::getBaseCardType($paymentMethod->getCardType()))
{
case CardType::VISA:
case CardType::AMEX:
Expand Down
6 changes: 6 additions & 0 deletions src/Entities/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ class Transaction
*/
public $accountNumberLast4;

/** @var string */
public $fingerprint;

/** @var string */
public $fingerprintIndicator;

/**
* Creates a `Transaction` object from a stored transaction ID.
*
Expand Down
13 changes: 11 additions & 2 deletions src/Gateways/Gp3DSProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use GlobalPayments\Api\Entities\Exceptions\GatewayException;
use GlobalPayments\Api\PaymentMethods\CreditCardData;
use GlobalPayments\Api\PaymentMethods\RecurringPaymentMethod;
use GlobalPayments\Api\Utils\CardUtils;
use GlobalPayments\Api\Utils\GenerationUtils;
use GlobalPayments\Api\Utils\StringUtils;

Expand Down Expand Up @@ -101,7 +102,11 @@ public function processSecure3d(Secure3dBuilder $builder)
if ($paymentMethod instanceof CreditCardData) {
$cardData = $paymentMethod;
$request = $this->maybeSetKey($request, 'number', $cardData->number);
$request = $this->maybeSetKey($request, 'scheme', $this->mapCardScheme(strtoupper($cardData->getCardType())));
$request = $this->maybeSetKey(
$request,
'scheme',
$this->mapCardScheme(strtoupper(CardUtils::getBaseCardType($cardData->getCardType())))
);
$hashValue = $cardData->number;
} elseif ($paymentMethod instanceof RecurringPaymentMethod) {
$storedCard = $paymentMethod;
Expand Down Expand Up @@ -158,7 +163,11 @@ public function processSecure3d(Secure3dBuilder $builder)
$hashValue = $cardData->number;

$request['card_detail'] = $this->maybeSetKey($request['card_detail'], 'number', $cardData->number);
$request['card_detail'] = $this->maybeSetKey($request['card_detail'], 'scheme', strtoupper($cardData->getCardType()));
$request['card_detail'] = $this->maybeSetKey(
$request['card_detail'],
'scheme',
strtoupper(CardUtils::getBaseCardType($cardData->getCardType()))
);
$request['card_detail'] = $this->maybeSetKey($request['card_detail'], 'expiry_month', $cardData->expMonth);
$request['card_detail'] = $this->maybeSetKey($request['card_detail'], 'expiry_year',
substr(str_pad($cardData->expYear, 4, '0', STR_PAD_LEFT), 2, 2));
Expand Down
18 changes: 15 additions & 3 deletions src/Gateways/RealexConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use GlobalPayments\Api\Entities\Enums\AlternativePaymentType;
use GlobalPayments\Api\Entities\Enums\CvnPresenceIndicator;
use GlobalPayments\Api\Entities\Enums\DccProcessor;
use GlobalPayments\Api\Entities\Enums\GatewayProvider;
use GlobalPayments\Api\Entities\Enums\PaymentMethodType;
use GlobalPayments\Api\Entities\Enums\ReportType;
use GlobalPayments\Api\Entities\Enums\TransactionModifier;
Expand All @@ -21,8 +22,10 @@
use GlobalPayments\Api\Entities\Reporting\TransactionSummary;
use GlobalPayments\Api\Entities\Transaction;
use GlobalPayments\Api\HostedPaymentConfig;
use GlobalPayments\Api\Mapping\EnumMapping;
use GlobalPayments\Api\PaymentMethods\CreditCardData;
use GlobalPayments\Api\PaymentMethods\TransactionReference;
use GlobalPayments\Api\Utils\CardUtils;
use GlobalPayments\Api\Utils\CountryUtils;
use GlobalPayments\Api\Utils\GenerationUtils;
use GlobalPayments\Api\Entities\Enums\EncyptedMobileType;
Expand Down Expand Up @@ -300,7 +303,11 @@ public function processAuthorization(AuthorizationBuilder $builder)
$cardElement->appendChild($xml->createElement("number", $card->number));
$cardElement->appendChild($xml->createElement("expdate", $card->getShortExpiry()));
$cardElement->appendChild($xml->createElement("chname", $card->cardHolderName));
$cardElement->appendChild($xml->createElement("type", strtoupper($card->getCardType())));

$cardElement->appendChild($xml->createElement(
"type",
strtoupper(EnumMapping::mapCardType(GatewayProvider::GP_ECOM, CardUtils::getBaseCardType($card->getCardType())))
));

if ($card->cvn !== null) {
//if cvn number is not empty indicator should be PRESENT
Expand Down Expand Up @@ -1046,7 +1053,12 @@ private function buildCardElement($xml, $payment, $paymentKey = '')
$cardElement->appendChild($xml->createElement("number", $card->number));
$cardElement->appendChild($xml->createElement("expdate", $card->getShortExpiry()));
$cardElement->appendChild($xml->createElement("chname", $card->cardHolderName));
$cardElement->appendChild($xml->createElement("type", strtoupper($card->getCardType())));
$cardElement->appendChild($xml->createElement(
"type",
strtoupper(EnumMapping::mapCardType(
GatewayProvider::GP_ECOM,
CardUtils::getBaseCardType($card->getCardType())))
));

return $cardElement;
}
Expand Down Expand Up @@ -1584,7 +1596,7 @@ private function mapAPMUrls($paymentMethodType)
return ['returnurl', 'statusupdateurl', 'cancelurl'];
}
}

private function setSerializeData($key, $value = null)
{
if ($value !== null) {
Expand Down
17 changes: 17 additions & 0 deletions src/Mapping/EnumMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace GlobalPayments\Api\Mapping;

use GlobalPayments\Api\Entities\Enums\AccountType;
use GlobalPayments\Api\Entities\Enums\CardType;
use GlobalPayments\Api\Entities\Enums\EmvLastChipRead;
use GlobalPayments\Api\Entities\Enums\EncyptedMobileType;
use GlobalPayments\Api\Entities\Enums\GatewayProvider;
Expand Down Expand Up @@ -95,4 +96,20 @@ public static function mapEmvLastChipRead($gateway, $value)
return null;
}
}

public static function mapCardType($gateway, $value)
{
switch ($gateway) {
case GatewayProvider::GP_ECOM:
case GatewayProvider::GP_API:
switch ($value) {
case 'DinersClub':
return CardType::DINERS;
default:
return $value;
}
default:
return null;
}
}
}
14 changes: 10 additions & 4 deletions src/Mapping/GpApiMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,18 @@ public static function mapResponse($response)
$transaction->token = substr($response->id, 0, 4) === PaymentMethod::PAYMENT_METHOD_TOKEN_PREFIX ?
$response->id : null;
$transaction->clientTransactionId = !empty($response->reference) ? $response->reference : null;
$transaction->fingerprint = !empty($response->fingerprint) ? $response->fingerprint : null;
$transaction->fingerprintIndicator = !empty($response->fingerprint_presence_indicator) ?
$response->fingerprint_presence_indicator : null;
if (!empty($response->payment_method)) {
$transaction->authorizationCode = $response->payment_method->result;
if (!empty($response->payment_method->id)) {
$transaction->token = $response->payment_method->id;
}
$transaction->fingerprint = !empty($response->payment_method->fingerprint) ?
$response->payment_method->fingerprint : null;
$transaction->fingerprintIndicator = !empty($response->payment_method->fingerprint_presence_indicator) ?
$response->payment_method->fingerprint_presence_indicator : null;
if (!empty($response->payment_method->card)) {
$card = $response->payment_method->card;
$transaction->cardLast4 = !empty($card->masked_number_last4) ?
Expand All @@ -80,6 +87,9 @@ public static function mapResponse($response)
$transaction->accountType = !empty($bankTransfer->account_type) ? $bankTransfer->account_type : null;
$transaction->paymentMethodType = PaymentMethodType::ACH;
}
if (!empty($response->payment_method->apm)) {
$transaction->paymentMethodType = PaymentMethodType::APM;
}
}

if (!empty($response->card)) {
Expand All @@ -94,10 +104,6 @@ public static function mapResponse($response)

$transaction->dccRateData = self::mapDccInfo($response);

if (!empty($response->payment_method->apm)) {
$transaction->paymentMethodType = PaymentMethodType::APM;
}

return $transaction;
}

Expand Down
30 changes: 2 additions & 28 deletions src/PaymentMethods/CreditCardData.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use GlobalPayments\Api\Entities\Enums\DccRateType;
use GlobalPayments\Api\Entities\DccRateData;
use GlobalPayments\Api\Entities\ThreeDSecure;
use GlobalPayments\Api\Utils\CardUtils;

class CreditCardData extends Credit implements ICardData
{
Expand Down Expand Up @@ -69,21 +70,6 @@ class CreditCardData extends Credit implements ICardData
* @var bool
*/
public $readerPresent;

/**
* Card type regex patterns
*
* @var array
*/
public static $cardTypes = [
'Visa' => '/^4/',
'MC' => '/^(5[1-5]|2[2-7])/',
'Amex' => '/^3[47]/',
'DinersClub' => '/^3[0689]/',
'EnRoute' => '/^2(014|149)/',
'Discover' => '/^6([045]|22)/',
'Jcb' => '/^35/',
];

/**
* Set the Card on File storage
Expand Down Expand Up @@ -126,19 +112,7 @@ public function getShortExpiry()
*/
public function getCardType()
{
$number = str_replace(
[' ', '-'],
'',
$this->number
);

foreach (static::$cardTypes as $type => $regex) {
if (1 === preg_match($regex, $this->number)) {
return $type;
}
}

return 'Unknown';
return CardUtils::getCardType($this->number);
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/Utils/CardUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,19 @@ public static function getCvvIndicator($cvnPresenceIndicator)

return $cvvIndicator;
}

/**
* @param string $cardType
* @return mixed
*/
public static function getBaseCardType($cardType)
{
foreach (array_keys(self::$cardTypes) as $baseCardType) {
if (substr($cardType, 0, strlen($baseCardType)) == $baseCardType) {
return $baseCardType;
}
}

return $cardType;
}
}
22 changes: 22 additions & 0 deletions test/Integration/Gateways/GpApiConnector/AccessTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,28 @@ public function testGenerateAccessTokenWrongAppKey()
}
}

public function testCreateAccessTokenWithMaximum_SecondsToExpire()
{
$this->config->secondsToExpire = 604801;
try {
GpApiService::generateTransactionKey($this->config);
} catch (GatewayException $e) {
$this->assertEquals('40213', $e->responseCode);
$this->assertEquals('Status Code: INVALID_REQUEST_DATA - seconds_to_expire contains unexpected data', $e->getMessage());
}
}

public function testCreateAccessTokenWithInvalid_SecondsToExpire()
{
$this->config->secondsToExpire = 10;
try {
GpApiService::generateTransactionKey($this->config);
} catch (GatewayException $e) {
$this->assertEquals('40213', $e->responseCode);
$this->assertEquals('Status Code: INVALID_REQUEST_DATA - seconds_to_expire contains unexpected data', $e->getMessage());
}
}

public function testUseExpiredAccessToken()
{
$accessTokenInfo = new AccessTokenInfo();
Expand Down
Loading

0 comments on commit a4febbe

Please sign in to comment.