工具類:Android 支付寶支付

首先是OrderInfoUtil2_0這個基礎類。後面調用的不少方法都抽出來了集成在這個類裏面,就當這個是一個工具類吧。web

public class OrderInfoUtil2_0 {  express

/**
     * 構造受權參數列表
     *
     * @param pid
     * @param app_id
     * @param target_id
     * @return
     */
    public static Map<String, String> buildAuthInfoMap(String pid, String app_id, String target_id) {
        Map<String, String> keyValues = new HashMap<String, String>();

        // 商戶簽約拿到的app_id,如:2013081700024223
        keyValues.put("app_id", app_id);

        // 商戶簽約拿到的pid,如:2088102123816631
        keyValues.put("pid", pid);

        // 服務接口名稱, 固定值
        keyValues.put("apiname", "com.alipay.account.auth");

        // 商戶類型標識, 固定值
        keyValues.put("app_name", "mc");

        // 業務類型, 固定值
        keyValues.put("biz_type", "openservice");

        // 產品碼, 固定值
        keyValues.put("product_id", "APP_FAST_LOGIN");

        // 受權範圍, 固定值
        keyValues.put("scope", "kuaijie");

        // 商戶惟一標識,如:kkkkk091125
        keyValues.put("target_id", target_id);

        // 受權類型, 固定值
        keyValues.put("auth_type", "AUTHACCOUNT");

        // 簽名類型
        keyValues.put("sign_type", "RSA");

        return keyValues;
    }

    /**
     * 構造支付訂單參數列表
     *
     * @return
     */
    public static Map<String, String> buildOrderParamMap(String app_id, String total_amount, String product_info, String time,String out_trade_no) {
        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_amount + "\",\"subject\":\"" + product_info + "\",\"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", time);// "2016-07-29 16:55:53"

        keyValues.put("version", "1.0");
        keyValues.put("notify_url", "成功回調地址");

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

    /**
     * 要求外部訂單號必須惟一。
     *
     * @return
     */
    private 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;
    }

}

 

/**
 * 重要說明:
 * <p/>
 * 這裏只是爲了方便直接向商戶展現支付寶的整個支付流程;因此Demo中加簽過程直接放在客戶端完成;
 * 真實App裏,privateKey等數據嚴禁放在客戶端,加簽過程務必要放在服務端完成;
 * 防止商戶私密數據泄露,形成沒必要要的資金損失,及面臨各類安全風險;
 */
public class PayDemoActivity extends FragmentActivity {

    /**
     * 支付寶支付業務:入參app_id
     */
    public static final String APPID = "入參app_id";

    /**
     * 支付寶帳戶登陸受權業務:入參pid值
     */
    public static final String PID = "入參pid值";
    /**
     * 支付寶帳戶登陸受權業務:入參target_id值
     */
    public static final String TARGET_ID = "入參target_id值";

