前言
现在很多应用都需要接入第三方支付sdk,支付方式有很多,常用的支付宝,微信,银联,百度,京东等等,如果一一接入那就太麻烦了,能不能只接入一个sdk但是常用支付方式都能使用呢?ping++帮我们实现了这个功能。这篇博客是我结合开发文档和官方demo写的,使得ping++ sdk的接入非常清晰,下面的代码也是摘自官方demo。
1. ping++简介
ping++是一个聚合支付接口,简单来说,就是它的sdk,就可以使用各种支付方式,而不用自己再一个一个接入。ping++适配了 Android,iOS 和 HTML5 三种移动端平台以及 PC 端网页这4种平台。
- Server SDK
目前 Server SDK 支持 PHP、Java、Python、Node.js、Ruby、Go、C# 七种语言。
- Client SDK
Client SDK 支持 Android 终端、iOS 终端 、手机网页和 PC 网页这四种平台,分别对应 Android、iOS 、 HTML5 和 PC 这四种 Client SDK。
- 壹收款
为了让用户接入有更好的体验,Ping++ 在 Client SDK 的基础上推出了「壹收款」。它提供内嵌支付页面和支付完成页面,不仅进一步降低了接入的开发成本,同时优化了支付流程体验。你可以选择 Server SDK + Client SDK 接入支付,也可以通过壹收款 + Server SDK 接入支付,壹收款在支付中的作用等同于 Client SDK。目前 Ping++ 支持 iOS、Android 和 HTML5 的壹收款,具体可以通过 SDK 交易流程查看壹收款是如何交易的。
Server是服务器端,移动端是Client SDK和壹收款。壹收款其实就是内嵌了这几种支付方式,自己提供了支付方式选择的页面和支付的回调。是下面这个样子:
壹收款有如下缺点:
-
支付方式页面的样式貌似不能改(不确定,如果我说的不对,欢迎指正),就是上面大家看到的那个样子
-
壹收款可能会与友盟、百度地图等其他第三方 jar 包冲突,当同时使用这些 jar 包的时候用户需要根据情况判断保留哪一方的 jar 包。
综上,本篇博客只看Client SDK的 android接入。
ping++支持的android端的支付方式有:支付宝,微信,京东,百度,银联。
ping++有2中模式,Test 模式和Live 模式。
- Test 模式
Test 模式供开发测试时使用。因为 Test 模式把支付流程与渠道参数隔离开,所以开发可以与渠道申请同时进行,从而缩短接入调试时间。Test 模式中发起模拟交易不会调用真实支付控件,支付时客户端会跳转到 Ping++ 提供的模拟支付页面。
- Live 模式
Live 模式是应用上线的模式。该模式下会发生真实的交易,调起真实的支付控件产生真实的资金流动,所以请确保在 Test 模式下所有的功能都测试通过后,再切换到 Live 模式。
我们下面的测试程序使用Test模式。这是效果图:
2. 接入方法
2.1 导入jar包
ping++代码在github上托管,点击下载:PingPlusPlus/pingpp-android
下载完后,把项目pingpp-android-master下的lib文件夹拷到你的项目中,和app在同级目录,然后在seeting.gradle中加入:
include ':lib:pingpp'
include ':lib:bdwallet_pay_sdk'
include ':lib:pingpp_one'
或者 菜单 -> file -> new -> import module,定位到刚才下载的pingpp-android-master下的lib文件夹,分别把这三个项目引入。
注意:
通过import引入的项目都和app项目是同级目录,而第一种方式是把他们都放到lib文件夹中。
在build.gradle中加入:
dependencies {
compile project(':lib:pingpp')
compile project(':lib:pingpp_one')
compile project(':lib:bdwallet_pay_sdk')
}
2.2 加权限
manifest中加入:
2.3 注册 activity
sible" />
2.4 请求服务器,获得 Charge
我们需要向服务器发起请求,来获得json类型的Charge。然后用获取到的Charge去请求pay。
参数是json格式的 String channel 和 int amount。channel即支付方式,amount即支付金额。
charge信息如下:
{
"id": "ch_iPu9qTHSOy1GP88eX1X9afXD",
"object": "charge",
"created": 1464687715,
"livemode": false,
"paid": false,
"refunded": false,
"app": "app_1Gqj58ynP0mHeX1q",
"channel": "alipay",
"order_no": "403c6f0a48a25661",
"client_ip": "101.81.25.208",
"amount": 1,
"amount_settle": 1,
"currency": "cny",
"subject": "Your Subject",
"body": "Your Body",
"extra": {},
"time_paid": null,
"time_expire": 1464774115,
"time_settle": null,
"transaction_no": null,
"refunds": {
"object": "list",
"url": "\/v1\/charges\/ch_iPu9qTHSOy1GP88eX1X9afXD\/refunds",
"has_more": false,
"data": []
},
"amount_refunded": 0,
"failure_code": null,
"failure_msg": null,
"metadata": {},
"credential": {
"object": "credential",
"alipay": {
"orderInfo": "_input_charset=\"utf-8\"&body=\"Your Body\"&it_b_pay=\"2016-06-01 17:41:55\"¬ify_url=\"https%3A%2F%2Fapi.pingxx.com%2Fnotify%2Fcharges%2Fch_iPu9qTHSOy1GP88eX1X9afXD\"&out_trade_no=\"403c6f0a48a25661\"&partner=\"2008476488964232\"&payment_type=\"1\"&seller_id=\"2008476488964232\"&service=\"mobile.securitypay.pay\"&subject=\"Your Subject\"&total_fee=\"0.01\"&sign=\"eVhmMUtLRHViSENTemZUdVAwS0dDYWpM\"&sign_type=\"RSA\""
}
},
"description": null
}
其实,支付最核心的代码是:
Intent intent = new Intent(MainActivity.this, PaymentActivity.class);
intent.putExtra(PaymentActivity.EXTRA_CHARGE, data);
startActivityForResult(intent, REQUEST_CODE_PAYMENT);
而Pingpp
类的createPayment()
方法封装了上述代码,所以下面的例子中和我们直接用这行代码来发起支付请求。
Pingpp.createPayment(ClientSDKActivity.this, data);
注意:
- manifest文件中PaymentActivity必须注册。
- 另外,需要接入哪种支付方式,就在manifest文件中注册对应的activity。
- wx 渠道是通过向微信客户端发起请求进行支付的,要求: 手机必须安装微信。 应用包名和签名必须与填写在微信开放平台上的一致,微信平台上的签名需是 MD5 且不带冒号的格式。 调试的时候必须打包出来测试,否则无法调用微信支付控件。
ClientSDKActivity即当前activity,data即我们从服务器获取到的Charge。
注意:
因为是向服务器请求数据,所以要用
AsyncTask
或者Thread
+Handler
。为了测试方便,我们新建一个ClientSDKActivity,包括记录输入金额的EditText,几个button,分别表示支付宝,微信支付等等。
以支付宝支付为例:
输入金额,点击“支付宝”支付按钮,向服务器发起请求。这里因为篇幅限制,我们只列出一些核心代码,具体的大家看源码。
/**
* 支付支付渠道
*/
private static final String CHANNEL_ALIPAY = "alipay";
//官方给的获取chage的地址,用来模拟服务器
public static final String URL = "http://218.244.151.190/demo/charge";
@Override
public void onClick(View view) {
//支付金额
int amount = 0.01;
// 点击“支付宝”按钮
if (view.getId() == R.id.upmpButton) {
new PaymentTask().execute(new PaymentRequest(CHANNEL_UPACP, amount));
}
}
class PaymentRequest {
//支付方式
String channel;
//支付金额
int amount;
public PaymentRequest(String channel, int amount) {
this.channel = channel;
this.amount = amount;
}
}
class PaymentTask extends AsyncTask {
@Override
protected void onPreExecute() {
//按键点击之后的禁用,防止重复点击
alipayButton.setOnClickListener(null);
}
@Override
protected String doInBackground(PaymentRequest... pr) {
PaymentRequest paymentRequest = pr[0];
String data = null;
String json = new Gson().toJson(paymentRequest);
try {
//向服务请求数据,这里做模拟,url是ping++官方给的测试url,能得到data
//这里的data就是最后我们要拿去请求支付的参数。
data = postJson(URL, json);
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
/**
* 获得服务端的charge,调用ping++ sdk。
*/
@Override
protected void onPostExecute(String data) {
Log.d("charge", data);
//发起支付请求,需要在 onActivityResult 中处理支付返回信息
Pingpp.createPayment(ClientSDKActivity.this, data);
}
}
/**
* onActivityResult 获得支付结果,如果支付成功,服务器会收到ping++ 服务器发送的异步通知。
* 最终支付成功根据异步通知为准
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
alipayButton.setOnClickListener(ClientSDKActivity.this);
//支付页面返回处理
if (requestCode == Pingpp.REQUEST_CODE_PAYMENT) {
if (resultCode == Activity.RESULT_OK) {
String result = data.getExtras().getString("pay_result");
/* 处理返回值
* "success" - payment succeed
* "fail" - payment failed
* "cancel" - user canceld
* "invalid" - payment plugin not installed
*/
}
}
}
2.5 混淆设置
用户进行 apk 混淆打包的时候,为了不影响 Ping++ SDK 以及渠道 SDK 的使用,请在 proguard-rules 中添加一下混淆规则。
-dontwarn com.alipay.**
-keep class com.alipay.** {*;}
-dontwarn com.ta.utdid2.**
-keep class com.ta.utdid2.** {*;}
-dontwarn com.ut.device.**
-keep class com.ut.device.** {*;}
-dontwarn com.tencent.**
-keep class com.tencent.** {*;}
-dontwarn com.unionpay.**
-keep class com.unionpay.** {*;}
-dontwarn com.pingplusplus.**
-keep class com.pingplusplus.** {*;}
-dontwarn com.baidu.**
-keep class com.baidu.** {*;}
-keepclassmembers class * {
@android.webkit.JavascriptInterface ;
}
3. 其他
好了,支付基本的使用我们已经讲完了,live模式这里就不多说了,大家自己去查阅官方文档。红包的使用需要serer端发起,所以暂时不讲,放到后面。
-
微信现金红包、企业转帐、支付宝扫码和微信公众帐号扫码支付的支付流程比较类似,都只需要 Server 端发起请求即可。
-
现金红包红包使用的是 Red Envelopde 对象,企业转帐使用的是 Transfer 对象,而其他的都是使用的 Charge 对象。
参考:
pin++ github地址
ping++官方文档