用Ping++做支付

2017-05-04

支付Ping++

Ping++是一个聚合了主流支付平台(例如:支付宝、微信支付、银联、Apple Pay、招行一网通支付、 百度钱包、京东支付、易宝支付、Visa、MasterCard、JCB等)提供统一化SDK的接口、并可以提供部分支付的数据运维工作的第三方支付平台。

目前类似的支付平台还有:BeanCloud、现在支付等。但是就目前的市场反应而言,首选Ping++。

Ping++支付流程

ping++的使用非常的简单,号称“花费10分钟,让APP拥有支付功能”:

  • 第一、注册Ping++登陆账户
  • 第二、创建应用,并认证:
    • 1、验证企业信息 约2天
    • 2、开通支付渠道 约 1~10工作日
    • 3、发起真实交易 约 1日
  • 第三、 接入Ping++ SDK 并使用
    https://www.pingxx.com/docs/overview/index
    ( 注意支付流程,client端SDK和服务端SDK都要下。)

流程图

Note

  • Ping++是针对2B业务的,所以,注册之后,要提供APP相关的企业信息。不提供个人业务,所以个人应用不能使用。
  • Ping++不支持单纯的client端直接连接Ping++服务器完成支付,所有只有APP没有server端是不能完成支付的。我想这么设计的原因可能是:确保了Ping++的每次支付请求都是来自认证过的商户的server,而不是任意匹配了某些参数条件的其他IP。

可粘贴的例子

Client端:
加上包 npm install pingpp-js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var pingpp = require('pingpp-js');
fetch('get/charge').then(function(response) {
return response.json();
}).then(function(json) {
pingpp.createPayment(json, function(result, err){
if(result === "success"){
//do something
} else if(result === "fail"){
//do something
} else if(result === "cancel"){
//do something
}
});
})

Server端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @param Request $request
*/
public function test()
{
$appId = "app_y9ivL0yHGGSCfj5q";
$appTestKey = "sk_test_zn9iLGj5qPKKSGyzzP54iXHG";
Pingpp::setApiKey($appTestKey);
$charge = Charge::create(array(
'order_no' => '77777777',
'amount' => '100',
'app' => array('id' => $appId),
'channel' => 'alipay',
'currency' => 'cny',
'client_ip' => '127.0.0.1',
'subject' => 'Your Subject',
'body' => 'Your Body'
));

return json_encode($charge);
}

项目中的使用

  • 在项目利用的过程中,我们定义了两张表,一张是orders订单表,一个是user_service用户服务表。orders表记录的是购买渠道、订单号、订单状态等订单相关的记录信息;user_service表存放的则是购买成功的用户,以及用户买了哪些服务,及其服务的类型。由于这两张表要保持高度的数据一致性,所以,加了事务。

  • 为了让整个支付流程有据可查,支付的每个环节都打了日志,放入的单独的日志文件中。日志命名payment。如下图:

需要注意的技术细节

webhooks:

  • Ping++的webhooks是需要自己手动去设置的,设置的时候一定要注意咱们的url地址是http还是https,回调url写准确。
  • 再就是虽然webhooks在设置通知事件的时候,写了这么一大堆 但是其实官方只支持: 只有九种。写的时候要注意
  • 还有在回调函数中一定要注明response的状态码,这是ping++判断返回结果是否正确的唯一标识。不加有时候也可以,但是为了代码健壮性,最好是加上。
    所以代码中应该加上以下header
  • Ping++支持直接使用订单号来查询回调的结果正不正确,而且提供了日志功能,解决了回调没法追踪的问题。微信公众号等平台的回调就没有提供这个功能,这个功能很有用。

charge:

  • 这个charge就是在调起支付的时候,Ping++服务器返回的一个调用成功的标记对象。里面有很多支付订单的信息: 这里面对应的信息可以直接查阅文档:https://www.pingxx.com/api#查询-charge-对象 这个charge需要注意的一点是:不可以通过order_no订单号来查询charge对象。所以在的服务端,需要同时记录 charge id 和order_no,并做对应。charge 代表一个订单,在某种意义上可以算作一笔交易。可以直接存下这个charge对象到数据库中。我们现在并没有存charge,建议以后charge对象要存到库中,方便查询。
  • 在调用支付请求charge对象的时候,订单号是不可以重复的。也正是这个原因,咱们现在的支付系统出现了一次支付出现多条数据的情况,Ping++讨论组里提供了一条解决方案,可以作为以后改进的参考:https://help.pingxx.com/article/123347/
  • 在微信中是可以调用支付宝的,Ping++提供了专门的方法: 可以直接访问[alipay_in_weixin](https://github.com/PingPlusPlus/pingpp-js/blob/master/README.md) ,很详细,其实就是帮你做了一个页面,告诉患者:复制链接,跳出浏览器,使用其他浏览器打开。 特别注意一下一点,就是默认调起的都是支付宝的网页版,但是大部分需求应该是调用的支付宝app,如何更改?其实ping++已经想到了这个问题: 在传参数的时候把“app_pay”这个参数指定为true就可以了。

运维相关

  • 如果在微信平台上点击退款,由于没有走Ping++的接口,Ping++是无法知道该笔订单已经退款的,所以Ping++平台的状态是未退款,暂时无法更改,这算是一个Ping++的小漏洞吧。
  • 管理平台上的TEST、LIVE 模式切换只是用来查看不同模式下的数据的。这里的切换不影响代码中的支付执行~ 这一点可能很多人会不习惯

支付流程

现在存在一个问题:第一次支付没钱,又一次支付成功会出现两条数据。 改进版本: 但是这个方式解决了订单重复的问题,但是存在另一个致命问题,不存在“待支付”的类型,寻找待支付的用户只能去Ping++管理后台去看了