让android支持https访问银联后台,测试成功

简介: 让android支持https访问银联后台,测试成功

根据XX公网前置接入规范,XX后台支持公网接入。但必须走https协议加密传输。


java很强大,在java上调用http接口以及解析json之类的应该很容易,有很多现成的接口和第三方库如httpclinet,okhttp,volley,retrofit等。


但是,XX的这套接口涉及到https加密传输,需加载本地公钥证书,以及定制http协议报文头,并且post的是16进制数据。


网上查资料,大多都是讲如何post提交json的,以及如何上传二进制图片的等内容。没找到如何提交二进制流的。


于是自己摸索了吧,接口通了。在此总结下,非专业andorid出身,代码有点乱。但要点就那几个。


使用的是retrofit.


要实现的协议格式如下:


POST/mjc/webtrans/VPB_lb HTTP/1.1
HOST:xxxxxxxx:xxxxx
User-Agent: Donjin Http0.1
Cache-Control: no-cache
Content-Type:x-XX-XXXX/x-XX
Accept: */*
Content-Length: xx
00 XX XX 00 0X 00 00 XX XX 00 XX XX XX XX00 00 20 00 00 00 c0 00 16 00 00 01 31 30 30 30 30


要点1,自定义http报文头,这个很简单了,举例如下:


@Headers({"User-Agent: Donjin Http 0.1","Cache-Control: no-cache","Content-Type: x-xxx","Accept-Encoding: *","Content-Length: xx"})//需要添加头
   // @Multipart
    @POST("/")
    Call<LoginResult> postData(@Body  RequestBody bodyhex);


需要注意的是,content-lenth这个别按上面的写固定了,这个是根据要提交的16进制数据来的。他不是一个固定值。


提交的数据内容直接传参 @Body RequestBody bodyhex


传的参数怎么处理,让他能够以16进制post呢?


如下,重新overrite RequestBody中的writeto方法和contenlenth放法,注意,必须得有contenlenth方法,否则会出错,不知道你post的数据有多少。


示例如下:


class DataBean {
    public byte[] data;
    public String DA = "00000000000000c0006300011000000010030002953657175656e6365204343131390003303120";//要发送的16进制数据的字符串形式
    public RequestBody bodyhex;
    public DataBean()
    {
        data = hexStringToBytes(DA);//转为hex 16进制
        bodyhex =  new RequestBody() {
            @Override
            public MediaType contentType() {
                return null;
            }
            @Override
            public void writeTo(BufferedSink sink) throws IOException {
                sink.write(data);
            }
            @Override
            public long contentLength() {
                return data.length;
            }
        };
    };
}


还有一个比较重要的地方就是加载https的本地公钥证书啦


/**
 * 通过okhttpClient来设置证书
 * @param clientBuilder OKhttpClient.builder
 * @param certificates 读取证书的InputStream
 */
public static void setCertificates(OkHttpClient.Builder clientBuilder, InputStream... certificates) {
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        int index = 0;
        for (InputStream certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory
                    .generateCertificate(certificate));
            try {
                if (certificate != null)
                    certificate.close();
            } catch (IOException e) {
            }
        }
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }
        X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        clientBuilder.sslSocketFactory(sslSocketFactory,trustManager);
    } catch (Exception e) {
        e.printStackTrace();
    }
}


public  static OkHttpClient getOkHttpSingletonInstance( Context ct) {
    mContext = ct;
    if (okHttpClient == null) {
        synchronized (OkHttpClient.class) {
            if (okHttpClient == null) {
                okHttpClient = new OkHttpClient();
                //设置合理的超时
                OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder()
                        .readTimeout(3, TimeUnit.SECONDS)
                        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) //设置连接超时 30秒
                        .writeTimeout(3, TimeUnit.MINUTES)
                        //.addInterceptor(new LoggingInterceptor())//添加请求拦截
                        .addNetworkInterceptor(
                                new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))
                        .hostnameVerifier(new HostnameVerifier() {
                            @Override
                            public boolean verify(String hostname, SSLSession session) {
                                return true;
                            }
                        })
                        //.sslSocketFactory(sslParams.sSLSocketFactory,sslParams.trustManager)
                        .retryOnConnectionFailure(true);
                //InputStream in = new InputStream()
                try {
                    //AssetManager assetManager =  AssetManager.class.newInstance();
                    InputStream is = MyAppcation.getInstance().getAssets().open("UP.pem");
                    OkHttp3Utils.setCertificates( httpBuilder,is);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                okHttpClient = httpBuilder.build();
            }
        }
    }
    return okHttpClient;
}


完成以上这些,就够了。能够实现一开始的要求了。最后完善下接口,在自定义一个


ConverterFactory


对应答的报文解析就完整了。


测试结果如下:


06-15 03:37:45.183 4061-4099/com.example.yang.myapplication D/OkHttp: Connection: Keep-Alive
    --> END POST
