我在我的网站上使用 PayPal Adaptive Payments(并行),我遇到了一个奇怪的问题,即来自同一发件人的两个不同浏览器选项卡中的两次付款。之前有人问过类似的问题,但没有人在那里回答。
重现问题的场景
- 用户打开网站的第一个浏览器选项卡并开始向第一个卖家付款。
- 出现带有登录按钮的 PayPal 灯箱。
- 用户打开网站的第二个浏览器选项卡并开始向第二个卖家付款。
- 再次出现带有登录按钮的 PyaPal 灯箱。
- 用户返回到第一个浏览器选项卡并登录到 PayPal。
- 在第一个浏览器选项卡中登录 PayPal 后,用户会看到第二个卖家的付款详细信息。
- 在第二个浏览器选项卡中登录 PayPal 后,用户会看到第二个卖家的付款详细信息。
似乎 PayPal 自适应付款仅支持来自一位发件人的一笔交易。
这个怎么运作
该网站使用 Ruby on Rails,我使用paypal_adaptive gem通过 PayPal 付款。付款流程非常简单:
- 用户点击网站上的购买按钮。客户端发出 AJAX 请求,由 Ruby on Rails 中的支付控制器处理。
- 在控制器中,应用程序使用 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
我已经删除了一些不重要的代码,只是为了清楚它是如何工作的。
在此先感谢您的帮助!