本文主要讲解下类似于支付宝、银联支付的第三方支付插件开发流程(应用调用支付插件流程+支付插件主逻辑开发)。
一、首先介绍下什么是aidl和icp:
aidl是 Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口;
icp:interprocess communication :内部进程通信。
二、支付插件开发要先掌握aidl使用方法,下面我来介绍下支付插件开发的流程:
1、我们需要创建一个支付插件工程,如图所示:
在IPayService.aidl中我们定义了支付、注册回调、注销回调等方法,代码如下:
package com.lukejun.app;
import com.lukejun.app.IRemoteServiceCallback;
interface IPayService {
String pay(String orderInfo);
String prePay(String pre);
void registerCallback(IRemoteServiceCallback callback);
String test();
void unregisterCallback(IRemoteServiceCallback callback);
}
IRemoteServiceCallback.aidl就是上面用到的回调接口,其中startActivity方法是从主应用中activity进入支付插件中activity,在插件activity中可做支付业务操作,代码如图:
package com.lukejun.app;
import android.os.Bundle;
interface IRemoteServiceCallback {
void startActivity(String packageName , String className, int iCallingPid, in Bundle bundle);
boolean isHideLoadingScreen();
void payEnd(boolean arg0, String arg1);
}
接下来贴MyRemoteService代码,如图:
public class MyRemoteService extends Service{
public class MIPayService extends IPayService.Stub{
IRemoteServiceCallback iCallback = null;
@Override
public String pay(String orderInfo) throws RemoteException {
if(iCallback != null){
Bundle bundle = new Bundle();
bundle.putString("orderInfo", orderInfo);
iCallback.startActivity(getPackageName(), "com.lukejun.app.ShowActivity", 1, bundle);
}
String result = null;
while (true) {
result = PayResult.getInstance().getResult();
PayResult.getInstance().setResult(null);
if(null != result){
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result;
}
@Override
public String prePay(String pre) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
@Override
public void registerCallback(IRemoteServiceCallback callback)
throws RemoteException {
iCallback = callback;
}
@Override
public String test() throws RemoteException {
return null;
}
@Override
public void unregisterCallback(IRemoteServiceCallback callback)
throws RemoteException {
iCallback = null;
}
}
@Override
public IBinder onBind(Intent intent) {
return new MIPayService() ;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
我们通过实现IPayService类,在pay方法中读取从主应用中传来的支付订单信息(orderInfo),调用IRemoteServiceCallback的startactivity方法进入插件页面进行业务操作,然后建立while循环一直等待插件业务处理后的支付结果,得到支付结果后跳出循环,把支付结果返回给主应用。
2、支付插件端的主要逻辑已经完成了,接下来我们介绍主应用调用插件方法,工程截图如下:
把支付插件端的IPayService和IRemoteServiceCallback连包一起拷贝到主应用要(保持包名一致),一般第三方支付都会打包成jar包供主应用调用,下面贴下主应用调用示例:
public class TextActivity extends Activity{
private MobileSecurePayHelper mspHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mspHelper = new MobileSecurePayHelper(this);
findViewById(R.id.Button01).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
boolean isMobile_spExist = mspHelper.detectMobile_sp();
//检测插件支付安装,如果没有安装提示安装和是否插件有更新。
if (!isMobile_spExist){
return;
}
MobileSecurePayer msp = new MobileSecurePayer();
boolean bRet = msp.pay("content", mHandler, Constants.RQF_PAY,
TextActivity.this);
Log.i(TextActivity.class.getSimpleName(), String.valueOf(bRet));
}
});
}
private Handler mHandler = createHandler();
private Handler createHandler()
{
return new Handler(){
public void handleMessage(Message msg)
{
String strRet = (String) msg.obj;
Toast.makeText(TextActivity.this, strRet, Toast.LENGTH_SHORT).show();
super.handleMessage(msg);
}
};
}
}
下面讲解下pay方法,代码如下:
public boolean pay(final String strOrderInfo, final Handler callback,
final int myWhat, final Activity activity) {
if (mbPaying)
return false;
mbPaying = true;
mActivity = activity;
// bind the service.
// 绑定服务
if (payService == null) {
// 绑定安全支付服务需要获取上下文环境,
// 如果绑定不成功使用mActivity.getApplicationContext().bindService
// 解绑时同理
mActivity.getApplicationContext().bindService(
new Intent("com.lukejun.app.action.MY_REMOTE_SERVICE"),
mSecurePayConnection, Context.BIND_AUTO_CREATE);
}
// else ok.
// 实例一个线程来进行支付
new Thread(new Runnable() {
public void run() {
try {
// wait for the service bind operation to completely
// finished.
// Note: this is important,otherwise the next
// payService.Pay()
// will fail.
// 等待安全支付服务绑定操作结束
// 注意:这里很重要,否则payService.pay()方法会失败
synchronized (lock) {
if (payService == null)
lock.wait();
}
// register a Callback for the service.
// 为安全支付服务注册一个回调
payService.registerCallback(mCallback);
// call the MobileSecurePay service.
// 调用安全支付服务的pay方法
String strRet = payService.pay(strOrderInfo);
BaseHelper.log(TAG, "服务端支付结果:" + strRet);
// set the flag to indicate that we have finished.
// unregister the Callback, and unbind the service.
// 将mbPaying置为false,表示支付结束
// 移除回调的注册,解绑安全支付服务
mbPaying = false;
payService.unregisterCallback(mCallback);
mActivity.getApplicationContext().unbindService(
mSecurePayConnection);
// send the result back to caller.
// 发送交易结果
Message msg = new Message();
msg.what = myWhat;
msg.obj = strRet;
callback.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
// send the result back to caller.
// 发送交易结果
Message msg = new Message();
msg.what = myWhat;
msg.obj = e.toString();
callback.sendMessage(msg);
}
}
}).start();
return true;
}
private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
/**
* This is called by the remote service regularly to tell us about new
* values. Note that IPC calls are dispatched through a thread pool
* running in each process, so the code executing here will NOT be
* running in our main thread like most other things -- so, to update
* the UI, we need to use a Handler to hop over there. 通过IPC机制启动安全支付服务
*/
public void startActivity(String packageName, String className,
int iCallingPid, Bundle bundle) throws RemoteException {
Intent intent = new Intent(Intent.ACTION_MAIN, null);
if (bundle == null)
bundle = new Bundle();
// else ok.
try {
bundle.putInt("CallingPid", iCallingPid);
intent.putExtras(bundle);
} catch (Exception e) {
e.printStackTrace();
}
intent.setClassName(packageName, className);
mActivity.startActivity(intent);
}
/**
* when the msp loading dialog gone, call back this method.
*/
@Override
public boolean isHideLoadingScreen() throws RemoteException {
return false;
}
/**
* when the current trade is finished or cancelled, call back this
* method.
*/
@Override
public void payEnd(boolean arg0, String arg1) throws RemoteException {
}
};
3、demo运行流程:把RemoteServiceText工程的apk安装包复制到
RemoteClientText的assets文件中中,然后运行RemoteClientText工程,就介绍到这里,如有需要可以自己下载代码看看。
代码下载:http://download.csdn.net/detail/lukejun1988/7368517