Android支付宝支付接入(支付宝支付SDKV2.0版)

前言:个人上篇文章介绍了Android微信支付接入,这里将支付宝支付也介绍下,希望对大家能有帮助。
正文:无论是微信支付还是支付宝支付,其总体流程基本都是相同的。结构图如下:这里写图片描述
订单信息:其中包含订单价格,订单号,密钥等订单信息。在支付宝支付中,该订单信息是一段由key&value拼接的字符串。如果在项目中,该订单字符串由服务器构造完成,那么在APP客户端只需使用该订单信息串即可,无需自己构造,支付工作在Android端也会简单很多。如果服务端没有对该串进行构造,而只是返回了关键数据给APP端,那么APP端就要完成拼接工作。(支付宝也是极力推荐订单信息在服务端构造的,当然后文还是会详细说明订单信息的详细字段以及构造方法)
支付请求:在APP端调用支付SDK进行支付(详情见后文)
支付结果反馈:支付宝SDK调用支付方法会直接将结果返回,由于该操作有网络延迟,故要在子线程中调用, 并采用Handler通知的形式将支付结果返回到UI层。
1,接入与配置
a,官方SDK&demo下载地址,下载后将alipaySdk-20161129.jar导入项目中,这里本文介绍的2016版的这个jar包,也就是2.0版的。
b,AndroidManifest配置

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<activity
android:name="com.alipay.sdk.app.H5PayActivity"                                      android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" />

2,代码调用支付接口
这里注意了,一般来讲下面代码中orderInfo是完全由服务端构造生成的,APP端只需获取后在此使用即可。如果服务端没有构造该参数,那么参考后文中提到的参数构造。

        Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                PayTask alipay = new PayTask(activity);
                Map<String, String> result = alipay.payV2(orderInfo, true);
                Log.i("msp", result.toString());

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

        Thread payThread = new Thread(payRunnable);
        payThread.start();

3,实现回调
从上述代码中可看到支付宝已经将结果在payV2函数将其返回,并且发送给指定handler。故在handler中对返回结果进行判断即可。

Map<String, String> result = alipay.payV2(orderInfo, true);

private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1: {

                    @SuppressWarnings("unchecked")
                    PayResult payResult = new PayResult((Map<String, String>) msg.obj);
                    /**
                     对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
                     */
                    String resultInfo = payResult.getResult();// 同步返回需要验证的信息
                    String resultStatus = payResult.getResultStatus();
                    // 判断resultStatus 为9000则代表支付成功
                    if (TextUtils.equals(resultStatus, "9000")) {
                        // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
                        Toast.makeText(PayActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                    } else {
                        // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                        Toast.makeText(PayActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
                    }
                    break;
                }

                default:
                    break;
            }
        }

        ;
    };

4,订单信息构造
在本文第2点:代码调用支付接口中需得到一个String类型的订单信息参数,在服务端没有给定该完整参数的情况下,我们需要自己构造拼接该参数。
下面代码举例已知APPID,out_trade_no(订单号),subject(订单关键字等),body(交易的具体描述信息),total_fee(),5个参数的拼接代码。buildOrderParamMap()函数中的参数可自定义。具体参数说明

Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID,out_trade_no,subject,body,total_fee);
        String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
        String sign = OrderInfoUtil2_0.getSign(params, RSA_PRIVATE);//RSA_PRIVATE商户私钥,pkcs8格式
        final String orderInfo = orderParam + "&" + sign;

下面是所用到的工具类

public class OrderInfoUtil2_0 {


    /**
     * 构造支付订单参数列表
     * @param app_id
     * @return
     */
    public static Map<String, String> buildOrderParamMap(String app_id,String out_trade_no,String subject,String body,String total_fee) {
        Map<String, String> keyValues = new HashMap<String, String>();

        keyValues.put("app_id", app_id);

        keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\""+total_fee+"\",\"subject\":\""+subject+"\",\"body\":\""+body+"\",\"out_trade_no\":\"" + out_trade_no +  "\"}");//这里可以拼接自己需要填写的参数

        keyValues.put("charset", "utf-8");

        keyValues.put("method", "alipay.trade.app.pay");

        keyValues.put("sign_type", "RSA");

        keyValues.put("timestamp", "2016-07-29 16:55:53");

        keyValues.put("version", "1.0");

        keyValues.put("notify_url", "http://XXX");//服务端支付回调接口

        return keyValues;
    }

    /**
     * 构造支付订单参数信息
     * 
     * @param map
     * 支付订单参数
     * @return
     */
    public static String buildOrderParam(Map<String, String> map) {
        List<String> keys = new ArrayList<String>(map.keySet());

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < keys.size() - 1; i++) {
            String key = keys.get(i);
            String value = map.get(key);
            sb.append(buildKeyValue(key, value, true));
            sb.append("&");
        }

        String tailKey = keys.get(keys.size() - 1);
        String tailValue = map.get(tailKey);
        sb.append(buildKeyValue(tailKey, tailValue, true));

        return sb.toString();
    }

    /**
     * 拼接键值对
     * 
     * @param key
     * @param value
     * @param isEncode
     * @return
     */
    private static String buildKeyValue(String key, String value, boolean isEncode) {
        StringBuilder sb = new StringBuilder();
        sb.append(key);
        sb.append("=");
        if (isEncode) {
            try {
                sb.append(URLEncoder.encode(value, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                sb.append(value);
            }
        } else {
            sb.append(value);
        }
        return sb.toString();
    }

    /**
     * 对支付参数信息进行签名
     * 
     * @param map
     *            待签名授权信息
     * 
     * @return
     */
    public static String getSign(Map<String, String> map, String rsaKey) {
        List<String> keys = new ArrayList<String>(map.keySet());
        // key排序
        Collections.sort(keys);

        StringBuilder authInfo = new StringBuilder();
        for (int i = 0; i < keys.size() - 1; i++) {
            String key = keys.get(i);
            String value = map.get(key);
            authInfo.append(buildKeyValue(key, value, false));
            authInfo.append("&");
        }

        String tailKey = keys.get(keys.size() - 1);
        String tailValue = map.get(tailKey);
        authInfo.append(buildKeyValue(tailKey, tailValue, false));

        String oriSign = SignUtils.sign(authInfo.toString(), rsaKey);
        String encodedSign = "";

        try {
            encodedSign = URLEncoder.encode(oriSign, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "sign=" + encodedSign;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值