Reputation: 3521
I'm trying to use the PaymentRequest javascript API. Up until now I have the following code (repo), which runs quite fine until the browser sends a request to the default_applications
url.
The user clicks the pay button, and creates and shows a 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()">Start payment</button>
</body>
This triggers a HEAD request to https://localhost:7208/pay
which is handled like this
app.MapMethods("/pay", [HttpMethods.Head], async (context) =>
{
context.Response.Headers["Link"] = "</pay/payment-manifest.json>; rel=\"payment-method-manifest\"";
});
Now the browser wants to read the payment manifest, to which I reply with this
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"
}
});
});
Somehow, for a reason I don't understand yet, the browser then wants to fetch my PWA manifest.json, in any case, I send this response back
app.MapGet("/manifest.json", async (context) =>
{
await context.Response.WriteAsJsonAsync(new
{
name = "Example",
short_name = "Example",
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,
}
});
});
And now the browser also wants access to my service worker, because of this I filled out this field in the manifest above. worker.js
returns the following response for now:
(() => {
})();
However, I'm still getting an error in the browser console. And can't figure out how to make this work.
Uncaught (in promise) AbortError: Payment handler did not respond to "paymentrequest" event.
Upvotes: 0
Views: 58
Reputation: 21838
The root cause is missing paymentrequest
event handler in your worker.js
.
After investigating the repo, this repo is not finished yet, hope the owner will keep to update it.
You can set breakpoint in my test code to check the payment process.
Here is my working sample.
worker.js
// worker.js
self.addEventListener('paymentrequest', function (event) {
// Handle the payment request
event.respondWith(handlePaymentRequest(event));
});
async function handlePaymentRequest(event) {
// Extract payment details
const methodData = event.methodData;
const details = event.total;
const modifiers = event.modifiers;
// Process the payment (e.g., show a custom payment UI)
// For demonstration, we'll return a dummy response
return {
methodName: methodData[0].supportedMethods,
details: {
confirmationNumber: '1234567890', // Custom response data
},
};
}
Overview.cshtml
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/worker.js')
.then(function (registration) {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(function (error) {
console.error('Service Worker registration failed:', error);
});
} else {
console.error('Service Workers are not supported in this browser.');
}
function pay() {
const request = new PaymentRequest(
[
{
supportedMethods: "https://localhost:7208/pay",
//supportedMethods: "https://play.google.com/billing",
data: {}
},
],
{
total: { label: 'Donation', amount: { currency: 'USD', value: '55.00' } },
displayItems: [
{
label: 'Original donation amount',
amount: { currency: 'USD', value: '65.00' },
},
{
label: 'Friends and family discount',
amount: { currency: 'USD', value: '-10.00' },
},
],
},
);
request.canMakePayment().then(function (canMakePayment) {
if (canMakePayment) {
request.show().then(function (paymentResponse) {
console.log("Payment Response:", paymentResponse);
paymentResponse.complete('success').then(function () {
console.log('Payment completed successfully.');
alert('Payment successful!');
}).catch(function (err) {
console.error('Payment completion failed:', err);
});
}).catch(function (err) {
console.error('Payment failed:', err);
});
} else {
console.log('Cannot make payment.');
alert('Cannot make payment.');
}
}).catch(function (err) {
console.error('canMakePayment() failed:', err);
});
}
</script>
</head>
<body>
<button onclick="pay()">Start payment</button>
</body>
</html>
Still has some issue since the owner not use static files like payment-manifest.json
and manifest.json
, the error like below.
Upvotes: 0