adyen: Paze + SamsungPay for Authorize and SetupRecurring (Paze verified live; SamsungPay blocked on device token) - #2031
Open
shuklatushar226 wants to merge 8 commits into
Open
adyen: Paze + SamsungPay for Authorize and SetupRecurring (Paze verified live; SamsungPay blocked on device token)#2031shuklatushar226 wants to merge 8 commits into
shuklatushar226 wants to merge 8 commits into
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add Samsung Pay wallet support to the Adyen Authorize flow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
[blocking] The new Paze path depends on extracting the right |
Auto-applied by CI: - cargo +nightly fmt --all - make -C sdk generate (if applicable) - make docs (if applicable) This commit was automatically generated by GitHub Actions.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…urring Follow-up to the four GRACE commits that added Paze and SamsungPay to the Adyen Authorize and SetupRecurring (SetupMandate) flows. Fixes the defects found by the hyperswitch parity check, the merged-PR review-theme audit, and the shadow-validation router-data comparison. Correctness / parity: - Drop the fabricated PAZE_DEFAULT_ECI = "05" default. Defaulting asserted a full-authentication liability shift Adyen never granted. The reference omits mpiData.eci when absent; verified live that Adyen accepts the omission. - Remove the blind .or_else fallback in the Paze TAVV lookup, which shipped any dynamic_data entry (e.g. a dynamic CVV) as the cryptogram when no CRYPTOGRAM_3DS was present. Now fails with the present types attached. - skip_serializing_if on AdyenNetworkTokenData.holder_name; the reference uses skip_serializing_none, so UCS was emitting "holderName": null. Reachability / capability: - Map PaymentMethodType::Paze to PaymentType::Scheme. Paze rides the network-token pass-through, so without this a Paze mandate could be created but never charged via RepeatPayment/MIT. - Register SamsungPay in ADYEN_SUPPORTED_PAYMENT_METHODS (was never added) and flip Paze mandates to Supported, matching the implemented SetupRecurring. - Add the missing PazeSdk arm to ForeignTryFrom<grpc PaymentMethod> for PaymentMethod; Paze fell to the catch-all and was rejected as an unsupported variant on every path that consults this mapping. Robustness: - Replace the SetupMandate wallet catch-all with explicit variants so a new upstream wallet is a compile error rather than a runtime NotImplemented. Verified live against the Adyen sandbox: Authorize+Paze (ECI present and absent) and SetupRecurring+Paze all return CHARGED; SamsungPay reaches Adyen and is refused only at token decryption (11_006), which requires a genuine device SDK payload. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…SamsungPay Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Auto-applied by CI: - cargo +nightly fmt --all - make -C sdk generate (if applicable) - make docs (if applicable) This commit was automatically generated by GitHub Actions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This shared GRACE branch (
feat/adyen_grace) now carries four pieces of Adyen work. Two are validated; two are not, so the PR as a whole remains do not merge until the Samsung Pay paths are resolved or split out.1b1c832d99e3c4de329aac731f78a6d97cc5Each section below documents one of these, newest first. The previously-written summaries are preserved verbatim.
1. SetupRecurring (SamsungPay) — FAIL (blocks merge)
Summary
[FAILED — DO NOT MERGE] Attempted implementation of the SetupRecurring flow (Rust flow name
SetupMandate) for the Samsung Pay payment method on the Adyen connector.This implementation was generated by GRACE (automated connector integration pipeline) but could not be validated end-to-end. This section is opened for visibility and review — it requires manual intervention before merging.
Failure Reason
The grpcurl SetupRecurring test could not be validated end-to-end.
The request payload is confirmed correct on the wire: Adyen accepted it and issued pspReference
RTQ7VTSBJXGQJC75, with none of the request-shape error codes14_015(token missing),14_007(paymentMethod object error), or14_394. Adyen then failed at token decryption:{"status":500,"errorCode":"11_006","message":"Unknown Samsung Payment error","errorType":"internal"}because
data/field_probe/adyen.jsoncarries a fabricated dummy base64samsungPayToken.Two controls isolate the cause to the token, not to this change:
11_006(pspReferenceN85MJ3L7QJ2ZTL65) — the failure predates and is independent of this change.status: CHARGED,connectorMandateId: CR5T7BJDD8H7LN65) — the sharedSetupMandateplumbing is healthy.This is UNDECIDED item 6 of the technical specification: Adyen publishes no Samsung Pay test payload, so a real SDK payload from a Samsung device in Adyen's test environment is required to validate this path.
cargo build -p connector-integrationandcargo fmt --checkboth pass.Changes
All changes are confined to the wallet
SetupMandateTryFromimpl inadyen/transformers.rs; no new flow wiring was needed inadyen.rs.TryFrom<(AdyenRouterData<RouterDataV2<SetupMandate, ..>, T>, &WalletData)> for SetupMandateRequest<T>so the match yields(payment_method, mpi_data)— the only wallet-specific parts of the request — with everything after it shared with the card path.WalletData::SamsungPay(..)arm buildingAdyenPaymentMethod::SamsungPay(AdyenSamsungPay { samsung_pay_token })frompayment_credential.token_data.data, forwarded verbatim — identical construction to the existing Authorize path.mpi_dataisNonefor Samsung Pay:SamsungPayDetailsisadditionalProperties: false, and the 3DS cryptogram travels inside the opaque token payload.mpiData); every other wallet still returnsNotImplemented.POST /storedPaymentMethodscannot be used for either wallet: itsPaymentMethodToStoreschema isadditionalProperties: falseand exposes no wallet token field. The recurring credential is therefore created as a side effect of a zero-value authorization withstorePaymentMethod+shopperReference+recurringProcessingModel.Files Modified
crates/integrations/connector-integration/src/connectors/adyen/transformers.rs(the only file modified by this commit)Related, unchanged by this commit:
crates/integrations/connector-integration/src/connectors/adyen.rsgRPC Test Results — SetupRecurring (SamsungPay)
Status: FAIL
11_006/ 500 — token decryption11_006/ 500 — identicalCHARGED/ 200grpcurl output / error details (credentials redacted)
Validation Checklist — SetupRecurring (SamsungPay)
cargo build -p connector-integrationpassed with zero errorscargo fmt --checkclean11_006, UNDECIDED item 6 of the tech spec)14_015/14_007/14_394)2. SetupRecurring (Paze) — PASS
Implement the SetupRecurring flow for the Paze payment method on the Adyen connector.
This implementation was generated and validated by GRACE (automated connector integration pipeline).
Implementation Notes
Adyen exposes no Paze-native
paymentMethod.type, so Paze SetupRecurring goes through the same self-managed network-token pass-through the Authorize flow already uses:paymentMethod.type=networkTokenwith the TAVV cryptogram carried inmpiData. The recurring credential is created as a side effect of a zero-value authorization withstorePaymentMethod: true(plusshopperReferenceandrecurringProcessingModel).Changes
build_paze_network_token_data(...) -> AdyenNetworkTokenData— DPAN, expiry, brand, holder name.build_paze_mpi_data(...) -> Result<AdyenMpiData, Error>— TAVV cryptogram + fully-authenticated directory/authentication response + ECI.TryFrom<(AdyenRouterData<RouterDataV2<SetupMandate, ..>, T>, &WalletData)> for SetupMandateRequest<T>. Paze only; every other wallet returnsNotImplemented.PaymentMethodData::Wallet(ref wallet_data)to that impl in theSetupMandatedispatch (previously it fell into theNotImplementedcatch-all).All changes are confined to
adyen/transformers.rs— no new flow wiring was needed inadyen.rs, sinceSetupMandatewas already registered for this connector.Files Modified
crates/integrations/connector-integration/src/connectors/adyen/transformers.rsgRPC Test Results — SetupRecurring (Paze)
Status: PASS
Three calls were run: the target test, plus two regression controls to prove the extracted helpers did not disturb the existing Paze Authorize or card SetupRecurring paths.
CHARGED/ 200CHARGED/ 200CHARGED/ 200grpcurl calls and responses (credentials redacted)
Validation Checklist — SetupRecurring (Paze)
cargo buildpassed with zero errorsCHARGED)cargo +nightly fmt --checkclean3. Authorize (SamsungPay) — FAIL (blocks merge)
The section below is the previously-written Samsung Pay summary, preserved verbatim.
Summary
[FAILED — DO NOT MERGE] Attempted implementation of the Authorize flow for the SamsungPay payment method on the Adyen connector.
This implementation was generated by GRACE (automated connector integration pipeline) but did not pass validation. This PR is opened for visibility and review — it requires manual intervention before merging.
Failure Reason
Build passed (
cargo buildgreen) and the outgoing request is verifiably correct on the wire, but the end-to-end grpcurl Authorize cannot return 2xx without a genuine Samsung Pay SDK token generated on a Samsung device.Adyen returns HTTP 422 / errorCode
11_002("Samsung Payment Info is missing required fields") for every synthetic token. Critically, Adyen did not return:14_015(token missing) — so thesamsungPayTokenfield is present and correctly named,14_007(paymentMethod object error) — so thepaymentMethodobject shape is accepted,901/905_3(configuration) — so the payment method type and merchant-account enablement are confirmed correct.Only token authenticity fails. Adyen publishes no static Samsung Pay test token. Credentials were not rejected (no 401/403).
Changes (validated build, unverifiable end-to-end)
AdyenSamsungPay { #[serde(rename = "samsungPayToken")] samsung_pay_token: Secret<String> }alongside the existingAdyenGPay/AdyenApplePaystructs.#[serde(rename = "samsungpay")] SamsungPay(Box<AdyenSamsungPay>)variant toAdyenPaymentMethod.WalletData::SamsungPay(..)arm to theTryFrom<(&WalletData, &RouterDataV2<Authorize, ..>)>impl, and removedWalletData::SamsungPay(_)from theNotImplementedcatch-all.mpi_datais intentionally left at the_ => Nonedefault for Samsung Pay — 3DS data travels inside the opaque token.samsungPayTokenispayment_credential.token_data.dataforwarded verbatim, matching this repo's Cybersource consumer ofSamsungPayWalletDataand the upstream hyperswitch Adyen connector. Three envelope variants were probed against Adyen and all returned an identical11_002, confirming the rejection is token authenticity, not envelope shape.Out of scope / unchanged: the
PaymentMethodType::SamsungPay -> PaymentType::Schememapping, which is used only for stored-token MIT (AdyenMandate).Files Modified
crates/integrations/connector-integration/src/connectors/adyen/transformers.rsgRPC Test Results — SamsungPay
Status: FAIL
grpcurl output / error details (credentials redacted)
Validation Checklist — SamsungPay
cargo buildpassed with zero errors11_002)Previously validated on this branch: Paze Authorize (PASS)
Summary
Implement Authorize flow for the Paze payment method on the Adyen connector.
This implementation was generated and validated by GRACE (automated connector integration pipeline).
Adyen exposes no Paze-native
paymentMethod.type. Paze is therefore integrated through Adyen's documented network-token pass-through: the decrypted Paze DPAN is submitted aspaymentMethod.type = "networkToken", and the TAVV cryptogram is carried separately inmpiData.Changes
adyen/transformers.rs—WalletData::Pazemoved out of theNotImplementedarm ofAdyenPaymentMethod::try_from((&WalletData, &RouterDataV2))and mapped to the existingAdyenPaymentMethod::NetworkTokenvariant, built from the decrypted Paze DPAN (number/expiryMonth/expiryYearexpanded to 4 digits /holderName/brandviaget_adyen_card_network).adyen/transformers.rs— newWalletData::Pazearm in the walletmpi_datamatch ofAdyenPaymentRequest:tokenAuthenticationVerificationValue= Paze TAVV,eci= Paze ECI (falling back toPAZE_DEFAULT_ECI = "05"),directoryResponseandauthenticationResponse="Y".shopperInteractionresolves toEcommercevia the existingAdyenShopperInteraction::from.adyen/transformers.rs— two helpers:get_paze_decrypted_data(handles bothPazeWalletData::Decryptedand theCompleteResponseJSON form, mirroring the existing cybersource pattern) andget_paze_token_cryptogram(picks theCRYPTOGRAM_3DSdynamic-data entry, falls back to the first entry carrying a value, and errors withMissingRequiredFieldif absent).adyen.rs— declaredPaymentMethod::Wallet/PaymentMethodType::PazeinADYEN_SUPPORTED_PAYMENT_METHODS.grace/rulesbook/codegen/references/specs/Adyen.md(1009 lines) from 13 verified Adyen documentation sources.Files Modified
crates/integrations/connector-integration/src/connectors/adyen.rscrates/integrations/connector-integration/src/connectors/adyen/transformers.rsgRPC Test Results
Status: PASS — both Paze payload variants (
decrypted_dataandcomplete_response) returnedCHARGEDagainst the Adyen sandbox.grpcurl Authorize call — Paze via
decrypted_data(credentials redacted)grpcurl Authorize call — Paze via
complete_responseraw decrypted JSON (credentials redacted)Validation Checklist
cargo buildpassed with zero errorsCHARGED)Post-implementation verification (orchestrator follow-up, commits
07caf924b,db25bb5d8)Three verification passes were run after the four implementation commits: a line-by-line
parity check against the hyperswitch reference Adyen connector, an audit against recurring
review themes mined from merged PRs, and a router-data comparison.
Live status against the Adyen sandbox
11_006)11_006)SamsungPay needs a genuine Samsung device SDK payload — Adyen publishes no static test
token. Both refusals returned real
pspReferencevalues and none of the request-shapeerrors (
14_015,14_007,14_394), so the payload shape, type tag, and merchant-accountenablement are confirmed correct. The SamsungPay
paymentMethodobject is byte-identicalto the reference implementation.
Defects found and fixed in
07caf924bmpiData.eci = "05"default, which asserted a full-authenticationliability shift Adyen never granted. Verified live that Adyen accepts the omission.
.or_elsefallback that shipped anydynamic_dataentry (e.g. a dynamicCVV) as the TAVV cryptogram when no
CRYPTOGRAM_3DSwas present.skip_serializing_ifonAdyenNetworkTokenData.holder_name— was emitting"holderName": null.PaymentMethodType::PazetoPaymentType::Scheme; without it a Paze mandate couldbe created but never charged via RepeatPayment/MIT.
ADYEN_SUPPORTED_PAYMENT_METHODS(never added) and flipped PazemandatestoSupportedto match the implemented SetupRecurring.PazeSdkarm toForeignTryFrom<grpc PaymentMethod> for PaymentMethod.Reviewer decision needed
mpiData.tokenAuthenticationVerificationValueintentionally carries the TAVV cryptogram;the reference sends the Payment Account Reference. UCS's mapping appears correct (a PAR is
an identifier, not an authentication value) but this field will diff on every Paze transaction
under shadow validation. See
grace/adyen_paze_samsungpay_deviations.md(D1).Not verified
Router-data shadow validation never ran end-to-end — the hyperswitch router was never built
locally and the machine's root disk is full. For the same reason
data/field_probe/adyen.jsonand
docs-generated/could not be regenerated, so the probe still recordsauthorize.Paze: not_supported(stale — it returns CHARGED live).Full write-ups:
grace/adyen_paze_samsungpay_parity_report.md,grace/adyen_pr_review_theme_audit.md,grace/adyen_shadow_validation_report.md,grace/adyen_paze_samsungpay_deviations.md.