Skip to content

Commit

Permalink
feat: 支持 appAuthToken 代调用模式 (#128)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 authored Jun 4, 2024
1 parent 00c7a3a commit 9630916
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ curl 方式调用支付宝 [API v3 协议](https://opendocs.alipay.com/open-v3/0
| options.form | `AlipayFormData \| AlipayFormStream` | 表单方式提交数据 ||
| options.requestId | `string` | 调用方的 requestId,不填会默认生成 uuid v4 ||
| options.needEncrypt | `boolean` | 自动 AES 加解密,默认值是 `false` ||
| options.appAuthToken | `string` | [应用授权令牌](https://opendocs.alipay.com/isv/10467/xldcyq?pathHash=abce531a),代商家调用支付宝开放接口必填 | 否 |

#### `AlipayCommonResult<T>`

Expand Down
22 changes: 20 additions & 2 deletions src/alipay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ export interface AlipayCURLOptions {
* 注意:只支持 body 参数加密,如果同时设置 form 和 needEncrypt,会抛 TypeError 异常
*/
needEncrypt?: boolean;
/**
* 应用授权令牌,代商家调用支付宝开放接口必填
*/
appAuthToken?: string;
}

/**
Expand Down Expand Up @@ -393,10 +397,24 @@ export class AlipaySdk {
requestOptions.content = httpRequestBody;
}
}
// 签名规则 https://opendocs.alipay.com/open-v3/054q58?pathHash=474929ac#%E6%99%AE%E9%80%9A%E8%AF%B7%E6%B1%82
// 签名字符串拼接格式:
//
// ```txt
// ${authString}\n
// ${httpMethod}\n
// ${httpRequestUrl}\n
// ${httpRequestBody}\n
// ${appAuthToken}\n
// ```
//
// TODO: 需要支持 app_cert_sn
const authString = `app_id=${this.config.appId},nonce=${randomUUID()},timestamp=${Date.now()}`;
// TODO: 需要支持 appAuthToken
const signString = `${authString}\n${httpMethod}\n${httpRequestUrl}\n${httpRequestBody}\n`;
let signString = `${authString}\n${httpMethod}\n${httpRequestUrl}\n${httpRequestBody}\n`;
if (options?.appAuthToken) {
requestOptions.headers['alipay-app-auth-token'] = options.appAuthToken;
signString += `${options.appAuthToken}\n`;
}
const signature = createSign('RSA-SHA256')
.update(signString, 'utf-8')
.sign(this.config.privateKey, 'base64');
Expand Down
22 changes: 20 additions & 2 deletions test/alipay.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ describe('test/alipay.test.ts', () => {
});
});

it('POST 文件上传,使用 AlipayFormData', async () => {
it.skip('POST 文件上传,使用 AlipayFormData', async () => {
// https://opendocs.alipay.com/open-v3/5aa91070_alipay.open.file.upload?scene=common&pathHash=c8e11ccc
const filePath = getFixturesFile('demo.jpg');
const form = new AlipayFormData();
Expand All @@ -142,7 +142,7 @@ describe('test/alipay.test.ts', () => {
assert(uploadResult.traceId);
});

it('POST 文件上传,使用 AlipayFormData with body', async () => {
it.skip('POST 文件上传,使用 AlipayFormData with body', async () => {
// https://opendocs.alipay.com/open-v3/5aa91070_alipay.open.file.upload?scene=common&pathHash=c8e11ccc
const filePath = getFixturesFile('demo.jpg');
const form = new AlipayFormData();
Expand Down Expand Up @@ -563,6 +563,24 @@ describe('test/alipay.test.ts', () => {
assert.equal(result.responseHttpStatus, 200);
});

it('POST /v3/alipay/user/deloauth/detail/query with appAuthToken = xxx', async () => {
// https://opendocs.alipay.com/open-v3/668cd27c_alipay.user.deloauth.detail.query?pathHash=3ab93168
await assert.rejects(async () => {
await sdk.curl('POST', '/v3/alipay/user/deloauth/detail/query', {
body: {
date: '20230102',
offset: 20,
limit: 1,
},
appAuthToken: '201509BBeff9351ad1874306903e96b91d248A36',
});
}, (err: any) => {
assert.equal(err.name, 'AlipayRequestError');
assert.match(err.message, /无效的应用授权令牌/);
return true;
});
});

it('模拟解密失败,需要处理空字符串', async () => {
const mockPool = mockAgent.get('https://openapi.alipay.com');
mockPool.intercept({
Expand Down

0 comments on commit 9630916

Please sign in to comment.