meituan
This commit is contained in:
13
pom.xml
13
pom.xml
@ -190,6 +190,12 @@
|
|||||||
<version>2.11.1</version> <!-- 可根据需要选择版本 -->
|
<version>2.11.1</version> <!-- 可根据需要选择版本 -->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Apache Commons Codec -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
<version>1.15</version>
|
||||||
|
</dependency>
|
||||||
<!-- swagger2 -->
|
<!-- swagger2 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>io.springfox</groupId>
|
||||||
@ -261,6 +267,13 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.meituan.sdk</groupId>
|
||||||
|
<artifactId>sdk</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${project.basedir}/src/main/resources/lib/MtOpJavaSDK-1.0-SNAPSHOT.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
|
|||||||
@ -33,13 +33,10 @@ public class VerifyController {
|
|||||||
|
|
||||||
@ApiOperation(value = "接收需据接口")
|
@ApiOperation(value = "接收需据接口")
|
||||||
@GetMapping("/Prepare")
|
@GetMapping("/Prepare")
|
||||||
public Result prepare(@RequestParam("code") String code, @RequestParam("sign") String sign, @RequestParam("developerId") Long developerId, @RequestParam("businessId") int businessId,
|
public Result prepare(@RequestParam("code") String code) throws Exception {
|
||||||
@RequestParam("state") String state) throws Exception {
|
|
||||||
|
|
||||||
log.info("接收美团授权数据 - code: {}, sign: {}, developerId: {}, businessId: {}, state: {}",
|
|
||||||
code, sign, developerId, businessId, state);
|
|
||||||
|
|
||||||
douyinService.prepare( null);
|
douyinService.getAccessToken( code);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,4 +8,6 @@ public interface DouyinService {
|
|||||||
|
|
||||||
|
|
||||||
void prepare(List<String> orderIds) throws Exception;
|
void prepare(List<String> orderIds) throws Exception;
|
||||||
|
|
||||||
|
void getAccessToken(String code);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,31 @@
|
|||||||
package com.sczx.order.service.impl;
|
package com.sczx.order.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.aliyun.tea.TeaException;
|
import com.aliyun.tea.TeaException;
|
||||||
import com.douyin.openapi.client.Client;
|
import com.douyin.openapi.client.Client;
|
||||||
import com.douyin.openapi.client.models.*;
|
import com.douyin.openapi.client.models.*;
|
||||||
import com.douyin.openapi.credential.models.Config;
|
import com.douyin.openapi.credential.models.Config;
|
||||||
|
|
||||||
|
|
||||||
|
import com.meituan.sdk.DefaultMeituanClient;
|
||||||
|
import com.meituan.sdk.MeituanClient;
|
||||||
|
import com.meituan.sdk.auth.MeituanTokenResponse;
|
||||||
|
import com.meituan.sdk.internal.utils.SignerUtil;
|
||||||
|
import com.sczx.order.common.Result;
|
||||||
import com.sczx.order.config.DouyinTokenManager;
|
import com.sczx.order.config.DouyinTokenManager;
|
||||||
import com.sczx.order.exception.InnerException;
|
import com.sczx.order.exception.InnerException;
|
||||||
import com.sczx.order.service.DouyinService;
|
import com.sczx.order.service.DouyinService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -35,6 +43,12 @@ public class DouyinServiceImpl implements DouyinService {
|
|||||||
//@Value("${douyin.poiId}")
|
//@Value("${douyin.poiId}")
|
||||||
private String POI_ID = "7442188302710065206";
|
private String POI_ID = "7442188302710065206";
|
||||||
|
|
||||||
|
private String meituanApiUrl = "https://api-open-cater.meituan.com/oauth/token";
|
||||||
|
|
||||||
|
private Long DeveloperId = 116997L;
|
||||||
|
|
||||||
|
private String Signkey = "n8xihtshk7t1luvi";
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
public String resolveShortUrlToGetObjectId(String shortUrl) {
|
public String resolveShortUrlToGetObjectId(String shortUrl) {
|
||||||
@ -118,4 +132,22 @@ public class DouyinServiceImpl implements DouyinService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getAccessToken(String code) {
|
||||||
|
try {
|
||||||
|
// 使用美团SDK构建客户端
|
||||||
|
MeituanClient client = DefaultMeituanClient.builder(DeveloperId, Signkey).build();
|
||||||
|
|
||||||
|
|
||||||
|
// 使用美团SDK的getOAuthToken方法获取token
|
||||||
|
MeituanTokenResponse response = client.getOAuthToken(58, code);
|
||||||
|
|
||||||
|
|
||||||
|
log.info("获取access_token响应结果: {}", JSONObject.toJSONString(response));
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取access_token异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/main/java/com/sczx/order/utils/DouyinTokenManager.java
Normal file
107
src/main/java/com/sczx/order/utils/DouyinTokenManager.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package com.sczx.order.utils;
|
||||||
|
|
||||||
|
import com.aliyun.tea.TeaException;
|
||||||
|
import com.douyin.openapi.client.Client;
|
||||||
|
import com.douyin.openapi.client.models.OauthClientTokenRequest;
|
||||||
|
import com.douyin.openapi.client.models.OauthClientTokenResponse;
|
||||||
|
import com.douyin.openapi.credential.models.Config;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抖音 client_token 管理器
|
||||||
|
* 负责定时获取和缓存 client_token
|
||||||
|
*/
|
||||||
|
public class DouyinTokenManager {
|
||||||
|
|
||||||
|
// 应用凭证信息
|
||||||
|
private static final String CLIENT_KEY = "awomt6nnjlfc491m";
|
||||||
|
private static final String CLIENT_SECRET = "c678c411c7a68c6f97969f2dbd8ef8fc";
|
||||||
|
|
||||||
|
// Token 缓存
|
||||||
|
private static final AtomicReference<OauthClientTokenResponse> tokenCache =
|
||||||
|
new AtomicReference<>();
|
||||||
|
|
||||||
|
// 定时任务执行器
|
||||||
|
private static final ScheduledThreadPoolExecutor scheduler =
|
||||||
|
new ScheduledThreadPoolExecutor(1, r -> {
|
||||||
|
Thread t = new Thread(r, "DouyinTokenRefreshThread");
|
||||||
|
t.setDaemon(false);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 初始化时立即获取一次 token
|
||||||
|
refreshClientToken();
|
||||||
|
|
||||||
|
// 每小时更新一次 token (3600秒)
|
||||||
|
scheduler.scheduleAtFixedRate(
|
||||||
|
DouyinTokenManager::refreshClientToken,
|
||||||
|
3600,
|
||||||
|
3600,
|
||||||
|
TimeUnit.SECONDS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前有效的 client_token
|
||||||
|
*
|
||||||
|
* @return 当前有效的 access_token
|
||||||
|
*/
|
||||||
|
public static String getCurrentToken() {
|
||||||
|
OauthClientTokenResponse response = tokenCache.get();
|
||||||
|
if (response != null && response.getData() != null) {
|
||||||
|
return response.getData().getAccessToken();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新 client_token
|
||||||
|
*/
|
||||||
|
private static void refreshClientToken() {
|
||||||
|
try {
|
||||||
|
Config config = new Config()
|
||||||
|
.setClientKey(CLIENT_KEY)
|
||||||
|
.setClientSecret(CLIENT_SECRET);
|
||||||
|
|
||||||
|
Client client = new Client(config);
|
||||||
|
|
||||||
|
OauthClientTokenRequest sdkRequest = new OauthClientTokenRequest();
|
||||||
|
sdkRequest.setClientKey(CLIENT_KEY);
|
||||||
|
sdkRequest.setClientSecret(CLIENT_SECRET);
|
||||||
|
sdkRequest.setGrantType("client_credential");
|
||||||
|
|
||||||
|
OauthClientTokenResponse sdkResponse = client.OauthClientToken(sdkRequest);
|
||||||
|
|
||||||
|
// 更新缓存
|
||||||
|
tokenCache.set(sdkResponse);
|
||||||
|
|
||||||
|
if (sdkResponse.getData() != null) {
|
||||||
|
System.out.println("抖音 client_token 更新成功,有效期至: " +
|
||||||
|
(System.currentTimeMillis() + sdkResponse.getData().getExpiresIn() * 1000));
|
||||||
|
}
|
||||||
|
} catch (TeaException e) {
|
||||||
|
System.err.println("获取抖音 client_token 失败 (TeaException): " + e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("获取抖音 client_token 失败 (Exception): " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭定时任务
|
||||||
|
*/
|
||||||
|
public static void shutdown() {
|
||||||
|
scheduler.shutdown();
|
||||||
|
|
||||||
|
// 获取当前有效的 client_token
|
||||||
|
String token = DouyinTokenManager.getCurrentToken();
|
||||||
|
|
||||||
|
// 使用 token 调用抖音 API
|
||||||
|
if (token != null) {
|
||||||
|
// 调用订单查询等接口
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/main/java/com/sczx/order/utils/MeiTuanSignUtils.java
Normal file
86
src/main/java/com/sczx/order/utils/MeiTuanSignUtils.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package com.sczx.order.utils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class MeiTuanSignUtils {
|
||||||
|
private MeiTuanSignUtils() {}
|
||||||
|
|
||||||
|
public static String getSign(String signKey, Map<String, String> params) {
|
||||||
|
try {
|
||||||
|
String sortedStr = getSortedParamStr(params);
|
||||||
|
String paraStr = signKey + sortedStr;
|
||||||
|
|
||||||
|
return createSign(paraStr);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
log.warn("getSign UnsupportedEncodingException ", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造自然排序请求参数
|
||||||
|
*
|
||||||
|
* @param params 请求
|
||||||
|
* @return 字符串
|
||||||
|
*/
|
||||||
|
private static String getSortedParamStr(Map<String, String> params) throws UnsupportedEncodingException {
|
||||||
|
Set<String> sortedParams = new TreeSet<>(params.keySet());
|
||||||
|
|
||||||
|
StringBuilder strB = new StringBuilder();
|
||||||
|
// 排除sign和空值参数
|
||||||
|
for (String key : sortedParams) {
|
||||||
|
if ("sign".equalsIgnoreCase(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = params.get(key);
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(value)) {
|
||||||
|
strB.append(key).append(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strB.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成新sign
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
private static String createSign(String str) {
|
||||||
|
if (str == null || str.length() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
try {
|
||||||
|
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
|
||||||
|
mdTemp.update(str.getBytes("UTF-8"));
|
||||||
|
|
||||||
|
byte[] md = mdTemp.digest();
|
||||||
|
int j = md.length;
|
||||||
|
char[] buf = new char[j * 2];
|
||||||
|
int k = 0;
|
||||||
|
int i = 0;
|
||||||
|
while (i < j) {
|
||||||
|
byte byte0 = md[i];
|
||||||
|
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
|
||||||
|
buf[k++] = hexDigits[byte0 & 0xf];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return new String(buf);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("create sign was failed", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/main/resources/lib/MtOpJavaSDK-1.0-SNAPSHOT.jar
Normal file
BIN
src/main/resources/lib/MtOpJavaSDK-1.0-SNAPSHOT.jar
Normal file
Binary file not shown.
Reference in New Issue
Block a user