首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >材料散落、进度靠盯?我用 WorkBuddy 搭起微信支付特约商户进件系统

材料散落、进度靠盯?我用 WorkBuddy 搭起微信支付特约商户进件系统

原创
作者头像
悟空码字
发布于 2026-10-20 11:28:46
发布于 2026-10-20 11:28:46
30
举报
文章被收录于专栏:工具工具

大家好,我是小悟。

做微信支付服务商,帮商户完成入驻,也就是特约商户进件,是绕不开的一环。营业执照、法人身份证、结算银行卡、联系人信息、经营类目,五大类加起来四十多个字段,其中身份证号、银行卡号、手机号属于敏感个人信息,按规定必须用微信支付平台公钥做 RSA 加密才能上送,明文严禁出现在任何传输链路里。

听起来是个体力活,对吧?可真正折磨人的从来不是"能不能做",而是"做不做得稳"。商户随手一拍的营业执照往往单张就有四五兆,材料散在群里、散在本地盘;字段填错要翻半天聊天记录找原始依据;运营换班后新人接不住进度;同一个商户被重复问一遍身份证号。我一度以为,这种乱只能靠人盯、靠耐心去扛。直到我换了个思路:与其盯流程,不如给流程一个不会失忆的底座,把和微信、和 OCR 的对接交给代码——而写代码这件事,我全程只和 WorkBuddy 对话。

一、它解决了什么

在写第一行代码之前,我先把痛点理清楚。问题从来不在"能不能调接口",而在"能不能把一堆散乱的材料和状态稳稳地管起来"。

真实痛点

系统给出的解法

材料散落各处、易丢、易重复采集

每个商户对应一个 Agent Bucket Space,材料一次上传、永久可追溯,换人不丢上下文

身份证、银行卡明文流转,合规风险高

敏感字段经 RSA-OAEP 加密后才落库,系统自始至终只持密文,运营和日志里看不到任何明文

进度靠人盯,换班接不住

进件被建成一条状态机(草稿→已提交→驳回→通过),每一步都持久化,断点可恢复

微信驳回后,要在聊天里翻原始材料重传

驳回自愈:把微信返回的审核项直接映射到材料类型,精准告诉运营"该补传哪一张"

签约与审计无据可查

审核通过后生成只读确认函外链,每一动作都写入事件时间线,事后可回溯

这些解法不是凭空设计的,而是每一次被微信驳回、每一次在群里找不到材料时,我把它讲给 WorkBuddy 听,再由它帮我想清楚"该把这块能力放哪一层"逐步长出来的。

二、系统由哪些模块组成

系统的骨架很朴素:一个原生 JS + Jinja2 的前端向导,一个 FastAPI 编排层,下面挂三个"会干活"的能力——Agent Bucket 存储底座、腾讯云 OCR 预审、微信支付 v3 进件适配器。它们之间不直接互传文件,而是把产物写进 Bucket,再从 Bucket 读取下游需要的状态。

逐个说一下它们各自做什么:

  • 前端向导(templates/index.html):按主体类型动态显隐字段,实时做必填与日期合法性校验,支持拖拽上传、图片压缩回显。表单是创建时手填、编辑时回填,提交前后端双重校验。
  • 后端编排层(main.py / workflow.py):系统的"大脑"。它把 Space 创建、材料上传、OCR、微信审核、驳回自愈、签约串成一条状态机;每一次状态流转都写进事件时间线。关键设计是适配器可替换——AgentBucketAdapter 和 WeChatApplymentAdapter 都同时提供 mock 和 real 两套实现,页面填了密钥就走 real、留空走 mock,改完配置重启即可切换,开发期完全不用真连微信就能把全流程跑通。
  • Agent Bucket 存储底座(storage/agent_bucket.py):以 Space 为一级容器、Task 为二级单元。它把 COS 的 V5 签名、分区、生命周期屏蔽掉,上层只看到 put / get / delete / share_link 几个动作。多租户靠 Space 前缀硬隔离,一个商户的材料绝不会串到另一个商户。
  • 腾讯云 OCR 预审(ocr/precheck.py):上传营业执照或身份证,OCR 抽出统一社会信用代码、商户全称、身份证号等结构化文本,直接回填表单,运营只需核对。真实调用失败会自动降级为模拟预审,不会让上传卡死。
  • 加密落库(crypto_sign.py / rsa_oaep.py):零依赖实现 RSA 签名与 RSA-OAEP 加密。前者给微信 v3 请求签名(手写 WECHATPAY2-SHA256-RSA2048),后者把敏感字段加密成密文再落 Bucket。两者都带自检,不依赖 cryptography 也能跑。
  • 微信 v3 进件适配器(wechat/applyment.py):手写微信签名、图片转 media_id 上传、按官方文档完整拼装申请单、查询审核状态并把驳回项映射回材料类型。
  • 图片压缩(image_compress.py):上传前把图片压到 ≤2MB(微信图片上传限制),最长边缩到两千像素以内,逐级降质,保留肉眼可见信息。
  • 签约确认函(workflow.py + main.py):审核通过后生成 confirmation_token,据此产出 COS 预签名外链,渲染成一张只读确认函页面,给商户或协作方查看。

三、一次进件走完是怎样的

把一次完整的进件拆开看,引导逻辑是一条清晰的路径。商户建 Space 后,材料上传即触发 OCR 预审回填,图片压缩后做 RSA 加密落库,再交微信 v3 提交;任何一步卡住都会回到对应节点给出精准提示,而不是笼统报错;微信驳回时,自愈模块定位需重传的材料,运营在原任务上补传即可,不必从头再来。

