Skip to content

Commit

Permalink
feat: 增加 HTTP 代理调用支持
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Jul 5, 2024
1 parent 800e910 commit 7c2c581
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 0 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,32 @@ const signCheckPass = alipaySdk.rsaCheck(signContent, sign, signType);
console.log(signCheckPass);
```

### 通过 HTTP 代理服务器调用

在需要固定 IP 白名单调用的场景下,可以通过配置 `config.proxyAgent` 来指定 HTTP 代理服务器调用。

```ts
import { AlipaySdk, ProxyAgent } from 'alipay-sdk';

// 实例化客户端
const alipaySdk = new AlipaySdk({
// 其他配置不展示
// ...
proxyAgent: new ProxyAgent('http(s)://your-http-proxy-address'),
});

// 后续的所有 http 调用都会走此 HTTP 代理服务器
const result = await alipaySdk.curl('POST', '/v3/alipay/user/deloauth/detail/query', {
body: {
date: '20230102',
offset: 20,
limit: 1,
},
});

console.log(result);
```

## alipay-sdk v3 到 v4 的升级说明

从 v3 到 v4 有以下不兼容变更,请参考示例代码进行更新
Expand Down
6 changes: 6 additions & 0 deletions src/alipay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Readable } from 'node:stream';
import urllib, { Agent, IncomingHttpHeaders } from 'urllib';
import type {
HttpClientResponse, HttpMethod, RequestOptions, RawResponseWithMeta,
ProxyAgent,
} from 'urllib';
import camelcaseKeys from 'camelcase-keys';
import snakeCaseKeys from 'snakecase-keys';
Expand Down Expand Up @@ -174,6 +175,7 @@ export interface AlipayCURLOptions {
export class AlipaySdk {
public readonly version = 'alipay-sdk-nodejs-4.0.0';
public config: Required<AlipaySdkConfig>;
#proxyAgent?: ProxyAgent;

/**
* @class
Expand Down Expand Up @@ -205,6 +207,7 @@ export class AlipaySdk {
// 普通公钥模式,传入了支付宝公钥
config.alipayPublicKey = this.formatKey(config.alipayPublicKey, 'PUBLIC KEY');
}
this.#proxyAgent = config.proxyAgent;
this.config = Object.assign({
urllib,
gateway: 'https://openapi.alipay.com/gateway.do',
Expand Down Expand Up @@ -337,6 +340,7 @@ export class AlipaySdk {
method: httpMethod,
dataType: dataType === 'stream' ? 'stream' : 'text',
timeout: options?.requestTimeout ?? this.config.timeout,
dispatcher: this.#proxyAgent,
};
// 默认需要对响应做验签,确保响应是由支付宝返回的
let validateResponseSignature = true;
Expand Down Expand Up @@ -598,6 +602,7 @@ export class AlipaySdk {
...formStream.headers(),
},
content: new Readable().wrap(formStream as any),
dispatcher: this.#proxyAgent,
};
// 计算签名
const signData = sign(method, signParams, config);
Expand Down Expand Up @@ -839,6 +844,7 @@ export class AlipaySdk {
// 'content-type': 'application/json',
accept: 'application/json',
},
dispatcher: this.#proxyAgent,
});
} catch (err: any) {
debug('HttpClient Request error: %s', err);
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { ProxyAgent } from 'urllib';
export * from './types.js';
export * from './alipay.js';
export { AlipayFormData } from './form.js';
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ProxyAgent } from 'urllib';

export type AlipaySdkSignType = 'RSA2' | 'RSA';

/**
Expand Down Expand Up @@ -56,4 +58,6 @@ export interface AlipaySdkConfig {
encryptKey?: string;
/** 服务器地址 */
wsServiceUrl?: string;
/** httpClient 请求代理 */
proxyAgent?: ProxyAgent;
}
28 changes: 28 additions & 0 deletions test/alipay.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from './helper.js';
import {
AlipayFormData, AlipayFormStream, AlipayRequestError, AlipaySdk, AlipaySdkConfig,
ProxyAgent,
} from '../src/index.js';
import { aesDecryptText } from '../src/util.js';

Expand Down Expand Up @@ -127,6 +128,33 @@ describe('test/alipay.test.ts', () => {
});
});

it('使用 HTTP 代理调用', async () => {
if (!process.env.TEST_ALIPAY_HTTP_PROXY) {
return;
}
const proxyAgent = new ProxyAgent(process.env.TEST_ALIPAY_HTTP_PROXY);
const sdkWithProxy = new AlipaySdk({
...sdkStableConfig,
proxyAgent,
});
await assert.rejects(async () => {
await sdkWithProxy.curl('POST', '/v3/alipay/user/info/share', {
body: {
auth_token: '20120823ac6ffaa4d2d84e7384bf983531473993',
},
});
}, err => {
console.error(err);
assert(err instanceof AlipayRequestError);
assert.match(err.message, /无效的访问令牌/);
assert.equal(err.links!.length, 1);
assert.equal(err.code, 'invalid-auth-token');
assert(err.traceId);
assert.equal(err.responseHttpStatus, 401);
return true;
});
});

it('POST 文件上传,使用 AlipayFormData', async () => {
// https://opendocs.alipay.com/open-v3/5aa91070_alipay.open.file.upload?scene=common&pathHash=c8e11ccc
const filePath = getFixturesFile('demo.jpg');
Expand Down

0 comments on commit 7c2c581

Please sign in to comment.