Android app 第三方支付宝支付接入

支付宝的接入相对比较简单,看看支付宝官网的文档基本都能搞定,但是切记一点让你们的后台也要搞清楚支付宝的流程,不然对接起来是一件很蛋疼的事情。

开始搬砖

注意事项

开发前一定要阅读支付宝官方文档

强烈建议签名等处理在后台处理,我这个是测试是在自己本地写的,不要吐槽

想获取支付宝合作商户ID,及支付宝公钥请点击支付宝链接,生成密钥及PKCS8转码工具在文档中

添加android.permission.INTERNET权限和android.permission.ACCESS_NETWORK_STATE权限

要导入支付宝的包

特别注意事项(坑点)

下载支付宝的官网之后生成你所需要的密钥及PKCS8转码一定要小心

代码:

MainActivity中调起支付

    Pay pay = new Pay(AffirmOrderActivity.this, paymoney);

Pay 类

public class Pay {

                                 /**以下四项这些数值机密填入自己申请的就好**/
    // 商户PID
    public static final String PARTNER = "";
    // 商户收款账号
    public static final String SELLER = "";
    // 商户私钥,pkcs8格式
    public static final String RSA_PRIVATE = "";
    // 支付宝公钥
    public static final String RSA_PUBLIC = "";

    private Activity context;
    private String mgoods,mprice,micon;
    private int mtype;
    private String mOutTradeNo;
    public  Pay(Activity activity, String goods,String goodsmore,String price,String icon,int type, String outTradeNo) {
        context = activity;
        mprice = price;
        pay(price);
    }

    private Handler mHandler = new Handler() {

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SDK_PAY_FLAG: {
                    PayResult payResult = new PayResult((String) msg.obj);
                    /**
                     * 同步返回的结果必须放置到服务端进行验证(验证的规则请看https://doc.open.alipay.com/doc2/
                     * detail.htm?spm=0.0.0.0.xdvAU6&treeId=59&articleId=103665&
                     * docType=1) 建议商户依赖异步通知
                     */
                    String resultInfo = payResult.getResult();// 同步返回需要验证的信息

                    String resultStatus = payResult.getResultStatus();
                    // 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档
                    if (TextUtils.equals(resultStatus, "9000")) {
                        Toast.makeText(context, "支付成功", Toast.LENGTH_SHORT).show();

                    } else {
                        // 判断resultStatus 为非"9000"则代表可能支付失败
                        // "8000"代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)
                        if (TextUtils.equals(resultStatus, "8000")) {
                            Toast.makeText(context, "支付结果确认中", Toast.LENGTH_SHORT).show();

                        } else {
                            // 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误
                            Toast.makeText(context, "支付失败", Toast.LENGTH_SHORT).show();

                        }
                    }
                    break;
                }
                default:
                    break;
            }
        };
    };

    /**
     * call alipay sdk pay. 调用SDK支付
     *
     */
    public void pay(String goods,String goodsmore,String price) {
        if (TextUtils.isEmpty(PARTNER) || TextUtils.isEmpty(RSA_PRIVATE) || TextUtils.isEmpty(SELLER)) {
            new AlertDialog.Builder(context).setTitle("警告").setMessage("需要配置PARTNER | RSA_PRIVATE| SELLER")
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                            //
//                            finish();
                        }
                    }).show();
            return;
        }
        String orderInfo = getOrderInfo(goods, goodsmore, price);

        String sign = sign(orderInfo);

        try {
            /**
             * 仅需对sign 做URL编码
             */
            sign = URLEncoder.encode(sign, "UTF-8");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        /**
         * 完整的符合支付宝参数规范的订单信息
         */
        final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();
        Log.i("lff", "orderInfo == " +orderInfo);
        Log.i("lff", "sign == " +sign);        Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                // 构造PayTask 对象
                PayTask alipay = new PayTask(context);
                // 调用支付接口,获取支付结果
                String result = alipay.pay(payInfo, true);

                Message msg = new Message();
                msg.what = SDK_PAY_FLAG;
                msg.obj = result;
                mHandler.sendMessage(msg);
            }
        };

        // 必须异步调用
        Thread payThread = new Thread(payRunnable);
        payThread.start();
    }

    /**
     * get the sdk version. 获取SDK版本号
     *
     */
    public void getSDKVersion() {
        PayTask payTask = new PayTask(context);
        String version = payTask.getVersion();
        Toast.makeText(context, version, Toast.LENGTH_SHORT).show();
    }

    /**
     * create the order info. 创建订单信息
     *
     */
    private String getOrderInfo(String subject, String body, String price) {

        // 签约合作者身份ID
        String orderInfo = "partner=" + "\"" + PARTNER + "\"";

        // 签约卖家支付宝账号
        orderInfo += "&seller_id=" + "\"" + SELLER + "\"";

        // 商户网站唯一订单号
        orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\"";

        // 商品名称
        orderInfo += "&subject=" + "\"" + subject + "\"";

        // 商品详情
        orderInfo += "&body=" + "\"" + body + "\"";

        // 商品金额
        orderInfo += "&total_fee=" + "\"" + "0.01" + "\"";

        // 服务器异步通知页面路径
//        orderInfo += "&notify_url=" + "\"" + "http://notify.msp.hk/notify.htm" + "\"";
        orderInfo += "&notify_url=" + "\"" + "http://112.74.129.252/new/zfbCallback" + "\"";
        // 服务接口名称, 固定值
        orderInfo += "&service=\"mobile.securitypay.pay\"";

        // 支付类型, 固定值
        orderInfo += "&payment_type=\"1\"";

        // 参数编码, 固定值
        orderInfo += "&_input_charset=\"utf-8\"";

        // 设置未付款交易的超时时间
        // 默认30分钟,一旦超时,该笔交易就会自动被关闭。
        // 取值范围:1m~15d。
        // m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
        // 该参数数值不接受小数点,如1.5h,可转换为90m。
        orderInfo += "&it_b_pay=\"30m\"";

        // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
        // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";

        // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空
        orderInfo += "&return_url=\"m.alipay.com\"";

        // 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)
        // orderInfo += "&paymethod=\"expressGateway\"";
        return orderInfo;
    }

    /**
     * get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
     *
     */
    private String getOutTradeNo() {
//        SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());
//        Date date = new Date();
//        String key = format.format(date);
//
//        Random r = new Random();
//        key = key + r.nextInt();
//        key = key.substring(0, 15);
//        return key;
        return mOutTradeNo;
    }

    /**
     * sign the order info. 对订单信息进行签名
     *
     * @param content
     *            待签名订单信息
     */
    private String sign(String content) {
        return SignUtils.sign(content, RSA_PRIVATE);
    }

    /**
     * get the sign type we use. 获取签名方式
     *
     */
    private String getSignType() {
        return "sign_type=\"RSA\"";
    }

}

