Android接入支付宝和银联

支付宝接入参考链接:https://software.intel.com/zh-cn/node/542608

银联接入参考链接:http://blog.csdn.net/gf771115/article/details/41935683

         

银联支付相关问题记录:

1、我们看文档知道客户端使用银联(Android、IOS)需要有一个获取TN的接口。

2、我们来看银联支付返回回来的逻辑。代码如下:

 1  /*
 2          * 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消
 3          */
 4         String str = data.getExtras().getString("pay_result");
 5         if (str.equalsIgnoreCase("success")) {
 6             // 支付成功后,extra中如果存在result_data,取出校验
 7             // result_data结构见c)result_data参数说明
 8             if (data.hasExtra("result_data")) {
 9                 String result = data.getExtras().getString("result_data");
10                 try {
11                     JSONObject resultJson = new JSONObject(result);
12                     String sign = resultJson.getString("sign");
13                     String dataOrg = resultJson.getString("data");
14                     // 验签证书同后台验签证书
15                     // 此处的verify,商户需送去商户后台做验签
16                     boolean ret = RSAUtil.verify(dataOrg, sign, mMode);
17                     if (ret) {
18                         // 验证通过后,显示支付结果
19                         payStatus(true);
20                     } else {
21                         // 验证不通过后的处理
22                         // 建议通过商户后台查询支付结果
23                         payStatus(false);
24                     }
25                 } catch (JSONException e) {
26                     e.printStackTrace();
27                 }
28             } else {
29                 // 未收到签名信息
30                 // 建议通过商户后台查询支付结果
31                 payStatus(true);
32             }
33         } else if (str.equalsIgnoreCase("fail")) {
34             payStatus(false);
35         } else if (str.equalsIgnoreCase("cancel")) {
36             payStatus(false);
37         }
38     }

  我们看代码的第16行,我们看到在pay_result返回success后,还需要将证书与后台的商户进行验签。这个逻辑应该是最近版本的银联加上的。我看过老版本的没有这一步。测试的时候支付成功后,我们发现验证不通过,所以还是显示支付失败。那么显然是verify方法中的哪一步出现了问题。我们跟下去,看到了下面的代码:

1 public static PublicKey getPublicKeyProduct() {
2         // 请将此处的module换成生产环境商户验签的公钥模数
3         //String modulus = "24882698307025187401768229621661046262584590315978248721358993520593720674589904440569546585666019820242051570504151753011145804842286060932917913063481673780509705461614953345565639235206110825500286080970112119864280897521494849627888301696007067301658192870705725665343356870712277918685009799388229000694331337917299248049043161583425309743997726880393752539043378681782404204317246630750179082094887254614603968643698185220012572776981256942180397391050384441191238689965500817914744059136226832836964600497185974686263216711646940573711995536080829974535604890076661028920284600607547181058581575296480113060083";
4         String modulus="24882698307025187401768229621661046262584590315978248721358993520593720674589904440569546585666019820242051570504151753011145804842286060932917913063481673780509705461614953345565639235206110825500286080970112119864280897521494849627888301696007067301658192870705725665343356870712277918685009799388229000694331337917299248049043161583425309743997726880393752539043378681782404204317246630750179082094887254614603968643698185220012572776981256942180397391050384441191238689965500817914744059136226832836964600497185974686263216711646940573711995536080829974535604890076661028920284600607547181058581575296480113060083";
5         String publicExponent = "65537";
6         PublicKey publicKey = RSAUtil.generateRSAPublicKey(modulus,
7                 publicExponent);
8         return publicKey;
9     }

  我们看到需要将公钥模数进行替换。起初找了好久没有找到公钥模数。后来发现将生成环境下的证书的信息读取出来就可以获取公钥模数,替换即可。读取证书信息的Java代码如下:

public static void main(String[] args){
        try {
            CertificateFactory certificatefactory=CertificateFactory.getInstance("X.509");
            FileInputStream bais=new FileInputStream("d:/aa.cer");
            X509Certificate Cert = (X509Certificate)certificatefactory.generateCertificate(bais);
            RSAPublicKey pk = (RSAPublicKey) Cert.getPublicKey();
            sun.security.rsa.RSAPublicKeyImpl ppk = (sun.security.rsa.RSAPublicKeyImpl) pk;
            System.out.println(ppk.getModulus());//获取公钥模数
            System.out.println(ppk.getPublicExponent());
            System.out.println(ppk.getAlgorithm());
            System.out.println(ppk.getFormat());
            System.out.println(ppk.getAlgorithmId());
            System.out.println(ppk.getModulus().toString(16));
            System.out.println(ppk.getPublicExponent().toString(16));//10001
            System.out.println(new BigInteger(ppk.getEncoded()).toString(16));
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
原文地址:https://www.cnblogs.com/dreamGong/p/5265467.html