请基于这个api后端构建对应的react支付页面：

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import hashlib
import time
import httpx
from urllib.parse import urlencode, unquote_plus
import os
from typing import Dict, Any
import logging
import config

app = FastAPI()

# Setup CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Change this for production
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Setup logging
logging.basicConfig(level=logging.INFO)

# Pydantic models
class PaymentRequest(BaseModel):
    trade_order_id: str
    payment: str
    total_fee: float
    title: str

class PaymentResponse(BaseModel):
    status: str
    transaction_id: str
    trade_order_id: str
    amount: float
    message: str

# Hupi utility functions
def ksort(d: Dict[str, Any]) -> Dict[str, Any]:
    return dict(sorted(d.items()))

def sign(attributes: Dict[str, Any], app_secret: str) -> str:
    attributes = ksort(attributes)
    sign_str = unquote_plus(urlencode(attributes)) + app_secret
    logging.info(f"String to hash: {sign_str}")
    return hashlib.md5(sign_str.encode('utf-8')).hexdigest()

async def curl(data: Dict[str, Any], url: str, app_secret: str) -> Dict[str, Any]:
    data['hash'] = sign(data, app_secret)
    headers = {"Referer": "http://localhost:5000"}
    async with httpx.AsyncClient() as client:
        response = await client.post(url, data=data, headers=headers)
    return response.json()

async def process_payment(payment_data: PaymentRequest) -> Dict[str, Any]:
    appid = os.getenv("HUPI_APPID", "202303140058")
    app_secret = os.getenv("HUPI_APPSECRET", "60b31fde738c25dd0b28f7bff7f06311")
    url = "https://api.xunhuweb.com/payment/do.html"
    current_time = str(int(time.time()))
    
    data = {
        "version": "1.1",
        "lang": "zh-cn",
        "plugins": "fastapi",
        "appid": appid,
        "trade_order_id": payment_data.trade_order_id,
        "payment": payment_data.payment,
        "is_app": "Y",
        "total_fee": payment_data.total_fee,
        "title": payment_data.title,
        "description": "",
        "time": current_time,
        "notify_url": f"{config.domain}/notify_url",
        "return_url": f"{config.domain}/return_url",
        "callback_url": f"{config.domain}/callback_url",
        "nonce_str": current_time,
    }
    logging.info(f"Request data: {data}")
    return await curl(data, url, app_secret)

@app.post("/pay", response_model=PaymentResponse)
async def pay(payment_request: PaymentRequest):
    logging.info(f"Payment request received: {payment_request}")
    try:
        response = await process_payment(payment_request)
        logging.info(f"Payment response: {response}")
        return PaymentResponse(
            status=response.get('status', 'unknown'),
            transaction_id=response.get('transaction_id', ''),
            trade_order_id=payment_request.trade_order_id,
            amount=payment_request.total_fee,
            message=response.get('message', 'Payment processed')
        )
    except Exception as e:
        logging.error(f"Error processing payment: {e}")
        raise HTTPException(status_code=500, detail="Payment processing failed")

if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="localhost", port=8000)