我在我的网站上使用 PayPal 自适应支付(并行),我遇到了一个奇怪的问题,即同一发件人在两个不同的浏览器选项卡中进行两次支付。类似的问题是asked before , 但那里没有人回答。
重现问题的场景
- 用户打开网站的第一个浏览器标签并开始向第一个卖家付款。
- 带有登录按钮的 PayPal 灯箱出现。
- 用户打开网站的第二个浏览器标签并开始向第二个卖家付款。
- 再次出现带有登录按钮的 PyaPal 灯箱。
- 用户返回到第一个浏览器选项卡并登录到 PayPal。
- 在第一个浏览器选项卡中登录 PayPal 后,用户会看到支付给第二个卖家的详细信息。
- 在第二个浏览器选项卡中登录 PayPal 后,用户会看到支付给第二个卖家的详细信息。
PayPal Adaptive Payments 似乎只支持来自一位发件人的一笔交易。
工作原理
该网站使用 Ruby on Rails,我使用 paypal_adaptive gem用于使用 PayPal 付款。支付流程非常简单:
- 用户点击网站上的“购买”按钮。客户端发出由 Ruby on Rails 中的支付 Controller 处理的 AJAX 请求。
- 在 Controller 中,应用程序生成 Pay request使用 paypal_adaptive gem 到 PayPal API 并接收一个 PayKey(见下面的代码)。
- 服务器用 PayKey 响应客户端,客户端使用它以 PayPal 形式通过 PayPal 的灯箱开始支付过程(见下面的代码)。
就是这样。之后我就无法控制任何东西了(付款过程通过 PayPal 的外部网页进行)。
附加说明
- 我确定在上面列出的测试场景中,支付请求的数据在服务器端是不同的。
- 除了 PayPal 的灯箱之外,我还尝试过不同的 PayPal 对话框选项:迷你浏览器和弹出窗口。这些选项不会影响这个错误,它仍然可以重现。
客户端代码
<script src="https://www.paypalobjects.com/js/external/dg.js" type="text/javascript"></script>
<form action="https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay" class="paypal-hidden-form" target="PPDGFrame">
<button id="paypal-submit"></button>
<input id="type" type="hidden" name="expType" value="light">
<!-- Insert PayKey here and click on the form's submit button using jQuery after server's response. -->
<input id="paypal-key" type="hidden" name="paykey" value="">
</form>
<!-- Paypal -->
<script type="text/javascript" charset="utf-8">
var dgFlow = new PAYPAL.apps.DGFlow({ trigger: "paypal-submit", expType: "light" });
function MyEmbeddedFlow(embeddedFlow) {
this.embeddedPPObj = embeddedFlow;
this.paymentSuccess = function(paymentStatus) {
this.embeddedPPObj.closeFlow();
// More UI code here...
};
this.paymentCanceled = function() {
this.embeddedPPObj.closeFlow();
// More UI code here...
};
}
var myEmbeddedPaymentFlow = new MyEmbeddedFlow(dgFlow);
</script>
服务器代码
# Make a Pay request to PayPal API.
paypal_payment_thread = Thread.new do
# Some preparation code goes here...
pay_request = PaypalAdaptive::Request.new
process_guid = SecureRandom.uuid
# Construct Pay API request data.
data = {
:returnUrl => "#{PAYPAL_RETURN_URL}?process_guid=#{process_guid}",
:cancelUrl => "#{PAYPAL_CANCEL_URL}?process_guid=#{process_guid}",
:requestEnvelope => {
:errorLanguage => "en_US"
},
:currencyCode => "USD",
:receiverList => {
:receiver => [{
# seller_paypal value is different for two payments.
# But in fact we do the last payment for both payments.
:email => seller_paypal,
:amount => ORDER_SELLER_AMOUNT,
:paymentType => "DIGITALGOODS"
}, {
:email => PAYPAL_MARKETPLACE_EMAIL,
:amount => ORDER_MARKETPLACE_AMOUNT,
:paymentType => "DIGITALGOODS"
}]
},
:actionType => "PAY",
:ipnNotificationUrl => PAYPAL_NOTIFY_URL,
:reverseAllParallelPaymentsOnError => "true",
:trackingId => process_guid
}
# Make a Pay API request.
pay_response = pay_request.pay(data)
if pay_response.success?
# Everything is ok. Update database here...
else
raise Exceptions::PaypalPaymentError
end
end
为了清楚起见,我删除了一些不重要的代码,它是如何工作的。
在此先感谢您的帮助!
最佳答案
看起来这是设计使然。我在 the website 上尝试过相同的测试PayPal 的一名员工,并且可以在那里重现。
PayPal 的支持回答了我使用Lightbox 的问题。但是,我已经尝试过我在帖子中描述的 Mini-Browser 和 Popup 选项,但没有任何效果。
此外,PayPal 的支持人员回答说这是设计使然,并建议我联系技术支持。也许它对其他人有用。
Hi Michael, Thanks, yes I was able to reproduce it as well. However it’s important to understand that PayPal is not made for handling 2 payment flows at the same time. If you want to get further on that, you can contact our Technical Support : https://ppmts.custhelp.com/ They have other tools to debug and may be able to give you a better understanding of the technical problem.
最后,我使用 HTML5 本地存储中的特殊标志和 PAYPAL.apps.DGFlow
对象的 dgFlow.isOpen()
方法来阻止同时付款以检测 PayPal 窗口.在窗口关闭时,我使用 window
的 onunload
和 onbeforeunload
事件重置了这个标志。
我关闭这个问题。谢谢。
关于 Paypal 自适应支付 : two payments from one sender in two browser tabs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19659524/