## 准备工作
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();} } };
}