Skip to content

Commit d0846b4

Browse files
Merge pull request #14 from Virtual-Protocol/feat/acp-837-v2
2 parents 9668515 + dfca8ae commit d0846b4

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

examples/python/servers/fastapi/main.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ async def async_create_headers():
106106
# Custom dynamic pricing middleware for /acp-budget
107107
async def dynamic_price_middleware(request: Request, call_next):
108108
"""Middleware that reads price from X-Budget header"""
109-
if not request.url.path.startswith("/acp-budget"):
109+
if not request.url.path.startswith("/acp-budget") and not request.url.path.startswith("/acp-budget/v2"):
110110
return await call_next(request)
111111

112112
# Read dynamic price from X-Budget header
@@ -124,10 +124,13 @@ async def dynamic_price_middleware(request: Request, call_next):
124124
pay_to_address = ACP_V2_RECEIVER_ADDRESS
125125
else:
126126
pay_to_address = ACP_V1_RECEIVER_ADDRESS
127+
128+
if request.url.path.startswith("/acp-budget/v2"):
129+
pay_to_address = ACP_V2_RECEIVER_ADDRESS
127130

128131
# Use the standard require_payment middleware with dynamic price
129132
payment_middleware = require_payment(
130-
path="/acp-budget",
133+
path=["/acp-budget", "/acp-budget/v2"],
131134
price=budget, # ⭐ dynamic price
132135
pay_to_address=pay_to_address,
133136
network=NETWORK,
@@ -257,6 +260,32 @@ async def acp_budget(request: Request) -> Dict[str, Any]:
257260
}
258261
)
259262

263+
@app.api_route("/acp-budget/v2", methods=["GET", "POST"])
264+
async def acp_budget(request: Request) -> Dict[str, Any]:
265+
"""
266+
Handle both GET and POST requests for ACP budget payment.
267+
x402scan may use either method depending on the request.
268+
"""
269+
from fastapi.responses import JSONResponse
270+
271+
response_data = {
272+
"message": "pay acp job budget",
273+
"token": "acp job payment token",
274+
"protocol": "x402",
275+
"utility": "none",
276+
"vibes": "acp early adopter",
277+
"advice": "not financial advice",
278+
"method": request.method # Show which method was used
279+
}
280+
281+
# Explicitly disable compression for x402scan compatibility
282+
return JSONResponse(
283+
content=response_data,
284+
headers={
285+
"Content-Encoding": "identity", # Tell CloudFlare: no compression
286+
"Cache-Control": "no-transform", # Prevent any transformation
287+
}
288+
)
260289

261290
# @app.get("/premium/content")
262291
# async def get_premium_content() -> Dict[str, Any]:
13.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)