|
|
@@ -10,8 +10,10 @@ import cn.hutool.crypto.SecureUtil;
|
|
|
|
import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
|
|
|
|
import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
|
|
|
|
import cn.hutool.crypto.asymmetric.KeyType;
|
|
|
|
import cn.hutool.crypto.asymmetric.KeyType;
|
|
|
|
import cn.hutool.crypto.asymmetric.RSA;
|
|
|
|
import cn.hutool.crypto.asymmetric.RSA;
|
|
|
|
|
|
|
|
import cn.hutool.http.HttpUtil;
|
|
|
|
import cn.hutool.json.JSONConfig;
|
|
|
|
import cn.hutool.json.JSONConfig;
|
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
|
|
|
|
|
import com.dengqn.igps2xingzhe.config.Giant;
|
|
|
|
import com.dengqn.igps2xingzhe.config.IGPSport;
|
|
|
|
import com.dengqn.igps2xingzhe.config.IGPSport;
|
|
|
|
import com.dengqn.igps2xingzhe.config.XingZhe;
|
|
|
|
import com.dengqn.igps2xingzhe.config.XingZhe;
|
|
|
|
import com.dengqn.igps2xingzhe.vo.IGPSActivity;
|
|
|
|
import com.dengqn.igps2xingzhe.vo.IGPSActivity;
|
|
|
@@ -49,6 +51,7 @@ import java.security.spec.RSAPublicKeySpec;
|
|
|
|
import java.security.spec.X509EncodedKeySpec;
|
|
|
|
import java.security.spec.X509EncodedKeySpec;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 同步
|
|
|
|
* 同步
|
|
|
@@ -68,24 +71,49 @@ public class Trigger {
|
|
|
|
@Value("${dataDir:/data}")
|
|
|
|
@Value("${dataDir:/data}")
|
|
|
|
private String fileDir;
|
|
|
|
private String fileDir;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
|
|
|
private Giant giant;
|
|
|
|
@Autowired
|
|
|
|
@Autowired
|
|
|
|
private XingZhe xingZhe;
|
|
|
|
private XingZhe xingZhe;
|
|
|
|
@Autowired
|
|
|
|
@Autowired
|
|
|
|
private IGPSport igpSport;
|
|
|
|
private IGPSport igpSport;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final String GIANT_TOKEN_KEY = "GIANT_TOKEN_KEY";
|
|
|
|
|
|
|
|
private static final Map<String, Object> contextCache = new ConcurrentHashMap<>(4);
|
|
|
|
|
|
|
|
|
|
|
|
@GetMapping("/sync/igps2xingzhe")
|
|
|
|
@GetMapping("/sync/igps2xingzhe")
|
|
|
|
public ResponseEntity<String> onSyncIGPS2XingZhe() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
|
|
|
public ResponseEntity<String> onSyncIGPS2XingZhe() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
|
|
|
// 1. 登录行者
|
|
|
|
// 1. 登录行者
|
|
|
|
xingzheLogin();
|
|
|
|
xingzheLogin();
|
|
|
|
// 2. 登录igps
|
|
|
|
// 2. 登录igps
|
|
|
|
igpsLogin();
|
|
|
|
igpsLogin();
|
|
|
|
|
|
|
|
// 3. 登录捷安特
|
|
|
|
|
|
|
|
giantLogin();
|
|
|
|
// 3. 获取igps活动
|
|
|
|
// 3. 获取igps活动
|
|
|
|
syncIgpsActicities();
|
|
|
|
syncIgpsActicities();
|
|
|
|
|
|
|
|
|
|
|
|
return ResponseEntity.ok("ok");
|
|
|
|
return ResponseEntity.ok("ok");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void giantLogin() throws IOException {
|
|
|
|
|
|
|
|
if (!giant.getEnable()) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// clear cookie
|
|
|
|
|
|
|
|
httpClient.execute(ClassicRequestBuilder.get("https://ridelife.giant.com.cn/web/login.html/index.php/api/login").build());
|
|
|
|
|
|
|
|
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(CollUtil.toList(
|
|
|
|
|
|
|
|
new BasicNameValuePair("username", giant.getUsername()),
|
|
|
|
|
|
|
|
new BasicNameValuePair("password", giant.getPassword())
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
ClassicRequestBuilder igpsLoginReq = ClassicRequestBuilder
|
|
|
|
|
|
|
|
.post("https://ridelife.giant.com.cn/index.php/api/login")
|
|
|
|
|
|
|
|
.setEntity(formEntity);
|
|
|
|
|
|
|
|
CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(igpsLoginReq.build());
|
|
|
|
|
|
|
|
String responseData = new String(IoUtil.readBytes(response.getEntity().getContent()));
|
|
|
|
|
|
|
|
String token = JSONUtil.parseObj(responseData).getStr("user_token");
|
|
|
|
|
|
|
|
contextCache.put(GIANT_TOKEN_KEY, token);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void syncIgpsActicities() throws IOException {
|
|
|
|
private void syncIgpsActicities() throws IOException {
|
|
|
|
CloseableHttpResponse activityResp = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.get("https://my.igpsport.com/Activity/MyActivityList").build());
|
|
|
|
CloseableHttpResponse activityResp = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.get("https://my.igpsport.com/Activity/MyActivityList").build());
|
|
|
|
String activityRespStr = new String(IoUtil.readBytes(activityResp.getEntity().getContent()));
|
|
|
|
String activityRespStr = new String(IoUtil.readBytes(activityResp.getEntity().getContent()));
|
|
|
@@ -100,27 +128,49 @@ public class Trigger {
|
|
|
|
log.info("文件已存在" + filePath);
|
|
|
|
log.info("文件已存在" + filePath);
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 下载文件
|
|
|
|
// 下载文件
|
|
|
|
String downloadUrl = "https://my.igpsport.com/fit/activity?type=0&rideid=" + activity.getRideId();
|
|
|
|
downloadFileFromIgps(activity, filePath);
|
|
|
|
log.info("尝试下载" + downloadUrl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CloseableHttpResponse downloadResp = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.get(downloadUrl).build());
|
|
|
|
|
|
|
|
InputStream downloadInputStream = downloadResp.getEntity().getContent();
|
|
|
|
|
|
|
|
long copied = IoUtil.copy(downloadInputStream, new FileOutputStream(filePath));
|
|
|
|
|
|
|
|
log.info("{} bytes copied", copied);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 上传到xingzhe
|
|
|
|
// 上传到xingzhe
|
|
|
|
String uploadUrl = "https://www.imxingzhe.com/api/v4/upload_fits";
|
|
|
|
uploadToXingZhe(activity, filePath);
|
|
|
|
HttpEntity uploadForm = MultipartEntityBuilder.create()
|
|
|
|
// sync to giant app
|
|
|
|
.addPart("upload_file_name", new FileBody(new File(filePath)))
|
|
|
|
uploadToGiant(filePath);
|
|
|
|
.addPart("title", new StringBody(activity.getFileName(), ContentType.create("text/plain", Charset.defaultCharset())))
|
|
|
|
}
|
|
|
|
.addPart("device", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
|
|
|
|
}
|
|
|
|
.addPart("sport", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
|
|
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CloseableHttpResponse uploadResponse = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.post(uploadUrl).setEntity(uploadForm).build());
|
|
|
|
private void downloadFileFromIgps(IGPSActivity activity, String filePath) throws IOException {
|
|
|
|
log.info("upload result: {}", new String(IoUtil.readBytes(uploadResponse.getEntity().getContent())));
|
|
|
|
String downloadUrl = "https://my.igpsport.com/fit/activity?type=0&rideid=" + activity.getRideId();
|
|
|
|
|
|
|
|
log.info("尝试下载" + downloadUrl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CloseableHttpResponse downloadResp = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.get(downloadUrl).build());
|
|
|
|
|
|
|
|
InputStream downloadInputStream = downloadResp.getEntity().getContent();
|
|
|
|
|
|
|
|
long copied = IoUtil.copy(downloadInputStream, new FileOutputStream(filePath));
|
|
|
|
|
|
|
|
log.info("{} bytes copied", copied);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void uploadToXingZhe(IGPSActivity activity, String filePath) throws IOException {
|
|
|
|
|
|
|
|
String uploadUrl = "https://www.imxingzhe.com/api/v4/upload_fits";
|
|
|
|
|
|
|
|
HttpEntity uploadForm = MultipartEntityBuilder.create()
|
|
|
|
|
|
|
|
.addPart("upload_file_name", new FileBody(new File(filePath)))
|
|
|
|
|
|
|
|
.addPart("title", new StringBody(activity.getFileName(), ContentType.create("text/plain", Charset.defaultCharset())))
|
|
|
|
|
|
|
|
.addPart("device", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
|
|
|
|
|
|
|
|
.addPart("sport", new StringBody("3", ContentType.create("text/plain", Charset.defaultCharset())))
|
|
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CloseableHttpResponse uploadResponse = (CloseableHttpResponse) httpClient.execute(ClassicRequestBuilder.post(uploadUrl).setEntity(uploadForm).build());
|
|
|
|
|
|
|
|
log.info("upload to xingzhe result: {}", new String(IoUtil.readBytes(uploadResponse.getEntity().getContent())));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void uploadToGiant(String filePath) throws IOException {
|
|
|
|
|
|
|
|
if (giant.getEnable()) {
|
|
|
|
|
|
|
|
String giantUploadUrl = "https://ridelife.giant.com.cn/index.php/api/upload_fit";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cn.hutool.http.HttpRequest formed = HttpUtil.createPost(giantUploadUrl)
|
|
|
|
|
|
|
|
.form("files[]", new File[]{new File(filePath)})
|
|
|
|
|
|
|
|
.form("brand", "giant")
|
|
|
|
|
|
|
|
.form("device", "bike_computer")
|
|
|
|
|
|
|
|
.form("token", contextCache.getOrDefault(GIANT_TOKEN_KEY, "").toString());
|
|
|
|
|
|
|
|
cn.hutool.http.HttpResponse execute = formed.execute();
|
|
|
|
|
|
|
|
log.info("upload to giant result: {}", execute.body());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|