Связать умные кнопки PayPal с помощью Ruby on Rails form_for и контроллера / метода? - PullRequest
1 голос
/ 13 апреля 2019

У меня есть умные кнопки, «работающие» в песочнице, но я не могу придумать, как прикрепить успех умных кнопок к форме заказа, которая создает заказ. С 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 с формой, чтобы после завершения платежа он создавал заказ в случае успеха?

UPDATE :::::::

Создан контроллер 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');

При этом появляется окно PayPal, но затем сразу же после его загрузки в 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)

1 Ответ

0 голосов
/ 14 апреля 2019

Я не использовал умные кнопки.Тем не менее, вы не должны иметь «тонны больше кода» в действии создания.Если вы следуете правилам 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;
        }
     });
  });
}
...