    /**
     * 商戶私鑰,pkcs8格式
     */
    public static final String RSA_PRIVATE = "商戶私鑰";
    private static final int SDK_PAY_FLAG = 1;
    private static final int SDK_AUTH_FLAG = 2;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @SuppressWarnings("unused")
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SDK_PAY_FLAG: {
                    @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")) {
                        // 該筆訂單是否真實支付成功,須要依賴服務端的異步通知。
                        MyToast.makeText(PayDemoActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                    } else {
                        // 該筆訂單真實的支付結果,須要依賴服務端的異步通知。
                        MyToast.makeText(PayDemoActivity.this, "支付失敗", Toast.LENGTH_SHORT).show();
                    }
                    break;
                }
                case SDK_AUTH_FLAG: {
                    @SuppressWarnings("unchecked")
                    AuthResult authResult = new AuthResult((Map<String, String>) msg.obj, true);
                    String resultStatus = authResult.getResultStatus();

                    // 判斷resultStatus 爲「9000」且result_code
                    // 爲「200」則表明受權成功,具體狀態碼錶明含義可參考受權接口文檔
                    if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
                        // 獲取alipay_open_id,調支付時做爲參數extern_token 的value
                        // 傳入,則支付帳戶爲該受權帳戶
                        MyToast.makeText(PayDemoActivity.this,
                                "受權成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        // 其餘狀態值則爲受權失敗
                        MyToast.makeText(PayDemoActivity.this,
                                "受權失敗" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

                    }
                    break;
                }
                default:
                    break;
            }
        }

        ;
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pay_main);

        SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date_e = dfs.format(new Date());

        payV2("0.02", "團幣兌換", date_e);
    }

    /**
     * 支付寶支付業務
     */
    public void payV2(String price, String product_info, String time) {
        if (TextUtils.isEmpty(APPID) || TextUtils.isEmpty(RSA_PRIVATE)) {
            new AlertDialog.Builder(this).setTitle("警告").setMessage("須要配置APPID | RSA_PRIVATE")
                    .setPositiveButton("肯定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                            finish();
                        }
                    }).show();
            return;
        }

        /**
         * 這裏只是爲了方便直接向商戶展現支付寶的整個支付流程;因此Demo中加簽過程直接放在客戶端完成;
         * 真實App裏,privateKey等數據嚴禁放在客戶端,加簽過程務必要放在服務端完成;
         * 防止商戶私密數據泄露,形成沒必要要的資金損失,及面臨各類安全風險;
         *
         * orderInfo的獲取必須來自服務端;
         */
//        Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, price, product_info, time);
        Map<String, String> params=new HashMap<String, String>();
        String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
        String sign = OrderInfoUtil2_0.getSign(params, RSA_PRIVATE);
        final String orderInfo = orderParam + "&" + sign;

        Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                PayTask alipay = new PayTask(PayDemoActivity.this);
                Map<String, String> result = alipay.payV2(orderInfo, true);
                Log.e("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();
    }

    /**
     * 支付寶帳戶受權業務
     *
     * @param v
     */
    public void authV2(View v) {
        if (TextUtils.isEmpty(PID) || TextUtils.isEmpty(APPID) || TextUtils.isEmpty(RSA_PRIVATE)
                || TextUtils.isEmpty(TARGET_ID)) {
            new AlertDialog.Builder(this).setTitle("警告").setMessage("須要配置PARTNER |APP_ID| RSA_PRIVATE| TARGET_ID")
                    .setPositiveButton("肯定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                        }
                    }).show();
            return;
        }

        /**
         * 這裏只是爲了方便直接向商戶展現支付寶的整個支付流程;因此Demo中加簽過程直接放在客戶端完成;
         * 真實App裏,privateKey等數據嚴禁放在客戶端,加簽過程務必要放在服務端完成;
         * 防止商戶私密數據泄露,形成沒必要要的資金損失,及面臨各類安全風險;
         *
         * authInfo的獲取必須來自服務端;
         */
        Map<String, String> authInfoMap = OrderInfoUtil2_0.buildAuthInfoMap(PID, APPID, TARGET_ID);
        String info = OrderInfoUtil2_0.buildOrderParam(authInfoMap);
        String sign = OrderInfoUtil2_0.getSign(authInfoMap, RSA_PRIVATE);
        final String authInfo = info + "&" + sign;
        Runnable authRunnable = new Runnable() {

            @Override
            public void run() {
                // 構造AuthTask 對象
                AuthTask authTask = new AuthTask(PayDemoActivity.this);
                // 調用受權接口,獲取受權結果
                Map<String, String> result = authTask.authV2(authInfo, true);

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

        // 必須異步調用
        Thread authThread = new Thread(authRunnable);
        authThread.start();
    }

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

    /**
     * 原生的H5(手機網頁版支付切natvie支付) 【對應頁面網頁支付按鈕】
     *
     * @param v
     */
    public void h5Pay(View v) {
        Intent intent = new Intent(this, H5PayDemoActivity.class);
        Bundle extras = new Bundle();
        /**
         * url是測試的網站,在app內部打開頁面是基於webview打開的,demo中的webview是H5PayDemoActivity,
         * demo中攔截url進行支付的邏輯是在H5PayDemoActivity中shouldOverrideUrlLoading方法實現,
         * 商戶能夠根據本身的需求來實現
         */
        String url = "http://m.taobao.com";
        // url能夠是一號店或者淘寶等第三方的購物wap站點,在該網站的支付過程當中,支付寶sdk完成攔截支付
        extras.putString("url", url);
        intent.putExtras(extras);
        startActivity(intent);
    }

}

 

