# app/api/shopify.py import json import base64 import hmac import hashlib from fastapi import APIRouter, Request, HTTPException from app.core.config import settings router = APIRouter() def create_payme_payment_link(order_id: str, amount_uzs: float) -> str: """Generate a Payme checkout URL""" # Amount must be in tiyin (1 UZS = 100 tiyin) amount_tiyin = int(amount_uzs * 100) # Payme requires account params to be base64-encoded import json account = json.dumps({"order": str(order_id)}) account_encoded = base64.b64encode(account.encode()).decode() merchant_id = settings.PAYME_MERCHANT_ID # Payme checkout URL format params = f"m={merchant_id};ac.order={order_id};a={amount_tiyin}" params_encoded = base64.b64encode(params.encode()).decode() return f"https://checkout.paycom.uz/{params_encoded}" @router.post("/shopify/order-created") async def order_created(request: Request): raw_body = await request.body() # Verify Shopify webhook signature hmac_header = request.headers.get("X-Shopify-Hmac-Sha256") computed_hmac = base64.b64encode( hmac.new( settings.SHOPIFY_WEBHOOK_SECRET.encode(), raw_body, hashlib.sha256 ).digest() ).decode() if not hmac.compare_digest(computed_hmac, hmac_header or ""): raise HTTPException(status_code=401, detail="Invalid webhook") data = json.loads(raw_body) order_id = str(data["id"]) total_price = float(data["total_price"]) customer_email = data.get("email", "") # Generate Payme payment link payment_link = create_payme_payment_link(order_id, total_price) # Add the link as an order note in Shopify so customer can see it await add_payment_link_to_order(order_id, payment_link) return {"status": "payment_link_created", "link": payment_link} async def add_payment_link_to_order(order_id: str, payment_link: str): """Add payment link as a note on the Shopify order""" import httpx url = f"https://{settings.SHOPIFY_STORE_URL}/admin/api/2024-01/orders/{order_id}.json" headers = { "X-Shopify-Access-Token": settings.SHOPIFY_ACCESS_TOKEN, "Content-Type": "application/json", } payload = { "order": { "id": order_id, "note": f"Payme payment link: {payment_link}" } } async with httpx.AsyncClient() as client: await client.put(url, json=payload, headers=headers)