Мгновенное обновление PayPal CallbackURL не вызывается в режиме реального времени
Я работаю над интеграцией PayPal Express Checkout в существующее веб-приложение, для которого я уже настроил Google Checkout и Amazon Payments (как SimplePay, так и CBA). Так что я не новичок в этом.
Все, в том числе мгновенный обратный вызов обновления, прекрасно работает в настройках, которые используют параметры песочницы. Обратный вызов отлично работает как по HTTP, так и по HTTPS в песочнице. Но как только я переключаюсь на учетные данные Live, пользовательский интерфейс PayPal перестает использовать CallbackURL и возвращается к использованию (откат) стоимости доставки, отправленной в SetExpressCheckout. Очевидно, что налоги вообще не рассчитываются.
Я использую последнюю версию PayPal PHP SDK (версия 106.0). Единственные настройки, которые изменяются для переключения настроек из Песочницы в Live:
- UserName
- пароль
- Подпись
- режим (от
sandbox
вlive
)
Я вижу похожую проблему, опубликованную на справочном форуме сообщества PayPal, но в ней не упоминается решение. По какой-то причине я не могу писать в этой теме... возможно, потому что она заархивирована.
Обновление 16.09.2013: Кажется, это проблема, связанная с HTTPS. Песочница также не работает на HTTPS, но при обращении к URL обратного вызова из браузера не возникает ошибка SSL. Сертификат действителен и вполне приемлем для других поставщиков платежей, которые мы используем на сайте: Google Wallet и Amazon Payments.
3 ответа
Эта проблема была исправлена с помощью: 1. Установка CallbackTimeout на 6 2. Использование SSL-сертификата, который принят PayPal. В нашем случае сертификат был выдан "Go Daddy Root Secure Certificate - G2", который не был принят системой PayPal.
У меня была эта проблема с сертификатом Godaddy UCC, но у меня не было проблемы с сертификатом не UCC. Поэтому мне пришлось написать прокси, чтобы перенаправить запрос в нужное место.
Однако в последнее время это тоже не удалось с моим сертификатом Godaddy, поэтому они, кажется, менее разрешительный, чем более разрешительный. Это даже терпит неудачу с сертификатом EV.
Это не имеет никакого смысла. Все, что делает URL-адрес обратного вызова, - это тарифы на доставку! Насколько безопасным должен быть этот процесс? Это нелепо! Никакое решение, кроме изменения сертификата, которое я даже не могу гарантировать, будет работать.
Мне удалось заставить его работать с бесплатным сертификатом от startcom.org
(слышал о безопасности сейчас подкаст).
Их веб-сайт ужасен, но PayPal, кажется, в порядке со своим сертификатом, где они не в порядке с сертификатом Godaddy - оба 4096 бит. Плюс это бесплатно:-) Хотя только год хорош.
Как только я перешел на этот сертификат, он работал нормально.
Для PayPal было определенно что-то недопустимое в отношении выданного сертификата GoDadaddy/Starfield.
Также есть сервис ngrok
который я нашел очень полезным, чтобы позволить мне проверить на месте. Это позволяет вам настроить туннельный прокси, который доступен снаружи. Даже не касаясь настроек брандмауэра, вы можете создать такой адрес, как http://83def5f1.ngrok.io
это доступно через PayPal и перенаправляет трафик на ваш локальный компьютер, позволяя вам устанавливать точки останова.
Страница прокси
(Совершенно не связано с нгрок)
Я предпочел не использовать этот сертификат для своих живых сайтов (плюс у меня есть несколько разных сайтов на сертификатах UCC, которые я не хотел менять), поэтому я создал прокси-страницу, которая перенаправляет запрос на нужный сервер. Затем я просто отправляю следующее в PayPal
"https://example.com/paypalproxy.aspx?callbackUrl=" + HttpUtility.UrlEncode(callbackUrl)
(Куда callbackUrl
ваш обычный URL обратного вызова, который вы отправляете в PayPal)
Прокси-сервер является страницей ASPX - его не нужно компилировать, просто поместив на веб-сайт.NET IIS.
Вы можете проверить, чтобы увидеть последний запрос / ответ, вызывающий его с ?debug=Y
<%@ Page language="c#" AutoEventWireup="true" %>
<%@ Import Namespace="System.IO"%>
<Script runat="server" language="C#">
private static string _lastURL;
private static string _lastRequest = "";
private static string _lastResponse = "";
private static DateTime? _lastTime;
private static int _lastDurationMs;
private void Page_Load(object sender, System.EventArgs e)
{
// no cache
Response.Cache.SetCacheability(HttpCacheability.NoCache);
var sw = new System.Diagnostics.Stopwatch();
var wc = new System.Net.WebClient();
sw.Start();
var callbackUrl = Request.Params["callbackUrl"];
var debugMode = Request.Params["debug"] == "Y";
if (debugMode)
{
Response.ContentType = "text/text";
Response.Write(_lastTime + "\n");
Response.Write("LastURL = ["+_lastURL+"]\n\n");
Response.Write("LastDuration = [" + _lastDurationMs +"]\n\n");
Response.Write("REQUEST: \n[\n "+_lastRequest.Replace("&", "&\n ")+"\n]\n\n");
Response.Write("RESPONSE: \n[\n "+_lastResponse.Replace("&", "&\n ")+"\n]");
Response.End();
return;
}
_lastDurationMs = -1;
_lastURL = Request.Params["callbackUrl"];
_lastTime = DateTime.Now;
if (callbackUrl.Contains("dev."))
{
throw new ApplicationException("Callback shouldn't be to a dev machine!");
}
if (callbackUrl.Contains("https") == false)
{
throw new ApplicationException("Callback must be https");
}
var newUri = callbackUrl + "?" + Request.Form.ToString();
var str = wc.DownloadString(newUri);
_lastRequest = Request.Form.ToString();
_lastResponse = str;
_lastDurationMs = (int)sw.ElapsedMilliseconds;
Response.Write(str);
Response.End();
}
</Script>