超詳細Android接入支付寶支付實現,有圖有真相

t839in24 8年前發布 | 578K 次閱讀 Android開發 移動開發

接上篇android接入微信支付文章,這篇我們帶你來接入支付寶支付服務

 

簡介

首先要說明的是個人感覺接入支付寶比微信簡單多了,很輕松的,所以同學們不要緊張~

當然還是老規矩啦,上來肯定的貼上官網地址,因為我這些服務天天在更新,而我的文章是教大家方法,而讓你不是照葫蘆畫瓢

進入app支付文檔有兩種方式,一種是直接在下面的開放業務里

還有一種是通過上面的導航欄文檔中心,然后滾動到業務接入那一欄,可以看到移動支付

當然也可以直接打開這個地址,文檔還是挺多,可以關注我勾選的這幾項

首先這里我也要說明的是個人是不能申請的,只能是企業,所以我demo里面的用的一些資料也是demo里面的

這里是交互流程的官方文檔,需要詳細的可以點進去看看

運行Demo

我們來到官方demo的下載地址

可以看到有兩個,選擇你需要的就行了,下載解壓完直接導入eclipse并配置一些參數運行就可以查看效果了

導入jar

將demo里面的alipaySdk-20160223.jar拷貝到我們工程的libs下,并添加到依賴中

配置

權限

<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

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

訂單數據生成

這一步,可以在服務端完成,也可以在本地完成

String orderInfo = getOrderInfo("測試的商品", "該測試商品的詳細描述", "0.01");

/**
 * 特別注意,這里的簽名邏輯需要放在服務端,切勿將私鑰泄露在代碼中!
 */
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(MainActivity.this);
        // 調用支付接口,獲取支付結果
        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();

處理支付結果

@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
    @SuppressWarnings("unused")
    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(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                } else {
                    // 判斷resultStatus 為非"9000"則代表可能支付失敗
                    // "8000"代表支付結果因為支付渠道原因或者系統原因還在等待支付結果確認,最終交易是否成功以服務端異步通知為準(小概率狀態)
                    if (TextUtils.equals(resultStatus, "8000")) {
                        Toast.makeText(MainActivity.this, "支付結果確認中", Toast.LENGTH_SHORT).show();

                    } else {
                        // 其他值就可以判斷為支付失敗,包括用戶主動取消支付,或者系統返回的錯誤
                        Toast.makeText(MainActivity.this, "支付失敗", Toast.LENGTH_SHORT).show();

                    }
                }
                break;
            }
            default:
                break;
        }
    }

};

這里支付成功了,只是提示用戶,還得從服務器確認是否正在支付了,我這里只寫了本地,其他如果在服務端實現是一樣的,你把這代碼直接發給后端就行了(如果后端是Java開發),可以看到我們已經成功調起支付寶服務了

完整代碼:

package cn.woblog.testalipay;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;

import com.alipay.sdk.app.PayTask;

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 cn.woblog.testalipay.domain.PayResult;
import cn.woblog.testalipay.util.SignUtils;

public class MainActivity extends AppCompatActivity {
    public static final String PARTNER = "";

    // 商戶收款賬號
    public static final String SELLER = "";

    // 商戶私鑰,pkcs8格式
    public static final String RSA_PRIVATE = "";

    private static final int SDK_PAY_FLAG = 1;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @SuppressWarnings("unused")
        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(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                    } else {
                        // 判斷resultStatus 為非"9000"則代表可能支付失敗
                        // "8000"代表支付結果因為支付渠道原因或者系統原因還在等待支付結果確認,最終交易是否成功以服務端異步通知為準(小概率狀態)
                        if (TextUtils.equals(resultStatus, "8000")) {
                            Toast.makeText(MainActivity.this, "支付結果確認中", Toast.LENGTH_SHORT).show();

                        } else {
                            // 其他值就可以判斷為支付失敗,包括用戶主動取消支付,或者系統返回的錯誤
                            Toast.makeText(MainActivity.this, "支付失敗", Toast.LENGTH_SHORT).show();

                        }
                    }
                    break;
                }
                default:
                    break;
            }
        }

    };

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

    public void testAlipay(View view) {
        if (TextUtils.isEmpty(PARTNER) || TextUtils.isEmpty(RSA_PRIVATE) || TextUtils.isEmpty(SELLER)) {
            new AlertDialog.Builder(this).setTitle("警告").setMessage("需要配置PARTNER | RSA_PRIVATE| SELLER")
                    .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialoginterface, int i) {
                            //
                            finish();
                        }
                    }).show();
            return;
        }

        String orderInfo = getOrderInfo("測試的商品", "該測試商品的詳細描述", "0.01");

/**
 * 特別注意,這里的簽名邏輯需要放在服務端,切勿將私鑰泄露在代碼中!
 */
        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(MainActivity.this);
                // 調用支付接口,獲取支付結果
                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();
    }


    /**
     * 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=" + "\"" + 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;
    }

    /**
     * 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\"";
    }

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

}

如果要測試demo,請替換

MainActivity中PARTNER,SELLER,RSA_PRIVATE為你申請到的值

以上測試代碼都在github上,官方的下載的sdk包也在該倉庫的docs目錄下

如果我的文章對來帶來的幫助,可加我微信,微博,QQ什么啥的交個朋友也是不錯的,另外微信,微博都會不定期發一些優質的文章,感謝大家的支持
~,聯系方式在我的個人介紹里啦

來自: http://www.jianshu.com/p/2aa2e8748476

 本文由用戶 t839in24 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!