【好东西】android 手机集成支付宝 开发分享

2024-06-06 03:18

本文主要是介绍【好东西】android 手机集成支付宝 开发分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在Android开发过程中,分享和交流是很重要的环节,在eoeAndroid开发社区每天活跃很多Android开发者,提问,交流,解答,共享!Android论坛-安卓开发论坛-android开发 http://www.eoeandroid.com/ 推荐访问Android开发论坛和更多开发者交流共享,互相学习进步!


手机的在线支付,被认为是2012年最看好的功能,我个人认为这也是移动互联网较传统互联网将会大放光彩的一个功能。

人人有手机,人人携带手机,花钱买东西,不再需要取钱付现,不再需要回家上网银,想买什么,扫描一下,或者搜索一下,然后下单,不找零,直接送到你家,这将是手机支付给我们带来的全新交易体验。
谷歌刚推出了谷歌钱包,这必是我们后面要使用的主要手段,但是鉴于当前国情,我觉得有必要介绍一下android手机集成支付宝功能。 

1.下载官方架包和说明文档
其实官方已经提供了安装指南,下载地址:
https://mobiless.alipay.com/product/product_down_load.htm?code=SECURITY_PAY
里面有有个pdf,详细说明了说用指南,写的比较详细,可以重点参考。


下载下来,我们主要是用到Android(20120104)目录下的alipay_plugin.jar和AppDemo/assets下的alipay_plugin223_0309.apk,这两个文件是我们不能修改的支付宝api和安装包。

2. 商户签约
现在的安全机制,都是这样,客户端需要先和服务端请求验证后才能进行进一步操作,oauth也是如此。
打开https://ms.alipay.com/,登陆支付宝,点击签约入口,选择"应用类产品",填写并等待审核,获取商户ID和账户ID。
签约的时候还要向需要提供实名认证和上传应用,所以我建议先把应用做好了,最后再集成支付宝。


我大概等了1-2天审核,审核是失败的,回复是应用类型啥的应该是"虚拟货币",我改成那个马上自动就审核通过了。

3.密钥配置
解压openssl-0.9.8k_WIN32(RSA密钥生成工具).zip,打开cmd,命令行进入openssl-0.9.8k_WIN32(RSA密钥生成工具)\bin目录下,
(1).执行

?
1
openssl genrsa  -out rsa_private_key.pem 1024

生成rsa_private_key.pem文件。
(2).再执行

?
1
openssl rsa  -in rsa_private_key.pem  -pubout -out rsa_public_key.pem

生成rsa_public_key.pem 文件。
(3).在执行

?
1
openssl pkcs8  -topk8  -inform PEM  -in rsa_private_key.pem  -outform PEM  -nocrypt

将RSA私钥转换成 PKCS8 格式,去掉begin和end那两行,把里面的内容拷贝出来,保存到某个txt中,如rsa_private_pkcs8_key.txt中(我好像没用到这个)。
打开rsa_public_key.pem,即商户的公钥,复制到一个新的TXT中,删除文件头”-----BEGIN PUBLIC KEY-----“与文件尾”-----END PUBLIC KEY-----“还有空格、换行,变成一行字符串并保存该 TXT 文件,然后在网站的“我的商家服务”切换卡下的右边点击“密钥管理”,然后有个"上传商户公钥(RSA)"项,选择上传刚才的TXT文件.
好了,服务器配置OK,因为这一段之前没有截图,现在弄好了又不好截图,如果有不明白的地方请大家参考官方文档。 

4.引用jar和包含安装包
    (1).新建android工程;
    (2).copy上面说的alipay_plugin.jar到工程的libs目录下,并在java build path中通过Add External JARs找到并引用该jar;
    (3).copy上面说的alipay_plugin223_0309.apk安装包到assets目录下,后面配置路径用到。

如果libs和assets目录没有,手动建立者两个目录。

5.调用代码整理
这里我们要严重的参考文档中AppDemo,我们建一个包com.tianxia.lib.baseworld.alipay,把AppDemo的com.alipay.android.appDemo4包下的源码全部copy到刚才我们自己的包下,还有res目录下的资源文件也合并到我们工程res下。
其中AlixDemo.java,ProductListAdapter.java,Products.java是示例类,我们借鉴完后可以删除。
PartnerConfig.java是配置类,配置商户的一些配置参数。
其他的类是严重参考类,直接留下使用。
PartnerConfig.java代码如下