其它的工具类,原封不动拷贝过去就好

Base64 类

package com.easyhomework.teacher.ui;

public final class Base64 {

    private static final int BASELENGTH = 128;
    private static final int LOOKUPLENGTH = 64;
    private static final int TWENTYFOURBITGROUP = 24;
    private static final int EIGHTBIT = 8;
    private static final int SIXTEENBIT = 16;
    private static final int FOURBYTE = 4;
    private static final int SIGN = -128;
    private static char PAD = ‘=‘;
    private static byte[] base64Alphabet = new byte[BASELENGTH];
    private static char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];

    static {
        for (int i = 0; i < BASELENGTH; ++i) {
            base64Alphabet[i] = -1;
        }
        for (int i = ‘Z‘; i >= ‘A‘; i--) {
            base64Alphabet[i] = (byte) (i - ‘A‘);
        }
        for (int i = ‘z‘; i >= ‘a‘; i--) {
            base64Alphabet[i] = (byte) (i - ‘a‘ + 26);
        }

        for (int i = ‘9‘; i >= ‘0‘; i--) {
            base64Alphabet[i] = (byte) (i - ‘0‘ + 52);
        }

        base64Alphabet[‘+‘] = 62;
        base64Alphabet[‘/‘] = 63;

        for (int i = 0; i <= 25; i++) {
            lookUpBase64Alphabet[i] = (char) (‘A‘ + i);
        }

        for (int i = 26, j = 0; i <= 51; i++, j++) {
            lookUpBase64Alphabet[i] = (char) (‘a‘ + j);
        }

        for (int i = 52, j = 0; i <= 61; i++, j++) {
            lookUpBase64Alphabet[i] = (char) (‘0‘ + j);
        }
        lookUpBase64Alphabet[62] = (char) ‘+‘;
        lookUpBase64Alphabet[63] = (char) ‘/‘;

    }

    private static boolean isWhiteSpace(char octect) {
        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
    }

    private static boolean isPad(char octect) {
        return (octect == PAD);
    }

    private static boolean isData(char octect) {
        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
    }

    /**
     * Encodes hex octects into Base64
     *
     * @param binaryData
     *            Array containing binaryData
     * @return Encoded Base64 array
     */
    public static String encode(byte[] binaryData) {

        if (binaryData == null) {
            return null;
        }

        int lengthDataBits = binaryData.length * EIGHTBIT;
        if (lengthDataBits == 0) {
            return "";
        }

        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
                : numberTriplets;
        char encodedData[] = null;

        encodedData = new char[numberQuartet * 4];

        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;

        int encodedIndex = 0;
        int dataIndex = 0;

        for (int i = 0; i < numberTriplets; i++) {
            b1 = binaryData[dataIndex++];
            b2 = binaryData[dataIndex++];
            b3 = binaryData[dataIndex++];

            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
                    : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
                    : (byte) ((b2) >> 4 ^ 0xf0);
            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
                    : (byte) ((b3) >> 6 ^ 0xfc);

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
        }

        // form integral number of 6-bit groups
        if (fewerThan24bits == EIGHTBIT) {
            b1 = binaryData[dataIndex];
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
                    : (byte) ((b1) >> 2 ^ 0xc0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
            encodedData[encodedIndex++] = PAD;
            encodedData[encodedIndex++] = PAD;
        } else if (fewerThan24bits == SIXTEENBIT) {
            b1 = binaryData[dataIndex];
            b2 = binaryData[dataIndex + 1];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
                    : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
                    : (byte) ((b2) >> 4 ^ 0xf0);

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
            encodedData[encodedIndex++] = PAD;
        }

        return new String(encodedData);
    }

    /**
     * Decodes Base64 data into octects
     *
     * @param encoded
     *            string containing Base64 data
     * @return Array containind decoded data.
     */
    public static byte[] decode(String encoded) {

        if (encoded == null) {
            return null;
        }

        char[] base64Data = encoded.toCharArray();
        // remove white spaces
        int len = removeWhiteSpace(base64Data);

        if (len % FOURBYTE != 0) {
            return null;// should be divisible by four
        }

        int numberQuadruple = (len / FOURBYTE);

        if (numberQuadruple == 0) {
            return new byte[0];
        }

        byte decodedData[] = null;
        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;

        int i = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        decodedData = new byte[(numberQuadruple) * 3];

        for (; i < numberQuadruple - 1; i++) {

            if (!isData((d1 = base64Data[dataIndex++]))
                    || !isData((d2 = base64Data[dataIndex++]))
                    || !isData((d3 = base64Data[dataIndex++]))
                    || !isData((d4 = base64Data[dataIndex++]))) {
                return null;
            }// if found "no data" just return null

            b1 = base64Alphabet[d1];
            b2 = base64Alphabet[d2];
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];

            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }

        if (!isData((d1 = base64Data[dataIndex++]))
                || !isData((d2 = base64Data[dataIndex++]))) {
            return null;// if found "no data" just return null
        }

        b1 = base64Alphabet[d1];
        b2 = base64Alphabet[d2];

        d3 = base64Data[dataIndex++];
        d4 = base64Data[dataIndex++];
        if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
            if (isPad(d3) && isPad(d4)) {
                if ((b2 & 0xf) != 0)// last 4 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 1];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                return tmp;
            } else if (!isPad(d3) && isPad(d4)) {
                b3 = base64Alphabet[d3];
                if ((b3 & 0x3) != 0)// last 2 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 2];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                return tmp;
            } else {
                return null;
            }
        } else { // No PAD e.g 3cQl
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);

        }

        return decodedData;
    }

    /**
     * remove WhiteSpace from MIME containing encoded Base64 data.
     *
     * @param data
     *            the byte array of base64 data (with WS)
     * @return the new length
     */
    private static int removeWhiteSpace(char[] data) {
        if (data == null) {
            return 0;
        }

        // count characters that‘s not whitespace
        int newSize = 0;
        int len = data.length;
        for (int i = 0; i < len; i++) {
            if (!isWhiteSpace(data[i])) {
                data[newSize++] = data[i];
            }
        }
        return newSize;
    }
}

