Skip to content

Commit

Permalink
SP-1106 - redirect user to checkout success page on invoice close and…
Browse files Browse the repository at this point in the history
… show pay button if invoice isn't paid
swlodarski committed Dec 5, 2024
1 parent afbd9fc commit e33a64b
Showing 16 changed files with 647 additions and 206 deletions.
140 changes: 140 additions & 0 deletions Block/Checkout/Onepage/Success/PayButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?php
declare(strict_types=1);

namespace Bitpay\BPCheckout\Block\Checkout\Onepage\Success;

use Bitpay\BPCheckout\Model\Client;
use Bitpay\BPCheckout\Model\Config;
use Bitpay\BPCheckout\Model\TransactionRepository;
use BitPaySDK\Model\Invoice\Invoice;
use Magento\Checkout\Block\Onepage\Success as MagentoSuccess;
use Magento\Checkout\Model\Session;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Config as OrderConfig;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\UrlInterface;
use Magento\Framework\View\Element\Template\Context;

class PayButton extends MagentoSuccess
{
/**
* @var TransactionRepository
*/
protected TransactionRepository $transactionRepository;

/**
* @var Client
*/
protected Client $client;

/**
* @var Config
*/
protected Config $config;

/**
* @var UrlInterface
*/
protected UrlInterface $url;

/**
* @var Invoice|null
*/
protected ?Invoice $invoice = null;

/**
* @param Context $context
* @param Session $checkoutSession
* @param OrderConfig $orderConfig
* @param HttpContext $httpContext
* @param TransactionRepository $transactionRepository
* @param Client $client
* @param Config $config
* @param UrlInterface $url
* @param array $data
*/
public function __construct(
Context $context,
Session $checkoutSession,
OrderConfig $orderConfig,
HttpContext $httpContext,
TransactionRepository $transactionRepository,
Client $client,
Config $config,
UrlInterface $url,
array $data = []
) {
parent::__construct($context, $checkoutSession, $orderConfig, $httpContext, $data);

$this->transactionRepository = $transactionRepository;
$this->client = $client;
$this->config = $config;
$this->url = $url;
}

/**
* Returns true when Pay button be displayed
*
* @return bool
*/
public function canViewPayButton(): bool
{
if ($this->config->getBitpayCheckoutSuccess() === 'standard'
&& $this->config->getBitpayInvoiceCloseHandling() === 'keep_order') {
$invoice = $this->getBitpayInvoice();

return $invoice !== null;
}

return false;
}

/**
* Returns button url
*
* @return string
*/
public function getButtonUrl(): string
{
return $this->url->getUrl('bpcheckout/invoice/pay', [
'_query' => [
'order_id' => $this->getOrder()->getId(), 'invoice_id' => $this->getBitpayInvoice()->getId()
]
]);
}

/**
* Get BitPay invoice by last order
*
* @return Invoice|null
*/
protected function getBitpayInvoice(): ?Invoice
{
if (!$this->invoice) {
$order = $this->getOrder();
if ($order->canInvoice()) {
$transactions = $this->transactionRepository
->findByOrderIdAndTransactionStatus($order->getIncrementId(), 'new');
if (!empty($transactions)) {
$lastTransaction = array_pop($transactions);
$client = $this->client->initialize();
$invoice = $client->getInvoice($lastTransaction['transaction_id']);

$this->invoice = $invoice;
}
}
}

return $this->invoice;
}

/**
* Get order instance based on last order ID
*
* @return Order
*/
protected function getOrder(): Order
{
return $this->_checkoutSession->getLastRealOrder();
}
}
139 changes: 139 additions & 0 deletions Controller/Invoice/Pay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php
declare(strict_types=1);

namespace Bitpay\BPCheckout\Controller\Invoice;

use Bitpay\BPCheckout\Model\Client;
use Bitpay\BPCheckout\Model\Config;
use Bitpay\BPCheckout\Model\TransactionRepository;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Controller\Result\RedirectFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Message\Manager;
use Magento\Framework\Phrase;
use Magento\Sales\Api\OrderRepositoryInterface;

