ruby-on-rails - 使用 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¤cy=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)
解决方案
我没有使用智能按钮。但是,您不应该在创建操作中有“大量代码”。如果您遵循 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;
}
});
});
}
推荐阅读
- python-3.x - Python & Tensorflow & CUDA 环境设置问题
- unity3d - 在 Unity 中构建 Mapbox
- sqlite - 如何将 Ubuntu 18.04 sqlite3 从 3.13 升级到新版本 3.25
- ios - 使用“执行segue”传递错误返回nil?
- c - 如何在C中获取整数字节?
- javascript - 在 HTML5 Canvas 中将 eventListeners 与对象一起使用(无法在函数中获取对象属性)
- spring-boot - HaProxy 具有用于 Spring Boot 应用程序的负载平衡器
- python - 使用 sqlalchemy 连接到 sqlite3.Connection
- r - 使用 `rle` 函数和 `dplyr` `group_by` 命令映射分组变量
- json - facebook 内部 API 响应主体的端点包含一个 for 循环,后跟 JSON blob,为什么?