4. 客户端SDK集成与初始化配置
4.1 初始化原理与核心任务
支付SDK初始化是所有支付功能调用的前置条件。初始化过程本质上是应用与支付网关建立安全通信通道、加载本地加密资源、注册回调通知地址的过程。无论iOS、Android还是Web,初始化都需要完成以下核心任务:
- SDK加载:将支付核心库引入项目依赖
- 身份认证:使用AppID/AppKey(公钥)与商户密钥(私钥)建立双向信任
- 环境配置:明确指向沙箱或生产网关URL
- 参数预检:校验必要参数完整性,避免运行时崩溃
4.2 iOS SDK集成与初始化
4.2.1 集成方式
推荐使用CocoaPods或Swift Package Manager引入SDK。确保Xcode项目中Other Linker Flags已添加-ObjC标志。
| 集成方式 | 配置入口 | 示例代码片段 |
|---|---|---|
| CocoaPods | Podfile | pod 'PaymentSDK', '~> 3.2.0' |
| Swift Package Manager | Xcode > File > Add Packages | https://github.com/merchant/payment-sdk-ios.git |
| 手动集成 | Embed Frameworks | 将PaymentSDK.framework拖入项目 |
4.2.2 初始化调用
在AppDelegate或SceneDelegate的application:didFinishLaunchingWithOptions:中调用如下代码。初始化参数包括appId、merchantSecret、环境标志以及可选的enableLog调试开关。
// AppDelegate.m
#import <PaymentSDK/PaymentSDK.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
PaymentConfig *config = [[PaymentConfig alloc] init];
config.appId = @"wx_appid_xxxxxxxx";
config.merchantSecret = @"sk_live_xxxxxxxxxxxxxxxxxxxx";
config.environment = PaymentEnvironmentSandbox; // 沙箱环境
config.enableLog = YES; // 调试阶段开启
[PaymentSDK startWithConfig:config
completion:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSLog(@"[PaymentSDK] 初始化成功");
} else {
NSLog(@"[PaymentSDK] 初始化失败: %@", error.localizedDescription);
}
}];
return YES;
}
4.3 Android SDK集成与初始化
4.3.1 Gradle依赖配置
在项目级build.gradle添加Maven仓库地址,在模块级build.gradle添加依赖。
// 项目 build.gradle
allprojects {
repositories {
maven { url 'https://jitpack.io' }
mavenCentral()
google()
}
}
// 模块 build.gradle
dependencies {
implementation 'com.github.merchant:payment-sdk-android:3.2.0'
implementation 'com.google.code.gson:gson:2.10.1'
}
4.3.2 初始化代码
建议在Application.onCreate()中完成初始化,确保全局唯一实例。
// MyApplication.java
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
PaymentSDKConfig config = new PaymentSDKConfig.Builder()
.setAppId("wx_appid_xxxxxxxx")
.setMerchantSecret("sk_live_xxxxxxxxxxxxxxxxxxxx")
.setEnvironment(PaymentSDKConfig.ENV_SANDBOX)
.enableLog(BuildConfig.DEBUG)
.build();
PaymentSDK.init(this, config, new PaymentInitCallback() {
@Override
public void onSuccess() {
Log.d("PaymentSDK", "初始化成功");
}
@Override
public void onError(int errorCode, String errorMsg) {
Log.e("PaymentSDK", "初始化失败: " + errorCode + " " + errorMsg);
}
});
}
}
4.4 Web SDK集成与初始化
4.4.1 引入方式
SDK以ES Module或UMD形式发布。推荐使用npm安装,并按需加载。
// npm安装
npm install @merchant/payment-sdk --save
// 或直接CDN引入
<script src="https://cdn.jsdelivr.net/npm/@merchant/payment-sdk@3.2.0/dist/payment-sdk.min.js"></script>
4.4.2 初始化调用
初始化必须异步完成,SDK会在内部加载加密证书和路由表。
// 使用ES Module方式
import { PaymentSDK } from '@merchant/payment-sdk';
const config = {
appId: 'wx_appid_xxxxxxxx',
merchantSecret: 'sk_live_xxxxxxxxxxxxxxxxxxxx',
environment: 'sandbox', // 'sandbox' | 'production'
debug: true, // 调试日志
timeout: 15000 // 网络超时 (ms)
};
PaymentSDK.initialize(config)
.then(() => {
console.log('[PaymentSDK] 初始化成功');
})
.catch((error) => {
console.error('[PaymentSDK] 初始化失败', error.code, error.message);
});
🏷️ 一次性初始化原则:所有平台均应保证SDK在整个应用生命周期内只初始化一次。重复初始化可能导致状态冲突或内存泄漏。生产环境中建议将初始化逻辑封装在单例或依赖注入容器中。
4.5 初始化参数对照表
| 参数名 | 类型 | 必填 | 说明 | 示例值 |
|---|---|---|---|---|
appId | String | 是 | 商户应用标识,由支付平台下发 | wx_appid_xxxxxxxx |
merchantSecret | String | 是 | 商户密钥,用于签名;请放在服务端 | sk_live_xxxxxxxx... |
environment | Enum/String | 是 | 沙箱(sandbox)或生产(production) | PaymentEnvironmentSandbox |
enableLog/debug | Boolean | 否 | 输出SDK内部日志,默认关闭 | true |
timeout | Number | 否 | 网络请求超时时间(毫秒) | 15000 |
4.6 沙箱与生产环境切换
环境切换是开发测试与上线部署之间最常见的操作。切换本质上是改变SDK内部网关终结点(Endpoint)。沙箱环境使用模拟网关、测试证书和虚拟资金;生产环境使用真实网关、正式证书和结算资金。
💡 切换最佳实践:不要硬编码环境标志。建议通过构建配置或环境变量控制:iOS使用#if DEBUG,Android使用BuildConfig.DEBUG,Web使用process.env.NODE_ENV。
// 多环境配置示例(JavaScript)
const envConfig = {
development: {
environment: 'sandbox',
endpoint: 'https://api.sandbox.payment.com/v3',
debug: true
},
production: {
environment: 'production',
endpoint: 'https://api.payment.com/v3',
debug: false
}
};
const config = envConfig[process.env.NODE_ENV || 'development'];
PaymentSDK.initialize(config);
⚠️ 生产密钥泄露风险:merchantSecret严禁硬编码在客户端代码中。Web场景应通过后端接口下发临时令牌;移动端可使用白盒加密或密钥注入服务。沙箱环境的测试密钥与生产密钥务必隔离管理。
4.7 调试案例:初始化失败的完整排查流程
以下是一次典型的初始化失败调试案例,包含错误日志分析和修复步骤。
// 错误日志输出
[PaymentSDK] Failed to initialize:
Error Domain=com.payment.sdk Code=-1001
"Network connection timed out"
UserInfo={NSLocalizedDescription=Network connection timed out}
| 排查步骤 | 操作 | 预期结果 |
|---|---|---|
| 1. 确认环境URL可达性 | curl -v https://api.sandbox.payment.com/v3/init | 返回HTTP 200 |
| 2. 检查AppId合法性 | 登录商户后台 > 应用管理 > 复制AppId | AppId格式正确且状态为已激活 |
| 3. 验证密钥匹配 | 使用工具对固定字符串签名,比对SDK内部签名 | 签名一致 |
| 4. 切换日志级别 | 设置enableLog=true,观察SDK初始化阶段日志 | 可见“开始获取根证书”“签名验证通过”等关键日志 |
| 5. 客户端时间校准 | 同步NTP时间,保证误差在2分钟内 | 时间戳校验通过 |
// 修复后成功日志
[PaymentSDK] Environment set to: sandbox
[PaymentSDK] Root certificate loaded successfully
[PaymentSDK] Signature validation passed
[PaymentSDK] Initialization completed in 1.23s
4.8 常见初始化错误
| 错误码 | 错误描述 | 解决建议 |
|---|---|---|
-1001 | 网络超时 | 检查网络防火墙、代理配置;沙箱环境确认已添加域名白名单 |
-1003 | AppId格式无效 | AppId通常以wx_/app_等前缀开头;检查是否包含空格或换行符 |
-1005 | 密钥不对称 | 确认公钥与私钥属于同一密钥对;生产密钥不能用于沙箱环境 |
-1010 | 重复初始化 | 使用单例模式或状态锁避免多次调用startWithConfig |
-1020 | 时间戳误差过大 | 校准设备系统时间;移动端建议接入NTP服务 |
4.9 性能与稳定性优化
- 延迟初始化:将SDK初始化推迟到首个支付页面加载前,避免阻塞应用启动。初始化耗时通常为300ms~1.5s。
- 证书缓存:SDK初始化会下载根证书和公钥列表。第一次初始化后应缓存至本地,后续冷启动优先使用缓存,减少网络依赖。
- 重试机制:初始化失败后设置指数退避重试(如1s、2s、4s、8s,最多4次)。Web端注意避免页面切换时重复重试。
- 内存监控:Android端注意在
onTrimMemory回调中释放SDK内部临时资源;iOS端避免在后台队列持有SDK引用。