1
2
3
4
5
6
7
8
9
10
11
12
public class PartnerConfig {
     //合作商户ID。用签约支付宝账号登录ms.alipay.com后,在账户信息页面获取。
     public static final String PARTNER = "xxx" ;
     //账户ID。用签约支付宝账号登录ms.alipay.com后,在账户信息页面获取。
     public static final String SELLER = "xxx" ;
     //商户(RSA)私钥 ,即rsa_private_key.pem中去掉首行,最后一行,空格和换行最后拼成一行的字符串
     public static final String RSA_PRIVATE = "xxx" ;
     //支付宝(RSA)公钥  用签约支付宝账号登录ms.alipay.com后,在密钥管理页面获取。
     public static final String RSA_ALIPAY_PUBLIC = "xxx" ;
     //下面的配置告诉应用去assets目录下找安装包
     public static final String ALIPAY_PLUGIN_NAME = "alipay_plugin223_0309.apk" ;
}

AlixDemo中代码是最终的调用代码在onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {}中,下面我们提取其中的核心代码。

6.提取核心调用代码
在AlixDemo.java同目录下新建AlixPay.java,来提取AlixDemo.java的核心代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
package com.tianxia.lib.baseworld.alipay;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.tianxia.lib.baseworld.R;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.widget.Toast;
public class AlixPay {
     static String TAG = "AlixPay" ;
     private Activity mActivity;
     public AlixPay(Activity activity) {
         mActivity = activity;
     }
     private ProgressDialog mProgress = null ;
     // the handler use to receive the pay result.
     private Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
             try {
                 String strRet = (String) msg.obj;
                 switch (msg.what) {
                 case AlixId.RQF_PAY: {
                     closeProgress();
                     BaseHelper.log(TAG, strRet);
                     try {
                         String memo = "memo=" ;
                         int imemoStart = strRet.indexOf( "memo=" );
                         imemoStart += memo.length();
                         int imemoEnd = strRet.indexOf( ";result=" );
                         memo = strRet.substring(imemoStart, imemoEnd);
                         ResultChecker resultChecker = new ResultChecker(strRet);
                         int retVal = resultChecker.checkSign();
                         if (retVal == ResultChecker.RESULT_CHECK_SIGN_FAILED) {
                             BaseHelper.showDialog(
                                     mActivity,
                                     "提示" ,
                                     mActivity.getResources().getString(
                                             R.string.check_sign_failed),
                                     android.R.drawable.ic_dialog_alert);
                         } else {
                             BaseHelper.showDialog(mActivity, "提示" , memo,
                                     R.drawable.infoicon);
                         }
                         
                     } catch (Exception e) {
                         e.printStackTrace();
                         BaseHelper.showDialog(mActivity, "提示" , strRet,
                                 R.drawable.infoicon);
                     }
                 }
                     break ;
                 }
                 super .handleMessage(msg);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     };
     // close the progress bar
     void closeProgress() {
         try {
             if (mProgress != null ) {
                 mProgress.dismiss();
                 mProgress = null ;
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
     public void pay() {
         MobileSecurePayHelper mspHelper = new MobileSecurePayHelper(mActivity);
         boolean isMobile_spExist = mspHelper.detectMobile_sp();
         if (!isMobile_spExist)
             return ;
         if (!checkInfo()) {
             BaseHelper.showDialog(mActivity, "提示" ,
                     "缺少partner或者seller," , R.drawable.infoicon);
             return ;
         }
         try {
             // prepare the order info.
             String orderInfo = getOrderInfo();
             String signType = getSignType();
             String strsign = sign(signType, orderInfo);
             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, mActivity);
             
             if (bRet) {
                 // show the progress bar to indicate that we have started paying.
                 closeProgress();
                 mProgress = BaseHelper.showProgress(mActivity, null , "正在支付" , false ,
                         true );
             } else
                 ;
         } catch (Exception ex) {
             Toast.makeText(mActivity, R.string.remote_call_failed,
                     Toast.LENGTH_SHORT).show();
         }
         
     }
     private boolean checkInfo() {
         String partner = PartnerConfig.PARTNER;
         String seller = PartnerConfig.SELLER;
         if (partner == null || partner.length() <= 0 || seller == null
                 || seller.length() <= 0 )
             return false ;
         return true ;
     }
     // get the selected order info for pay.
     String getOrderInfo() {
         String strOrderInfo = "partner=" + "\"" + PartnerConfig.PARTNER + "\"" ;
         strOrderInfo += "&" ;
         strOrderInfo += "seller=" + "\"" + PartnerConfig.SELLER + "\"" ;
         strOrderInfo += "&" ;
         strOrderInfo += "out_trade_no=" + "\"" + getOutTradeNo() + "\"" ;
         strOrderInfo += "&" ;
         //这笔交易价钱
         strOrderInfo += "subject=" + "\"" + mActivity.getString(R.string.donate_subject) + "\"" ;
         strOrderInfo += "&" ;
         //这笔交易内容
         strOrderInfo += "body=" + "\"" + mActivity.getString(R.string.donate_body) + "\"" ;
         strOrderInfo += "&" ;
         //这笔交易价钱
         strOrderInfo += "total_fee=" + "\"" + "10.00" + "\"" ;
         strOrderInfo += "&" ;
         strOrderInfo += "notify_url=" + "\""
                 + "http://notify.java.jpxx.org/index.jsp" + "\"" ;
         return strOrderInfo;
     }
     // get the out_trade_no for an order.
     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.
     String getSignType() {
         String getSignType = "sign_type=" + "\"" + "RSA" + "\"" ;
         return getSignType;
     }
     // sign the order info.
     String sign(String signType, String content) {
         return Rsa.sign(content, PartnerConfig.RSA_PRIVATE);
     }
     // the OnCancelListener for lephone platform.
     static class AlixOnCancelListener implements
             DialogInterface.OnCancelListener {
         Activity mcontext;
         AlixOnCancelListener(Activity context) {
             mcontext = context;
         }
         public void onCancel(DialogInterface dialog) {
             mcontext.onKeyDown(KeyEvent.KEYCODE_BACK, null );
         }
     }
}

这个类的pay方法就是支付的方法,最简单的不设置的话,调用方法如下:

?
1
2
AlixPay alixPay = new AlixPay(SettingTabActivity. this );
alixPay.pay();

如果没有安装支付宝,它会提示你安装,如果已经安装,它直接让你选择付款:

这说明已经配置成功了。
然后可以删掉那些示例java文件了: AlixDemo.java,ProductListAdapter.java,Products.java。 
你也可以通过调整参数来修改订单信息,如主题,价格等。
另外在BaseHelper的94行:

?
1
dialog.setOnCancelListener( new AlixDemo.AlixOnCancelListener( (Activity)context ) );

需要修改为:

?
1
dialog.setOnCancelListener( new AlixPay.AlixOnCancelListener( (Activity)context ) );

7.注意
我在测试的时候,调用的activity是框在一个ActivityGroup里的(与tabhost类似,据说tabhost也有这个问题),导致MobileSecurePayer.java的pay方法中调用服务的两行代码:

?
mActivity.bindService( new Intent(IAlixPay. class .getName()), mAlixPayConnection, Context.BIND_AUTO_CREATE);
mActivity.unbindService(mAlixPayConnection);

需要修改为:

?
1
2
mActivity.getApplicationContext().bindService( new Intent(IAlixPay. class .getName()), mAlixPayConnection, Context.BIND_AUTO_CREATE);
mActivity.getApplicationContext().unbindService(mAlixPayConnection);

不然会报错java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.android.server.am.ActivityRecord$Token...

8.小结
支付宝的集成比我想象的要复杂一些,比较麻烦,首先需要审核,然后代码需要提取,所以写出来与大家分享。 
在做集成配置的时候,一定要仔细认真,一个地方出错,可能要导致后面查错查很长时间。
因为本人是先集成成功后才写的这篇文章,难免会漏掉一些重要的细节或者步骤,如有不对,请留言指正。 


在Android开发过程中,分享和交流是很重要的环节,在eoeAndroid开发社区每天活跃很多Android开发者,提问,交流,解答,共享!Android论坛-安卓开发论坛-android开发 http://www.eoeandroid.com/ 推荐访问Android开发论坛和更多开发者交流共享,互相学习进步!

这篇关于【好东西】android 手机集成支付宝 开发分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1034945

相关文章

找完工作该补充的东西

首先: 锻炼身体,包括乒乓球,羽毛球,都必须练习,学习,锻炼身体等是一个很重要的与人交际沟通的方式; 打牌,娱乐:会玩是一个人很重要的交际沟通的法宝; 摄影:这个是一个兴趣爱好,也是提高自己的审美,生活品质,当然也是与人沟通的重要途径; 做饭:这个的话就是对自己,对朋友非常有益的一件事情;

[职场] 护理专业简历怎么写 #经验分享#微信

护理专业简历怎么写   很多想成为一名护理方面的从业者,但是又不知道应该怎么制作一份简历,现在这里分享了一份护理方面的简历模板供大家参考。   蓝山山   年龄:24   号码:12345678910   地址:上海市 邮箱:jianli@jianli.com   教育背景   时间:2011-09到2015-06   学校:蓝山大学   专业:护理学   学历:本科

大学湖北中医药大学法医学试题及答案,分享几个实用搜题和学习工具 #微信#学习方法#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式,可以快速查找问题解析,加深对题目答案的理解。 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试、组卷考试、赶快下载吧! 2.彩虹搜题 这是个老公众号了 支持手写输入,截图搜题,详细步骤,解题必备

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

SpringBoot集成Netty,Handler中@Autowired注解为空

最近建了个技术交流群,然后好多小伙伴都问关于Netty的问题,尤其今天的问题最特殊,功能大概是要在Netty接收消息时把数据写入数据库,那个小伙伴用的是 Spring Boot + MyBatis + Netty,所以就碰到了Handler中@Autowired注解为空的问题 参考了一些大神的博文,Spring Boot非controller使用@Autowired注解注入为null的问题,得到

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c