Skip to content

Commit 152bbd9

Browse files
committed
MAGETWO-95512: [2.3] Unable to create invoice for an order via Braintree PayPal
- Added an exception if Payment Token is not available
1 parent 80469a6 commit 152bbd9

File tree

4 files changed

+72
-31
lines changed

4 files changed

+72
-31
lines changed

app/code/Magento/Braintree/Gateway/Request/PayPal/VaultDataBuilder.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public function build(array $buildSubject)
4949

5050
$payment = $paymentDO->getPayment();
5151
$data = $payment->getAdditionalInformation();
52+
// the payment token could be stored only if a customer checks the Vault flow on storefront
53+
// see https://developers.braintreepayments.com/guides/paypal/vault/javascript/v2#invoking-the-vault-flow
5254
if (!empty($data[VaultConfigProvider::IS_ACTIVE_CODE])) {
5355
$result[self::$optionsKey] = [
5456
self::$storeInVaultOnSuccess => true

app/code/Magento/Braintree/Gateway/Request/VaultCaptureDataBuilder.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
namespace Magento\Braintree\Gateway\Request;
77

88
use Magento\Braintree\Gateway\SubjectReader;
9+
use Magento\Framework\Exception\LocalizedException;
10+
use Magento\Payment\Gateway\Command\CommandException;
911
use Magento\Payment\Gateway\Request\BuilderInterface;
1012
use Magento\Payment\Helper\Formatter;
1113

@@ -41,6 +43,9 @@ public function build(array $buildSubject)
4143
$payment = $paymentDO->getPayment();
4244
$extensionAttributes = $payment->getExtensionAttributes();
4345
$paymentToken = $extensionAttributes->getVaultPaymentToken();
46+
if ($paymentToken === null) {
47+
throw new CommandException(__('The Payment Token is not available to perform the request.'));
48+
}
4449
return [
4550
'amount' => $this->formatPrice($this->subjectReader->readAmount($buildSubject)),
4651
'paymentMethodToken' => $paymentToken->getGatewayToken()

app/code/Magento/Braintree/Test/Unit/Gateway/Request/VaultCaptureDataBuilderTest.php

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Braintree\Test\Unit\Gateway\Request;
79

8-
use Magento\Braintree\Gateway\SubjectReader;
910
use Magento\Braintree\Gateway\Request\VaultCaptureDataBuilder;
11+
use Magento\Braintree\Gateway\SubjectReader;
1012
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
1113
use Magento\Sales\Api\Data\OrderPaymentExtension;
1214
use Magento\Sales\Model\Order\Payment;
@@ -26,47 +28,46 @@ class VaultCaptureDataBuilderTest extends \PHPUnit\Framework\TestCase
2628
/**
2729
* @var PaymentDataObjectInterface|MockObject
2830
*/
29-
private $paymentDOMock;
31+
private $paymentDO;
3032

3133
/**
3234
* @var Payment|MockObject
3335
*/
34-
private $paymentMock;
36+
private $payment;
3537

3638
/**
37-
* @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
39+
* @var SubjectReader|MockObject
3840
*/
39-
private $subjectReaderMock;
41+
private $subjectReader;
4042

4143
/**
4244
* @inheritdoc
4345
*/
44-
protected function setUp()
46+
protected function setUp(): void
4547
{
46-
$this->paymentDOMock = $this->createMock(PaymentDataObjectInterface::class);
47-
$this->paymentMock = $this->getMockBuilder(Payment::class)
48+
$this->paymentDO = $this->createMock(PaymentDataObjectInterface::class);
49+
$this->payment = $this->getMockBuilder(Payment::class)
4850
->disableOriginalConstructor()
4951
->getMock();
50-
$this->paymentDOMock->expects(static::once())
51-
->method('getPayment')
52-
->willReturn($this->paymentMock);
52+
$this->paymentDO->method('getPayment')
53+
->willReturn($this->payment);
5354

54-
$this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
55+
$this->subjectReader = $this->getMockBuilder(SubjectReader::class)
5556
->disableOriginalConstructor()
5657
->getMock();
5758

58-
$this->builder = new VaultCaptureDataBuilder($this->subjectReaderMock);
59+
$this->builder = new VaultCaptureDataBuilder($this->subjectReader);
5960
}
6061

6162
/**
62-
* \Magento\Braintree\Gateway\Request\VaultCaptureDataBuilder::build
63+
* Checks the result after builder execution.
6364
*/
64-
public function testBuild()
65+
public function testBuild(): void
6566
{
6667
$amount = 30.00;
6768
$token = '5tfm4c';
6869
$buildSubject = [
69-
'payment' => $this->paymentDOMock,
70+
'payment' => $this->paymentDO,
7071
'amount' => $amount,
7172
];
7273

@@ -75,36 +76,68 @@ public function testBuild()
7576
'paymentMethodToken' => $token,
7677
];
7778

78-
$this->subjectReaderMock->expects(self::once())
79-
->method('readPayment')
79+
$this->subjectReader->method('readPayment')
8080
->with($buildSubject)
81-
->willReturn($this->paymentDOMock);
82-
$this->subjectReaderMock->expects(self::once())
83-
->method('readAmount')
81+
->willReturn($this->paymentDO);
82+
$this->subjectReader->method('readAmount')
8483
->with($buildSubject)
8584
->willReturn($amount);
8685

87-
$paymentExtensionMock = $this->getMockBuilder(OrderPaymentExtension::class)
86+
/** @var OrderPaymentExtension|MockObject $paymentExtension */
87+
$paymentExtension = $this->getMockBuilder(OrderPaymentExtension::class)
8888
->setMethods(['getVaultPaymentToken'])
8989
->disableOriginalConstructor()
9090
->getMockForAbstractClass();
9191

92-
$paymentTokenMock = $this->getMockBuilder(PaymentToken::class)
92+
/** @var PaymentToken|MockObject $paymentToken */
93+
$paymentToken = $this->getMockBuilder(PaymentToken::class)
9394
->disableOriginalConstructor()
9495
->getMock();
9596

96-
$paymentExtensionMock->expects(static::once())
97-
->method('getVaultPaymentToken')
98-
->willReturn($paymentTokenMock);
99-
$this->paymentMock->expects(static::once())
100-
->method('getExtensionAttributes')
101-
->willReturn($paymentExtensionMock);
97+
$paymentExtension->method('getVaultPaymentToken')
98+
->willReturn($paymentToken);
99+
$this->payment->method('getExtensionAttributes')
100+
->willReturn($paymentExtension);
102101

103-
$paymentTokenMock->expects(static::once())
104-
->method('getGatewayToken')
102+
$paymentToken->method('getGatewayToken')
105103
->willReturn($token);
106104

107105
$result = $this->builder->build($buildSubject);
108106
self::assertEquals($expected, $result);
109107
}
108+
109+
/**
110+
* Checks a builder execution if Payment Token doesn't exist.
111+
*
112+
* @expectedException \Magento\Payment\Gateway\Command\CommandException
113+
* @expectedExceptionMessage The Payment Token is not available to perform the request.
114+
*/
115+
public function testBuildWithoutPaymentToken(): void
116+
{
117+
$amount = 30.00;
118+
$buildSubject = [
119+
'payment' => $this->paymentDO,
120+
'amount' => $amount,
121+
];
122+
123+
$this->subjectReader->method('readPayment')
124+
->with($buildSubject)
125+
->willReturn($this->paymentDO);
126+
$this->subjectReader->method('readAmount')
127+
->with($buildSubject)
128+
->willReturn($amount);
129+
130+
/** @var OrderPaymentExtension|MockObject $paymentExtension */
131+
$paymentExtension = $this->getMockBuilder(OrderPaymentExtension::class)
132+
->setMethods(['getVaultPaymentToken'])
133+
->disableOriginalConstructor()
134+
->getMockForAbstractClass();
135+
136+
$this->payment->method('getExtensionAttributes')
137+
->willReturn($paymentExtension);
138+
$paymentExtension->method('getVaultPaymentToken')
139+
->willReturn(null);
140+
141+
$this->builder->build($buildSubject);
142+
}
110143
}

app/code/Magento/Braintree/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,4 @@ Currency,Currency
192192
"Too many concurrent attempts to refund this transaction. Try again later.","Too many concurrent attempts to refund this transaction. Try again later."
193193
"Too many concurrent attempts to void this transaction. Try again later.","Too many concurrent attempts to void this transaction. Try again later."
194194
"Braintree Settlement","Braintree Settlement"
195+
"The Payment Token is not available to perform the request.","The Payment Token is not available to perform the request."

0 commit comments

Comments
 (0)