Статьи

Интеграция PayPal, часть 3: веб-заезды PayPal

Конечный продукт
Что вы будете создавать

Webhook — это обратный вызов HTTP, который происходит, когда что-то происходит; простая система уведомлений о событиях через HTTP POST, которая позволяет разработчикам легко получать доступ к уведомлениям об операциях оплаты, таких как обновление статуса платежа или периодические платежи Вы можете выполнять действия на своем сервере после обработки каждого уведомления, например:

  • Отправить подтверждение покупки вашему клиенту.
  • Включить загрузку цифрового мультимедиа.
  • Выдать возврат.
  • Следите за тем, какие подписки активны.

Чтобы создать веб-крючок, перейдите на панель инструментов PayPal и нажмите « Мои приложения и учетные данные» . Затем выберите приложение, в котором вы хотите настроить Webhooks.

PayPal Developer

Вы можете увидеть подробную информацию о вашем приложении. Обратите внимание, что в правом верхнем углу есть две кнопки (Sandbox, Live), я буду использовать Sandbox в этом уроке, но вам нужно настроить параметры Live, прежде чем переходить в Live. Чтобы настроить Webhooks для этого приложения, нажмите Add Webhook, как показано на скриншоте:

Добавление WebHook

Выберите типы событий, которые вы заинтересованы в получении уведомлений, и введите URL-адрес, на который будут отправляться веб-хуки (это должен быть HTTPS). Для обработки вызовов Webhook я собираюсь добавить новый метод действия в HomeController под названием «Webhook»:

1
2
3
4
public IActionResult Webhook()
{
    // TODO: Handle Webhook call
}

Таким образом, URL-адрес Webhook в этом случае будет следующим: https://pedroalonso.localtunnel.me/home/webhook . Я объясню часть ‘localtunnel’ в следующем разделе.

Панель разработчика PayPal

Когда вы сохраните Webhook, вы увидите этот экран подтверждения:

Webhook создан успешно

Теперь, когда Webhook настроен, вы можете увидеть в левом меню «Webhooks Simulator», здесь вы можете отправить «тестовые» события webhook на ваш URL, чтобы проверить, работает ли ваш код. Кроме того, в разделе «События Webhooks» вы можете увидеть все события, отправленные PayPal для этого приложения. Вы можете проверить правильность обработки событий и повторно отправить их, если хотите провести дальнейшее тестирование.

Чтобы увидеть, как работают веб-хуки, я запустил проект, который мы создали в предыдущем уроке, и создал «авторизовать платеж и захватить позже», чтобы PayPal отправил событие. После запуска примера я нажал «Событие Webhooks» и увидел, что событие отправлено:

События Webhook

Как видите, справа есть кнопка « Переслать» , если вы хотите отладить свой код и посмотреть, как правильно реализовать обработчик. Кроме того, если вы нажмете на событие, вы можете увидеть все детали:

Детали события Webhook

Это полный JSON для события Webhook:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
    «id»: «WH-9U51749144910293K-8LX80763BC1567402»,
    «create_time»: «2016-01-19T17:50:30Z»,
    «resource_type»: «sale»,
    «event_type»: «PAYMENT.SALE.COMPLETED»,
    «summary»: «Payment completed for $ 100.0 USD»,
    «resource»: {
        «amount»: {
            «total»: «100.00»,
            «currency»: «USD»,
            «details»: {
                «subtotal»: «100.00»,
                «tax»: «15.00»,
                «shipping»: «10.00»
            }
        },
        «id»: «73G8209522783053E»,
        «parent_payment»: «PAY-7MB27930V5981832YK2PHN7Q»,
        «update_time»: «2016-01-19T17:49:05Z»,
        «create_time»: «2016-01-19T17:49:05Z»,
        «payment_mode»: «INSTANT_TRANSFER»,
        «state»: «completed»,
        «links»: [
            {
                «href»: «https://api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E»,
                «rel»: «self»,
                «method»: «GET»
            },
            {
                «href»: «https://api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E/refund»,
                «rel»: «refund»,
                «method»: «POST»
            },
            {
                «href»: «https://api.sandbox.paypal.com/v1/payments/payment/PAY-7MB27930V5981832YK2PHN7Q»,
                «rel»: «parent_payment»,
                «method»: «GET»
            }
        ],
        «protection_eligibility_type»: «ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE»,
        «transaction_fee»: {
            «value»: «3.20»,
            «currency»: «USD»
        },
        «protection_eligibility»: «ELIGIBLE»
    },
    «status»: «PENDING»,
    «transmissions»: [
        {
            «webhook_url»: «https://pedroalonso.localtunnel.me/home/webhook»,
            «response_headers»: {
                «Date»: «Wed, 20 Jan 2016 12:53:51 GMT»,
                «Content-Length»: «53»,
                «HTTP/1.1 502 Bad Gateway»: «»,
                «SERVER_INFO»: «»,
                «Connection»: «keep-alive»,
                «Server»: «nginx/1.7.8»
            },
            «transmission_id»: «218dc9c0-bed5-11e5-927f-6b62a8a99ac4»,
            «status»: «PENDING»,
            «timestamp»: «2016-01-19T17:50:30Z»
        }
    ],
    «links»: [
        {
            «href»: «https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402»,
            «rel»: «self»,
            «method»: «GET»,
            «encType»: «application/json»
        },
        {
            «href»: «https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402/resend»,
            «rel»: «resend»,
            «method»: «POST»,
            «encType»: «application/json»
        }
    ]
}

