From e70866c4b6e414ac8e957384ecd3710231067b55 Mon Sep 17 00:00:00 2001 From: db_huang <18006480240@163.com> Date: Thu, 29 Oct 2026 10:47:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E4=BF=AE=E6=94=B9=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E5=AE=9D=E8=AF=81=E4=B9=A6=E9=80=90=E5=BC=A0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alipay_provider.cpython-313.pyc | Bin 21209 -> 21427 bytes backend/app/alipay_provider.py | 22 ++++++++++++++---- ...ipay_provider.cpython-313-pytest-9.1.1.pyc | Bin 20448 -> 23434 bytes backend/tests/test_alipay_provider.py | 20 ++++++++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/backend/app/__pycache__/alipay_provider.cpython-313.pyc b/backend/app/__pycache__/alipay_provider.cpython-313.pyc index d8ad69b1a0bae0ff9746e0161bfd101307903cad..8148ccae687318ab8f07230b415cca74362b1580 100644 GIT binary patch delta 1885 zcmZvceNa?Y6u|F&Z{GsT1H@%v0f8qVx{53+GzFppqG$;suHq=-V|nNbEZcpHfrF`y zGFVQLXL6jRCeyMhzxR(avs4@#o5@fcKb~gls9BREg*7EMb+HIF^LwQp`Ze@Tib^8H9urh5L>hG?BU_LR=xkGgZP_CFKJtrye|cM8$Nj z?6ocJm6!F4LX_oZR7{^FgxUJc+_~2j_tzsQk>mOal{}QY_ognt7+KS+t%7&rEGq^c z#ggcR?!4ZpjDBJc8`CF~i1?uuh?nK`3v&8EUj#Qi)}4F@ub7J?$tjakoGJ7~T8bTF zk6kWK7kknrlru-nv`alxqi0&B(^iSgZVGBtOklD-pVE5p#-~zu;LZ2}8p2laWUL9g z6Vqs8;6!4cKwDrS$w}A1gye?sCbYI7*1)c0g|@?~+>#23LE6|^MMxdSW`Iw4qjXSN4_BQ(!Rq-*;8h%wugVx42VlcL$ zLtw3ZFigG%x6axiKck}HRWxovWFuZfG;kQj6P zNyL{Nv)D0k<|l=)WvHo!CHYh78Q7jbMY_rrcLL|~9a8Kuw8e55A+ECL%gPs*@f{lw zQCLoILUrL-;TD0a((!Pp&}zPoz6P8v%%(TsabXEP3Nwo4B>aMETr6`TaIGv9aTRtK zjh^s;i;fY@K+QG8b;J*d8;F~TTZr56uqZM7G>XBTXTVlmV5XE1fd;CI%T4AxXuA*l zXDWS4&Fv5(4)ajM#J{hTXR-a@pXZw# zg$09ZT2RL3a67-cb68EfHI3H;4Clk5i`3|s#Hp;_bU^Ok?Iil z$TqX{hh}q=#m&cboAZlt?%}j9OWYPyLjw9Knk91%{~1x|d&}-AbNgps;CIhGuY2z~ z_f|SUFMULHx08}IgnxVPU0r{$;&WYm8a)kL^!>0iZA)f8X%h@&xmr}%h^R1-Is+j+ z?JenWAzw^Y)6GElBM8sBv<2jS{W%ybd)J0Wdh0- z0_v+ZHF?Uj3CT5?%CngQm!;&aW=dZKcXlCdlLoUNQN5h#@v@L_t68vai`k;xiq?&YK?s{G z=qBka^VgIz=(BXtZPK{qdj)+NJ}hc3b#bRnDS@7l$!!WU-%EUHQV8+ zA7oXq%OkQ7Oe=17ZAarEq7*TN@N&r7PPgd#CylIG?)LY3YZ>cdvc}sN>|r4nrXE1| z9SCeai|4S$F)S-9LJY$B;!GNb8^sp-rlg(zfDFO*=CsE;qznsUrge7FhuStR7v@N5Dv!gHDUX} zWm`;l!2#QJx*MXlU#SQuN@uBep>a1%l$x^kagn#n@AC#iE|1?Wicc0OoKq+q=hk7V ze$Ejkb-~@a9kdTt+bwhe2J8XhEH{29-LlsSsePD5)#3AmtV&r?Qp&>cd}S-W0mGFm zYEN+^`xbE$@eSfjjz#PQr&Ysp_#ms+`T`xYYQ5MKkOhB_yF-){mh}gxs?Oeq@~SEt z0kP^SVU)X%N{6egf)NuiBZkMdIhQyaS2%f<#^C0HMmi1^j$*}C0`~eD@P@;nzJ|VI zu-{QiFTV;sK%pA^$<@IYa|pJ&j^4X9RB5%v1lx=XZ!?U)ZQp|BSZl@LJt6Z7kme&Tqm*T>~XBw|+jq^jr}$ z{f;KAKD!G$>YwB9hKv8ZOZ2&qc!0p|${Mk^-6e+HpLptKzECx?i?u%>^%*cFw94ZU90&k}f^EUCA_M(Hq&muE?*mJBJ9KH&kf zs-<;7*&=obnw`P2L|iYXrt_Svp4)kke&7QOBZfIdB?o^5Q%~SWxb2)ttDvB9vs#P6 zBk)0E?JRtj>{A3jHmeYeWauC#h`x0Jeq82dtI^>wq&7_#jNCL=s&1;L`5x4s=aA!q z?og-S*UnU^T8WTgPxDG^tl0lm7%!Qu^aVof9Qt4zV<%=t$ZN^dcv_(n(2DO#kSO5S3 diff --git a/backend/app/alipay_provider.py b/backend/app/alipay_provider.py index f7effa7..0fb924b 100644 --- a/backend/app/alipay_provider.py +++ b/backend/app/alipay_provider.py @@ -76,10 +76,24 @@ def _load_certificate_bundle(path_value: str, label: str): raise AlipayTransferError(f"{label}文件不存在,请检查对应 .env 绝对路径") content = Path(path_value).read_bytes() blocks = re.findall(rb"-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----", content, re.DOTALL) - try: - return [x509.load_pem_x509_certificate(block) for block in blocks] - except Exception as exc: - raise AlipayTransferError(f"{label}格式无效,应为 PEM 编码的 X.509 证书集合") from exc + certificates = [] + parse_errors = [] + for block in blocks: + try: + certificates.append(x509.load_pem_x509_certificate(block)) + except (TypeError, ValueError) as exc: + # Alipay's root bundle contains RSA, SM2 and ECC certificates. + # Some cryptography/OpenSSL builds cannot decode the SM2 + # certificate even though the RSA certificates needed for RSA2 + # are valid. Parse each PEM independently so one unsupported + # non-RSA certificate does not prevent the service from starting. + parse_errors.append(exc) + if not certificates: + cause = parse_errors[0] if parse_errors else None + raise AlipayTransferError( + f"{label}格式无效,应为包含有效 RSA 证书的 PEM X.509 证书集合" + ) from cause + return certificates def _certificate_serial(certificate) -> str: diff --git a/backend/tests/__pycache__/test_alipay_provider.cpython-313-pytest-9.1.1.pyc b/backend/tests/__pycache__/test_alipay_provider.cpython-313-pytest-9.1.1.pyc index 432bf2ccead7ca10d65cca11c55af192b2f3fc0e..5a93b9584831cb77d75137ce5476862f08012b93 100644 GIT binary patch delta 5077 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 R^-3SE delta 2738 zcmaKte{54#6vy9f*VlG!*OoHaST~;A*eHzBc1%FJQ5ek8!rZ7)6tui`kFC(I<-S+h z7IpH&K_o`Y^&bSdecrj} zo_pWD=YHS0Ph2G5yg;gET&_w1e$V|rz4vN$sj7yYF10S3Bnd0ECWWLaVT;?TT@t`H zCo1C(>WDk3Gwz};?yE>t#og4+ZA-!v_foGU)Ci42Qd}e?tsN$uTM+2Hq-~KveMviT zezFo+opb;fB%Q#8Nf)ptSp}>eCIPp26-V`zuAL%s@OD{AWn9l=|n>nbOlV* z4G-OxqRRfFqG~F>Ns_3C+07Dhvt?#U^nr`ISid>C-HT=|j;KzhR87`0>6EN#G&5M# z6g8DP2aCfH4+0ay;Q&K*0;YstOvJMISCLqvMqp)m+Wd^k!$T#EH-@uAVn3PBJ{Mb! zx3`?Ic9S-?$r|yuV$@PVz)aiVq1!Yn4=Jh9JPooF*1L(7eQ$k^bg?70ZV}g^uVf{0 zrAU)t`x8V>2lWKURb>nO$jl(i4cpsdq@*2xtrIaSGR2M z356oG9qb8TE~BcM(czdfCg%!SC790V=qj9`193azUPP2#bMGKAw#9Q$+=LD*`_vPd zw;4>`@{pV@DwMCIhyAp*rB=7gxxvhEF<(>zHrj{ryAb^>?oAR8d*0h&$$_J>e8t;Z z>EV6rF<>L2o4NgUB+8ciZ+$4yZK64*K^xFi1BS#=~?2 z`^~@DCPOKmsx-aI*egX-Av^J#`5k$Z$DxHu^pg0 zVukUP@zzyz1l{`(d)Z9=O4vzLLyu(w9Fg*9!=D5WW}j3t!NL61xLIt*z$L7=$-gLo z=B-cX(WX0EFpV^V;OF)TSOLPtL4)X>L`2zilV9AA=7T4i=TB0!)*&7RK%R|r0b94g zr$EPP4|d*(NFcT%wgCcG<4n51p1Z-2u|Z6O;og&{Ia%wVW8hJ(0Ll2_=fPNWtK}&8 zHnI1bzaT!);(RtKS;{Xji8(;(KZbUA_+mFe%#DM+C%m?KHMFk|p)-m&h&Y5ejNrR! zW94wFdUkX-_M{L&)*6w>ldLz=I8Xr&-7=^QXGZxaO+}2bAuQPC7*@1YI-f1(M%91k zq8FpKAmRukHSDd(T>~X-KaSvX7(k0F!A$c9j08=g4|75fATkJ4h3W=ePtlDB6r!E& zG0REl87QA@@3#|;{TyBIlfZF~@ZzNsu(4uwcdC;`uxD`jj|o?ND-1nI(Cj-W(mHrj zKcXJdfH;d-jF1pqKfGwzdgOgdpPW_H>&C2*wS|K_iv)L>(s zT^Gn0yV`Z(-iM*%kLqwR5?r$?6by&kJ65d?hVd`VU)LA7<)U=gP+rrNAtc~ZQU#xxw?ix~vo8T#Yj8|>l zjT`TVDv{ZfNz0l-Ux9!zb}F{QD8+BHFJmoGUjB-WEys-LHf5}!q+z|Vn;1BZdc$Qq zE4hKFt+QO1Tc!*CBlf$ZB@%WF=HNv~nvL`^>6q;KP} zcM-hK+|EH9_Ly6R@RP~dyg zZD0j+GSprhhEyVw2)x)S-ieg!;Urp@5x6QUA$)B}6pwC;=JG?utkOllg(iwn#kzaV ZObGc}5RM3k9W1)D(=pTHB?E*D>u={XVHf}a diff --git a/backend/tests/test_alipay_provider.py b/backend/tests/test_alipay_provider.py index fa3a03e..d8ed369 100644 --- a/backend/tests/test_alipay_provider.py +++ b/backend/tests/test_alipay_provider.py @@ -149,3 +149,23 @@ def test_root_certificate_serial_ignores_non_rsa_certificates(): expected = md5(b"CN=Alipay,O=Example,C=CN41259").hexdigest() assert alipay_provider._root_certificate_serial([sm2, rsa, ecc]) == expected + + +def test_certificate_bundle_keeps_valid_certificates_when_one_block_is_unsupported(monkeypatch, tmp_path): + bundle = tmp_path / "alipayRootCert.crt" + bundle.write_bytes( + b"-----BEGIN CERTIFICATE-----\nBAD\n-----END CERTIFICATE-----\n" + b"-----BEGIN CERTIFICATE-----\nGOOD\n-----END CERTIFICATE-----\n" + ) + valid_certificate = object() + + class FakeX509: + @staticmethod + def load_pem_x509_certificate(block): + if b"BAD" in block: + raise ValueError("unsupported SM2 certificate") + return valid_certificate + + monkeypatch.setitem(__import__("sys").modules, "cryptography.x509", FakeX509) + + assert alipay_provider._load_certificate_bundle(str(bundle), "支付宝根证书") == [valid_certificate]