Android 移动支付插件demo(主应用+支付插件)

来源:互联网 发布:无敌淘宝网 编辑:程序博客网 时间:2024/04/30 01:15

     本文主要讲解下类似于支付宝、银联支付的第三方支付插件开发流程(应用调用支付插件流程+支付插件主逻辑开发)。

一、首先介绍下什么是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;@Overridepublic 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;}@Overridepublic String prePay(String pre) throws RemoteException {// TODO Auto-generated method stubreturn null;}@Overridepublic void registerCallback(IRemoteServiceCallback callback)throws RemoteException {iCallback = callback;}@Overridepublic String test() throws RemoteException {return null;}@Overridepublic void unregisterCallback(IRemoteServiceCallback callback)throws RemoteException {iCallback = null;}}@Overridepublic IBinder onBind(Intent intent) {return new MIPayService() ;}@Overridepublic void onCreate() {super.onCreate();} @Overridepublic void onDestroy() {super.onDestroy();}}
我们通过实现IPayService类,在pay方法中读取从主应用中传来的支付订单信息(orderInfo),调用IRemoteServiceCallback的startactivity方法进入插件页面进行业务操作,然后建立while循环一直等待插件业务处理后的支付结果,得到支付结果后跳出循环,把支付结果返回给主应用。

2、支付插件端的主要逻辑已经完成了,接下来我们介绍主应用调用插件方法,工程截图如下:


把支付插件端的IPayService和IRemoteServiceCallback连包一起拷贝到主应用要(保持包名一致),一般第三方支付都会打包成jar包供主应用调用,下面贴下主应用调用示例:

public class TextActivity extends Activity{private MobileSecurePayHelper mspHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mspHelper = new MobileSecurePayHelper(this);findViewById(R.id.Button01).setOnClickListener(new OnClickListener() {@Overridepublic 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. */@Overridepublic boolean isHideLoadingScreen() throws RemoteException {return false;}/** * when the current trade is finished or cancelled, call back this * method. */@Overridepublic void payEnd(boolean arg0, String arg1) throws RemoteException {}};
3、demo运行流程:把RemoteServiceText工程的apk安装包复制到RemoteClientText的assets文件中中,然后运行RemoteClientText工程,就介绍到这里,如有需要可以自己下载代码看看。
代码下载:http://download.csdn.net/detail/lukejun1988/7368517


0 0