View source
<?php
namespace Drupal\commerce_payment\Plugin\Commerce\CheckoutPane;
use Drupal\commerce\InlineFormManager;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase;
use Drupal\commerce_payment\Entity\PaymentGatewayInterface;
use Drupal\commerce_payment\Exception\DeclineException;
use Drupal\commerce_payment\Exception\PaymentGatewayException;
use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\ManualPaymentGatewayInterface;
use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\OffsitePaymentGatewayInterface;
use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\SupportsStoredPaymentMethodsInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class PaymentProcess extends CheckoutPaneBase {
protected $inlineFormManager;
protected $logger;
public function __construct(array $configuration, $plugin_id, $plugin_definition, CheckoutFlowInterface $checkout_flow, EntityTypeManagerInterface $entity_type_manager, InlineFormManager $inline_form_manager, LoggerInterface $logger) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $checkout_flow, $entity_type_manager);
$this->inlineFormManager = $inline_form_manager;
$this->logger = $logger;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, CheckoutFlowInterface $checkout_flow = NULL) {
return new static($configuration, $plugin_id, $plugin_definition, $checkout_flow, $container
->get('entity_type.manager'), $container
->get('plugin.manager.commerce_inline_form'), $container
->get('logger.channel.commerce_payment'));
}
public function defaultConfiguration() {
return [
'capture' => TRUE,
] + parent::defaultConfiguration();
}
public function buildConfigurationSummary() {
if (!empty($this->configuration['capture'])) {
$summary = $this
->t('Transaction mode: Authorize and capture');
}
else {
$summary = $this
->t('Transaction mode: Authorize only');
}
return $summary;
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['capture'] = [
'#type' => 'radios',
'#title' => $this
->t('Transaction mode'),
'#description' => $this
->t('This setting is only respected if the chosen payment gateway supports authorizations.'),
'#options' => [
TRUE => $this
->t('Authorize and capture'),
FALSE => $this
->t('Authorize only (requires manual capture after checkout)'),
],
'#default_value' => (int) $this->configuration['capture'],
];
return $form;
}
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::submitConfigurationForm($form, $form_state);
if (!$form_state
->getErrors()) {
$values = $form_state
->getValue($form['#parents']);
$this->configuration['capture'] = !empty($values['capture']);
}
}
public function isVisible() {
if ($this->order
->isPaid() || $this->order
->getTotalPrice()
->isZero()) {
return FALSE;
}
$payment_info_pane = $this->checkoutFlow
->getPane('payment_information');
if (!$payment_info_pane
->isVisible() || $payment_info_pane
->getStepId() == '_disabled') {
return FALSE;
}
return TRUE;
}
public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
$error_step_id = $this
->getErrorStepId();
if ($this->order
->get('payment_gateway')
->isEmpty()) {
$this
->messenger()
->addError($this
->t('No payment gateway selected.'));
$this->checkoutFlow
->redirectToStep($error_step_id);
}
$payment_gateway = $this->order->payment_gateway->entity;
$payment_gateway_plugin = $payment_gateway
->getPlugin();
$payment = $this
->createPayment($payment_gateway);
$next_step_id = $this->checkoutFlow
->getNextStepId($this
->getStepId());
if ($payment_gateway_plugin instanceof SupportsStoredPaymentMethodsInterface && !$this->order
->get('payment_method')
->isEmpty()) {
try {
$payment->payment_method = $this->order
->get('payment_method')->entity;
$payment_gateway_plugin
->createPayment($payment, $this->configuration['capture']);
$this->checkoutFlow
->redirectToStep($next_step_id);
} catch (DeclineException $e) {
$message = $this
->t('We encountered an error processing your payment method. Please verify your details and try again.');
$this
->messenger()
->addError($message);
$this->checkoutFlow
->redirectToStep($error_step_id);
} catch (PaymentGatewayException $e) {
$this->logger
->error($e
->getMessage());
$message = $this
->t('We encountered an unexpected error processing your payment method. Please try again later.');
$this
->messenger()
->addError($message);
$this->checkoutFlow
->redirectToStep($error_step_id);
}
}
elseif ($payment_gateway_plugin instanceof OffsitePaymentGatewayInterface) {
$complete_form['actions']['next']['#value'] = $this
->t('Proceed to @gateway', [
'@gateway' => $payment_gateway_plugin
->getDisplayLabel(),
]);
$complete_form['actions']['next']['#suffix'] = Link::fromTextAndUrl($this
->t('Go back'), $this
->buildCancelUrl())
->toString();
$complete_form['actions']['#access'] = FALSE;
$inline_form = $this->inlineFormManager
->createInstance('payment_gateway_form', [
'operation' => 'offsite-payment',
'catch_build_exceptions' => FALSE,
], $payment);
$pane_form['offsite_payment'] = [
'#parents' => array_merge($pane_form['#parents'], [
'offsite_payment',
]),
'#inline_form' => $inline_form,
'#return_url' => $this
->buildReturnUrl()
->toString(),
'#cancel_url' => $this
->buildCancelUrl()
->toString(),
'#capture' => $this->configuration['capture'],
];
try {
$pane_form['offsite_payment'] = $inline_form
->buildInlineForm($pane_form['offsite_payment'], $form_state);
} catch (PaymentGatewayException $e) {
$this->logger
->error($e
->getMessage());
$message = $this
->t('We encountered an unexpected error processing your payment. Please try again later.');
$this
->messenger()
->addError($message);
$this->checkoutFlow
->redirectToStep($error_step_id);
}
return $pane_form;
}
elseif ($payment_gateway_plugin instanceof ManualPaymentGatewayInterface) {
try {
$payment_gateway_plugin
->createPayment($payment);
$this->checkoutFlow
->redirectToStep($next_step_id);
} catch (PaymentGatewayException $e) {
$this->logger
->error($e
->getMessage());
$message = $this
->t('We encountered an unexpected error processing your payment. Please try again later.');
$this
->messenger()
->addError($message);
$this->checkoutFlow
->redirectToStep($error_step_id);
}
}
else {
$this->logger
->error('Unable process payment with :plugin_id', [
':plugin_id' => $payment_gateway_plugin
->getPluginId(),
]);
$message = $this
->t('We encountered an unexpected error processing your payment. Please try again later.');
$this
->messenger()
->addError($message);
$this->checkoutFlow
->redirectToStep($error_step_id);
}
}
protected function buildReturnUrl() {
return Url::fromRoute('commerce_payment.checkout.return', [
'commerce_order' => $this->order
->id(),
'step' => 'payment',
], [
'absolute' => TRUE,
]);
}
protected function buildCancelUrl() {
return Url::fromRoute('commerce_payment.checkout.cancel', [
'commerce_order' => $this->order
->id(),
'step' => 'payment',
], [
'absolute' => TRUE,
]);
}
protected function getErrorStepId() {
$step_id = $this->checkoutFlow
->getPane('payment_information')
->getStepId();
if ($step_id == '_disabled') {
throw new \RuntimeException('Cannot get the step ID for the payment_information pane. The pane is disabled.');
}
return $step_id;
}
protected function createPayment(PaymentGatewayInterface $payment_gateway) {
$payment_storage = $this->entityTypeManager
->getStorage('commerce_payment');
$payment = $payment_storage
->create([
'state' => 'new',
'amount' => $this->order
->getBalance(),
'payment_gateway' => $payment_gateway
->id(),
'order_id' => $this->order
->id(),
]);
return $payment;
}
}