为什么在POST超全局变量上使用'php:// input'-Stripe SCA示例

时间:2019-08-07 09:59:28

标签: javascript php laravel stripe-payments

Stripe即将在平台上推广使用强客户身份验证进行支付。他们的文档中有相当一部分内容。

https://stripe.com/docs/payments/payment-intents/quickstart#manual-confirmation-flow

该过程具有以下流程:

enter image description here

原始的PHP实现如下:

<?php
  # vendor using composer
  require_once('vendor/autoload.php');

  \Stripe\Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));

  header('Content-Type: application/json');

  # retrieve json from POST body
  $json_str = file_get_contents('php://input');
  $json_obj = json_decode($json_str);

  $intent = null;
  try {
    if (isset($json_obj->payment_method_id)) {
      # Create the PaymentIntent
      $intent = \Stripe\PaymentIntent::create([
        'payment_method' => $json_obj->payment_method_id,
        'amount' => 1099,
        'currency' => 'gbp',
        'confirmation_method' => 'manual',
        'confirm' => true,
      ]);
    }
    if (isset($json_obj->payment_intent_id)) {
      $intent = \Stripe\PaymentIntent::retrieve(
        $json_obj->payment_intent_id
      );
      $intent->confirm();
    }
    generatePaymentResponse($intent);
  } catch (\Stripe\Error\Base $e) {
    # Display error on client
    echo json_encode([
      'error' => $e->getMessage()
    ]);
  }

  function generatePaymentResponse($intent) {
    # Note that if your API version is before 2019-02-11, 'requires_action'
    # appears as 'requires_source_action'.
    if ($intent->status == 'requires_action' &&
        $intent->next_action->type == 'use_stripe_sdk') {
      # Tell the client to handle the action
      echo json_encode([
        'requires_action' => true,
        'payment_intent_client_secret' => $intent->client_secret
      ]);
    } else if ($intent->status == 'succeeded') {
      # The payment didn’t need any additional actions and completed!
      # Handle post-payment fulfillment
      echo json_encode([
        "success" => true
      ]);
    } else {
      # Invalid status
      http_response_code(500);
      echo json_encode(['error' => 'Invalid PaymentIntent status']);
    }
  }
?>

与Stripe Elements配合使用所需的JavaScript如下所示:

var cardholderName = document.getElementById('cardholder-name');
var cardButton = document.getElementById('card-button');

cardButton.addEventListener('click', function(ev) {
  stripe.createPaymentMethod('card', cardElement, {
    billing_details: {name: cardholderName.value}
  }).then(function(result) {
    if (result.error) {
      // Show error in payment form
    } else {
      // Otherwise send paymentMethod.id to your server (see Step 2)
      fetch('/ajax/confirm_payment', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ payment_method_id: result.paymentMethod.id })
      }).then(function(result) {
        // Handle server response (see Step 3)
        result.json().then(function(json) {
          handleServerResponse(json);
        })
      });
    }
  });
});

function handleServerResponse(response) {
  if (response.error) {
    // Show error from server on payment form
  } else if (response.requires_action) {
    // Use Stripe.js to handle required card action
    stripe.handleCardAction(
      response.payment_intent_client_secret
    ).then(function(result) {
      if (result.error) {
        // Show error in payment form
      } else {
        // The card action has been handled
        // The PaymentIntent can be confirmed again on the server
        fetch('/ajax/confirm_payment', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ payment_intent_id: result.paymentIntent.id })
        }).then(function(confirmResult) {
          return confirmResult.json();
        }).then(handleServerResponse);
      }
    });
  } else {
    // Show success message
  }
}

在我自己的项目中,我使用的是Laravel,它完全基于MVC架构,在大多数事情上对您来说都很不错。

我试图重构一些,但是我有一个问题。

为什么为什么要尝试从Laravel中使用的$json_str = file_get_contents('php://input');对象中获取已发布的变量而不是使用Request行?

我还从PHP手册中阅读了以下文章:

https://www.php.net/manual/en/wrappers.php.php

说实话,我一直没有使用过程PHP,这使我感到无休止。

1 个答案:

答案 0 :(得分:0)

  

为什么在POST超全局变量上使用'php:// input'-Stripe SCA示例

主体被编码为JSON。您可以知道,因为下一行会对其进行显式解码。

PHP无法理解application/json请求。如果数据使用$_POSTapplication/x-www-form-urlencoded格式编码,则只会填充multipart/form-data

  

为什么只尝试从Laravel中使用的Request对象中获取发布的变量,而不是使用$json_str = file_get_contents('php://input');行?

如果您使用的是Laravel,则没有理由这样做。

由于在您给出的示例中没有任何Laravel的迹象,因此可能并不是为了引入对Laravel的依赖而编写的。