From 37b2c7284c487e399a2888802990cb50e7598a07 Mon Sep 17 00:00:00 2001 From: securesubmit-buildmaster Date: Thu, 8 Sep 2022 08:20:05 -0400 Subject: [PATCH] OctopusDeploy release: 5.0.1 --- CHANGELOG.md | 5 ++ metadata.xml | 2 +- .../GpEcom/GpEcomRecurringRequestBuilder.php | 7 ++ src/Entities/CardIssuerResponse.php | 44 ++++++++++++ src/Entities/Customer.php | 4 +- src/Entities/Transaction.php | 3 + src/Mapping/GpApiMapping.php | 21 +++++- src/PaymentMethods/RecurringPaymentMethod.php | 6 ++ .../CreditCardNotPresentTest.php | 68 ++++++++++--------- .../GpEcomConnector/RecurringTest.php | 52 ++++++++++++++ 10 files changed, 178 insertions(+), 34 deletions(-) create mode 100644 src/Entities/CardIssuerResponse.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 568afdc8..f84dfcbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ ## Latest version #### Enhancements: +GP-API: Add new mapping for card issuer avs/cvv result +GP-ECOM: Add srd tag to card storage request + +## v5.0.0 (08/23/2022) +#### Enhancements: - Support PHP v. >= 8.0 - GP_API: Update PayLink unit tests diff --git a/metadata.xml b/metadata.xml index a5f3a662..579751dd 100644 --- a/metadata.xml +++ b/metadata.xml @@ -1,3 +1,3 @@ - 5.0.0 + 5.0.1 \ No newline at end of file diff --git a/src/Builders/RequestBuilder/GpEcom/GpEcomRecurringRequestBuilder.php b/src/Builders/RequestBuilder/GpEcom/GpEcomRecurringRequestBuilder.php index ce046015..a79f1d7e 100644 --- a/src/Builders/RequestBuilder/GpEcom/GpEcomRecurringRequestBuilder.php +++ b/src/Builders/RequestBuilder/GpEcom/GpEcomRecurringRequestBuilder.php @@ -42,6 +42,7 @@ public static function canProcess($builder) */ public function buildRequest(BaseBuilder $builder, $config) { + /** @var RecurringBuilder $builder */ $xml = new DOMDocument(); $timestamp = GenerationUtils::generateTimestamp(); $orderId = $builder->orderId ? $builder->orderId : GenerationUtils::generateOrderId(); @@ -113,6 +114,12 @@ public function buildRequest(BaseBuilder $builder, $config) } $request->appendChild($xml->createElement("orderid", $orderId)); $request->appendChild($this->buildCardElement($xml, $payment, $paymentKey)); + // stored credential + if ($payment->storedCredential != null) { + $storedCredential = $xml->createElement("storedcredential"); + $storedCredential->appendChild($xml->createElement("srd", $payment->storedCredential->schemeId)); + $request->appendChild($storedCredential); + } $request->appendChild($xml->createElement("defaultcard", 1)); } elseif ($builder->entity instanceof Schedule) { $schedule = $builder->entity; diff --git a/src/Entities/CardIssuerResponse.php b/src/Entities/CardIssuerResponse.php new file mode 100644 index 00000000..8affcb41 --- /dev/null +++ b/src/Entities/CardIssuerResponse.php @@ -0,0 +1,44 @@ +firstName, $this->lastName); if (empty(str_replace(' ', '', $nameOnAccount))) { @@ -151,6 +152,7 @@ public function addPaymentMethod($paymentId, IPaymentMethod $paymentMethod) $payment->customerKey = $this->key; $payment->id = $paymentId; $payment->nameOnAccount = $nameOnAccount; + $payment->storedCredential = $storedCredential; return $payment; } } diff --git a/src/Entities/Transaction.php b/src/Entities/Transaction.php index 713ed950..3cacff6b 100644 --- a/src/Entities/Transaction.php +++ b/src/Entities/Transaction.php @@ -304,6 +304,9 @@ class Transaction /** @var PayLinkResponse */ public $payLinkResponse; + /** @var CardIssuerResponse $cardIssuerResponse */ + public $cardIssuerResponse; + /** * Creates a `Transaction` object from a stored transaction ID. * diff --git a/src/Mapping/GpApiMapping.php b/src/Mapping/GpApiMapping.php index 338340e5..b39cb166 100644 --- a/src/Mapping/GpApiMapping.php +++ b/src/Mapping/GpApiMapping.php @@ -4,6 +4,7 @@ use GlobalPayments\Api\Entities\AlternativePaymentResponse; use GlobalPayments\Api\Entities\BatchSummary; +use GlobalPayments\Api\Entities\CardIssuerResponse; use GlobalPayments\Api\Entities\DisputeDocument; use GlobalPayments\Api\Entities\DccRateData; use GlobalPayments\Api\Entities\Enums\AuthenticationSource; @@ -105,6 +106,9 @@ public static function mapResponse($response) $card->avs_postal_code_result : null; $transaction->avsAddressResponse = !empty($card->avs_address_result) ? $card->avs_address_result : null; $transaction->avsResponseMessage = !empty($card->avs_action) ? $card->avs_action : null; + if (!empty($card->provider)) { + self::mapCardIssuerResponse($transaction, $card->provider); + } } if (!empty($response->payment_method->bank_transfer)) { $bankTransfer = $response->payment_method->bank_transfer; @@ -704,7 +708,6 @@ public static function mapPayLinkSummary($response) foreach ($response->transactions as $transaction) { $summary->transactions[] = self::createTransactionSummary($transaction); } - } return $summary; @@ -754,4 +757,20 @@ private static function createTransactionSummary($response) return $transaction; } + + /** + * Map the result codes directly from the card issuer. + * + * @param Transaction $transaction + * @param $cardIssuerResponse + */ + private static function mapCardIssuerResponse(Transaction &$transaction, $cardIssuerResponse) + { + $transaction->cardIssuerResponse = new CardIssuerResponse(); + $transaction->cardIssuerResponse->result = $cardIssuerResponse->result ?? null; + $transaction->cardIssuerResponse->avsResult = $cardIssuerResponse->avs_result ?? null; + $transaction->cardIssuerResponse->cvvResult = $cardIssuerResponse->cvv_result ?? null; + $transaction->cardIssuerResponse->avsAddressResult = $cardIssuerResponse->avs_address_result ?? null; + $transaction->cardIssuerResponse->avsPostalCodeResult = $cardIssuerResponse->avs_postal_code_result ?? null; + } } \ No newline at end of file diff --git a/src/PaymentMethods/RecurringPaymentMethod.php b/src/PaymentMethods/RecurringPaymentMethod.php index 161b1d13..fb0d3889 100644 --- a/src/PaymentMethods/RecurringPaymentMethod.php +++ b/src/PaymentMethods/RecurringPaymentMethod.php @@ -8,6 +8,7 @@ use GlobalPayments\Api\Entities\Enums\PaymentMethodType; use GlobalPayments\Api\Entities\Exceptions\ArgumentException; use GlobalPayments\Api\Entities\Schedule; +use GlobalPayments\Api\Entities\StoredCredential; use GlobalPayments\Api\PaymentMethods\Interfaces\IAuthable; use GlobalPayments\Api\PaymentMethods\Interfaces\IChargable; use GlobalPayments\Api\PaymentMethods\Interfaces\IPaymentMethod; @@ -125,6 +126,11 @@ class RecurringPaymentMethod extends RecurringEntity implements */ public $cardBrandTransactionId; + /** + * @var StoredCredential + */ + public $storedCredential; + /** * @param string|IPaymentMethod $customerIdOrPaymentMethod * @param string $paymentId diff --git a/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php b/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php index f417184b..9ca4b264 100644 --- a/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php +++ b/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php @@ -5,9 +5,9 @@ use GlobalPayments\Api\Builders\ManagementBuilder; use GlobalPayments\Api\Entities\Address; use GlobalPayments\Api\Entities\Customer; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\Environment; use GlobalPayments\Api\Entities\Enums\ManualEntryMethod; -use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\PaymentMethodUsageMode; use GlobalPayments\Api\Entities\Enums\SortDirection; use GlobalPayments\Api\Entities\Enums\StoredCredentialInitiator; @@ -46,7 +46,7 @@ class CreditCardNotPresentTest extends TestCase private $currency = 'GBP'; - public function setup() : void + public function setup(): void { ServicesContainer::configureService($this->setUpConfig()); $this->card = new CreditCardData(); @@ -1240,8 +1240,11 @@ public function testCreditSale_ExpiryCard() * @param $avsAddressResponse * @param $status * @param $transactionStatus + * @param $cvvResult + * @param $avsPostcode + * @param $addressResult */ - public function testCreditSale_CVVResult($cardNumber, $cvnResponseMessage, $avsResponseCode, $avsAddressResponse, $status, $transactionStatus) + public function testCreditSale_CVVResult($cardNumber, $cvnResponseMessage, $avsResponseCode, $avsAddressResponse, $status, $transactionStatus, $cvvResult, $avsPostcode, $addressResult) { $address = new Address(); $address->streetAddress1 = "123 Main St."; @@ -1263,6 +1266,9 @@ public function testCreditSale_CVVResult($cardNumber, $cvnResponseMessage, $avsR $this->assertEquals($cvnResponseMessage, $response->cvnResponseMessage); $this->assertEquals($avsResponseCode, $response->avsResponseCode); $this->assertEquals($avsAddressResponse, $response->avsAddressResponse); + $this->assertEquals($addressResult, $response->cardIssuerResponse->avsAddressResult); + $this->assertEquals($avsPostcode, $response->cardIssuerResponse->avsPostalCodeResult); + $this->assertEquals($cvvResult, $response->cardIssuerResponse->cvvResult); } public function testCreditAuthorizationWithPaymentLinkId() @@ -1423,34 +1429,34 @@ public function testCardTokenizationThenUpdateWithoutUsageMode() public function AvsCardTests() { return [ - [GpApiAvsCheckTestCards::AVS_MASTERCARD_1, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_2, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_3, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_4, "MATCHED", "MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_5, "MATCHED", "MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_6, "MATCHED", "NOT_MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_7, "MATCHED", "NOT_MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_8, "NOT_MATCHED", "NOT_MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_9, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_10, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_11, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_12, "NOT_MATCHED", "MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_13, "NOT_MATCHED", "MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_MASTERCARD_14, "NOT_MATCHED", "NOT_MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], - [GpApiAvsCheckTestCards::AVS_VISA_1, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_2, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_3, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_4, "NOT_CHECKED", "MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_5, "NOT_CHECKED", "MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_6, "NOT_CHECKED", "NOT_MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_7, "NOT_CHECKED", "NOT_MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_8, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_9, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_10, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_11, "NOT_CHECKED", "MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_12, "NOT_CHECKED", "MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_13, "NOT_CHECKED", "NOT_MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], - [GpApiAvsCheckTestCards::AVS_VISA_14, "NOT_CHECKED", "NOT_MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED] + [GpApiAvsCheckTestCards::AVS_MASTERCARD_1, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED, "M", "U", "U"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_2, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED, "M", "I", "I"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_3, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED, "M", "P", "P"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_4, "MATCHED", "MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "M", "M", "M"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_5, "MATCHED", "MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "M", "M", "N"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_6, "MATCHED", "NOT_MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "M", "N", "M"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_7, "MATCHED", "NOT_MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "M", "N", "N"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_8, "NOT_MATCHED", "NOT_MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "N", "N", "M"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_9, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED, "N", "U", "U"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_10, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED, "N", "I", "I"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_11, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED, "N", "P", "P"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_12, "NOT_MATCHED", "MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "N", "M", "M"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_13, "NOT_MATCHED", "MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "N", "M", "N"], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_14, "NOT_MATCHED", "NOT_MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED, "N", "N", "N"], + [GpApiAvsCheckTestCards::AVS_VISA_1, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED, "I", "U", "U"], + [GpApiAvsCheckTestCards::AVS_VISA_2, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED, "I", "I", "I"], + [GpApiAvsCheckTestCards::AVS_VISA_3, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED, "I", "P", "P"], + [GpApiAvsCheckTestCards::AVS_VISA_4, "NOT_CHECKED", "MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED, "I", "M", "M"], + [GpApiAvsCheckTestCards::AVS_VISA_5, "NOT_CHECKED", "MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED, "I", "M", "N"], + [GpApiAvsCheckTestCards::AVS_VISA_6, "NOT_CHECKED", "NOT_MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED, "I", "N", "M"], + [GpApiAvsCheckTestCards::AVS_VISA_7, "NOT_CHECKED", "NOT_MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED, "I", "N", "N"], + [GpApiAvsCheckTestCards::AVS_VISA_8, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED, "U", "U", "U"], + [GpApiAvsCheckTestCards::AVS_VISA_9, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED, "U", "I", "I"], + [GpApiAvsCheckTestCards::AVS_VISA_10, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED, "U", "P", "P"], + [GpApiAvsCheckTestCards::AVS_VISA_11, "NOT_CHECKED", "MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED, "U", "M", "M"], + [GpApiAvsCheckTestCards::AVS_VISA_12, "NOT_CHECKED", "MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED, "U", "M", "N"], + [GpApiAvsCheckTestCards::AVS_VISA_13, "NOT_CHECKED", "NOT_MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED, "U", "N", "M"], + [GpApiAvsCheckTestCards::AVS_VISA_14, "NOT_CHECKED", "NOT_MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED, "U", "N", "N"] ]; } diff --git a/test/Integration/Gateways/GpEcomConnector/RecurringTest.php b/test/Integration/Gateways/GpEcomConnector/RecurringTest.php index bc321a8f..d60bf750 100644 --- a/test/Integration/Gateways/GpEcomConnector/RecurringTest.php +++ b/test/Integration/Gateways/GpEcomConnector/RecurringTest.php @@ -14,6 +14,7 @@ use GlobalPayments\Api\Entities\Exceptions\GatewayException; use GlobalPayments\Api\Entities\Reporting\SearchCriteria; use GlobalPayments\Api\Entities\Schedule; +use GlobalPayments\Api\Entities\StoredCredential; use GlobalPayments\Api\PaymentMethods\CreditCardData; use GlobalPayments\Api\PaymentMethods\RecurringPaymentMethod; use GlobalPayments\Api\ServiceConfigs\Gateways\GpEcomConfig; @@ -151,6 +152,35 @@ public function testcardStorageStoreCard() } } + /* 09.01 Card Storage Store Card with Stored Credential */ + /* Request Type: card-new */ + + public function testcardStorageStoreCardWithStoredCredential() + { + $card = new CreditCardData(); + $card->number = "4012001037141112"; + $card->expMonth = 10; + $card->expYear = TestCards::validCardExpYear(); + $card->cvn = '123'; + $card->cardHolderName = 'James Mason'; + + $storedCredential = new StoredCredential(); + $storedCredential->schemeId = 'YOUR_DESIRED_SCHEME_ID'; + $paymentId = sprintf("%s-RealexStoredCredential-%s", (new \DateTime())->format("Ymd"), 'Credit'); + try { + $paymentMethod = $this->newCustomer + ->addPaymentMethod($paymentId, $card, $storedCredential) + ->create(); + + $this->assertNotNull($paymentMethod); + $this->assertEquals("Successful", $paymentMethod->responseMessage); + } catch (GatewayException $exc) { + if ($exc->responseCode != '501' && $exc->responseCode != '520') { + throw $exc; + } + } + } + /* 10. Card Storage Charge Card */ /* Request Type: receipt-in */ @@ -341,6 +371,28 @@ public function testcardStorageUpdateCard() $this->assertEquals("00", $response->responseCode); } + /* 17.01 Card Storage UpdateCard with StoredCredential */ + /* Request Type: card-update-card */ + + public function testcardStorageUpdateCardWithStoredCredential() + { + $paymentMethod = new RecurringPaymentMethod($this->getCustomerId(), $this->getPaymentId("Credit")); + $storedCredential = new StoredCredential(); + $storedCredential->schemeId = 'YOUR_DESIRED_SCHEME_ID'; + $paymentMethod->storedCredential = $storedCredential; + + $paymentMethod->paymentMethod = new CreditCardData(); + $paymentMethod->paymentMethod->number = "5425230000004415"; + $paymentMethod->paymentMethod->expMonth = 10; + $paymentMethod->paymentMethod->expYear = TestCards::validCardExpYear(); + $paymentMethod->paymentMethod->cardHolderName = "Philip Marlowe"; + + $response = $paymentMethod->SaveChanges(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + /* 18. Card Storage Verify Card */ /* Request Type: receipt-in-otb */