总结一下

支付宝支付一共五部

生成秘钥私钥等(一般是后台处理的)

支付宝包复制带项目中

调用支付(上述MainActivity和pay类)

添加工具类

欢迎加入QQ技术群 225948944

时间: 2024-08-13 09:31:35

Android app 第三方支付宝支付接入的相关文章

Android App集成支付宝

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

iOS app集成支付宝支付流程及后台php订单签名处理

iOS app集成支付宝支付流程 1: 开通支付宝商户 由公司去支付宝 https://b.alipay.com/order/serviceIndex.htm 签约支付宝开通支付宝商家: 2:商户支付宝开通无线支付功能 开通商户支付宝之后,虽然可以获取到应用使用的 key和id,如果如果不开通无线支付功能的话,会在app集成的时间 提示商户未开通无线支付功能的错误: 开通商户支付宝-无线支付功能,请在商户支付宝后台,按要求提供审核材料开通: 3:在商户支付宝后台下载SDK 在商户支付宝后台,即可

使用Tornado异步接入第三方(支付宝)支付

目前国内比较流行的第三方支付主要有支付宝和微信支付,博主最近研究了下如何用Python接入支付宝支付,这里我以Tornado作为web框架,接入支付宝构造支付接口. 使用Tornado异步接入支付宝支付流程: 1. 进入蚂蚁金服开放平台填写开发者信息.应用信息 2. 配置RSA256密钥,生成支付宝和应用的密钥 3. 构造订单接口API,生成订单 4. 构造支付接口 1. 进入蚂蚁金服开放平台填写开发者信息.应用信息 这里通过沙箱环境开发测试接口,蚂蚁金服开放平台-->开发者中心-->研发者服

