要点速览
支付插件的安装包里不该有 API 密钥,Paymos 的包也确实没有:这个压缩包对每个商户 都是同一个文件,不含 API key、API secret、项目 ID、webhook secret、OAuth 令牌 或设备码。安装之后也不用手工补:连接店铺是一次授权,密钥、webhook 和项目绑定 都在这一步里配好。按商户单独打包的做法,是用「把一个可用的密钥写进文件」换来 更短的安装流程,而这个文件之后会进备份、工单附件和代码仓库。两步检查——一次 搜索和一次校验和——就能看出你拿到的是哪一种。
Paymos 的插件包里没有凭据。商户为 WooCommerce、Magento 2 或者另外六个官方插件下载的压缩包,和其他商户下载的是同一个;里面没有 API key、API secret、项目 ID、webhook secret、OAuth 令牌,也没有设备码。下载这个动作不连接任何东西。
后面的步骤也不会把它们塞进去。连接店铺是一次授权,密钥、webhook 和项目绑定都在这一步里配好,然后在店铺自己这一侧加密保存。
把压缩包留空不是细节,正是这件事的重点。按商户单独打包、密钥已经写在里面的文件,本身就是一份可用的凭据——而文件是会跑的:跑进下载目录、跑进每晚的备份、跑进工单附件,跑进那个装着站点主题的代码仓库。
找外包或者代运营的店铺尤其容易碰上。「这个插件发我一份」听起来只是传个文件;包里要是带着密钥,同一句话的意思就变成了把账户交出去。
装插件是 WooCommerce 文档和它旁边七篇的事,选哪一个是插件总览的事。这篇写在两者下面:一个插件包能装下什么,Paymos 的包里装了什么,以及怎么核实别人递给你的那一个。
支付插件的安装包里装着什么?
支付插件的安装包是一个代码压缩包——CMS 要安装的那个扩展,加上向店铺描述它的那些文件。里面的内容对每个下载的人都一样,没有哪一部分是为下载它的那个商户准备的。
值得把它打开看一眼的原因,是一套能跑起来的接入最终需要的东西:一个 API key、一个 API secret、一个项目绑定,和一个 webhook secret。所以网关在这里有一个选择:这些东西什么时候存在——在打包时写进文件,还是在连接时再配。
Paymos 把这个选择放在连接那一刻。下载路由提供的是一个静态文件,不是按账户临时拼装的包;这就是为什么压缩包对每个商户都一样,也不含上面那几类凭据中的任何一种。
两种做法的差别在于压缩包是什么东西。打包时写进去的密钥,把这个文件变成了一份机密;连接时才配的密钥,让文件保持为代码,机密在店铺自己那一侧生成。
为什么有的网关会把密钥写进下载包?
网关把凭据写进下载包,是为了把安装的活从商户身上拿掉。它的前提是两件事必然连在一起——一家什么都不用配的店铺,肯定是拿到了一个早就知道自己属于谁的文件。
这条捷径的代价由压缩包来付。把一把密钥写进插件包,就是把它从代码变成了持有即生效的凭据:拿到文件的人就等于拿到了它对应的那个账户,而拿到一个文件的门槛非常低。
写死密钥的包还把两件事压成了一件。拿代码不需要账户,谁都可以重复拿;连接一家店铺是要认证的,而且只发生一次。带密钥的压缩包把这两件事合成了同一件。
MITRE 把这种一般形态编在 CWE-798,Use of Hard-coded Credentials——「产品中含有硬编码的凭据,例如口令或加密密钥」。它的经典情形是所有安装共用一个机密;按商户打包把这一点反过来,给每个文件配一把自己的,却保留了要害的那部分:一个可用的机密,静静躺在一个可以分发的文件里。
插件包下载之后会去哪些地方?
插件包不会停在它落地的位置。下载目录只是若干站里的第一站,而后面那些站点在设立的时候,没有一个是把凭据考虑在内的:
- 笔记本上的下载目录,没有加密,在有人清理之前一直躺着。
- 每晚一次的站点备份,以及这份备份产生的每一个还原点。
- 工单附件——商户把「那个插件」发给正在帮他看问题的人的那一刻。
- 纳入版本管理的站点仓库,就放在主题旁边。
- 外包同事的电脑,因为把文件转过去是交接工作最快的方式。
对一个不含凭据的压缩包,这五处都不算事:文件里是公开的字节,什么都不泄露。对一个写进了密钥的压缩包,这五处每一处都是一次泄露,而商户手里没有一份「发生过几次」的记录。
这份清单真正麻烦的地方在于不可撤回。删掉一份备份,收不回从它还原出来的副本;撤回一个工单附件,也撤不回已经下载过它的人。凭据从一开始就不在里面时,这些问题一个都不会提出来。
怎么核实别人给你的这个包?
核实一个插件包的方法,是在它进入站点之前解开来搜一遍。三条命令就能把问题问完,而且都不需要网关配合。
# 1. 在包进入店铺之前先解开
unzip -q plugin.zip -d pkg
# 2. 搜一遍所有长得像可用凭据的东西
grep -rIn -iE 'api[_-]?key|secret|token|client_id|device_code' pkg
# 3. 算哈希,再和同一版本的第二次下载比对
shasum -a 256 plugin.zip
第二步里的 -i 是真在干活:一个常量写成 API_KEY 或 ApiKey 的概率不比 api_key 低,区分大小写的搜索会从两者旁边走过去。拿这条模式跑公开的 Paymos WooCommerce 源码,带 -i 返回 65 行,不带返回 63 行。
这些命中要当成字段名、标签和翻译文案来读,不是当成结论。在那棵源码树里,其中三十八行落在 tests/ 下面,那里像 'api_key' => 'pk_test_1234567890' 这样的写法本来就是占位;真正要停下来看的,是测试目录之外带着真实值的那一条。
搜索只能给出提示,校验和才能定案。换一台机器把同一个版本再下载一次,也算一遍哈希:对每个商户都相同的压缩包会两次给出同一个哈希,按商户拼装的包做不到。
包里是空的,插件的密钥从哪来?
插件的密钥来自一次授权。装好这个版本,在店铺后台点 Connect Paymos,在打开的 Paymos 标签页里确认这次请求——剩下的由连接这一步配好:
- 密钥。 复用商户当前生效的收款密钥,没有就新建一个;沙盒和正式一起配好,所以之后把插件切到正式环境不需要重新连接。
- webhook。 账单 webhook 由平台自己注册,只有回调地址、类别和项目三者都一致时才复用已有的那个,同一地址上冲突的 webhook 绝不做静默覆盖。
- 项目。 在插件里根本不选——绑定的是控制台里当前打开的那个项目,整条流程里没有第二个项目选择器。
于是「为了省事」这个论点自己回答了自己。按商户打包,是拿一个写进文件的机密换来更短的安装流程;而用这种方式连接的店铺,同样什么都没配,它装进去的那个文件里也仍然什么都没有。
为什么一个包能给所有商户用?
一个包能给所有商户用,是因为插件是代码,而代码里面没有账户。各个 CMS 平台假设的正是这一点,它们的分发规则也是围着这一点写的。
WordPress 把这个假设写成了目录规则:「WordPress.org 分发的插件版本只有目录里的那一个」。一个版本一个产物、发给所有人,是 CMS 期待插件抵达时的形态——不管由哪条渠道送达。
按商户拼装的包塞不进这样的渠道。这种文件没法作为一个发布版本公开,没法和一个公共版本对照,也没法在版本之间做差异比对,因为根本不存在唯一一个已发布的版本可以拿来比。
Paymos 的八个官方插件按公开发布下载分发,一个平台一个版本一个包。每次发布为 WooCommerce 和 WHMCS、OpenCart 和 PrestaShop、Magento 2 和 Shopware 6、CS-Cart 和 Easy Digital Downloads 各产出一个压缩包。
不带密钥的包让哪些操作变简单?
一个不含凭据的包,让三件很平常的操作不至于变成泄露:把文件发给别人、轮换一把密钥、替换插件。这三件事在普通的一周里都会发生。
把文件交给开发、外包或者同事,什么都不会泄露,因为 Paymos 的压缩包就是别人手里已经有的那一个。会移动的那个东西,不是能授予访问权限的那个东西。
轮换凭据也不需要重新下载。密钥和压缩包是两个独立的对象,所以轮换之后整套操作就是把店铺重新连接一次;webhook secret 的轮换还带一个过渡期,当前密钥和上一把密钥签出来的签名都接受。
OWASP 把轮换放在同一个位置:「你应当定期轮换机密,这样被盗的凭据只能在很短的时间内可用」。一次得先重新下载插件才能开始的轮换,就是一次会被一直往后拖的轮换。
空包又证明不了什么?
一个不含凭据的压缩包只证明一件事:这个文件里没有带着机密。它留下两个问题没答,而这两个都比它答掉的那个更重要。
第一个是存储。凭据到了店铺那边,总得有个东西把它存下来,怎么存是另一个属性、另一个答案——Paymos 插件把这些值加密存在店铺自己一侧,从不返回给浏览器,也不提供手工修改的入口。
第二个是运行时。压缩包是代码的一张快照,所以读一个插件的压缩包,看到的是它能做什么,不是它在一家有真实账单在跑的店铺上实际做了什么。
存储和运行时都值得一个答案,而校验和一个都解决不了。翻压缩包是便宜的那一步:在装任何东西之前花几分钟,把一整类暴露方式挡在外面。
这个密钥本身该有多窄?
递到 CMS 手里的凭据,应该是能干完这件事的最窄的那一份,因为店铺是一台共享的机器,插件目录里的东西,任何有后台权限的人都读得到。Paymos 的做法在这个问题被提出之前就先把它收窄了。
连接这一步配的是一份收款凭据,而收款和转出是两套凭据,所以一个收银插件从来不会拿到那把能把钱转走的。沙盒和正式也在同一套 API 契约上用两套凭据,所以店铺拿去测试的那把,不是收真实付款的那把。
一份 Paymos 凭据可以带最多 50 条 IP 白名单,把它钉在店铺实际运行的那些地址上。从别处递上来的同一份凭据会被拒绝,所以从备份里捞出来的密钥,不是一把能用的密钥。
Merchant API 的认证是 HMAC-SHA256 请求签名,不是持有即生效的令牌,所以这份机密是用来签请求的,不会跟着请求一起发出去。API 密钥那一页把整套凭据模型讲完了。
装插件之前该问哪几个问题?
四个问题就能把一个支付插件怎么处理凭据问清楚,而且四个都能在文件进入站点之前回答。
- 这个压缩包对所有人都一样吗?给自己的下载算个哈希,再从另一台机器取同一个版本,对一遍。
- 包里有没有一个可用的值?在解开的文件里搜像凭据的字符串;字段名和测试数据不算结论。
- 装好之后插件把凭据放在哪里?这该写在文档里,不该出现在一条客服回复里。
- 它手里那份凭据有多窄?一个带着转出权限的收银插件,拿的比这份活需要的多。
这四个问题没有一个称得上安全审计;但合起来,它们排掉了那种没有补救步骤的故障:一个机密已经被复制到了没人记过账的地方。
插件只是从店铺通向收款通道的一条路,在网站上收加密货币的其他做法讲的是其余几条。不管店铺走哪一条,它的凭据都该从那里开始,而不是从一个已经跑过好几个地方的文件里开始。
| 凭据 | 是否写在下载包里 | 不在包里的话从哪来 | |
|---|---|---|---|
| API key | 没有 | 连接那一步配好,沙盒和正式一起 | |
| API secret | 没有 | 连接那一步配好,在店铺侧加密存储 | |
| 项目 ID | 没有 | 按控制台里打开的项目绑定,插件里不选 | |
| webhook secret | 没有 | 随平台注册的 webhook 一起生成 | |
| OAuth 令牌或设备码 | 没有 | 短时有效,连接过程中用掉即丢弃 |
常见问题
Paymos 插件下载包里有我的 API key 吗?
没有。压缩包里不含 API key、API secret、项目 ID、webhook secret、OAuth 令牌 或设备码。这些是在连接店铺之后,由一次授权配好的。
装完插件之后我要配置什么?
什么都不用配。连接就是店铺后台里的一个按钮,加上在 Paymos 标签页里点一次确认; 密钥、webhook 和项目绑定都在这一步里完成。
每个商户拿到的插件文件不一样吗?
一样。下载的包对每个商户都是同一个,所以同一个版本下载两次,字节相同,校验和 也相同。
装好之后,Paymos 插件把凭据存在哪里?
存在店铺自己这一侧,加密保存,并且不会返回给浏览器。凭据跟着店铺走,不在分发 的压缩包里,所以换一个压缩包不会搬动任何一份凭据。
怎么检查一个插件包里有没有凭据?
把压缩包解开,搜一遍像凭据的字符串,再对文件做一次哈希,和同一版本的第二次 下载比对。结果里出现字段名是正常的,出现真实值不正常;测试目录下的命中是 测试数据。
下载插件会把我的店铺连上 Paymos 吗?
不会。下载只搬运代码。店铺是在另一个步骤里连接的,由店铺后台发起的一次授权 完成。
插件最后手里拿着哪一种凭据?
一份收款凭据,在连接时从商户当前生效的收款密钥推导,没有就新建一个。收款和 转出是两套凭据,所以插件从来不会拿到那把能把钱转走的。
什么时候不该用翻查安装包这件事
- 如果你的问题是店铺装好之后怎么保管这把密钥,翻压缩包回答不了。一个不含凭据的 文件说明不了存储方式,去读插件的凭据存储文档。
- 如果接入的是你自己写的 REST API 代码,不是打包的插件,那就没有压缩包可查。 该审的是部署路径:环境变量、CI 变量、配置文件。
- 如果你要的是一份连服务器自己都读不回来的凭据,跑在自己主机上的插件不是该找的 地方。店铺能递给 API 的东西,店铺就能保存;真正管用的是密钥外面的控制,比如 IP 白名单。
- 如果这家网关根本不提供下载,扩展是从它自己的后台装进去的,校验和这一步没有可 比对的对象。那就问清凭据被写到哪里,以及还有谁能读到那个位置。
参考来源
- 1. CWE-798: Use of Hard-coded Credentials (accessed 2026-08-16)
- 2. OWASP Secrets Management Cheat Sheet (accessed 2026-08-16)
- 3. WordPress Plugin Directory guidelines (accessed 2026-08-16)
- 4. Paymos 文档 — WooCommerce 插件 (accessed 2026-08-16)
最近复核:2026年8月16日


