commerce-8.x-2.8/modules/payment/src/PaymentOptionsBuilder.php
modules/payment/src/PaymentOptionsBuilder.php
<?php namespace Drupal\commerce_payment; use Drupal\commerce\EntityHelper; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\SupportsStoredPaymentMethodsInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; class PaymentOptionsBuilder implements PaymentOptionsBuilderInterface { use StringTranslationTrait; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * Constructs a new PaymentOptionsBuilder object. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation * The string translation. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) { $this->entityTypeManager = $entity_type_manager; $this->stringTranslation = $string_translation; } /** * {@inheritdoc} */ public function buildOptions(OrderInterface $order, array $payment_gateways = []) { if (empty($payment_gateways)) { /** @var \Drupal\commerce_payment\PaymentGatewayStorageInterface $payment_gateway_storage */ $payment_gateway_storage = $this->entityTypeManager->getStorage('commerce_payment_gateway'); $payment_gateways = $payment_gateway_storage->loadMultipleForOrder($order); } /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface[] $payment_gateways_with_payment_methods */ $payment_gateways_with_payment_methods = array_filter($payment_gateways, function ($payment_gateway) { /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */ return $payment_gateway->getPlugin() instanceof SupportsStoredPaymentMethodsInterface; }); $options = []; // 1) Add options to reuse stored payment methods for known customers. $customer = $order->getCustomer(); if ($customer) { $billing_countries = $order->getStore()->getBillingCountries(); /** @var \Drupal\commerce_payment\PaymentMethodStorageInterface $payment_method_storage */ $payment_method_storage = $this->entityTypeManager->getStorage('commerce_payment_method'); foreach ($payment_gateways_with_payment_methods as $payment_gateway) { $payment_methods = $payment_method_storage->loadReusable($customer, $payment_gateway, $billing_countries); foreach ($payment_methods as $payment_method_id => $payment_method) { $options[$payment_method_id] = new PaymentOption([ 'id' => $payment_method_id, 'label' => $payment_method->label(), 'payment_gateway_id' => $payment_gateway->id(), 'payment_method_id' => $payment_method_id, ]); } } } // 2) Add the order's payment method if it was not included above. /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $order_payment_method */ $order_payment_method = $order->get('payment_method')->entity; if ($order_payment_method) { $order_payment_method_id = $order_payment_method->id(); // Make sure that the payment method's gateway is still available. $payment_gateway_id = $order_payment_method->getPaymentGatewayId(); $payment_gateway_ids = EntityHelper::extractIds($payment_gateways_with_payment_methods); if (in_array($payment_gateway_id, $payment_gateway_ids) && !isset($options[$order_payment_method_id])) { $options[$order_payment_method_id] = new PaymentOption([ 'id' => $order_payment_method_id, 'label' => $order_payment_method->label(), 'payment_gateway_id' => $order_payment_method->getPaymentGatewayId(), 'payment_method_id' => $order_payment_method_id, ]); } } // 3) Add options to create new stored payment methods of supported types. $payment_method_type_counts = []; // Count how many new payment method options will be built per gateway. foreach ($payment_gateways_with_payment_methods as $payment_gateway) { $payment_method_types = $payment_gateway->getPlugin()->getPaymentMethodTypes(); foreach ($payment_method_types as $payment_method_type_id => $payment_method_type) { if (!isset($payment_method_type_counts[$payment_method_type_id])) { $payment_method_type_counts[$payment_method_type_id] = 1; } else { $payment_method_type_counts[$payment_method_type_id]++; } } } foreach ($payment_gateways_with_payment_methods as $payment_gateway) { $payment_gateway_plugin = $payment_gateway->getPlugin(); $payment_method_types = $payment_gateway_plugin->getPaymentMethodTypes(); foreach ($payment_method_types as $payment_method_type_id => $payment_method_type) { $option_id = 'new--' . $payment_method_type_id . '--' . $payment_gateway->id(); $option_label = $payment_method_type->getCreateLabel(); // If there is more than one option for this payment method type, // append the payment gateway label to avoid duplicate option labels. if ($payment_method_type_counts[$payment_method_type_id] > 1) { $option_label = $this->t('@payment_method_label (@payment_gateway_label)', [ '@payment_method_label' => $payment_method_type->getCreateLabel(), '@payment_gateway_label' => $payment_gateway_plugin->getDisplayLabel(), ]); } $options[$option_id] = new PaymentOption([ 'id' => $option_id, 'label' => $option_label, 'payment_gateway_id' => $payment_gateway->id(), 'payment_method_type_id' => $payment_method_type_id, ]); } } // 4) Add options for the remaining gateways (off-site, manual, etc). /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface[] $other_payment_gateways */ $other_payment_gateways = array_diff_key($payment_gateways, $payment_gateways_with_payment_methods); foreach ($other_payment_gateways as $payment_gateway) { $payment_gateway_id = $payment_gateway->id(); $options[$payment_gateway_id] = new PaymentOption([ 'id' => $payment_gateway_id, 'label' => $payment_gateway->getPlugin()->getDisplayLabel(), 'payment_gateway_id' => $payment_gateway_id, ]); } return $options; } /** * {@inheritdoc} */ public function selectDefaultOption(OrderInterface $order, array $options) { /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $order_payment_gateway */ $order_payment_gateway = $order->get('payment_gateway')->entity; /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $order_payment_method */ $order_payment_method = $order->get('payment_method')->entity; $default_option_id = NULL; if ($order_payment_method) { $default_option_id = $order_payment_method->id(); } elseif ($order_payment_gateway && !($order_payment_gateway instanceof SupportsStoredPaymentMethodsInterface)) { $default_option_id = $order_payment_gateway->id(); } // The order doesn't have a payment method/gateway specified, or it has, but it is no longer available. if (!$default_option_id || !isset($options[$default_option_id])) { $option_ids = array_keys($options); $default_option_id = reset($option_ids); } return $options[$default_option_id]; } }