Android 集成支付宝支付详解

一说到支付宝,相信没有人不知道,生活中付款,转账都会用到。

今天来详细介绍下在Android中如何集成支付宝支付到自己的APP中去。让APP能够拥有方便,快捷的支付功能。

准备工作:

商户在b.alipay.com里进行产品签约
RSA私钥及公钥生成
上传RSA公钥,签名验证
接口调用

一.商户在b.alipay.com里进行产品签约

商户或者开发者到b.alipay.com进行产品签约,获取商户的PID。

二.RSA私钥及公钥生成

生成方式一(推荐):使用支付宝提供的一键生成工具:

Windwos:点击下载

MAC OSX:点击下载

解压打开文件夹,直接运行“支付宝RAS密钥生成器SHAwithRSA1024_V1.0.bat”(WINDOWS)或“SHAwithRSA1024_V1.0.command”(MACOSX),点击“生成RSA密钥”,会自动生成公私钥,然后点击“打开文件位置”,即可找到工具自动生成的密钥。

生成方式二:也可以使用OpenSSL工具命令生成
首先进入OpenSSL工具,再输入以下命令。

[java] view plain copy

  1. <span style="font-size:12px">OpenSSL> genrsa -out rsa_private_key.pem   1024  #生成私钥
  2. OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pkcs8.pem #Java开发者需要将私钥转换成PKCS8格式
  3. OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #生成公钥
  4. OpenSSL> exit #退出OpenSSL程序</span>

经过以上步骤,开发者可以在当前文件夹中(OpenSSL运行文件夹),看到rsa_private_key.pem(RSA私钥)、rsa_private_key_pkcs8.pem(pkcs8格式RSA私钥)和rsa_public_key.pem(对应RSA公钥)3个文件。开发者将私钥保留,将公钥提交给支付宝网关,用于验证签名。以下为私钥文件和公钥文件示例。

注意:对于使用Java的开发者,将pkcs8在console中输出的私钥去除头尾、换行和空格,作为开发者私钥,对于.NET和PHP的开发者来说,无需进行pkcs8命令行操作。

PKCS8处理后的私钥文件示例:

[java] view plain copy

  1. <span style="font-size:12px">-----BEGIN PRIVATE KEY-----
  2. MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN0yqPkLXlnhM+2H/57aHsYHaHXazr9pFQun907TMvmbR04wHChVsKVgGUF1hC0FN9hfeYT5v2SXg1WJSg2tSgk7F29SpsF0I36oSLCIszxdu7ClO7c22mxEVuCjmYpJdqb6XweAZzv4Is661jXP4PdrCTHRdVTU5zR9xUByiLSVAgMBAAECgYEAhznORRonHylm9oKaygEsqQGkYdBXbnsOS6busLi6xA+iovEUdbAVIrTCG9t854z2HAgaISoRUKyztJoOtJfI1wJaQU+XL+U3JIh4jmNx/k5UzJijfvfpT7Cv3ueMtqyAGBJrkLvXjiS7O5ylaCGuB0Qz711bWGkRrVoosPM3N6ECQQD8hVQUgnHEVHZYtvFqfcoq2g/onPbSqyjdrRu35a7PvgDAZx69Mr/XggGNTgT3jJn7+2XmiGkHM1fd1Ob/3uAdAkEA4D7aE3ZgXG/PQqlm3VbE/+4MvNl8xhjqOkByBOY2ZFfWKhlRziLEPSSAh16xEJ79WgY9iti+guLRAMravGrs2QJBAOmKWYeaWKNNxiIoF7/4VDgrcpkcSf3uRB44UjFSn8kLnWBUPo6WV+x1FQBdjqRviZ4NFGIP+KqrJnFHzNgJhVUCQFzCAukMDV4PLfeQJSmna8PFz2UKva8fvTutTryyEYu+PauaX5laDjyQbc4RIEMU0Q29CRX3BA8WDYg7YPGRdTkCQQCG+pjU2FB17ZLuKRlKEdtXNV6zQFTmFc1TKhlsDTtCkWs/xwkoCfZKstuV3Uc5J4BNJDkQOGm38pDRPcUDUh2/
  3. -----END PRIVATE KEY-----</span>

