diff --git a/jituan/services/wechat_native_pay.py b/jituan/services/wechat_native_pay.py index a7dc641..f4edd4b 100644 --- a/jituan/services/wechat_native_pay.py +++ b/jituan/services/wechat_native_pay.py @@ -25,12 +25,32 @@ logger = logging.getLogger(__name__) CACHE_KEY_PREFIX = 'wx_native_code_' CACHE_TTL_SECONDS = 60 * 30 +# 相册扫码友好:二维码图编码 HTTPS 中转页(打开后再跳 weixin://),复制链接仍给官方 code_url +BRIDGE_URL_BASE = 'https://www.abas.asia/hqhd/dingdan/wx-native-pay/' def _cache_key(dingdanid: str) -> str: return f'{CACHE_KEY_PREFIX}{dingdanid}' +def build_native_bridge_url(dingdanid: str) -> str: + from urllib.parse import quote + return f'{BRIDGE_URL_BASE}?out_trade_no={quote(dingdanid, safe="")}' + + +def _native_pay_response(dingdanid: str, code_url: str) -> dict: + from jituan.services.alipay_pay import qr_link_to_base64 + bridge = build_native_bridge_url(dingdanid) + return { + # 复制支付链接:与同行一致,官方 weixin://wxpay/bizpayurl?... + 'qr_code': code_url, + # 展示用二维码:HTTPS 中转,便于微信「扫一扫-相册」识别 + 'qr_image': qr_link_to_base64(bridge), + 'bridge_url': bridge, + 'pay_method': PAY_METHOD_WECHAT_NATIVE, + } + + def generate_wechat_native_pay_params( *, dingdanid, @@ -46,8 +66,6 @@ def generate_wechat_native_pay_params( 同一业务单号未过期时复用 cache 中的 code_url,避免重复点支付产生双码。 不需要 openid。第一期不走付呗。 """ - from jituan.services.alipay_pay import qr_link_to_base64 - dingdanid = (dingdanid or '').strip() notify_url = (notify_url or '').strip() body = (body or '微信支付').strip() or '微信支付' @@ -63,11 +81,7 @@ def generate_wechat_native_pay_params( '[WX_NATIVE] reuse code_url dingdan=%s club=%s scene=%s', dingdanid, club_id, scene, ) - return { - 'qr_code': cached_url, - 'qr_image': qr_link_to_base64(cached_url), - 'pay_method': PAY_METHOD_WECHAT_NATIVE, - } + return _native_pay_response(dingdanid, cached_url) pay_cfg = get_wechat_v2_config(club_id) log_wechat_v2_pay_diag( @@ -131,8 +145,4 @@ def generate_wechat_native_pay_params( '[WX_NATIVE] unifiedorder ok dingdan=%s club=%s mch=%s scene=%s', dingdanid, pay_cfg.get('club_id'), mch_id, scene, ) - return { - 'qr_code': code_url, - 'qr_image': qr_link_to_base64(code_url), - 'pay_method': PAY_METHOD_WECHAT_NATIVE, - } + return _native_pay_response(dingdanid, code_url) diff --git a/orders/urls.py b/orders/urls.py index ce2f94a..5a19390 100644 --- a/orders/urls.py +++ b/orders/urls.py @@ -1,6 +1,6 @@ from django.urls import path from django.views.decorators.csrf import csrf_exempt -from .views import CreateOrderView, WechatPayNotifyView, AlipayPayNotifyView, alipay_pay_page, \ +from .views import CreateOrderView, WechatPayNotifyView, AlipayPayNotifyView, alipay_pay_page, wx_native_pay_page, \ PaymentFailView, PaymentVerifyView, ContinuePayView, DingdanHuoquView, DingdanXiangqingView, JiedanView, \ ShangpinLeixingView, ShangjiaPaifaView, ShangjiaDingdanHuoquView, ShangjiaJiesuanView, \ ShangjiaDingdanXiangqingView, ShangjiaChufaShenqingView, ShangjiaTuikuanShenqingView, \ @@ -24,6 +24,7 @@ urlpatterns = [ path('alipay-notify/', csrf_exempt(AlipayPayNotifyView.as_view()), name='老板下单支付宝支付回调'), path('fubei-notify/', csrf_exempt(FubeiPayNotifyView.as_view()), name='付呗支付回调'), path('alipay-pay/', csrf_exempt(alipay_pay_page), name='支付宝H5中转页'), + path('wx-native-pay/', csrf_exempt(wx_native_pay_page), name='微信Native扫码中转页'), path('shibai', PaymentFailView.as_view(), name='老板支付失败接口'), path('fucha', PaymentVerifyView.as_view(), name='老板支付成功复查接口'), path('dingdanhuoqu', DingdanHuoquView.as_view(), name='老板订单获取'), diff --git a/orders/views/__init__.py b/orders/views/__init__.py index 417e10e..73c5b70 100644 --- a/orders/views/__init__.py +++ b/orders/views/__init__.py @@ -10,6 +10,7 @@ from .payment import ( CreateOrderView, ContinuePayView, alipay_pay_page, + wx_native_pay_page, ) from .boss_orders import ( DingdanHuoquView, @@ -73,6 +74,7 @@ __all__ = [ "PaymentFailView", "WechatPayNotifyView", "AlipayPayNotifyView", "PaymentVerifyView", "CreateOrderView", "ContinuePayView", "alipay_pay_page", + "wx_native_pay_page", "DingdanHuoquView", "DingdanXiangqingView", "JiedanView", "DingdanXiangqingView2", "JiedanView2", "ShangpinLeixingView", "ShangjiaPaifaView", "ShangjiaDingdanHuoquView", diff --git a/orders/views/payment.py b/orders/views/payment.py index be977f9..cef878a 100644 --- a/orders/views/payment.py +++ b/orders/views/payment.py @@ -530,6 +530,19 @@ def alipay_pay_page(request): return render(request, 'alipay/pay.html', {}) +def wx_native_pay_page(request): + """微信 Native 扫码中转页:相册扫 HTTPS 码后跳转到 weixin:// 付款链接。""" + out_trade_no = (request.GET.get('out_trade_no') or request.GET.get('dingdanid') or '').strip() + code_url = '' + if out_trade_no: + cached = cache.get(f'wx_native_code_{out_trade_no}') or {} + if isinstance(cached, dict): + code_url = (cached.get('code_url') or '').strip() + elif isinstance(cached, str): + code_url = cached.strip() + return render(request, 'wechat/native_pay.html', {'code_url': code_url, 'out_trade_no': out_trade_no}) + + class PaymentVerifyView(APIView): """ 订单支付成功复查接口 - 前端支付成功后调用,确认订单状态 diff --git a/templates/wechat/native_pay.html b/templates/wechat/native_pay.html new file mode 100644 index 0000000..5dba4c2 --- /dev/null +++ b/templates/wechat/native_pay.html @@ -0,0 +1,37 @@ + + + + + + 微信支付 + + + +
+{% if code_url %} +
+
正在打开微信支付...
+
若未自动跳转,请点击下方按钮
+ 立即支付 + +{% else %} +
支付链接无效或已过期
+
请返回小程序重新发起支付
+{% endif %} +
+ +