-
Notifications
You must be signed in to change notification settings - Fork 227
SDK 配置详解
为了在集成到你的系统后能正常运行,SDK 需要以下两个部分的配置:
- 商户配置。例如,商户 API 私钥、商户 API 证书序列号、APIv3Key 等。
- HTTP 配置。例如,超时时间、代理地址等。
商户配置主要是商户的身份信息,用于构造请求的签名和验证应答的签名。
为了适配开发者不同的密钥基础设施,SDK 对商户配置做了抽象。
- 面向底层 HttpClient,将配置抽象成身份认证实体
Credential
和应答验证实体Validator
。 - 面向开发者,SDK 使用
Config
接受商户配置,并为 HTTP 客户端提供所需的Credential
和Validator
。
如果你在你的服务内部署商户 API 私钥,可使用 SDK 提供的 Config
实现类。
因为配置项众多导致构造函数有多个参数,Config
实现都采用了生成器(Builder)模式。Builder 提供了以下配置方法:
方法 | 说明 |
---|---|
merchantId(String) | 商户号 |
merchantSerialNumber(String) | 商户 API 证书的证书序列号 |
privateKey(String) | 私钥字符串 |
privateKey(PrivateKey) | 私钥对象 |
privateKeyFromPath(String) | 本地私钥文件的路径字符串 |
不过,以上商户配置还不够。为了验证 API 应答签名,SDK 还需要微信支付平台证书。根据不同的平台证书提供方式,SDK 提供了两种 Config
实现类:
-
RSAConfig
。由 SDK 使用方,即商户开发者,提供本地微信支付平台证书,并在证书过期前人工更新证书。 -
RSAAutoCertificateConfig
。由 SDK 自动下载,并定时更新微信支付平台证书。
我们推荐使用 RSAAutoCertificateConfig
,因为它无需开发者人工维护微信支付平台证书,使用更简单更可靠。
RSAAutoCertificateConfig
在构造时会首次下载证书。如果首次下载失败,构造将失败,并抛出异常。
它还包含一个后台线程定时更新微信支付平台证书(目前更新间隔设计为60分钟),实现了当前证书过期时的新老证书平滑切换。如果在更新时下载失败,则不抛出异常,并继续使用之前的证书。
代码片段-配置商户信息 演示了如何构造 RSAAutoCertificateConfig
并用它初始化一个 Service。
RSAAutoCertificateConfig.Builder
增加的配置方法见下表。
方法 | 说明 |
---|---|
apiV3Key(String) | APIv3 密钥 |
httpClientBuilder() | 见代理配置 |
如果你不想使用 SDK 提供的定时更新平台证书,你可以使用 RSAConfig
加载本地证书。
Config config =
new RSAConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.wechatPayCertificatesFromPath(wechatPayCertificatePath)
.build();
// 以JsapiService为例,使用 config 初始化 service
JsapiService service = new JsapiService.Builder().config(config).build();
除了一般的配置方法外,它新增的配置方法见下表。
方法 | 说明 |
---|---|
wechatPayCertificatesFromPath(String...) | 本地微信支付平台证书的路径,支持多个 |
wechatPayCertificates(String...) | 微信支付平台证书字符串,支持多个 |
跟商户配置一样,HTTP 客户端也采用了生成器模式,网络配置通过生成器设置。
SDK 使用 OkHttp 作为底层的 HTTP 客户端。如果开发者不熟悉 OkHttp,推荐使用 SDK 封装的 DefaultHttpClientBuilder 来构造 HTTP 客户端。
目前支持的网络配置方法见下表。
方法 | 说明 | 默认值 | 更多信息 |
---|---|---|---|
readTimeoutMs() |
设置新连接的默认读超时 | 10*1000(10秒) | OkHttpClient/Builder/readTimeout |
writeTimeoutMs() |
设置新连接的默认写超时 | 10*1000(10秒) | OkHttpClient/Builder/writeTimeout |
connectTimeoutMs() |
设置新连接的默认连接超时 | 10*1000(10秒) | OkHttpClient/Builder/connectTimeout |
proxy() |
设置客户端创建的连接时使用的 HTTP 代理 | 无 | OkHttpClient/Builder/proxy |
下面的示例演示了如何使用 DefaultHttpClientBuilder 初始化某个具体的业务 Service。
HttpClient httpClient =
new DefaultHttpClientBuilder()
.config(config)
.connectTimeoutMs(500)
.build();
// 以JsapiService为例,使用 httpclient 初始化 service
JsapiService service = new JsapiService.Builder().httpclient(httpClient).build();
PS:由于微信支付 API 请求需要签名和验签,HTTP 客户端的运行也依赖了商户配置。所以,除了网络配置外,生成器还提供了设置商户配置的方法 DefaultHttpClientBuilder.config()
。
SDK 支持使用方自定义 OkHttpClient。这样开发者可以直接从底层更丰富地配置 HTTP 客户端的行为,例如:超时、重试、HTTP 拦截器。
下面的代码演示了如何使用 OkHttpClient.Builder 配置超时。更多配置,请直接查阅 OkHttpClient.Builder 的文档。
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3key)
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
HttpClient httpClient =
new DefaultHttpClientBuilder()
.config(config)
.okHttpClient(okHttpClient)
.build();
// 以JsapiService为例,使用 httpclient 初始化 service
JsapiService service = new JsapiService.Builder().httpclient(httpClient).build();
很多开发者的网络环境限制了访问外网需经过代理。SDK 在 DefaultHttpClientBuilder
中提供了 proxy()
方法。
// 使用 proxy 设置代理
HttpClient httpClient =
new DefaultHttpClientBuilder()
.config(config)
.proxy(new Proxy(Type.SOCKS, new InetSocketAddress("localhost", 8099))
.build();
// 使用 httpclient 初始化 service
JsapiService service = new JsapiService.Builder().httpclient(httpClient).build();
但是,这种方式不适用于自动更新证书的 RSAAutoCertificateConfig
。因为 RSAAutoCertificateConfig
自身就需要一个可用的 HTTP 客户端,跟 DefaultHttpClient
产生了循环依赖。
graph LR;
RSAAutoCertificateConfig-->HttpClient;
HttpClient-->DefaultHttpClient;
DefaultHttpClient-->RSAAutoCertificateConfig;
正确的方式是使用 RSAAutoCertificateConfig.Builder.httpClientBuilder()
方法,通过 HttpClientBuilder
将网络配置传递给证书下载器。
示例代码如下:
// 设置下载自动更新证书时网络配置
DefaultHttpClientBuilder clientBuilder =
new DefaultHttpClientBuilder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8099));
// 设置商户配置,并使用 httpClientBuilder 设置 HttpClient 所需的网络配置
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3key)
.httpClientBuilder(clientBuilder)
.build();
这样,RSAAutoCertificateConfig
会使用 clientBuilder
提供的网络配置,包括代理配置。
接下来,如果在业务请求时,你希望沿用下载证书时的商户配置和网络配置,只需将新得到的 Config
设置到 clientBuilder
中,得到 Service 可用的 HTTP 客户端。
// case1: 继续使用网络配置
clientBuilder.config(config);
JsapiService service = new JsapiService.Builder()
.httpclient(clientBuilder.build())
.build();
如果在业务请求时,你希望使用一组新的网络配置,那么你可以将 Config
设置到新的 HttpClientBuilder
中,重新构造 HTTP 客户端。这样,下载证书会使用之前的网络配置,而在业务请求时使用新的网络配置。
// case2: 如果希望另外设置 API 请求的网络配置,可以这样构造 Service
HttpClient httpClient = new DefaultHttpClientBuilder.Builder()
.config(config)
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8099)))
.connectTimeoutMs(10 * 1000)
.build()
JsapiService service = new JsapiService.Builder()
.httpClient(httpClient)
.build();