Yet Another Alipay OpenAPI Smart Development Kit
Axios
aes-128-cbc
)加/解密功能sha1WithRSAEncryption
)及RSA2(sha256WithRSAEncryption
)签名、验签功能method({请求参数}[, {公共请求参数}[, {特殊头参数}]])
作为HTTP接口驱动,释义如下:
公共请求参数
的 method
,即作为本SDK标准方法链,弹性扩容,示例使用方法如下,详细审查见文末请求参数
,以 Object
对象作为第一个入参公共请求参数
,以 Object
对象作为第二个入参multipart/form-data
头信息,以 Object
对象作为第三个入参,见如下示例Formatter.page
,返回结果可直接作为页面/接口输出,说明用法见如下示例headers[x-alipay-verified]
为验签结果,值可能为 ok
, undefined
headers[x-alipay-signature]
为源返回数据签名值,值可能为 undefined
headers[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 { Alipay, Rsa } = require('whats-alipay');
//应用app_id
const app_id = '2014072300007148';
//商户RSA私钥,入参是'从官方工具获取到的BASE64字符串'
const privateKey = Rsa.fromPkcs1('MIIEpAIBAAKCAQEApdXuft3as2x...');
// 以上是下列代码的语法糖,格式为 'private.pkcs1://' + '从官方工具获取到的字符串'
// const privateKey = Rsa.from('private.pkcs1://MIIEpAIBAAKCAQEApdXuft3as2x...');
// Node10仅支持以下方式,须保证`private_key.pem`为完整X509格式
// const privateKey = require('fs').readFileSync('/your/openapi/private_key.pem');
//支付宝RSA公钥,入参是'从官方工具获取到的BASE64字符串'
const publicKey = Rsa.fromSpki('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg...');
// 以上是下列代码的语法糖,格式为 'public.spki://' + '从官方工具获取到的字符串'
// const publicKey = Rsa.from('public.spki://MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg...');
// Node10仅支持以下方式,须保证`public_key.pem`为完整X509格式
// const publicKey = require('fs').readFileSync('/the/alipay/public_key.pem');
const whats = new Alipay({ privateKey, publicKey, params: { app_id, } });
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 { Multipart } = require('whats-alipay');
const form = new Multipart();
form.append(
'image_content',
require('fs').readFileSync('/path/for/uploading.jpg'),
'uploading.jpg'
);
whats
.ant.merchant.expand.indirect.image.upload(
form.getBuffer(),
{image_type: 'jpg'},
{...form.getHeaders()}
)
.then(({data}) => data)
.catch(({response: {data}}) => data)
.then(console.log)
const { Multipart } = require('whats-alipay');
const form = new Multipart();
form.append(
'image_content',
require('fs').readFileSync('/path/for/uploading.jpg'),
'uploading.jpg'
);
whats
.alipay.offline.material.image.upload(
form.getBuffer(),
{image_type: 'jpg', image_name: 'uploading.jpg'},
{...form.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
,即扩容至多少,以上示例打印如下:
通知消息验签,依赖相关 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)
}
npm install && npm test
To disable nock
and request with the real gateway, just NOCK_OFF=true npm test