class Pay implements HttpGetActionInterface
{
/**
* @var RequestInterface
*/
private $request;

/**
* @var Manager
*/
protected Manager $messageManager;

/**
* @var RedirectFactory
*/
protected $resultRedirectFactory;

/**
* @var OrderRepositoryInterface
*/
protected $orderRepository;

/**
* @var TransactionRepository
*/
protected TransactionRepository $transactionRepository;

/**
* @var Session
*/
protected Session $checkoutSession;

/**
* @var Client
*/
protected Client $client;

/**
* @var Config
*/
protected Config $config;

/**
* @param RequestInterface $request
* @param Manager $messageManager
* @param RedirectFactory $resultRedirectFactory
* @param OrderRepositoryInterface $orderRepository
* @param TransactionRepository $transactionRepository
* @param Session $checkoutSession
* @param Client $client
* @param Config $config
*/
public function __construct(
RequestInterface $request,
Manager $messageManager,
RedirectFactory $resultRedirectFactory,
OrderRepositoryInterface $orderRepository,
TransactionRepository $transactionRepository,
Session $checkoutSession,
Client $client,
Config $config,
) {
$this->request = $request;
$this->messageManager = $messageManager;
$this->resultRedirectFactory = $resultRedirectFactory;
$this->orderRepository = $orderRepository;
$this->transactionRepository = $transactionRepository;
$this->checkoutSession = $checkoutSession;
$this->client = $client;
$this->config = $config;
}

/**
* Get checkout customer info
*
* @return ResultInterface
*/
public function execute()
{
$orderId = $this->request->getParam('order_id', null);
$invoiceId = $this->request->getParam('invoice_id', null);

try {
if (!$orderId || !$invoiceId || $this->config->getBitpayCheckoutSuccess() !== 'standard'
|| $this->config->getBitpayInvoiceCloseHandling() !== 'keep_order') {
throw new LocalizedException(new Phrase('Invalid request!'));
}

/** @var \Magento\Sales\Model\Order $order */
$order = $this->orderRepository->get($orderId);
if (!$order->canInvoice()) {
throw new LocalizedException(new Phrase('Order already paid!'));
}

$client = $this->client->initialize();
$invoice = $client->getInvoice($invoiceId);
$invoiceStatus = $invoice->getStatus();
if ($invoiceStatus === 'paid' || $invoiceStatus === 'confirmed' || $invoiceStatus === 'complete') {
throw new LocalizedException(new Phrase('The invoice has already been paid!'));
} elseif ($invoiceStatus === 'expired') {
throw new LocalizedException(new Phrase('The invoice has expired!'));
} elseif ($invoiceStatus !== 'new') {
throw new LocalizedException(new Phrase('The invoice is invalid or expired!'));
}

$this->checkoutSession->setLastSuccessQuoteId($order->getQuoteId())
->setLastQuoteId($order->getQuoteId())
->setLastOrderId($order->getEntityId());

return $this->resultRedirectFactory->create()->setUrl($invoice->getUrl());
} catch (\Exception $exception) {
$this->messageManager->addErrorMessage($exception->getMessage());

return $this->resultRedirectFactory->create()->setPath('checkout/cart');
} catch (\Error $error) {
$this->messageManager->addErrorMessage('Invalid request!');

return $this->resultRedirectFactory->create()->setPath('checkout/cart');
}
}
}
55 changes: 55 additions & 0 deletions Helper/ReturnHash.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);

namespace Bitpay\BPCheckout\Helper;

use Magento\Framework\App\Helper\Context;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Sales\Api\Data\OrderInterface;

