Skip to content
Snippets Groups Projects

Resolve #3232779 "Improve exception handling"

All threads resolved!
Files
5
+ 68
34
@@ -2,6 +2,10 @@
@@ -2,6 +2,10 @@
namespace Drupal\commerce_afterpay\Client;
namespace Drupal\commerce_afterpay\Client;
 
use Afterpay\SDK\Exception\InvalidArgumentException;
 
use Afterpay\SDK\Exception\NetworkException;
 
use Afterpay\SDK\Exception\ParsingException;
 
use Afterpay\SDK\Exception\PrerequisiteNotMetException;
use Afterpay\SDK\HTTP\Request;
use Afterpay\SDK\HTTP\Request;
use Afterpay\SDK\HTTP\Request\CreateCheckout;
use Afterpay\SDK\HTTP\Request\CreateCheckout;
use Afterpay\SDK\HTTP\Request\CreateRefund;
use Afterpay\SDK\HTTP\Request\CreateRefund;
@@ -18,6 +22,7 @@ use Drupal\commerce_order\Entity\OrderInterface;
@@ -18,6 +22,7 @@ use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\commerce_payment\Entity\PaymentInterface as CommercePayment;
use Drupal\commerce_payment\Entity\PaymentInterface as CommercePayment;
use Drupal\commerce_payment\Exception\DeclineException;
use Drupal\commerce_payment\Exception\DeclineException;
 
