/*
* Copyright (C) 2010 The MobileSecurePay Project
* All right reserved.
* author: shiqun.shi@alipay.com
*/
package com.mzeat.alipay;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import com.alipay.android.app.IAlixPay;
import com.alipay.android.app.IRemoteServiceCallback;
/**
* 和安全支付服务通信,发送订单信息进行支付,接收支付宝返回信息
*
*/
public class MobileSecurePayer {
static String TAG = "MobileSecurePayer";
Integer lock = 0;
IAlixPay mAlixPay = null;
boolean mbPaying = false;
Activity mActivity = null;
// 和安全支付服务建立连接
private ServiceConnection mAlixPayConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
//
// wake up the binder to continue.
// 获得通信通道
synchronized (lock) {
mAlixPay = IAlixPay.Stub.asInterface(service);
lock.notify();
}
}
public void onServiceDisconnected(ComponentName className) {
mAlixPay = null;
}
};
/**
* 向支付宝发送支付请求
*
* @param strOrderInfo
* 订单信息
* @param callback
* 回调handler
* @param myWhat
* 回调信息
* @param activity
* 目标activity
* @return
*/
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 (mAlixPay == null) {
// 绑定安全支付服务需要获取上下文环境,
// 如果绑定不成功使用mActivity.getApplicationContext().bindService
// 解绑时同理
mActivity.getApplicationContext().bindService(
new Intent(IAlixPay.class.getName()), mAlixPayConnection,
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 mAlixPay.Pay()
// will fail.
// 等待安全支付服务绑定操作结束
// 注意:这里很重要,否则mAlixPay.Pay()方法会失败
synchronized (lock) {
if (mAlixPay == null)
lock.wait();
}
// register a Callback for the service.
// 为安全支付服务注册一个回调
mAlixPay.registerCallback(mCallback);
// call the MobileSecurePay service.
// 调用安全支付服务的pay方法
String strRet = mAlixPay.Pay(strOrderInfo);
BaseHelper.log(TAG, "After Pay: " + strRet);
// set the flag to indicate that we have finished.
// unregister the Callback, and unbind the service.
// 将mbPaying置为false,表示支付结束
// 移除回调的注册,解绑安全支付服务
mbPaying = false;
mAlixPay.unregisterCallback(mCallback);
mActivity.getApplicationContext().unbindService(
mAlixPayConnection);
// 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;
}
/**
* This implementation is used to receive callbacks from the remote service.
* 实现安全支付的回调
*/
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 {
}
};
}