class ReturnHash extends AbstractHelper
{
/**
* @var EncryptorInterface
*/
protected EncryptorInterface $encryptor;

/**
* @param Context $context
* @param EncryptorInterface $encryptor
*/
public function __construct(
Context $context,
EncryptorInterface $encryptor
) {
$this->encryptor = $encryptor;

parent::__construct($context);
}

/**
* Generates return hash
*
* @param OrderInterface $order
* @return string
*/
public function generate(OrderInterface $order): string
{
return $this->encryptor->hash(
"{$order->getIncrementId()}:{$order->getCustomerEmail()}:{$order->getProtectCode()}"
);
}

/**
* Checks if returnHash is valid
*
* @param string $returnHashToCheck
* @param OrderInterface $order
* @return bool
*/
public function isValid(string $returnHashToCheck, OrderInterface $order): bool
{
return $returnHashToCheck === $this->generate($order);
}
}
15 changes: 9 additions & 6 deletions Model/BPRedirect.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Bitpay\BPCheckout\Model;

use Bitpay\BPCheckout\Helper\ReturnHash;
use Bitpay\BPCheckout\Logger\Logger;
use Magento\Checkout\Model\Session;
use Magento\Framework\DataObject;
@@ -35,7 +36,7 @@ class BPRedirect
protected Client $client;
protected OrderRepository $orderRepository;
protected BitpayInvoiceRepository $bitpayInvoiceRepository;
protected EncryptorInterface $encryptor;
protected ReturnHash $returnHashHelper;

