Android 微信支付和支付寶支付 快速接入

現(xiàn)在的支付潮流莫過(guò)于微信跟支付寶了,最近我們項(xiàng)目涉及到會(huì)員需求,就用到微信支付跟支付寶支付,說(shuō)實(shí)話(huà)接入之前會(huì)覺(jué)得這個(gè)復(fù)雜,等真正去動(dòng)手實(shí)踐的時(shí)候才覺(jué)得狠簡(jiǎn)單,真的狠簡(jiǎn)單。從接入到支付一步到位,Run完直接調(diào)起了微信跟支付寶。接入前也看了這兩個(gè)支付的詳細(xì)接入文檔,但是看是一碼事,做也是一碼事。所以實(shí)踐很重要。

  • 之所以說(shuō)狠簡(jiǎn)單而且快速接入,主要是因?yàn)槲覀児镜倪\(yùn)維后臺(tái)很給力,把微信的一些請(qǐng)求參數(shù),全部后臺(tái)返回給我們,我們直接用實(shí)體是接受拿到就好。
先說(shuō)下微信支付吧,畢竟相對(duì)于支付而言,還是支付寶簡(jiǎn)單快速一點(diǎn),就留到后面說(shuō)了

1.如果你已經(jīng)成功集成了微信登錄和分享,直接用你的 libammsdk.jar和 WECHAT_APP_ID就可以了, 那么下面幫你快速集成微信支付。

2.接入前可以看看上面鏈接的文檔,不過(guò)微信官方的文檔寫(xiě)的不夠好,好多開(kāi)發(fā)者吐槽,至今也沒(méi)改善點(diǎn)啥。
3.好了直接說(shuō)接入,接入微信支付SDK前準(zhǔn)備下面三個(gè)東西,如果你集成了微信分享,登錄那只需要一個(gè) WXPayEntryActivity 類(lèi)就行了
① 微信支付的APPID
② 微信支付依賴(lài)包 -------- libammsdk.jar
③ 一個(gè)Activity類(lèi) ----------- WXPayEntryActivity

  • 這里需要特別說(shuō)明一下,這個(gè)WXPayEntryActivity 類(lèi),直接從微信官方下載的Demo代碼中copy到自己的工程中即可,這個(gè)頁(yè)面是在你調(diào)起微信支付完成支付(或取消或失?。┖螅倩氐侥愕腁pp時(shí)會(huì)調(diào)用的一個(gè)頁(yè)面。頁(yè)面的布局可以是你自定義的布局(一般做法是直接注釋掉這個(gè)布局)
    網(wǎng)上copy的一張圖講解:
WXPayEntryActivity 的路徑

4、WXPayEntryActivity中的布局是可以自定義的,如果你不需要展示什么布局,而是要跳轉(zhuǎn)頁(yè)面,把這段代碼刪除即可

/**
 * -Created by Luke on 2017/2/14.
 */
public class WXPayEntryActivity extends AppCompatActivity  {
    private static final String TAG = WXPayEntryActivity.class.getSimpleName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.pay_result);
        BaseApplication.api.handleIntent(getIntent(), this);
    }
}
WECHAT_APP_ID 已經(jīng)在BaseApplication中定義了 在這里不需要再寫(xiě)

5.下面是回調(diào)的邏輯,官方是這樣的圖


官方回調(diào)頁(yè)面
  • 我這邊就簡(jiǎn)單的演示下支付成功的地方
    @Override
    public void onResp(BaseResp resp) {

        LogUtil.d(TAG, "Luke = " + resp.toString());
        
        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            int code = resp.errCode;
            switch (code) {
                case 0:
                    ToastUtil.show("支付成功");
                    break;
                case -1:
                    ToastUtil.show("支付失敗");
                    finish();
                    break;
                case -2:
                    ToastUtil.show("支付取消");
                    finish();
                    break;
                default:
                    ToastUtil.show("支付失敗");
                    setResult(RESULT_OK);
                    finish();
                    break;
            }
        }
    }

接下來(lái)咱就把這個(gè)WXPayEntryActivity放在清單manifest文件里面注冊(cè),然后加上exported屬性,設(shè)置為true:

<activity
            android:name=".wxapi.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/Theme.AppCompat.NoActionBar"/>
注意的地方:
  • 0 成功 展示成功頁(yè)面
  • -1 錯(cuò)誤 可能的原因:簽名錯(cuò)誤、未注冊(cè)APPID、項(xiàng)目設(shè)置APPID不正確、注冊(cè)的APPID與設(shè)置的不匹配、其他異常等。
  • -2 用戶(hù)取消 無(wú)需處理。發(fā)生場(chǎng)景:用戶(hù)不支付了,點(diǎn)擊取消,返回APP。

