在串接API之前我們還有一個重要的設定要做,我們必須先匯出證交所網站的SSL證書,並加入到JAVA的驗證裡面。
先進入證交所openAPI首頁
1.點選網頁上安全鎖的標示
2.選擇匯出憑證
3.選擇下一步
4.選擇DER編碼
5.選擇你要匯出的檔案的地址
因為我們會用到keytool ,所以PATH 環境變數要設置 C:\Program Files\Java\jdk-11.0.9\bin 這段路徑
(此處因人而異,請去看自己Java的安裝路徑)
接著執行下面的指令把憑證加入Java的憑證驗證庫中
keytool -import -file 憑證儲存路徑 -keystore cacerts -alias server
接著我們就要開始實作API請求囉~
我們先在 model建立一個Class- DailyTranctionStockData
package com.stockAPI.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class DailyTranctionStockData {
//上市個股日成交資訊
// {
// "Code": "string", //證券代號
// "Name": "string", //證券名稱
// "TradeVolume": "string", //成交股數
// "TradeValue": "string", //成交金額
// "OpeningPrice": "string", //開盤價
// "HighestPrice": "string", //最高價
// "LowestPrice": "string", //最低價
// "ClosingPrice": "string", //收盤價
// "Change": "string", //漲跌價差
// "Transaction": "string" //成交筆數
// }
@JsonProperty(value="Code")
private String code;
@JsonProperty(value="Name")
private String name;
@JsonProperty(value="TradeVolume")
private String tradevolume;
@JsonProperty(value="TradeValue")
private String tradevalue;
@JsonProperty(value="OpeningPrice")
private String openingprice;
@JsonProperty(value="HighestPrice")
private String highestprice;
@JsonProperty(value="LowestPrice")
private String lowestprice;
@JsonProperty(value="ClosingPrice")
private String closingprice;
@JsonProperty(value="Change")
private String change;
@JsonProperty(value="Transaction")
private String transaction;
public DailyTranctionStockData() {
}
public DailyTranctionStockData(String code, String name, String tradevolume, String tradevalue, String openingprice,
String highestprice, String lowestprice, String closingprice, String change, String transaction) {
super();
this.code = code;
this.name = name;
this.tradevolume = tradevolume;
this.tradevalue = tradevalue;
this.openingprice = openingprice;
this.highestprice = highestprice;
this.lowestprice = lowestprice;
this.closingprice = closingprice;
this.change = change;
this.transaction = transaction;
}
}
我在註釋裡面有放上從swagger的文件上看到的回傳格式,
然後我們再用@JsonProperty這個註解告訴框架我們Java物件屬性名與實際資料key的對應狀態。
再來我們實作一個Util 用來傳送資料給API(需要保留傳送物件類別的彈性)
在util的package新增一個類別-TWSIOpenAPIUtil
package com.stockAPI.util;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
public class TWSIOpenAPIUtil {
static Logger logger=LogManager.getLogger();
public static <T> T send(String url,HttpMethod method,Class<T> t){
try {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> httpEntity = new HttpEntity<String>(headers);
ResponseEntity<T> responseEntity =
restTemplate.exchange(url,method,httpEntity,t);
T result = responseEntity.getBody();
logger.info(responseEntity.getStatusCode());
return result;
}
catch(HttpClientErrorException httpClientErrorException) {
logger.error(httpClientErrorException.getResponseBodyAsString());
return null;
}
catch(Exception e) {
logger.error(e.getMessage());
return null;
}
}
}
可以看到我們這邊用泛型,讓使用者自己決定要回傳什麼物件
有了功能當然還需要儲存API資訊的Class囉
新建一個enumsave package並在裡面新增 TWSIOpenAPIUrl -enum
package com.stockAPI.enumsave;
import org.springframework.http.HttpMethod;
public enum TWSIOpenAPIUrl {
//證卷交易(exchangeReport)
EXCHANGE_REPORT_STOCK_DAY_ALL(1,"exchange_report",HttpMethod.GET,"https://openapi.twse.com.tw/v1/exchangeReport/STOCK_DAY_ALL");
private Integer id;
private String type;
private HttpMethod method;
private String url;
private TWSIOpenAPIUrl(Integer id, String type, HttpMethod method, String url) {
this.id = id;
this.type = type;
this.method =method;
this.url = url;
}
public Integer getId() {
return id;
}
public String getType() {
return type;
}
public HttpMethod getMethod() {
return method;
}
public String getUrl() {
return url;
}
}
Enum類別可以幫助我們管理一些固定資訊
最後我們在Service裡面新增一個類別- TWSIOpenService
package com.stockAPI.service;
import org.springframework.stereotype.Service;
import com.stockAPI.enumsave.TWSIOpenAPIUrl;
import com.stockAPI.model.DailyTranctionStockData;
import com.stockAPI.util.TWSIOpenAPIUtil;
@Service
public class TWSIOpenService {
public DailyTranctionStockData[] getDailyTranctionStockData(){
DailyTranctionStockData[] resultList =
TWSIOpenAPIUtil.send(
TWSIOpenAPIUrl.EXCHANGE_REPORT_STOCK_DAY_ALL.getUrl(),
TWSIOpenAPIUrl.EXCHANGE_REPORT_STOCK_DAY_ALL.getMethod(),
DailyTranctionStockData[].class);
return resultList;
}
}
這樣就完成我們獲取 證卷交易-上市個股日成交資訊 的功能了喔!
明日我們會對這個Service進行功能測試和權限設定。
參考資料:
Get and Post Lists of Objects with RestTemplate
從頭解決PKIX path building failed