Skip to content

Commit

Permalink
Merge pull request #47 from Judopay/Add3dsModelAndPut-JR-3516
Browse files Browse the repository at this point in the history
Add3dsModelAndPut-JR-3516
  • Loading branch information
chrisurun authored Jan 30, 2020
2 parents de6cc93 + 9e8839d commit fc4ae48
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 3 deletions.
22 changes: 22 additions & 0 deletions src/Judopay/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,28 @@ public function create()
return $this->getResponseArray($response);
}

/**
* Update an existing record
* @return array API response
**/
public function update()
{
$this->checkApiMethodIsSupported(__FUNCTION__);
$this->checkJudoId();
$this->checkRequiredAttributes($this->attributeValues);

// PUT needs to be done on a specific transaction
$requestPath = $this->resourcePath . "/" . $this->attributeValues["ReceiptId"];

$response = $this->request->put(
$requestPath,
$this->attributeValues
);

return $this->getResponseArray($response);
}


/**
* Validate card payment details without making a payment
* @return array $response
Expand Down
38 changes: 38 additions & 0 deletions src/Judopay/Model/CompleteThreeD.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
namespace Judopay\Model;

use Judopay\DataType;
use Judopay\Model;

class CompleteThreeD extends Model
{
protected $resourcePath = 'transactions';
protected $validApiMethods = array('create', 'update');

protected $attributes
= array(
'ReceiptId' => DataType::TYPE_STRING,
'MD' => DataType::TYPE_STRING,
'PaRes' => DataType::TYPE_STRING
);

protected $requiredAttributes
= array(
'ReceiptId',
'MD',
'PaRes'
);

public function complete3DSecure()
{
$this->checkApiMethodIsSupported(__FUNCTION__);
$this->checkJudoId();
$this->checkRequiredAttributes($this->attributeValues);
$this->resourcePath .= '/' . $this->attributeValues['ReceiptId'];
$response = $this->request->put(
$this->resourcePath,
$this->attributeValues
);
return $this->getResponseArray($response);
}
}
28 changes: 26 additions & 2 deletions src/Judopay/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public function getHeaders()
public function get($resourcePath)
{
$headers = $this->getHeaders();

try {
$guzzleResponse = $this->client->request(
'GET',
Expand All @@ -76,7 +75,6 @@ public function get($resourcePath)
public function post($resourcePath, $data)
{
$headers = $this->getHeaders();

try {
$guzzleResponse = $this->client->request(
'POST',
Expand All @@ -95,6 +93,32 @@ public function post($resourcePath, $data)
return $guzzleResponse;
}

/**
* Make a PUT request to the specified resource path and the provided data
* @param string $resourcePath
* @param array $data
* @return Response
*/
public function put($resourcePath, $data)
{
$headers = $this->getHeaders();
try {
$guzzleResponse = $this->client->request(
'PUT',
$resourcePath,
[
'headers' => $headers,
'json' => $data
]
);
} catch (BadResponseException $e) {
throw ApiException::factory($e);
} catch (GuzzleException $e) {
throw new ApiException($e->getMessage());
}
return $guzzleResponse;
}

/*
* Gets 'Authorization' header value
*/
Expand Down
10 changes: 10 additions & 0 deletions tests/Builders/CardPaymentBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class CardPaymentBuilder extends AbstractModelBuilder
{
const VALID_VISA_CARD = 0;
const INVALID_VISA_CARD = 1;
const THREEDS_VISA_CARD = 2;

protected $type = self::VALID_VISA_CARD;

public function __construct($amount = 1.02)
Expand Down Expand Up @@ -44,6 +46,14 @@ public function compile()
'cv2' => 125,
);
break;

case self::THREEDS_VISA_CARD:
$this->attributeValues += array(
'cardNumber' => '4976350000006891',
'expiryDate' => '12/21',
'cv2' => 341,
);
break;
}

return $this;
Expand Down
7 changes: 7 additions & 0 deletions tests/Builders/CompleteThreeDBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Tests\Builders;

class CompleteThreeDBuilder extends CardPaymentBuilder
{
}
10 changes: 9 additions & 1 deletion tests/Helpers/AssertionHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Tests\Helpers;

use Judopay\Exception\ApiException;
use PHPUnit_Framework_Assert as Assert;

class AssertionHelper
Expand All @@ -13,7 +14,7 @@ public static function assertApiExceptionWithModelErrors(
$statusCode = 400,
$errorCategory = 2
) {
/** @var \Judopay\Exception\ApiException $apiException */
/** @var ApiException $apiException */
Assert::assertInstanceOf(
'\Judopay\Exception\ApiException',
$apiException
Expand Down Expand Up @@ -42,4 +43,11 @@ public static function assertDeclinedPayment($result)
Assert::assertEquals('Declined', $result['result']);
Assert::assertGreaterThan(0, $result['receiptId']);
}

public static function assertRequiresThreeDSecure($result)
{
Assert::assertNotNull($result);
Assert::assertEquals('Requires 3D Secure', $result['result']);
Assert::assertGreaterThan(0, $result['receiptId']);
}
}
77 changes: 77 additions & 0 deletions tests/ThreeDSecureTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace Tests;

use PHPUnit\Framework\TestCase;
use Tests\Builders\CardPaymentBuilder;
use Tests\Builders\CompleteThreeDBuilder;
use Tests\Helpers\AssertionHelper;
use Tests\Helpers\ConfigHelper;
use Judopay\Exception\ApiException as ApiException;

class ThreeDSecureTest extends TestCase
{
protected function getBuilder()
{
return new CompleteThreeDBuilder();
}

protected function getPaymentBuilder()
{
return new CardPaymentBuilder();
}

public function testUpdateThreeDSecurePayment()
{
// Build a regular payment
$cardPayment = $this->getPaymentBuilder()
->setType(CardPaymentBuilder::THREEDS_VISA_CARD)
->build(ConfigHelper::getConfig());

// Process the payment
$paymentResult = $cardPayment->create();

// We should have a 3DS required message
AssertionHelper::assertRequiresThreeDSecure($paymentResult);

// Build the 3DS request
$threeDSecureCompletion = $this->getBuilder()
->setAttribute('ReceiptId', $paymentResult['receiptId'])
->setAttribute('MD', $paymentResult['md'])
->setAttribute('PaRes', "paResReturnedByTheAcsUrl") // The ACS URL needs to be visited by the consumer
->build(ConfigHelper::getConfig());

// Update the existing payment with a PUT
$threeDSecureResult = $threeDSecureCompletion->update();

// The payment has a successful status
AssertionHelper::assertSuccessfulPayment($threeDSecureResult);
}

public function testUpdateWrongThreeDSecurePayment()
{
// Build the 3DS request for a Receipt not linked to this account
$threeDSecureCompletion = $this->getBuilder()
->setAttribute('ReceiptId', "536586810336354304")
->setAttribute('MD', "200120164510412101100951")
->setAttribute('PaRes', "paResReturnedByTheAcsUrl") // The ACS URL needs to be visited by the consumer
->build(ConfigHelper::getConfig());

try {
// Update the existing payment with a PUT
$threeDSecureResult = $threeDSecureCompletion->update();
} catch (\Exception $e) {
AssertionHelper::assertApiExceptionWithModelErrors(
$e,
0,
72,
409,
ApiException::CATEGORY_PROCESSING
);

return;
}

$this->fail('An expected ApiException has not been raised.');
}
}

0 comments on commit fc4ae48

Please sign in to comment.