40 lines
1.8 KiB
Python
40 lines
1.8 KiB
Python
# unipay/providers/stripe.py
|
|
import aiohttp, json
|
|
from ..core import Gateway, GatewayError
|
|
|
|
class StripeGateway(Gateway):
|
|
def __init__(self, api_key: str):
|
|
self.api_key = api_key
|
|
self.base = "https://api.stripe.com/v1"
|
|
async def create_payment(self, payload):
|
|
# 使用 PaymentIntent -> 前端使用 stripe.js 完成卡片采集
|
|
url = self.base + "/payment_intents"
|
|
body = {
|
|
"amount": str(payload["amount_total"]), # in cents
|
|
"currency": payload.get("currency","usd"),
|
|
"payment_method_types[]": "card",
|
|
"description": payload.get("description",""),
|
|
"metadata[out_trade_no]": payload.get("out_trade_no","")
|
|
}
|
|
async with aiohttp.ClientSession() as s:
|
|
async with s.post(url, data=body, auth=aiohttp.BasicAuth(self.api_key, "")) as r:
|
|
return {"provider":"stripe","data": await r.json()}
|
|
async def refund(self, payload):
|
|
url = self.base + "/refunds"
|
|
body = {"charge": payload["charge_id"], "amount": str(payload.get("refund_amount"))}
|
|
async with aiohttp.ClientSession() as s:
|
|
async with s.post(url, data=body, auth=aiohttp.BasicAuth(self.api_key, "")) as r:
|
|
return {"provider":"stripe","data": await r.json()}
|
|
async def query(self, payload):
|
|
# query payment intent or charge
|
|
pid = payload.get("payment_intent_id") or payload.get("charge_id")
|
|
if not pid:
|
|
raise GatewayError("need payment_intent_id or charge_id")
|
|
async with aiohttp.ClientSession() as s:
|
|
async with s.get(self.base + f"/payment_intents/{pid}", auth=aiohttp.BasicAuth(self.api_key, "")) as r:
|
|
return {"provider":"stripe","data": await r.json()}
|
|
async def handle_notify(self, headers, body):
|
|
# stripe webhook: verify signature header (Stripe-Signature) — production use official lib or implement verification
|
|
return {"provider":"stripe","data": json.loads(body)}
|
|
|