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 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分
  • ¥15 delphi webbrowser组件网页下拉菜单自动选择问题
  • ¥15 linux驱动,linux应用,多线程