use Drupal\commerce_payment\Exception\InvalidResponseException;
use Drupal\commerce_payment\Exception\PaymentGatewayException;
use Drupal\commerce_payment\Exception\PaymentGatewayException;
use Drupal\commerce_price\Price;
use Drupal\commerce_price\Price;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Component\Uuid\UuidInterface;
@@ -61,10 +66,15 @@ class Client implements ClientInterface {
@@ -61,10 +66,15 @@ class Client implements ClientInterface {
*/
*/
public function __construct(ClientConfig $config, RemoteModel $remote_model, UuidInterface $uuid) {
public function __construct(ClientConfig $config, RemoteModel $remote_model, UuidInterface $uuid) {
$this->merchant = new MerchantAccount();
$this->merchant = new MerchantAccount();
$this->merchant->setMerchantId($config->getMerchantId())
try {
->setSecretKey($config->getSecretKey())
$this->merchant->setMerchantId($config->getMerchantId())
->setCountryCode($config->getCountryCode())
->setSecretKey($config->getSecretKey())
->setApiEnvironment($config->getMode() === 'live' ? 'production' : 'sandbox');
->setCountryCode($config->getCountryCode())
 
->setApiEnvironment($config->getMode() === 'live' ? 'production' : 'sandbox');
 
}
 
catch (InvalidArgumentException $e) {
 
throw new PaymentGatewayException($e->getMessage(), $e->getCode(), $e);
 
}
$this->uuidGenerator = $uuid;
$this->uuidGenerator = $uuid;
$this->remoteModel = $remote_model;
$this->remoteModel = $remote_model;
@@ -75,7 +85,7 @@ class Client implements ClientInterface {
@@ -75,7 +85,7 @@ class Client implements ClientInterface {
*/
*/
public function getConfiguration(): object {
public function getConfiguration(): object {
$request = new GetConfiguration([]);
$request = new GetConfiguration([]);
return $this->sendRequest($request, FALSE)->getParsedBody();
return $this->sendRequest($request)->getParsedBody();
}
}
/**
/**
@@ -100,7 +110,10 @@ class Client implements ClientInterface {
@@ -100,7 +110,10 @@ class Client implements ClientInterface {
return $item->hasPurchasedEntity();
return $item->hasPurchasedEntity();
});
});
$afterpay_items = array_map([$this->remoteModel, 'createItem'], $product_items);
$afterpay_items = array_map([
 
$this->remoteModel,
 
'createItem',
 
], $product_items);
$request = new CreateCheckout();
$request = new CreateCheckout();
$request
$request
@@ -118,7 +131,10 @@ class Client implements ClientInterface {
@@ -118,7 +131,10 @@ class Client implements ClientInterface {
// Add discounts.
// Add discounts.
$promotions = $order->collectAdjustments(['promotion']);
$promotions = $order->collectAdjustments(['promotion']);
if ($promotions) {
if ($promotions) {
$request->setDiscounts(array_map([$this->remoteModel, 'createDiscount'], $promotions));
$request->setDiscounts(array_map([
 
$this->remoteModel,
 
'createDiscount',
 
], $promotions));
}
}
// Add tax and shipping.
// Add tax and shipping.
@@ -169,12 +185,9 @@ class Client implements ClientInterface {
@@ -169,12 +185,9 @@ class Client implements ClientInterface {
'merchantReference' => $payment->getOrderId(),
'merchantReference' => $payment->getOrderId(),
'amount' => $this->remoteModel->createMoney($amount),
'amount' => $this->remoteModel->createMoney($amount),
]);
]);
// Don't pass the order ID in the constructor to avoid a curl warning.
$this->setOrderIdOnRequest($request, $payment);
// @see https://github.com/afterpay/sdk-php/issues/11
$request->setOrderId($payment->getOrder()->getData('commerce_afterpay_order_id'));
$response = $this->sendRequest($request);
$response = $this->sendRequest($request);
$afterpay_payment = new AfterpayPayment($response->getParsedBody());
return new AfterpayPayment($response->getParsedBody());
return $afterpay_payment;
}
}
/**
/**
@@ -185,9 +198,7 @@ class Client implements ClientInterface {
@@ -185,9 +198,7 @@ class Client implements ClientInterface {
'amount' => $this->remoteModel->createMoney($payment->getAmount()),
'amount' => $this->remoteModel->createMoney($payment->getAmount()),
'requestId' => $this->uuidGenerator->generate(),
'requestId' => $this->uuidGenerator->generate(),
]);
]);
// Don't pass the order ID in the constructor to avoid a curl warning.
$this->setOrderIdOnRequest($request, $payment);
// @see https://github.com/afterpay/sdk-php/issues/11
$request->setOrderId($payment->getOrder()->getData('commerce_afterpay_order_id'));
$response = $this->sendRequest($request);
$response = $this->sendRequest($request);
return new AfterpayPayment($response->getParsedBody());
return new AfterpayPayment($response->getParsedBody());
}
}
@@ -205,7 +216,7 @@ class Client implements ClientInterface {
@@ -205,7 +216,7 @@ class Client implements ClientInterface {
'merchantReference' => $payment->getOrderId(),
'merchantReference' => $payment->getOrderId(),
// @todo Implement refundMerchantReference.
// @todo Implement refundMerchantReference.
]);
]);
$request->setOrderId($this->getRemoteOrderId($payment));
$this->setOrderIdOnRequest($request, $payment);
$response = $this->sendRequest($request);
$response = $this->sendRequest($request);
return new Refund($response->getParsedBody());
return new Refund($response->getParsedBody());
}
}
@@ -215,21 +226,23 @@ class Client implements ClientInterface {
@@ -215,21 +226,23 @@ class Client implements ClientInterface {
*
*
* @param \Afterpay\SDK\HTTP\Request $request
* @param \Afterpay\SDK\HTTP\Request $request
* The request to be made.
* The request to be made.
* @param bool $validate
* Whether to validate the request data before sending; defaults to TRUE.
* Ideally we shouldn't need to care, but at the moment requests with no
* body parameters issue a warning on calling ::isValid(): see linked issue.
*
*
* @return \Afterpay\SDK\HTTP\Response
* @return \Afterpay\SDK\HTTP\Response
*
*
* @todo Remove $validate if https://github.com/afterpay/sdk-php/issues/13
* @throws \Drupal\commerce_payment\Exception\PaymentGatewayException
* lands.
* @throws \Drupal\commerce_payment\Exception\InvalidResponseException
 
*
* @todo Add platform details.
* @todo Add platform details.
*/
*/
protected function sendRequest(Request $request, bool $validate = TRUE): Response {
protected function sendRequest(Request $request): Response {
$request->setMerchantAccount($this->merchant);
try {
 
$request->setMerchantAccount($this->merchant);
 
}
 
catch (InvalidArgumentException $e) {
 
throw new PaymentGatewayException($e->getMessage(), $e->getCode(), $e);
 
}
if ($validate && !$request->isValid()) {
if (!$request->isValid()) {
$context = [
$context = [
'@uri' => $request->getUri(),
'@uri' => $request->getUri(),
'@messages' => $request->getValidationErrors(),
'@messages' => $request->getValidationErrors(),
@@ -237,28 +250,49 @@ class Client implements ClientInterface {
@@ -237,28 +250,49 @@ class Client implements ClientInterface {
$message = t("Invalid data for request to @uri: @messages.", $context);
$message = t("Invalid data for request to @uri: @messages.", $context);
throw new PaymentGatewayException($message);
throw new PaymentGatewayException($message);
}
}
$request->send();
 
try {
 
$request->send();
 
}
 
catch (InvalidArgumentException | ParsingException | PrerequisiteNotMetException $e) {
 
throw new PaymentGatewayException($e->getMessage(), $e->getCode(), $e);
 
}
 
catch (NetworkException $e) {
 
throw new InvalidResponseException($e->getMessage(), $e->getCode(), $e);
 
}
 
$response = $request->getResponse();
$response = $request->getResponse();
if (!$response->isSuccessful()) {
if (!$response->isSuccessful()) {
// @todo Improve the error handling.
$body = $response->getParsedBody();
throw new PaymentGatewayException();
throw new PaymentGatewayException($body->message, $body->errorCode);
}
}
return $response;
return $response;
}
}
/**
/**
* Get the remote order ID from a payment.
* Sets order ID on request.
*
*
 
* Must be done separately. Order ID is a path parameter in the Request, and
 
* thus is expected to be set using the setOrderId method, whereas Request
 
* body parameters can be passed via the constructor.
 
*
 
* @see https://github.com/afterpay/sdk-php/issues/11
 
*
 
* @param \Afterpay\SDK\HTTP\Request\DeferredPaymentCapture|\Afterpay\SDK\HTTP\Request\DeferredPaymentVoid|\Afterpay\SDK\HTTP\Request\CreateRefund $request
* @param \Drupal\commerce_payment\Entity\PaymentInterface $payment
* @param \Drupal\commerce_payment\Entity\PaymentInterface $payment
* The payment.
*
*
* @return string
* @throws \Drupal\commerce_payment\Exception\PaymentGatewayException
* The remote order ID.
*/
*/
protected function getRemoteOrderId(CommercePayment $payment): string {
protected function setOrderIdOnRequest(Request $request, CommercePayment $payment): void {
return $payment->getOrder()->getData('commerce_afterpay_order_id');
$order_id = $payment->getOrder()->getData('commerce_afterpay_order_id');
 
try {
 
$request->setOrderId($order_id);
 
}
 
catch (InvalidArgumentException $e) {
 
throw new PaymentGatewayException($e->getMessage(), $e->getCode(), $e);
 
}
}
}
}
}
Loading