doupingmao1903 2019-08-07 09:59
浏览 82

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

Stripe are soon to roll out their use of Strong Customer Authentication for payments with their platform. There's a fairly substantial section in their documentation about it.

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

The process has the following flow:

enter image description here

The vanilla PHP implementation is like so:

<?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']);
    }
  }
?>

The necessary JavaScript for its use with Stripe Elements looks like this:

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
  }
}

In my own project I'm using Laravel which is entirely based on the MVC architecture and it fairly nice to you when it comes to most things.

I have tried to refactor a little but I have a question.

Why would you use this line $json_str = file_get_contents('php://input'); over just trying to grab the posted variables from the Request object used in Laravel?

I also read the following article from the PHP Manual:

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

To be perfectly honest I've been away from procedural PHP so this has confused me to no end.

  • 写回答

1条回答 默认 最新

  • dongzhanlu0658 2019-08-07 10:06
    关注

    Why use 'php://input' over the POST superglobal - Stripe SCA example

    The body is encoded as JSON. You can tell because the next line explicitly decodes it.

    PHP doesn't understand application/json requests. It will only populate $_POST if the data is encoding using the application/x-www-form-urlencoded or multipart/form-data formats.

    Why would you use this line $json_str = file_get_contents('php://input'); over just trying to grab the posted variables from the Request object used in Laravel?

    If you were using Laravel, there's no reason to do that.

    Since there is no sign of anything Laravel in the example you gave, it is presumably not written with the intention of introducing a dependency on Laravel.

    评论

报告相同问题?

悬赏问题

  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制