/**
* @param Session $checkoutSession
@@ -51,7 +52,7 @@ class BPRedirect
* @param Client $client
* @param OrderRepository $orderRepository
* @param BitpayInvoiceRepository $bitpayInvoiceRepository
* @param EncryptorInterface $encryptor
* @param ReturnHash $returnHashHelper
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -68,7 +69,7 @@ public function __construct(
Client $client,
OrderRepository $orderRepository,
BitpayInvoiceRepository $bitpayInvoiceRepository,
EncryptorInterface $encryptor,
ReturnHash $returnHashHelper
) {
$this->checkoutSession = $checkoutSession;
$this->orderInterface = $orderInterface;
@@ -83,7 +84,7 @@ public function __construct(
$this->client = $client;
$this->orderRepository = $orderRepository;
$this->bitpayInvoiceRepository = $bitpayInvoiceRepository;
$this->encryptor = $encryptor;
$this->returnHashHelper = $returnHashHelper;
}

/**
@@ -114,9 +115,10 @@ public function execute(ResultInterface $defaultResult, string $returnId = null)
}

$isStandardCheckoutSuccess = $this->config->getBitpayCheckoutSuccess() === 'standard';
$returnHash = $this->encryptor->hash("$incrementId:{$order->getCustomerEmail()}:{$order->getProtectCode()}");

if ($isStandardCheckoutSuccess && $returnId) {
if ($returnId !== $returnHash) {
$returnHash = $this->returnHashHelper->generate($order);
if (!$this->returnHashHelper->isValid($returnId, $order)) {
$this->checkoutSession->clearHelperData();

return $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
@@ -127,6 +129,7 @@ public function execute(ResultInterface $defaultResult, string $returnId = null)
}

try {
$returnHash = $this->returnHashHelper->generate($order);
$baseUrl = $this->config->getBaseUrl();
$order = $this->setToPendingAndOverrideMagentoStatus($order);
$modal = $this->config->getBitpayUx() === 'modal';
44 changes: 29 additions & 15 deletions Model/IpnManagement.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@

use Bitpay\BPCheckout\Api\IpnManagementInterface;
use Bitpay\BPCheckout\Exception\IPNValidationException;
use Bitpay\BPCheckout\Helper\ReturnHash;
use Bitpay\BPCheckout\Logger\Logger;
use Bitpay\BPCheckout\Model\Ipn\BPCItem;
use Bitpay\BPCheckout\Model\Ipn\Validator;
@@ -41,6 +42,7 @@ class IpnManagement implements IpnManagementInterface
protected Request $request;
protected Client $client;
protected Response $response;
protected ReturnHash $returnHashHelper;

/**
* @param ResponseFactory $responseFactory
@@ -57,6 +59,7 @@ class IpnManagement implements IpnManagementInterface
* @param Request $request
* @param Client $client
* @param Response $response
* @param ReturnHash $returnHashHelper
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -73,7 +76,8 @@ public function __construct(
Invoice $invoice,
Request $request,
Client $client,
Response $response
Response $response,
ReturnHash $returnHashHelper
) {
$this->coreRegistry = $registry;
$this->responseFactory = $responseFactory;
@@ -89,6 +93,7 @@ public function __construct(
$this->request = $request;
$this->client = $client;
$this->response = $response;
$this->returnHashHelper = $returnHashHelper;
}

/**
@@ -104,21 +109,30 @@ public function postClose()
try {
$orderID = $this->request->getParam('orderID', null);
$order = $this->orderInterface->loadByIncrementId($orderID);
$orderData = $order->getData();
$quoteID = $orderData['quote_id'];
$quote = $this->quoteFactory->create()->loadByIdWithoutStore($quoteID);
if ($quote->getId()) {
$quote->setIsActive(1)->setReservedOrderId(null)->save();
$this->checkoutSession->replaceQuote($quote);
$invoiceCloseHandling = $this->config->getBitpayInvoiceCloseHandling();
if ($invoiceCloseHandling !== 'keep_order') {
$this->coreRegistry->register('isSecureArea', 'true');
$order->delete();
$this->coreRegistry->unregister('isSecureArea');
$invoiceCloseHandling = $this->config->getBitpayInvoiceCloseHandling();
if ($this->config->getBitpayCheckoutSuccess() === 'standard' && $invoiceCloseHandling === 'keep_order') {
$this->checkoutSession->setLastSuccessQuoteId($order->getQuoteId())
->setLastQuoteId($order->getQuoteId())
->setLastOrderId($order->getEntityId());

$returnHash = $this->returnHashHelper->generate($order);
$redirectUrl = $this->url->getUrl(
'checkout/onepage/success',
['_query' => ['return_id' => $returnHash]]
);
} else {
$orderData = $order->getData();
$quoteID = $orderData['quote_id'];
$quote = $this->quoteFactory->create()->loadByIdWithoutStore($quoteID);
if ($quote->getId()) {
$quote->setIsActive(1)->setReservedOrderId(null)->save();
$this->checkoutSession->replaceQuote($quote);
if ($invoiceCloseHandling !== 'keep_order') {
$this->coreRegistry->register('isSecureArea', 'true');
$order->delete();
$this->coreRegistry->unregister('isSecureArea');
}
}
$response->setRedirect($redirectUrl)->sendResponse();

return;
}

$response->setRedirect($redirectUrl)->sendResponse();
26 changes: 26 additions & 0 deletions Model/ResourceModel/Transaction.php
Original file line number Diff line number Diff line change
@@ -63,6 +63,32 @@ public function findBy(string $orderId, string $orderInvoiceId): ?array
return $row;
}

/**
* Find transaction by order_id and transaction_status
*
* @param string $orderId
* @param string $transactionStatus
* @return array|null
*/
public function findByOrderIdAndTransactionStatus(string $orderId, string $transactionStatus): ?array
{
$connection = $this->getConnection();
$tableName = $connection->getTableName(self::TABLE_NAME);

$sql = $connection->select()
->from($tableName)
->where('order_id = ?', $orderId)
->where('transaction_status = ?', $transactionStatus);

$row = $connection->fetchAll($sql);

if (!$row) {
return null;
}

return $row;
}

/**
* Update transaction
*
12 changes: 12 additions & 0 deletions Model/TransactionRepository.php
Original file line number Diff line number Diff line change
@@ -40,6 +40,18 @@ public function findBy(string $orderId, string $orderInvoiceId): ?array
return $this->resourceTransaction->findBy($orderId, $orderInvoiceId);
}

/**
* Find Transactions by order_id and transaction_status
*
* @param string $orderId
* @param string $transactionStatus
* @return array|null
*/
public function findByOrderIdAndTransactionStatus(string $orderId, string $transactionStatus): ?array
{
return $this->resourceTransaction->findByOrderIdAndTransactionStatus($orderId, $transactionStatus);
}

