fix: Native扫码二维码改为HTTPS中转以支持相册识别

This commit is contained in:
XingQue committed 2026-08-08 20:37:22 +08:00
1 parent 486c050c00
commit 94f7a2fba9
5 files changed
+76 -13

No files matched your search

+22 -12
View File
@@ -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)
+2 -1
View File
@@ -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='老板订单获取'),
+2
View File
@@ -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",
+13
View File
@@ -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):
"""
订单支付成功复查接口 - 前端支付成功后调用,确认订单状态
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>微信支付</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #f5f5f5; }
.container { max-width: 420px; margin: 0 auto; padding: 48px 20px; text-align: center; }
.icon { width: 72px; height: 72px; margin: 0 auto 20px; border: 4px solid #ddd; border-top-color: #07c160; border-radius: 50%; animation: spin 1s linear infinite; }
.title { font-size: 18px; color: #333; margin-bottom: 12px; }
.subtitle { font-size: 14px; color: #999; margin-bottom: 28px; line-height: 1.5; }
.btn { display: inline-block; width: 100%; padding: 14px; font-size: 16px; border: none; border-radius: 8px; background: #07c160; color: #fff; }
@keyframes spin { to { transform: rotate(360deg); } }
</style>
</head>
<body>
<div class="container">
{% if code_url %}
<div class="icon"></div>
<div class="title">正在打开微信支付...</div>
<div class="subtitle">若未自动跳转,请点击下方按钮</div>
<a class="btn" id="payBtn" href="{{ code_url }}">立即支付</a>
<script>
(function () {
var url = '{{ code_url|escapejs }}';
setTimeout(function () { window.location.href = url; }, 80);
})();
</script>
{% else %}
<div class="title">支付链接无效或已过期</div>
<div class="subtitle">请返回小程序重新发起支付</div>
{% endif %}
</div>
</body>
</html>