博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android调用支付宝的接口方法
阅读量:6757 次
发布时间:2019-06-26

本文共 10152 字,大约阅读时间需要 33 分钟。

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

1.下载官方架包和说明文档 其实官方已经提供了安装指南,下载地址: 里面有有个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).执行

openssl genrsa  -out rsa_private_key.pem 1024

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

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

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

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代码如下:

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的核心代码:

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方法就是支付的方法,最简单的不设置的话,调用方法如下:

AlixPay alixPay = new AlixPay(SettingTabActivity.this);alixPay.pay();

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

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

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

需要修改为:

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);

需要修改为:

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

 

转载于:https://www.cnblogs.com/ckl1988717/archive/2012/11/25/2787752.html

你可能感兴趣的文章
Auto reloading enabled
查看>>
GitHub的使用方法
查看>>
AT3576 Popping Balls
查看>>
springboot入门_多数据源
查看>>
如果一个游戏上面加一个透明层,js能不能实现 点击透明层的任意点 而正常玩游戏...
查看>>
图的m着色问题
查看>>
oracle 查询char类型的数据
查看>>
Vue项目碰到"‘webpack-dev-server’不是内部或外部命令,也不是可运行的程序或批处理文件"报错...
查看>>
Android zxing扫描二维码 为什么有些机型扫描不出来或者很慢?
查看>>
SQLHelp sql数据库的DAL
查看>>
进阶第二课 Python内置函数(补)及自定义函数
查看>>
《王者荣耀》的英雄是怎么诞生的?有没有最厉害的英雄?
查看>>
公司常用几种请求
查看>>
python3 字符串格式化
查看>>
一个字符在字符串中出现最多的次数的打印
查看>>
图片的三级缓存
查看>>
js跨域问题解决方案
查看>>
(八)统一配置中心-Config
查看>>
I.MX6 Android CAN 命令行测试
查看>>
linux shell except tcl login ssh Automatic interaction
查看>>