Как вы можете видеть на картинке, детали события закодированы в JSON, и они отправляются как тело запроса в ваш обработчик URL Webhook. Также есть несколько важных свойств, которые нам нужно использовать в нашем обработчике:

  • id : это идентификатор события webhook, и нам нужно отправить этот параметр в PayPal, если мы хотим получить конкретное событие webhook.
  • event_type : это используется, чтобы узнать тип события, которое мы получаем, поскольку нам, вероятно, нужно обрабатывать различные типы событий по-разному.
  • resource.parent_payment : это идентификатор платежа, с которым связано это событие. Возможно, этот идентификатор хранится в базе данных, и мы можем отправить электронное письмо нашему клиенту или отправить товары, приобретенные клиентом.

Исходя из предыдущего объяснения, это код контроллера действий для обработки Webhook:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public IActionResult Webhook()
{
    // The APIContext object can contain an optional override for the trusted certificate.
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    // Get the received request’s headers
    var requestheaders = HttpContext.Request.Headers;
 
    // Get the received request’s body
    var requestBody = string.Empty;
    using (var reader = new System.IO.StreamReader(HttpContext.Request.Body))
    {
        requestBody = reader.ReadToEnd();
    }
 
    dynamic jsonBody = JObject.Parse(requestBody);
    string webhookId = jsonBody.id;
    var ev = WebhookEvent.Get(apiContext, webhookId);
     
    // We have all the information the SDK needs, so perform the validation.
    // Note: at least on Sandbox environment this returns false.
    // var isValid = WebhookEvent.ValidateReceivedEvent(apiContext, ToNameValueCollection(requestheaders), requestBody, webhookId);
     
    switch (ev.event_type)
    {
        case «PAYMENT.CAPTURE.COMPLETED»:
            // Handle payment completed
            break;
        case «PAYMENT.CAPTURE.DENIED»:
            // Handle payment denied
            break;
            // Handle other webhooks
        default:
            break;
    }
 
    return new HttpStatusCodeResult(200);
}

Несколько вещей, чтобы объяснить из предыдущей функции. Из строк 10-16 я только читаю тело запроса и анализирую объект JSON для динамического объекта C #. В строке 18, которая является необязательной, я вызываю API PayPal с идентификатором события, чтобы получить полную информацию о событии. Это сделано для безопасности, чтобы убедиться, что я использую действительный объект PayPal. В строке 24 я создал переключатель для оценки типов веб-хуков, которые я хочу обрабатывать, и по мере необходимости пишу собственный код.

Как вы также можете видеть, строка 22 закомментирована. Очевидно, этот метод проверяет, что сертификат SSL из запроса действителен и принадлежит PayPal, но он не работает в режиме песочницы. Это может работать в Live, но мне не нравится, что в Live не тестируется код, особенно если он работает с платежным шлюзом, поэтому я решил удалить его и использовать другой подход. Если вы используете PHP-версию библиотеки PayPal SDK, имейте в виду, что функция ValidateReceivedEvent даже не существует.

Как вы видели ранее, для тестирования Webhooks нам нужно настроить публичный URL, который PayPal может использовать для отправки событий. Если мы работаем локально, обычно мы разрабатываем с использованием ‘localhost’, так что это будет небольшой проблемой. Чтобы решить эту проблему, нам нужно настроить безопасный туннель к нашему локальному компьютеру.

Localtunnel — это небольшая часть программного обеспечения, которая создает безопасный туннель между вашим локальным компьютером и общедоступным доменом. Это полезно для тестирования Webhooks, но вы также можете использовать его, чтобы делиться живыми URL-адресами с веб-приложениями, работающими на вашем компьютере разработчика, для целей тестирования, обратной связи или других задач.

Вам нужно иметь Node.js, чтобы иметь возможность установить localtunnel. Затем просто откройте консоль или терминал и запустите:

$ npm install -g localtunnel

Чтобы создать туннель, запустите:

$ lt --port 5000 --subdomain pedroalonso

Это отобразит URL « https://pedroalonso.localtunnel.me » на «localhost: 5000». Если вы запустите свой проект на IIS Express, вы, вероятно, будете использовать другой порт, поэтому вам необходимо отразить это в своей команде.

После настройки localtunnel и запуска нашего проекта я добавил точку останова в Visual Studio, чтобы оценить полученные данные. Как вы можете видеть на этом снимке экрана, я сопоставил объект события JSON с динамическим объектом C #.

Событие сопоставлено с динамическим объектом

Получая событие из API PayPal, используя идентификатор события, мы также получаем детали события, как вы можете видеть здесь:

Событие WebHook

Webhooks становятся стандартным способом для REST API уведомлять приложения о событиях. Как вы можете видеть, с ними довольно легко обращаться, и они используются многими компаниями, такими как Stripe, SendGrid, MailChimp и т. Д. PayPal имел уведомление о мгновенных платежах, и он все еще используется, но они рекомендуют внедрять Webhooks, когда это возможно. ,

Я думаю, что было бы действительно интересно, если бы другие потребительские приложения также предлагали Webhooks. Возможность запуска процесса на основе события в отдельном приложении чрезвычайно полезна и дает представление о будущем сети в реальном времени.