/**
* Update Transaction
*
20 changes: 16 additions & 4 deletions Test/Integration/Model/BPRedirectTest.php
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@

namespace Bitpay\BPCheckout\Test\Integration\Model;

use Bitpay\BPCheckout\Helper\ReturnHash;
use Bitpay\BPCheckout\Model\BitpayInvoiceRepository;
use Bitpay\BPCheckout\Model\BPRedirect;
use Bitpay\BPCheckout\Model\Client;
@@ -97,8 +98,9 @@ class BPRedirectTest extends TestCase
* @var ResultFactory $resultFactory
*/
private $resultFactory;

/**
* @var Client $client
* @var Client|MockObject $client
*/
private $client;

@@ -112,6 +114,11 @@ class BPRedirectTest extends TestCase
*/
private $bitpayInvoiceRepository;

/**
* @var ReturnHash $returnHash
*/
private $returnHash;

public function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
@@ -128,6 +135,7 @@ public function setUp(): void
$this->client = $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock();
$this->orderRepository = $this->objectManager->get(OrderRepository::class);
$this->bitpayInvoiceRepository = $this->objectManager->get(BitpayInvoiceRepository::class);
$this->returnHash = $this->objectManager->get(ReturnHash::class);

$this->bpRedirect = new BPRedirect(
$this->checkoutSession,
@@ -142,7 +150,8 @@ public function setUp(): void
$this->resultFactory,
$this->client,
$this->orderRepository,
$this->bitpayInvoiceRepository
$this->bitpayInvoiceRepository,
$this->returnHash
);
}

@@ -178,7 +187,8 @@ public function testExecute(): void
$this->invoice->expects($this->once())->method('BPCCreateInvoice')
->willReturn($invoice);

$this->bpRedirect->execute();
$defaultResult = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE);
$this->bpRedirect->execute($defaultResult);
$customerInfo = $this->checkoutSession->getCustomerInfo();

$this->assertEquals('customer@example.com', $customerInfo['email']);
@@ -218,8 +228,10 @@ public function testExecuteException(): void

$this->invoice->expects($this->once())->method('BPCCreateInvoice')
->willThrowException(new LocalizedException(new Phrase('Invalid token')));

$defaultResult = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE);

$this->bpRedirect->execute();
$this->bpRedirect->execute($defaultResult);
$this->assertEquals(
'We are unable to place your Order at this time',
$this->messageManager->getMessages()->getLastAddedMessage()->getText()
17 changes: 12 additions & 5 deletions Test/Integration/Model/IpnManagementTest.php
Original file line number Diff line number Diff line change
@@ -9,9 +9,8 @@
use Bitpay\BPCheckout\Model\TransactionRepository;
use BitPaySDK\Model\Invoice\Buyer;
use Magento\Framework\ObjectManagerInterface;
use Bitpay\BPCheckout\Api\IpnManagementInterface;
use Bitpay\BPCheckout\Helper\ReturnHash;
use Bitpay\BPCheckout\Logger\Logger;
use Bitpay\BPCheckout\Model\Ipn\BPCItem;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\ResponseFactory;
use Magento\Framework\DataObject;
@@ -42,7 +41,7 @@ class IpnManagementTest extends TestCase
private $responseFactory;

/**
* @var OrderInterface $url
* @var UrlInterface $url
*/
private $url;

@@ -87,7 +86,7 @@ class IpnManagementTest extends TestCase
private $transactionRepository;

/**
* @var Invoice|\PHPUnit\Framework\MockObject\MockObject $invoice
* @var Invoice|MockObject $invoice
*/
private $invoice;

@@ -111,6 +110,11 @@ class IpnManagementTest extends TestCase
*/
private $response;

/**
* @var ReturnHash $returnHash
*/
private ReturnHash $returnHash;

public function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
@@ -128,6 +132,8 @@ public function setUp(): void
$this->request = $this->objectManager->get(Request::class);
$this->client = $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock();
$this->response = $this->objectManager->get(Response::class);
$this->returnHash = $this->objectManager->get(ReturnHash::class);

$this->ipnManagement = new IpnManagement(
$this->responseFactory,
$this->url,
@@ -142,7 +148,8 @@ public function setUp(): void
$this->invoice,
$this->request,
$this->client,
$this->response
$this->response,
$this->returnHash
);
}

