From 1a2d8f8f2de9d36b20f701100bf49a1ffd848d35 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 15 Jul 2026 17:22:40 +0800 Subject: [PATCH] feat(wechat): switch from H5 to Native payment (QR code scan) - Change API endpoint from /v3/pay/transactions/h5 to /v3/pay/transactions/native - Remove scene_info (not needed for native mode) - Return code_url instead of h5_url - recharge.dspy: display QR code image via api.qrserver.com - user_recharge.dspy: return both code_url and qr_url --- unipay/providers/wechat.py | 16 ++++++---------- wwwroot/recharge.dspy | 10 ++++++---- wwwroot/user_recharge.dspy | 7 +++++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/unipay/providers/wechat.py b/unipay/providers/wechat.py index 9e34947..5297a01 100644 --- a/unipay/providers/wechat.py +++ b/unipay/providers/wechat.py @@ -143,7 +143,7 @@ class WechatGateway(Gateway): # ----------------------------------------------------- async def create_payment(self, payload: Dict[str, Any]) -> str: """ - H5 下单(默认 H5,可改为 jsapi/native) + Native 下单(扫码支付) """ body = { "appid": self.appid, @@ -154,15 +154,11 @@ class WechatGateway(Gateway): "amount": { "total": int(payload["amount"]), "currency": payload.get("currency", "CNY") - }, - "scene_info": { - "payer_client_ip": payload.get("client_ip", "127.0.0.1"), - "h5_info": {"type": "Wap"} } } body_str = json.dumps(body, ensure_ascii=False) - url_path = "/v3/pay/transactions/h5" + url_path = "/v3/pay/transactions/native" url = WECHAT_API_BASE + url_path auth = self._sign("POST", url_path, body_str) @@ -176,10 +172,10 @@ class WechatGateway(Gateway): err_code = ret.get("code", "UNKNOWN") err_msg = ret.get("message", str(ret)) raise Exception(f"WeChat API error (HTTP {resp.status}): [{err_code}] {err_msg}") - h5_url = ret.get("h5_url") - if not h5_url: - raise Exception(f"WeChat API response missing h5_url: {json.dumps(ret, ensure_ascii=False)}") - return h5_url + code_url = ret.get("code_url") + if not code_url: + raise Exception(f"WeChat Native API response missing code_url: {json.dumps(ret, ensure_ascii=False)}") + return code_url # ----------------------------------------------------- async def refund(self, payload: Dict[str, Any]) -> Dict[str, Any]: diff --git a/wwwroot/recharge.dspy b/wwwroot/recharge.dspy index c552677..547a0e3 100644 --- a/wwwroot/recharge.dspy +++ b/wwwroot/recharge.dspy @@ -1,13 +1,15 @@ +import urllib.parse params_kw.amount = float(params_kw.amount) debug(f'recharge.dspy: {params_kw=}') try: - url = await create_payment(request, params_kw) + code_url = await create_payment(request, params_kw) + qr_img_url = 'https://api.qrserver.com/v1/create-qr-code/?size=280x280&data=' + urllib.parse.quote(code_url, safe='') return { "widgettype":"NewWindow", "options":{ - "url": url, - "height": "100%", - "width":"100%" + "url": qr_img_url, + "height": "340", + "width":"340" } } except Exception as e: diff --git a/wwwroot/user_recharge.dspy b/wwwroot/user_recharge.dspy index 7eaf5d1..f763d1f 100644 --- a/wwwroot/user_recharge.dspy +++ b/wwwroot/user_recharge.dspy @@ -1,3 +1,4 @@ +import urllib.parse if params_kw.amount is None: return { "status": "error", @@ -20,14 +21,16 @@ if params_kw.currency != 'CNY': } } params_kw.amount = float(params_kw.amount) -debug(f'recharge.dspy: {params_kw=}') +debug(f'user_recharge.dspy: {params_kw=}') try: url = await create_payment(request, params_kw) + qr_url = 'https://api.qrserver.com/v1/create-qr-code/?size=280x280&data=' + urllib.parse.quote(url, safe='') return { "status": "ok", "data": { - "url": url + "code_url": url, + "qr_url": qr_url } } except Exception as e: