public function Checkout::createPayment in Commerce PayPal 8
Creates a payment.
Parameters
\Drupal\commerce_payment\Entity\PaymentInterface $payment: The payment.
bool $capture: Whether the created payment should be captured (VS authorized only). Allowed to be FALSE only if the plugin supports authorizations.
Throws
\InvalidArgumentException If $capture is FALSE but the plugin does not support authorizations.
\Drupal\commerce_payment\Exception\PaymentGatewayException Thrown when the transaction fails for any reason.
Overrides SupportsStoredPaymentMethodsInterface::createPayment
1 call to Checkout::createPayment()
- Checkout::onReturn in src/
Plugin/ Commerce/ PaymentGateway/ Checkout.php - Processes the "return" request.
File
- src/
Plugin/ Commerce/ PaymentGateway/ Checkout.php, line 416
Class
- Checkout
- Provides the PayPal Checkout payment gateway.
Namespace
Drupal\commerce_paypal\Plugin\Commerce\PaymentGatewayCode
public function createPayment(PaymentInterface $payment, $capture = TRUE) {
$payment_method = $payment
->getPaymentMethod();
if (!$payment_method || empty($payment_method
->getRemoteId())) {
throw new PaymentGatewayException('Cannot create the payment without the PayPal order ID.');
}
$sdk = $this->checkoutSdkFactory
->get($this->configuration);
$order = $payment
->getOrder();
$checkout_data = $order
->getData('commerce_paypal_checkout', [
'flow' => '',
]);
$remote_id = $payment_method
->getRemoteId();
try {
// Ensure the PayPal order is up to date and in sync with Drupal.
$sdk
->updateOrder($remote_id, $order);
$request = $sdk
->getOrder($remote_id);
$paypal_order = Json::decode($request
->getBody());
} catch (BadResponseException $exception) {
throw new PaymentGatewayException($exception
->getMessage());
}
// When in the "shortcut" flow, the PayPal order status is expected to be
// "approved".
if ($checkout_data['flow'] === 'shortcut' && !in_array($paypal_order['status'], [
'APPROVED',
'SAVED',
])) {
throw new PaymentGatewayException(sprintf('Wrong remote order status. Expected: "approved"|"saved", Actual: %s.', $paypal_order['status']));
}
$intent = $checkout_data['intent'] ?? $this->configuration['intent'];
try {
if ($intent == 'capture') {
$response = $sdk
->captureOrder($remote_id);
$paypal_order = Json::decode($response
->getBody()
->getContents());
$remote_payment = $paypal_order['purchase_units'][0]['payments']['captures'][0];
$payment
->setRemoteId($remote_payment['id']);
}
else {
$response = $sdk
->authorizeOrder($remote_id);
$paypal_order = Json::decode($response
->getBody()
->getContents());
$remote_payment = $paypal_order['purchase_units'][0]['payments']['authorizations'][0];
if (isset($remote_payment['expiration_time'])) {
$expiration = new \DateTime($remote_payment['expiration_time']);
$payment
->setExpiresTime($expiration
->getTimestamp());
}
}
} catch (BadResponseException $exception) {
throw new PaymentGatewayException($exception
->getMessage());
}
$remote_state = strtolower($remote_payment['status']);
if (in_array($remote_state, [
'denied',
'expired',
'declined',
])) {
throw new HardDeclineException(sprintf('Could not %s the payment for order %s. Remote payment state: %s', $intent, $order
->id(), $remote_state));
}
$state = $this
->mapPaymentState($intent, $remote_state);
// If we couldn't find a state to map to, stop here.
if (!$state) {
$this->logger
->debug('PayPal remote payment debug: <pre>@remote_payment</pre>', [
'@remote_payment' => print_r($remote_payment, TRUE),
]);
throw new PaymentGatewayException(sprintf('The PayPal payment is in a state we cannot handle. Remote state: %s.', $remote_state));
}
// Special handling of the "pending" state, if the order is "pending review"
// we allow the order to go "through" to give a chance to the merchant
// to accept the payment, in case manual review is needed.
if ($state === 'pending' && $remote_state === 'pending') {
$reason = $remote_payment['status_details']['reason'];
if ($reason === 'PENDING_REVIEW') {
$state = 'authorization';
}
else {
throw new PaymentGatewayException(sprintf('The PayPal payment is pending. Reason: %s.', $reason));
}
}
$payment_amount = Price::fromArray([
'number' => $remote_payment['amount']['value'],
'currency_code' => $remote_payment['amount']['currency_code'],
]);
$payment
->setAmount($payment_amount);
$payment
->setState($state);
$payment
->setRemoteId($remote_payment['id']);
$payment
->setRemoteState($remote_state);
$payment
->save();
}