Hi,
I was wondering if it's possible to use our API (backend app) in between my website (frontend app) and Apple servers.
This means having a website (frontend app) with all the logic to present the Apple Pay button and handle ApplePaySession events, on the click to pay it communicates with our API (backend app), and that will communicate with Apple servers. Receiving the response and send it back to the front-end website.
With Merchant Identity Certificate set up for the API, and assuming that for the Domain validation, we need only the API domain as well.
As an example let's say that the website runs on https://website.example.com and the API on https://api.example.com, both as HTTPS. So the flow would be:
Website (frontend app) <-> API (backend app) <-> Apple server
Is this implementation possible?
Thanks!
Apple Pay on the Web
RSS for tagApple Pay on the Web allows you to accept Apple Pay on your website using JavaScript-based APIs.
Posts under Apple Pay on the Web tag
109 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hi Team
I am trying to integrate apple pay into my system but session.completeMerchantValidation() is failing
Error
For generating merchant session I am using this url
https://apple-pay-gateway-cert.apple.com/paymentservices/paymentSession
In response i am getting merchant session but after passing that merchant session I am getting error as mentioned above in the image
I am stuck since 2 weeks but not getting any solution, your quick response will clear my blocker
Regards
Rutvij Doshi
I have troubles sometimes (with slow internet connections) when the customers clicks on my Buy Now button, i got the error "Must crerate a new ApplePaySession from a user gesture hanlder..."
I removed some logics to shipping to nt make this too long, but essentially my code is:
export default function ApplePayButton({setLoadingApple}) {
// Effects
React.useEffect(() => {
// listen click
const button = document.querySelector('apple-pay-button')
if(button){
button.addEventListener('click', startApplePaySession)
}
return () => {
button.removeEventListener('click', startApplePaySession)
}
}, [])
// Methods
const selectStep = step => {
// Check if step is available
if (state.steps.allowed >= step) {
dispatch({
type: 'UPDATE_STEPS',
data: {
...state.steps,
current: step
}
})
}
}
const startApplePaySession = () => {
const apple = window.buckedup.payment_extensions.find(extension => extension.code === 'apple_pay')
if (window.ApplePaySession && apple) {
setLoadingApple(true)
let clientToken
if (window.braintree_config) {
const {
token
} = window.braintree_config
clientToken = token
}
window.braintree.client.create({
authorization: clientToken
}, (clientErr, clientInstance) => {
if (clientErr) {
setLoadingApple(false)
console.error('Error creating client:', clientErr)
return
}
window.braintree.applePay.create({
client: clientInstance
}, (applePayErr, applePayInstance) => {
if (applePayErr) {
setLoadingApple(false)
console.error('Error creating applePayInstance:', applePayErr)
return
}
const amount = state.totals.amount_due.amount
const appleSession = window.ApplePaySession
// Build request object
const request = applePayInstance.createPaymentRequest({
'countryCode': 'US',
'currencyCode': 'USD',
'merchantCapabilities': [
'supports3DS',
'supportsDebit',
'supportsCredit'
],
'shippingMethods': [],
'shippingType': 'shipping',
'supportedNetworks': [
'visa',
'masterCard',
'amex',
'discover'
],
'requiredBillingContactFields': [
'postalAddress',
'name'
],
'requiredShippingContactFields': [
'postalAddress',
'name',
'phone',
'email'
],
'total': {
'label': 'Bucked Up',
'amount': amount,
'type': 'final'
}
})
// Define ApplePayPaymentRequest
const session = new appleSession(3, request)
// Validate merchant
session.onvalidatemerchant = async event => {
// Do request
const response = await getApplePay()
applePayInstance.performValidation({
validationURL: event.validationURL,
displayName: 'Bucked Up'
}, (err, merchantSession) => {
if (err) {
setLoadingApple(false)
return
}
session.completeMerchantValidation(response.data)
setLoadingApple(false)
})
}
// Validate payment method
session.onpaymentmethodselected = async event => {
// Update totals
const totals = await postApplePayment()
const update = {
'newTotal': {
'label': 'Bucked Up',
'amount': totals.data.amount_owed
}
}
session.completePaymentMethodSelection(update)
}
// Request to track shipping user data
session.onshippingcontactselected = async event => {
// Extract user available
const dataShipping = event.shippingContact
let body
// Do first request to checkout endpoint
const responseData = await shippingService(body)
if (responseData.success) {
// Get Shipping methods
const body = {
combined_shipments: true
}
const responseMethods = await getMethods(body)
if (responseMethods.success) {
const methods = responseMethods.data.shipments
// Do request to update totals
const responseTotals = await postApplePayment()
const update = {
'newTotal': {
'label': 'Bucked Up',
'amount': responseTotals.data.amount_owed
},
'newShippingMethods': mappedMethods
}
session.completeShippingContactSelection(update)
}
}
}
// Authorize purchase
session.onpaymentauthorized = async (event) => {
applePayInstance.tokenize({
token: event.payment.token
}, async (tokenizeErr, payload) => {
if (tokenizeErr) {
console.error('Error tokenizing Apple Pay:', tokenizeErr)
session.completePayment(appleSession.STATUS_FAILURE)
return
}
const nonce = payload.nonce
const billing = event.payment.billingContact
const shipping = event.payment.shippingContact
const body = {
shipping,
billing
}
const response = await patchApplePayment(body)
if (response.success) {
// Process payment
const bodyBraintree = {
apple_pay: true,
payment_method_nonce: nonce
}
const responseBraintree = await postBraintree(bodyBraintree)
if (responseBraintree.success) {
// Define ApplePayPaymentAuthorizationResult
const result = {
'status': appleSession.STATUS_SUCCESS
}
session.completePayment(result)
location.href = `${API_URL}checkout/thank-you`
}
}
})
}
session.oncancel = (event) => {
console.log(event, 'session cancel')
setLoadingApple(false)
selectStep(1)
}
session.begin()
}
)
})
}
}
return (
<apple-pay-button buttonstyle='black' locale='en' type='plane' />
)
}
If the customer closes Apple payment sheet before validation is complete, the error appears.
It's not a big deal, but we are improving our performance, so I need to fix this annoying log:
My code to validate merchant works and is this (I'm using braintree with apple pay):
// Validate merchant
session.onvalidatemerchant = async event => {
// Do request
const response = await getApplePay()
console.log(response)
if (response.success) {
instance.performValidation({
validationURL: event.validationURL,
displayName: 'Bucked Up'
}, (err, merchantSession) => {
if (err) {
setLoadingApple(false)
session.abort()
return
} else if(merchantSession) {
session.completeMerchantValidation(response.data)
setLoadingApple(false)
}
})
} else {
setLoadingApple(false)
session.abort()
}
}
https://applepaydemo.apple.com/payment-request-api
using this code can anyone help me to configure and code setup for apple pay web
I tried to screen record the Apple Pay payment process but after merchant validation the payment authorization option disappears (not asking for touch id or password).
I could find anything related to this issue in apple pay docs or forums.
Can someone help or anyone else faced the same issue do let me know.
Hello!
I am working on developing a POC for Apple Pay on the Web for my website. When I go to request an Apple Pay Payment Session, I am getting the following error in my logs:
apple pay javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I know it has something to do with the certificates, but I am not sure what I am doing wrong. I am not seeing a great deal of documentation on Apple's developer site. I am using a sandbox account to test with test cards, and using the test endpoint url. Is there a way to get a test Payment Session locally without verifying my websites domain?
I can provide more info if needed. Thanks!
I am currently in the process of integrating Apple Pay into my website using the JavaScript SDK and have encountered a specific issue that I am unable to resolve.
I have successfully implemented the merchant validation part of the process; the merchant is being validated without any issues. However, I am facing a challenge with the onpaymentauthorized event, which is not being triggered. Instead, the session is getting canceled after the successful merchant validation.
Here are the details of the implementation:
SDK Used: Apple Pay JS SDK
Current Behavior: The merchant validation process completes successfully. However, the onpaymentauthorized event handler is not invoked, and the session is canceled.
Expected Behavior: After merchant validation, the onpaymentauthorized event should be triggered to complete the payment process.
I have checked the following:
The paymentRequest object configuration.
Browser compatibility (testing on supported browsers).
Network stability and configurations.
User interaction with the Apple Pay payment sheet.
Despite these checks, the issue persists. I would greatly appreciate any guidance or suggestions you could provide on what might be causing this issue and how to resolve it.
If there are any logs, code snippets, or additional information you require, please let me know, and I will provide them promptly.
Thanks
By mistake i have added funds to apple developer account. How to bring back
I know Apple Pay recently added some new token types for unscheduled card on file use cases.
In my app, I attain the token from Apple Pay, and then I submit that token to my gateway for full payment anywhere from 1-12 hours later-- after the user had used up the service. The final payment is based on a usage of the service.
Do I need to use the ApplePayDeferredPaymentRequest token type for this kind of use case?
Our apple pay integration with the gateway "Checkout.com" is succeeding from Checkout side & the amount is captured (withdrawn from bank account) and confirmed yet on the apple pay popup it fails with a "Payment not completed" error message. Any idea how to resolve this? This is on multiple devices (iPhones, MacBooks)
-The request in the headers is a success (200)
We have multiple domains that were about to expire and we've verified them without any issue but the Verify button is still present and active and the expiration date hasn't changed:
Found only one post related to our situation:
https://developer.apple.com/forums/thread/672279
Will removing and then adding them again fix this? We have multiple domains in this situation.
Hi all
Im trying to update deferDeferredPaymentRequest on event completeShippingMethodSelection
API ver 14
So Im using ApplePayShippingMethodUpdate object which contains newDeferredPaymentRequest
But deferred payment cannot be updated.
Here is my ApplePayDeferredPaymentRequest object for newDeferredPaymentRequest:
"deferredBilling": {
"label": "Pay for Later",
"amount": 68,
"paymentTiming": "deferred",
"type": "final",
"deferredPaymentDate": "2024-01-25"
},
"managementURL": "https://siteURL.com",
"paymentDescription": "A description of the deferred payment to display to the user in the payment sheet.",
"freeCancellationDate": "2024-01-25",
"freeCancellationDateTimeZone": "America/New_York"
}
Even I tried to put mistake for newDeferredPaymentRequest but ApplePay doesn't throw a JS error
Can we update deferred ?
for example, ApplePayRecurringPaymentRequest can't be updated according to documentation https://developer.apple.com/documentation/apple_pay_on_the_web/applepayrecurringpaymentrequest
But I can't find same info for Deferred.
Who can help me with it?
Hello,
Here's some sample Javascript code:
if (window.ApplePaySession) {
console.log('ApplePaySession is available');
console.log('canMakePayments: ' + ApplePaySession.canMakePayments());
ApplePaySession.canMakePaymentsWithActiveCard(merchantId)
.then(function(canMakePayments) {
console.log('canMakePaymentsWithActiveCard: ' + canMakePayments);
});
} else {
console.log('ApplePaySession is not available');
}
I'm logged into macOS with a sandbox test account that has Apple Pay permissions. The merchantId value is the one listed with my merchant ID. I'm running this locally. canMakePayments returns true, but canMakePaymentsWithActiveCard always returns false.
I have two test cards setup in the macOS account's Apple Pay wallet, and both have a billing address setup.
What can I do to troubleshoot why ApplePaySession.canMakePaymentsWithActiveCard is returning false?
Hi, I have a question about the merchant ID domain verification file. Do we need to store that file on our site permanently, or can we delete it after domain verification? I searched for this information in the documentation, but found nothing specific.
https://developer.apple.com/documentation/applepaywebmerchantregistrationapi/preparing_merchant_domains_for_verification
Trying to get Apple Pay with PayPal to work in our Wordpress WooCommerce platform. We've done all of the registration, and have uploaded the apple-developer-merchantid-domain-association data file to .well-known but the file can not be read. It is 644 permission and we have removed the extension per Apple Support, but the link is still not readable and gives a 404 error. If I add a dat or txt extension, it is readable to a web browser, but Apple still doesn't see the file as it doesn't want the extension.
I even tried an order with Apple Pay but it failed. PayPal is useless and just send us to Apple, and Apple doesn't seem to have much on it either. Searching the support files I only find 5 year old posts.
Google Pay works without issue, *** do credit cards and PayPal. Just no Apple Pay.
The instructions are pretty basic:
Download and host live domain association file
Host a domain association file for each high-level domain and subdomain that show the Apple Pay button.
Download the domain association file for your live environment.
Host the file on your live site for each domain and subdomain you want to register, at /.well-known/apple-developer-merchantid-domain-association. For example:
https://example.com/.well-known/apple-developer-merchantid-domain-association
https://subdomain.example.com/.well-known/apple-developer-merchantid-domain-association
Hello,
I'm not sure this is the right place to ask this question, but we've a scenario that I'd like to get some help on. We're integrated with Stripe, and have enabled Apple Pay for Stripe accounts. So, in order for the domain to be verified to enable apple pay, we're hosting the file apple-developer-merchantid-domain-association under ${domain}/.well-known/. And that's working great.
Now, we also want to enable apple pay through another payment processor Cardknox, for which the integration is done. But for domain verification purposes, we've to host a different apple-developer-merchantid-domain-association in the same directory. So, if I update the file contents, domain verification through Stripe will fail, and vice-versa.
I'm sure this must have come up before, and I'd like to know your opinion on how we can resolve this. Is there a way to configure different paths for verification?
Thanks a lot.
I received an email.
There was a request to renew the domain registered with the Apple Pay Merchant ID as it was expiring.
I went into my Merchant ID to renew, but couldn't find a way.
How do I renew?
As the document mentioned "Host your domain-verification file at the following path for each domain you’re registering:
https://[DOMAIN_NAME]/.well-known/apple-developer-merchantid-domain-association" and that file contain "pspId" and "signature" so just want to know these are not sensitive it gets in the hands of an attacker ??
HI,
ApplePay was working fine. Since we did a dot net upgrade to 6.026 on the server it has stopped working I think it is to do with the above issue.
In the code we set the protocol which matches what's on the server:
ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls12;
Has anyone experienced this before?