
后端金融科技【免费下载链接】pay可能是我用过的最优雅的 Alipay/WeChat/Unipay/江苏银行 的支付 SDK 扩展包了项目地址https://gitcode.com/yansongda/pay点击查看免费下载本文基于仓库根目录的 AGENTS.md 展开。这份文档是 yansongda/pay 项目面向开发者及 AI Agent的工程约定总纲规定了项目的目录结构、核心组件、安全原则、开发命令与验签体系。读懂它你不仅能掌握这套 PHP 多支付网关 SDK 的插件管道架构与回调验签全貌还能按仓库既定规范独立完成一个支付网关 Provider 的完整扩展。一、项目概览以插件管道为核心的多网关支付 SDKAGENTS.md 对项目的一句话定义是PHP 支付 SDK支持支付宝、微信、银联、抖音、江苏银行、PayPal、Stripe基于插件管道架构关注支付流程、回调验签和 Provider 扩展一致性。结合仓库现状可以看到从 composer.json 可知项目要求 PHP 8.2依赖yansongda/artful管道/容器/事件底层与yansongda/supportsCollection、Config 等支持类src/ 下内置了 11 个 ProviderAlipay、Wechat、Unipay、Jsb、Douyin、Allinpay、Bestpay、Apple、Airwallex、Paypal、Stripe其入口类均在 src/Provider/ 下每个 Provider 的完整能力由「配置类 Provider 类 插件集 Shortcut Trait」五部分协同提供这一结构正是 AGENTS.md 中「代码一致性」原则要求新增网关时必须遵循的骨架。二、目录结构各层职责一目了然AGENTS.md 给出的src/结构总览如下src/ ├── Config/ # Typed ConfigWechatConfig、AlipayConfig 等 ├── Event/ # PSR-14 事件 ├── Plugin/{Provider}/V{n}/ ├── Provider/ # Alipay、Wechat 等 ├── Shortcut/{Provider}/ ├── Traits/ # {Provider}Trait、ProviderConfigTrait ├── CertManager.php # 证书缓存 └── Pay.php对照实际源码各目录的职责可以进一步说明目录/文件职责典型证据src/Config/每个 Provider 一个类型化配置类如AlipayConfig、WechatConfig并各自实现validate()AlipayConfig.php、WechatConfig.phpsrc/Provider/Provider 门面类统一实现ProviderInterface暴露pay/query/cancel/close/refund/callback/success等能力Alipay.php、Wechat.phpsrc/Plugin/按{Provider}/V{n}/组织版本化插件是管道中执行具体动作的最小单元Alipay/V2/Pay/、Wechat/V3/Pay/src/Shortcut/{Action}Shortcut将「一次调用」编排为一串插件列表Alipay/WebShortcut.phpsrc/Traits/静态工具方法网关 URL 构建、回调验签、配置获取AlipayTrait.php、WechatTrait.phpsrc/Event/PSR-14 事件定义CallbackReceived、MethodCalled、PayStart/PayEnd、HttpStart/HttpEndCallbackReceived.phpsrc/CertManager.php证书读取、解析与静态缓存见第七节详解src/Pay.php全局静态入口负责配置注入与各 Provider 服务注册见第六节详解三、核心组件速查AGENTS.md 列出了一张核心组件表这里逐项结合源码位置加以印证符号位置用途Pay::alipay()src/Pay.php支付入口Pay::wechat()src/Pay.php微信入口ProviderInterfacesrc/Contract/核心接口pay/query/cancel/close/refund/callback/successRocketYansongda\Artful\Rocket承载 params/payload/radar/destinationCertManagersrc/CertManager.php证书读取与缓存Eventsrc/Event.phpPSR-14 事件分发{Provider}Configsrc/Config/类型化配置对象关于Pay::alipay()这类入口方法的真实形态Pay.php 中通过__callStatic实现任意Pay::xxx()静态调用都会先从容器取出对应服务而 11 个 Provider 的服务实例是在Pay::config()执行时通过$providers数组逐个Artful::load()注入的见 Pay.php 与 Pay.php每个 ServiceProvider 继承自 src/Service/AbstractServiceProvider.php在register()中把 Provider 实例同时注册为「类名」和「Provider 名」如alipay两个键。ProviderInterface则是所有 Provider 的统一契约见 src/Contract/ProviderInterface.phppay(array $plugins, array $params)接收插件列表与参数其余query/cancel/close/refund均以订单数组为入参callback()同时兼容array与ServerRequestInterface两种回调内容。四、两条核心开发原则AGENTS.md 将开发原则浓缩为两条安全第一回调/Webhook 必须验签禁止直接信任传入数据。这一点在整个代码库中是强制执行的。以支付宝为例src/Plugin/Alipay/CallbackPlugin.php 的assembly()在解析业务数据前先完成 RSA2 验签以抖音为例src/Plugin/Douyin/V1/CallbackPlugin.php 中如果回调参数缺少_request或其不是ServerRequestInterface实例会直接抛出InvalidParamsException根本走不到业务解析环节。代码一致性新增 Provider 遵循现有结构。具体的六阶段流程在.agents/skills/dev-guide/SKILL.md中展开见下节。五、开发命令与代码规范AGENTS.md 将「COMMANDS 开发规范」指向.agents/skills/dev-guide/SKILL.md。该指南规定对src/PHP 代码的任何修改需运行以下三项检查composer cs-fix composer analyse composer test各命令的具体含义与 composer.json 中scripts一一对应命令作用说明composer test运行 PHPUnitPHPUnit 11.x Mockery 1.6测试前需安装hyperf/pimple用 Mock HTTP 客户端避免真实请求composer cs-fix代码格式化检查php-cs-fixer 的 dry-run 模式带 diff 输出composer analyse静态分析PHPStan-l 6级别300M 内存上限作用于./src文档站开发命令VitePresscd web pnpm web:dev # 文档开发 cd web pnpm web:build # 文档构建 cd web pnpm web:serve # 本地预览代码规范要点每个 PHP 文件必须declare(strict_types1);可在任意 src 文件开头确认必须使用use导入禁止在代码中直接书写\Yansongda\Pay\...完整命名空间日志与异常消息统一使用中文例如 CertManager.php 中的配置异常: 解析证书失败命名约定{Action}Plugin.php、{Action}Shortcut.php、{Provider}Trait.php。新增 Provider 的六阶段流程源自 SKILL.md可结合仓库现状逐一对照配置src/Config/{Provider}Config.php核心类src/Provider/{Provider}.phpsrc/Service/{Provider}ServiceProvider.php继承AbstractServiceProvider插件src/Plugin/{Provider}/V{n}/必须含 CallbackPlugin快捷方式src/Shortcut/{Provider}/{Action}Shortcut.phpTraitsrc/Traits/{Provider}Trait.php提供get{Provider}Url、verify{Provider}Sign注册Pay.php的$providers数组 Config.php的PROVIDERS映射 Exception.php常量 测试 文档。其中第 6 步可以在 src/Pay.phpProvider 常量与服务提供者清单和 src/Config.phpPROVIDERS名单中直接看到对应的注册点。六、架构要点深度解析6.1 插件管道一次调用的完整流转AGENTS.md 给出的管道模型是StartPlugin → [前置] → 业务插件 → [后置] → ParserPlugin以最典型的支付宝电脑支付为例src/Shortcut/Alipay/WebShortcut.php 中getPlugins()返回的插件链完整印证了这一结构return [ StartPlugin::class, // 装载配置、初始化 Rocket PayPlugin::class, // 业务插件构造下单报文 FormatPayloadBizContentPlugin::class, // 前置格式化 biz_content AddPayloadSignaturePlugin::class, // 后置签名 AddRadarPlugin::class, // 后置挂载调试雷达信息 ResponseHtmlPlugin::class, // 组装 HTML 表单响应 ParserPlugin::class, // 终态解析/收尾 ];管道中数据流动的载体是 AGENTS.md 表中提到的Rocket来自Yansongda\Artful\Rocket它贯穿始终承载params入参、payload请求体、radar调试信息与destination最终响应。每个插件实现统一的assembly(Rocket $rocket, Closure $next)签名通过修改 Rocket 后调用$next($rocket)将控制权交给下一个插件。6.2 动态调用__call→ Shortcut → 管道AGENTS.md 指出「Provider 通过__call调用 Shortcut再进入管道」。以 src/Provider/Alipay.php 为例public function __call(string $shortcut, array $params): Collection|MessageInterface|Rocket|null { $shortcut strtolower($shortcut); $plugin \Yansongda\Pay\Shortcut\Alipay\\.Str::studly($shortcut).Shortcut; return Artful::shortcut($plugin, ...$params); }即Pay::alipay()-web($order)会自动映射到Shortcut\Alipay\WebShortcut再由 Artful 框架按该 Shortcut 声明的插件列表执行管道。显式方法query、cancel、close、refund则先派发MethodCalled事件再委托给__call见 Alipay.php。而pay(array $plugins, array $params)是手动指定插件列表的底层入口直接调用Artful::artful()见 Alipay.php。6.3 配置系统数组自动转为类型化 Config 对象AGENTS.md 提到「Config类自动将数组配置转为{Provider}Config对象」。实现位于 src/Config.php构造函数遍历PROVIDERS名单对items中每个 Provider 下的每个租户default或多租户名执行match实例化对应的WechatConfig/AlipayConfig等类型化对象并替换原始数组。此后任意插件通过getProviderConfig(Pay::PROVIDER_ALIPAY, $params)获取配置时见 src/Traits/ProviderConfigTrait.php都能拿到已具备validate()能力的强类型对象。多租户能力由此而来——getTenant($params)从_config参数读取租户名缺省为default。6.4 事件系统PayListener 桥接 Artful 事件 → Pay 事件AGENTS.md 概括为「PayListener桥接 Artful 事件 → Pay 事件」。注册时机在 Pay.phpPay::config()成功配置 Artful 后立即监听四个底层事件Event::addListener(ArtfulStart::class, [PayListener::class, artfulStart]); Event::addListener(ArtfulEnd::class, [PayListener::class, artfulEnd]); Event::addListener(HttpStart::class, [PayListener::class, httpStart]); Event::addListener(HttpEnd::class, [PayListener::class, httpEnd]);src/PayListener.php 中四个监听方法分别将其转发为 Pay 层事件ArtfulStart → PayStart、ArtfulEnd → PayEnd、HttpStart/HttpEnd → Pay\{HttpStart,HttpEnd}。此外Provider 在关键动作处还会主动派发业务事件每次query/cancel/close/refund派发MethodCalled每次callback()进入时派发CallbackReceived携带 provider 名、原始回调内容与参数见 src/Event/CallbackReceived.php。开发者可以基于这些 PSR-14 事件挂载审计、日志或统计逻辑无需侵入插件代码。七、签名验证体系必须掌握回调验签是支付 SDK 的安全底线。AGENTS.md 给出的各 Provider 验签方式对照表如下Provider方式Trait 方法支付宝RSA 本地验证AlipayTrait::verifyAlipaySign()微信证书签名本地验证WechatTrait::verifyWechatSign()PayPalAPI 验证PaypalTrait::verifyPaypalWebhookSign()StripeHMAC-SHA256 本地StripeTrait::verifyStripeWebhookSign()银联证书签名本地验证UnipayTrait::verifyUnipaySign()江苏银行RSA 本地验证JsbTrait::verifyJsbSign()抖音SHA1 本地验证CallbackPlugin::verifySign()通联支付RSA-SHA1 本地验证AllinpayTrait::verifyAllinpaySign()各方法在源码中的实际位置可以进一步确认支付宝src/Traits/AlipayTrait.phpverifyAlipaySign(AlipayConfig, string $contents, string $sign)回调侧由 CallbackPlugin.php 先把参数「除去sign/sign_type后按字典序组串」再验签微信src/Traits/WechatTrait.phpverifyWechatSign()另有 V2 版本verifyWechatSignV2()同文件 #L185并内置时间戳校验verifyWechatTimestamp()#L479Stripesrc/Traits/StripeTrait.php 从Stripe-Signature请求头解析t时间戳与v1签名再本地 HMAC 验证缺少webhook_secret配置会直接抛出配置异常PayPalsrc/Traits/PaypalTrait.phpverifyPaypalWebhookSign()采用 API 验证方式银联src/Traits/UnipayTrait.phpverifyUnipaySign()另有针对二维码QRA通道的verifyUnipaySignQra()#L110。关于抖音一栏从源码结构看可以更精确地描述抖音的验签实际发生在 src/Plugin/Douyin/V1/CallbackPlugin.php 的assembly()中委托给DouyinTrait::verifyDouyinTradeSign($request, $config)见 src/Traits/DouyinTrait.php即在插件内部完成而非独立的 Trait 静态入口——使用上无差别均遵循「先验签、后解析」的顺序。八、回调处理差异_request与Collection两种形态AGENTS.md 特别强调了回调处理的一个重要差异Wechat/Stripe/Paypal把_requestServerRequestInterface传入 CallbackPluginAlipay/Douyin/Unipay/Jsb/Allinpay通过getCallbackParams()获取Collection。源码印证如下微信src/Provider/Wechat.php 的callback()中getCallbackParams()的返回类型是ServerRequestInterface见 #L193-L199它把body/headers形态的数组重新包装成ServerRequest最终以[_request $request, _params $params]送入管道。原因是微信 V3 回调是 JSON 报文 头部签名Wechatpay-Signature等验签必须基于原始请求体与请求头Collection形态会丢失这些信息支付宝src/Provider/Alipay.php 的getCallbackParams()返回Collection按GET/POST方法、body/headers转发形态或全局请求三种来源解析参数。支付宝 form 回调只需键值对即可完成 RSA 组串验签因此Collection已足够。进一步从源码结构看这个二分法在仓库中还有延伸Douyin、Allinpay、Airwallex、Bestpay、Apple的callback()同样以[_request $request, ...]形式传入完整请求例如 src/Provider/Douyin.php这与它们「需要原始 body 或头部才能验签」的特性一致。对回调接口的实现者而言可以归纳出两条使用规则若网关验签依赖原始报文/请求头微信、Stripe、PayPal、抖音、Apple 等框架内部会自动构造并传递ServerRequestInterface业务侧只需保证把框架要求的请求对象交给callback()若网关验签基于表单参数组串支付宝、银联、江苏银行等参数会被归一化为Collection参与验签。两条路径最终都收敛到同一个success()响应约定验签与业务处理后按 Provider 各自的应答规范返回如支付宝返回字符串success微信 V3 返回{code:SUCCESS,message:成功}见 src/Provider/Wechat.php。九、Trait 参考与证书管理AGENTS.md 的 Trait 参考表按用途归纳了各 Provider Trait 中的方法族用途方法示例配置获取ProviderConfigTrait::getProviderConfig()、getTenant()、getRadarUrl()URL 构建get{Provider}Url()各 Trait签名验证verify{Provider}Sign()、verify{Provider}WebhookSign()证书管理CertManager::getPublicCert()、getPrivateCert()微信专用decryptWechatResource()、reloadWechatPublicCerts()其中getProviderConfig()与getTenant()的完整实现见 src/Traits/ProviderConfigTrait.php它同时是「Provider 名 租户名 → 类型化配置」的唯一入口配置缺失时抛出带 Provider 与租户名的InvalidConfigExceptionURL 构建方法签名统一为get{Provider}Url(ProviderConfig, ?Collection $payload): string如 AlipayTrait.php支付宝还额外提供 V3 专用的getAlipayV3Url()#L141微信专用方法decryptWechatResource()AES-256-GCM 解密回调 resource与reloadWechatPublicCerts()拉取并缓存微信平台证书支持按序列号指定均位于 src/Traits/WechatTrait.php 与 #L297。AGENTS.md 提示「完整方法列表见src/Traits/{Provider}Trait.php」11 个 Trait 文件均位于 src/Traits/。CertManager证书读取与缓存的实现细节src/CertManager.php 是各 Trait 验签、加签共用的证书底座几个值得注意的实现点静态缓存所有读取都经过getCachedContent()#L212-L223缓存键为{type}_{sha1($key)}避免同一请求内重复读文件、重复解析证书私钥多形态兼容getPrivateCert()#L44-L59接受三种输入——文件路径、完整 PEM 字符串以-----BEGIN PRIVATE KEY-----开头则原样使用、或裸 base64 私钥自动包裹成 RSA PEM 并折行支付宝证书 SN 提取alipayGetAppCertSn()/alipayGetRootCertSn()解析证书 issuer serialNumber 生成 SN根证书还支持多证书拼接文件PKCS12 支持getPkcs12Certs()/unipayGetPkcs12Certs()#L135-L159用密码读取.pfx/.p12证书包供银联、翼支付等 PKCS12 体系的 Provider 共用读取失败抛出「配置异常: 读取证书失败确认参数是否正确」微信按租户隔离的证书缓存$wechatCerts[$tenant][$serialNo] $cert#L189-L210回调验签时根据Wechatpay-Serial头部快速定位平台证书多租户互不干扰缓存随Pay::clear()一并清理见 Pay.php 中的CertManager::clearCache()调用。十、上手路径从入口到管道的一次完整走查把 AGENTS.md 的约定串起来一次典型的支付调用链路如下每一环都可在仓库中定位Pay::config($config)—— 数组配置被 src/Config.php 转为类型化 Config 对象11 个 ServiceProvider 完成注册src/Pay.phpPay::alipay()-web($order)——__callStatic取出AlipayProvider__call(web)映射到WebShortcutsrc/Provider/Alipay.phpShortcut 声明插件链Artful 逐个执行StartPlugin → PayPlugin → 签名 → Radar → Response → ParserPluginsrc/Shortcut/Alipay/WebShortcut.php全程以 Rocket 传递数据AddRadarPlugin把调试信息挂在结果上回调侧Pay::alipay()-callback()先派发CallbackReceived事件再由CallbackPlugin完成验签src/Provider/Alipay.php、src/Plugin/Alipay/CallbackPlugin.php开发完成后按第五节的composer cs-fix composer analyse composer test三项检查收尾测试用例分布在 tests/ 下与 src 同构的目录中如 tests/Provider/AlipayTest.php、tests/Plugin/Alipay/CallbackPluginTest.php。最后补充一点适用前提本文基于当前仓库yansongda/artful ~1.2.0、yansongda/supports ~4.1.0、PHP 8.2的实际代码结构撰写Rocket、Artful 容器等底层实现位于外部依赖包中仓库内只体现其调用面。若需要逐行核对建议从 AGENTS.md 列出的符号出发按本文给出的文件路径在仓库内直接查看。赞分享后端金融科技【免费下载链接】pay可能是我用过的最优雅的 Alipay/WeChat/Unipay/江苏银行 的支付 SDK 扩展包了项目地址https://gitcode.com/yansongda/pay点击查看免费下载相关推荐yansongda/pay 支付 SDK 架构与扩展开发指南插件管道、多 Provider 统一契约与回调验签全解析yansongda/pay 支付 SDK 架构与扩展开发指南插件管道、多 Provider 统一契约与回调验签全解析 本篇技术指南以仓库根目录下的 AGENT金融科技后端yansongda/pay 支付宝回调接收指南异步通知验签与 ISV 应用网关验证yansongda/pay 支付宝回调接收指南异步通知验签与 ISV 应用网关验证 本指南聚焦 yansongda/pay 中支付宝Alipay回调的完整金融科技后端Yansongda Pay 微信确认回调指南success() 方法与响应插件体系全解析Yansongda Pay 微信确认回调指南success 方法与响应插件体系全解析 本指南以 Yansongda Pay 微信支付模块的确认回调能力为核金融科技后端上一篇利用支持向量数据描述SVDD进行异常检测的高效工具下一篇为什么选择Forge5大理由让你的开发效率翻倍创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考