From b552ac56b0143ff3fa9ac4ae5a838deed86fc77b Mon Sep 17 00:00:00 2001 From: db_huang <18006480240@163.com> Date: Sat, 31 Oct 2026 17:49:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B5=8B=E8=AF=95=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alipay_provider.cpython-313.pyc | Bin 21960 -> 22969 bytes backend/app/alipay_provider.py | 27 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/backend/app/__pycache__/alipay_provider.cpython-313.pyc b/backend/app/__pycache__/alipay_provider.cpython-313.pyc index dbbec3e7b48cc60f45fe8f32b1e2835ae4132c7e..fad1e2e3fa4f9a1617f6c46ceb6dcc0b5ec1a3f6 100644 GIT binary patch delta 3500 zcmZ`*Yj9h|6~3#-)z!n2Z22L}wtQtdIBJaT_z{Tn!m*WyahkW~M-A+C3|a z$1vTIzTN%K*|U4k?w+$}PoZZtWWQQcV&Q0c>h$GZ2YVl|yV1!9nwC!KLq=?rkYot) z{U&S@Ioj5T1T08Ki4U3kE!ZM*QDe9g#{RH0a8X+qDsZ^O%{6e6$-_xP)ZV3EWF1nI zWbtsj4A?1|qotiX$;x_Vk}c|zN}{f*PJ?7;RC$r2jDs;1bcl-%ak5_JVy~3-sup`? ztml?o)Lc3J!z8>^!Px4eMW)M3m5lXBRaDO%EoJN!FI6+TM)G(#Tr1U3tdnY^UMhA- z`fE)bM;BDbbm}E99adj^0~=H zRX;O&n}>Wwx@)mf^t{N8a;i?`RDBwyxe+c{9`IL_=zCKN2j zGwG4!Xb#KSWF{@{kyFWpoK+Itq8eAy%9Q~zNl7FJ^H-+2g43>LC2SVqCsX4(pD=eE4mdy#iw*>!}CWDdx z>gr0t!K*ep=1lvwo16KU{XE4uM`oPm_L6nIcJv+4HBK}X6sg}jr#xw ziQ*DbuXc}XmEL+IFkt|RoU1%izny6SL;wT;1HexKZYF!HeCQ_fU{#&-dj>(YgS=W5 zHGw&`3X%I<*K5P>5gpn^Uh_1dG3^u2e-NJl#XHESwSKfmE350)p$W33z7g&T%90=)@fGr%d3+2X0BlFr8BDOpwV;t~%pZ!o?3;Cogh<1?n6@KFzRBw*#Sn)C1p#`tI)lhW+%o-BOcs8KV>ss0hE((%o zR&7Q9CBo{PYF?ol_*H;20DlK~nZgGABAHz6zXoM;^M9g6?nF+Y`maw>3H$aWdMD|wb&0#lV z&EZNi$h-Wod9;X}mx~AuT*NFnR-&|R2)2Qha3{IQ*N|`4*-)ia zCew=nz8IlJtlW`P)GUqo%D9Yw5ZNID$FdXSETppzJ*!!IAR+9_W0_o`HJqF*#Cf1; z;z;D;^vD)6!5>lH401>esQ@A;*Edd0Hvf1HyOcP~DvQI!F-2A7QJ8o#_+#zDibv#R zN=b-!CbK&;xvVIQY8KO}bMzy=%U@Vg$1`bF$$6<;uKfCmOV5$%^);0*(jJC)OWqXO z8rr(;rmX=zeutpmO8v5Y7x{T_C28vw(Iqn2+k`HYiQW!$g*@K7mj3_-zC%9mJ&4{X zclNc`!a=~j0G(ith9Q~_Ct^9A!Y`21eVaSyK?WDG5WV0A7SaY>nY@vPsSL(eXq%P2 zab+A5E%64uZC5E5D8ui-fOi4j1GotAKENe_%K%pZJ|L-JtMe>0*_5wCYX>MaIu1F$ z?Jqb4BR^l}B7fM>hrHzCKpUyv=rGlAwu-BqjkIp`P0iWLjt(3eIPYA0-szon`e&Se z+E_3dO6>C%&gDB1pSA_&1pBPuo)O&B)wlmckmu~a>BjXhb-c7>x?$7w_M2zyw@k-| zr-k8f=BsVSIQm+J3;#EBk7q*{_ez&#Q-}VQbv><{TJ&dIjIYu96AK_U1Hk6xEoyE!re@`APQ~TKF;LS5(KTQx*e?Y=Hk}1pB>-&u*c^rJ zgNf}VHc)T$Q1NE%?tv8uJ*qvs<+!foDVV|#mU`MZ;3vt*jpOZgV1m(T%~s5Emma?f zHVy$iN>1xD6QGiDB8yO}GLC@P^6@t7)vtrIfX}l}hQ4Q}^d7iVB&YC@Mnmskgu7AtixSwC(4ak42d4Z$Vg58Js u`Avx2zkPOjH{y@=&U3VSRASZX4pyBlkkhxxtUEojYXOwzC&_Ok?f(Pt9+3(F delta 2714 zcmZ`)YfxLq72eh33cbZ!fDjTg7^OBZV}l<+03$G@veA`nQWR7H0*i+Pdqra0G&qwf zZtNx<=KM*2ILWk*Cw4oNCb!MRlV)N&wa3j&r^=+AW`x})X-G1iKCrQCyUBFA=gPF{ zk7~5vp8d|ZXU{#mckg+bUi~q(teedS!hbP&b<)wkY_Zcvmp9ieYWlT(0ux+Bq@ucC z$8@4r6#8@e^i1y}c2Y@1T`3WB!iMc?oJ|Nbikn44DVfwTlc*1yn^dAv8CgVA*eaUC z)+UW;Q5f4-7^}kM@)=e>!={Y#ME#;N%vFZ@_nmpls6fo;;R<-eMFg=>VGB1xDq2A- zQrIG~nCt9e^L@5NVT;AmQo`(F8OIXQ5iaFkqp04hBZQ||u4o3zL?@qG5q5|!-n)6L z!qsN(t5$q2`CU3dsZDmMw@{i3`!pA+ z4UF0VJs}TkcWP7<1b(33YnvdF%0(n~f+ol~@fONGhR>+VTOyw`ou@EonKJb9(8at- zEApq7-_erybB6D&H|JOd$;8=p^f6d))zKqx)-`2JqW3X`BT(UX(Qm_p?(fqlRqZNz z0$OSY>L|1cYW?=Dq=sbzg zi0}-;42O*Ia8!!i55pqJ7-C0elPnd%m`kX87U2*AR^F>q5@wr`z=#<`BFSc=)A6IR zv5YViWm7T6j-z*wgT&7>alzBxLV8Mm!TX4oUWBx}0CMYoUUnKqKSGg!BA4sfv18fi ze+fRS3(-r^T)(TipZoZtc-WX7p#-56;U$D}1Sbctn&qLL4GS;VKj40mk1z5jnK|5B zB6n08v-39LzzR9T&cb?q4?P9D8)}5-kq{x?@DV)<{f%4NPa&bO_#hc!G?^HWPq1#J zeF!}WXVGUGosP#6smSPbRFXClc)hVw`zH6kB42O(iJDHpi5+8f5&pizBPew}1oq}` zItatf9__EV?tNHl{xcnv=UN`o6fa^}%~*UiPm* z?RWH*CoC>9)C!%Q?bHVsA1a3zI&)|*w>;YXkTuYUmbXAGtW|F!ZZg!i5l=^=+)mhr zIyRV)ZKxBT{CWlLhCN*s&HO1sxglFjHPp4C5N#owg=|xaxnkZ<75YRTp~E&#$4RTY zf{asd5&Wxb1@?7sgB#sdb#L*RtcXKK7xMS}_aE}}19c6@IVlz$i$xO2j3A|=sd>p; zo!Jgg`ifx4=b|6Oa1dRi6;}(*FQV`izj=tJASn41Nt9J>Q`p!Vi1u z@|sZ3-<(u@d?7N=rrDeD*Peale?uJ}hU^Q6ryzUZ;kLnKue1IJH@taDV(dD)|A6pE zgbxuuM!;;?CkU(XMsJ<%3Ytpnt7r|vo!(srBjwxAn{*s@?|V(XrZU6!zP<4Lfd)9& zXVqDWsc@YLaG}rb`ykKt;%M6By=HNzH+5dvcA+X=*_#dyzGrzj9T`dIjC`?X7PO=E zpAw#iON||+-A;1ZY4BC6FW2n!xz$(PT3@vs?7yipeuf!*j_?;4@CS`pVz!2G1Agl7 zqh|QR-&StniDe)14!Z6l;LF5R+yVD`ykPSiy8m?lT9J~mP1B|pQ-8iNcN-q z4dl-w2Ubi>euH!I@F^8zn2Yl4*(({p zf0>*;Gs&^}=~x@{axecAX@cXLno@d0rJE76;bXT)vdN`^K)8mu3P_%Xsjz8S^Z_|mQ A3IG5A diff --git a/backend/app/alipay_provider.py b/backend/app/alipay_provider.py index 5ff753a..85758ae 100644 --- a/backend/app/alipay_provider.py +++ b/backend/app/alipay_provider.py @@ -7,12 +7,16 @@ mode do not require credentials or network access. from decimal import Decimal import hashlib import json +import logging from pathlib import Path import re from .config import settings +logger = logging.getLogger(__name__) + + class AlipayTransferError(RuntimeError): def __init__(self, message: str, code: str = "", ambiguous: bool = False): super().__init__(message) @@ -49,6 +53,11 @@ def validate_configuration() -> None: raise AlipayTransferError("应用公钥证书与应用私钥不匹配") else: _sdk_key(_read_key(settings.alipay_public_key_path, "支付宝公钥"), private=False) + logger.info( + "Alipay provider configuration validated: scene=%s certificate_mode=%s transfer_scene_report_schema=佣金报酬说明", + settings.alipay_transfer_scene_name, + _certificate_mode_enabled(), + ) def _certificate_mode_enabled() -> bool: @@ -278,6 +287,18 @@ def transfer(*, out_biz_no: str, amount_fen: int, account: str, payee_name: str, payee.identity_type = "ALIPAY_LOGON_ID" payee.name = payee_name model.payee_info = payee + # Keep a deploy-time diagnostic in the server log without exposing the + # recipient account, name, private key, or certificate data. This makes + # it possible to distinguish an old server build from an Alipay rejection. + logger.info( + "Alipay transfer request prepared: scene=%s info_type=%s info_content=%s amount=%s biz_scene=%s product_code=%s", + model.transfer_scene_name, + reward_description.info_type, + reward_description.info_content, + model.trans_amount, + model.biz_scene, + model.product_code, + ) try: request = AlipayFundTransUniTransferRequest(biz_model=model) if settings.alipay_notify_url: @@ -290,7 +311,13 @@ def transfer(*, out_biz_no: str, amount_fen: int, account: str, payee_name: str, raise provider_error = _provider_error_from_exception(exc) if provider_error: + logger.error( + "Alipay transfer rejected: code=%s message=%s", + provider_error.code, + provider_error, + ) raise provider_error from exc + logger.exception("Alipay transfer request failed without a structured provider response") raise AlipayTransferError(f"支付宝转账请求失败:{exc}", ambiguous=True) from exc return { "out_biz_no": response.out_biz_no or out_biz_no,