Android中植入支付宝遇到的坑

最近公司有需求在项目中要植入支付宝支付等功能。 在完成植入的过程中,遇到了一些坑,今天趁趁任务不多做了个总结。分享给大家,希望以小伙伴不要陷入这些坑中以免浪费很多的时间。
首先说一下遇到的坑及其碰到的问题
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
原因:
  1. public class SignUtils {  
  2.    private static final String ALGORITHM = “RSA”;  
  3.    private static final String SIGN_ALGORITHMS = “SHA1WithRSA”;  
  4.    private static final String DEFAULT_CHARSET = “UTF-8”;  
  5.    public static String sign(String content, String privateKey) {  
  6.       try {  
  7.          java.security.Signature signature = java.security.Signature  
  8.                .getInstance(SIGN_ALGORITHMS);  
  9. PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(PayBase64.decode(privateKey));  
  10.       KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);  
  11.       PrivateKey priKey = keyf.generatePrivate(priPKCS8);  
  12.          PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(PayBase64.decode(privateKey));  
  13.          KeyFactory keyFactory = KeyFactory.getInstance(”RSA”“BC”);  
  14.          PrivateKey priKey = keyFactory.generatePrivate(privSpec);  
  15.          signature.initSign(priKey);  
  16.          signature.update(content.getBytes(DEFAULT_CHARSET));  
  17.          byte[] signed = signature.sign();  
  18.          return PayBase64.encode(signed);  
  19.       } catch (Exception e) {  
  20.          e.printStackTrace();  
  21.       }  
  22.       return null;  
  23.    }  
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:
  1. PayTask payTask = new PayTask(DocPayConunselActivity.this);  
  2. // String result = payTask.pay(signInfo, true);  
  3. Map<String, String> result = payTask.payV2(signInfo, true);  
  4. Message message = mHandler.obtainMessage();  
  5. message.what = SDK_PAY_FLAG;  
  6. message.obj = result;  
  7. mHandler.sendMessage(message);  
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的时候,网络出错,或者是手机没有安装支付宝的时候,弹不出来网页版的支付登录框 这个时候也是会提示网络错误 。这时候你要查找你的配置文件看一下是否配置了以下文件:
  1. <activityandroid:name=“com.alipay.sdk.app.H5PayActivity”android:configChanges=“orientation|keyboardHidden|navigation”android:exported=“false”android:screenOrientation=“behind” ></activity>  
  2. <activityandroid:name=”com.alipay.sdk.auth.AuthActivity”android:configChanges=“orientation|keyboardHidden|navigation”android:exported=“false”android:screenOrientation=“behind” ></activity>  
  3. 添加必要权限  
  4. <uses-permissionandroid:name=”android.permission.INTERNET” />  
  5. <uses-permissionandroid:name=”android.permission.ACCESS_NETWORK_STATE” />  
  6. <uses-permissionandroid:name=”android.permission.ACCESS_WIFI_STATE” />  
  7. <uses-permissionandroid:name=”android.permission.READ_PHONE_STATE” />  
  8. <uses-permissionandroid:name=”android.permission.WRITE_EXTERNAL_STORAGE” />  
<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
  1. <pre name=“code” class=“java”>PayTask payTask = new PayTask(DocPayConunselActivity.this);  
  2. // String result = payTask.pay(signInfo, true);  
  3. Map<String, String> result = payTask.payV2(signInfo, true);  
  4. Message message = mHandler.obtainMessage();  
  5. message.what = SDK_PAY_FLAG;  
  6. message.obj = result;  
  7. mHandler.sendMessage(message)  
<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)


