{"id":19506316,"url":"https://github.com/thenorthmemory/whats-alipay","last_synced_at":"2026-03-02T17:36:39.164Z","repository":{"id":57397698,"uuid":"298473184","full_name":"TheNorthMemory/whats-alipay","owner":"TheNorthMemory","description":"支付宝 Alipay OpenAPI SDK","archived":false,"fork":false,"pushed_at":"2024-02-25T09:51:11.000Z","size":251,"stargazers_count":15,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-18T06:24:46.558Z","etag":null,"topics":["aes-cbc","alipay","alipay-openapi","axios-ecosystem","chainable-openapi","locale-date-time","rsa-sha1","rsa-sha256"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TheNorthMemory.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-25T05:08:44.000Z","updated_at":"2025-04-09T10:16:54.000Z","dependencies_parsed_at":"2024-10-04T08:57:46.692Z","dependency_job_id":"a5a726b3-6b5b-41e8-bb40-3d34dd11c529","html_url":"https://github.com/TheNorthMemory/whats-alipay","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNorthMemory%2Fwhats-alipay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNorthMemory%2Fwhats-alipay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNorthMemory%2Fwhats-alipay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheNorthMemory%2Fwhats-alipay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheNorthMemory","download_url":"https://codeload.github.com/TheNorthMemory/whats-alipay/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250922127,"owners_count":21508279,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes-cbc","alipay","alipay-openapi","axios-ecosystem","chainable-openapi","locale-date-time","rsa-sha1","rsa-sha256"],"created_at":"2024-11-10T22:36:38.818Z","updated_at":"2026-03-02T17:36:39.087Z","avatar_url":"https://github.com/TheNorthMemory.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 支付宝 OpenAPI SDK\n\nYet Another Alipay OpenAPI Smart Development Kit\n\n[![GitHub actions](https://github.com/TheNorthMemory/whats-alipay/workflows/ci/badge.svg)](https://github.com/TheNorthMemory/whats-alipay/actions)\n[![GitHub issues](https://img.shields.io/github/issues/TheNorthMemory/whats-alipay)](https://github.com/TheNorthMemory/whats-alipay/issues)\n[![GitHub release](https://img.shields.io/node/v/whats-alipay)](https://github.com/TheNorthMemory/whats-alipay/releases)\n[![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/whats-alipay?label=snyk.io)](https://snyk.io/advisor/npm-package/whats-alipay)\n[![NPM module version](https://img.shields.io/npm/v/whats-alipay)](https://www.npmjs.com/package/whats-alipay)\n[![NPM module downloads per month](https://img.shields.io/npm/dm/whats-alipay)](https://www.npmjs.com/package/whats-alipay)\n[![NPM module license](https://img.shields.io/npm/l/whats-alipay?color=blue)](https://www.npmjs.com/package/whats-alipay)\n\n## 主要功能\n\n- OOP风格化的，可弹性扩容的，支付宝OpenAPI SDK\n- 低依赖，目前仅依赖 `Axios`\n- 使用Node原生代码实现支付宝OpenAPI的AES(`aes-128-cbc`)加/解密功能\n- 使用Node原生代码实现支付宝OpenAPI的RSA(`sha1WithRSAEncryption`)及RSA2(`sha256WithRSAEncryption`)签名、验签功能\n- 异步通知消息验签\n- 命令行网关交互工具\n\n## SDK约定\n\n- 使用 `method({请求参数}[, {公共请求参数}[, {特殊头参数}]])` 作为HTTP接口驱动，释义如下：\n  - 接口定义中`公共请求参数`的 `method`，即作为本SDK标准方法链，弹性扩容，示例使用方法如下，详细审查见文末\n  - 接口定义中的`请求参数`，以 `Object` 对象作为第一个入参\n  - 接口定义中的`公共请求参数`，以 `Object` 对象作为第二个入参\n  - 特别的，对于图片/视频上传，需要定义 `multipart/form-data` 头信息，以 `Object` 对象作为第三个入参，见如下示例\n  - 特别的，对于页面表单提交型，即所谓的page类接口，第三参数须定义为 `Formatter.page`，返回结果可直接作为页面/接口输出，说明用法见如下示例\n- 请求数据签名以及返回数据验签均自动完成，开发者仅需关注业务代码即可；特别地，对于验签结果有依赖的情况，可以从返回值的头部获取：\n  - `headers[x-alipay-verified]` 为验签结果，值可能为 `ok`, `undefined`\n  - `headers[x-alipay-signature]` 为源返回数据签名值，值可能为 `undefined`\n  - `headers[x-alipay-responder]` 为源返回值字段名转译，值可能为 `undefined`, `error` 或者实际请求的 `method` 值\n\n## 使用手册\n\n### whatsCli 命令行工具\n\n以命令行的形式，与OpenAPI网关交互，play the OpenAPI requests over command line.\n\n\u003cdetails\u003e\n  \u003csummary\u003e$ \u003cb\u003e./node_modules/.bin/whatsCli -h\u003c/b\u003e (click to toggle display)\u003c/summary\u003e\n\n```\nUsage: cli.js [options]\n\nOptions:\n  -k, --privateKey  The privateKey pem file path                                                              [required]\n  -p, --publicCert  The publicCert pem file path                                                              [required]\n  -m, --method      The method, eg: alipay.trade.query                                                        [required]\n  -s, --search      The search parameters, eg: search.app_id=2088                                             [required]\n  -b, --biz         The biz_content, eg: biz.out_trade_no=abcd1234                                            [required]\n  -d, --log         Turn on the request trace log                                                              [boolean]\n  -u, --baseURL     The OpenAPI gateway, eg: https://openapi.alipaydev.com/gateway.do\n  -h, --help        Show help                                                                                  [boolean]\n  -V, --version     Show version number                                                                        [boolean]\n\nExamples:\n  cli.js -k merchant.key -p alipay.pub -m alipay.trade.pay      The Face2Face barCode scenario\n  -s.app_id=2088 -b.subject=HelloKitty\n  -b.out_trade_no=Kitty0001 -b.scene=bar_code\n  -b.total_amount=0.01 -b.auth_code=\n  cli.js -k merchant.key -p alipay.pub -m alipay.trade.refund   The trade refund scenario\n  -s.app_id=2088 -b.refund_amount=0.01 -b.refund_currency=CNY\n  -b.out_trade_no=Kitty0001\n  cli.js -d -u https://openapi.alipaydev.com/gateway.do -k      The trade query scenario over the sandbox environment\n  merchant.key -p alipay.pub -m alipay.trade.query              with trace logging\n  -s.app_id=2088 -b.out_trade_no=Kitty0001\n```\n\u003c/details\u003e\n\n### certHelper 命令行工具\n\n\u003cdetails\u003e\n  \u003csummary\u003e$ \u003cb\u003e./node_modules/.bin/certHelper -h\u003c/b\u003e (click to toggle display)\u003c/summary\u003e\n\n```\nUsage: cert.js [command] [options]\n\nCommands:\n  cert.js SN       Get the certificatie(s) `SN`                 [default]\n  cert.js extract  Extract the chained certificate(s)\n\nOptions:\n  -f, --file     The certificate(s) file path                   [required]\n  -p, --pattern  The algo prefix or suffix, dot(.) for all\n  -h, --help     Show help                                      [boolean]\n  -V, --version  Show version number                            [boolean]\n\nExamples:\n  cert.js SN -f alipayRootCert.crt                              get the `sha256`(default) certificate `SN`\n  cert.js SN -f alipayRootCert.crt -p ec                        get the signatureAlgorithm whose contains `ec` words\n                                                                certificate `SN`\n  cert.js SN -f alipayRootCert.crt -p .                         get all chained certificate(s) `SN`\n  cert.js extract -f alipayRootCert.crt                         extract the `sha256`(default) certificate\n  cert.js extract -f alipayRootCert.crt -p sha1                 extract the `sha1` certificate\n  cert.js extract -f alipayRootCert.crt -p .                    extract all chained certificate(s)\n  cert.js extract -f alipayRootCert.crt -p sha1 | openssl x509  piped openssl x509 command\n  -noout -text\n  cert.js extract -f alipayRootCert.crt -p sha1 \u003e tmp.pem       save to a file\n```\n\u003c/details\u003e\n\n此命令行工具，主要是用来计算并获取 **公钥证书模式** 所需的 应用公钥证书SN(*app_cert_sn*)及 支付宝公钥证书SN(*alipay_root_cert_sn*)。\n\n\u003e ./bin/cert.js SN -f /path/your/app_cert.crt\n\n\u003e ./bin/cert.js SN -f /path/your/alipay_root_cert.crt -p RSAEncryption\n\n而`SN` 命令是 `Helpers.SN` 的语法糖，可从如下[API文档](#Helpers.SN)查看更详细用法\n\n### 初始化\n\n```javascript\nconst { Alipay, Rsa } = require('whats-alipay');\n\n//应用app_id\nconst app_id = '2014072300007148';\n\n//商户RSA私钥，入参是'从官方工具获取到的BASE64字符串'\nconst privateKey = Rsa.fromPkcs1('MIIEpAIBAAKCAQEApdXuft3as2x...');\n// 以上是下列代码的语法糖，格式为 'private.pkcs1://' + '从官方工具获取到的字符串'\n// const privateKey = Rsa.from('private.pkcs1://MIIEpAIBAAKCAQEApdXuft3as2x...');\n// Node10仅支持以下方式，须保证`private_key.pem`为完整X509格式\n// const privateKey = require('fs').readFileSync('/your/openapi/private_key.pem');\n\n//支付宝RSA公钥，入参是'从官方工具获取到的BASE64字符串'\nconst publicKey = Rsa.fromSpki('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg...');\n// 以上是下列代码的语法糖，格式为 'public.spki://' + '从官方工具获取到的字符串'\n// const publicKey = Rsa.from('public.spki://MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg...');\n// Node10仅支持以下方式，须保证`public_key.pem`为完整X509格式\n// const publicKey = require('fs').readFileSync('/the/alipay/public_key.pem');\n\nconst whats = new Alipay({ privateKey, publicKey, params: { app_id, } });\n```\n\n#### 统一收单线下交易查询\n\n```javascript\nwhats\n  .alipay.trade.query({out_trade_no})\n  .then(({headers,data}) =\u003e ({headers,data}))\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e$ \u003cb\u003econsole.log sample result\u003c/b\u003e (click to toggle display)\u003c/summary\u003e\n\n```javascript\n{\n  headers: {\n    server: 'Tengine/2.1.0',\n    date: 'Fri, 25 Sep 2020 03:27:32 GMT',\n    'content-type': 'text/html;charset=utf-8',\n    'content-length': '829',\n    connection: 'close',\n    'set-cookie': [\n      'JSESSIONID=6FF6F65BB1EC785992117C95EA7C27BB; Path=/; HttpOnly',\n      'spanner=ubOmkyHGnYLtouOsffShT4n70pJgSji6Xt2T4qEYgj0=;path=/;secure;'\n    ],\n    via: 'spanner-internet-5396.sa127[200]',\n    'x-alipay-responder': 'alipay.trade.query',\n    'x-alipay-signature': 'gALtsKSWEWRG4wSx8==',\n    'x-alipay-verified': 'ok'\n  },\n  data: {\n    code: '10000',\n    msg: 'Success',\n    buyer_logon_id: '134******38',\n    buyer_pay_amount: '183.00',\n    buyer_user_id: '2088101117955611',\n    fund_bill_list: [ { amount: '183.00', fund_channel: 'ALIPAYACCOUNT' } ],\n    invoice_amount: '183.00',\n    out_trade_no: '6823789339978248',\n    point_amount: '0.00',\n    receipt_amount: '183.00',\n    send_pay_date: '2020-09-19 17:00:28',\n    total_amount: '183.00',\n    trade_no: '2013112011001004330000121536',\n    trade_status: 'TRADE_SUCCESS'\n  }\n}\n```\n\u003c/details\u003e\n\n#### 统一收单交易支付接口\n\n```javascript\nwhats\n  .alipay.trade.pay({\n    out_trade_no,\n    scene,\n    auth_code,\n    product_code,\n    subject,\n    total_amount,\n  })\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 统一收单线下交易预创建\n\n```javascript\nwhats\n  .alipay.trade.precreate({\n    out_trade_no,\n    subject,\n    total_amount,\n  })\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 手机网站支付接口2.0\n\n```javascript\nwhats\n  .alipay.trade.wap.pay({\n    out_trade_no,\n    subject,\n    total_amount,\n    product_code,\n    quit_url,\n  }, {}, Formatter.page)\n  .then(res =\u003e res)\n  .then(console.log)\n```\n\n- 注: 特别地 `res` 结构做了优化，直接支持 `literal`(独立服务模式: `${res}`) 或者 `JSON.stringify` (二次接口模式: `JSON.stringify(res)`)\n\n#### 统一收单下单并支付页面接口\n\n```javascript\nwhats\n  .alipay.trade.page.pay({\n    out_trade_no,\n    subject,\n    total_amount,\n    product_code,\n  }, {return_url}, Formatter.page)\n  .then(res =\u003e res)\n  .then(console.log)\n```\n\n- 注: 特别地 `res` 结构做了优化，直接支持 `literal`(独立服务模式: `${res}`) 或者 `JSON.stringify` (二次接口模式: `JSON.stringify(res)`)\n\n#### 订单咨询服务\n\n```javascript\nwhats\n  .alipay.trade.advance.consult({/*文档上的参数就好*/})\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 口碑营销活动列表查询\n\n```javascript\nwhats\n  .koubei.marketing.campaign.activity.batchquery(/*文档上的参数就好*/})\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 支付API \u003e 图片上传\n\n```javascript\nconst { Multipart } = require('whats-alipay');\nconst form = new Multipart();\nform.append(\n  'image_content',\n  require('fs').readFileSync('/path/for/uploading.jpg'),\n  'uploading.jpg'\n);\n\nwhats\n  .ant.merchant.expand.indirect.image.upload(\n    form.getBuffer(),\n    {image_type: 'jpg'},\n    {...form.getHeaders()}\n  )\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 店铺API \u003e 上传门店照片和视频接口\n\n```javascript\nconst { Multipart } = require('whats-alipay');\nconst form = new Multipart();\nform.append(\n  'image_content',\n  require('fs').readFileSync('/path/for/uploading.jpg'),\n  'uploading.jpg'\n);\n\nwhats\n  .alipay.offline.material.image.upload(\n    form.getBuffer(),\n    {image_type: 'jpg', image_name: 'uploading.jpg'},\n    {...form.getHeaders()}\n  )\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 芝麻信用API \u003e 授权查询\n\n```javascript\nwhats\n  .zhima.auth.info.authquery(/*文档上的参数就好*/})\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 车主服务API \u003e 车辆驶入接口\n\n```javascript\nwhats\n  .alipay.eco.mycar.parking.enterinfo.sync(/*文档上的参数就好*/})\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n#### 资金API \u003e 单笔转账接口\n\n```javascript\nwhats\n  .alipay.fund.trans.uni.transfer(/*文档上的参数就好*/})\n  .then(({data}) =\u003e data)\n  .catch(({response: {data}}) =\u003e data)\n  .then(console.log)\n```\n\n## 何以弹性扩容\n\n`whats` 上绑定多少 `method`，即扩容至多少，以上示例打印如下：\n\n\u003cdetails\u003e\n  \u003csummary\u003e$ \u003cb\u003econsole.info sample result\u003c/b\u003e (click to toggle display)\u003c/summary\u003e\n\n```javascript\nconsole.info(whats)\n\n[Function (anonymous)] {\n  ant: [Function: ant] {\n    merchant: [Function: ant.merchant] {\n      expand: [Function: ant.merchant.expand] {\n        indirect: [Function: ant.merchant.expand.indirect] {\n          image: [Function: ant.merchant.expand.indirect.image] {\n            upload: [Function: ant.merchant.expand.indirect.image.upload]\n          }\n        }\n      }\n    }\n  },\n  alipay: [Function: alipay] {\n    trade: [Function: alipay.trade] {\n      query: [Function: alipay.trade.query],\n      precreate: [Function: alipay.trade.precreate],\n      advance: [Function: alipay.trade.advance] {\n        consult: [Function: alipay.trade.advance.consult]\n      },\n      page: [Function: alipay.trade.page] {\n        pay: [Function: alipay.trade.page.pay]\n      },\n      wap: [Function: alipay.trade.wap] {\n        pay: [Function: alipay.trade.wap.pay]\n      }\n    },\n    fund: [Function: alipay.fund] {\n      trans: [Function: alipay.fund.trans] {\n        uni: [Function: alipay.fund.trans.uni] {\n          transfer: [Function: alipay.fund.trans.uni.transfer]\n        }\n      }\n    },\n    eco: [Function: alipay.eco] {\n      mycar: [Function: alipay.eco.mycar] {\n        parking: [Function: alipay.eco.mycar.parking] {\n          enterinfo: [Function: alipay.eco.mycar.parking.enterinfo] {\n            sync: [Function: alipay.eco.mycar.parking.enterinfo.sync]\n          }\n        }\n      }\n    },\n    offline: [Function: alipay.offline] {\n      material: [Function: alipay.offline.material] {\n        image: [Function: alipay.offline.material.image] {\n          upload: [Function: alipay.offline.material.image.upload]\n        }\n      }\n    }\n  },\n  zhima: [Function: zhima] {\n    auth: [Function: zhima.auth] {\n      info: [Function: zhima.auth.info] {\n        authquery: [Function: zhima.auth.info.authquery]\n      }\n    }\n  },\n  koubei: [Function: koubei] {\n    marketing: [Function: koubei.marketing] {\n      campaign: [Function: koubei.marketing.campaign] {\n        activity: [Function: koubei.marketing.campaign.activity] {\n          batchquery: [Function: koubei.marketing.campaign.activity.batchquery]\n        }\n      }\n    }\n  }\n}\n```\n\u003c/details\u003e\n\n## 异步通知消息验签\n\n通知消息验签，依赖相关 `webserver` 提供的 `POST` 数据解析能力，以下函数在 `http.createServer` 上做过验证，仅供参考。\n\n```javascript\nfunction notificationValidator(things, publicCert, withoutSignType = true) {\n  const {groups: {sign}} = (typeof things === 'string' ? things : '').match(/\\bsign=(?\u003csign\u003e[^\u0026]+)/) || {groups: {}}\n  const source = [...new URLSearchParams(things)].reduce((des, [key, value]) =\u003e (des[key] = value, des), {})\n  const signType = source['sign_type']\n  const signature = (source.sign || '').replace(/ /g, '+').replace(/_/g, '/')\n  // The signature with `sign_type` is only for the notifications whose come from `alipay.open.public.*` APIs.\n  if (withoutSignType) {\n      delete source['sign_type']\n  }\n\n  return Rsa.verify(Formatter.queryStringLike(Formatter.ksort(source)), sign || signature, publicCert, signType)\n}\n```\n\n## 单元测试\n\n`npm install \u0026\u0026 npm test`\n\nTo disable `nock` and request with the real gateway, just `NOCK_OFF=true npm test`\n\n## 链接\n\n- [变更历史](CHANGELOG.md)\n## 许可证\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthenorthmemory%2Fwhats-alipay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthenorthmemory%2Fwhats-alipay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthenorthmemory%2Fwhats-alipay/lists"}