contacts_subscriptions-1.x-dev/src/Form/SubscriptionPaymentMethodAddForm.php

src/Form/SubscriptionPaymentMethodAddForm.php
<?php

namespace Drupal\contacts_subscriptions\Form;

use Drupal\commerce_payment\Entity\PaymentGatewayInterface;
use Drupal\commerce_payment\Form\PaymentMethodAddForm;
use Drupal\commerce_stripe\ErrorHelper;
use Drupal\commerce_stripe\Plugin\Commerce\PaymentGateway\StripeInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Http\Exception\CacheableNotFoundHttpException;
use Drupal\user\UserInterface;
use Stripe\Customer;
use Stripe\Exception\ApiErrorException;
use Stripe\SetupIntent;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Add payment method form for subscriptions.
 */
class SubscriptionPaymentMethodAddForm extends PaymentMethodAddForm {

  /**
   * The invoice manager.
   *
   * @var \Drupal\contacts_subscriptions\InvoiceManager
   */
  protected $invoiceManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $form = parent::create($container);
    $form->invoiceManager = $container->get('contacts_subscriptions.invoice_manager');
    $form->entityTypeManager = $container->get('entity_type.manager');
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, UserInterface $user = NULL) {
    $cacheability = new CacheableMetadata();
    $cacheability->addCacheContexts(['url.path']);
    if (!$user) {
      throw new CacheableNotFoundHttpException($cacheability, 'User required for payment method.');
    }
    $cacheability->addCacheableDependency($user);

    $subscription = $this->entityTypeManager
      ->getStorage('contacts_subscription')
      ->loadByUser($user);
    $cacheability->addCacheableDependency($subscription);
    if (!$subscription->willRenew()) {
      throw new CacheableNotFoundHttpException($cacheability, 'User does not have a renewing membership.');
    }

    if ($existing_method = $this->invoiceManager->getPaymentMethod($user)) {
      $form['existing'] = [
        '#type' => 'item',
        '#title' => $this->t('Existing payment method:'),
        '#markup' => $existing_method->label(),
      ];
    }

    // Ensure we are always collecting card details.
    $gateway = $this->entityTypeManager
      ->getStorage('commerce_payment_gateway')
      ->load('stripe');
    $form_state->set('payment_gateway', $gateway);

    // Build the rest of the form.
    $form = parent::buildForm($form, $form_state, $user);
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  protected function buildPaymentMethodForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildPaymentMethodForm($form, $form_state);

    $form['add_payment_method']['#inline_form']->getEntity()->setDefault(TRUE);
    $gateway = $form['add_payment_method']['#inline_form']->getEntity()->getPaymentGateway();
    $gateway_plugin = $gateway->getPlugin();

    if ($js_library = $gateway_plugin->getJsLibrary()) {
      $form['#attached']['library'][] = $js_library;
    }

    if ($gateway_plugin instanceof StripeInterface) {
      try {
        // We are not collecting payment now, so we want to use a SetupIntent.
        $intent = SetupIntent::create([
          'usage' => 'off_session',
          'customer' => $this->getRemoteCustomerId($form_state->getBuildInfo()['args'][0], $gateway),
        ]);
        $form['payment_method']['payment_details']['#attached']['drupalSettings']['commerceStripe']['clientSecret'] = $intent->client_secret;
        $form['payment_method']['payment_details']['#attached']['drupalSettings']['commerceStripe']['futureUsage'] = TRUE;
      }
      catch (ApiErrorException $e) {
        ErrorHelper::handleException($e);
      }
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);

    if ($form_state->get('step') === 'payment_method') {
      $user_id = $form_state->getBuildInfo()['args'][0]->id();

      $form_state->setRedirect(
        'contacts_subscriptions.manage',
        ['user' => $user_id],
      );

      // Un-default all other payment methods.
      $new_method_id = $form['payment_method']['#inline_form']->getEntity()->id();
      /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface[] $other_methods */
      $other_methods = $this->entityTypeManager
        ->getStorage('commerce_payment_method')
        ->loadByProperties([
          'uid' => $user_id,
          'reusable' => TRUE,
        ]);
      foreach ($other_methods as $payment_method) {
        if ($payment_method->id() != $new_method_id) {
          // Mark BACS as no longer reusable.
          if ($payment_method->getPaymentGatewayId() === 'bacs') {
            $payment_method->setReusable(FALSE);
          }
          $payment_method->setDefault(FALSE)->save();
        }
      }
    }
  }

  /**
   * Gets the remote customer ID for the given user.
   *
   * The remote customer ID is specific to a payment gateway instance
   * in the configured mode. This allows the gateway to skip test customers
   * after the gateway has been switched to live mode.
   *
   * @param \Drupal\user\UserInterface $account
   *   The user account.
   * @param \Drupal\commerce_payment\Entity\PaymentGatewayInterface $gateway
   *   The gateway entity.
   *
   * @return string
   *   The remote customer ID, or NULL if none found.
   */
  protected function getRemoteCustomerId(UserInterface $account, PaymentGatewayInterface $gateway) {
    $gateway_plugin = $gateway->getPlugin();
    $remote_id = $gateway_plugin->getRemoteCustomerId($account);

    if (!$account->isAnonymous() && !$remote_id && $gateway_plugin instanceof StripeInterface) {

      // If we haven't got a remote ID, create a customer.
      $email = $account->getEmail();
      $customer = Customer::create([
        'email' => $email,
        'description' => $account->label(),
      ]);
      $remote_id = $customer->id;
      $account->get('commerce_remote_id')->setByProvider($gateway->id() . '|' . $gateway_plugin->getMode(), $remote_id);
      $account->save();
    }

    return $remote_id;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc