Commit aab70d1c authored by 曾水平's avatar 曾水平

京东api接入

parent 7b9b016f
...@@ -39,6 +39,10 @@ dependencies { ...@@ -39,6 +39,10 @@ dependencies {
compile 'redis.clients:jedis' compile 'redis.clients:jedis'
compile 'com.caucho:hessian:4.0.38' compile 'com.caucho:hessian:4.0.38'
compile 'commons-io:commons-io:2.4' compile 'commons-io:commons-io:2.4'
compile 'org.apache.httpcomponents:httpcore:4.4.11'
compile 'org.apache.httpcomponents:httpcore-nio:4.4.11'
compile 'org.apache.httpcomponents:httpclient:4.5.9'
testCompile('junit:junit')
} }
test { test {
......
package cn.com.duiba.jdactivity.common.log;
import com.alibaba.fastjson.JSONObject;
/**
* @author chengsiyi
* @date 2018/12/12 11:19
*/
public final class HttpRequestLog {
private HttpRequestLog() {
}
/**
* @param url 请求地址
* @param param 请求参数
*/
public static void log(String url, String param, String result) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("url", url);
jsonObject.put("param", param);
jsonObject.put("result", result);
InnerLog.log(2, 60, null, null, jsonObject);
}
}
package cn.com.duiba.jdactivity.common.log;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 统一内部日志<br>
*
* @see <a>http://cf.dui88.com:8090/pages/viewpage.action?pageId=4494009</a>
* Created by zzy on 2017/2/27.
*/
public final class InnerLog {
private static final Logger log = LoggerFactory.getLogger("innerLog");
private static final ThreadLocal<SimpleDateFormat> localDateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
private InnerLog() {
}
/**
* 记录统一内部日志
*
* @param group 大类分组 必填
* @param type 小类分组 必填
* @param dpm 位置信息 可选
* @param dcm 内容信息 可选
* @param json JSON格式,内容根据group和type自定义 可选
*/
public static void log(int group, int type, String dpm, String dcm, JSONObject json) {
JSONObject jsonLog = new JSONObject();
jsonLog.put("group", group);
jsonLog.put("type", type);
jsonLog.put("time", localDateFormat.get().format(new Date()));
jsonLog.put("dpm", dpm);
jsonLog.put("dcm", dcm);
jsonLog.put("json", json);
log.info(jsonLog.toJSONString());
}
}
...@@ -2,11 +2,13 @@ package cn.com.duiba.jdactivity.common.utils; ...@@ -2,11 +2,13 @@ package cn.com.duiba.jdactivity.common.utils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
/** /**
* Created by gyf . * Created by gyf .
* 2018/3/29 . * 2018/3/29 .
*/ */
@Component
public final class MainApplicationContextHolder { public final class MainApplicationContextHolder {
private MainApplicationContextHolder() { private MainApplicationContextHolder() {
} }
......
package cn.com.duiba.jdactivity.common.utils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* URLUtils
* <p/>
* Created by wangyuanjie on 2018/3/21.
*/
public final class UrlUtils {
/**
* 拼接签名字符串
*
* @param prefix 前缀
* @param queryString 参数
* @return 拼接后的字符串
*/
public static String assembleUrl(String prefix, String queryString) {
if (StringUtils.isBlank(prefix)) {
return queryString;
} else {
return prefix + (prefix.contains("?") ? "&" : "?") + queryString;
}
}
/**
* 拼接签名字符串
*
* @param prefix 前缀
* @param paramsMap 参数
* @return 拼接后的字符串
*/
public static String assembleUrl(String prefix, Map<String, ?> paramsMap) {
return assembleUrl(prefix, paramsMap, true);
}
/**
* 拼接签名字符串
*
* @param prefix 前缀
* @param paramsMap 参数
* @param isUrlEncode 是否urlEncode
* @return 拼接后的字符串
*/
public static String assembleUrl(String prefix, Map<String, ?> paramsMap, boolean isUrlEncode) {
return assembleUrl(prefix, mapToQueryString(paramsMap, true, isUrlEncode));
}
/**
* 将map转为queryString
*
* @param map 参数
* @param isSort 是否排序
* @param isUrlEncode 是否需要UrlEncode
* @return queryString
*/
public static String mapToQueryString(Map<String, ?> map, boolean isSort, boolean isUrlEncode) {
Map<String, ?> tempMap;
if (isSort) {
tempMap = new TreeMap<>(map);
} else {
tempMap = map;
}
// map拼接
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, ?> entry : tempMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
String valueStr = objectToString(value);
if (StringUtils.isBlank(valueStr)) {
continue;
}
if (isUrlEncode) {
valueStr = urlEncode(valueStr);
}
// 剔除空字符串
if (StringUtils.isNotBlank(valueStr)) {
sb.append(key).append("=").append(valueStr).append("&");
}
}
String queryString = sb.toString();
if (queryString.length() > 1) {
queryString = queryString.substring(0, queryString.length() - 1);
}
return queryString;
}
/**
* 将对象转换为String
* 若对象为集合,则转换为json
*
* @param object
* @return
*/
public static String objectToString(Object object) {
if (null == object) {
return "";
}
return (object instanceof Map || object instanceof Collection)
? JSON.toJSONString(object) : object + "";
}
/**
* urlEncode
*
* @param str 字符串
* @return urlEncode之后的字符串
*/
public static String urlEncode(String str) {
try {
String[] temp = str.split("\\ ");
StringBuilder sb = new StringBuilder();
for (int t = 0; t < temp.length; t++) {
sb.append(URLEncoder.encode(temp[t], StandardCharsets.UTF_8.name()));
if (t < temp.length - 1) {
sb.append("%20");
}
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Map<String, String> explainURLParams(String params) {
Map<String, String> mapRequest = new HashMap<>();
String[] arrSplit;
// 每个键值为一组
arrSplit = params.split("[&]");
for (String strSplit : arrSplit) {
String[] arrSplitEqual;
arrSplitEqual = strSplit.split("[=]");
// 解析出键值
if (arrSplitEqual.length > 1) {
// 正确解析
mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
} else {
if (arrSplitEqual[0] != "") {
// 只有参数没有值,加入空字符
mapRequest.put(arrSplitEqual[0], "");
}
}
}
return mapRequest;
}
}
package cn.com.duiba.jdactivity.common.vo;
import java.io.Serializable;
/**
* ClassName: Result <br/>
* date: 2016年7月13日 上午10:01:40 <br/>
*
* @author zp
* @version @param <T>
* @since JDK 1.6
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = -1467576157657126613L;
/**
* 是否成功
*/
private Boolean success;
/**
* 响应码
*/
private String code;
/**
* 错误描述
*/
private String desc;
/**
* 返回的时间戳
*/
private Long timestamp;
/**
* 响应数据
*/
private T data;
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
package cn.com.duiba.jdactivity.common.vo;
/**
* Created by zzy on 2017/10/30.
*/
public final class ResultBuilder {
private ResultBuilder() {
}
/**
* 失败
*
* @param code
* @param desc
* @param <T>
* @return
*/
public static <T> Result<T> fail(String code, String desc) {
Result<T> result = new Result<>();
result.setTimestamp(System.currentTimeMillis());
result.setSuccess(false);
result.setCode(code);
result.setDesc(desc);
return result;
}
/**
* 前端对于需要根据错误信息做不同的处理时,可以定义多个业务异常枚举,通过code进行区分
*
* @param resultCode 业务错误枚举类
* @param <T>
* @return
* @see ResultCode
*/
public static <T> Result<T> fail(ResultCode resultCode) {
Result<T> result = new Result<>();
result.setTimestamp(System.currentTimeMillis());
result.setSuccess(false);
result.setCode(resultCode.getCode());
result.setDesc(resultCode.getDescription());
return result;
}
/**
* 可以自定义错误提示,统一使用默认错误码,不需要去添加业务异常枚举类
*
* @param desc
* @param <T>
* @return
*/
public static <T> Result<T> fail(String desc) {
return fail(ResultCode.C100000.getCode(), desc);
}
/**
* 带有数据的失败返回,统一使用默认错误码,不需要去添加业务异常枚举类
*
* @param resultCode
* @param data
* @param <T>
* @return
*/
public static <T> Result<T> fail(ResultCode resultCode, T data) {
Result<T> result = new Result<>();
result.setTimestamp(System.currentTimeMillis());
result.setSuccess(false);
result.setCode(resultCode.getCode());
result.setDesc(resultCode.getDescription());
result.setData(data);
return result;
}
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setTimestamp(System.currentTimeMillis());
result.setSuccess(true);
result.setData(data);
return result;
}
/**
* 成功,不返回任何数据
*
* @param <T>
* @return
*/
public static <T> Result<T> success() {
Result<T> result = new Result<>();
result.setTimestamp(System.currentTimeMillis());
result.setSuccess(true);
return result;
}
}
package cn.com.duiba.jdactivity.common.vo;
/**
* 用于管理使用系统的所有返回码,避免业务code重复<br>
* 用法:枚举_业务参数
*/
public enum ResultCode {
/**
* 状态码
*/
C100000("100000", "默认错误码"),
C100001("100001", "用户未登录"),
C100002("100002", "参数错误"),
C100003("100003", "token错误"),
C100004("100004", "用户不存在"),
C100005("100005", "活动不存在"),
C100006("100006", "活动已结束"),
//命中风控参与规则
C777777("777777", "网络错误"),
C999999("999999", "系统繁忙,请稍候"),
;
/**
* 错误码
*/
private String code;
/**
* 业务错误描述
*/
private String description;
ResultCode(String code, String description) {
this.code = code;
this.description = description;
}
public String getCode() {
return code;
}
/**
* 得到描述
*
* @return {@link String}
*/
public String getDescription() {
return description;
}
}
package cn.com.duiba.jdactivity.config;
import org.apache.http.HttpClientConnection;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.io.IOException;
/**
* 自动构建HttpClient和HttpAsyncClient
*/
@Configuration
@ConditionalOnClass(HttpClient.class)
@AutoConfigureBefore(name = "org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration")
public class HttpClientAutoConfiguration {
private static final Logger logger = LoggerFactory.getLogger(HttpClientAutoConfiguration.class);
//默认情况下不能调用CloseableHttpResponse.close()否则tcp长连接会关闭,但是这里构造的httpClient可以这样调用,因为经过aop处理过。
//这个httpClient可以被业务使用,但是由于这个httpClient也会被FeignClient使用,所以注意有些参数不能设置过小
@Primary
@Bean(name = "httpClient", destroyMethod = "close")
public CloseableHttpClient httpClient() {
return HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(60000).setConnectionRequestTimeout(10).build())
.setMaxConnPerRoute(100)
.setMaxConnTotal(5000)//一定要设置maxConnTotal,不然默认是10
.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36")//userAgent仿真,以防第三方设置的WAF判断了UA从而调用失败.
.disableAutomaticRetries()//禁止重试
.disableCookieManagement()
// 默認會redirect,假如調用方不希望redirect,需要在RequestConfig上做文章,比如:HttpGet req; req.setConfig(RequestConfig.custom().setRedirectsEnabled(false).build());
// .disableRedirectHandling()
.useSystemProperties()//for proxy
.setKeepAliveStrategy(getKeepAliveStrategy())
.setRequestExecutor(new HttpRequestExecutor() {
@Override
public HttpResponse execute(HttpRequest request, HttpClientConnection conn, HttpContext context) throws IOException, HttpException {
return super.execute(request, conn, context);
}
})
.evictExpiredConnections()//每隔10秒主动扫描并逐出超时的连接(超过keepAliveTimeout)
// .setConnectionTimeToLive(30, TimeUnit.SECONDS)//这个要么不设,要么就设大点,这个用于设置连接最长保留多长时间(从创建开始计算)。而keepalive策略会在连接被使用后重新计算存活时间
.build();
}
private ConnectionKeepAliveStrategy getKeepAliveStrategy() {
return new DefaultConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
long time = super.getKeepAliveDuration(response, context);
if (time == -1) {
time = 30000;//链接最多空闲30秒
}
return time;
}
};
}
}
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.com.duiba.jdactivity.core.autoconfigure.redis; package cn.com.duiba.jdactivity.config;
import cn.com.duiba.jdactivity.dao.redis.Hessian2SerializationRedisSerializer;
import cn.com.duiba.jdactivity.dao.redis.JedisConnectionFactoryBean;
import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
......
package cn.com.duiba.jdactivity.web; package cn.com.duiba.jdactivity.controller;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
......
package cn.com.duiba.jdactivity.controller;
import cn.com.duiba.jdactivity.developer.jd.AppKeyEnum;
import cn.com.duiba.jdactivity.developer.jd.domain.AccessTokenResponse;
import cn.com.duiba.jdactivity.developer.jd.domain.JosParameters;
import cn.com.duiba.jdactivity.developer.jd.utils.AccessTokenUtils;
import cn.com.duiba.jdactivity.developer.jd.utils.LoginUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 订购商家用
*
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 13:58
*/
@RestController
@RequestMapping("/fw")
public class LoginController {
public static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
@Resource
private AccessTokenUtils accessTokenUtils;
@RequestMapping("/login")
public String login(
@RequestParam(required = false) String code,
@RequestParam(required = false) String state) {
if (StringUtils.isBlank(code)) {
return code + "参数缺失";
}
if (StringUtils.isNoneBlank(state)) {
JosParameters josParameters = LoginUtils.getStateParam(state);
}
AccessTokenResponse accessTokenByCode = accessTokenUtils.getAccessTokenByCode(AppKeyEnum.DUIBA, code);
if (accessTokenByCode.isOk()) {
}
return null;
}
@RequestMapping("/index")
public String index() {
return null;
}
}
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package cn.com.duiba.jdactivity.core.autoconfigure.redis; package cn.com.duiba.jdactivity.dao.redis;
import com.caucho.hessian.io.Hessian2Input; import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output; import com.caucho.hessian.io.Hessian2Output;
...@@ -79,6 +79,7 @@ public class Hessian2SerializationRedisSerializer implements RedisSerializer<Obj ...@@ -79,6 +79,7 @@ public class Hessian2SerializationRedisSerializer implements RedisSerializer<Obj
this.compressionThreshold = compressionThreshold; this.compressionThreshold = compressionThreshold;
} }
@Override
public Object deserialize(byte[] bytes) { public Object deserialize(byte[] bytes) {
if (bytes == null || bytes.length == 0) { if (bytes == null || bytes.length == 0) {
return null; return null;
...@@ -102,6 +103,7 @@ public class Hessian2SerializationRedisSerializer implements RedisSerializer<Obj ...@@ -102,6 +103,7 @@ public class Hessian2SerializationRedisSerializer implements RedisSerializer<Obj
} }
} }
@Override
public byte[] serialize(Object object) { public byte[] serialize(Object object) {
if (object == null) { if (object == null) {
return EMPTY_ARRAY; return EMPTY_ARRAY;
......
package cn.com.duiba.jdactivity.core.autoconfigure.redis; package cn.com.duiba.jdactivity.dao.redis;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
......
package cn.com.duiba.jdactivity.developer.jd;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 14:56
*/
@SuppressWarnings("AlibabaEnumConstantsMustHaveComment")
public enum AppKeyEnum {
DUIBA("互动营销-兑吧", "B0F491866BC8C8BA5954B4DFCCF283CC", "571df532d10c4c1e839cef1f1a9a2113", "www.jd.com");
private String appName;
private String appKey;
private String appSecret;
/**
* 应用信息设置的回调地址
*/
private String url;
AppKeyEnum(String appName, String appKey, String appSecret, String url) {
this.appName = appName;
this.appKey = appKey;
this.appSecret = appSecret;
this.url = url;
}
public String getAppName() {
return appName;
}
public String getAppKey() {
return appKey;
}
public String getAppSecret() {
return appSecret;
}
public String getUrl() {
return url;
}
}
package cn.com.duiba.jdactivity.developer.jd;
import com.jd.open.api.sdk.request.JdRequest;
import com.jd.open.api.sdk.request.user.UserGetUserInfoByOpenIdRequest;
/**
* 京东api
*
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/11 13:47
*/
@SuppressWarnings("AlibabaEnumConstantsMustHaveComment")
public enum JdApiEnum {
GET(UserGetUserInfoByOpenIdRequest.class, true),
;
private Class<? extends JdRequest> request;
private Boolean needAccessToken;
JdApiEnum(Class<? extends JdRequest> request,
Boolean needAccessToken) {
this.request = request;
this.needAccessToken = needAccessToken;
}
public Class<? extends JdRequest> getRequest() {
return request;
}
public Boolean getNeedAccessToken() {
return needAccessToken;
}
}
package cn.com.duiba.jdactivity.developer.jd;
import com.alibaba.fastjson.JSON;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.request.openid.JosTokenSourceToOpenIdRequest;
import com.jd.open.api.sdk.response.openid.JosTokenSourceToOpenIdResponse;
import com.jd.security.tdeclient.SecretJdClient;
import com.jd.security.tdeclient.TDEClient;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/11 13:57
*/
public class Main {
public static final String SERVER_URL = "https://api.jd.com/routerjson";
public static final String LOG_SERVER_URL = "https://api-log.jd.com/routerjson";
public static final String appKey = "B0F491866BC8C8BA5954B4DFCCF283CC";
public static final String appSecret = "571df532d10c4c1e839cef1f1a9a2113";
public static final String accessToken = "35d57da4101d498b99e2963302d5e112ntdk";
public static void main(String[] args) {
testDataEncryptOrDecrypt();
}
private static void test() {
try {
String accessToken = "";
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, appKey, appSecret);
JosTokenSourceToOpenIdRequest request = new JosTokenSourceToOpenIdRequest();
request.setToken("36A9C36584F3519B8FA4C5072B9211DFD6D8A7B4778C7184EE59A9BC9B582914");
request.setSource("02");
request.setAppKey("B0F491866BC8C8BA5954B4DFCCF283CC");
JosTokenSourceToOpenIdResponse response = client.execute(request);
System.out.println(JSON.toJSONString(response));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void testDataEncryptOrDecrypt() {
try {
/*
* 请求宙斯网关获取凭证和密钥
* 1、凭证和密钥缓存本地(用于数据加解密)
* 2、数据来源于请求宙斯网关 API 敏感字段值
* 3、数据加解密案例如下
*/
TDEClient tdeClient = SecretJdClient.
getInstance(SERVER_URL, accessToken, appKey, appSecret);
String type = "phone";
String plaintext = "16612341234";
// 加密手机号
String ciphertext = tdeClient.encryptString(plaintext);
System.out.println(type + "明文:" + plaintext + "—> 密文:" + ciphertext);
// 判断是否为加密手机号码数据
if (tdeClient.isEncryptData(ciphertext)) {
// 解密手机号
plaintext = tdeClient.decryptString(ciphertext);
System.out.println(type + "密文:" + ciphertext + "—> 明文:" + plaintext);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package cn.com.duiba.jdactivity.developer.jd;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 15:05
*/
@Configuration
@ConfigurationProperties(prefix = "jd.url")
public class UrlConstants {
private String oauthUrl = "https://open-oauth.jd.com/oauth2";
private String apiServerUrl = "https://api.jd.com/routerjson";
private String logServerUrl = "https://api-log.jd.com/routerjson";
public String getOauthUrl() {
return oauthUrl;
}
public void setOauthUrl(String oauthUrl) {
this.oauthUrl = oauthUrl;
}
public String getApiServerUrl() {
return apiServerUrl;
}
public void setApiServerUrl(String apiServerUrl) {
this.apiServerUrl = apiServerUrl;
}
public String getLogServerUrl() {
return logServerUrl;
}
public void setLogServerUrl(String logServerUrl) {
this.logServerUrl = logServerUrl;
}
}
package cn.com.duiba.jdactivity.developer.jd.domain;
/*
{
"access_token":"00bc0ce7409d49d9bc0317a0ba6221740mdb",
"expires_in":86399,
"refresh_token":"0d20c7c3be7e4075904b7d23825de10am3yz",
"scope":"snsapi_base",
"open_id":"hin2kGWWyBuhQP0mv-IQoBxyxEhk5qUMWNnTrAmzEII",
"uid":"2731075896",
"time":1620895134560,
"token_type":"bearer",
"code":0
}
*/
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 15:24
*/
public class AccessToken {
private String access_token;
/**
* 相对过期时间,秒,
*/
private Long expires_in;
private String refresh_token;
private String scope;
private String open_id;
private String uid;
private Long time;
private String token_type;
private Integer code;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public Long getExpires_in() {
return expires_in;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getOpen_id() {
return open_id;
}
public void setOpen_id(String open_id) {
this.open_id = open_id;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
package cn.com.duiba.jdactivity.developer.jd.domain;
import java.util.Objects;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 16:44
*/
public class AccessTokenResponse extends AccessToken {
private static final int SUCCESS = 0;
/**
* 错误信息
*/
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public boolean isOk() {
return Objects.equals(SUCCESS, getCode());
}
}
package cn.com.duiba.jdactivity.developer.jd.domain;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 14:39
*/
public class JosParameters {
/**
* 订购到期时间
*/
private Long end_date;
/**
* 订购商品版本
*/
private Integer version_no;
/**
* 购买的收费项目编码
*/
private String item_code;
/**
* 服务应用的appKey
*/
private String app_key;
/**
* 购买人
*/
private String user_name;
/**
* 购买数量
*/
private Integer article_num;
public Long getEnd_date() {
return end_date;
}
public void setEnd_date(Long end_date) {
this.end_date = end_date;
}
public Integer getVersion_no() {
return version_no;
}
public void setVersion_no(Integer version_no) {
this.version_no = version_no;
}
public String getItem_code() {
return item_code;
}
public void setItem_code(String item_code) {
this.item_code = item_code;
}
public String getApp_key() {
return app_key;
}
public void setApp_key(String app_key) {
this.app_key = app_key;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public Integer getArticle_num() {
return article_num;
}
public void setArticle_num(Integer article_num) {
this.article_num = article_num;
}
}
package cn.com.duiba.jdactivity.developer.jd.domain;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 14:10
*/
public class StateParam {
private JosParameters jos_parameters;
public JosParameters getJosParameters() {
return jos_parameters;
}
public void setJosParameters(JosParameters josParameters) {
this.jos_parameters = josParameters;
}
}
package cn.com.duiba.jdactivity.developer.jd.utils;
import cn.com.duiba.jdactivity.common.utils.HttpClientUtil;
import cn.com.duiba.jdactivity.common.utils.UrlUtils;
import cn.com.duiba.jdactivity.developer.jd.AppKeyEnum;
import cn.com.duiba.jdactivity.developer.jd.UrlConstants;
import cn.com.duiba.jdactivity.developer.jd.domain.AccessTokenResponse;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.TreeMap;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/11 15:00
*/
@Component
public class AccessTokenUtils {
private static final String TO_LOGIN_SUFFIX = "/to_login";
private static final String ACCESS_TOKEN_SUFFIX = "/access_token";
private static final String NULL = "null";
@Resource
private UrlConstants urlConstants;
@Resource
private HttpClientUtil httpClientUtil;
public String generateAuthUrl(AppKeyEnum appKey, String state) {
Map<String, String> param = new TreeMap<>();
param.put("app_key", appKey.getAppKey());
param.put("response_type", "code");
param.put("redirect_uri", appKey.getUrl());
param.put("scope", "snsapi_base");
param.put("state", state);
return UrlUtils.assembleUrl(urlConstants.getOauthUrl() + TO_LOGIN_SUFFIX, param);
}
public AccessTokenResponse getAccessTokenByCode(AppKeyEnum appKey, String code) {
Map<String, String> param = new TreeMap<>();
param.put("app_key", appKey.getAppKey());
param.put("app_secret", appKey.getAppSecret());
param.put("grant_type", "authorization_code");
param.put("code", code);
String url = UrlUtils.assembleUrl(urlConstants.getOauthUrl() + ACCESS_TOKEN_SUFFIX, param);
String s = httpClientUtil.sendGet(url);
if (StringUtils.isNotBlank(s)
&& !StringUtils.equalsIgnoreCase(NULL, s)
&& JSONValidator.from(s).validate()) {
return JSONObject.parseObject(s, AccessTokenResponse.class);
}
return null;
}
}
package cn.com.duiba.jdactivity.developer.jd.utils;
import cn.com.duiba.jdactivity.developer.jd.UrlConstants;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 15:08
*/
@Component
public class ApiUtil {
@Resource
private UrlConstants urlConstants;
// private void test() {
// try {
// String accessToken = "";
// JdClient client = new DefaultJdClient(urlConstants.getApiServerUrl(), accessToken, appKey, appSecret);
// JosTokenSourceToOpenIdRequest request = new JosTokenSourceToOpenIdRequest();
// request.setToken("36A9C36584F3519B8FA4C5072B9211DFD6D8A7B4778C7184EE59A9BC9B582914");
// request.setSource("02");
// request.setAppKey("B0F491866BC8C8BA5954B4DFCCF283CC");
// JosTokenSourceToOpenIdResponse response = client.execute(request);
// System.out.println(JSON.toJSONString(response));
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// public static void testDataEncryptOrDecrypt() {
// try {
// /*
// * 请求宙斯网关获取凭证和密钥
// * 1、凭证和密钥缓存本地(用于数据加解密)
// * 2、数据来源于请求宙斯网关 API 敏感字段值
// * 3、数据加解密案例如下
// */
// TDEClient tdeClient = SecretJdClient.
// getInstance(SERVER_URL, accessToken, appKey, appSecret);
// String type = "phone";
// String plaintext = "16612341234";
// // 加密手机号
// String ciphertext = tdeClient.encryptString(plaintext);
// System.out.println(type + "明文:" + plaintext + "—> 密文:" + ciphertext);
// // 判断是否为加密手机号码数据
//
// if (tdeClient.isEncryptData(ciphertext)) {
// // 解密手机号
// plaintext = tdeClient.decryptString(ciphertext);
// System.out.println(type + "密文:" + ciphertext + "—> 明文:" + plaintext);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
}
package cn.com.duiba.jdactivity.developer.jd.utils;
import cn.com.duiba.jdactivity.developer.jd.domain.JosParameters;
import cn.com.duiba.jdactivity.developer.jd.domain.StateParam;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import org.apache.commons.lang3.StringUtils;
import java.util.Base64;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 14:45
*/
public class LoginUtils {
public static JosParameters getStateParam(String state) {
StateParam stateParam = null;
// state 中如果有 “+” 号,因浏览器交互的原因,会出现 “+” 号替换成空格的现象,导致授权报错,如果出现此种情况,请把的 state 中的空格再替换成 “+” 号
state = state.replace(" ", "+");
String stateBody = new String(Base64.getDecoder().decode(state));
if (StringUtils.isNoneBlank(stateBody)
&& !StringUtils.equalsIgnoreCase("null", stateBody)
&& JSONValidator.from(stateBody).validate()) {
stateParam = JSONObject.parseObject(stateBody, StateParam.class);
}
return stateParam.getJosParameters();
}
public static void main(String[] args) {
System.out.println(JSON.toJSONString(getStateParam("eyJqb3NfcGFyYW1ldGVycyI6eyJlbmRfZGF0ZSI6MTYyMTkzOTkzMDAwMCwidmVyc2lvbl9ubyI6MiwiaXRlbV9jb2RlIjoiRldfR09PRFMtNTQ5MjExLTIiLCJhcHBfa2V5IjoiMWJhZGExYWFlZDEzNGM2OTk2ZjMxZTgxZDM3MmFjNDgiLCJ1c2VyX25hbWUiOiJkdWliYTIwMjFqZCIsImFydGljbGVfbnVtIjoxfX0=")));
}
}
...@@ -6,6 +6,7 @@ spring.autoconfigure.exclude=\ ...@@ -6,6 +6,7 @@ spring.autoconfigure.exclude=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
# tomcat # tomcat
server.port=8080 server.port=8080
server.tomcat.accesslog.enabled=false server.tomcat.accesslog.enabled=false
...@@ -22,8 +23,10 @@ logging.file.path=${user.home}/logs/${spring.application.name} ...@@ -22,8 +23,10 @@ logging.file.path=${user.home}/logs/${spring.application.name}
mybatis.config-location=classpath:mybatis/config.xml mybatis.config-location=classpath:mybatis/config.xml
mybatis.mapper-locations=classpath:mybatis/*/*.xml mybatis.mapper-locations=classpath:mybatis/*/*.xml
#redis 注意这是内网地址 #redis 注意这是内网地址
spring.redis.host=redis-x4n822igaxnu-proxy-nlb.jvessel-open-hb.jdcloud.com #spring.redis.host=redis-x4n822igaxnu-proxy-nlb.jvessel-open-hb.jdcloud.com
spring.redis.password=kP6oWdeYU78tHee #spring.redis.password=kP6oWdeYU78tHee
spring.redis.host=localhost
spring.redis.password=mypassword
spring.redis.timeout=1000 spring.redis.timeout=1000
spring.redis.jedis.pool.max-wait=100 spring.redis.jedis.pool.max-wait=100
spring.redis.jedis.pool.min-idle=1 spring.redis.jedis.pool.min-idle=1
......
package cn.com.duiba.jdactivity; package cn.com.duiba.jdactivity;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest @SpringBootTest
class JdActivityApplicationTests { public class BaseTest {
@Test
void contextLoads() {
}
} }
...@@ -3,11 +3,9 @@ package cn.com.duiba.jdactivity; ...@@ -3,11 +3,9 @@ package cn.com.duiba.jdactivity;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import redis.clients.jedis.Jedis;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
...@@ -18,9 +16,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. ...@@ -18,9 +16,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
* @author zsp (zengshuiping@duiba.com.cn) * @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/12 15:28 * @date 2021/5/12 15:28
*/ */
@SpringBootTest
@AutoConfigureMockMvc @AutoConfigureMockMvc
public class HelloControllerTest { public class ControllerTest extends BaseTest {
@Autowired @Autowired
private MockMvc mvc; private MockMvc mvc;
...@@ -32,32 +29,4 @@ public class HelloControllerTest { ...@@ -32,32 +29,4 @@ public class HelloControllerTest {
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!"))); .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
} }
public static void main(String[] args) {
Jedis jedis = null;
try {
String host = "redis-x4n822igaxnu-proxy-nlb.jvessel-open-hb.jdcloud.com";//控制台显示访问地址
int port = 6379;
String password = "kP6oWdeYU78tHee";//控制台显示的token
jedis = new Jedis(host, port);
//鉴权信息
jedis.auth("password");
String key = "redis";
String value = "jmiss-redis";
//set一个key
String retCode = jedis.set(key, value);
System.out.println("Set Key: " + key + " Value: " + value + " return code is: " + retCode);
//get 设置进去的key
String getvalue = jedis.get(key);
System.out.println("Get Key: " + key + " ReturnValue: " + getvalue);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != jedis) {
jedis.quit();
jedis.close();
}
}
}
} }
package cn.com.duiba.jdactivity.developer.jd;
import cn.com.duiba.jdactivity.BaseTest;
import cn.com.duiba.jdactivity.developer.jd.domain.AccessTokenResponse;
import cn.com.duiba.jdactivity.developer.jd.utils.AccessTokenUtils;
import com.alibaba.fastjson.JSON;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import javax.annotation.Resource;
/**
* @author zsp (zengshuiping@duiba.com.cn)
* @date 2021/5/13 16:49
*/
class AccessTokenUtilsTest extends BaseTest {
@Resource
private AccessTokenUtils accessTokenUtils;
@Test
void generateAuthUrl() {
System.out.println(accessTokenUtils.generateAuthUrl(AppKeyEnum.DUIBA, "sss"));
}
@Test
void getAccessTokenByCode() {
AccessTokenResponse tokenByCode = accessTokenUtils.getAccessTokenByCode(AppKeyEnum.DUIBA, "a");
Assert.assertNotNull(tokenByCode);
System.out.println(JSON.toJSONString(tokenByCode));
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment