feat(golang): add Go implementation using x402 v2 protocol with testable architecture#65
feat(golang): add Go implementation using x402 v2 protocol with testable architecture#650xfakeSpike wants to merge 13 commits intogoogle-agentic-commerce:mainfrom
Conversation
…jection - Add ResourceServer and ExtensionChecker interfaces for testability - Add NewBusinessOrchestratorWithDeps constructor for dependency injection - Create resourceServerWrapper to adapt concrete type to interface - Maintain backward compatibility with existing code
…succeeds - Fix ensureExtension to return error even if transitionToFailed succeeds - Fix handlePaymentSubmitted to return error even if transitionToFailed succeeds - Ensures proper error propagation in payment flow
- Add TestExtractPaymentPayload with coverage for message and task extraction - Add TestExtractPaymentRequirements with error handling tests - Add TestExtractPaymentReceipts with multiple receipt scenarios
Update client configuration documentation to use 'networkName' instead of 'network' to match the actual configuration field name.
- ExtractPaymentStatus now only reads from task status, completely ignores message metadata - Merchant orchestrator only processes payment based on task state, not client-submitted status - Added PaymentRequired branch to handle client payment submission correctly - Updated tests to reflect security changes This fixes a critical security vulnerability where malicious clients could bypass payment verification by setting x402.payment.status in message metadata to 'payment-verified' or 'payment-completed'. Now merchant only uses task status which is merchant-controlled.
Previously, when payment failed, if marshalling the error message failed or if there was no message, the function would return nil, effectively swallowing the error. This could lead to payment failures being silently ignored. Now the function always returns an error in the PaymentFailed case: - First tries to marshal the full message object - Falls back to extracting text from message parts if marshalling fails - Returns a generic error if no message is available This ensures payment failures are never silently ignored.
… task Previously, when encountering an unknown payment state in a working task, if json.Marshal failed or if there was no message, the function would return nil, effectively swallowing the error. This could lead to silent failures. Now the function always returns an error when task is in working state with unknown payment state: - First tries to marshal the full message object - Falls back to extracting text from message parts if marshalling fails - Returns a generic error with payment state if no message is available This ensures unknown payment states in working tasks are never silently ignored and errors are properly propagated to the caller.
Previously, when payment verification failed, the task was transitioned to a failed state but then the verification error was returned. This caused the Execute method in the orchestrator to propagate an error, suggesting an orchestrator failure rather than a normal business flow failure. After successfully transitioning the task to a failed state, the function now returns nil, nil. This indicates that the request was handled successfully (by failing the task), allowing the orchestrator's Execute method to complete without an error, which is consistent with how other business logic failures are handled.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a full Go implementation of the x402 Agent-to-Agent (A2A) payment protocol, focusing on version 2. The changes establish a robust and testable architecture for both merchant and client functionalities, complete with example applications. It also includes significant improvements in error handling and comprehensive test coverage to ensure reliability and maintainability. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive Go implementation for the x402 A2A payment protocol, including both client and merchant components, along with a full set of tests and example applications. The architecture is well-designed for testability, with clear separation of concerns and dependency injection through interfaces like ResourceServer and ExtensionChecker. The state management and error handling are generally robust. I've identified a few areas for improvement, including a potential race condition in the merchant's payment handling logic, some code duplication in the client, and an ignored error in the example code. Overall, this is a high-quality contribution that significantly expands the project's capabilities.
- Reorder payment settlement to execute before business logic
* Prevents side effects (e.g., image generation) if settlement fails
* If business logic fails after successful settlement, merchant can handle
as business-level issue (e.g., refund) rather than protocol failure
- Refactor duplicated error message extraction logic
* Extract common error message extraction into extractErrorMessage helper
* Reduces code duplication in PaymentFailed and default cases
* Improves maintainability and readability
- Improve error handling in image service
* Add proper error logging for file write operations
| "prompt": prompt, | ||
| } | ||
|
|
||
| // if imageBase64 != "" { |
There was a problem hiding this comment.
Can we uncomment this to handle the image generation or include it in the datapart response
| }, nil | ||
| } | ||
|
|
||
| func (o *BusinessOrchestrator) settlePayment( |
There was a problem hiding this comment.
Here we are currently returning nil for the response. The x402 spec requires that we append all settlement attempts (including failures) to the x402.payment.receipts array. Could you update settlePayment to return the settleResponse even if it fails, so handlePaymentVerified can properly record the failed receipt before transitioning to the failed state?
Summary
Add complete Go implementation of x402 A2A payment protocol with improved architecture for testability and comprehensive test coverage.
Changes
Features
Refactoring
Fixes
Testing
Files Changed