5 changes: 5 additions & 0 deletions Test/Integration/Model/ResourceModel/TransactionTest.php
Original file line number Diff line number Diff line change
@@ -20,6 +20,11 @@ class TransactionTest extends TestCase
*/
private $transactionResource;

/**
* @var Context $context
*/
private $context;

public function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
41 changes: 28 additions & 13 deletions Test/Unit/Model/BPRedirectTest.php
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@

namespace Bitpay\BPCheckout\Test\Unit\Model;

use Bitpay\BPCheckout\Helper\ReturnHash;
use Bitpay\BPCheckout\Model\BitpayInvoiceRepository;
use Bitpay\BPCheckout\Model\BPRedirect;
use Bitpay\BPCheckout\Logger\Logger;
@@ -16,11 +17,8 @@
use Magento\Framework\Message\Manager;
use Magento\Framework\Registry;
use Magento\Framework\UrlInterface;
use Magento\Quote\Api\Data\PaymentInterface;
use Magento\Sales\Api\Data\OrderInterface;
use \Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Sales\Model\Order;
use Magento\Payment\Model\MethodInterface;
use Magento\Sales\Model\OrderRepository;
@@ -39,7 +37,7 @@ class BPRedirectTest extends TestCase
private $bpRedirect;

/**
* @var Seesion|MockObject $checkoutSession
* @var Session|MockObject $checkoutSession
*/
private $checkoutSession;

@@ -64,12 +62,12 @@ class BPRedirectTest extends TestCase
private $client;

/**
* @var OrderRepository $orderRepository
* @var OrderRepository|MockObject $orderRepository
*/
private $orderRepository;

/**
* @var BitpayInvoiceRepository $bitpayInvoiceRepository
* @var BitpayInvoiceRepository|MockObject $bitpayInvoiceRepository
*/
private $bitpayInvoiceRepository;

@@ -104,9 +102,9 @@ class BPRedirectTest extends TestCase
private $resultFactory;

/**
* @var EncryptorInterface|MockObject $encryptor
* @var ReturnHash|MockObject $returnHash
*/
private $encryptor;
private $returnHash;

public function setUp(): void
{
@@ -123,7 +121,7 @@ public function setUp(): void
$this->resultFactory = $this->getMock(ResultFactory::class);
$this->orderRepository = $this->getMock(OrderRepository::class);
$this->bitpayInvoiceRepository = $this->getMock(BitpayInvoiceRepository::class);
$this->encryptor = $this->getMock(EncryptorInterface::class);
$this->returnHash = $this->getMock(ReturnHash::class);
$this->bpRedirect = $this->getClass();
}

@@ -155,7 +153,10 @@ public function testExecute($ux): void
'getUrl'
)
->withConsecutive(['bitpay-invoice', ['_query' => ['order_id' => $incrementId]]], ['checkout/cart'])
->willReturnOnConsecutiveCalls('http://localhost/bitpay-invoice?order_id=' . $incrementId, 'http://localhost/checkout/cart');
->willReturnOnConsecutiveCalls(
'http://localhost/bitpay-invoice?order_id=' . $incrementId,
'http://localhost/checkout/cart'
);

$billingAddress->expects($this->once())->method('getData')
->willReturn(['first_name' => 'test', 'last_name' => 'test1']);
@@ -186,6 +187,9 @@ public function testExecute($ux): void
$this->resultFactory->expects($this->once())->method('create')->willReturn($result);
}

/**
* @var \Magento\Framework\View\Result\Page
*/
$page = $this->getMock(\Magento\Framework\View\Result\Page::class);

$this->bpRedirect->execute($page);
@@ -203,7 +207,6 @@ public function getUxDataProvider(): array

