子商户应用

接入 Ping++ 子商户应用接口,仅需要 Ping++ Server SDK 即可。服务器端需要做的就是向 Ping++ 请求创建 Sub App 对象,具体步骤如下:

  1. 设置 API-Key
  2. SDK 验证签名设置
  3. 从服务端发起创建子商户应用请求,获取 Sub App 对象

第一步:设置 API-Key

Ping++ API 交易时需要设置 API-Key,Server SDK 提供了设置的方法。如果你直接使用 API ,需要在 header 中加入 Authorization,格式是 Authorization: Bearer API-Key。

\Pingpp\Pingpp::setApiKey('sk_test_ibbTe5jLGCi5rzfH4OqPW9KC');
Pingpp.apiKey = "sk_test_ibbTe5jLGCi5rzfH4OqPW9KC";
var pingpp = require('pingpp')('sk_test_ibbTe5jLGCi5rzfH4OqPW9KC');
pingpp.api_key = 'sk_test_ibbTe5jLGCi5rzfH4OqPW9KC'
Pingpp.api_key = "sk_test_ibbTe5jLGCi5rzfH4OqPW9KC"
pingpp.Key = "sk_test_ibbTe5jLGCi5rzfH4OqPW9KC"
Pingpp.Pingpp.SetApiKey("sk_test_ibbTe5jLGCi5rzfH4OqPW9KC");

第二步:SDK 验证签名设置

为了进一步增强交易请求的安全性,Ping++ 交易接口针对所有的 POST 和 PUT 请求已经新增 RSA 加密验签功能。如果使用该签名验证功能,你需要生成密钥,然后将私钥配置到你的代码中,公钥上传至 Ping++ 管理平台并启用验签开关。首先你需要本地生成 RSA 公钥和私钥,生成方法请参考:如何获取 RSA 公钥和私钥?

设置请求签名密钥

你需要在代码中设置请求签名的私钥(rsa_private_key.pem),可以读取配置私钥文件的路径或者直接定义变量。你如果通过 API 接口校验的话,需要生成 RSA 签名(SHA256)并在请求头中添加 Pingplusplus-Signature,如果使用 SDK 的话只需要配置私钥即可。

\Pingpp\Pingpp::setPrivateKeyPath(__DIR__ . '/your_rsa_private_key.pem');
Pingpp.privateKeyPath = "/path/to/your_rsa_private_key.pem";
pingpp.setPrivateKeyPath(__dirname + "/your_rsa_private_key.pem");
pingpp.private_key_path = 'your_rsa_private_key.pem'
Pingpp.private_key_path = File.dirname(__FILE__) + '/your_rsa_private_key.pem'
privateKey, err := ioutil.ReadFile("your_rsa_private_key.pem")
Pingpp.Pingpp.SetPrivateKeyPath(@"../../your_rsa_private_key.pem");

上传公钥至 Ping++ 管理平台

设置完代码中的私钥,你需要将已经生成的公钥(rsa_public_key.pem)填写到 Ping++ 管理平台上。 配置路径: 登录 Ping++ 管理平台->点击右上角公司名称->企业面板->开发参数->商户 RSA 公钥->将你的公钥复制粘贴进去并且保存->先启用 Test 模式进行测试->测试通过后启用 Live 模式

rsa_keys_setting

注意: 一旦上传公钥至 Ping++ 管理平台并启用 Live 模式,则验证签名功能即时生效,Ping++ 会立即验证你的真实线上交易验签请求。如果私钥为空或错误,则会交易失败,所以请确保测试模式正常后再启用 Live 开关。

第三步:从服务端发起创建子商户应用请求,获取 Sub App 对象

调用 Ping++ Server SDK 发起创建请求,发起请求所需参数具体可参考 API 文档

