## 准备工作
1. 要有一个支付宝账号
2. 去http://ms.alipay.com 登录和自助签约 “无线部-自助签约-手机安全支付”;
3. 完成后登录 ms.alipay.com 在“我的产品页” 会见到 账户信息像以下内容
账户名:abc@xxx.com
账户ID:208800*******993
合作商户ID:2088*******993
4. 这个时候先不管密钥管理,先去下载SDK包和文档,
下载地址 https://mobiless.alipay.com/product/product_down_load.htm?product_id=1
解压出以下东东备用
- DEMO项目 //里面有好多现成的类,好东西~
- mobile_sp.jar //支付的类库
- mobile_sp.apk //支付宝安全支付控件,手机支付的前提,可捆绑在应用安装包内支付前检测和提示用户安装
- RSA密钥的W32生成工具 //不解释... 交易流程sign用
5. 按文档说明生成商家私钥、公钥对,再将私钥转换为 PKCS8 格式,备用~
6. 回到 ms.alipay.com 进入账号信息下的密钥管理,上传刚生成的商家公钥,获得 AliPay的对应公钥,备用~
(注意不要混淆 商家pub_key 和Ali_pub_key)
## 准备工作 part.2
呃,还得准备准备,刚才说了DEMO里面有很多好东西,可以直接拿来就用,省下不少爬文档和代码的时间省力又省心..有用的是
- AlixId.java
- Base64.java
- BaseHelper.java
- MobileSecurePayer.java
- MobileSecurePayHelper.java
- NetworkManager.java
- ResultChecker.java
- Rsa.java
全部拿出来扔到我们自己的项目包内,然后逐一来看看
AlixId.java ——这个不需要动,只是一些静态的全局变量;
Base64.java ——编码算法,不动;
Rsa.java ——同上,不动;
BaseHelper.java ——一些调用 ProgressDialog AlertDialog 还有格式转换的现成的方法,不动;
MobileSecurePayer.java ——不用改动,里面的 pay((String, Handler, int, Activity) ,支付用它;
MobileSecurePayHelper.java ——这里要注意,捆绑安装支付控件的话,要把mobile_sp.apk 放到项目 assets 路径下,文件名可以改别的随便,但要注意与源码中52行 cachePath 文件名一致,还有 retrieveApkFromAssets()中的第二个文件名参数一致。若还打算提供在线下载安装控件的话还要更改 apkUrl ,url根据实际情况修改。其余的不用动,是一些检验、安装安全控件的方法;
NetworkManager.java ——不用动,上面如果启用了在线下载安装控件,就要用到这个包实现下载。
ResultChecker.java ——支付结果的解释和校验用,留意 Rsa.doCheck() 的第三个参数,这里要用的是 Ali_pub_key;
## 开工集成
public class Pay extends Activity {
Spinner spPrice; //下拉菜单,有几个不同金额的支付项目选择
Button btAlipayl; //支付按钮
ProgressDialog pd; //提示Loading信息用
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pay);
//绑定实例
spPrice = (Spinner) findViewById(R.id.sp_pay);
btAlipay = (Button) findViewById(R.id.bt_pay_alipay);
pd = new ProgressDialog(this);
pd.setCancelable(false);
//点击支付按钮
btAlipay.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
// check to see if the MobileSecurePay is already installed. 没有支付安全控件的话提示安装
MobileSecurePayHelper mspHelper = new MobileSecurePayHelper(Pay.this);
boolean isMobile_spExist = mspHelper.detectMobile_sp();
if( !isMobile_spExist )
return;
// start pay for this order.
try
{
// prepare the order info.
String orderInfo = getOrderInfo(spPrice.getSelectedItemPosition()); //组织要发去支付接口的数据,这里传递了一个下拉菜单的选中序号,我在Array.xml仲分别定义了下拉菜单各项对应的商品名称、详情、价格数组
String strsign = Rsa.sign(orderInfo,getString(R.string.privateKey_Rsa)); //rsa算法,文档说支持md5,我用出错不清楚原因,换回来了
strsign = URLEncoder.encode(strsign);
String info = orderInfo
+ "&sign=" + "\"" + strsign + "\""
+ "&" + getSignType();
// start the pay. 支付
MobileSecurePayer msp = new MobileSecurePayer();
boolean bRet = msp.pay(info, mHandler, AlixId.RQF_PAY, Pay.this);
if( bRet )
{// 尝试收起ProgressDialog
try
{ if( pd != null ) pd.dismiss(); }
catch(Exception e)
{e.printStackTrace(); }
//然后投放支付中的提示
pd.setMessage("正在支付");
pd.show();
}
else ;
}
catch (Exception ex)
{showMsg(getString(R.string.remote_call_failed), false); }
} });
}
//Alipay 的函数族
// get the selected order info for pay. 组织交易数据
String getOrderInfo(int arg2)
{
//以下内容在string.xml 或Array.xml中定义,参考SDK文档
String strOrderInfo = "partner=" + "\"" + getString(R.string.partner) + "\"";
strOrderInfo += "&";
strOrderInfo += "seller=" + "\"" + getString(R.string.seller) + "\"";
strOrderInfo += "&";
strOrderInfo += "out_trade_no=" + "\"" + getOutTradeNo() + "\"";
strOrderInfo += "&";
strOrderInfo += "subject=" + "\"" + getString(R.string.subject) + "\"";
strOrderInfo += "&";
strOrderInfo += "body=" + "\"" + getResources().getStringArray(R.array.pay_name)[arg2] + "\"";
strOrderInfo += "&";
strOrderInfo += "total_fee=" + "\"" + getResources().getStringArray(R.array.pay_ap)[arg2] + "\"";
strOrderInfo += "&";
strOrderInfo += "notify_url=" + "\"" + getString(R.string.notify_url) + "\"";
return strOrderInfo;
}
// get the out_trade_no for an order.根据文档生成一个不重复的商家交易号ID
String getOutTradeNo()
{
SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss");
Date date = new Date();
String strKey = format.format(date);
java.util.Random r = new java.util.Random();
strKey = strKey + r.nextInt();
strKey = strKey.substring(0, 15);
return strKey;
}
// get the sign type we use. 定义签名的算法,这里用了RSA
String getSignType()
{
String getSignType = "sign_type=" + "\"" + "RSA" + "\"";
return getSignType;
}
// the handler use to receive the pay result. 接收响应支付结果的 Handler
private Handler mHandler = new Handler()
{
public void handleMessage(Message msg)
{
try
{
String strRet = (String)msg.obj; //这个是交易结果返回的信息由几部分组成,如: resultStatus={};memo={};result={}
switch (msg.what)
{
case AlixId.RQF_PAY:
{
//如果支付中提示仍在,收起
try
{if( pd != null ) pd.dismiss();}
catch(Exception e)
{e.printStackTrace(); }
//把返回的结果拆包..解析成各部分信息,包括交易结果的状态码、错误信息等
try
{
String memo = "memo=";
int imemoStart = strRet.indexOf("memo=");
imemoStart += memo.length();
int imemoEnd = strRet.indexOf(";result=");
memo = strRet.substring(imemoStart, imemoEnd);
BaseHelper.showDialog(PayForm.this, "提示", memo, R.drawable.icon);
// handle result
ResultChecker resultChecker = new ResultChecker(strRet);
boolean isPayOk = resultChecker.isPayOk(); //这种是严谨的验证支付结果是否成功的方法,不严谨的可以只检测状态码是否9000详情参考文档说明
if(isPayOk){//支付成功了,以下该干啥干啥...
... ...
}else ; //支付不成功的处理...
}
catch(Exception e)
{ e.printStackTrace(); }
}
break;
}
super.handleMessage(msg);
}
catch(Exception e)
{e.printStackTrace();}
} };
}