# epaygateway **Repository Path**: rootxss/epaygateway ## Basic Information - **Project Name**: epaygateway - **Description**: 一个将支付宝openai支付接口转换为易支付兼容接口的无状态型网关 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-28 - **Last Updated**: 2026-07-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # xiling-epay-adapter 轻量、无状态的易支付(EPay)到支付宝 OpenAPI 协议适配服务。用于 New API 仅支持 EPay 协议、实际收款渠道为支付宝官方开放平台的场景。 ## 架构 ```text 用户 -> New API -> EPay -> xiling-epay-adapter -> 支付宝 OpenAPI -> 支付宝 ^ | |---- 支付成功通知 --------| ``` 服务不使用数据库、Redis 或本地持久化,不保存订单、用户和支付状态。订单事实与支付状态以支付宝查询结果为准。 ## 功能 - `POST /submit.php`:校验 EPay 请求,调用 `alipay.trade.page.pay` 并 302 跳转。 - `POST /notify.php`:验证支付宝 RSA2 签名,查询交易交叉校验后通知 New API。 - `POST /query.php`:调用 `alipay.trade.query` 返回实时状态。 - `GET /health`:健康检查。 - 支持传统 Node.js 22 和 EdgeOne Cloud Functions。 ## 安装与本地运行 ```bash npm install cp .env.example .env npm run dev ``` 生产构建与运行: ```bash npm run build npm start ``` 本地启动依赖完整环境变量。私钥可填写单行 `\\n` 转义文本,也可填写真实 PEM 多行内容。 ## 环境变量 | 变量 | 必填 | 说明 | | --- | --- | --- | | `NODE_ENV` | 否 | 运行环境,生产设为 `production` | | `PORT` | 传统 Node 否 | 默认 `3000`,EdgeOne 不使用 | | `LOG_LEVEL` | 否 | Pino 日志级别,默认 `info` | | `ALIPAY_APP_ID` | 是 | 支付宝开放平台应用 ID | | `ALIPAY_PRIVATE_KEY` | 是 | 应用 RSA2 私钥,不提交仓库 | | `ALIPAY_PUBLIC_KEY` | 是 | 支付宝公钥,不是应用公钥 | | `ALIPAY_GATEWAY` | 否 | 默认生产网关;沙箱使用沙箱网关 | | `ADAPTER_NOTIFY_URL` | 是 | 本服务公开的 `/notify.php` 完整 HTTPS 地址 | | `NEW_API_NOTIFY_URL` | 是 | 支付成功后通知 New API 的固定地址 | | `EPAY_PID` | 是 | New API 配置的商户 ID | | `EPAY_KEY` | 生产必填 | EPay MD5 签名密钥;留空时不校验,仅供联调 | | `CORS_ORIGINS` | 否 | 逗号分隔浏览器来源;服务间调用无需配置 | ## 支付宝配置 1. 在支付宝开放平台创建网页支付应用并签约电脑网站支付。 2. 配置 RSA2 应用公钥,取得支付宝公钥。 3. 将应用 ID、应用私钥、支付宝公钥设置为环境变量。 4. 将 `ADAPTER_NOTIFY_URL` 设置为部署域名,例如 `https://pay.example.com/notify.php`。 5. 确保支付宝能够通过公网 HTTPS 访问该地址。 `ALIPAY_PUBLIC_KEY` 必须是支付宝公钥。使用应用公钥会导致通知验签失败。 ## New API 配置 在 New API 易支付渠道中配置: - 支付接口地址:部署后的服务域名。 - 商户 ID:与 `EPAY_PID` 一致。 - 商户密钥:与 `EPAY_KEY` 一致。 - 支付类型:`alipay`。 `NEW_API_NOTIFY_URL` 是本服务向 New API 转发成功结果的固定地址。New API 应按 `out_trade_no` 实现幂等,因为支付宝通知可能重试。 ## EdgeOne 部署 项目已提供 EdgeOne Express 框架入口: ```text cloud-functions/express/[[default]].ts ``` 该入口直接导出 Express 实例,不监听端口。将仓库推送到 EdgeOne Pages/Makers 项目后,在项目设置中配置以下生产环境变量: ```text NODE_ENV=production LOG_LEVEL=info ALIPAY_APP_ID=... ALIPAY_PRIVATE_KEY=... ALIPAY_PUBLIC_KEY=... ALIPAY_GATEWAY=https://openapi.alipay.com/gateway.do ADAPTER_NOTIFY_URL=https://你的域名/notify.php NEW_API_NOTIFY_URL=https://New-API域名/回调路径 EPAY_PID=xiling EPAY_KEY=... ``` 不要在仓库中创建真实 `.env`。EdgeOne 构建和运行时会通过 `process.env` 注入项目环境变量。部署后先访问 `/health`,再使用支付宝沙箱完成创建、异步通知和查询闭环。 ## 接口 ### 创建支付 `POST /submit.php` 支持 `application/json` 和 `application/x-www-form-urlencoded`: ```json { "pid": "xiling", "type": "alipay", "out_trade_no": "202607280001", "name": "API余额充值", "money": "100.00", "notify_url": "https://new-api.example.com/notify", "return_url": "https://new-api.example.com/pay/return", "sign_type": "MD5", "sign": "易支付签名" } ``` 成功返回 `302`,`Location` 为支付宝收银台。请求中的 `notify_url` 不会直接传给支付宝,支付宝异步通知固定发往 `ADAPTER_NOTIFY_URL`。 ### 支付宝异步通知 `POST /notify.php` 接收支付宝表单通知。仅当以下条件同时满足才通知 New API: - RSA2 签名有效,`app_id` 匹配。 - 状态为 `TRADE_SUCCESS` 或 `TRADE_FINISHED`。 - 主动查询结果中的订单号、支付宝交易号、状态和金额均匹配。 处理成功响应纯文本 `success`;失败响应 `fail`,支付宝将按其策略重试。 转发 New API 的 JSON: ```json { "trade_no": "支付宝交易号", "out_trade_no": "商户订单号", "amount": "100.00", "status": "TRADE_SUCCESS" } ``` ### 查询订单 `POST /query.php` ```json { "pid": "xiling", "out_trade_no": "202607280001", "sign_type": "MD5", "sign": "易支付签名" } ``` 返回实时支付宝状态、是否已支付、金额及支付宝响应代码。 ## EPay 签名 除 `sign`、`sign_type` 和空值外,参数按字段名升序排列为 `key=value`,使用 `&` 拼接,末尾直接追加 `EPAY_KEY`,计算 MD5 小写十六进制摘要。生产环境必须配置 `EPAY_KEY`。 ## 安全说明 - 请求仅接受明确字段和标量字符串,拒绝未知字段、数组、对象及参数污染。 - 请求体上限为 32 KB,表单参数最多 32 个。 - 金额只接受 `0.01` 至 `99999999.99`,最多两位小数。 - 支付宝通知必须通过 RSA2 验签和主动查询交叉校验。 - New API 通知地址来自受控环境变量,不接受请求参数作为出站目标。 - Pino 日志只记录请求 ID、方法、路径、耗时和状态,不记录请求体、签名、令牌或密钥。 - `.env`、构建产物和依赖目录已排除在版本控制之外。 - 建议在 EdgeOne 配置 WAF、请求频率限制和 HTTPS 自定义域名。