近來在集成第三方支付---支付寶,在集成的過程中嚴格按照支付寶開發者平台所發布的說明文檔和Demo,在我的測試機上可以完美的運行,但是在別人的手機無論怎么就是調用不起來,總是彈出"remote call failed". 翻來復去,代碼檢查了好幾遍,總是找不到錯誤在哪。
然后,仔細地查看了一下LogCat,發現一條Warning,顯示是InvalidKeySpecException異常,顯示如下:
09-23 20:03:34.735: W/System.err(24906): java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag 09-23 20:03:34.740: W/System.err(24906): at org.apache.harmony.xnet.provider.jsse.OpenSSLKey.getPrivateKey(OpenSSLKey.java:124) 09-23 20:03:34.740: W/System.err(24906): at org.apache.harmony.xnet.provider.jsse.OpenSSLRSAKeyFactory.engineGeneratePrivate(OpenSSLRSAKeyFactory.java:64) 09-23 20:03:34.740: W/System.err(24906): at java.security.KeyFactory.generatePrivate(KeyFactory.java:186) 09-23 20:03:34.740: W/System.err(24906): at com.slanissue.apps.mobile.bevarhymes.util.Rsa.sign(Rsa.java:68) 09-23 20:03:34.740: W/System.err(24906): at com.slanissue.apps.mobile.bevarhymes.PayActivity.executeAliPay(PayActivity.java:1055) 09-23 20:03:34.740: W/System.err(24906): at com.slanissue.apps.mobile.bevarhymes.PayActivity.access$9(PayActivity.java:1050) 09-23 20:03:34.740: W/System.err(24906): at com.slanissue.apps.mobile.bevarhymes.PayActivity$5.onSuccess(PayActivity.java:443) 09-23 20:03:34.740: W/System.err(24906): at com.loopj.android.http.JsonHttpResponseHandler$1$1.run(JsonHttpResponseHandler.java:125) 09-23 20:03:34.740: W/System.err(24906): at android.os.Handler.handleCallback(Handler.java:730) 09-23 20:03:34.740: W/System.err(24906): at android.os.Handler.dispatchMessage(Handler.java:92) 09-23 20:03:34.740: W/System.err(24906): at android.os.Looper.loop(Looper.java:176) 09-23 20:03:34.740: W/System.err(24906): at android.app.ActivityThread.main(ActivityThread.java:5454) 09-23 20:03:34.740: W/System.err(24906): at java.lang.reflect.Method.invokeNative(Native Method) 09-23 20:03:34.740: W/System.err(24906): at java.lang.reflect.Method.invoke(Method.java:525) 09-23 20:03:34.740: W/System.err(24906): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209) 09-23 20:03:34.740: W/System.err(24906): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025) 09-23 20:03:34.740: W/System.err(24906): at dalvik.system.NativeStart.main(Native Method) 09-23 20:03:34.745: W/System.err(24906): Caused by: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag 09-23 20:03:34.745: W/System.err(24906): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(Native Method) 09-23 20:03:34.745: W/System.err(24906): at org.apache.harmony.xnet.provider.jsse.OpenSSLKey.getPrivateKey(OpenSSLKey.java:122) 09-23 20:03:34.745: W/System.err(24906): ... 16 more
點擊第8行進去,發現錯誤在這兒:
1 PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec( 2 Base64.decode(privateKey)); 3 KeyFactory keyf = KeyFactory.getInstance("RSA"); 4 PrivateKey priKey = keyf.generatePrivate(priPKCS8);
但是這里顯然沒有錯啊?這到底是怎么回事呢??
經過在博客和StackOverFlow上查詢,發現原來是這樣的:(我的測試機比較早了,Android版本是4.0.3的,但是用的其它人的手機版本基本上都在4.3.x)
在Android4.1.0之前的版本,代碼行
1 KeyFactory keyf = KeyFactory.getInstance("RSA");
是工作正常的。但是在4.1.0之后,這個就不能正常工作了,需要將該代碼改變成:
1 KeyFactory keyf = KeyFactory.getInstance("RSA", "BC");
然后就研究了一下這個方法的作用,API上面說的是:“為指定提供程序中的指定算法生成 KeyFactory 對象”;
即:KeyFactory.getInstance(String algorithm, String provider);中的algorithm為“指定算法”,provider為“指定提供程序”。
或許是因為Android虛擬機Dalvik對KeyFactory的實現中,默認的provider在4.1.0之后由"BC"改為了其它的了。當然,僅是猜測。
還好最終解決了問題。