返回的结果:
  1. private Handler mHandler =new Handler(){  
  2.     @Override  
  3.     public void handleMessage(Message msg) {  
  4.         super.handleMessage(msg);  
  5.         switch (msg.what){  
  6.             case SDK_PAY_FLAG:  
  7.                 PayResult payResult = null;  
  8.                         try{  
  9.                             payResult = new PayResult((Map<String, String>) msg.obj);  
  10.                         }catch (Exception e){  
  11.                             e.printStackTrace();  
  12.                         }  
  13.   
  14.   
  15.                 /** 
  16.                  对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。 
  17.                  */  
  18.                 String resultInfo = payResult.getResult();// 同步返回需要验证的信息  
  19.                 String resultStatus = payResult.getResultStatus();  
  20.                 // 判断resultStatus 为9000则代表支付成功  
  21.                 if (TextUtils.equals(resultStatus, PAY_OK)) {//———————————–>支付成功  
  22.                     // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。  
  23.                     GetToast.useString(DocPayConunselActivity.this“购买服务成功”);  
  24.                 } else if (TextUtils.equals(resultStatus, PAY_FAILED)) {//————————->支付失败  
  25.                     // 该笔订单真实的支付结果,需要依赖服务端的异步通知。  
  26.                     GetToast.useString(DocPayConunselActivity.this“”+payResult.getMemo());  
  27.                 } else if (TextUtils.equals(resultStatus, PAY_CANCLE)) {//————————–>交易取消  
  28.                     GetToast.useString(DocPayConunselActivity.this“”+payResult.getMemo());  
  29.                 } else if (TextUtils.equals(resultStatus, PAY_NET_ERR)) {//————————->网络出现错误  
  30.                     GetToast.useString(DocPayConunselActivity.this“”+payResult.getMemo());  
  31.                 } else if (TextUtils.equals(resultStatus, PAY_WAIT_CONFIRM)) {//———————>交替等待  
  32.                 }  
  33.                 break;  
  34.         }  
  35.     }  
  36. };  
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;
        }
    }
};
  1. 最后注意的是,有些手机没有安装支付宝客户端,如牵扯到支付功能的时候,我们直接天转到网页版的支付进行去输入密码去支付 。当然你也可以判断利用支付的sdk进行判断,如没有安装支付宝,提示去安装支付宝模块也是可以的。            
最后注意的是,有些手机没有安装支付宝客户端,如牵扯到支付功能的时候,我们直接天转到网页版的支付进行去输入密码去支付 。当然你也可以判断利用支付的sdk进行判断,如没有安装支付宝,提示去安装支付宝模块也是可以的。          
这样就完美无缺了。
QQ交流群 :232203809,欢迎入群 
这里写图片描述 
微信公众号:终端研发部 
(欢迎关注学习和交流)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Android 使用 AspectJ 来实现 AOP 需要注意以下几点: 1. 需要将 AspectJ 相关的依赖添加到项目,这通常是使用 Gradle 来实现的。 2. 需要在项目添加一个 aop.xml 文件,并在该文件定义切面和切点。 3. 需要使用 @Aspect 注解标记 Aspect 类,并使用 @Pointcut 注解来定义切点。 4. 使用 @Before、@After、@Around 等注解来定义切面的通知。 5. 在应用启动时,需要将 AspectJ 注册为应用的一个组件。 6. 需要注意,使用 AspectJ 进行 AOP 编程可能会对应用的性能产生影响,因此应该谨慎使用。 ### 回答2: 在Android实现面向切面编程(AOP)时,需要注意以下几点: 1. 选择合适的AOP框架:Android有多个AOP框架可供选择,如AspectJ、ButterKnife等。选择合适的框架可以根据项目的需求和规模来决定。 2. 配置AOP框架:在使用AOP框架前,需要进行相应的配置。例如,引入所需的依赖项,配置插件,设置编译选项等。这些步骤可能因使用的AOP框架而有所不同。 3. 定义切入点:切入点是在代码添加横切逻辑的地方。根据项目的需求,需要清楚地定义切入点,以便在运行时能够准确地触发AOP操作。 4. 编写切面逻辑:切面是指要在切入点处执行的逻辑。可以在切面定义各种行为,如日志记录、权限检查等。根据需要,切面可以是通知(advice)和增强(advice)的组合。 5. 注入切面逻辑:将切面逻辑与目标代码进行绑定。可以使用注解或配置文件的方式将切面逻辑注入到需要植入的代码。 6. 优化性能:由于AOP会在运行时动态地植入代码,因此可能会对应用的性能产生一定的影响。可以采取一些优化措施,如选择合适的切入点、减少植入的代码量等,以降低性能损失。 7. 测试和调试:在使用AOP框架实现AOP之后,需要进行充分的测试和调试,确保AOP操作的正确性和可靠性。 总之,在Android实现AOP需要仔细考虑框架选择、切入点的定义、切面逻辑的编写和注入、性能优化以及测试和调试等方面的问题。只有在深入理解AOP原理的基础上,并合理运用AOP框架,才能在Android开发充分发挥AOP的优势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值