1.简介
WingEpicExeSDK主要是为满足PC端Epic平台Windows的游戏需要,为此类游戏提供基于Epic平台的登录、支付、数据收集等通用功能。以下文档中会把WingEpicExeSDK简称为SDK。
2.集成
2.1.SDK库选择
SDK提供了多个版本的库文件,可以根据项目需求使用。
序号 | 平台 | 是否MT编译 | lib库文件 | SDK下载 |
---|---|---|---|---|
1 | x86 | 否 | wingsdk.lib | 下载 |
2 | x64 | 否 | wingsdk64.lib | 下载 |
3 | x86 | 是 | wingsdk_mt.lib | 下载(推荐) |
4 | x64 | 是 | wingsdk64_mt.lib | 下载 |
MT编译版本:已经内置VC运行库内容,不依赖于外部VC运行库。
普通(MD)编译版本:该版本会使用附带的vcruntime140.dll,msvcp140.dll,vcruntime140_1.dll这几个文件。
对应的dll版本:
版本 | 包含文件 | 备注 |
---|---|---|
x86 | EOSSDK-Win32-Shipping.dll libcrypto-3-wing.dll libssl-3-wing.dll msvcp140.dll vcruntime140.dll wingsdk.dll xaudio2_9redist.dll |
|
x64 | EOSSDK-Win64-Shipping.dll libcrypto-3-x64-wing.dll libssl-3-x64-wing.dll msvcp140.dll vcruntime140.dll vcruntime140_1.dll wingsdk64.dll xaudio2_9redist.dll |
|
x86_mt | EOSSDK-Win32-Shipping.dll libcrypto-3-wing-mt.dll libssl-3-wing-mt.dll wingsdk_mt.dll xaudio2_9redist.dll |
|
x64_mt | EOSSDK-Win64-Shipping.dll libcrypto-3-x64-wing-mt.dll libssl-3-x64-wing-mt.dll wingsdk64_mt.dll xaudio2_9redist.dll |
2.2.项目集成
以VisualStudio项目工程为例
1.下载最新版本SDK压缩包,并解压
2.SDK头文件引入
1)复制include文件夹及其内容到项目中,主要包含wing目录下的wing_api.h头文件
2)右键项目->属性->C/C++->常规->附加包含目录,填入include文件夹路径,例如include文件夹是复制到项目根目录下,则路径可以填写:$(ProjectDir)include
3.SDK库文件引入
1)复制lib文件夹及其内容到项目中,并在项目属性页->链接器->常规->附加库目录,中填入lib文件夹路径,例如lib文件夹是复制到项目根目录下,则路径可以填写:$(ProjectDir)lib
2)在项目属性页->链接器->输入->附加依赖项中填入sdk的lib文件,如果是x86编译,则填入wingsdk.lib,如果是x64编译,则填入wingsdk64.lib,如果使用mt版本,则选择对应带mt后缀lib文件。
4.SDK的Api使用
1)在项目中引入。以前面步骤的配置路径作为示例,那么引入的路径为 #include “wing/wing_api.h”
2)在项目中使用。wing_api.h的接口为命名空间+方法的使用方式,例如:sdk的初始化方法使用,WingProxy::Init(“appId”,“appKey”,[](int code,string msg,string data){});
5.项目编译后,需要把sdk用到的dll文件复制到编译后的exe程序目录中,否则项目无法正常运行。具体版本对应的dll文件,参考前面dll版本文件对应表。例如x86的dll内容如下图:
6.运行程序
2.3.三方库版本
三方库 | 版本 | 包含dll(只列举x86版本) | 功能 |
---|---|---|---|
OpenSSL | 3.1.3 | libcrypto-3-wing.dll libssl-3-wing.dll |
网络请求 |
EpicSDK | 1.16.2 | EOSSDK-Win32-Shipping.dll xaudio2_9redist.dll |
Epic平台SDK |
3.接口说明
3.1.使用方式
sdk的api采用命名空间+方法的形式定义的,WingProxy是所有sdk接口的命名空间,以初始化方法为例,使用方式:
1 2 3 |
WingProxy::Init(appId, appKey, callback); |
3.2.回调函数
sdk接口的参数中,除了一些常见类型参数,在wing_api.h中还声明了WingCallback回调函数,参数说明如下:
参数 | 类型 | 说明 | |
---|---|---|---|
code | int | 状态码,具体取值参考《状态码说明》章节 | |
msg | std::wstring | 状态码说明 | |
data | std::wstring | Json字符串,里面包含该接口会返回的字段,例如登录接口登录成功后返回的data内容:{“msg”:”token refreshed”,”code”:200,”isFirstLogin”:0,”userId”:7822920,”token”:”30_o1hejvBB22LKMu”} |
4.SDK接口
4.1.初始化
调用下面接口对SDK进行初始化,建议在程序开始时首先调用,确保后续其他sdk接口可以正常使用,该方法需在主线程中调用.
1 2 3 |
WingProxy::Init(wstring appId, wstring appKey, WingCallback callback); |
参数说明:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
appId | std::wstring | Y | appId,具体值从运营处获取 |
appKey | std::wstring | Y | appKey,具体值从运营处获取 |
WingCallback | WingCallback | Y | 回调函数 |
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
std::wstring appId = L"9910e80...80429f5"; // 从运营处获取 std::wstring appKey = L"oHg7c7pW....N8YTWJN"; // 从运营处获取 WingProxy::Init(appId, appKey, [](int code, std::wstring msg, std::wstring data) { if (code == 200) { MessageBoxW(NULL, (L"初始化成功..." + msg).c_str(), L"提示", MB_OK); } else { MessageBoxW(NULL, (L"初始化失败. 错误:" + msg).c_str(), L"提示", MB_OK); } }); |
4.2.更新SDK事件
调用以下方法通知SDK进行工作。为了使SDK提供的服务正常运行,必须经常调用该函数。对于基于时间间隔(tick-based)的应用,通常希望每个时间间隔调用一次这个函数。该方法需在主线程中调用.
1 2 |
WingProxy::UpdateSDKEvent(); |
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc = { 0 }; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); wc.lpszClassName = TEXT("MyWindowClass"); RegisterClass(&wc); // 创建窗口 LPCWSTR title = DemoUtils::ToLPCWSTR("WING EPIC EXE SDK v1.0.0 - Build at " + DemoUtils::GetCompileTime()); g_hWnd = CreateWindow(TEXT("MyWindowClass"), title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL); // 显示窗口 ShowWindow(g_hWnd, nCmdShow); UpdateWindow(g_hWnd); // 消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); WingProxy::UpdateSDKEvent(); } return (int)msg.wParam; } |
4.3.退出程序
调用下面接口对SDK内资源进行释放,必须在程序退出前调用。
1 2 3 |
WingProxy::Exit(); |
4.4.登录
使用下面接口进行登录
1 2 3 |
WingProxy::Login(WingCallback callback); |
参数说明:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
WingCallback | Y | 回调函数 |
WingCallback的data内容字段说明:
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
userId | long | Y | 用户Id |
token | std::wstring | Y | 在线token |
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
WingProxy::Login([](int code, std::wstring msg, std::wstring data) { if (code == 200) { json jsonData = json::parse(data); long long userId = jsonData["userId"]; std::wstring token = jsonData["token"]; std::wstring tips = L"登录成功."; tips.append(L"\nUserId:").append(std::to_wstring(userId)) .append(L"\nToken:").append(DemoUtils::Utf82Unicode(token)); MessageBoxW(NULL, tips.c_str(), L"提示", MB_OK); } else { MessageBoxW(NULL, (L"登录失败. 错误:" + msg).c_str(), L"提示", MB_OK); } }); |
4.5.购买商品
1 2 |
WingProxy::CallPay(std::wstring productId, std::wstring extInfo, WingCallback callback); |
参数说明:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
productId | std::wstring | Y | WINGSDK平台的商品ID |
extInfo | std::wstring | Y | CP 扩展信息字段,限长512(JSON格式),WING服务器到CP服务器发货通知时原样返回给CP。如果CP的通知发货地址是动态变化的(比如每个服务区的地址都不一致),可以通过此字段设置:参数格式为标准JSON,参数名为 deliverUrl,参考格式{ “deliverUrl”:” http://game.com/deliver.do”, “otherInfo”:”otherInfo”,“merId”:””}merId字段(选填),收款商户ID,使用场景:同一个支付渠道下有多个不同的收款验证信息(或收款帐号)。无内容建议传入空字符串“”。 |
WingCallback | Y | 回调函数 |
WingCallback的data内容字段说明:
字段名 | 类型 | 必填 | 说明 |
---|---|---|---|
orderId | std::wstring | Y | 订单ID |
productId | std::wstring | Y | WINGSDK平台的商品ID |
currency | std::wstring | Y | 基准货币 |
amount | long long | Y | 基准货币价格 |
quantity | int | Y | 购买数量,目前一般都是1 |
extInfo | std::wstring | N | 扩展信息字段,内容与该方法传入的extInfo相同 |
status | int | Y | 1表示支付成功,其他表示支付失败 |
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
std::wstring strProductId = L"game001"; std::wstring strExtInfo = L"MyInfo|10086"; WingProxy::CallPay(strProductId, strExtInfo, [](int code, std::wstring msg, std::wstring data) { if (code != 200) { MessageBoxW(NULL, (L"支付失败. 错误:" + msg).c_str(), L"提示", MB_OK); } else { json jsonData = json::parse(data); std::wstring orderId = DemoUtils::Utf82Unicode(jsonData["orderId"]); std::wstring productId = DemoUtils::Utf82Unicode(jsonData["productId"]); std::wstring currency = DemoUtils::Utf82Unicode(jsonData["currency"]); long long amount = jsonData["amount"]; int quantity = jsonData["quantity"]; std::wstring extInfo = DemoUtils::Utf82Unicode(jsonData["extInfo"]); int status = jsonData["status"]; std::wstring tips = L""; tips.append(L"\n订单ID:").append(orderId) .append(L"\n商品ID:").append(productId) .append(L"\n基准币种:").append(currency) .append(L"\n基准货币价格:").append(std::to_wstring(amount)) .append(L"\n购买数量:").append(std::to_wstring(quantity)) .append(L"\n透传信息:").append(extInfo) .append(L"\n订单状态:").append(std::to_wstring(status)) .append(L"\n\n") .append(status == 1 ? L"支付成功" : L"支付失败"); MessageBoxW(NULL, tips.c_str(), L"提示", MB_OK); } }); |
4.6.游戏必要参数设置
WINGSDK包括serverId等游戏参数,这些参数主要用于数据跟踪和统计。
该部分参数必须严格按照文档进行设置,在后续的接口中会使用到这些参数,没有按照要求配置会导致部分接口调用失败。
参数设置时机除了按照说明设置,另外需要特别注意在游戏启动时的设置时机,具体参考 流程要求
4.6.1 设置服务器ID
当用户的服务器ID发生改变时,需要调用设置服务器ID接口设置新的服务器ID,例如每次进入服务
1 2 |
WingProxy::SetServerId(wstring serverId); |
注意:设置服务器id的操作在每次选服后都需要进行,必须在调用其他事件前设置
4.6.2.设置GameUserId
当游戏角色ID发生改变时,需要调用设置接口设置新的gameUserId,例如成功登录账号后、切换账号成功后
1 2 |
WingProxy::SetGameUserId(wstring gameUserId); |
注意:
1.必须在调用其他事件前设置。
2.游戏角色ID是游戏角色在游戏中的ID,不是WINGSDK自身的UserId。
3.若未创角前拿不到游戏角色ID,可以先设置-1,创角后再设置一次正确的角色ID
4.6.3.设置用户等级Level
当用户角色等级发生改变时,需要调用设置等级接口设置新的等级,例如开始进入游戏、等级提升等。
1 2 |
WingProxy::SetLevel(int level); |
注意:第一次进服获取玩家等级或玩家等级变更后,需要及时调用这个接口设置玩家等级,必须在调用其他事件前设置。
4.6.4.设置玩家游戏昵称
设置游戏玩家的昵称,调用接口:
1 2 |
WingProxy::SetNickName(wstring nickName); |
注意:
1.当玩家登录、登出游戏,或修改昵称时,需要及时调用这个接口设置玩家昵称。
2.调用该接口设置昵称后,玩家进行购买时会自动记录昵称到订单信息中。
4.7.数据收集
4.7.1.流程要求
WINGSDK数据收集使用在游戏的过程中打点的方式,如图所示:
注意:
1.以上流程图中涉及到的几个接口是有时序要求的,请参考流程图中的逻辑步骤进行设置:WingProxy::SetServerId()、WingProxy::SetGameUserId()、WingProxy::SetLevel()、WingProxy::SetNickName()、ghw_user_import事件、ghw_user_create事件。
2.其它的事件如ghw_level_achieved、ghw_self_tutorial_completed等请根据对应业务逻辑,在对应业务发生时调用接口发送。
序号 | 事件(接口)名称 | 事件描述 | 事件作用 | 建议触发点 | 备注 |
---|---|---|---|---|---|
1 | SetServerId | 设置服务器ID | 标记玩家当前所在的服务器,后台根据该字段统计每个服务器的数据 | 登录游戏服成功后 | |
2 | SetGameUserId | 设置玩家角色ID | 标记玩家当前的游戏角色ID,后台根据该字段统计玩家的数据 | 登录游戏服成功后 | |
3 | SetLevel | 设置玩家当前等级 | 标记玩家当前的游戏角色等级 | 玩家等级发生变更后,如登录游戏服成功后、玩家完成升级后 | |
4 | SetNickName | 设置玩家昵称 | 标记玩家当前的游戏昵称 | 玩家设置昵称后 | |
5 | ghw_user_import | 玩家登录游戏服 | 记录玩家登录游戏服的动作,后台根据该事件统计导入数、登录数、导入留存等数据 | 玩家登录游戏服成功后 | 需要先调用SetServerId、SetGameUserId、SetLevel接口 |
6 | ghw_user_create | 玩家创建角色 | 记录玩家创建角色的动作,后台根据该事件统计创角数 | 玩家创建角色成功后 | 需要先调用SetServerId、SetGameUserId、SetLevel接口 |
7 | ghw_user_info_update | 更新用户信息 | 更新用户信 | 玩家信息更新时 | 需要先调用SetServerId、SetGameUserId、SetNickname接口 |
8 | ghw_level_achieved | 更新玩家等级 | 更新玩家等级,后台根据此字段更新玩家等级 | 玩家达到新的等级时 | 需要先调用setLevel接口更新玩家等级 |
9 | ghw_self_lv_x | 更新关键等级 | 更新关键等级 | 关键等级到达时 | 属于自定义事件 |
10 | ghw_self_tutorial_completed | 完成新手任务 | 完成新手任务 | 完成新手任务时 | 属于自定义事件 |
4.7.2.发送事件
使用下面接口发送事件
1 2 |
WingProxy::PostEvent(const wstring & eventName, const wstring & params = "", double eventValue = numeric_limits<double>::quiet_NaN()) |
参数说明:
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
eventName | const std::wstring& | Y | 事件名称 |
params | const std::wstring& | N | 事件参数,可以不传,默认空。以json字符串的形式传递。例如需要设置isFirstEnter为1,则应该传递内容为:{“isFirstEnter”:1}。 |
eventValue | double | N | 事件价值,可以不传,默认无。 |
代码示例:
1 2 3 4 5 |
std::wstring strEventName = L"ghw_user_import"; std::wstring strEventParams = L"{\"isFirstEnter\":1}"; double value = 9.9; WingProxy::PostEvent(strEventName, strEventParams,value); |
4.7.3.预定义事件
4.7.3.1.ghw_user_import导入用户事件(进服)
说明:导入用户事件,玩家第一次进某个服时调用
参数名 | 类型 | 说明 | 必填 | 备注 |
---|---|---|---|---|
isFirstEnter | int | 是否第一次进服 | Y | 0->否;1->是;默认为0 |
注意:发送ghw_user_import事件前需调用设置服务器ID接口更新服务器id、设置gameUserId接口更新游戏用户id
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<br />/* ghw_user_import 导入用户事件 事件描述 : 玩家登录游戏服 事件作用 : 记录玩家登录游戏服的动作,后台根据该事件统计导入数、登录数、导入留存等数据 建议触发点 : 玩家登录游戏服成功后 调用前提 : 需要先调用SetServerId、SetGameUserId、SetLevel接口 必填字段 : isFirstEnter 类型int 是否第一次进服 0→否 1→是; 默认为0 */ WingProxy::SetServerId(服务器ID); WingProxy::SetGameUserId(游戏用户ID); WingProxy::SetLevel(用户等级); //未创角时可以传0 std::wstring strEventName = L"ghw_user_import"; std::wstring strEventParams = L"{\"isFirstEnter\":1}"; WingProxy::PostEvent(strEventName, strEventParams); |
4.7.3.2.ghw_user_create 创建角色
说明:创建游戏角色,游戏角色创建时调用
参数名 | 类型 | 说明 | 必填 | 备注 |
---|---|---|---|---|
nickname | std::wstring | 角色名(昵称) | Y | |
registerTime | long long | 创建时间 | Y | 注册时间戳,13位数,单位为毫秒(1970以后) |
gender | int | 角色性别 | N | 0 女,1 男,2 未知 |
roleType | std::wstring | 角色类型 | N | |
vip | int | 等级 | N | |
bindGameGold | long long | 绑定钻石 | N | |
gameGold | long long | 用户钻石数 | N | |
fighting | long long | 战斗力 | N | |
status | int | 状态 | N | 状态标识,-1: 锁定,1:未锁定 |
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<br /> /* ghw_user_create 创角事件 事件描述 : 玩家创建角色 事件作用 : 记录玩家创建角色的动作,后台根据该事件统计创角数 建议触发点 : 玩家创建角色成功后 调用前提 : 需要先调用SetServerId、SetGameUserId、SetLevel接口 必填字段 : nickname 昵称 registerTime 注册时间戳 单位为毫秒(1970以后) 可选字段 : roleType、gender、vip、bindGameGold、gameGold、fighting、status 具体参考博客 */ WingProxy::SetServerId(服务器ID); WingProxy::SetGameUserId(游戏用户ID); WingProxy::SetLevel(等级); std::wstring strEventName = L"ghw_user_create"; //只有必传参数 std::wstring strEventParams = L"{\"nickname\":\"Gooood\",\"registerTime\":1234567890123}"; //包含非必传参数 //std::wstring strEventParams = L"{\"nickname\":\"Gooood\",\"registerTime\":1234567890123,\"gender\":1,\"roleType\":\"战士\",\"vip\":11,\"bindGameGold\":25467,\"gameGold\":98797878,\"fighting\":515747966,\"status\":1}"; WingProxy::PostEvent(strEventName, strEventParams); |
4.7.3.3.ghw_user_info_update 更新用户信息
参数名 | 类型 | 说明 | 必填 | 备注 |
---|---|---|---|---|
roleType | std::wstring | 角色类型 | N | |
nickname | std::wstring | 角色名称 | Y | 无昵称时,可填写空字符串 |
vip | int | 等级 | N | |
status | int | 状态 | N | 状态标识,-1:锁定,1:未锁定 |
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/* ghw_user_info_update 更新用户信息 事件描述 : 更新用户信息 事件作用 : 更新用户信 建议触发点 : 玩家信息更新时 调用前提 : 需要先调用setServerId、setGameUserId、setNickname接口 必填字段 : nickname std::wstring 昵称 可选字段 : roleType std::wstring 角色类型 vip int 等级 status int 状态 状态标识,-1:锁定,1:未锁定 */ WingProxy::SetServerId(服务器ID); WingProxy::SetGameUserId(游戏用户ID); WingProxy::SetNickname(用户昵称); std::wstring strEventName = L"ghw_user_info_update"; //只有必传参数 std::wstring strEventParams = L"{\"nickname\":\"Gooood\"}"; //包含非必传参数 //std::wstring strEventParams = L"{\"nickname\":\"Gooood\",\"roleType\":\"战士\",\"vip\":11,\"status\":1}"; WingProxy::PostEvent(strEventName, strEventParams); |
4.7.3.4.ghw_level_achieved 等级增长事件
说明:统计玩家等级增长事件,达到等级时调用。
参数名 | 类型 | 说明 | 必填 | 备注 |
---|---|---|---|---|
score | long long | 账户分数 | N | |
fighting | long long | 战斗力 | N |
注意:发送ghw_level_achieved事件前需调用设置用户等级level接口更新用户等级信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<br />/* ghw_level_achieved 更新玩家等级 事件描述 : 更新玩家等级 事件作用 : 更新玩家等级,后台根据此字段更新玩家等级 建议触发点 : 玩家达到新的等级时 调用前提 : 需要先调用SetLevel接口更新玩家等级 必填字段 : 可选字段 : score long long 账户分数 fighting long long 战斗力 */ WingProxy::SetLevel(等级); std::wstring strEventName = L"ghw_level_achieved"; // 可选参数 // std::wstring strEventParams = L"{\"score\":112344656,\"fighting\":12345656}"; WingProxy::PostEvent(strEventName); |
4.7.4.自定义事件
如果发送的事件不属于预定义事件范围,事件发送时会自动补上ghw_self_前缀,例如关键等级5的事件名称传入,lv_5,最终发送的事件名称为ghw_self_lv_5。
4.7.4.1.ghw_self_lv_x关键等级事件
代码示例:
1 2 3 |
// 关键等级事件,ghw_self_lv_x,关键等级为5时发送lv_5即可 WingProxy::PostEvent(L"lv_5"); |
4.7.4.2.ghw_self_tutorial_completed完成新手任务
1 2 3 |
// 完成新手任务事件,ghw_self_tutorial_completed,发送tutorial_completed即可 WingProxy::PostEvent(L"tutorial_completed"); |
5.调试日志
SDK的日志默认是关闭状态的,开启日志后会在程序目录下生成winglog.log日志文件,可以查看SDK的日志信息。
开启SDK调试日志:
1.SDK日志的开启需要提供设备的ClientId,在用户的隐藏目录AppData下找到SharedConf配置文件,以文本的形式查看文件可以得到ClientId值。
具体路径:C:\Users\用户名\AppData\Local\WingEpicExeSDK\SharedConf
文本内容参考:{“ClientId”:”5c56b3400000000000000e0a76c72″}
2.把ClientId的值提供给运营,运营在后台操作加入测试设备
3.重启已接入SDK的程序,进行SDK相关操作,即可在winlog.log查看SDK输出的相关日志信息。
6.状态码说明
状态码 | 说明 |
---|---|
200 | 操作成功 |
-400 | 一般错误 |
-401 | SDK未初始化 |
-402 | Epic初始化失败 |
-403 | Epic登录授权超时 |
-404 | Epic登录授权失败 |
-405 | 未登录 |
-500 | 服务器异常 |
-501 | 服务器异常:json解析异常 |
400 | 失败 |
500 | 服务器内部故障 |
501 | 所请求接口或页面未实现 |
4010 | 无效appId: appId不存在或未开启 |
4011 | 无效osign:osign校验失败 |
4012 | 请求已过期:ots校验失败 |
4013 | 第三方平台验证失败 |
4017 | 用户不存在(没有找到) |
4019 | 无效orderId |
4020 | 订单验证失败 |
4023 | 未找到渠道信息 |
4025 | 汇率转换失败 |
4026 | 支付渠道已关闭 |
4029 | 登录渠道已关闭 |
5005 | 该设备不能支付或者不允许支付 |
5006 | 支付过程中出错 |