|
|
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="x-dns-prefetch-control" content="on"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><meta name="renderer" content="webkit"><meta name="force-rendering" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="HandheldFriendly" content="True"><meta name="mobile-web-app-capable" content="yes"><link rel="shortcut icon" href="https://hans362-img.oss.0vv0.top/favicon.ico"><link rel="icon" type="image/png" sizes="16x16" href="https://hans362-img.oss.0vv0.top/favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="https://hans362-img.oss.0vv0.top/favicon-32x32.png"><link rel="apple-touch-icon" sizes="180x180" href="https://hans362-img.oss.0vv0.top/apple-touch-icon.png"><link rel="mask-icon" href="https://hans362-img.oss.0vv0.top/safari-pinned-tab.svg"><title>阿里云金融级实人认证接入踩坑记 | Hans362 's Blog</title><meta name="keywords" content="阿里云, Web, Python, Hans362"><meta name="description" content="最近需要给一个基于 Django 的项目开发实名认证功能,除了常规的核验姓名和身份证号是否匹配,还需要对用户进行活体检测。看了一圈最后选定了阿里云的金融级实人认证产品,可以直接让用户使用支付宝APP完成活体检测的认证过程,开发工作量相对较小,对用户而言也比较方便(毕竟这年头谁手机上还没个支付宝呢)。 开通金融级实人认证后,我开始照着阿里云提供的开发参考文档尝试将其接入到项目中。得益于阿里云这份含糊"><meta property="og:type" content="article"><meta property="og:title" content="阿里云金融级实人认证接入踩坑记"><meta property="og:url" content="https://blog.hans362.cn/post/aliyun-financial-grade-id-verification/"><meta property="og:site_name" content="Hans362 's Blog"><meta property="og:description" content="最近需要给一个基于 Django 的项目开发实名认证功能,除了常规的核验姓名和身份证号是否匹配,还需要对用户进行活体检测。看了一圈最后选定了阿里云的金融级实人认证产品,可以直接让用户使用支付宝APP完成活体检测的认证过程,开发工作量相对较小,对用户而言也比较方便(毕竟这年头谁手机上还没个支付宝呢)。 开通金融级实人认证后,我开始照着阿里云提供的开发参考文档尝试将其接入到项目中。得益于阿里云这份含糊"><meta property="og:locale" content="zh_CN"><meta property="og:image" content="https://hans362-img.oss.0vv0.top/2023/12/02/c5543f0d5d32feffb172c231be9e0ace.png"><meta property="article:published_time" content="2023-12-02T09:32:00.000Z"><meta property="article:modified_time" content="2025-04-11T10:35:15.353Z"><meta property="article:author" content="Hans362"><meta property="article:tag" content="阿里云"><meta property="article:tag" content="Web"><meta property="article:tag" content="Python"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://hans362-img.oss.0vv0.top/2023/12/02/c5543f0d5d32feffb172c231be9e0ace.png"><link rel="stylesheet" href="/css/style/main.css"><link rel="stylesheet" id="hl-default-theme" href="https://blog.hans362.cn/npm/highlight.js@10.1.2/styles/atom-one-light.css" media="none"><link rel="stylesheet" id="hl-dark-theme" href="https://blog.hans362.cn/npm/highlight.js@10.1.2/styles/atom-one-dark.css" media="none"><script src="/js/darkmode.js"></script><link rel="dns-prefetch" href="https://analytics.0vv0.top"><link rel="preconnect" href="https://hans362-img.oss.0vv0.top"><meta name="generator" content="Hexo 7.1.1"><link rel="alternate" href="/atom.xml" title="Hans362 's Blog" type="application/atom+xml"></head><body><div class="app-shell-loader">加载中...</div><div class="container" tabindex="-1"><header><div class="header__left"><a href="/" class="button"><span class="logo__text">Hans362 's Blog</span></a></div><div class="header__right"><div class="navbar__menus"><a href="/" class="button"><div class="navbar-menu">首页</div></a><a href="/archives/" class="button"><div class="navbar-menu">归档</div></a><a href="/tags/" class="button"><div class="navbar-menu">标签</div></a><a href="/bangumi/" class="button"><div class="navbar-menu">追番</div></a><a href="/links/" class="button"><div class="navbar-menu">友链</div></a><a href="/about/" class="button"><div class="navbar-menu">关于</div></a><a href="/atom.xml" class="button"><div class="navbar-menu">RSS</div></a></div><a href="/search/" class="button"><div id="btn-search"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="24" height="24" fill="currentColor" stroke="currentColor" stroke-width="32"><path d="M192 448c0-141.152 114.848-256 256-256s256 114.848 256 256-114.848 256-256 256-256-114.848-256-256z m710.624 409.376l-206.88-206.88A318.784 318.784 0 0 0 768 448c0-176.736-143.264-320-320-320S128 271.264 128 448s143.264 320 320 320a318.784 318.784 0 0 0 202.496-72.256l206.88 206.88 45.248-45.248z"></path></svg></div></a><a href="javaScript:void(0);" rel="external nofollow noreferrer" class="button"><div id="btn-toggle-dark"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg></div></a><a href="#" class="button" id="b2t" aria-label="回到顶部" title="回到顶部"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="32" height="32"><path d="M233.376 722.752L278.624 768 512 534.624 745.376 768l45.248-45.248L512 444.128zM192 352h640V288H192z" fill="currentColor"></path></svg> </a><a class="dropdown-icon button" tabindex="0"><div id="btn-dropdown"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="24" height="24" fill="none" stroke="currentColor" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round"><path fill="currentColor" d="M3.314,4.8h13.372c0.41,0,0.743-0.333,0.743-0.743c0-0.41-0.333-0.743-0.743-0.743H3.314c-0.41,0-0.743,0.333-0.743,0.743C2.571,4.467,2.904,4.8,3.314,4.8z M16.686,15.2H3.314c-0.41,0-0.743,0.333-0.743,0.743s0.333,0.743,0.743,0.743h13.372c0.41,0,0.743-0.333,0.743-0.743S17.096,15.2,16.686,15.2z M16.686,9.257H3.314c-0.41,0-0.743,0.333-0.743,0.743s0.333,0.743,0.743,0.743h13.372c0.41,0,0.743-0.333,0.743-0.743S17.096,9.257,16.686,9.257z"></path></svg></div></a><div class="dropdown-menus" id="dropdown-menus"><a href="/" class="dropdown-menu button">首页</a> <a href="/archives/" class="dropdown-menu button">归档</a> <a href="/tags/" class="dropdown-menu button">标签</a> <a href="/bangumi/" class="dropdown-menu button">追番</a> <a href="/links/" class="dropdown-menu button">友链</a> <a href="/about/" class="dropdown-menu button">关于</a> <a href="/atom.xml" class="dropdown-menu button">RSS</a></div></div></header><cover></cover><main><div class="post-content"><div class="post-title"><h1 class="post-title__text">阿里云金融级实人认证接入踩坑记</h1><div class="post-title__meta"><a href="/archives/2023/12/" class="post-meta__date button">2023-12-02</a> <span class="separate-dot"></span> <a href="/categories/%E6%8A%80%E6%9C%AF%E5%90%91/" class="button"><span class="post-meta__cats">技术向</span></a><style>.post-meta__pv{color:var(--t-l);visibility:hidden;opacity:0;transition:.2s}</style><span class="separate-dot"></span> <span class="post-meta__pv"></span></div></div><aside class="post-side"><div class="post-side__toc"><div class="toc-title">文章目录</div><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#tldr"><span class="toc-text">TL;DR</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%BF%87%E6%97%B6%E7%9A%84-sdk-%E7%89%88%E6%9C%AC"><span class="toc-text">过时的 SDK 版本</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8A%A0%E5%AF%86%E4%BC%A0%E5%8F%82%E5%85%A8%E9%9D%A0%E7%8C%9C"><span class="toc-text">加密传参全靠猜</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%BB%E7%BB%93"><span class="toc-text">总结</span></a></li></ol></div></aside><a class="btn-toc button" id="btn-toc" tabindex="0"><svg viewBox="0 0 1024 1024" width="32" height="32" xmlns="http://www.w3.org/2000/svg"><path d="M128 256h64V192H128zM320 256h576V192H320zM128 544h64v-64H128zM320 544h576v-64H320zM128 832h64v-64H128zM320 832h576v-64H320z" fill="currentColor"></path></svg></a><div class="toc-menus" id="toc-menus"><div class="toc-title">文章目录</div><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#tldr"><span class="toc-text">TL;DR</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%BF%87%E6%97%B6%E7%9A%84-sdk-%E7%89%88%E6%9C%AC"><span class="toc-text">过时的 SDK 版本</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8A%A0%E5%AF%86%E4%BC%A0%E5%8F%82%E5%85%A8%E9%9D%A0%E7%8C%9C"><span class="toc-text">加密传参全靠猜</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%BB%E7%BB%93"><span class="toc-text">总结</span></a></li></ol></div><article class="post post__with-toc card"><div class="post__header"><img alt="Cover Image" class="lazy" src="https://hans362-img.oss.0vv0.top/2023/12/02/c5543f0d5d32feffb172c231be9e0ace.png" srcset="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAABlBMVEXMzMyWlpYU2uzLAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAACklEQVQImWNgAAAAAgAB9HFkpgAAAABJRU5ErkJggg==" data-srcset="https://hans362-img.oss.0vv0.top/2023/12/02/c5543f0d5d32feffb172c231be9e0ace.png"><div class="post__expire" id="post-expired-notify"><p><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" style="fill:#f5a623;stroke:#f5a623"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg> 本文最后更新于 <span id="expire-date"></span> 天前,文中部分描述可能已经过时。</p></div><script>(()=>{var e=Date.parse("2023-12-02"),t=(new Date).getTime(),t=Math.floor((t-e)/864e5);120<=t&&(document.querySelectorAll("#expire-date")[0].innerHTML=t,document.querySelectorAll("#post-expired-notify")[0].style.display="block")})()</script></div><div class="post__content"><html><head><script>var meting_api="https://api-v2.hans362.cn/vip/?server=:server&type=:type&id=:id&r=:r"</script><script class="meting-secondary-script-marker" src="/js/Meting.min.js"></script></head><body><p>最近需要给一个基于 Django 的项目开发实名认证功能,除了常规的核验姓名和身份证号是否匹配,还需要对用户进行活体检测。看了一圈最后选定了阿里云的<a target="_blank" rel="noopener" href="https://help.aliyun.com/zh/id-verification/product-overview/financial-level-real-person-certification">金融级实人认证</a>产品,可以直接让用户使用支付宝APP完成活体检测的认证过程,开发工作量相对较小,对用户而言也比较方便(毕竟这年头谁手机上还没个支付宝呢)。</p><p>开通金融级实人认证后,我开始照着阿里云提供的<a target="_blank" rel="noopener" href="https://help.aliyun.com/zh/id-verification/financial-grade-id-verification/integration-by-using-the-sdk">开发参考文档</a>尝试将其接入到项目中。得益于阿里云这份含糊其辞、不清不楚的过时文档,开发花费的时间比我想象中要多😇,在此也记录一下我踩过的坑,希望能够帮助到后来者。</p><span id="more"></span><h2 id="tldr"><a class="markdownIt-Anchor" href="#tldr"></a> TL;DR</h2><ul><li>阿里云文档中的 Python SDK 版本过时,需要手动指定版本号</li><li>阿里云文档中提供的国密 SM2公钥为压缩格式,需要先还原完整公钥</li><li>阿里云使用 C1C2C3模式,而非现行标准的 C1C3C2模式</li><li>须确保加密结果的第一个字节为 <code>\x04</code>,否则须手动补充</li></ul><h2 id="过时的-sdk-版本"><a class="markdownIt-Anchor" href="#过时的-sdk-版本"></a> 过时的 SDK 版本</h2><p>因为项目是基于 Django 框架开发的,所以我参考了文档中 Python SDK 的部分。按文档所说,我首先通过 <code>pip install aliyun-python-sdk-saf</code> 安装了云产品SAF SDK,接着在项目中引入 SDK 包时却出现了问题。</p><p><img src="https://hans362-img.oss.0vv0.top/2023/12/01/e58476620b6db44fd4f6d75846efb4c7.png" class="lazy" data-srcset="https://hans362-img.oss.0vv0.top/2023/12/01/e58476620b6db44fd4f6d75846efb4c7.png" srcset="/loading.gif" alt=""></p><p><img src="https://hans362-img.oss.0vv0.top/2023/12/01/0da7caca43f25b7cb02fe195626a6300.png" class="lazy" data-srcset="https://hans362-img.oss.0vv0.top/2023/12/01/0da7caca43f25b7cb02fe195626a6300.png" srcset="/loading.gif" alt=""></p><p>怀疑八成是文档没及时更新,看了眼包安装目录下的文件结构,果然最新版本都已经 <code>v20190521</code> 了,改一下版本号就解决了问题。</p><p><img src="https://hans362-img.oss.0vv0.top/2023/12/01/2f4a29a91074aa58c0d77a21240504f0.png" class="lazy" data-srcset="https://hans362-img.oss.0vv0.top/2023/12/01/2f4a29a91074aa58c0d77a21240504f0.png" srcset="/loading.gif" alt=""></p><p>同时最好在 <code>requirements.txt</code> 中锁版本,以免以后哪次 <code>pip install</code> 时更新了 SDK 导致又出现问题。</p><h2 id="加密传参全靠猜"><a class="markdownIt-Anchor" href="#加密传参全靠猜"></a> 加密传参全靠猜</h2><p>由于项目的合规要求,数据库不能留存用户的身份证号明文或可解密的密文,而阿里云的金融级实人认证接口刚好支持非对称加密传参,因此可以将用户输入的身份证号使用阿里云提供的公钥进行非对称加密,然后存储在数据库中(由于私钥由阿里云保管,即使数据库发生数据泄露也无法解开),发起认证请求时直接将密文传递给阿里云。</p><p>然而文档中关于加密方式的约定含糊其辞,只提到了加密方式为国密 SM2,给出了一个公钥,并提供了一段 Java 语言下的调包例程。</p><p><img src="https://hans362-img.oss.0vv0.top/2023/12/01/ca962256b7e79f2a35f78e68aef5dcba.png" class="lazy" data-srcset="https://hans362-img.oss.0vv0.top/2023/12/01/ca962256b7e79f2a35f78e68aef5dcba.png" srcset="/loading.gif" alt=""></p><p>好在 Python 这边也已经有<a target="_blank" rel="noopener" href="https://github.com/duanhongyi/gmssl">现成的国密加密包</a>了,我天真地以为调用一下包里的加密函数就行了,于是我一开始是这么写的:</p><pre><code class="hljs python"><span class="hljs-keyword">import</span> base64
|
|
|
<span class="hljs-keyword">from</span> gmssl <span class="hljs-keyword">import</span> sm2
|
|
|
|
|
|
sm2_crypt = sm2.CryptSM2(public_key=<span class="hljs-string">'02cd77e007bdc86eeaf9a479ba7a2c22bc0a517ccb3a6975c3f94b4ac93347dea6'</span>, private_key=<span class="hljs-string">''</span>, mode=<span class="hljs-number">1</span>)
|
|
|
idcard_encrypted = base64.b64encode(sm2_crypt.encrypt(idcard.encode(<span class="hljs-string">'utf-8'</span>))).decode(<span class="hljs-string">'utf-8'</span>)</code></pre><p>结果呢,还没到给阿里云传参这一步,光是加密就报错了:</p><pre><code class="hljs vim">TypeError: object of <span class="hljs-built_in">type</span> <span class="hljs-string">'NoneType'</span> <span class="hljs-built_in">has</span> <span class="hljs-keyword">no</span> <span class="hljs-built_in">len</span>()</code></pre><p>翻了翻 Issues 才知道存在公钥压缩这回事。根据现行 <a target="_blank" rel="noopener" href="https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=2127A9F19CB5D7F20D17D334ECA63EE5">GB/T 35276-2017</a> 7.1节的定义,SM2算法公钥内容为 <code>04||X||Y</code>,其中 X 和 Y 分别标识公钥的 x 分量和 y 分量,其长度各为256位。阿里云提供的公钥既不以 <code>04</code> 开头,长度也不满足规范,显然是经过压缩的,需要先还原完整公钥。可以使用<a target="_blank" rel="noopener" href="https://const.net.cn/tool/sm2/sm2-pubkey-decompress/">这个小工具</a>进行还原,也可以研究一下压缩的原理然后自己造个轮子,当然我懒所以选择前者。</p><pre><code class="hljs python"><span class="hljs-keyword">import</span> base64
|
|
|
<span class="hljs-keyword">from</span> gmssl <span class="hljs-keyword">import</span> sm2
|
|
|
|
|
|
sm2_crypt = sm2.CryptSM2(public_key=<span class="hljs-string">'04cd77e007bdc86eeaf9a479ba7a2c22bc0a517ccb3a6975c3f94b4ac93347dea65fb8709f2915105fdd5c81bae765774ca7a9392ad3b557b1d239741c2899c868'</span>, private_key=<span class="hljs-string">''</span>, mode=<span class="hljs-number">1</span>)
|
|
|
idcard_encrypted = base64.b64encode(sm2_crypt.encrypt(idcard.encode(<span class="hljs-string">'utf-8'</span>))).decode(<span class="hljs-string">'utf-8'</span>)</code></pre><p>这样就可以正常加密了。正以为万事大吉,当我把加密的密文传给阿里云时,阿里云接口却报错了。令人无语的是,接口返回的信息只有一句 <code>501 系统错误</code>,除此之外啥也没有。起初我甚至没有怀疑是加密的问题,还以为是别的参数有问题或者阿里云接口挂了(毕竟最近阿里云频繁出事),直到我尝试明文传参成功后才意识到问题出在加密上。显然,阿里云的私钥解不开我传递给它的密文。</p><p>于是我又花了大量的时间弄清究竟是哪出了问题。根据现行 <a target="_blank" rel="noopener" href="https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=2127A9F19CB5D7F20D17D334ECA63EE5">GB/T 35276-2017</a> 7.2节的定义,我们不妨将 x 分量和 y 分量合称为 C1,密文称为 C2,杂凑值称为 C3,则加密数据由 C1、C2、C3三部分组成,且三者的排列顺序为 C1C3C2。同时在查阅了一些资料后,我还了解到在最初的国密标准中,加密数据的排列顺序为 C1C2C3,不过我没有找到相关的标准文件。正因为国密 SM2存在 C1C3C2和 C1C2C3两种加密模式,我使用的 Python 国密加密包提供了 <code>mode</code> 选项以便开发者根据需求设定加密模式。然而阿里云根本没告诉我它解密时使用的是哪一种,不过这个问题暂时不重要,因为经过尝试无论哪一种都问题依旧。</p><p>迫不得已我只好把目光看向了阿里云提供的 Java 例程,尝试跑了一下,比对了同一个字符串使用 Python 国密加密包和使用 Java 例程的加密结果,终于发现了问题所在。Java 例程产生的密文 Base64 串永远以字符 <code>B</code> 开头,而 Python 加密包产生的密文 Base64 串开头字符却一直在变,这显然不合理。通过观察 Java 例程加密结果的第一个字节,我惊奇地发现竟然永远是 <code>\x04</code> 这个熟悉的家伙。于是我手动给 Python 加密包的加密结果加上了这个字节,然后尝试了一下 C1C3C2和 C1C2C3两种加密模式,确认是 C1C2C3 模式(非现行标准),总算是对接成功了。</p><pre><code class="hljs python"><span class="hljs-keyword">import</span> base64
|
|
|
<span class="hljs-keyword">from</span> gmssl <span class="hljs-keyword">import</span> sm2
|
|
|
|
|
|
sm2_crypt = sm2.CryptSM2(public_key=<span class="hljs-string">'04cd77e007bdc86eeaf9a479ba7a2c22bc0a517ccb3a6975c3f94b4ac93347dea65fb8709f2915105fdd5c81bae765774ca7a9392ad3b557b1d239741c2899c868'</span>, private_key=<span class="hljs-string">''</span>, mode=<span class="hljs-number">0</span>)
|
|
|
idcard_encrypted = base64.b64encode(<span class="hljs-string">b'\x04'</span> + sm2_crypt.encrypt(idcard.encode(<span class="hljs-string">'utf-8'</span>))).decode(<span class="hljs-string">'utf-8'</span>)</code></pre><h2 id="总结"><a class="markdownIt-Anchor" href="#总结"></a> 总结</h2><p>这次开发可以说是一波三折,一部分原因是对国密算法不熟悉,互联网上相关的资料(尤其是 Python 下的进行国密加密)也较少,另一部分原因则是阿里云存在如下的问题有待改进:</p><ul><li>文档过时内容未及时更新</li><li>接口不返回详细错误信息,导致排查困难</li><li>参数加密约定不清晰、不详细</li><li>使用非现行标准(C1C2C3)且不加说明</li></ul><p>总之希望这篇文章能够帮助到后来者,也希望阿里云能够改进文档和接口,提升产品的易用性。</p></body></html></div><div class="license"><div class="license-title">阿里云金融级实人认证接入踩坑记</div><div class="license-link"><a href="https://blog.hans362.cn/post/aliyun-financial-grade-id-verification/">https://blog.hans362.cn/post/aliyun-financial-grade-id-verification/</a></div><div class="license-meta"><div class="license-meta-item"><div class="license-meta-title">本文作者</div><div class="license-meta-text">Hans362</div></div><div class="license-meta-item"><div class="license-meta-title">最后更新</div><div class="license-meta-text">2023-12-02</div></div><div class="license-meta-item"><div class="license-meta-title">许可协议</div><div class="license-meta-text"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="nofollow noopener noreferrer" target="_blank">CC BY-NC-SA 4.0</a></div></div></div><div>转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!</div></div><div class="post-footer__cats"><a href="/categories/%E6%8A%80%E6%9C%AF%E5%90%91/" class="post-cats__link button">技术向</a><a href="/tags/%E9%98%BF%E9%87%8C%E4%BA%91/" class="post-tags__link button"># 阿里云</a><a href="/tags/Web/" class="post-tags__link button"># Web</a><a href="/tags/Python/" class="post-tags__link button"># Python</a></div></article><div class="nav"><div class="nav__prev"><a href="/post/2023-annual-report/" class="nav__link"><div><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M589.088 790.624L310.464 512l278.624-278.624 45.248 45.248L400.96 512l233.376 233.376z" fill="#808080"></path></svg></div><div><div class="nav__label">上一篇</div><div class="nav__title">2023年终总结</div></div></a></div><div class="nav__next"><a href="/post/weekly-30/" class="nav__link"><div><div class="nav__label">下一篇</div><div class="nav__title">周记#30</div></div><div><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M434.944 790.624l-45.248-45.248L623.04 512l-233.376-233.376 45.248-45.248L713.568 512z" fill="#808080"></path></svg></div></a></div></div><div class="post__sponsers card"><div class="sponser-label">喜欢这篇文章吗?考虑支持一下作者吧~</div><a class="sponser-button button" href="https://afdian.net/@hans362" rel="external nofollow noreferrer" target="_blank" data-type="afdian">爱发电</a> <a class="sponser-button button" data-type="alipay">支付宝<img class="sponser-qrcode" src="https://hans362-img.oss.0vv0.top/2021/08/05/68281340.jpg"></a></div><div class="post__comments post__with-toc card" id="comment"><h4>评论</h4><div id="disqus_thread">您所在的地区可能无法访问 Disqus 评论系统,请切换网络环境再尝试。</div></div></div></main><footer><p class="footer-copyright">Copyright © 2017 - 2025 <a href="/">Hans362 's Blog</a></p><p>Powered by <a href="https://hexo.io" target="_blank">Hexo</a> | Theme - <a href="https://github.com/ChrAlpha/hexo-theme-cards" target="_blank">Cards</a></p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-8746554831230893" data-ad-slot="6356225601" data-ad-format="auto" data-full-width-responsive="true"></ins><script>(adsbygoogle=window.adsbygoogle||[]).push({})</script></footer></div><script defer src="https://blog.hans362.cn/npm/vanilla-lazyload@17.8.3/dist/lazyload.min.js"></script><script>window.lazyLoadOptions={elements_selector:".lazy"}</script><script async defer data-website-id="5d181692-8a81-4c20-a282-cee87a6b90ef" src="https://analytics.0vv0.top/vue.js"></script><script src="/js/pageviews.js"></script><link rel="stylesheet" href="https://blog.hans362.cn/npm/katex@0.16.0/dist/katex.min.css" crossorigin="anonymous"><script>function loadComment(){let n,e;(n=document.createElement("script")).src="https://blog.hans362.cn/js/disqus.js",document.body.appendChild(n),n.onload=()=>{new DisqusJS({shortname:"hans362-s-blog",siteName:"Hans362 's Blog",api:"https://api-v3.hans362.cn/",apikey:"8Z1UVT4UOk22yNyk9MhpqQ0FLb27Hb1bpV066b4v9zOFie0GQ6VCoJ9TJwoGlCVF",admin:"hans362",identifier:"post/aliyun-financial-grade-id-verification/",url:"https://blog.hans362.cn/post/aliyun-financial-grade-id-verification/",nesting:"4"})},(e=document.createElement("link")).rel="stylesheet",e.href="https://blog.hans362.cn/css/disqusjs.css",document.head.appendChild(e)}var runningOnBrowser="undefined"!=typeof window,isBot=runningOnBrowser&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro|msn)bot|crawl|spider|yand|duckgo/i.test(navigator.userAgent),supportsIntersectionObserver=runningOnBrowser&&"IntersectionObserver"in window;setTimeout(function(){var e;!isBot&&supportsIntersectionObserver?(e=new IntersectionObserver(function(n){n[0].isIntersecting&&(loadComment(),e.disconnect())},{threshold:[0]})).observe(document.getElementById("comment")):loadComment()},1)</script></body></html> |