最让我满意的一处设计是:密文在提交之前就已经落进 Bucket,提交这一动作因此变成幂等的"读密文再上送"。哪怕提交环节网络抖动失败,重试时直接读取密文即可,不用让商户再提供一遍敏感信息——商户完全感知不到中间失败。

四、它怎么从一句想法,变成跑着的系统

这是我想重点说的部分。系统不是一次写对的,而是和 WorkBuddy 反复对话、把每一次报错当成线索逐步拆出来的。整个过程是一个循环:我有一个想法或遇到一个报错,描述给它,它生成或修改代码,我运行,报错就再丢回对话,对齐官方文档定位根因,修复,再运行。

开局并没有先把整张架构图画完。第一句话大概是:"帮我搭一个微信支付特约商户进件的 Web 工具,先把 mock 全流程跑通。"WorkBuddy 给了我一个 FastAPI + Jinja2 的 MVP 骨架,我很快就能在 127.0.0.1:7860 上走完"建 Space→传材料→提交→驳回→自愈→签约"的完整链路。等骨架立住,再一轮轮往里填真实能力:先是把 OCR、Agent Bucket、微信三组配置改成页面录入、填了走 real 留空走 mock;然后是手写 COS V5 签名接入真实存储;接着是手写微信 v3 签名、图片转 media_id、零依赖 RSA——每一步都是"我先说要什么,它给初版,我跑,报错再聊"。

几个印象最深的排障:

Wechatpay-Serial 头被悄悄改了大小写。 加上请求头之后仍报错"缺少微信支付平台证书序列号"。我把报错丢回对话,WorkBuddy 让我去看底层实现才发现:底层用 email.Message 存请求头,会把 Wechatpay-Serial 规范成全小写,而微信严格区分大小写。修法是改用 unredirected_hdrs(纯字典)注入,保住原始大小写;序列号则从平台证书 DER 结构里递归抽取第一个 INTEGER。

RSA-OAEP 的哈希算法用错了。 这是最隐蔽的一个。微信要求用 SHA-1 做掩码生成哈希,而一开始按惯例用了 SHA-256,结果微信回"平台私钥解密失败"。为确认不是我多心,临时装了 pycryptodome,用它的 PKCS1_OAEP(hashAlgo=SHA1) 当作微信官方算法的权威实现,对七个样本(姓名、身份证、手机、邮箱、执照号、住址、银行卡)做交叉验证——本系统的加密结果和官方实现逐字节 MATCH,才敢确信 SHA-1 才是正解。验证完立刻卸载,没让测试依赖污染项目。

长期执照的"开始时间"也必须填。 以为选了"长期"就可以省略有效期起期,结果微信回"证书有效期开始时间格式错误"。和 WorkBuddy 对齐官方文档后明白:period_begin 对所有执照必填,只有 period_end 才能填"长期"。然后在后端加了护栏——缺失 period_begin 直接抛清晰的中文错误,不再把空值丢给微信让它回含糊提示。

这三处,每一个背后都对应一条分散在文档角落的硬约束。WorkBuddy 的价值,是让我能把"这次又报了什么"直接丢进对话,快速定位到对应字段和文档条款,而不是从头翻规范。

五、几个工程取舍

  • 加密与落库的时序:早期把加密放在提交那一刻,提交失败就要重加密、重采集。把密文提前落 Bucket 后,提交变成幂等的"读密文再上送",重试成本趋近于零。
  • OCR 与压缩的顺序:先压再识别,而非先识别再压。大图直接送 OCR 既慢又费配额,压到合理体积后识别准确率几乎没有损失,成本却降了一截。这个顺序后来成了处理所有用户上传图片的默认姿势。
  • 删除的可见性:级联删除一开始只返回成功,运营不知道到底清了哪些子任务和令牌。改成先返回一份影响范围清单、二次确认后再物理清理,等于在危险操作前加了一道护栏。对存储底座来说,删得对比删得快重要得多。
  • 多返回值的约定:曾因 (body, status) 与 (status, body) 解构反了,导致取到的 body 其实是 int 的状态码,触发一串晦涩的类型错误。自此我更倾向用命名元组或 dataclass 来明确多返回值。

六、写在最后

用下来,我对 WorkBuddy 这类 AI 编程环境的判断更明确了:它的价值不在于替你写出完美代码,而在于把"反复试错"压缩成"即时对话复盘"。进件接口里那些散落、隐晦、报错含糊的约束,恰好是需要人和 AI 一起啃的硬骨头——它帮你快速比对文档、构造请求体、做交叉验证,最终的判断权和责任仍在写代码的人手里。

接口约束的权威性永远来自官方文档,系统只是把文档翻译成了人话。这一点,在每一处修复时都坚持用真实提交或权威实现去验证,而不是凭推断下结论。毕竟支付进件没有"差不多",只有"过"和"不过"。

如果你也正在和某个报错含糊、文档分散的接口搏斗,不妨试着不急着翻源码,而是先把报错原样讲给 WorkBuddy 听,往往聊着聊着,路就清楚了。

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。

您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、它解决了什么
  • 二、系统由哪些模块组成
  • 三、一次进件走完是怎样的
  • 四、它怎么从一句想法,变成跑着的系统
  • 五、几个工程取舍
  • 六、写在最后
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档