首页 > 解决方案 > 使用 Ruby on Rails form_for 和控制器/方法绑定 PayPal 智能按钮?

问题描述

我的智能按钮在沙箱中“工作”,但我想不出任何方法可以将智能按钮成功附加到创建订单的订单表单上。使用 Stripe Elements,它非常即插即用,因为它在页面上并且是表单本身的一部分,但是使用带有重定向的 PayPal,我似乎想不出办法。

这是否需要 javascript 或者我可以在没有它的情况下执行此操作,除了已经存在的内容吗?

形式:

<%= form_for(@order, url: listing_orders_path([@listing, @listing_video]), html: {id: "payment_form-4"} ) do |form| %>

   <%= form.label :name, "Your Name", class: "form-label" %>
   <%= form.text_field :name, class: "form-control", required: true, placeholder: "John" %>
#stripe code here (not important)
<%= form.submit %>
  <div id="paypal-button-container"></div>

<!-- Include the PayPal JavaScript SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=sb&currency=USD"></script>

  <script>
    // Render the PayPal button into #paypal-button-container
    paypal.Buttons({

        // Set up the transaction
        createOrder: function(data, actions) {
            return actions.order.create({
                purchase_units: [{
                    amount: {
                        value: <%= @listing.listing_video.price %>
                    }
                }]
            });
        },

        // Finalize the transaction
        onApprove: function(data, actions) {
            return actions.order.capture().then(function(details) {
                // Show a success message to the buyer
                alert('Transaction completed by ' + details.payer.name.given_name + '!');
            });
        }


    }).render('#paypal-button-container');
</script>

在控制器中创建方法:

require 'paypal-checkout-sdk'
client_id = Rails.application.credentials[Rails.env.to_sym].dig(:paypal, :client_id)
client_secret = Rails.application.credentials[Rails.env.to_sym].dig(:paypal, :client_secret)
# Creating an environment
environment = PayPal::SandboxEnvironment.new(client_id, client_secret)
client = PayPal::PayPalHttpClient.new(environment)

@amount_paypal = (@listing.listing_video.price || @listing.listing_tweet.price)
request = PayPalCheckoutSdk::Orders::OrdersCreateRequest::new
request.request_body(
  {
    intent: 'AUTHORIZE',
    purchase_units: [
      {
        amount: {
          currency_code: 'USD',
          value: "#{@amount_paypal}"
        }
      }
    ]
  }
)

begin
  # Call API with your client and get a response for your call
  response = client.execute(request)

  # If call returns body in response, you can get the deserialized version from the result attribute of the response
  order = response.result
  puts order
  @order.paypal_authorization_token = response.id
rescue BraintreeHttp::HttpError => ioe
  # Something went wrong server-side
  puts ioe.status_code
  puts ioe.headers['debug_id']
end

如何将 PayPal 智能按钮与表单绑定,以便付款完成后,如果成功,它会创建订单?

更新:::::::

创建了一个 PaypalPayments 控制器和模型:

控制器:

  def create
    @paypal_payment = PaypalPayment.new
    @listing = Listing.find_by(params[:listing_id])  

    require 'paypal-checkout-sdk'
    client_id = "#{Rails.application.credentials[Rails.env.to_sym].dig(:paypal, :client_id)}"
    client_secret = "#{Rails.application.credentials[Rails.env.to_sym].dig(:paypal, :client_secret)}"
    # Creating an environment
    environment = PayPal::SandboxEnvironment.new(client_id, client_secret)
    client = PayPal::PayPalHttpClient.new(environment)

    @amount_paypal = @listing.listing_video.price
    request = PayPalCheckoutSdk::Orders::OrdersCreateRequest::new
    @paypal_payment = request.request_body({
                            intent: "AUTHORIZE",
                            purchase_units: [
                                {
                                    amount: {
                                        currency_code: "USD",
                                        value: "#{@amount_paypal}"
                                    }
                                }
                            ]
                          })

    begin
        # Call API with your client and get a response for your call
        response = client.execute(request)

        # If call returns body in response, you can get the deserialized version from the result attribute of the response
        order = response.result
        puts order
        # @order.paypal_authorization_token = response.id
    rescue BraintreeHttp::HttpError => ioe
        # Something went wrong server-side
        puts ioe.status_code
        puts ioe.headers["debug_id"]
    end

    # if @paypal_payment.create
    #   render json: {success: true}
    # else
    #   render json: {success: false}
    # end

  end

Javascript 视图:

paypal.Buttons({

                                      createOrder: function() {
                                        return fetch('/paypal_payments', {
                                          method: 'post',
                                          headers: {
                                            'content-type': 'application/json'
                                          }
                                        }).then(function(res) {
                                          return res.json();
                                        }).then(function(data) {
                                          return data.orderID;
                                        });
                                      },



                                      onApprove: function(data) {
                                        return fetch('/orders', {
                                          method: 'post',
                                          headers: {
                                            'content-type': 'application/json'
                                          },
                                          body: JSON.stringify({
                                            orderID: data.orderID
                                          })
                                        }).then(function(res) {
                                          return res.json();
                                        }).then(function(details) {
                                          alert('Authorization created for ' + details.payer_given_name);
                                        });
                                      },


                                  }).render('#paypal-button-container');

有了这个,贝宝框出现了,但在它在 CMD 中加载后立即消失:

#<OpenStruct id="1Pxxxxxxx394U", links=[#<OpenStruct href="https://api.sandbox.paypal.com/v2/checkout/orders/1P0xxxxxxx394U", rel="self", method="GET">, #<OpenStruct href="https://www.sandbox.paypal.com/checkoutnow?token=1P07xxxxxxx94U", rel="approve", method="GET">, #<OpenStruct href="https://api.sandbox.paypal.com/v2/checkout/orders/1Pxxxxxxx4U", rel="update", method="PATCH">, #<OpenStruct href="https://api.sandbox.paypal.com/v2/checkout/orders/1P07xxxxxxx394U/authorize", rel="authorize", method="POST">], status="CREATED">
No template found for PaypalPaymentsController#create, rendering head :no_content
Completed 204 No Content in 2335ms (ActiveRecord: 15.8ms)

标签: ruby-on-railsrubypaypalpaypal-rest-sdkexpress-checkout

解决方案


我没有使用智能按钮。但是,您不应该在创建操作中有“大量代码”。如果您遵循 MVC 和 rails 约定。您似乎需要一个单独的控制器操作来与创建操作分开处理支付授权。但是,如果您可以在您的 javascript 中达到这一点,这里是您如何将数据从 paypal javascript 发送回您的控制器的示例,这将需要一些工作,但希望它为您指明正确的方向:

// Finalize the transaction
onApprove: function(data, actions) {
  return actions.order.capture().then(function(details) {
    // Show a success message to the buyer
    alert('Transaction completed by ' + details.payer.name.given_name + '!');
   // here is where you should send info to your controller action via ajax.
     $.ajax({
        type: "POST",
        url: "/orders",
        data: data,
        success: function(data) {
          alert(data); // or whatever you wanna do here
          return false;
        },
        error: function(data) {
          alert(data); // or something else
          return false;
        }
     });
  });
}

推荐阅读