You are here

public function Stripe::createPayment in Commerce Stripe 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

File

src/Plugin/Commerce/PaymentGateway/Stripe.php, line 211

Class

Stripe
Provides the Stripe payment gateway.

Namespace

Drupal\commerce_stripe\Plugin\Commerce\PaymentGateway

Code

public function createPayment(PaymentInterface $payment, $capture = TRUE) {
  $this
    ->assertPaymentState($payment, [
    'new',
  ]);
  $payment_method = $payment
    ->getPaymentMethod();
  assert($payment_method instanceof PaymentMethodInterface);
  $this
    ->assertPaymentMethod($payment_method);
  $order = $payment
    ->getOrder();
  assert($order instanceof OrderInterface);
  $intent_id = $order
    ->getData('stripe_intent');
  try {
    $intent = PaymentIntent::retrieve($intent_id);
    if ($intent->status === PaymentIntent::STATUS_REQUIRES_CONFIRMATION) {
      $intent = $intent
        ->confirm();
    }
    if ($intent->status === PaymentIntent::STATUS_REQUIRES_ACTION) {
      throw new SoftDeclineException('The payment intent requires action by the customer for authentication');
    }
    if (!in_array($intent->status, [
      PaymentIntent::STATUS_REQUIRES_CAPTURE,
      PaymentIntent::STATUS_SUCCEEDED,
    ], TRUE)) {
      $order
        ->set('payment_method', NULL);
      $this
        ->deletePaymentMethod($payment_method);
      if ($intent->status === PaymentIntent::STATUS_CANCELED) {
        $order
          ->setData('stripe_intent', NULL);
      }
      if (is_object($intent->last_payment_error)) {
        $error = $intent->last_payment_error;
        $decline_message = sprintf('%s: %s', $error->type, isset($error->message) ? $error->message : '');
      }
      else {
        $decline_message = $intent->last_payment_error;
      }
      throw new HardDeclineException($decline_message);
    }
    if (count($intent->charges->data) === 0) {
      throw new HardDeclineException(sprintf('The payment intent %s did not have a charge object.', $intent_id));
    }
    $next_state = $capture ? 'completed' : 'authorization';
    $payment
      ->setState($next_state);
    $payment
      ->setRemoteId($intent->charges->data[0]->id);
    $payment
      ->save();

    // Add metadata and extra transaction data where required.
    $event = new TransactionDataEvent($payment);
    $this->eventDispatcher
      ->dispatch(StripeEvents::TRANSACTION_DATA, $event);

    // Update the transaction data from additional information added through
    // the event.
    $metadata = $intent->metadata
      ->toArray();
    $metadata += $event
      ->getMetadata();
    PaymentIntent::update($intent->id, [
      'metadata' => $metadata,
    ]);
    $order
      ->unsetData('stripe_intent');
    $order
      ->save();
  } catch (ApiErrorException $e) {
    ErrorHelper::handleException($e);
  }
}