6.這個(gè)類(lèi)中的其余的回調(diào)方法,我們都不需要去操作。然后我們就可以開(kāi)始支付了,蠻簡(jiǎn)單

  • 下面是請(qǐng)求的參數(shù)列表,我們都是服務(wù)器端返回,包括APPID,直接用已經(jīng)正式的sign。
微信支付請(qǐng)求參數(shù)列表
  • 大概的支付流程是
    ① 點(diǎn)擊支付的時(shí)候創(chuàng)建訂單,獲取訂單號(hào)orderNumber (或者在需要獲取訂單號(hào)的時(shí)候獲取)
    ② 通過(guò)你的價(jià)格和這個(gè)orderNumber去請(qǐng)求微信返回的一堆參數(shù),以及調(diào)起支付頁(yè)面:
    下面是關(guān)鍵的一步:

//PrePayWeChatEntity 服務(wù)器返回給我們微信支付的參數(shù)

private void WeChatPay(PrePayWeChatEntity data) {

        if (null == data) {
             //判斷是否為空。丟一個(gè)toast,給個(gè)提示。比如服務(wù)器異常,錯(cuò)誤啥的
            return;
        }

        IWXAPI api = WXAPIFactory.createWXAPI(this, data.getAppid());
        
        if (!isWXAppInstalledAndSupported(api)) {
            // throw new WeChartNoFoundException();
            ToastUtil.show(getString(R.string.text_uninstalled_wchat));
            
            return;
        }

        //data  根據(jù)服務(wù)器返回的json數(shù)據(jù)創(chuàng)建的實(shí)體類(lèi)對(duì)象
        PayReq req = new PayReq();

        req.appId = data.getAppid();
        
        req.partnerId = data.getPartnerid();
        
        req.prepayId = data.getPrepayid();
        
        req.packageValue = data.getPkgstr();
        
        req.nonceStr = data.getNoncestr();
        
        req.timeStamp = data.getTimestamp();
        
        req.sign = data.getSign();

        api.registerApp(data.getAppid());
        
        //發(fā)起請(qǐng)求
        api.sendReq(req);
    }

7.到這就是成功了,調(diào)起了微信支付。再回到 WXPayEntryActivity 中去判斷成功后的動(dòng)作,例如支付完成跳轉(zhuǎn)一個(gè)成功的頁(yè)面finish();也許是用戶(hù)取消,和異常的支付失敗,可以在這個(gè)邏輯中去請(qǐng)求訂單的狀態(tài)是怎么樣的。
8.最后一個(gè)問(wèn)題就是關(guān)于微信開(kāi)放平臺(tái)簽名的問(wèn)題。只要你手機(jī)上的程序的簽名和你在微信平臺(tái)登記的簽名一致即可,無(wú)論是debug版本,還是release版本,都是可以的,默認(rèn)都可以用release的簽名

到這微信支付就愉快的結(jié)束了

支付寶支付,這個(gè)比微信稍微簡(jiǎn)單那么點(diǎn),同樣在請(qǐng)求參數(shù)服務(wù)端返回的情況下
  • 支付寶開(kāi)放平臺(tái) 在這個(gè)平臺(tái)申請(qǐng)我們的支付功能:
  • 注意一點(diǎn)就是個(gè)人不能申請(qǐng)的,只能是企業(yè),so 我demo里面的用的一些資料也是demo里面的

1.進(jìn)入支付寶開(kāi)放平臺(tái),注冊(cè)賬戶(hù)并登錄。


官網(wǎng)地址

支付寶移動(dòng)支付

2.登錄成功后,點(diǎn)擊管理中心創(chuàng)建應(yīng)用(創(chuàng)建應(yīng)用時(shí),注意命名規(guī)范)。

  • 下載 alipaySdk-20161222.jar 和 alipay_demo

  • 將demo里面的alipaySdk-20161222.jar拷貝到我們工程的libs下,并添加到依賴(lài)中

  • 跟微信一樣在清單文件中注冊(cè)下這兩個(gè)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>

3.設(shè)置應(yīng)用公鑰

4.生成密鑰

5.點(diǎn)擊上方的支付寶密鑰生成器下載下jar包之后解壓

6.點(diǎn)擊密鑰生成器之后回彈出黑窗口,等幾秒之后彈出生成器窗口

