Вопрос или проблема
Я пытаюсь использовать PaymentRequest javascript API. На данный момент у меня есть следующий код (репозиторий), который работает довольно хорошо, пока браузер не отправляет запрос на default_applications
url.
Пользователь нажимает кнопку оплаты и создает и показывает PaymentRequest
<head>
<script type="text/javascript">
function pay() {
const createRequest = () => new PaymentRequest(
[
{
supportedMethods: "https://localhost:7208/pay",
// supportedMethods: "https://play.google.com/billing",
data: {}
},
],
{
total: { label: 'Donation', amount: { currency: 'USD', value: '55.00' } },
displayItems: [ ... ],
},
);
createRequest().canMakePayment().then(can => {
createRequest().show().then(function (data) { console.log("Data", data); });
});
}
</script>
</head>
<body>
<button onclick="pay()">Начать оплату</button>
</body>
Это вызывает HEAD запрос к https://localhost:7208/pay
, который обрабатывается следующим образом
app.MapMethods("/pay", [HttpMethods.Head], async (context) =>
{
context.Response.Headers["Link"] = "</pay/payment-manifest.json>; rel=\"payment-method-manifest\"";
});
Теперь браузер хочет прочитать манифест платежа, на что я отвечаю следующим образом
app.MapGet("/pay/payment-manifest.json", async (context) =>
{
await context.Response.WriteAsJsonAsync(new
{
default_applications = new string[]
{
"https://localhost:7208/manifest.json"
},
supported_origins = new string[]
{
"https://localhost:7208"
}
});
});
Почему-то, по причинам, которые я еще не понимаю, браузер затем хочет получить мой PWA манифест.json, в любом случае, я отправляю этот ответ обратно
app.MapGet("/manifest.json", async (context) =>
{
await context.Response.WriteAsJsonAsync(new
{
name = "Пример",
short_name = "Пример",
theme_color = "#1976d2",
background_color = "#fafafa",
display = "standalone",
scope = "/",
start_url = "/",
icons = new[] {
new {
src = "music_note_192.png",
sizes = "192x192",
type = "image/png"
},
},
serviceworker = new {
src = "worker.js",
scope = "/",
use_cache = false,
}
});
});
А теперь браузер также хочет доступ к моему сервис-воркеру, из-за этого я заполнил это поле в манифесте выше. worker.js
пока возвращает следующий ответ:
(() => {
})();
Тем не менее, я все еще получаю ошибку в консоли браузера. И не могу разобраться, как это сделать.
Uncaught (in promise) AbortError: Payment handler did not respond to “paymentrequest” event.
Ответ или решение
Для успешного использования API PaymentRequest в ASP.NET Core важно гарантировать, что ваш сервер правильно обрабатывает запросы от браузера и что структура манифеста соответствует ожиданиям браузера. Давайте разберем ваш код и выявим потенциальные проблемы, а затем предложим решения.
Шаги для решения проблемы
-
Обработка запроса на загрузку манифеста платежного метода:
Убедитесь, что ваш обработчикMapMethods
для URL/pay
возвращает правильный заголовок дляLink
, а также что вы возвращаете корректный JSON-ответ при запросе/pay/payment-manifest.json
.Ваш код уже выглядит корректно, но убедитесь, что
https://localhost:7208/pay
действительно доступен в вашем окружении и что у вас корректно настроен сервер. -
Проверка манифеста платежного метода:
Убедитесь, что ваше приложение действительно может быть идентифицировано как платежный обработчик. В вашем манифесте платежного метода нужно убедиться, что вы правильно указалиdefault_applications
. Убедитесь, что JSON-ответ имеет корректный формат.Пример вашего манифеста:
{ "default_applications": [ "https://localhost:7208/manifest.json" ], "supported_origins": [ "https://localhost:7208" ] }
-
Обработка события
paymentrequest
в service worker:
Код вашего service worker (worker.js
) не содержит логики для обработки событияpaymentrequest
. Вам нужно добавить обработчик, который будет слушать это событие и отвечать на него:Пример реализации service worker:
self.addEventListener('paymentrequest', (event) => { event.respondWith(new Promise((resolve, reject) => { // Здесь вы должны обработать платеж, например, проанализировать данные и вернуть результат const paymentResponse = { payment: { // Здесь вы можете указать детали платежа, если нужно } }; // Подтверждение платежа, если все верно resolve(paymentResponse); })); });
-
Отказ от тестирования на localhost:
Поскольку многие браузеры ограничивают работу с API PaymentRequest при использованииlocalhost
, попробуйте использовать HTTPS-сервер с реальным доменом или, по крайней мере, настройте вашhosts
файл для использования имени домена. Например,myapp.local
. -
Получение ошибок:
Сообщение об ошибкеAbortError: Payment handler did not respond to "paymentrequest" event
говорит о том, что обработчик платежей не ответил на событиеpaymentrequest
. Проверьте вашу логику в service worker и убедитесь, что ваш интерфейс пользователя ожидает, что вы выполните необходимые действия, прежде чем эта ошибка появится.
Заключение
После внесения предложенных правок протестируйте свое приложение заново. Убедитесь, что все URL доступны, и что ваш service worker правильно обрабатывает события. Если возникнут дополнительные ошибки, добавьте отладочные сообщения в ваш код, чтобы лучше понять, где возникают проблемы. Эта структура охватывает основные шаги по настройке API PaymentRequest с использованием ASP.NET Core и service worker, и, надеюсь, поможет вам успешно реализовать платежную систему.