Compare commits
5 Commits
dafd63a9ec
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
caa36c4966 | ||
|
|
269e8e48a7 | ||
|
|
dde274acba | ||
|
|
0297c6e131 | ||
|
|
6394658a70 |
@@ -1539,9 +1539,12 @@ public class TencentDocController extends BaseController {
|
|||||||
log.info("✓ 准备写入是否安排 - 单号: {}, 是否安排: 2, 行: {}, 列: {}", expectedOrderNo, row, arrangedColumn);
|
log.info("✓ 准备写入是否安排 - 单号: {}, 是否安排: 2, 行: {}, 列: {}", expectedOrderNo, row, arrangedColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 更新"标记"列(如果存在)
|
// 5. 更新"标记"列(如果存在,且不是物流链接更新时才写入,物流链接更新时保留原日期)
|
||||||
if (markColumn != null) {
|
if (markColumn != null && !Boolean.TRUE.equals(isLinkUpdated)) {
|
||||||
requests.add(buildUpdateCellRequest(sheetId, row - 1, markColumn, today, false));
|
requests.add(buildUpdateCellRequest(sheetId, row - 1, markColumn, today, false));
|
||||||
|
log.info("✓ 准备写入标记日期 - 单号: {}, 日期: {}, 行: {}, 列: {}", expectedOrderNo, today, row, markColumn);
|
||||||
|
} else if (markColumn != null && Boolean.TRUE.equals(isLinkUpdated)) {
|
||||||
|
log.info("✓ 物流链接更新,保留原标记日期 - 单号: {}, 行: {}", expectedOrderNo, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建完整的 batchUpdate 请求体
|
// 构建完整的 batchUpdate 请求体
|
||||||
|
|||||||
@@ -287,7 +287,11 @@ public class InstructionServiceImpl implements IInstructionService {
|
|||||||
list.forEach(order -> order.setDistributionMark(truncateDistributionMark(order.getDistributionMark())));
|
list.forEach(order -> order.setDistributionMark(truncateDistributionMark(order.getDistributionMark())));
|
||||||
// 过滤条件:时间范围 + 参与统计标记(isCountEnabled为null或1表示参与统计)
|
// 过滤条件:时间范围 + 参与统计标记(isCountEnabled为null或1表示参与统计)
|
||||||
List<JDOrder> filtered = list.stream().filter(o -> o.getOrderTime() != null && !o.getOrderTime().before(start) && !o.getOrderTime().after(end) && (o.getIsCountEnabled() == null || o.getIsCountEnabled() == 1)).collect(Collectors.toList());
|
List<JDOrder> filtered = list.stream().filter(o -> o.getOrderTime() != null && !o.getOrderTime().before(start) && !o.getOrderTime().after(end) && (o.getIsCountEnabled() == null || o.getIsCountEnabled() == 1)).collect(Collectors.toList());
|
||||||
if (filtered.isEmpty()) return Collections.singletonList("今天没有订单。");
|
if (filtered.isEmpty()) {
|
||||||
|
LocalDate queryDate = range.get(0);
|
||||||
|
String dateStr = queryDate.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
return Collections.singletonList("日期:" + dateStr + "\n" + dateStr + "没有订单。");
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, List<JDOrder>> byDM = filtered.stream().filter(o -> o.getStatus() == null || !"拍错退款".equals(o.getStatus())).collect(Collectors.groupingBy(JDOrder::getDistributionMark));
|
Map<String, List<JDOrder>> byDM = filtered.stream().filter(o -> o.getStatus() == null || !"拍错退款".equals(o.getStatus())).collect(Collectors.groupingBy(JDOrder::getDistributionMark));
|
||||||
List<String> outputs = new ArrayList<>();
|
List<String> outputs = new ArrayList<>();
|
||||||
@@ -623,6 +627,17 @@ public class InstructionServiceImpl implements IInstructionService {
|
|||||||
}
|
}
|
||||||
// ==================== 按下单人统计结束 ====================
|
// ==================== 按下单人统计结束 ====================
|
||||||
|
|
||||||
|
// 在返回数据前,在每个元素的头部添加日期信息
|
||||||
|
if (!outputs.isEmpty()) {
|
||||||
|
LocalDate queryDate = range.get(0);
|
||||||
|
String dateStr = queryDate.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
String dateHeader = "日期:" + dateStr + "\n";
|
||||||
|
// 在每个原有元素的头部追加日期信息
|
||||||
|
for (int i = 0; i < outputs.size(); i++) {
|
||||||
|
outputs.set(i, dateHeader + outputs.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return outputs.isEmpty() ? Collections.singletonList("无数据") : outputs;
|
return outputs.isEmpty() ? Collections.singletonList("无数据") : outputs;
|
||||||
}
|
}
|
||||||
if (input.startsWith("单")) {
|
if (input.startsWith("单")) {
|
||||||
|
|||||||
@@ -226,29 +226,104 @@ public class WPS365ApiServiceImpl implements IWPS365ApiService {
|
|||||||
// 如果用户只提供了一个ID(fileId),则fileId和worksheetId使用同一个值
|
// 如果用户只提供了一个ID(fileId),则fileId和worksheetId使用同一个值
|
||||||
String baseUrl = "https://openapi.wps.cn/v7";
|
String baseUrl = "https://openapi.wps.cn/v7";
|
||||||
|
|
||||||
// 如果worksheetId为空或与fileId相同,说明用户只配置了一个ID(类似腾讯文档)
|
// 根据WPS365官方文档,AirSheet的worksheet_id必须是整数
|
||||||
// 在AirSheet中,这个ID既是file_id也是worksheet_id
|
// 如果worksheetId为空或"0",使用0(第一个工作表)
|
||||||
|
// 如果worksheetId与fileId相同,说明用户只配置了一个ID,尝试使用fileId作为worksheetId
|
||||||
String wsId;
|
String wsId;
|
||||||
if (worksheetId == null || worksheetId.trim().isEmpty() || worksheetId.equals(fileId)) {
|
if (worksheetId == null || worksheetId.trim().isEmpty() || "0".equals(worksheetId)) {
|
||||||
// 使用fileId作为worksheetId(AirSheet中文件ID就是工作表ID)
|
// 默认使用0(第一个工作表)
|
||||||
|
wsId = "0";
|
||||||
|
} else if (worksheetId.equals(fileId)) {
|
||||||
|
// 如果worksheetId与fileId相同,说明用户只配置了一个ID(类似腾讯文档)
|
||||||
|
// 在AirSheet中,这个ID可能既是file_id也是worksheet_id
|
||||||
wsId = fileId;
|
wsId = fileId;
|
||||||
} else {
|
} else {
|
||||||
// 使用提供的worksheetId(可能是整数索引,如"0")
|
// 使用提供的worksheetId(应该是整数)
|
||||||
wsId = worksheetId;
|
wsId = worksheetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试不同的API路径格式
|
// 根据官方文档:https://open.wps.cn/documents/app-integration-dev/wps365/server/airsheet/worksheets/VbHZwButmh
|
||||||
// 格式1: /v7/airsheet/{file_id}/worksheets/{worksheet_id}
|
// 正确路径:https://openapi.wps.cn/v7/airsheet/{file_id}/worksheets
|
||||||
String url = baseUrl + "/airsheet/" + fileId + "/worksheets/" + wsId;
|
// 注意:路径中不需要 worksheet_id,只需要 file_id
|
||||||
|
try {
|
||||||
|
String url = baseUrl + "/airsheet/" + fileId + "/worksheets";
|
||||||
|
|
||||||
// 如果指定了range,添加range参数
|
// 如果指定了range,添加range参数
|
||||||
// 根据官方文档,可能需要使用 /values 子路径,或者使用query参数
|
|
||||||
if (range != null && !range.trim().isEmpty()) {
|
if (range != null && !range.trim().isEmpty()) {
|
||||||
// 先尝试作为query参数
|
|
||||||
url += "?range=" + java.net.URLEncoder.encode(range, "UTF-8");
|
url += "?range=" + java.net.URLEncoder.encode(range, "UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("读取AirSheet数据 - url: {}, fileId: {}, worksheetId: {}, range: {}", url, fileId, wsId, range);
|
// 如果指定了worksheetId,也可以作为查询参数传递(如果API支持)
|
||||||
|
if (worksheetId != null && !worksheetId.trim().isEmpty() && !worksheetId.equals("0") && !worksheetId.equals(fileId)) {
|
||||||
|
if (url.contains("?")) {
|
||||||
|
url += "&worksheet_id=" + java.net.URLEncoder.encode(worksheetId, "UTF-8");
|
||||||
|
} else {
|
||||||
|
url += "?worksheet_id=" + java.net.URLEncoder.encode(worksheetId, "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("使用官方文档路径 - url: {}, fileId: {}, worksheetId: {}, range: {}", url, fileId, worksheetId, range);
|
||||||
|
return WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("官方文档路径失败,尝试其他方案", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试多种API路径格式(降级方案)
|
||||||
|
// 方案1: 尝试使用fileId作为worksheetId(如果用户只配置了一个ID)
|
||||||
|
if (wsId.equals("0") && !fileId.equals(worksheetId)) {
|
||||||
|
try {
|
||||||
|
String url = baseUrl + "/airsheet/" + fileId + "/worksheets/" + fileId;
|
||||||
|
if (range != null && !range.trim().isEmpty()) {
|
||||||
|
url += "?range=" + java.net.URLEncoder.encode(range, "UTF-8");
|
||||||
|
}
|
||||||
|
log.debug("尝试方案1 - 使用fileId作为worksheetId - url: {}", url);
|
||||||
|
return WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("方案1失败,尝试其他方案", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方案2: 使用 /range_data 子路径(根据官方文档,这是读取区域数据的标准路径)
|
||||||
|
// 注意:range_data接口需要使用 row_from, row_to, col_from, col_to 参数,而不是 range=A1:B5
|
||||||
|
try {
|
||||||
|
String url = baseUrl + "/airsheet/" + fileId + "/worksheets/" + wsId + "/range_data";
|
||||||
|
if (range != null && !range.trim().isEmpty()) {
|
||||||
|
// 尝试解析A1:B5格式的range,转换为行列参数
|
||||||
|
int[] rangeParams = parseRangeToRowCol(range);
|
||||||
|
if (rangeParams != null && rangeParams.length == 4) {
|
||||||
|
// 使用行列参数格式(row_from, row_to, col_from, col_to)
|
||||||
|
// 注意:WPS365的行列索引可能从0开始或从1开始,需要测试确认
|
||||||
|
url += "?row_from=" + rangeParams[0] + "&row_to=" + rangeParams[1]
|
||||||
|
+ "&col_from=" + rangeParams[2] + "&col_to=" + rangeParams[3];
|
||||||
|
} else {
|
||||||
|
// 如果解析失败,尝试作为range参数传递
|
||||||
|
url += "?range=" + java.net.URLEncoder.encode(range, "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("尝试方案2 - 使用/range_data子路径 - url: {}", url);
|
||||||
|
return WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("方案2失败,尝试其他方案", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方案3: 使用 /values 子路径
|
||||||
|
try {
|
||||||
|
String url = baseUrl + "/airsheet/" + fileId + "/worksheets/" + wsId + "/values";
|
||||||
|
if (range != null && !range.trim().isEmpty()) {
|
||||||
|
url += "?range=" + java.net.URLEncoder.encode(range, "UTF-8");
|
||||||
|
}
|
||||||
|
log.debug("尝试方案3 - 使用/values子路径 - url: {}", url);
|
||||||
|
return WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("方案3失败,尝试其他方案", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方案4: 基础路径(不带子路径)
|
||||||
|
String url = baseUrl + "/airsheet/" + fileId + "/worksheets/" + wsId;
|
||||||
|
if (range != null && !range.trim().isEmpty()) {
|
||||||
|
url += "?range=" + java.net.URLEncoder.encode(range, "UTF-8");
|
||||||
|
}
|
||||||
|
log.debug("尝试方案4 - 基础路径 - url: {}", url);
|
||||||
JSONObject result = WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
|
JSONObject result = WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
|
||||||
return result;
|
return result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -274,19 +349,13 @@ public class WPS365ApiServiceImpl implements IWPS365ApiService {
|
|||||||
public JSONObject updateAirSheetCells(String accessToken, String fileId, String worksheetId, String range, List<List<Object>> values) {
|
public JSONObject updateAirSheetCells(String accessToken, String fileId, String worksheetId, String range, List<List<Object>> values) {
|
||||||
try {
|
try {
|
||||||
// WPS365 AirSheet API路径格式
|
// WPS365 AirSheet API路径格式
|
||||||
// 注意:AirSheet中,fileId和worksheetId可能是同一个值
|
// 根据文档:https://open.wps.cn/documents/app-integration-dev/wps365/server/airsheet/worksheets/VbHZwButmh
|
||||||
|
// 正确路径:https://openapi.wps.cn/v7/airsheet/{file_id}/worksheets
|
||||||
|
// 注意:路径中不需要 worksheet_id,只需要 file_id
|
||||||
String baseUrl = "https://openapi.wps.cn/v7";
|
String baseUrl = "https://openapi.wps.cn/v7";
|
||||||
|
|
||||||
// 如果worksheetId为空或与fileId相同,说明用户只配置了一个ID
|
// 使用官方文档中的正确路径格式
|
||||||
String wsId;
|
String url = baseUrl + "/airsheet/" + fileId + "/worksheets";
|
||||||
if (worksheetId == null || worksheetId.trim().isEmpty() || worksheetId.equals(fileId)) {
|
|
||||||
wsId = fileId;
|
|
||||||
} else {
|
|
||||||
wsId = worksheetId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 尝试不同的API路径格式
|
|
||||||
String url = baseUrl + "/airsheet/" + fileId + "/worksheets/" + wsId;
|
|
||||||
|
|
||||||
// 构建请求体
|
// 构建请求体
|
||||||
JSONObject requestBody = new JSONObject();
|
JSONObject requestBody = new JSONObject();
|
||||||
@@ -309,23 +378,106 @@ public class WPS365ApiServiceImpl implements IWPS365ApiService {
|
|||||||
}
|
}
|
||||||
requestBody.put("values", valuesArray);
|
requestBody.put("values", valuesArray);
|
||||||
|
|
||||||
|
// 如果指定了worksheetId,也可以添加到请求体中(如果API支持)
|
||||||
|
if (worksheetId != null && !worksheetId.trim().isEmpty() && !worksheetId.equals("0") && !worksheetId.equals(fileId)) {
|
||||||
|
requestBody.put("worksheet_id", worksheetId);
|
||||||
|
}
|
||||||
|
|
||||||
String bodyStr = requestBody.toJSONString();
|
String bodyStr = requestBody.toJSONString();
|
||||||
log.debug("更新AirSheet数据 - url: {}, fileId: {}, worksheetId: {}, range: {}, values: {}",
|
log.debug("更新AirSheet数据 - url: {}, fileId: {}, worksheetId: {}, range: {}, values: {}",
|
||||||
url, fileId, wsId, range, bodyStr);
|
url, fileId, worksheetId, range, bodyStr);
|
||||||
|
|
||||||
try {
|
|
||||||
return WPS365ApiUtil.httpRequest("PUT", url, accessToken, bodyStr);
|
return WPS365ApiUtil.httpRequest("PUT", url, accessToken, bodyStr);
|
||||||
} catch (Exception e) {
|
|
||||||
// 如果失败,尝试使用 /values 子路径
|
|
||||||
log.warn("使用基础路径失败,尝试/values子路径", e);
|
|
||||||
String urlWithValues = baseUrl + "/airsheet/" + fileId + "/worksheets/" + wsId + "/values";
|
|
||||||
log.debug("尝试使用/values子路径 - url: {}", urlWithValues);
|
|
||||||
return WPS365ApiUtil.httpRequest("PUT", urlWithValues, accessToken, bodyStr);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("更新AirSheet数据失败 - fileId: {}, worksheetId: {}, range: {}", fileId, worksheetId, range, e);
|
log.error("更新AirSheet数据失败 - fileId: {}, worksheetId: {}, range: {}", fileId, worksheetId, range, e);
|
||||||
throw new RuntimeException("更新AirSheet数据失败: " + e.getMessage(), e);
|
throw new RuntimeException("更新AirSheet数据失败: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析A1:B5格式的range,转换为行列参数
|
||||||
|
* 返回数组:[row_from, row_to, col_from, col_to]
|
||||||
|
* 注意:WPS365的行列索引可能从0开始或从1开始,这里假设从1开始(Excel标准)
|
||||||
|
*
|
||||||
|
* @param range 单元格范围,如 "A1:B5"
|
||||||
|
* @return 行列参数数组,如果解析失败返回null
|
||||||
|
*/
|
||||||
|
private int[] parseRangeToRowCol(String range) {
|
||||||
|
if (range == null || range.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 解析A1:B5格式
|
||||||
|
String[] parts = range.split(":");
|
||||||
|
if (parts.length != 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String startCell = parts[0].trim();
|
||||||
|
String endCell = parts[1].trim();
|
||||||
|
|
||||||
|
// 解析起始单元格,如 "A1" -> row=1, col=1
|
||||||
|
int[] start = parseCellAddress(startCell);
|
||||||
|
int[] end = parseCellAddress(endCell);
|
||||||
|
|
||||||
|
if (start == null || end == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回 [row_from, row_to, col_from, col_to]
|
||||||
|
// 注意:WPS365可能从0开始索引,这里先使用从1开始的索引(Excel标准)
|
||||||
|
// 如果API要求从0开始,需要减1
|
||||||
|
return new int[]{start[0], end[0], start[1], end[1]};
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("解析range失败: {}", range, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析单元格地址,如 "A1" -> [row=1, col=1]
|
||||||
|
*
|
||||||
|
* @param cellAddress 单元格地址,如 "A1", "B5"
|
||||||
|
* @return [row, col] 数组,如果解析失败返回null
|
||||||
|
*/
|
||||||
|
private int[] parseCellAddress(String cellAddress) {
|
||||||
|
if (cellAddress == null || cellAddress.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 分离字母部分(列)和数字部分(行)
|
||||||
|
// 例如 "A1" -> col="A", row="1"
|
||||||
|
String colStr = "";
|
||||||
|
String rowStr = "";
|
||||||
|
|
||||||
|
for (char c : cellAddress.toCharArray()) {
|
||||||
|
if (Character.isLetter(c)) {
|
||||||
|
colStr += c;
|
||||||
|
} else if (Character.isDigit(c)) {
|
||||||
|
rowStr += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colStr.isEmpty() || rowStr.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换列字母为数字,A=1, B=2, ..., Z=26, AA=27, ...
|
||||||
|
int col = 0;
|
||||||
|
for (char c : colStr.toUpperCase().toCharArray()) {
|
||||||
|
col = col * 26 + (c - 'A' + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换行号为整数
|
||||||
|
int row = Integer.parseInt(rowStr);
|
||||||
|
|
||||||
|
return new int[]{row, col};
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("解析单元格地址失败: {}", cellAddress, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,14 @@ public class WPS365OAuthServiceImpl implements IWPS365OAuthService {
|
|||||||
authUrl.append("&state=").append(state);
|
authUrl.append("&state=").append(state);
|
||||||
log.debug("授权URL参数 - state: {}", state);
|
log.debug("授权URL参数 - state: {}", state);
|
||||||
|
|
||||||
|
// prompt参数(可选,用于控制授权页面显示)
|
||||||
|
// prompt=consent: 强制显示授权确认页面,即使用户已授权过
|
||||||
|
// prompt=login: 强制显示登录页面
|
||||||
|
// 如果不添加此参数,已登录且已授权的用户会直接跳过授权页面
|
||||||
|
// 注意:WPS365可能不支持此参数,如果不支持会被忽略
|
||||||
|
authUrl.append("&prompt=consent");
|
||||||
|
log.debug("授权URL参数 - prompt: consent (强制显示授权确认页面)");
|
||||||
|
|
||||||
String result = authUrl.toString();
|
String result = authUrl.toString();
|
||||||
log.info("生成授权URL: {}", result);
|
log.info("生成授权URL: {}", result);
|
||||||
log.warn("⚠️ 请确保WPS365开放平台配置的回调地址与以下地址完全一致(包括协议、域名、路径):");
|
log.warn("⚠️ 请确保WPS365开放平台配置的回调地址与以下地址完全一致(包括协议、域名、路径):");
|
||||||
@@ -148,6 +156,10 @@ public class WPS365OAuthServiceImpl implements IWPS365OAuthService {
|
|||||||
log.info(" - response_type: code");
|
log.info(" - response_type: code");
|
||||||
log.info(" - scope: {}", scope);
|
log.info(" - scope: {}", scope);
|
||||||
log.info(" - state: {}", state);
|
log.info(" - state: {}", state);
|
||||||
|
log.info(" - prompt: consent (强制显示授权确认页面)");
|
||||||
|
log.info("💡 说明:已添加 prompt=consent 参数,强制显示授权确认页面");
|
||||||
|
log.info(" 如果用户已登录且已授权过,WPS365可能会跳过授权页面直接返回code");
|
||||||
|
log.info(" 这是正常的OAuth2行为,不是安全问题");
|
||||||
log.info("如果仍然报错,请检查:");
|
log.info("如果仍然报错,请检查:");
|
||||||
log.info(" 1. WPS365平台配置的回调地址是否与上述redirect_uri完全一致");
|
log.info(" 1. WPS365平台配置的回调地址是否与上述redirect_uri完全一致");
|
||||||
log.info(" 2. 参数名是否正确(WPS365可能使用app_id而不是client_id)");
|
log.info(" 2. 参数名是否正确(WPS365可能使用app_id而不是client_id)");
|
||||||
|
|||||||
Reference in New Issue
Block a user