06-15 03:37:45.585 4061-4099/com.example.yang.myapplication D/OkHttp: <-- 200 OK https://xx.xx.1xx.xx:xxx0/ (400ms)
06-15 03:37:45.589 4061-4099/com.example.yang.myapplication D/OkHttp: Allow: POST, PUT
06-15 03:37:45.590 4061-4099/com.example.yang.myapplication D/OkHttp: Content-Type: x-ISO-xxx/x-xx
06-15 03:37:45.591 4061-4099/com.example.yang.myapplication D/OkHttp: Date: Fri, 15 Jun 2018 03:39:44 GMT
06-15 03:37:45.592 4061-4099/com.example.yang.myapplication D/OkHttp: Content-Length: 112
    Server: Access-Guard-1000-Software/1.0
06-15 03:37:45.603 4061-4099/com.example.yang.myapplication D/OkHttp: Connection: close
06-15 03:37:45.604 4061-4099/com.example.yang.myapplication D/OkHttp: <-- END HTTP
06-15 03:37:45.633 4061-4099/com.example.yang.myapplication 
D/respond:: 00XXXXXXXXXXXXXXXXXXXXXXXXXXX600000001003000296f3136333135305358582d3443333034313139
06-15 03:37:45.704 4061-4061/com.example.yang.myapplication D/AA: 成功
Response{protocol=http/1.1, code=200, message=OK, url=https://XXXXXXXX;XXX/}
D/OkHttp: --> POST https://1xx.xx.xx.xx:xxxx/ http/1.1
          Content-Type: x-ISO-TPDU/x-auth
D/OkHttp: Content-Length: 89
          User-Agent: Donjin Http 0.1
          Cache-Control: no-cache
          Accept-Encoding: *
D/OkHttp: Host: xxx.xxx.xxx.xx:xxxx
          Connection: Keep-Alive
          --> END POST
D/OkHttp: <-- 200 OK https://xxx.xxx.xxx.xx:xxxx/ (421ms)
D/OkHttp: Allow: POST, PUT
          Content-Type: x-ISO-TPDU/x-auth
          Date: Sat, 30 Jun 2018 09:58:41 GMT
D/OkHttp: Content-Length: 123
D/OkHttp: Server: Access-Guard-1000-Software/1.0
          Connection: close
          <-- END HTTP
D/AA: 成功
      Response{protocol=http/1.1, code=200, message=OK, url=https://xxxxxxxx:xxxxx/}
D/respondAA:: 007960000005016131003111080810003800010ac0001400000117563506300800094900313735363335353837303233303037333738323231343839383431313334313331303031340011000007500030004050bc9eb4774a92544c29dad2c764150bb93eba92d9f11a222efa9c2300000000000000002b580802
I/System.out: 开始解析...
I/System.out: ->ok 解析成功!
I/System.out: pinkey:b1a7ab3cb49c9757390f39a19ce71ae7
I/System.out: <-Er PIK错误


相关文章
|
4月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
680 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
4月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
575 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
4月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
909 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
4月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
266 0
|
6月前
|
运维 网络协议 安全
为什么经过IPSec隧道后HTTPS会访问不通?一次隧道环境下的实战分析
本文介绍了一个典型的 HTTPS 无法访问问题的排查过程。问题表现为 HTTP 正常而 HTTPS 无法打开,最终发现是由于 MTU 设置不当导致报文被丢弃。HTTPS 因禁止分片,对 MTU 更敏感。解决方案包括调整 MSS 或中间设备干预。
|
7月前
|
存储 Android开发 数据安全/隐私保护
Thanox安卓系统增加工具下载,管理、阻止、限制后台每个APP运行情况
Thanox是一款Android系统管理工具,专注于权限、后台启动及运行管理。支持应用冻结、系统优化、UI自定义和模块管理,基于Xposed框架开发,安全可靠且开源免费,兼容Android 6.0及以上版本。
894 4
|
7月前
|
数据采集 Web App开发 iOS开发
解决Python爬虫访问HTTPS资源时Cookie超时问题
解决Python爬虫访问HTTPS资源时Cookie超时问题
|
缓存 Java 测试技术
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
1759 3
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
|
11月前
|
安全 网络协议 网络安全
只有IP地址没有域名,如何实现HTTPS访问?
在仅有IP地址而无域名的情况下,实现HTTPS访问并非不可能。主要挑战包括证书颁发机构(CA)对IP地址的支持有限及浏览器兼容性问题。解决方案有:1) 搭建私有CA为内部IP地址颁发证书;2) 使用支持IP地址的公共CA服务。选择合适的方案需根据需求权衡。具体步骤包括选择证书类型、生成CSR文件、提交并完成验证、安装SSL证书和配置强制HTTPS访问。确保IP地址稳定,并定期维护安全性。 **申请优惠**:访问JoySSL官网并填写注册码“230907”可优惠申请IP地址证书。
2007 5
|
安全 应用服务中间件 网络安全
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
807 60

热门文章

最新文章