public function testExecuteNoOrderId(): void
{
$response = $this->getMock(\Magento\Framework\HTTP\PhpEnvironment\Response::class);
$this->checkoutSession->expects($this->once())
->method('getData')
->with('last_order_id')
@@ -212,6 +215,9 @@ public function testExecuteNoOrderId(): void
$result->expects($this->once())->method('setUrl')->willReturnSelf();
$this->resultFactory->expects($this->once())->method('create')->willReturn($result);

/**
* @var \Magento\Framework\View\Result\Page
*/
$page = $this->getMock(\Magento\Framework\View\Result\Page::class);

$this->bpRedirect->execute($page);
@@ -237,6 +243,9 @@ public function testExecuteNoBitpayPaymentMethod(): void
$order->expects($this->once())->method('getPayment')->willReturn($payment);
$this->order->expects($this->once())->method('load')->with($lastOrderId)->willReturn($order);

/**
* @var \Magento\Framework\View\Result\Page
*/
$page = $this->getMock(\Magento\Framework\View\Result\Page::class);

$this->assertSame($page, $this->bpRedirect->execute($page));
@@ -268,7 +277,10 @@ public function testExecuteException($exceptionType): void
'getUrl'
)
->withConsecutive(['bitpay-invoice', ['_query' => ['order_id' => $incrementId]]], ['checkout/cart'])
->willReturnOnConsecutiveCalls('http://localhost/bitpay-invoice?order_id=' . $incrementId, 'http://localhost/checkout/cart');
->willReturnOnConsecutiveCalls(
'http://localhost/bitpay-invoice?order_id=' . $incrementId,
'http://localhost/checkout/cart'
);

$billingAddress->expects($this->once())->method('getData')
->willReturn(['first_name' => 'test', 'last_name' => 'test1']);
@@ -288,6 +300,9 @@ public function testExecuteException($exceptionType): void
->method('BPCCreateInvoice')
->willThrowException(new $exceptionType('something went wrong'));

/**
* @var \Magento\Framework\View\Result\Page
*/
$page = $this->getMock(\Magento\Framework\View\Result\Page::class);

$this->bpRedirect->execute($page);
@@ -368,7 +383,7 @@ private function getClass(): BPRedirect
$this->client,
$this->orderRepository,
$this->bitpayInvoiceRepository,
$this->encryptor
$this->returnHash
);
}

32 changes: 16 additions & 16 deletions Test/Unit/Model/IpnManagementTest.php
Original file line number Diff line number Diff line change
@@ -3,21 +3,16 @@

namespace Bitpay\BPCheckout\Test\Unit\Model;

use Bitpay\BPCheckout\Exception\IPNValidationException;
use Bitpay\BPCheckout\Model\Client;
use Bitpay\BPCheckout\Model\Config;
use Bitpay\BPCheckout\Model\Invoice;
use Bitpay\BPCheckout\Model\IpnManagement;
use Bitpay\BPCheckout\Api\IpnManagementInterface;
use Bitpay\BPCheckout\Helper\ReturnHash;
use Bitpay\BPCheckout\Logger\Logger;
use Bitpay\BPCheckout\Model\Ipn\BPCItem;
use Bitpay\BPCheckout\Model\TransactionRepository;
use BitPaySDK\Model\Invoice\Buyer;
use Hoa\Iterator\Mock;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\ResponseFactory;
use Magento\Framework\App\Response;
use Magento\Framework\DataObject;
use Magento\Framework\Registry;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Framework\UrlInterface;
@@ -109,6 +104,11 @@ class IpnManagementTest extends TestCase
*/
private $response;

/**
* @var ReturnHash|MockObject
*/
private $returnHashHelper;

public function setUp(): void
{
$this->coreRegistry = $this->getMock(Registry::class);
@@ -125,6 +125,7 @@ public function setUp(): void
$this->request = $this->getMock(Request::class);
$this->client = $this->getMock(Client::class);
$this->response = $this->getMock(\Magento\Framework\Webapi\Rest\Response::class);
$this->returnHashHelper = $this->getMock(ReturnHash::class);
$this->ipnManagement = $this->getClass();
}