7.跟微信的流程相差無(wú)幾。拿到價(jià)格和訂單號(hào),就可以去請(qǐng)求支付的地址了,然后用這些參數(shù)回調(diào)支付

    //orderNum,  orderInfo,  sign,  signType  服務(wù)器端返回,本地生成也是OK的
    private void requestAlipay(String orderNum, String orderInfo, String sign, String signType) {

        try {

            // 對(duì)sign做URL編碼
            sign = URLEncoder.encode(sign, "UTF-8");

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

        //  整的符合支付寶參數(shù)規(guī)范的訂單信息
        final String payInfo = orderInfo + "&sign=\"" + sign + "\"&sign_type=\"" + signType + "\"";

        //lambda    此處  () ->  為lambda 表達(dá)式寫(xiě)法
        Runnable payRunnable = () -> {
            // 構(gòu)造PayTask 對(duì)象
            PayTask payTask = new PayTask(this);
            // 調(diào)用支付接口,獲取支付結(jié)果
            String result = payTask.pay(payInfo, true);

            if (null == result) {
                result = "out_trade_no={" + orderNum + "}";
            } else {
                result += ";out_trade_no={" + orderNum + "}";
            }

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

        // 必須異步調(diào)用
        Thread payThread = new Thread(payRunnable);
        payThread.start();
    }

上述生成的這些東西一般都是后臺(tái)返回的,當(dāng)然我們本地生成也是可以的,所以我就大概的說(shuō)下流程

  • 處理支付結(jié)果:
 @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);
                    /**
                     對(duì)于支付結(jié)果,請(qǐng)商戶(hù)依賴(lài)服務(wù)端的異步通知結(jié)果。同步通知結(jié)果,僅作為支付結(jié)束的通知。
                     */
                    String resultInfo = payResult.getResult();// 同步返回需要驗(yàn)證的信息
                    String resultStatus = payResult.getResultStatus();
                    // 判斷resultStatus 為9000則代表支付成功
                    if (TextUtils.equals(resultStatus, "9000")) {
                        // 該筆訂單是否真實(shí)支付成功,需要依賴(lài)服務(wù)端的異步通知。
                        Toast.makeText(PayDemoActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                    } else {
                        // 該筆訂單真實(shí)的支付結(jié)果,需要依賴(lài)服務(wù)端的異步通知。
                        Toast.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”則代表授權(quán)成功,具體狀態(tài)碼代表含義可參考授權(quán)接口文檔
                    if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
                        // 獲取alipay_open_id,調(diào)支付時(shí)作為參數(shù)extern_token 的value
                        // 傳入,則支付賬戶(hù)為該授權(quán)賬戶(hù)
                        Toast.makeText(PayDemoActivity.this,
                                "授權(quán)成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        // 其他狀態(tài)值則為授權(quán)失敗
                        Toast.makeText(PayDemoActivity.this,
                                "授權(quán)失敗" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

                    }
                    break;
                }

                default:
                    break;
            }
        }

        ;
    };

  • 到這兒就支付成功了,提示用戶(hù)的邏輯,我們得從服務(wù)器確認(rèn)是否正在支付了,查詢(xún)是否支付成功的狀態(tài)。根據(jù)服務(wù)器端返回的判斷碼來(lái)處理支付之后的一些動(dòng)作。

  • 接入的時(shí)候有啥問(wèn)題可以隨時(shí)跟我談?wù)?,我想這些會(huì)給你們一些幫助,記錄就是在腦子里過(guò)一遍,也許是最好的成長(zhǎng)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 實(shí)現(xiàn)支付寶支付的準(zhǔn)備工作: 1.向支付寶簽約,成為支付寶的商戶(hù) 簽約完成后,支付寶會(huì)提供一些必要的數(shù)據(jù)給我們 商戶(hù)...
    Anson楊春安閱讀 8,632評(píng)論 0 6
  • 一、背景介紹 作為一名Android開(kāi)發(fā),從最初的跌跌撞撞到現(xiàn)在小有所悟,這其中經(jīng)歷過(guò)的辛酸苦辣也是一種痛并快樂(lè)著...
    freecats08閱讀 5,158評(píng)論 7 54
  • 簡(jiǎn)介: 隨著移動(dòng)支付的普及,越來(lái)越多的App采用第三發(fā)支付,在這里我們以支付寶為例,做一個(gè)快速集成! 1、首先,我...
    laer_L閱讀 10,182評(píng)論 9 176
  • 銀聯(lián)支付,支付寶支付,微信支付的三大總結(jié),之前也有寫(xiě)過(guò)兩篇。 微信支付,支付寶支付,銀聯(lián)支付——三大支付總結(jié): h...
    LucasAdam閱讀 5,091評(píng)論 2 23
  • 前情回顧 第九章 進(jìn)墓 我順著墓道前行,這墓道的墻壁上刻滿(mǎn)算命之術(shù),此處的洞壁要比之前的好太多,都是大青磚砌成,地...
    笨阿三閱讀 463評(píng)論 0 0

友情鏈接更多精彩內(nèi)容