公钥文件示例:

[java] view plain copy

  1. <span style="font-size:12px">-----BEGIN PUBLIC KEY-----
  2. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQWiDVZ7XYxa4CQsZoB3n7bfxLDkeGKjyQPt2FUtm4TWX9OYrd523iw6UUqnQ+Evfw88JgRnhyXadp+vnPKP7unormYQAfsM/CxzrfMoVdtwSiGtIJB4pfyRXjA+KL8nIa2hdQy5nLfgPVGZN4WidfUY/QpkddCVXnZ4bAUaQjXQIDAQAB
  3. -----END PUBLIC KEY-----</span>
三.上传RSA公钥,签名验证

登录支付宝官方网站b.alipay.com,点击导航栏中“我的商家服务”,点击“查询PID、Key”,在“合作伙伴密钥管理”下(根据不同的产品选择对应的入口),点击“RSA加密”后的“添加密钥”,把自己的公钥复制进去

注意:上传的公钥是一行格式,不允许有注释、空格、换行等!

点击“确认上传”,提示:上传成功,说明已经成功上传。

四.接口调用

首先,导入需要的支付宝SDK资源放入商户应用工程的libs目录下

右键 Build Path,将libs目录下的alipaySDK-20150602.jar导入,选中Order and Export,勾选alipaySDK-20151014.jar

拷贝sdk提供的类到工程下:

这几个类也很简单,不需要做打的修改,只改动pay.java里面的就好了

[java] view plain copy

  1. <span style="font-size:12px">// 商户PID
  2. public static final String PARTNER = "";
  3. // 商户收款账号
  4. public static final String SELLER = "";
  5. // 商户私钥,pkcs8格式
  6. public static final String RSA_PRIVATE = "";</span>

添加上对应的参数,java私钥一定要是pkcs8格式的。

