PayPal Adaptive Payments: два платежа от одного отправителя на двух вкладках браузера
Я использую адаптивные платежи PayPal (параллельные) на своем веб-сайте, и я столкнулся со странной проблемой с двумя платежами в двух разных вкладках браузера от одного отправителя. Подобный вопрос задавался и раньше, но там никто не ответил.
Сценарий, который воспроизводит проблему
- Пользователь открывает первую вкладку браузера веб-сайта и начинает процесс оплаты первого продавца.
- Появится лайтбокс PayPal с кнопкой входа в систему.
- Пользователь открывает вторую вкладку браузера веб-сайта и начинает процесс оплаты для второго продавца.
- Снова появляется лайтбокс PyaPal с кнопкой входа в систему.
- Пользователь возвращается на первую вкладку браузера и входит в систему PayPal.
- После входа в PayPal на первой вкладке браузера пользователь видит реквизиты платежа для второго продавца.
- После входа в PayPal во второй вкладке браузера пользователь видит реквизиты платежа для второго продавца.
Похоже, что PayPal Adaptive Payments поддерживает только одну транзакцию от одного отправителя.
Как это устроено
Сайт работает с Ruby on Rails, и я использую гем paypal_adaptive для платежей через PayPal. Поток платежей довольно прост:
- Пользователь нажимает кнопку "Купить" на сайте. Клиент делает AJAX-запрос, который обрабатывается контроллером платежей в Ruby on Rails.
- В контроллере приложение отправляет запрос Pay в PayPal API, используя гем paypal_adaptive, и получает 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
Я удалил какой-то неважный код, чтобы понять, как он на самом деле работает.
Заранее спасибо за помощь!
1 ответ
Похоже, что это дизайн. Я попробовал этот же тест здесь на веб-сайте одного из сотрудников PayPal, и он воспроизводится там.
Поддержка PayPal ответила мне, что проблема в использовании Lightbox. Тем не менее, я пробовал варианты Mini-Browser и Popup, как я описал в своем посте, безрезультатно.
Кроме того, служба поддержки PayPal ответила мне, что это сделано специально, и посоветовала мне обратиться в службу технической поддержки. Может быть, это будет полезно для кого-то еще.
Привет, Майкл, спасибо, да, я также смог воспроизвести это. Однако важно понимать, что PayPal не предназначен для обработки двух потоков платежей одновременно. Если вы хотите получить дополнительную информацию об этом, вы можете обратиться в нашу службу технической поддержки: https://ppmts.custhelp.com/ У них есть другие инструменты для отладки, и они могут помочь вам лучше понять техническую проблему.
Наконец, я заблокировал одновременные платежи, используя специальный флаг в HTML5 Local Storage и dgFlow.isOpen()
метод PAYPAL.apps.DGFlow
объект для обнаружения окна PayPal. При закрытии окна я сбрасываю этот флаг, используя onunload
а также onbeforeunload
события window
,
Я закрываю этот вопрос. Благодарю.