Yet Another Alipay OpenAPI Smart Development Kit
Axiosaes-128-cbc)加/解密功能sha1WithRSAEncryption)及RSA2(sha256WithRSAEncryption)签名、验签功能method({请求参数}[, {公共请求参数}[, {特殊头参数}]]) 作为HTTP接口驱动,释义如下:
公共请求参数的 method,即作为本SDK标准方法链,弹性扩容,示例使用方法如下,详细审查见文末请求参数,以 Object 对象作为第一个入参公共请求参数,以 Object 对象作为第二个入参multipart/form-data 头信息,以 Object 对象作为第三个入参,见如下示例Formatter.page,返回结果可直接作为页面/接口输出,说明用法见如下示例headers[x-alipay-verified] 为验签结果,值可能为 ok, undefinedheaders[x-alipay-signature] 为源返回数据签名值,值可能为 undefinedheaders[x-alipay-responder] 为源返回值字段名转译,值可能为 undefined, error 或者实际请求的 method 值以命令行的形式,与OpenAPI网关交互,play the OpenAPI requests over command line.
此命令行工具,主要是用来计算并获取 公钥证书模式 所需的 应用公钥证书SN(app_cert_sn)及 支付宝公钥证书SN(alipay_root_cert_sn)。
./bin/cert.js SN -f /path/your/app_cert.crt
./bin/cert.js SN -f /path/your/alipay_root_cert.crt -p RSAEncryption
而SN 命令是 Helpers.SN 的语法糖,可从如下API文档查看更详细用法
const {readFileSync} = require('fs')
const {Alipay} = require('whats-alipay')
//应用app_id
const app_id = '2014072300007148'
//商户私钥证书,须完整格式,同时支持 `PKCS#1` `PKCS#8` 格式
const privateKey = readFileSync('/your/openapi/private_key.pem')
//支付宝公钥证书,须完整格式,同时支持 `PKCS#1` `PKCS#8` 格式
const publicCert = readFileSync('/the/alipay/public_cert.pem')
const whats = new Alipay({ privateKey, publicCert, params: { app_id, } })
证书完整格式 是指: 包含
-----BEGIN及-----END,内容是列宽64的base64-encoded字符串,可直接用openssl命令行工具进行验证格式。
whats
.alipay.trade.query({out_trade_no})
.then(({headers,data}) => ({headers,data}))
.catch(({response: {data}}) => data)
.then(console.log)
whats
.alipay.trade.pay({
out_trade_no,
scene,
auth_code,
product_code,
subject,
total_amount,
})
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
whats
.alipay.trade.precreate({
out_trade_no,
subject,
total_amount,
})
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
whats
.alipay.trade.wap.pay({
out_trade_no,
subject,
total_amount,
product_code,
quit_url,
}, {}, Formatter.page)
.then(res => res)
.then(console.log)
res 结构做了优化,直接支持 literal(独立服务模式: ${res}) 或者 JSON.stringify (二次接口模式: JSON.stringify(res))whats
.alipay.trade.page.pay({
out_trade_no,
subject,
total_amount,
product_code,
}, {return_url}, Formatter.page)
.then(res => res)
.then(console.log)
res 结构做了优化,直接支持 literal(独立服务模式: ${res}) 或者 JSON.stringify (二次接口模式: JSON.stringify(res))whats
.alipay.trade.advance.consult({/*文档上的参数就好*/})
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
whats
.koubei.marketing.campaign.activity.batchquery(/*文档上的参数就好*/})
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
const {Form} = require('whats-alipay')
const payload = new Form()
payload.append('image_content', require('fs').readFileSync('/path/for/uploading.jpg'), 'uploading.jpg')
whats
.ant.merchant.expand.indirect.image.upload(
payload.getBuffer(),
{image_type: 'jpg'},
{...payload.getHeaders()}
)
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
const {Form} = require('whats-alipay')
const payload = new Form()
payload.append('image_content', require('fs').readFileSync('/path/for/uploading.jpg'), 'uploading.jpg')
whats
.alipay.offline.material.image.upload(
payload.getBuffer(),
{image_type: 'jpg', image_name: 'uploading.jpg'},
{...payload.getHeaders()}
)
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
whats
.zhima.auth.info.authquery(/*文档上的参数就好*/})
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
whats
.alipay.eco.mycar.parking.enterinfo.sync(/*文档上的参数就好*/})
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
whats
.alipay.fund.trans.uni.transfer(/*文档上的参数就好*/})
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
whats 上绑定多少 method,即扩容至多少,以上示例打印如下:
Alipay 类实例链如下:
通知消息验签,依赖相关 webserver 提供的 POST 数据解析能力,以下函数在 http.createServer 上做过验证,仅供参考。
function notificationValidator(things, publicCert, withoutSignType = true) {
const {groups: {sign}} = (typeof things === 'string' ? things : '').match(/\bsign=(?<sign>[^&]+)/) || {groups: {}}
const source = [...new URLSearchParams(things)].reduce((des, [key, value]) => (des[key] = value, des), {})
const signType = source['sign_type']
const signature = (source.sign || '').replace(/ /g, '+').replace(/_/g, '/')
// The signature with `sign_type` is only for the notifications whose come from `alipay.open.public.*` APIs.
if (withoutSignType) {
delete source['sign_type']
}
return Rsa.verify(Formatter.queryStringLike(Formatter.ksort(source)), sign || signature, publicCert, signType)
}
Manually generated by for f in lib/*.js; do ./node_modules/.bin/jsdoc2md -d 3 $f; done
Aes - Advanced Encryption Standard
Kind: global class
To prevent new operation, works only as static class.
Kind: static property of Aes
Properties
| Name | Type | Description |
|---|---|---|
| hex | string |
Alias of hex string |
Kind: static property of Aes
Properties
| Name | Type | Description |
|---|---|---|
| utf8 | string |
Alias of utf8 string |
Kind: static property of Aes
Properties
| Name | Type | Description |
|---|---|---|
| base64 | string |
Alias of base64 string |
Kind: static property of Aes
Properties
| Name | Type | Description |
|---|---|---|
| BLOCK_SIZE | integer |
The aes block size |
Kind: static property of Aes
Properties
| Name | Type | Description |
|---|---|---|
| MODE_CBC | string |
The cbc mode string |
arrayDetect the algo with given cipherkey length and mode.
Kind: static method of Aes
Returns: array - - [algorithm, key] pairs
| Param | Type | Description |
|---|---|---|
| cipherkey | string |
Based64 encoded key string. |
| [mode] | string |
The mode string, default is this.MODE_CBC. |
AesCbc
Kind: global class
stringstringstringEncrypts plaintext.
Kind: static method of AesCbc
Returns: string - Base64-encoded ciphertext.
| Param | Type | Description |
|---|---|---|
| plaintext | string |
Text to encode. |
| cipherkey | string |
The secret key, base64 encoded string. |
| [iv] | string | buffer |
The initialization vector, 16 bytes string or buffer, default is 0{16} buffer. |
stringDecrypts ciphertext.
Kind: static method of AesCbc
Returns: string - Utf-8 plaintext.
| Param | Type | Description |
|---|---|---|
| ciphertext | string |
Base64-encoded ciphertext. |
| cipherkey | string |
The secret key, base64 encoded string. |
| [iv] | string | buffer |
The initialization vector, 16 bytes string or buffer, default is 0{16} buffer. |
Whats Alipay Core
objectWhats Alipay Core
Kind: global class
ProxyfunctionTo compose the method chain.
| Param | Type | Description |
|---|---|---|
| config | object |
The configuration passed in Decorator. |
| config.privateKey | string | Buffer |
The merchant’s RSA’s private key. |
| config.publicCert | string | Buffer |
The alipay’s RSA’s pubkey or certificate(recommend). |
| [config.params] | object |
The general parameters. |
| [config.params.app_id] | string | number |
The merchant’s application id. |
| [config.params.app_auth_token] | string |
The merchant’s authorization token. |
| [config.params.app_cert_sn] | string |
The merchant’s RSA’s certificate SN. |
| [config.params.alipay_root_cert_sn] | string |
The alipay’s RSA’s certificate SN. |
Kind: static property of Alipay
Properties
| Name | Type | Description |
|---|---|---|
| handler | object |
A Getter handler object |
ProxyCompose a named function with prefix and suffix whose joined by a dot(.)
Kind: static method of Alipay
Returns: Proxy - - With a special Getter Function.
| Param | Type | Description |
|---|---|---|
| [prefix] | string |
The prefix string. |
| [suffix] | string |
The suffix string. |
functionChain the input method
Kind: static method of Alipay
Returns: function - - Named as given method function
| Param | Type | Description |
|---|---|---|
| method | string |
The naming string. |
objectKind: global function
Returns: object - - An object or object’s property
| Param | Type | Description |
|---|---|---|
| target | object |
The object |
| property | string |
The property |
Properties
| Name | Type | Description |
|---|---|---|
| get | function |
Object’s getter handler |
Decorate the Axios instance
Kind: global class
Decorate factory
| Param | Type | Description |
|---|---|---|
| config | object |
The configuration. |
| config.privateKey | string | Buffer |
The merchant’s RSA’s private key. |
| config.publicCert | string | Buffer |
The alipay’s RSA’s pubkey or certificate(recommend). |
| [config.params] | object |
The general parameters. |
| [config.params.app_id] | string | number |
The merchant’s application id. |
| [config.params.app_auth_token] | string |
The merchant’s authorization token. |
| [config.params.app_cert_sn] | string |
The merchant’s RSA’s certificate SN. |
| [config.params.alipay_root_cert_sn] | string |
The alipay’s RSA’s certificate SN. |
Kind: static property of Decorator
Properties
| Name | Type | Description |
|---|---|---|
| client | AxiosInstance |
The Axios instance. |
Kind: static property of Decorator
Properties
| Name | Type | Description |
|---|---|---|
| privateKey | buffer |
Buffer of the private key certificate. |
Kind: static property of Decorator
Properties
| Name | Type | Description |
|---|---|---|
| publicCert | buffer |
Buffer of the alipay public certificate. |
Kind: static property of Decorator
Properties
| Name | Type | Description |
|---|---|---|
| requestInterceptor | function |
Named as signer function. |
Kind: static property of Decorator
Properties
| Name | Type | Description |
|---|---|---|
| responseVerifier | function |
Named as verifier function. |
Kind: static property of Decorator
Properties
| Name | Type | Description |
|---|---|---|
| defaults | object |
The defaults configuration whose pased in Axios. |
PromiseLikePortable of the axios.request with defaults {method, params, headers}
compatible since Axios >= 0.19.0
function of config.headers is available since v0.0.9Kind: static method of Decorator
Returns: PromiseLike - - The AxiosPromise instance.
| Param | Type | Description |
|---|---|---|
| config | object |
The configuration. |
| config.data | object | Buffer | undefined |
The post data |
| config.params | object | undefined |
The search parameters |
| config.headers | object | function | undefined |
The request’s headers object or a callback function for sign-only requests |
objectDeep merge the input with the defaults
Kind: static method of Decorator
Returns: object - - With the built-in configuration.
| Param | Type | Description |
|---|---|---|
| config | object |
The configuration. |
Simple and lite of multipart/form-data implementation, most similar to form-data
(new Form)
.append('a', 1)
.append('b', '2')
.append('c', Buffer.from('31'))
.append('d', JSON.stringify({}), 'any.json')
.append('e', require('fs').readFileSync('/path/your/file.jpg'), 'file.jpg')
.getBuffer()
Object.<string, string>built-in mime-type mapping
BufferBufferBufferarray.<Buffer>The Form's data storage
Object.<string, number>The entities' value indices whose were in this.data
Simple and lite of multipart/form-data implementation, most similar to form-data
(new Form)
.append('a', 1)
.append('b', '2')
.append('c', Buffer.from('31'))
.append('d', JSON.stringify({}), 'any.json')
.append('e', require('fs').readFileSync('/path/your/file.jpg'), 'file.jpg')
.getBuffer()
Kind: global class
BufferObject.<string, string>FormFormCreate a multipart/form-data buffer container for the file uploading.
BufferTo retrieve the data buffer
Kind: instance method of Form
Returns: Buffer - - The payload buffer
Object.<string, string>To retrieve the Content-Type multipart/form-data header
Kind: instance method of Form
Returns: Object.<string, string> - - The Content-Type header With this.boundary
FormAppend a customized mime-type(s)
Kind: instance method of Form
Returns: Form - - The Form class instance self
| Param | Type | Description |
|---|---|---|
| things | Object.<string, string> |
The mime-type |
FormAppend data wrapped by boundary
Kind: instance method of Form
Returns: Form - - The Form class instance self
| Param | Type | Description |
|---|---|---|
| field | string |
The field |
| value | string | Buffer |
The value |
| [filename] | String |
Optional filename, when provided, then append the Content-Type after of the Content-Disposition |
Object.<string, string>built-in mime-type mapping
BufferBufferBufferarray.<Buffer>The Form’s data storage
Object.<string, number>The entities’ value indices whose were in this.data
Provides easy used methods using in this project.
Kind: global class
objectstringstringobjectbooleanobjectTo prevent new operation, works only as static class.
objectSorts an Object by key.
Kind: static method of Formatter
Returns: object - - The sorted object.
| Param | Type | Description |
|---|---|---|
| thing | object | URLSearchParams |
The input plain or URLSearchParams object. |
stringLike queryString does but without the sign and empty value entities.
Kind: static method of Formatter
Returns: string - - The sorted object.
| Param | Type | Description |
|---|---|---|
| thing | object |
The input object. |
stringRetrieve the current yyyy-MM-dd HH:mm:ss date time based on given timeZone.
Notes: NodeJS v10.15.3,v12.18.0,v14.5.0 had strange behavior on Intl.DateTimeFormat, see hourCycle:h23 comments below:
Kind: static method of Formatter
Returns: string - - yyyy-MM-dd HH:mm:ss date time string
| Param | Type | Default | Description |
|---|---|---|---|
| [when] | string | number | Date |
Any available inputs refer to the Date() constructor, default Date.now(). |
|
| [timeZone] | string |
"Asia/Shanghai" |
Any available inputs refer to the options in Intl.DateTimeFormat, default Asia/Shanghai. |
objectParse the source with given placeholder.
Kind: static method of Formatter
Returns: object - - {ident, payload, sign} object
| Param | Type | Default | Description |
|---|---|---|---|
| source | string |
The inputs string. | |
| [placeholder] | string |
(?<ident>[a-z](?:[a-z_])+)_response |
The payload pattern. |
booleanCheck the given numeric input whether or nor the leap year.
Kind: static method of Formatter
Returns: boolean - - True means is leap year, otherwise NOT.
| Param | Type | Description |
|---|---|---|
| numeric | number |
The inputs number. |
objectTranslate the inputs for the page service, such as alipay.trade.page.pay, alipay.trade.wap.pay OpenAPI methods.
Kind: static method of Formatter
Returns: object - - Minimal following the AxiosResponse specification, returns {data, toJSON(), toString()} object
| Param | Type | Description |
|---|---|---|
| options | object |
The inputs |
| options.baseURL | string |
The OpenAPI gateway URL |
| options.method | string |
The HTTP method, should be get or post, default is post |
| options.params | object |
The gernal paramters object, including method, version, charset, sign_type, format etc. |
| options.params.method | string |
The OpenAPI’s method, should be alipay.trade.page.pay etc. |
| options.params.version | string |
The OpenAPI’s version, default is 1.0 |
| options.params.charset | string |
The OpenAPI’s charset, default is utf-8 |
| options.params.format | string |
The OpenAPI’s format, default is JSON |
| options.params.sign_type | string |
The OpenAPI’s sign_type, default is RSA2 |
| options.data | URLSearchParams |
The biz_content and sign contents |
| options.data.biz_content | string |
The OpenAPI’s biz_content, json string |
| options.data.sign | string |
The OpenAPI’s sign, base64 encoded string dependent on the options.params.sign_type |
Provide some useful functions for the catificate(s)
Kind: global class
stringstringarray.<Certificate>stringstringTo prevent new operation, works only as static class.
Kind: static property of Helpers
Propertiy: LF - The line feed character
Kind: static property of Helpers
Propertiy: OIDs - Built-in ASN.1 OIDs
stringMD5 hash function
Kind: static method of Helpers
Returns: string - - The digest string
| Param | Type | Description |
|---|---|---|
| …things | string | Buffer | BufferView |
To caculating things |
stringSimilar to require(‘wordwrap’) function for formatting the PEM certificate
Kind: static method of Helpers
Returns: string - - The wrapped string
| Param | Type | Default | Description |
|---|---|---|---|
| str | string |
The input string | |
| [width] | number |
64 |
The wrapping width, default is 64 |
| [char] | string |
The wrapping character, default is this.LF |
array.<Certificate>Mapping to @fidm/x509.Certificate.fromPEMs
Kind: static method of Helpers
Returns: array.<Certificate> - - Array of the @fidm/x509.Certificate instance
| Param | Type | Default | Description |
|---|---|---|---|
| thing | string | Buffer |
The certificatie(s) file path or Buffer | |
| [pattern] | string |
"." |
The signatureAlgorithm matching pattern, default is dot(.) for all |
stringExtract a certificate from given thing
Kind: static method of Helpers
Returns: string - - The pem format certificate(s)
| Param | Type | Default | Description |
|---|---|---|---|
| thing | string | Buffer |
The certificatie(s) file path or Buffer | |
| [pattern] | string |
"sha256" |
The algo prefix or suffix, default is sha256 prefix |
stringCalculate the given certificate(s) SN value string
Note: The primitive BigInt was shipped since nodejs v10.8.0, we’re >= 10.15.0 on safety.
Kind: static method of Helpers
Returns: string - - The SN value string
| Param | Type | Default | Description |
|---|---|---|---|
| thing | string | Buffer |
The certificatie(s) file path or Buffer | |
| [pattern] | string |
"sha256" |
The algo prefix or suffix, default is sha256 prefix |
Provides sign/verify for the RSA sha1WithRSAEncryption RSA2 sha256WithRSAEncryption cryptos.
Kind: global class
To prevent new operation, works only as static class.
Kind: static property of Rsa
Properties
| Name | Type | Description |
|---|---|---|
| base64 | string |
Alias of base64 string |
Kind: static property of Rsa
Properties
| Name | Type | Description |
|---|---|---|
| ALGO_TYPE_RSA | string |
Alias of sha1WithRSAEncryption string |
Kind: static property of Rsa
Properties
| Name | Type | Description |
|---|---|---|
| ALGO_TYPE_RSA2 | string |
Alias of sha256WithRSAEncryption string |
stringCreates and returns a Sign string that uses given type=RSA|RSA2.
Kind: static method of Rsa
Returns: string - Base64-encoded signature.
| Param | Type | Description |
|---|---|---|
| message | string |
Content will be crypto.Sign. |
| privateKeyCertificate | string | Buffer |
A PEM encoded private key certificate. |
| [type] | string |
one of the algo alias RSA/RSA2, default is RSA2. |
booleanVerifying the message with given signature string that uses given type=RSA|RSA2.
Kind: static method of Rsa
Returns: boolean - True is passed, false is failed.
| Param | Type | Description |
|---|---|---|
| message | string |
Content will be crypto.Verify. |
| signature | string |
The base64-encoded ciphertext. |
| publicCertificate | string | Buffer |
A PEM encoded public certificate. |
| [type] | string |
one of the algo alias RSA/RSA2, default is RSA2. |
npm test
To disable nock and request with the real gateway, just NOCK_OFF=true npm test
Helpers 为本模块基础类之一;Helpers.SN 方法,兼容多DN属性情况;Formatter.localeDateTime 方法,使用 String.padStart 计算 h23 小时;同步应答验签 逻辑,遵从本SDK约定,只要能从应答返回中解析出有效负载,即仅返回负载;异步通知消息 验签文档示例函数;ts,相关问题 #4;npm install --no-optional(>5.8.0)不起作用,不再可选依赖 form-data,以内置 Form 类为主;v0.0.11 新增 whatsCli cli.js 命令行交互工具
v0.0.10 优化 Formatter.page().data.html, 重点兼容utf8
v0.0.9 新增 Formatter.page 函数,支持page类接口调用(以第三入参回调)
v0.0.8 完善 API 文档 by jsdoc2md
v0.0.7 新增 Helpers 类及 certHelper 命令行工具集
v0.0.6 新增 Form 类,缩减并兼容 form-data
v0.0.5 向下兼容 NodeJS >= 10.15.0
v0.0.4 向下兼容 Axios >= 0.19.0
v0.0.3 增加测试用例及BUG修复
v0.0.2 重新发布版本
The MIT License (MIT)
Copyright (c) 2020 James ZHANG(TheNorthMemory)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.