Continuous "Tag mismatch" (AES-GCM) decrypting Apple Pay Web token - Suspected KDF / PartyV environment issue

I'm implementing payment processing with Apple Pay on the web, but I've been stuck right at the final step of the flow: decrypting the payment data sent by Apple.

Here is a summary of my implementation:

The backend language is Java. The frontend portal requests the session and performs the payment using the endpoints exposed by the backend. I created .p12 files from the .cer files returned by the Apple Developer portal for both certificates (Merchant Identity and Payment Processing) and I'm using them in my backend.

The merchant validation works perfectly; the user is able to request a session and proceed to the payment sheet.

However, when the frontend sends the encrypted token back to my sale endpoint, the problem begins. My code consistently fails when trying to decrypt the data (inside the paymentData node) throwing a javax.crypto.AEADBadTagException: Tag mismatch!

I can confirm that the certificate used by Apple to encrypt the payment data is the correct one. The hash received from the PKPaymentToken (header.publicKeyHash) object exactly matches the hash generated manually on my side from my .p12 file.

In the decryption process, I'm using Bouncy Castle only to calculate the Elliptic Curve (ECC) shared secret. For the final AES-GCM decryption, I am using Java's native provider since I already have the bytes of the shared secret calculated. (Originally, I was doing it entirely with BC, but it failed with the exact same error).

We have exhaustively verified our cryptographic implementation:

We successfully reconstruct the ephemeralPublicKey and compute the ECDH Shared Secret using our Payment Processing Certificate's private key (prime256v1).

We perform the Key Derivation Function (KDF) using id-aes256-GCM, PartyU as Apple, and counter 00000001.

For PartyV, we have tried calculating the SHA-256 hash of our exact Merchant ID string.

We also extracted the exact ASN.1 hex payload from the certificate's extension OID 1.2.840.113635.100.6.32 and used it as PartyV.

We have tried generating brand new CSRs and Processing Certificates via OpenSSL directly from the terminal.

Despite having the correct ECDH shared secret (and confirming Apple used our public key via the hash), the AES tag validation always fails.et, the AES tag validation always fails.

Given that the math seems correct and the public key hashes match, could there be an environment mismatch (Sandbox vs. Production) or a domain validation issue causing Apple to encrypt the payload with a dummy PartyV or scramble the data altogether?

Any guidance on this behavior or the exact PartyV expected in this scenario would be highly appreciated.

Continuous "Tag mismatch" (AES-GCM) decrypting Apple Pay Web token - Suspected KDF / PartyV environment issue
 
 
Q