• android支付之支付宝支付


    先导入jar包alipaySDK-20150818

    调用支付宝

    AlipayUtils.pay(this,mHandler,"订单信息","订单描述","0.01");

    接收支付宝的返回结果

    /**
     * 接收支付宝的返回结果
     */
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case ConstantValues.SDK_PAY_FLAG: {
                    PayResult payResult = new PayResult((String) msg.obj);
                    // 支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签
                    String resultInfo = payResult.getResult();
                    String resultStatus = payResult.getResultStatus();
                    if (TextUtils.equals(resultStatus, "9000")) {
                        Toast.makeText(MainActivity.this,"支付成功",Toast.LENGTH_SHORT).show();
                    } else {
                        if (TextUtils.equals(resultStatus,"8000")) {
                            Toast.makeText(MainActivity.this,"支付结果确认中",Toast.LENGTH_SHORT).show();
                        } else if (TextUtils.equals(resultStatus,"6001")){
                            Toast.makeText(MainActivity.this,"您取消了订单支付",Toast.LENGTH_SHORT).show();
                        }else if (TextUtils.equals(resultStatus,"6002")){
                            Toast.makeText(MainActivity.this,"网络连接出错",Toast.LENGTH_SHORT).show();
                        }else {
                            Toast.makeText(MainActivity.this,"支付失败",Toast.LENGTH_SHORT).show();
                        }
                    }
                    break;
                }
                default:
                    break;
            }
        };
    };

    以上是在支付页面中的调用↑

    下面是几个必须的页面(类名不要改)

    1、Base64

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

    2、PayResult

    import android.text.TextUtils;
    
    public class PayResult {
        private String resultStatus;
        private String result;
        private String memo;
    
        public PayResult(String rawResult) {
    
            if (TextUtils.isEmpty(rawResult))
                return;
    
            String[] resultParams = rawResult.split(";");
            for (String resultParam : resultParams) {
                if (resultParam.startsWith("resultStatus")) {
                    resultStatus = gatValue(resultParam, "resultStatus");
                }
                if (resultParam.startsWith("result")) {
                    result = gatValue(resultParam, "result");
                }
                if (resultParam.startsWith("memo")) {
                    memo = gatValue(resultParam, "memo");
                }
            }
        }
    
        @Override
        public String toString() {
            return "resultStatus={" + resultStatus + "};memo={" + memo
                    + "};result={" + result + "}";
        }
    
        private String gatValue(String content, String key) {
            String prefix = key + "={";
            return content.substring(content.indexOf(prefix) + prefix.length(),
                    content.lastIndexOf("}"));
        }
    
        /**
         * @return the resultStatus
         */
        public String getResultStatus() {
            return resultStatus;
        }
    
        /**
         * @return the memo
         */
        public String getMemo() {
            return memo;
        }
    
        /**
         * @return the result
         */
        public String getResult() {
            return result;
        }
    }

    3、SignUtils

    import java.security.KeyFactory;
    import java.security.PrivateKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    
    public class SignUtils {
    
        private static final String ALGORITHM = "RSA";
    
        private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
    
        private static final String DEFAULT_CHARSET = "UTF-8";
    
        public static String sign(String content, String privateKey) {
            try {
                PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
                        Base64.decode(privateKey));
                KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
                PrivateKey priKey = keyf.generatePrivate(priPKCS8);
    
                java.security.Signature signature = java.security.Signature
                        .getInstance(SIGN_ALGORITHMS);
    
                signature.initSign(priKey);
                signature.update(content.getBytes(DEFAULT_CHARSET));
    
                byte[] signed = signature.sign();
    
                return Base64.encode(signed);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    }

    4、AlipayUtils

    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;
    import java.util.Random;
    
    import android.os.Handler;
    import android.os.Message;
    
    import com.alipay.sdk.app.PayTask;
    import com.xh.boke.ConstantValues;
    import com.xh.boke.base.BaseActivity;
    
    /**
     * 支付宝支付工具类
     * Created by Administrator on 2015/10/23 0023.
     */
    public class AlipayUtils {
        /**
         * call alipay sdk pay. 调用SDK支付
         */
        public static void pay(final BaseActivity activity,final Handler handler,String title,String desc,String price) {
            // 订单
            String orderInfo = getOrderInfo(title,desc,price);
    
            // 对订单做RSA 签名
            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();
    
            Runnable payRunnable = new Runnable() {
    
                @Override
                public void run() {
                    // 构造PayTask 对象
                    PayTask alipay = new PayTask(activity);
                    // 调用支付接口,获取支付结果
                    String result = alipay.pay(payInfo);
    
                    Message msg = new Message();
                    msg.what = ConstantValues.SDK_PAY_FLAG;
                    msg.obj = result;
                    handler.sendMessage(msg);
                }
            };
            // 必须异步调用
            Thread payThread = new Thread(payRunnable);
            payThread.start();
        }
    
        /**
         * check whether the device has authentication alipay account.
         * 查询终端设备是否存在支付宝认证账户
         *
         */
        public static void check(final BaseActivity activity,final Handler handler) {
            Runnable checkRunnable = new Runnable() {
    
                @Override
                public void run() {
                    // 构造PayTask 对象
                    PayTask payTask = new PayTask(activity);
                    // 调用查询接口,获取查询结果
                    boolean isExist = payTask.checkAccountIfExist();
    
                    Message msg = new Message();
                    msg.what = ConstantValues.SDK_CHECK_FLAG;
                    msg.obj = isExist;
                    handler.sendMessage(msg);
                }
            };
            Thread checkThread = new Thread(checkRunnable);
            checkThread.start();
    
        }
    
    
        /**
         * create the order info. 创建订单信息
         *
         */
        public static String getOrderInfo(String subject, String body, String price) {
            // 签约合作者身份ID
            String orderInfo = "partner=" + """ + ConstantValues.PARTNER + """;
    
            // 签约卖家支付宝账号
            orderInfo += "&seller_id=" + """ + ConstantValues.SELLER + """;
    
            // 商户网站唯一订单号
            orderInfo += "&out_trade_no=" + """ + getOutTradeNo() + """;
    
            // 商品名称
            orderInfo += "&subject=" + """ + subject + """;
    
            // 商品详情
            orderInfo += "&body=" + """ + body + """;
    
            // 商品金额
            orderInfo += "&total_fee=" + """ + price + """;
    
            // 服务器异步通知页面路径
            orderInfo += "&notify_url=" + """ + "http://notify.msp.hk/notify.htm"
                    + """;
    
            // 服务接口名称, 固定值
            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. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
         *
         */
        public static 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;
        }
    
        /**
         * sign the order info. 对订单信息进行签名
         *
         * @param content
         *            待签名订单信息
         */
        public static String sign(String content) {
            return SignUtils.sign(content, ConstantValues.RSA_PRIVATE);
        }
    
        /**
         * get the sign type we use. 获取签名方式
         *
         */
        public static String getSignType() {
            return "sign_type="RSA"";
        }
    }

    下面是支付宝商户的配置信息

    /**
     * 常量
     * Created by Administrator on 2015/10/23 0023.
     */
    public class ConstantValues {
        /** 支付宝支付 */
        //商户PID
        public static final String PARTNER = "";
        //商户收款账号
        public static final String SELLER = "";
        //商户私钥,pkcs8格式
        public static final String RSA_PRIVATE = "";
        //支付宝公钥
        public static final String RSA_PUBLIC = "";
        public static final int SDK_PAY_FLAG = 1;
        public static final int SDK_CHECK_FLAG = 2;
    }

    获取公钥和私钥

    1、获取公钥和私钥的方法

    2、如何上传公钥

    另外,在Android Manifest.xml 里面加上这句,在没有安装支付宝的情况下可以跳转一个H5页面进行支付

    <!--没安装支付宝时弹出的支付页面-->
    <activity
        android:name="com.alipay.sdk.app.H5PayActivity"
        android:configChanges="orientation|keyboardHidden|navigation"
        android:exported="false"
        android:screenOrientation="behind"
        android:windowSoftInputMode="adjustResize|stateHidden" >
    </activity>
  • 相关阅读:
    Liskov替换原则
    OCP开放封闭原则
    SRC单一职责原则
    什么是敏捷设计
    [WCF编程]13.并发:服务并发模式
    [WCF编程]12.事务:服务事务编程(下)
    [WCF编程]12.事务:服务事务编程(上)
    [WCF编程]12.事务:Transaction类
    [WCF编程]12.事务:事务传播
    [WCF编程]12.事务:事务协议与管理器
  • 原文地址:https://www.cnblogs.com/kangweifeng/p/4904564.html
Copyright © 2020-2023  润新知