@@ -160,25 +161,23 @@ public function testPostCloseKeepOrder(): void
{
$this->config->expects($this->once())->method('getBitpayInvoiceCloseHandling')->willReturn('keep_order');

$quoteId = 21;
$cartUrl = 'http://localhost/checkout/cart?reload=1';
$quote = $this->getMock(Quote::class);
$response = $this->getMock(\Magento\Framework\HTTP\PhpEnvironment\Response::class);
$order = $this->getMock(Order::class);
$orderId = '000000012';
$this->url->expects($this->once())->method('getUrl')->willReturn($cartUrl);

$this->request->expects($this->once())->method('getParam')->willReturn($orderId);
$this->responseFactory->expects($this->once())->method('create')->willReturn($response);
$order->expects($this->once())->method('getData')->willReturn(['quote_id' => $quoteId]);
$this->orderInterface->expects($this->once())->method('loadByIncrementId')->willReturn($order);

$quote->expects($this->once())->method('loadByIdWithoutStore')->willReturnSelf();
$quote->expects($this->once())->method('getId')->willReturn($quoteId);
$quote->expects($this->once())->method('setIsActive')->willReturnSelf();
$quote->expects($this->once())->method('setReservedOrderId')->willReturnSelf();

$this->quoteFactory->expects($this->once())->method('create')->willReturn($quote);
$this->checkoutSession
->method('__call')
->willReturnCallback(fn($operation) => match ([$operation]) {
['setLastSuccessQuoteId'] => $this->checkoutSession,
['setLastQuoteId'] => $this->checkoutSession,
['setLastOrderId'] => $this->checkoutSession
});

$response->expects($this->once())->method('setRedirect')->willReturnSelf();
$order->expects($this->never())->method('delete')->willReturnSelf();
@@ -428,7 +427,8 @@ private function getClass(): IpnManagement
$this->invoice,
$this->request,
$this->client,
$this->response
$this->response,
$this->returnHashHelper
);
}

11 changes: 8 additions & 3 deletions Test/Unit/Model/ResourceModel/TransactionTest.php
Original file line number Diff line number Diff line change
@@ -23,10 +23,15 @@ class TransactionTest extends TestCase
*/
private $adapter;

/**
* @var Context|MockObject $context
*/
private $context;

public function setUp(): void
{
$this->prepareContext();
$this->transaction = new Transaction($this->contex);
$this->transaction = new Transaction($this->context);
}

public function testAdd(): void
@@ -94,8 +99,8 @@ private function prepareContext(): void
$resourceConnection = $this->getMockBuilder(ResourceConnection::class)->disableOriginalConstructor()->getMock();
$this->adapter = $this->getMockBuilder(AdapterInterface::class)->disableOriginalConstructor()->getMock();
$resourceConnection->expects($this->once())->method('getConnection')->willReturn($this->adapter);
$this->contex = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock();
$this->contex->expects($this->once())->method('getResources')->willReturn($resourceConnection);
$this->context = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock();
$this->context->expects($this->once())->method('getResources')->willReturn($resourceConnection);
}

private function prepareTableName(): void
11 changes: 11 additions & 0 deletions view/frontend/layout/checkout_onepage_success.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Bitpay\BPCheckout\Block\Checkout\Onepage\Success\PayButton" name="checkout.order.success.bitpay.paybutton"
template="Bitpay_BPCheckout::checkout/order/success/pay-button.phtml" after="-">
</block>
</referenceContainer>
</body>
</page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php /** @var $block \Bitpay\BPCheckout\Block\Checkout\Onepage\Success\PayButton */ ?>
<?php if ($block->getOrderId() && $block->canViewPayButton()) :?>
<div>
<br/>
<a href="<?= $block->escapeUrl($block->getButtonUrl()) ?>" title="<?= $block->escapeHtml(__('Pay with BitPay')) ?>">
<img src="<?php echo $block->getViewFileUrl('Bitpay_BPCheckout::images/Pay-with-BitPay-CardGroup.svg'); ?>" alt="<?= $block->escapeHtml(__('Pay with BitPay')) ?>" />
</a>
</div>
<?php endif; ?>
276 changes: 132 additions & 144 deletions view/frontend/web/images/Pay-with-BitPay-CardGroup.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit e33a64b

Please sign in to comment.