[java] view plain copy

  1. <span style="font-size:12px">public class Pay {
  2. // 商户PID
  3. public static final String PARTNER = "";
  4. // 商户收款账号
  5. public static final String SELLER = "";
  6. // 商户私钥,pkcs8格式
  7. public static final String RSA_PRIVATE = "";
  8. private static final int SDK_PAY_FLAG = 1;
  9. private Activity activity;
  10. public Pay(Activity activity) {
  11. this.activity = activity;
  12. }
  13. /**
  14. * call alipay sdk pay. 调用SDK支付
  15. *
  16. */
  17. public void pay(String name, String msg, String orderno, String money,
  18. final Handler handler) {
  19. // 订单
  20. String orderInfo = getOrderInfo(name, msg, orderno, money);
  21. // 对订单做RSA 签名
  22. String sign = sign(orderInfo);
  23. try {
  24. // 仅需对sign 做URL编码
  25. sign = URLEncoder.encode(sign, "UTF-8");
  26. } catch (UnsupportedEncodingException e) {
  27. e.printStackTrace();
  28. }
  29. // 完整的符合支付宝参数规范的订单信息
  30. final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"
  31. + getSignType();
  32. Runnable payRunnable = new Runnable() {
  33. @Override
  34. public void run() {
  35. // 构造PayTask 对象
  36. PayTask alipay = new PayTask(activity);
  37. // 调用支付接口,获取支付结果
  38. String result = alipay.pay(payInfo);
  39. Message msg = new Message();
  40. msg.what = SDK_PAY_FLAG;
  41. msg.obj = result;
  42. handler.sendMessage(msg);
  43. }
  44. };
  45. // 必须异步调用
  46. Thread payThread = new Thread(payRunnable);
  47. payThread.start();
  48. }
  49. /**
  50. * create the order info. 创建订单信息
  51. *
  52. */
  53. public String getOrderInfo(String subject, String body, String orderno,
  54. String price) {
  55. // 签约合作者身份ID
  56. String orderInfo = "partner=" + "\"" + PARTNER + "\"";
  57. // 签约卖家支付宝账号
  58. orderInfo += "&seller_id=" + "\"" + SELLER + "\"";
  59. // 商户网站唯一订单号
  60. orderInfo += "&out_trade_no=" + "\"" + orderno + "\"";
  61. // 商品名称
  62. orderInfo += "&subject=" + "\"" + subject + "\"";
  63. // 商品详情
  64. orderInfo += "&body=" + "\"" + body + "\"";
  65. // 商品金额
  66. orderInfo += "&total_fee=" + "\"" + price + "\"";
  67. // 服务器异步通知页面路径
  68. orderInfo += "?ify_url=" + "\"" + "notify_URL" + "\"";
  69. // 服务接口名称, 固定值
  70. orderInfo += "&service=\"mobile.securitypay.pay\"";
  71. // 支付类型, 固定值
  72. orderInfo += "&payment_type=\"1\"";
  73. // 参数编码, 固定值
  74. orderInfo += "&_input_charset=\"utf-8\"";
  75. // 设置未付款交易的超时时间
  76. // 默认30分钟,一旦超时,该笔交易就会自动被关闭。
  77. // 取值范围:1m~15d。
  78. // m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
  79. // 该参数数值不接受小数点,如1.5h,可转换为90m。
  80. orderInfo += "&it_b_pay=\"30m\"";
  81. // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
  82. // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";
  83. // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空
  84. orderInfo += "&return_url=\"m.alipay.com\"";
  85. // 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)
  86. // orderInfo += "&paymethod=\"expressGateway\"";
  87. return orderInfo;
  88. }
  89. /**
  90. * get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
  91. *
  92. */
  93. public String getOutTradeNo() {
  94. SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss",
  95. Locale.getDefault());
  96. Date date = new Date();
  97. String key = format.format(date);
  98. Random r = new Random();
  99. key = key + r.nextInt();
  100. key = key.substring(0, 15);
  101. return key;
  102. }
  103. /**
  104. * sign the order info. 对订单信息进行签名
  105. *
  106. * @param content
  107. *            待签名订单信息
  108. */
  109. public String sign(String content) {
  110. return SignUtils.sign(content, RSA_PRIVATE);
  111. }
  112. /**
  113. * get the sign type we use. 获取签名方式
  114. *
  115. */
  116. public String getSignType() {
  117. return "sign_type=\"RSA\"";
  118. }
  119. }</span>

其中public void pay(String name, String msg, String orderno, String money,final Handler handler) 方法是调用支付是用到的,传的参数为商户的名字,商品计费名称,订单号和价格,最后一个Handler handler参数是用来接收支付回调发送消息的

支付的线程必须异步调用

// 服务器异步通知页面路径

orderInfo += "?ify_url=" + "\"" + "notify_URL" + "\""; 这里要填写真实的回到地址,是支付宝回调通知服务器的。

orderInfo += "&it_b_pay=\"30m\""; 交易的超时时间默认30分钟,可以自己设置。 其余地方不用太大改动。

