最近公司有需求在項目中要植入支付寶支付等功能。 在完成植入的過程中,遇到了一些坑,今天趁趁任務不多做了個總結。分享給大家,希望以小夥伴不要陷入這些坑中以免浪費很多的時間。
首先說一下遇到的坑及其碰到的問題
1.java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag ClassCastException: com.android.org.bouncycastle.asn1.DLSequence cannot be cast to com.android.org.bouncycastle.asn1.ASN1Integer
原因:
public class SignUtils {
private static final String ALGORITHM = "RSA";
private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String DEFAULT_CHARSET = "UTF-8";
public static String sign(String content, String privateKey) {
try {
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_ALGORITHMS);
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(PayBase64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(PayBase64.decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
PrivateKey priKey = keyFactory.generatePrivate(privSpec);
signature.initSign(priKey);
signature.update(content.getBytes(DEFAULT_CHARSET));
byte[] signed = signature.sign();
return PayBase64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
修改之後,發現
com.android.org.bouncycastle.jcajce.provider.asymmetric.util.ExtendedInvalidKeySpecException: unable to process key spec: java.lang.ClassCastException: com.android.org.bouncycastle.asn1.DLSequence cannot be cast to com.android.org.bouncycastle.asn1.ASN1Integer
又這個錯誤,總麼辦?
最終是因為:
最終因為傳入私鑰錯誤。需要重新生成私鑰:
2.在handler裡面接受消息的時候,PayResult 轉換失敗,原因是你在進行
調用支付寶接口的時候,所發送的參數類型不一緻導緻的。eg:
PayTask payTask = new PayTask(DocPayConunselActivity.this);
// String result = payTask.pay(signInfo, true);
Map<String, String> result = payTask.payV2(signInfo, true);
Message message = mHandler.obtainMessage();
message.what = SDK_PAY_FLAG;
message.obj = result;
mHandler.sendMessage(message);
另外 如果傳回的resultStatus是6002的時候,網絡出錯,或者是手機沒有安裝支付寶的時候,彈不出來網頁版的支付登入框 這個時候也是會提示網絡錯誤 。這時候你要查找你的配置檔案看一下是否配置了以下檔案:
<activityandroid:name="com.alipay.sdk.app.H5PayActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind" ></activity>
<activityandroid:name="com.alipay.sdk.auth.AuthActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind" ></activity>
添加必要權限
<uses-permissionandroid:name="android.permission.INTERNET" />
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permissionandroid:name="android.permission.READ_PHONE_STATE" />
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Android快捷支付SDK Demo resultStatus={4001};memo={參數錯誤};result={}問題
分析:填寫的支付寶pkcs8編碼的私鑰 有問題,或者對應的公鑰沒有上傳至支付寶造成的。
背景處理的必須有這個步驟。上傳公鑰到支付寶
java.lang.NoClassDefFoundError: com.alipay.android.app.lib.ResourceMap
分析:沒有加入android_lib 沒有加入項目依賴項
resultStatus={7001};memo={商戶沒有開通移動快捷支付服務,請使用其他支付工具};result={}!
內建的基本流程如下:
第一步:2.1 導入jar包資源
目前最新版支付寶開發jar包下載下傳位址:androidstarjack_支付寶內建過程詳解— 運作DEMO.zip
下載下傳後将之拷貝libs目錄,Eclipse會自動添加依賴,Android Studio需在app的gradle中添加一行
compilefiles('libs/alipaySdk-20160223.jar')
點選右上角:Sync Now,稍等片刻
第二步:修改AndroidManifest.xml清單
聲明必要Activity
<!--支付相關-->
<activity
android:name="com.alipay.sdk.app.H5PayActivity" android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false" android:screenOrientation="behind" />
<activity
android:name="com.alipay.sdk.auth.AuthActivity" android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false" android:screenOrientation="behind" />
添加必要權限
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
第四步:
private void payToOrderService(final String signInfo){
new Thread() {
@Override
public void run() {
super.run();
PayTask payTask = new PayTask(DocPayConunselActivity.this);
// String result = payTask.pay(signInfo, true);
Map<String, String> result = payTask.payV2(signInfo, true);
Message message = mHandler.obtainMessage();
message.what = SDK_PAY_FLAG;
message.obj = result;
mHandler.sendMessage(message);
}
}.start();
}
app攜帶支付資訊調用支付接口請求支付寶用戶端調起支付界面;
使用者操作,輸入密碼支付,支付成功;直接傳回取消支付;出現錯誤,支付失敗;進入支付界面,但輸入密碼支付,支付待确認;
支付寶用戶端将支付結果告訴app用戶端,商戶伺服器通知app伺服器支付結果;
app用戶端處理支付結果;
app伺服器處理支付結果。
注意請求是異步的:x
<pre name="code" class="java">PayTask payTask = new PayTask(DocPayConunselActivity.this);
// String result = payTask.pay(signInfo, true);
Map<String, String> result = payTask.payV2(signInfo, true);
Message message = mHandler.obtainMessage();
message.what = SDK_PAY_FLAG;
message.obj = result;
mHandler.sendMessage(message)
傳回的結果:
private Handler mHandler =new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case SDK_PAY_FLAG:
PayResult payResult = null;
try{
payResult = new PayResult((Map<String, String>) msg.obj);
}catch (Exception e){
e.printStackTrace();
}
/**
對于支付結果,請商戶依賴服務端的異步通知結果。同步通知結果,僅作為支付結束的通知。
*/
String resultInfo = payResult.getResult();// 同步傳回需要驗證的資訊
String resultStatus = payResult.getResultStatus();
// 判斷resultStatus 為9000則代表支付成功
if (TextUtils.equals(resultStatus, PAY_OK)) {//----------------------------------->支付成功
// 該筆訂單是否真實支付成功,需要依賴服務端的異步通知。
GetToast.useString(DocPayConunselActivity.this, "購買服務成功");
} else if (TextUtils.equals(resultStatus, PAY_FAILED)) {//------------------------->支付失敗
// 該筆訂單真實的支付結果,需要依賴服務端的異步通知。
GetToast.useString(DocPayConunselActivity.this, ""+payResult.getMemo());
} else if (TextUtils.equals(resultStatus, PAY_CANCLE)) {//-------------------------->交易取消
GetToast.useString(DocPayConunselActivity.this, ""+payResult.getMemo());
} else if (TextUtils.equals(resultStatus, PAY_NET_ERR)) {//------------------------->網絡出現錯誤
GetToast.useString(DocPayConunselActivity.this, ""+payResult.getMemo());
} else if (TextUtils.equals(resultStatus, PAY_WAIT_CONFIRM)) {//--------------------->交替等待
}
break;
}
}
};
最後注意的是,有些手機沒有安裝支付寶用戶端,如牽扯到支付功能的時候,我們直接天轉到網頁版的支付進行去輸入密碼去支付 。當然你也可以判斷利用支付的sdk進行判斷,如沒有安裝支付寶,提示去安裝支付寶子產品也是可以的。
這樣就完美無缺了。
QQ交流群 :232203809,歡迎入群
微信公衆号:終端研發部
(歡迎關注學習和交流)