PHP TP5框架-手机APP端支付宝支付

最近应业务需求,做了支付宝支付和微信支付,今天分享一下手机端app支付宝支付对接流程,实际开发过程是前后端分离,前端调用后端API接口,实现功能返回数据,我所用的跨挤啊为TP5,大致可以分为四步: 1.在蚂蚁金服开放平台创建应用,签约商户,生成应用公钥和私钥: 2.配置统一下单支付参数: 3.整合支付宝demo类文件: 4.创建Alipay支付类,类内创建两个方法(alipay_app:统一下单方法和alipay_notify:支付成功异步回调方法); 第一步主要是在蚂蚁金服开放平台登录你的支付

app微信支付宝支付后台的插件模式+回调通过spring广播处理后续业务(已亲测可用)

写在前面的话:每当我们做一个项目,基本上都会涉及到支付的业务,最常用的莫过于微信和支付宝的支付了,项目有bug,有问题,都不叫问题,可一旦钱出了问题,那就是大问题了,所以在支付业务上我们必须慎之又慎! 但是我们做开发的,并不是在一个项目中完成支付模块就万事大吉了,在下一个项目中,我们是不是又要将支付模块的代码复制粘贴一遍,然后再重改支付模块?这样的坏处是频繁修改支付模块难免出现一些我们自己都意识不到的问题,一旦暴露在一些不怀好心的又懂技术的人面前,那我们哭都不知道去找谁. 所以,我试着通过利用s

安卓Android轻松完成支付宝支付教程

介绍 参考安卓Dialog源码,他的builder设计模式实现方式是,使用内部类来实现功能,外部类的作用是通过build()函数,来对内部类进行参数设置,例如setter方法. Buidler设计模式它一般用于用户不知道内部构建细节的情况下更加精细地控制对象构建流程,例如安卓系统的AlertDialog类,它包括了icon.title.msg.button1.button2等,这些装配的部分是比较多的,代码实现过程也较为漫长.使用Builder模式,可以使得这些调用变得简单,在构建过程各个部件可

最近接触的几种APP支付方式——支付宝支付

项目是在VS2017上.基于.net core 开发的web api 接口 所有的支付接入之前都要先申请好自己的商户平台,还有有一个账户用于测试使用,这些没有事先配置好,那么接下来的开发会无从下手的(个人建议),进入正题 1.首先配置好申请的商户id.支付账号id(个人建议新手最好用配置文件保存,不建议写死在代码中) 2.添加引用--AlipaySdk 3.引用添加好了后,接下来的代码与微信很类似,几乎相同,核心代码如下: sdk里面的用法有好几种,视情况而定.我用的是最后一种,具体参数源码如下

PHP app 唤起支付宝支付 获取链接【项目实例】

// 获取 支付宝app 支付字符串public function alipay_params_data(){ $data = $this->ApiData();//获取数据 if(!$data['out_trade_no']){ systemmess('0','参数错误'); } $out_trade_no = $data['out_trade_no']; $_biz_data = array(); $_biz_data['body'] = $oid_body; $_biz_data['sub

支付宝支付接入(接入与验证)

原文:https://fuwu.alipay.com/platform/doc.htm#c11 一.概述 开发者生成私钥.公钥之后,将公钥提交给服务窗平台,同时下载支付宝的公钥,使用OpenSSL的方式验证签名之后便可完成接入. 开发者使用接口之前需要激活开发者模式,请打开服务窗平台开发者模式,点击下方的“激活开发者模式”按钮. 建议开发者使用支付宝提供的SDK进行服务窗开发,使用SDK进行开发有以下优点: SDK会随着新接口的发布而同步更新 SDK会随着老接口的更新而同步更新 SDK让底层逻辑