【问题标题】:How to implement asynchronous calls for payment in Ruby on Rails如何在 Ruby on Rails 中实现异步支付调用
【发布时间】:2020-11-18 04:07:51
【问题描述】:

希望有人可以为我提供一些见解,因为我是一个新开发人员,所以我在这里不确定一些事情。

所以过去几天我一直在努力实现自定义条带结帐,我认为我在这里要做的是从我的 rails 视图执行一个异步操作,以便我结帐到我的服务器,以确认付款是否有效.

在 stripes 网站上,我找到了我想要实施的解决方案,但我不清楚他们的意思,我知道他们指的是什么,并且认为我可以做到,但老实说,我不确定我放在哪里我在 rails 中的服务器端代码来处理这个异步调用。它进入我的控制器吗?在我的控制器中的方法内?我是否在某处制作另一个文件?

function stripePaymentMethodHandler(result) {
  if (result.error) {
    // Show error in payment form
  } else {
    // Otherwise send paymentMethod.id to your server (see Step 4)
    fetch('/pay', { // I am not sure about this part. They say to make an endpoint on my server to handle this, does this mean I make a route only for this action in my routes? Then this action gets performed via that route?
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        payment_method_id: result.paymentMethod.id,
      })
    }).then(function(result) {
      // Handle server response (see Step 4)
      result.json().then(function(json) {
        handleServerResponse(json);
      })
    });
  }
}

这是我需要实现的相应服务器端代码,而且,我理解代码本身,我只是不确定我把它放在哪里。在我的控制器中?在我的创建操作中?

post '/pay' do
  data = JSON.parse(request.body.read.to_s)

  begin
    if data['payment_method_id']
      # Create the PaymentIntent
      intent = Stripe::PaymentIntent.create(
        payment_method: data['payment_method_id'],
        amount: 1099,
        currency: 'usd',
        confirmation_method: 'manual',
        confirm: true,
      )
    elsif data['payment_intent_id']
      intent = Stripe::PaymentIntent.confirm(data['payment_intent_id'])
    end
  rescue Stripe::CardError => e
    # Display error on client
    return [200, { error: e.message }.to_json]
  end

  return generate_response(intent)
end

def generate_response(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
    [
      200,
      {
        requires_action: true,
        payment_intent_client_secret: intent.client_secret
      }.to_json
    ]
  elsif intent.status == 'succeeded'
    # The payment didn’t need any additional actions and is completed!
    # Handle post-payment fulfillment
    [200, { success: true }.to_json]
  else
    # Invalid status
    return [500, { error: 'Invalid PaymentIntent status' }.to_json]
  end
end

我明白这一切都在做什么,对我来说最令人困惑的部分是这里引用的“/pay”路线。我可以对我的网站已有的 url 执行这些请求吗?例如 '/orders/new' ?或者我是否需要创建一个名为“/pay”的新路由,如示例中所示,并且该路由仅用于此呼叫?如果是这样,我如何在我的路线中定义它?资源:支付,还是什么?这条路线有什么资源?它只是存储信息的占位符吗?

感谢任何帮助!我一直试图在网上找到一些使用 RoR 的明确示例,也许我用谷歌搜索了错误的东西,因为我找不到太多。

【问题讨论】:

  • 这看起来像一个 Sinatra 示例。您能否指出您从中获取此文件的那部分文档?那我也许能帮上忙。

标签: ruby-on-rails asynchronous routes stripe-payments


【解决方案1】:

这些示例使用 Sinatra 作为 Web 框架,因此使用 Rails 的实际路由看起来会有些不同。基本上,在示例中使用getpost 定义路由的任何地方,您都需要在 routes.rb 文件中创建路由并添加映射到该路由的控制器操作并使用示例中的逻辑。您可以使用下面的示例以一种相当预期的方式从data = JSON.parse(request.body.read.to_s) 转换为params

在 Rails 中,您可以使用现有路由,或者在您的 routes.rb 文件中定义一个新路由:

# routes.rb
resources :orders, only: [:create]

然后在 JavaScript 中,您可以更新 fetch 调用中使用的路径以映射到您自己在 Rails 中定义的路由。所以可能是:

fetch('/orders', // ...

然后处理请求的逻辑将存在于您的 OrdersController 中。在这种情况下,您可能会执行 create 操作来处理此 POST 请求:

# OrdersController
def create
  begin
    if params[:payment_method_id]
      # Create the PaymentIntent
      intent = Stripe::PaymentIntent.create(
        payment_method: params[:payment_method_id],
        amount: 1099,
        currency: 'usd',
        confirmation_method: 'manual',
        confirm: true,
      )
    elsif params[:payment_intent_id]
      intent = Stripe::PaymentIntent.confirm(params[:payment_intent_id])
    end
  rescue Stripe::CardError => e
    # Display error on client
    render json: { error: e.message }
  end

  return generate_response(intent)
end 

def generate_response(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
    render json: {
      requires_action: true,
      payment_intent_client_secret: intent.client_secret
    }
  elsif intent.status == 'succeeded'
    # The payment didn’t need any additional actions and is completed!
    # Handle post-payment fulfillment
    render json: { success: true }
  else
    # Invalid status
    render json: { error: 'Invalid PaymentIntent status' }, 500, .to_json]
  end
end

【讨论】:

  • 谢谢!这很清楚,正是我想要的!我也会研究 Sinatra 以学习新的东西!
【解决方案2】:

您确实需要将逻辑放入控制器中,我们称之为付款

1.生成控制器

$> rails g controller Payments

2。定义创建方法

class PaymentsController < ApplicationController
  def create
    respond_to do |format|
      format.json do
        begin
          if payment_params[:payment_method_id]
            # Create the PaymentIntent
            intent = Stripe::PaymentIntent.create(
              payment_method: payment_params[:payment_method_id],
              amount: 1099,
              currency: 'usd',
              confirmation_method: 'manual',
              confirm: true,
            )
          elsif payment_params[:payment_intent_id]
            intent = Stripe::PaymentIntent.confirm(payment_params[:payment_intent_id])
          end
        rescue Stripe::CardError => e
          # Display error on client
          render json:  { status: :unprocessable_entity, message: e.message }
        end
      end
    end
  end

  private

  def payment_params
    params.permit(:payment_method_id, :payment_intent_id)
  end

  def generate_response(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
      render json: {
        status: 200,
        requires_action: true,
        payment_intent_client_secret: intent.client_secret
      }
    elsif intent.status == 'succeeded'
      # The payment didn’t need any additional actions and is completed!
      # Handle post-payment fulfillment
      render json: { status: 200 }
    else
      # Invalid status
      render json: { status: 500, message: 'Invalid PaymentIntent status' }
    end
  end
end

3.定义路线

routes.rb

resources :payments, only: %i[create]

4.替换代码中的路由

fetch('/payments.json' ...

【讨论】:

  • 感谢您的回答!
猜你喜欢
  • 2016-08-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2013-10-26
  • 2017-08-10
  • 2012-03-24
  • 1970-01-01
相关资源
最近更新 更多