[java] view plain copy

  1. <span style="font-size:12px">public class AppActivity extends Activity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_main);
  6. Button btn_pay = (Button) findViewById(R.id.btn_pay);
  7. btn_pay.setOnClickListener(new OnClickListener() {
  8. @Override
  9. public void onClick(View v) {
  10. Pay pay = new Pay(AppActivity.this);
  11. pay.pay("商户名称", "商品计费名称", "订单号", "1", handler);
  12. }
  13. });
  14. }
  15. Handler handler = new Handler() {
  16. @Override
  17. public void handleMessage(Message msg) {
  18. super.handleMessage(msg);
  19. switch (msg.what) {
  20. case 1: {
  21. PayResult payResult = new PayResult((String) msg.obj);
  22. // 支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签
  23. // String resultInfo = payResult.getResult();
  24. String resultStatus = payResult.getResultStatus();
  25. if (TextUtils.equals(resultStatus, "9000")) {
  26. Toast.makeText(AppActivity.this, "支付成功",
  27. Toast.LENGTH_SHORT).show();
  28. } else {
  29. // “8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)
  30. if (TextUtils.equals(resultStatus, "8000")) {
  31. Toast.makeText(AppActivity.this, "支付结果确认中",
  32. Toast.LENGTH_SHORT).show();
  33. } else {
  34. Toast.makeText(AppActivity.this, "支付失败",
  35. Toast.LENGTH_LONG).show();
  36. }
  37. }
  38. break;
  39. }
  40. }
  41. }
  42. };
  43. }</span>

这里是模拟调用支付,点击按钮开始跳转支付,handler收到消息后判断支付状态。9000为支付成功,8000为支付确认中,其余支付失败

支付时出现偶尔出现java.security.spec.InvalidKeySpecException: java.lang.RuntimeException错误,需要调整一下RSA签名私钥,SignUtils 类

把KeyFactory keyf = KeyFactory.getInstance("RSA");

改成KeyFactory keyf = KeyFactory.getInstance("RSA", "BC");

[java] view plain copy

  1. <span style="font-size:12px">public class SignUtils {
  2. private static final String ALGORITHM = "RSA";
  3. private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
  4. private static final String DEFAULT_CHARSET = "UTF-8";
  5. public static String sign(String content, String privateKey) {
  6. try {
  7. PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
  8. Base64.decode(privateKey));
  9. KeyFactory keyf = KeyFactory.getInstance("RSA", "BC");
  10. PrivateKey priKey = keyf.generatePrivate(priPKCS8);
  11. java.security.Signature signature = java.security.Signature
  12. .getInstance(SIGN_ALGORITHMS);
  13. signature.initSign(priKey);
  14. signature.update(content.getBytes(DEFAULT_CHARSET));
  15. byte[] signed = signature.sign();
  16. return Base64.encode(signed);
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. return null;
  21. }
  22. }</span>

公钥私钥一定要传正确才能签名成功

另外的Base64.java和PayResult.java两个类就不用做修改了。

常见的支付错误码如下:

在商户应用工程的AndroidManifest.xml文件里面添加声明:

[java] view plain copy

  1. <span style="font-size:12px">
  2. </span>

[java] view plain copy

  1. <span style="font-size:12px">
  2. </span>

特别注意事项:

测试场景一定注意,安装支付宝钱包则直接跳转app支付,没安装则进入H5网页支付。

未安装支付宝钱包测试如下:

[java] view plain copy

  1. Button btn_pay = (Button) findViewById(R.id.btn_pay);
  2. btn_pay.setOnClickListener(new OnClickListener() {
  3. @Override
  4. public void onClick(View v) {
  5. Pay pay = new Pay(AppActivity.this);
  6. pay.pay("商户名称", "商品计费名称", "1231321321", "1", handler);
  7. }
  8. });

传入参数是我任意填写的。

点击“支付按钮”,开始支付,未安装支付宝钱包,会自动跳转H5网页支付,第一次会输入手机号获取验证码,自动记录。再次进入时直接到确认付款页面,支付中途取消返回结果码为6001。

时间: 2024-11-19 13:46:13

Android 集成支付宝支付详解的相关文章

Android 集成 支付宝支付