剩下就是支付寶支付的業務邏輯了。下面的out_trade_no是本身請求服務器返回過來的訂單號,time就是當前時間,product_info就是顯示在支付頁面上的字段,本身設定,試試就知道。api

 

/**
     * 支付寶支付業務
     */
    public void payV2(String price, String product_info, String time, String out_trade_no) {
        if (TextUtils.isEmpty(APPID) || TextUtils.isEmpty(RSA_PRIVATE)) {
            new AlertDialog.Builder(this).setTitle("警告").setMessage("須要配置APPID | RSA_PRIVATE")
                    .setPositiveButton("肯定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                            finish();
                        }
                    }).show();
            return;
        }

        /**
         * 這裏只是爲了方便直接向商戶展現支付寶的整個支付流程;因此Demo中加簽過程直接放在客戶端完成;
         * 真實App裏,privateKey等數據嚴禁放在客戶端,加簽過程務必要放在服務端完成;
         * 防止商戶私密數據泄露,形成沒必要要的資金損失,及面臨各類安全風險;
         *
         * orderInfo的獲取必須來自服務端;
         */
        Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, price, product_info, time, out_trade_no);
        String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
        String sign = OrderInfoUtil2_0.getSign(params, RSA_PRIVATE);
        final String orderInfo = orderParam + "&" + sign;

        Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                PayTask alipay = new PayTask(RechargeMoneyActivity.this);
                Map<String, String> result = alipay.payV2(orderInfo, true);

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

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


handler處理
 安全

   private Handler mHandler = new Handler() {服務器

        @SuppressWarnings("unused")
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SDK_PAY_FLAG: {
                    @SuppressWarnings("unchecked")
                    PayResult payResult = new PayResult((Map<String, String>) msg.obj);
                    /**
                     對於支付結果,請商戶依賴服務端的異步通知結果。同步通知結果,僅做爲支付結束的通知。
                     */
                    String resultInfo = payResult.getResult();// 同步返回須要驗證的信息
                    String memo = payResult.getMemo();
                    String resultStatus = payResult.getResultStatus();
                    // 判斷resultStatus 爲9000則表明支付成功
                    if (TextUtils.equals(resultStatus, "9000")) {
                        // 該筆訂單是否真實支付成功,須要依賴服務端的異步通知。
//                        showHintDialog("支付成功");
                        
                    } else {
                        pay_state = "0";
                    }

                    String sign = TGmd5.getMD5(logid + pay_state + memo);
                    tuanbiExchangePresenter.doAlipay(logid, pay_state, memo, sign);

                    break;
                }
                case SDK_AUTH_FLAG: {
                    @SuppressWarnings("unchecked")
                    AuthResult authResult = new AuthResult((Map<String, String>) msg.obj, true);
                    String resultStatus = authResult.getResultStatus();

                    // 判斷resultStatus 爲「9000」且result_code
                    // 爲「200」則表明受權成功,具體狀態碼錶明含義可參考受權接口文檔
                    if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
                        // 獲取alipay_open_id,調支付時做爲參數extern_token 的value
                        // 傳入,則支付帳戶爲該受權帳戶
                        MyToast.makeText(RechargeMoneyActivity.this,
                                "受權成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        // 其餘狀態值則爲受權失敗
                        MyToast.makeText(RechargeMoneyActivity.this,
                                "受權失敗" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();
                    }
                    break;
                }
                default:
                    break;
            }
        }

        ;
    };


這樣一個支付寶支付就集成了,是否是很簡單。複製代碼就能寫出,注意裏面代碼註解。填寫各類id。app

源碼免費下載:http://www.jinhusns.com/Products/Download/?type=yhqdom

相關文章
相關標籤/搜索