http://blog.csdn.net/kroclin/article/details/40746779java
1、前言android
最近作的项目恰好要集成支付宝,上网找了不少资料,介绍得感受不是很全面,因此我通过这两天的集成,顺便记录下来,学习交流。须要的朋友也能够看看。主要集成仍是参照了官方给出的demo,再参照demo进行封装,如今使用起来变得方便好多。并且文章里面还提到了集成过程当中遇到的一些问题,固然最后也都解决了。安全
2、准备工做app
支付宝开放平台上面也明确了,目前仅仅支持企业用户申请,因此我的开发者就无法使用到。但愿支付宝早日能够开放给我的开发者。学习
支付宝的集成是相对比较麻烦,其中涉及到了不少东西要弄,要生成私钥公钥等等。文档里面也有详细说到如何如何生成那些东西,不过就是文档的内容量有点多了,看起来总抓不住先后,这里我稍做整理,把android须要用到的提取出来了。测试
一、PIDui
首先说一下就是支付宝的支付是这样的,企业用户申请了支付宝以后,支付宝就会提供一个合做者id,就是所谓的pid,是2088开头的16位纯数字;编码
二、支付宝帐户url
这个就是你用于收款用的支付宝帐号,要跟申请时候同一个。spa
如下几个要运行我附件中的“移动支付接口智能SDK版"中,\openssl\bin文件夹下面的openssl.exe生成,这个是由支付宝提供的
三、RSA私钥:genrsa -out rsa_private_key.pem 1024
运行完命令行能够看到bin文件夹下面会生成私钥

四、RSA公钥:rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
运行完命令行后能够看到生成了公钥

五、PKCS8编码的私钥:pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
运行完后,将生成的东西拷贝下来放到文本文件里面就行。这后面要用到的!!包括begin跟end那两句一块儿存起来

3、支付过程
须要进行再封装的主要有下面这个类,作几点说明,AliPayParamsBO是我封装的一个实体类,由于我把刚刚上面讲到的那些PID、私钥啊等等都放在服务端了,这样会比较安全,就算别人反编译了你的项目,那也看不到什么东西,支付宝官方也是这样建议的。测试的时候,能够把这个AliPayParamsBO类,装进你生成的那些参数去测试就好啦,至于OrderBO类,也是我封装的一个类,里面主要包含的是这个订单相关的一些东西,好比商品名称、商品介绍,价格等等,这些在支付过程当中都是必要的。
而须要强调一点就是,产生这个支付过程当中,我先是构造好须要请求的参数,注意一点就是我在createOrderInfo()方法中对参数进行构造,可是 sign、sign_type 两个参数先不要参与,由于这两个参数不须要参与签名,等前面那些参数构造好了以后,签完名再将sign、sign_type 两个参数构造进去,再进行支付。
- import java.io.UnsupportedEncodingException;
- import java.net.URLEncoder;
-
- import android.os.Handler;
- import android.os.Message;
-
- import com.alipay.android.app.sdk.AliPay;
- import com.common.ui.BaseActivity;
- import com.common.utils.CLog;
- import com.onecity.cs.bo.AliPayParamsBO;
- import com.onecity.cs.bo.OrderBO;
-
- public class AlipayUtil {
-
- private static final String TAG = "PayActivity";
- public static final int RQF_PAY = 1;
- public static final int RQF_LOGIN = 2;
-
-
- public static void pay(final BaseActivity activity, AliPayParamsBO aliPayBO, OrderBO orderBO, final Handler handler){
- try {
- String info = createOrderInfo(orderBO, aliPayBO);
- String sign = Rsa.sign(info, aliPayBO.getPrivate_key_pkcs8());
- sign = URLEncoder.encode(sign, "utf-8");
- info += "&sign=\"" + sign + "\"&" + getSignType();
- CLog.log("ExternalPartner", "start pay");
-
- CLog.log(TAG, "info = " + info);
-
- final String orderInfo = info;
- new Thread() {
- public void run() {
- AliPay alipay = new AliPay(activity, handler);
-
-
-
-
- String result = alipay.pay(orderInfo);
- CLog.log(TAG, "result = " + result);
- Message msg = handler.obtainMessage();
- msg.what = RQF_PAY;
- msg.obj = result;
- handler.sendMessage(msg);
- }
- }.start();
-
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
-
-
- private static String createOrderInfo(OrderBO orderBO, AliPayParamsBO aliPayBO)
- throws UnsupportedEncodingException {
- StringBuilder sb = new StringBuilder();
- sb.append("partner=\"");
- sb.append(aliPayBO.getPid());
- sb.append("\"&out_trade_no=\"");
- sb.append(orderBO.getOrder_sn());
- sb.append("\"&subject=\"");
- sb.append(orderBO.getSubject());
- sb.append("\"&body=\"");
- sb.append(orderBO.getBody());
- sb.append("\"&total_fee=\"");
- sb.append(
- sb.append("\"¬ify_url=\"");
-
-
- sb.append(URLEncoder.encode(aliPayBO.getNotify_url(), "utf-8"));
- sb.append("\"&service=\"mobile.securitypay.pay");
- sb.append("\"&_input_charset=\"UTF-8");
- sb.append("\"&return_url=\"");
- sb.append(URLEncoder.encode("http://m.alipay.com", "utf-8"));
- sb.append("\"&payment_type=\"1");
- sb.append("\"&seller_id=\"");
- sb.append(aliPayBO.getAccount());
-
-
-
- sb.append("\"&it_b_pay=\"1m");
- sb.append("\"");
-
- return new String(sb);
- }
-
- private static String getSignType() {
- return "sign_type=\"RSA\"";
- }
- }
遇到的问题:整个过程仍是比较顺利的,一开始我是使用了4.0系统的手机进行测试,也可以正常使用。可是跑给同事手机以后,问题出现了,竟然出现了。。点击支付的时候始终唤不起支付页面,还报了 failure calling remote service 异常,而后就挺纳闷,查了代码发现好像没啥问题。
立刻去打印log,看到了以下问题:


看了以上异常信息以后个人第一反应就是难道个人私钥弄错了,但想一想4.0仍是没问题的啊。后来就追查到了代码中,就在Rsa类中的sign方法,这是支付宝给出的类,我就在异常中将异常信息打印出来,果然

仍是编码问题。
- public static String sign(String content, String privateKey) {
- String charset = "UTF-8";
- try {
- PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
- Base64.decode(privateKey));
- KeyFactory keyf = KeyFactory.getInstance("RSA");
- PrivateKey priKey = keyf.generatePrivate(priPKCS8);
-
- java.security.Signature signature = java.security.Signature
- .getInstance(SIGN_ALGORITHMS);
-
- signature.initSign(priKey);
- signature.update(content.getBytes(charset));
-
- byte[] signed = signature.sign();
-
- return Base64.encode(signed);
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("Exception="+e.getMessage());
- }
-
- return null;
- }
而后我就忽然想到了上面生成的 “PKCS8编码的私钥”,而后将刚刚上面那个AlipayUtil类的pay方法里面的
- String sign = Rsa.sign(info, aliPayBO.getPrivate_key_pkcs8());
签名时用的就是 “PKCS8编码的私钥”(本来出问题是用到RSA私钥),代码中改过来了。此次就好了啦,不管4.0如下仍是以上通杀。界面以下:

好啦,客户端的集成大概就是这样,其余相关的类是按照支付宝demo里面的,就不要展现出来了,须要的到代码下载里面去下载就ok啦~