[Android] webview調起支付寶支付頁面記錄

我啥時候說啦jj發表於2018-01-03

專案新需求:接收一個支付寶二維碼支付url,通過webview開啟對應的支付寶app支付頁面; 之前在網上找了段程式碼結果適配有問題,然後就順便研究下,記錄(liu)在(shui)此(zhang);

測試過的機型 : 紅米1s(4.4.4), 華為TAG-AL100(5.1), 華為KNT-AL20(6.0), exus6p(7.1.1);

接收到的支付連結 : url=https://qr.alipay.com/stx01744jxpniu1ijb5wr7d P.S. 具體規則可以看 螞蟻金服文件

之前檢視到的文章大多類似 這篇;

主要程式碼:

//啟動支付寶,並跳轉到付款頁面
if (url.contains("platformapi/startapp")) {
    startAlipayActivity(url);
}

private void startAlipayActivity(String url) {
    LogUtils.d("alipay", "startUp");
    Intent intent;
    try {
        intent = Intent.parseUri(url,
                Intent.URI_INTENT_SCHEME);
        intent.addCategory(Intent.CATEGORY_BROWSABLE);
        intent.setComponent(null);
        startActivity(intent);
        LogUtils.d("alipay", "start intent = " + intent.toString());
    } catch (Exception e) {
        e.printStackTrace();
        LogUtils.d("alipay", "error " + e.getMessage());
    }
}
複製程式碼

不過運氣不好,我手上的機子Nexus6P系統是7.1.1的,執行不成功,一直停留在網頁中,並未跳轉,直接使用斷點chrome://inspect功能,發現最終的url是被encode過的,難怪條件不匹配,後來嘗試了UrlDecode在判斷,依然不行,然後嘗試單獨判斷兩個關鍵字,也是呼叫不成功,鬱悶,在網上沒搜尋到現成的方法,就按照 上面文章 的思路,自己跟蹤一下url跳轉執行情況看看:

測試

功能程式碼

mWebSettings = mWebView.getSettings();
mWebSettings.setJavaScriptEnabled(true);
mWebSettings.setDomStorageEnabled(true);

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // 判斷方法1 ,註釋掉方法2再測試
        if (url.contains("platformapi/startapp")) {
            startAlipayActivity(url);
        }else {
            mWebView.loadUrl(url)
        }
     return true;
     
     // 判斷方法2,註釋掉方法1再測試
     if (url.contains("platformapi") && url.contains("startapp")) {
            startAlipayActivity(url);
        } else {
            iew.loadUrl(url)
        }
    return true;
    }
    ......
}
複製程式碼

分別測試方法1和方法2,看看兩種呼叫的情況,四臺機子測試結果:

  1. 原始 urlOri = https://qr.alipay.com/stx01744jxpniu1ijb5wr7d
  2. 第一次載入返回: urlFirst = https://mobilecodec.alipay.com/client_download.htm?qrcode=stx01744jxpniu1ijb5wr7d
  3. 第二次載入返回: urlHttps = https://ds.alipay.com/?from=mobilecodec&scheme=alipays%3A%2F%2Fplatformapi%2Fstartapp%3FsaId%3D10000007%26clientVersion%3D3.7.0.0718%26qrcode%3Dhttps%253A%252F%252Fqr.alipay.com%252Fstx01744jxpniu1ijb5wr7d%253F_s%253Dweb-other
  4. 這個時候通過判斷 url.contains("platformapi/startapp")) 自然會由於url編碼的原因判斷失敗,再次呼叫 mWebView.loadUrl(urlHttps) :
  5. 此時:
  • 對於4.4/5.1/6.0機子的 WebView 來說:
    1. 繼續載入 urlHttps 的話會返回一個intent : urlIntent = intent://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0718&qrcode=https%3A%2F%2Fqr.alipay.com%2Fstx01744jxpniu1ijb5wr7d%3F_s%3Dweb-other&_t=1483682394666#Intent;scheme=alipays;package=com.eg.android.AlipayGphone;end
    2. 通過解析它獲取到 targetIntent = Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://ds.alipay.com/... }
    3. 成功調起支付寶App;
  • 而對於Nexus6p 7.1.1系統來說,返回的url還是那個 urlHttps, 無法滿足條件,也自然無法進行解析;
  1. 而如果通過分開判斷兩個關鍵字 (url.contains("platformapi") && url.contains("startapp")) 來解析intent的話,4.4/5.1機子的webview無法正常跳轉,而6.0/7.1.1的機子則正常;

適配方案

綜上, 在6.0及以上機子,可以直接對支付寶伺服器返回的https url進行解析並調起支付寶app跳轉到指定的支付頁面,而之前的機型則直接通過webview對https url進行載入,會返回一個inent url再進行跳轉:

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.contains("platformapi/startapp")) {
            startAlipayActivity(url);
            // android  6.0 兩種方式獲取intent都可以跳轉支付寶成功,7.1測試不成功
        } else if ((Build.VERSION.SDK_INT > Build.VERSION_CODES.M)
                && (url.contains("platformapi") && url.contains("startapp"))) {
            startAlipayActivity(url);
        } else {
            mWebView.loadUrl(url)
        }
        return true;
    }
}

// 調起支付寶並跳轉到指定頁面
private void startAlipayActivity(String url) {
    Intent intent;
    try {
        intent = Intent.parseUri(url,
                Intent.URI_INTENT_SCHEME);
        intent.addCategory(Intent.CATEGORY_BROWSABLE);
        intent.setComponent(null);
        startActivity(intent);
        finish();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
複製程式碼

擴充套件,網頁調起原生app

從瀏覽器或者Webview中喚醒APP 如何在瀏覽器中點選連結啟動App AS2.3直接提供了介面操作,很方便

官網這篇 Android Intents with Chrome 也解釋很清楚了,在 AndroidManifest.xml 中需要指定目標Activity的 category 屬性,新增 android.intent.category.BROWSABLE ,當然還要指定跳轉url的 host/scheme等值才行,比如:

<activity
    android:name="YourActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>

        <data
            android:host="platformapi.startapp.redeemcode"
            android:scheme="uplusgo"/>
    </intent-filter>
</activity>
複製程式碼

就可以在html頁面中設定a標籤指定其連結為 uplusgo://platformapi.startapp.redeemcode?your_parameter_name=... ,點選啟動應用,在Activity中通過如下方式來獲取附加引數:

Intent mIntent = getIntent();
Uri uri = mIntent.getData();
if (uri != null) {
     String value = uri.getQueryParameter("your_parameter_name");
}
複製程式碼

相關文章