$sub_app = \Pingpp\SubApp::create([
'display_name' => 'sub_app_display_name',
'user' => 'user_102',
'metadata' => [
'key' => 'value'
],
'parent_app' => \Pingpp\Pingpp::getAppId(), //父商户应用 ID,必须为平台或者平台下其他的子商户,默认值为平台
]);
echo $sub_app; // 返回子商户应用
exit;
String userId = "sub_app_user_" + System.currentTimeMillis();
String displayName = "sub_app_" + System.currentTimeMillis();
Map<String, Object> params = new HashMap<>();
params.put("user", userId);
params.put("display_name", displayName);
params.put("parent_app", PingppAccountTestData.getAppID()); //父商户应用 ID,必须为平台或者平台下其他的子商户,默认值为平台
// 创建子商户 app 方法
// 参数: params
SubApp obj = SubApp.create(params);
pingpp.subApps.create(APP_ID,{
'display_name': 'Display Name',
'user': 'test_user_for_sub_app',
'metadata': {
'key-1': 'value-1'
},
'description': 'Your description.'
}, function(err, data) {
// YOUR CODE
if (err != null){
console.log(err);
}
});
params = {
'display_name': 'sub_app_display_name',
'user': 'test_user_004',
'metadata': {
'key': 'value'
},
'description': 'Your description',
# 'parent_app': 'app_rDyHSCy14aL8m9ev'
}
sub_app = pingpp.SubApp.create(app=pingpp.app_id, **params)
user_id = Digest::MD5.hexdigest(Time.now.to_i.to_s)[0,12]
display_name = 'sub_app_' + user_id
params = {
:display_name => display_name,
:user => user_id
}
sub_app = Pingpp::SubApp.create(params)
func (c *AppDemo) New() (*pingpp.SubApp, error) {
params := &pingpp.SubAppParams{
DisplayName: "sub_app_wuxinyi_test" + time.Now().Format("060102150405"),
User: "wuxinyi_001" + time.Now().Format("060102150405"),
Metadata: map[string]interface{}{
"key": "value",
},
}
return app.New(c.demoAppID, params)
}
var param = new Dictionary<string, object> {
{"display_name", "sub_app_display_name"},
{"user", "user_0003"},
{"metadata", new Dictionary<string,object>{
{"key", "value"}
}},
{"description", "Your description"},
//{"parent_app", "app_HC4yrTP44OGGLOyL"}
};
var subApp = SubApp.Create(appId, param);

Ping++ 收到创建子商户应用请求后返回给你的服务器一个 Sub App 对象,下面是 Sub App 对象的一个示例:

{
"id": "app_q5eff1jHKqXP9qvr",
"object": "sub_app",
"created": 1488332846,
"display_name": "sub_app_display_name",
"account": "acct_14yPiHyrb1GGub1m",
"description": "Your description",
"metadata": {
"a": "b",
"c": "d"
},
"available_methods": [],
"user": "test_user_031",
"parent_app": "app_rDyHSCy14aL8m9ev",
"level" : 2
}

子商户应用查询

Ping++ 提供接口可以通过子商户应用 ID 查询一个已创建的 Sub App 对象及查询应用下的所有子商户应用。

单个子商户应用查询

$sub_app = \Pingpp\SubApp::retrieve('app_1Gqj58ynP0mHeX1q');
String subAppId = "app_rbDmXLHmLqbTLKm9";
SubApp obj = SubApp.retrieve(subAppId);
pingpp.subApps.retrieve(
APP_ID,
'SUB_APP_ID', // sub_app ID
function(err, data) {
// YOUR CODE
if (err != null){
console.log(err);
}
}
);
sub_app = pingpp.SubApp.retrieve(app=pingpp.app_id, id=sub_app.id)
Pingpp::SubApp.retrieve(get_sub_app_id)
func (c *AppDemo) Get() (*pingpp.SubApp, error) {
return app.Get(c.demoAppID, c.demoSubappID)
}
SubApp.Retrieve(appId, subApp.Id)

子商户应用列表查询

$sub_app_list = \Pingpp\SubApp::all();
Map<String, Object> params = new HashMap<>();
params.put("page", 1);
params.put("per_page", 3);
// 查询子商户 app 列表方法
// 参数: params
SubAppCollection objs = SubApp.list(params);
pingpp.subApps.list(
APP_ID,
{ page: 1, per_page: 3 },
function(err, data) {
// YOUR CODE
if (err != null){
console.log(err);
}
}
);
sub_app_list = pingpp.SubApp.list(app=pingpp.app_id)
Pingpp::SubApp.list(:per_page => 3)
func (c *AppDemo) List() (*pingpp.SubAppList, error) {
params := &pingpp.PagingParams{}
params.Filters.AddFilter("per_page", "", "3")
return app.List(c.demoAppID, params)
}
SubApp.List(appId)

注意事项

通过 API 或 Dashboard 创建子商户应用,子商户和平台一样,也会生成一个独立的 Ping++ 账号。如果子商户有登录管理平台的需求,可以在 Dashboard 上为子商户填写邮箱作为登录账号。