调用代码: ALiPayUtil.pay(getActivity(), new ALiPayUtil.PayResponse() { @Override public void success(PayResult payResult) { ToastUtil.show("pay success"); } @Override public void failure(PayResult payResult) { ToastUtil.show("pay failure"

Android集成支付宝接口 实现在线支付

手机的在线支付,被认为是2012年最看好的功能,我个人认为这也是移动互联网较传统互联网将会大放光彩的一个功能. 人人有手机,人人携带手机,花钱买东西,不再需要取钱付现,不再需要回家上网银,想买什么,扫描一下,或者搜索一下,然后下单,不找零,直接送到你家,这将是手机支付给我们带来的全新交易体验.谷歌刚推出了谷歌钱包,这必是我们后面要使用的主要手段,但是鉴于当前国情,我觉得有必要介绍一下android手机集成支付宝功能. 1.下载官方架包和说明文档其实官方已经提供了安装指南,下载地址:https:/

iOS集成支付宝支付

一. 开发前准备 iOS 支付宝SDK下载地址:(内含iOS Android 服务端demo及SDK) http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1 二. 集成支付宝 1.解压支付宝钱包支付接口开发包2.0标准版(iOS 15.0.2).zip(忽略版本号) 2.创建个文件夹,找到如下文件,放到文件夹里.便于将文件统一拷入项目 3.创建项目并将支付宝SDK添加进项目(项目创建不再演示)

Android传输数据时加密详解

Android传输数据时加密详解 ONE Goal , ONE Passion ! ------–MD5加密------- MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译摘要算法.哈希算法),主流编程语言普遍已有MD5实现.将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2.MD3和MD4 MD5算法具有以下特点: 1.压缩性:任意长度的数据,算出的MD5值长度都是固定

微信支付详解

原文:微信支付详解 1.为什么会有两种JS方法可以发起微信支付? 当你登陆微信公众号之后,左边有两个菜单栏,一个是微信支付,一个是开发者中心. 在开发者中心中,有一个微信JS-SDK说明文档. 在此说明文档中,有一个发起微信支付的请求API wx.chooseWXPay({ timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写.但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 nonceStr: '', // 支

Android Touch事件分发详解

Android Touch事件分发详解 先说一些基本的知识,方便后面分析源码时能更好理解. - 所有Touch事件都被封装成MotionEvent对象,包括Touch的位置.历史记录.第几个手指等. 事件类型分为ACTION_DOWN,ACTION_UP,ACTION_MOVE,ACTION_POINTER_DOWN,ACTION_POINTER_UP,ACTION_CANCEL, 每个 一个完整的事件以ACTION_DOWN开始ACTION_UP结束,并且ACTION_CANCEL只能由代码引

SpringSide集成支付宝支付功能

网络购物很流行,那么最流行的支付手段估计应该是支付宝了,那么怎么样将支付宝集成到自己的环境中呢,今天我来讲一下如何在springside框架中集成支付宝支付功能. 首先,我们去支付宝商家服务页面去注册和申请支付功能,并在那里下载sdk开发包https://b.alipay.com/order/productDetail.htm?productId=2012111200373124,这个是支付宝的即时到账收款功能,然后下面有一个流程的介绍,我们选择下面的技术集成,先下载sdk开发包,下载完成之后解

Android:ViewPager扩展详解——带有导航的ViewPagerIndicator(附带图片缓存,异步加载图片)

大家都用过viewpager了, github上有对viewpager进行扩展,导航风格更加丰富,这个开源项目是ViewPagerIndicator,很好用,但是例子比较简单,实际用起来要进行很多扩展,比如在fragment里进行图片缓存和图片异步加载. 下面是ViewPagerIndicator源码运行后的效果,大家也都看过了,我多此一举截几张图: 下载源码请点击这里 ===========================================华丽的分割线==============

给 Android 开发者的 RxJava 详解

作者:扔物线 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个月,我也发现国内越来越多的人开始提及 RxJava .有人说『RxJava 真是太好用了』,有人说『RxJava 真是太难用了』,另外更多的人表示:我真的百度了也谷歌了,但我还是想问: RxJava 到底是什么? 鉴于 RxJava 目前这种既火爆又神秘的现状,而我又在一年的使用