前言
一直以来都有写博客的想法,但是因为自己太懒又太菜了,所以迟迟没有动手。最近在写花旗比赛的API调用部分,由于经验不足,再加上自己学的东西太少,踩了许多的坑。索性功夫不负有心人,终于让我给搞了出来。再加上之前百度发现关于花旗API的使用的介绍几乎没有,所以就写下了这篇博客,希望对大家有所帮助。(大佬勿喷。。。嘿嘿)
好了,废话不多说,下面开始介绍。
花旗API介绍
点击花旗API官网查看API的详细信息。对于花旗的文档,我真的不想做太多评价(英文网站,看的脑壳疼)。可以使用360浏览器对整个网页进行翻译,然后对照着中英文看。
API调用–授权(Authorize)
在使用API之前需要进行客户端注册,获得一个客户端ID和密码以及设置重定向uri。大概就是这样:
和其他第三方API一样,花旗的授权采用的是OAuth2框架中的授权码模式,如果对OAuth2授权模式不熟悉,可以去看阮一峰的博客,里面讲解的很详细,我就不在这里赘述了。我直接对照文档和我的代码进行解释
获取授权码
文档里面的描述是这样的:
其中请求参数说明如下:
参数 | 内容 |
---|---|
response_type | 只能为 code |
client_id | 在应用程序注册期间生成的客户端ID |
scope | 直接使用实例中的 accounts_details_transaction |
countryCode | 国家/地区代码,表示你是为那个国家/地区开发的服务,如 US |
businessCode | 业务代码,使用GCB(大写)表示消费者银行业务 |
locale | 地区,可以直接使用实例中的en_US |
state | 州 ,可以直接使用实例中的 12093 |
redirect_uri | 重定向URI。在客户端注册时使用的URI |
呼,说了这么多,其实大部分都是照着文档来的,理解了AOuth2之后,文档真的很容易看懂。下面就上代码。
/**
* 初始化webview
*/
public void initWebView(){
webView = (WebView)findViewById(R.id.webview1);
WebSettings webSettings = webView.getSettings();
//支持获取手势焦点,输入用户名、密码或其他
webView.requestFocusFromTouch();
//支持JS
webSettings.setJavaScriptEnabled(true);
//支持插件,没有该方法,,?
// webSettings.setPluginsEnabled(true);
//提高渲染的优先级
webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);
//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true);//将图片调整到合适webview的大小
webSettings.setLoadWithOverviewMode(true);//缩放至屏幕的大小
//支持缩放,默认为true,是下面那个的前提
webSettings.setSupportZoom(true);
//设置内置的缩放控件,若上面是false,则该webview不可缩放,这个不管设置什么都不能缩放
webSettings.setBuiltInZoomControls(true);
//隐藏原生的缩放控件
webSettings.setDisplayZoomControls(false);
//支持内容重新布局
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
//多窗口
webSettings.supportMultipleWindows();
//关闭webView中缓存,加载时无论有没有缓存,都重新从网页请求数据
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
//设置可以访问文件
webSettings.setAllowFileAccess(true);
//当webView调用rewuestFocus时为webView设置节点
webSettings.setNeedInitialFocus(true);
//支持通过JS打开新窗口
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
//支持自动加载图片
webSettings.setLoadsImagesAutomatically(true);
//设置编码格式
webSettings.setDefaultTextEncodingName("utf-8");
}
重点来了!!!!
webview初始化的时候,一定要进行这个设置webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
将网页加载方式设置为无论有没有缓存都重新请求网页数据(或者是每次都清空webview的缓存也可以,但是那样有点麻烦)。这个坑我跳了好久才出来,如果使用缓存加载的网页进行用户登陆的话,服务器会拒绝服务(我也不知道这样说对不对,这应该是一种安全机制吧,但是我不懂,但是不要用缓存的网页数据请求登陆就对了)
另外,webview要手动设置成禁止跳转到外部浏览器,怎么搞自己去百度,嘿嘿。
下面是获取code的代码:
/**
* 第一步:通过浏览器获取 authorized code
* 使用get方法,添加header("accept","application/json")
*/
public void getCode() {
OkHttpClient client = new OkHttpClient();
String url = "https://sandbox.apihub.citi.com/gcb/api/authCode/oauth2/authorize?response_type=code" +
"&client_id=" + client_id
+ "&scope=" + scope + "&countryCode=US&businessCode=GCB&locale=en_US&state=12093&redirect_uri="+reDirectUri;
//String url1 = "https://sandbox.apihub.citi.com/gcb/api/authCode/oauth2/authorize?response_type=code&client_id=9e21dbc0-7d77-4874-83c2-4e154ae2bb36&scope=accounts_details_transactions&countryCode=US&businessCode=GCB&locale=en_US&state=12093&redirect_uri=https://hao.360.com";
Map<String,String> heards = new HashMap<>();
heards.put("accept","application/json");
webView.loadUrl(url,heards);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (url.startsWith(reDirectUri)) {//网址以重定向的URL开头,说明用户已经完成授权。接下来就要从网址中拿到code
view.stopLoading();//停止加载网页
Uri uri = Uri.parse(url);
String error = uri.getQueryParameter("error");
if (error != null) {
Log.e("获取code", error);
} else {
//拿到code
code = uri.getQueryParameter("code");
Log.e("获取code", code);
getToken();
finish();//退出当前webview
}
}
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if (error != null) {
handler.proceed();
}
}
});
}
开始的时候想了很久,不知道怎么从url中拿到code,后来才知道webview可以监测每次页面的加载。还是太菜了,学艺不精,呜呜。。。。。。
到这里code就已经拿到了,是不是感觉简单的一匹,鬼知道我当时琢磨了多长时间。
获取访问令牌
还是先看文档:
主要对Authorization做一下解释:
Authorization = "Base64 "+(client_id:client_se)的Base64编码
注意前面的"Base64 "有一个空格。
另外根据RFC822规定,BASE64Encoder编码每76个字符,还需要加上一个回车换行。部分Base64编码的java库还按照这个标准实行。Android中自带的Base64编码库就是这样,所以要对编码后的字符串进行去换行符的操作。
剩下的就没什么了,上代码:
/**
* 第二步:通过authorization code 获取access token
*/
public void getToken(){
OkHttpClient client = new OkHttpClient();
String auth = client_id + ":" + client_se;
//对auth使用Base进行编码
String auth_base = Base64.encodeToString(auth.getBytes(),Base64.DEFAULT);
//编码前面要加上"Basic ",注意有空格!
String auth_base1 = "Basic "+auth_base.replaceAll("[\\s*\t\n\r]", "");
new Thread(new Runnable() {
@Override
public void run() {
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "grant_type=authorization_code&code="+code+"&redirect_uri=https://hao.360.com");
Request request = new Request.Builder()
.url("https://sandbox.apihub.citi.com/gcb/api/authCode/oauth2/token/us/gcb")
.post(body)
.addHeader("authorization", auth_base1)
.addHeader("content-type", "application/x-www-form-urlencoded")
.addHeader("accept", "application/json")
.build();
try{
Response response1 = client.newCall(request).execute();
//System.out.println("response1::"+response1.body().string());
try{
JSONObject jsonObject = new JSONObject(response1.body().string());
access_token = jsonObject.get("access_token").toString();
refresh_token = jsonObject.get( "refresh_token").toString();
System.out.println("access_token++++"+access_token);
System.out.println("refresh_token++++"+refresh_token);
getMessage();
}catch (JSONException e){
e.printStackTrace();
}
}catch (IOException e){
e.printStackTrace();
}
}
}).start();
}
注意这里一定要使用post进行请求。
总结
没有一定的知识储备就去写东西真的好难受,浪费时间,疯狂踩坑,关键是出了问题还不知道怎么解决。基础知识太重要了,还是好好学习吧。
第一次写博客,有什么不足还请各位大佬指正,我会再接再厉。