zoukankan      html  css  js  c++  java
  • 转-android 支付宝SDK集成

    http://blog.csdn.net/kroclin/article/details/40746779

    一、前言

    最近做的项目刚好要集成支付宝,上网找了很多资料,介绍得感觉不是很全面,所以我经过这两天的集成,顺便记录下来,学习交流。需要的朋友也可以看看。主要集成还是参照了官方给出的demo,再参照demo进行封装,现在使用起来变得方便好多。而且文章里面还提到了集成过程中遇到的一些问题,当然最后也都解决了。

    二、准备工作

    支付宝开放平台上面也明确了,目前仅仅支持企业用户申请,所以个人开发者就没法使用到。希望支付宝早日可以开放给个人开发者。

    支付宝的集成是相对比较麻烦,其中涉及到了很多东西要弄,要生成私钥公钥等等。文档里面也有详细说到如何如何生成那些东西,不过就是文档的内容量有点多了,看起来总抓不住前后,这里我稍作整理,把android需要用到的提取出来了。

    1、PID

    首先说一下就是支付宝的支付是这样的,企业用户申请了支付宝之后,支付宝就会提供一个合作者id,就是所谓的pid,是2088开头的16位纯数字;

    2、支付宝账户

    这个就是你用于收款用的支付宝账号,要跟申请时候同一个。

    以下几个要运行我附件中的“移动支付接口智能SDK版"中,opensslin文件夹下面的openssl.exe生成,这个是由支付宝提供的

    3、RSA私钥:genrsa -out rsa_private_key.pem 1024

    运行完命令行可以看到bin文件夹下面会生成私钥

    4、RSA公钥:rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    运行完命令行后可以看到生成了公钥

    5、PKCS8编码的私钥:pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

    运行完后,将生成的东西拷贝下来放到文本文件里面就行。这后面要用到的!!包括begin跟end那两句一起存起来

    三、支付过程

    需要进行再封装的主要有下面这个类,做几点说明,AliPayParamsBO是我封装的一个实体类,因为我把刚刚上面讲到的那些PID、私钥啊等等都放在服务端了,这样会比较安全,就算别人反编译了你的项目,那也看不到什么东西,支付宝官方也是这样建议的。测试的时候,可以把这个AliPayParamsBO类,装进你生成的那些参数去测试就好啦,至于OrderBO类,也是我封装的一个类,里面主要包含的是这个订单相关的一些东西,比如商品名称、商品介绍,价格等等,这些在支付过程中都是必要的。

    而需要强调一点就是,产生这个支付过程中,我先是构造好需要请求的参数,注意一点就是我在createOrderInfo()方法中对参数进行构造,但是 sign、sign_type 两个参数先不要参与,因为这两个参数不需要参与签名,等前面那些参数构造好了之后,签完名再将sign、sign_type 两个参数构造进去,再进行支付。

    [java] view plaincopy
     
    1. import java.io.UnsupportedEncodingException;  
    2. import java.net.URLEncoder;  
    3.   
    4. import android.os.Handler;  
    5. import android.os.Message;  
    6.   
    7. import com.alipay.android.app.sdk.AliPay;  
    8. import com.common.ui.BaseActivity;  
    9. import com.common.utils.CLog;  
    10. import com.onecity.cs.bo.AliPayParamsBO;  
    11. import com.onecity.cs.bo.OrderBO;  
    12.   
    13. /** 
    14.  * @author 林楷鹏 
    15.  * @description 支付宝相关操作 
    16.  * @create 2014-11-1下午12:11:20 
    17.  *  
    18.  */  
    19. public class AlipayUtil {  
    20.       
    21.     private static final String TAG = "PayActivity";  
    22.     public static final int RQF_PAY = 1;  
    23.     public static final int RQF_LOGIN = 2;  
    24.       
    25.       
    26.     public static void pay(final BaseActivity activity, AliPayParamsBO aliPayBO, OrderBO orderBO, final Handler handler){  
    27.         try {  
    28.             String info = createOrderInfo(orderBO, aliPayBO);  
    29.             String sign = Rsa.sign(info, aliPayBO.getPrivate_key_pkcs8());  
    30.             sign = URLEncoder.encode(sign, "utf-8");  
    31.             info += "&sign="" + sign + ""&" + getSignType();  
    32.             CLog.log("ExternalPartner", "start pay");  
    33.             // start the pay.  
    34.             CLog.log(TAG, "info = " + info);  
    35.   
    36.             final String orderInfo = info;  
    37.             new Thread() {  
    38.                 public void run() {  
    39.                     AliPay alipay = new AliPay(activity, handler);  
    40.                       
    41.                     //设置为沙箱模式,不设置默认为线上环境  
    42.                     //alipay.setSandBox(true);  
    43.   
    44.                     String result = alipay.pay(orderInfo);  
    45.                     CLog.log(TAG, "result = " + result);  
    46.                     Message msg = handler.obtainMessage();  
    47.                     msg.what = RQF_PAY;  
    48.                     msg.obj = result;  
    49.                     handler.sendMessage(msg);  
    50.                 }  
    51.             }.start();  
    52.   
    53.         } catch (Exception ex) {  
    54.             ex.printStackTrace();  
    55.         }  
    56.     }  
    57.   
    58.     /** 
    59.      * 封装订单信息 
    60.      * @param orderBO 
    61.      * @return 
    62.      * @throws UnsupportedEncodingException 
    63.      */  
    64.     private static String createOrderInfo(OrderBO orderBO, AliPayParamsBO aliPayBO)  
    65.             throws UnsupportedEncodingException {  
    66.         StringBuilder sb = new StringBuilder();  
    67.         sb.append("partner="");  
    68.         sb.append(aliPayBO.getPid());  
    69.         sb.append(""&out_trade_no="");  
    70.         sb.append(orderBO.getOrder_sn());  
    71.         sb.append(""&subject="");  
    72.         sb.append(orderBO.getSubject());  
    73.         sb.append(""&body="");  
    74.         sb.append(orderBO.getBody());  
    75.         sb.append(""&total_fee="");  
    76.         sb.append(/*orderBO.getAmount()*/"0.01");  
    77.         sb.append(""¬ify_url="");  
    78.   
    79.         // 网址需要做URL编码  
    80.         sb.append(URLEncoder.encode(aliPayBO.getNotify_url(), "utf-8"));  
    81.         sb.append(""&service="mobile.securitypay.pay");  
    82.         sb.append(""&_input_charset="UTF-8");  
    83.         sb.append(""&return_url="");  
    84.         sb.append(URLEncoder.encode("http://m.alipay.com", "utf-8"));  
    85.         sb.append(""&payment_type="1");  
    86.         sb.append(""&seller_id="");  
    87.         sb.append(aliPayBO.getAccount());  
    88.   
    89.         // 如果show_url值为空,可不传  
    90.         // sb.append(""&show_url="");  
    91.         sb.append(""&it_b_pay="1m");  
    92.         sb.append(""");  
    93.   
    94.         return new String(sb);  
    95.     }  
    96.     /** 
    97.      * 获取sign_type参数信息,因为该参数不需要参加签名 
    98.      * @return 
    99.      */  
    100.     private static String getSignType() {  
    101.         return "sign_type="RSA"";  
    102.     }  
    103. }  

    遇到的问题:整个过程还是比较顺利的,一开始我是使用了4.0系统的手机进行测试,也能够正常使用。但是跑给同事手机之后,问题出现了,居然出现了。。点击支付的时候始终唤不起支付页面,还报了 failure calling remote service 异常,然后就挺纳闷,查了代码发现好像没啥问题。

    马上去打印log,看到了如下问题:

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

    还是编码问题。

    [java] view plaincopy
     
    1. public static String sign(String content, String privateKey) {  
    2.         String charset = "UTF-8";  
    3.         try {  
    4.             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(  
    5.                     Base64.decode(privateKey));  
    6.             KeyFactory keyf = KeyFactory.getInstance("RSA");  
    7.             PrivateKey priKey = keyf.generatePrivate(priPKCS8);  
    8.   
    9.             java.security.Signature signature = java.security.Signature  
    10.                     .getInstance(SIGN_ALGORITHMS);  
    11.   
    12.             signature.initSign(priKey);  
    13.             signature.update(content.getBytes(charset));  
    14.   
    15.             byte[] signed = signature.sign();  
    16.   
    17.             return Base64.encode(signed);  
    18.         } catch (Exception e) {  
    19.             e.printStackTrace();  
    20.             System.out.println("Exception="+e.getMessage());  
    21.         }  
    22.   
    23.         return null;  
    24.     }  


    然后我就突然想到了上面生成的  “PKCS8编码的私钥”,然后将刚刚上面那个AlipayUtil类的pay方法里面的

    [java] view plaincopy
     
    1. String sign = Rsa.sign(info, aliPayBO.getPrivate_key_pkcs8());  


    签名时用的就是 “PKCS8编码的私钥”(原本出问题是用到RSA私钥),代码中改过来了。这次就行了啦,无论4.0以下还是以上通杀。界面如下:

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

     

  • 相关阅读:
    《Machine Learning in Action》—— 白话贝叶斯,“恰瓜群众”应该恰好瓜还是恰坏瓜
    《Machine Learning in Action》—— 女同学问Taoye,KNN应该怎么玩才能通关
    《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”
    深度学习炼丹术 —— Taoye不讲码德,又水文了,居然写感知器这么简单的内容
    《Machine Learning in Action》—— 浅谈线性回归的那些事
    《Machine Learning in Action》—— 懂的都懂,不懂的也能懂。非线性支持向量机
    《Machine Learning in Action》—— hao朋友,快来玩啊,决策树呦
    《Machine Learning in Action》—— 剖析支持向量机,优化SMO
    《Machine Learning in Action》—— 剖析支持向量机,单手狂撕线性SVM
    JVM 字节码指令
  • 原文地址:https://www.cnblogs.com/awkflf11/p/4609186.html
Copyright © 2011-2022 走看看