余额转账
接入 Ping++ 发起余额转账,仅需要 Ping++ Server SDK 即可。服务器端需要做的就是向 Ping++ 请求 balance_transfer 接口,并且判断余额转账对象的状态,具体步骤如下:
- 设置 API-Key
- SDK 验证签名设置
- 从服务端发起余额转账请求
- 查询余额转账订单状态
第一步:设置 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 模式
注意: 一旦上传公钥至 Ping++ 管理平台并启用 Live 模式,则验证签名功能即时生效,Ping++ 会立即验证你的真实线上交易验签请求。如果私钥为空或错误,则会交易失败,所以请确保测试模式正常后再启用 Live 开关。
第三步:从服务端发起余额转账请求
调用 Ping++ Server SDK 发起余额转账请求,发起请求所需参数具体可参考 API 文档
$balance_transfer = \Pingpp\BalanceTransfer::create( [ 'amount' => 10, // 用户收到转账的余额,单位:分 'user_fee' => 0, // 向发起转账的用户额外收取的手续费,单位:分 'user' => 'user_001', // 发起转账的用户 ID(可以是 C类用户 或 B类用户,但不能填 0) 'recipient' => '0', // 接收转账的用户 ID(可以是 C类用户 或 B类用户,可以为 0) 'order_no' => substr(md5(time()), 0, 10), // 商户订单号,必须在商户系统内唯一 'description' => 'Your description', // 描述 'metadata' => [], // metadata 元数据 ] );
Map<String, Object> params = new HashMap<String, Object>(); params.put("user", "test_user_001"); params.put("recipient", "test_user_003"); params.put("amount", 10); params.put("order_no", "2017" + System.currentTimeMillis()); params.put("description", "Balance transfer description."); // 创建 balance_transfer 方法 // 参数: params BalanceTransfer obj = BalanceTransfer.create(params);
var order_no = new Date().getTime().toString().substr(0, 10);var params_create = { 'user': 'test_user_001', // 发起转账的用户 ID(可以是 customer 或 business,但不能填 0)必传 'recipient': 'test_user_003', // 接收转账的用户 ID(可以是 customer 或 business,可以为 0)必传 'order_no': order_no, // 商户订单号,必须在商户系统内唯一 必传 'user_fee': 0, // 向发起转账的用户额外收取的手续费,单位:分 可选 'amount': 1, // 用户收到转账的余额,单位:分 必传 'description': 'Balance transfer description.' // 描述 可选};pingpp.balanceTransfers.create(APP_ID, params_create, function(err, balanceTransfer) { if (err != null){ console.log('pingpp.balanceTransfers.list fail:', err); } // YOUR CODE});
params = { "amount": 100, # 支付受赠余额,单位:分 "user": "user_test_01", # 发起转账的用户 ID(可以是 customer 或 business,但不能填 0) "recipient": "user_test_02", # 接收转账的用户 ID(可以是 customer 或 business,可以为 0) "order_no": str(int(random.uniform(100000000, 200000000))), # 商户订单号,必须在商户系统内唯一 "description": "Your description", # 描述 "metadata": {} # metadata 元数据 } print 'create balance_bonus', pingpp.BalanceTransfer.create(**params)
params = { :order_no => order_no, # 转账订单号 :amount => 1, # 转账总金额, 人民币单位:分(如订单总金额为 1 元,此处请填 100) :user => existed_user_id_for_balance_transfer, # 转出用户 :recipient => existed_user_id, # 转入用户 :description => "用户间转账" # 描述 } o = Pingpp::BalanceTransfer.create( params, { :app => get_app_id } )
func (c *BalanceTransferDemo) New() (*pingpp.BalanceTransfer, error) { r := rand.New(rand.NewSource(time.Now().UnixNano())) orderno := r.Intn(999999999999999) params := &pingpp.BalanceTransferParams{ Amount: 1, User: "demoUser", Recipient: "demoUser2", Order_no: fmt.Sprintf("%d", orderno), Description: "转账", } return balanceTransfer.New(c.demoAppID, params)}
var createParams = new Dictionary<string, object>{ {"amount",10}, //用户收到转账的余额,单位:分 {"user_fee", 0}, //向发起转账的用户额外收取的手续费,单位:分 {"user", "user_test_01"}, //发起转账的用户 ID(可以是 customer 或 business,但不能填 0) {"recipient", "user_test_02"}, //接收转账的用户 ID(可以是 customer 或 business,可以为 0) {"order_no", new Random().Next(1, 999999999).ToString()}, //商户订单号,必须在商户系统内唯一 {"description", "Your Description"}, // 描述 {"metadata", new Dictionary<string,object>{}} //metadata 元数据};var balanceTransfer = BalanceTransfer.Create(appId, createParams);;
Ping++ 收到余额转账请求后返回给你的服务器一个 Balance Transfers 对象,示例:
{ "id": "311117071315154300000100", "object": "balance_transfer", "app": "app_1Gqj58ynP0mHeX1q", "created": 1496728534, "livemode": false, "status": "succeeded", "amount": 1000, "order_no": "2017071110259981", "user": "user_007", "recipient": "user_008", "user_fee": 0, "user_balance_transaction": "310317060612081500000101", "recipient_balance_transaction": "310317060612081500000201", "description": "余额转账", "metadata": {}}
第四步:查询余额转账订单状态
创建余额转账订单时,会实时返回的余额转账 Balance Transfers 的订单状态。如需查询,可以主动调用余额转账查询接口来获得交易的状态。
查询 Balance Transfer 对象
$balance_transfer = \Pingpp\BalanceTransfer::retrieve('661170807435256330240000');
BalanceTransfer obj = BalanceTransfer.retrieve("660170821690361139200002");
pingpp.balanceTransfers.retrieve(APP_ID, '660170829413280122880001', // BalanceTransfers ID function(err, balanceTransfer) { if (err != null){ console.log('pingpp.balanceTransfers.retrieve fail:', err); } // YOUR CODE});
pingpp.BalanceTransfer.retrieve("660170815382093332480000")
o = Pingpp::BalanceTransfer.retrieve( existed_balance_transfer_id, { :app => get_app_id } )
func (c *BalanceTransferDemo) Get() (*pingpp.BalanceTransfer, error) { return balanceTransfer.Get(c.demoAppID, c.demoTransferId)}
BalanceTransfer.Retrieve(appId, balanceTransfer.Id);
查询 Balance Transfer 对象列表
$params = [ 'page' => 1, 'per_page' => 10, ]; $balance_transfer = \Pingpp\BalanceTransfer::all($params);
Map<String, Object> params = new HashMap<>(); params.put("page", 1); params.put("per_page", 10); // 查询 balance_transfer 列表方法 // 参数: params BalanceTransferCollection objs = BalanceTransfer.list(params);
var params_list = { 'page': 1, 'per_page': 3};pingpp.balanceTransfers.list(APP_ID, params_list, function(err, data) { if (err != null){ console.log('pingpp.balanceTransfers.list fail:', err); } // YOUR CODE});
pingpp.BalanceTransfer.list()
o = Pingpp::BalanceTransfer.list( { :per_page => 3 }, { :app => get_app_id } )
func (c *BalanceTransferDemo) List() (*pingpp.BalanceTransferList, error) { params := &pingpp.PagingParams{} params.Filters.AddFilter("page", "", "1") //页码,取值范围:1~1000000000;默认值为"1" params.Filters.AddFilter("per_page", "", "2") //每页数量,取值范围:1~100;默认值为"20" return balanceTransfer.List(c.demoAppID, params)}
BalanceTransfer.List(appId, new Dictionary<string, object> { {"page", 1}, {"per_page", 10} } );
注意事项
-
创建 Balance Transfer 余额转账对象,即发起一次余额转账请求。返回的 Balance Transfer 对象中包含转账的结果,可通过
status
字段判断是否转账成功。若status
为 succeeded 则成功。 -
该接口支持的是用户之间的余额转账,不支持你(企业用户)向用户转账,如果要发起 B2C 转账,请使用 企业付款。
-
使用此接口必须保证用户可提现余额大于0。
下一步余额明细