1.新增邮件,阿里,腾讯短信调用接口

2.新增微信模板通知,目前通知接口都是同步调用
3.添加redisson,延迟消息队列,超时订单自动取消
This commit is contained in:
Administrator
2019-11-22 17:00:44 +08:00
parent 17f6d107ce
commit f60e8d816a
31 changed files with 1782 additions and 130 deletions

View File

@ -196,6 +196,11 @@
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.2</version>
</dependency>
</dependencies>
<build>

View File

@ -99,6 +99,21 @@
<!-- <version>3.1.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>com.github.qcloudsms</groupId>
<artifactId>qcloudsms</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>3.3.1.B</version>
</dependency>
</dependencies>
<build>

View File

@ -3,6 +3,11 @@ package co.yixiang.common.constant;
public interface CommonConstant {
/**
* 订单超时未支付时间 默认30分钟
*/
Long ORDER_OUTTIME_UNPAY = 1000* 1800L;
/**
* 默认页码为1
*/

View File

@ -0,0 +1,225 @@
package co.yixiang.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ConfigurationProperties(prefix = "yshop.notify")
public class NotifyProperties {
private Mail mail;
private Sms sms;
private Wx wx;
public Mail getMail() {
return mail;
}
public void setMail(Mail mail) {
this.mail = mail;
}
public Sms getSms() {
return sms;
}
public void setSms(Sms sms) {
this.sms = sms;
}
public Wx getWx() {
return wx;
}
public void setWx(Wx wx) {
this.wx = wx;
}
public static class Mail {
private boolean enable;
private String host;
private String username;
private String password;
private String sendfrom;
private String sendto;
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSendfrom() {
return sendfrom;
}
public void setSendfrom(String sendfrom) {
this.sendfrom = sendfrom;
}
public String getSendto() {
return sendto;
}
public void setSendto(String sendto) {
this.sendto = sendto;
}
}
public static class Sms {
private boolean enable;
private String active;
private String sign;
private Tencent tencent;
private Aliyun aliyun;
private List<Map<String, String>> template = new ArrayList<>();
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public List<Map<String, String>> getTemplate() {
return template;
}
public void setTemplate(List<Map<String, String>> template) {
this.template = template;
}
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public Tencent getTencent() {
return tencent;
}
public void setTencent(Tencent tencent) {
this.tencent = tencent;
}
public Aliyun getAliyun() {
return aliyun;
}
public void setAliyun(Aliyun aliyun) {
this.aliyun = aliyun;
}
public static class Tencent {
private int appid;
private String appkey;
public int getAppid() {
return appid;
}
public void setAppid(int appid) {
this.appid = appid;
}
public String getAppkey() {
return appkey;
}
public void setAppkey(String appkey) {
this.appkey = appkey;
}
}
public static class Aliyun {
private String regionId;
private String accessKeyId;
private String accessKeySecret;
public String getRegionId() {
return regionId;
}
public void setRegionId(String regionId) {
this.regionId = regionId;
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
}
}
public static class Wx {
private boolean enable;
private List<Map<String, String>> template = new ArrayList<>();
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public List<Map<String, String>> getTemplate() {
return template;
}
public void setTemplate(List<Map<String, String>> template) {
this.template = template;
}
}
}

View File

@ -0,0 +1,122 @@
package co.yixiang.modules.notify;
import co.yixiang.utils.JacksonUtil;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.HashMap;
import java.util.Map;
/*
* 阿里云短信服务
*/
public class AliyunSmsSender implements SmsSender {
private final Log logger = LogFactory.getLog(AliyunSmsSender.class);
private String regionId;
private String accessKeyId;
private String accessKeySecret;
private String sign;
public String getRegionId() {
return regionId;
}
public void setRegionId(String regionId) {
this.regionId = regionId;
}
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
@Override
public SmsResult send(String phone, String content) {
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
@Override
public SmsResult sendWithTemplate(String phone, String templateId, String[] params) {
DefaultProfile profile = DefaultProfile.getProfile(this.regionId, this.accessKeyId, this.accessKeySecret);
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("SendSms");
request.putQueryParameter("RegionId", this.regionId);
request.putQueryParameter("PhoneNumbers", phone);
request.putQueryParameter("SignName", this.sign);
request.putQueryParameter("TemplateCode", templateId);
/*
NOTE阿里云短信和腾讯云短信这里存在不一致
腾讯云短信模板参数是数组,因此短信模板形式如 “短信参数{1} 短信参数{2}”
阿里云短信模板参数是JSON因此短信模板形式如“短信参数{param1} 短信参数{param2}”
为了保持统一我们假定阿里云短信里面的参数是codecode1code2...
如果开发者在阿里云短信申请的模板参数是其他命名,请开发者自行调整这里的代码,或者直接写死。
*/
String templateParam = "{}";
if(params.length == 1){
Map<String, String> data = new HashMap<>();
data.put("code", params[0]);
templateParam = JacksonUtil.toJson(data);
}
else if(params.length > 1){
Map<String, String> data = new HashMap<>();
data.put("code", params[0]);
for(int i = 1; i < params.length; i++){
data.put("code" + i, params[i]);
}
templateParam = JacksonUtil.toJson(data);
}
request.putQueryParameter("TemplateParam", templateParam);
try {
CommonResponse response = client.getCommonResponse(request);
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(true);
smsResult.setResult(response);
return smsResult;
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
}

View File

@ -0,0 +1,137 @@
package co.yixiang.modules.notify;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.scheduling.annotation.Async;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 商城通知服务类
*/
public class NotifyService {
private MailSender mailSender;
private String sendFrom;
private String sendTo;
private SmsSender smsSender;
private List<Map<String, String>> smsTemplate = new ArrayList<>();
private List<Map<String, String>> wxTemplate = new ArrayList<>();
public boolean isMailEnable() {
return mailSender != null;
}
public boolean isSmsEnable() {
return smsSender != null;
}
/**
* 短信消息通知
*
* @param phoneNumber 接收通知的电话号码
* @param message 短消息内容,这里短消息内容必须已经在短信平台审核通过
*/
@Async
public void notifySms(String phoneNumber, String message) {
if (smsSender == null)
return;
smsSender.send(phoneNumber, message);
}
/**
* 短信模版消息通知
*
* @param phoneNumber 接收通知的电话号码
* @param notifyType 通知类别通过该枚举值在配置文件中获取相应的模版ID
* @param params 通知模版内容里的参数,类似"您的验证码为{1}"中{1}的值
*/
@Async
public void notifySmsTemplate(String phoneNumber, NotifyType notifyType, String[] params) {
if (smsSender == null) {
return;
}
String templateIdStr = getTemplateId(notifyType, smsTemplate);
if (templateIdStr == null) {
return;
}
smsSender.sendWithTemplate(phoneNumber, templateIdStr, params);
}
/**
* 以同步的方式发送短信模版消息通知
*
* @param phoneNumber 接收通知的电话号码
* @param notifyType 通知类别通过该枚举值在配置文件中获取相应的模版ID
* @param params 通知模版内容里的参数,类似"您的验证码为{1}"中{1}的值
* @return
*/
public SmsResult notifySmsTemplateSync(String phoneNumber, NotifyType notifyType, String[] params) {
if (smsSender == null)
return null;
return smsSender.sendWithTemplate(phoneNumber, getTemplateId(notifyType, smsTemplate), params);
}
/**
* 邮件消息通知,
* 接收者在spring.mail.sendto中指定
*
* @param subject 邮件标题
* @param content 邮件内容
*/
@Async
public void notifyMail(String subject, String content) {
if (mailSender == null)
return;
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(sendFrom);
message.setTo(sendTo);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
private String getTemplateId(NotifyType notifyType, List<Map<String, String>> values) {
for (Map<String, String> item : values) {
String notifyTypeStr = notifyType.getType();
if (item.get("name").equals(notifyTypeStr))
return item.get("templateId");
}
return null;
}
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setSendFrom(String sendFrom) {
this.sendFrom = sendFrom;
}
public void setSendTo(String sendTo) {
this.sendTo = sendTo;
}
public void setSmsSender(SmsSender smsSender) {
this.smsSender = smsSender;
}
public void setSmsTemplate(List<Map<String, String>> smsTemplate) {
this.smsTemplate = smsTemplate;
}
public void setWxTemplate(List<Map<String, String>> wxTemplate) {
this.wxTemplate = wxTemplate;
}
}

View File

@ -0,0 +1,18 @@
package co.yixiang.modules.notify;
public enum NotifyType {
PAY_SUCCEED("paySucceed"),
SHIP("ship"),
REFUND("refund"),
CAPTCHA("captcha");
private String type;
NotifyType(String type) {
this.type = type;
}
public String getType() {
return this.type;
}
}

View File

@ -0,0 +1,30 @@
package co.yixiang.modules.notify;
/**
* 发送短信的返回结果
*/
public class SmsResult {
private boolean successful;
private Object result;
/**
* 短信是否发送成功
*
* @return
*/
public boolean isSuccessful() {
return successful;
}
public void setSuccessful(boolean successful) {
this.successful = successful;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
}

View File

@ -0,0 +1,21 @@
package co.yixiang.modules.notify;
public interface SmsSender {
/**
* 发送短信息
*
* @param phone 接收通知的电话号码
* @param content 短消息内容
*/
SmsResult send(String phone, String content);
/**
* 通过短信模版发送短信息
* @param phone 接收通知的电话号码
* @param templateId 通知模板ID
* @param params 通知模版内容里的参数,类似"您的验证码为{1}"中{1}的值
*/
SmsResult sendWithTemplate(String phone, String templateId, String[] params);
}

View File

@ -0,0 +1,68 @@
package co.yixiang.modules.notify;
import com.github.qcloudsms.SmsSingleSender;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.github.qcloudsms.httpclient.HTTPException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.IOException;
/*
* 腾讯云短信服务
*/
public class TencentSmsSender implements SmsSender {
private final Log logger = LogFactory.getLog(TencentSmsSender.class);
private SmsSingleSender sender;
private String sign;
public SmsSingleSender getSender() {
return sender;
}
public void setSender(SmsSingleSender sender) {
this.sender = sender;
}
@Override
public SmsResult send(String phone, String content) {
try {
SmsSingleSenderResult result = sender.send(0, "86", phone, content, "", "");
logger.debug(result);
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(true);
smsResult.setResult(result);
return smsResult;
} catch (HTTPException | IOException e) {
logger.error(e.getMessage(), e);
}
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
@Override
public SmsResult sendWithTemplate(String phone, String templateId, String[] params) {
try {
SmsSingleSenderResult result = sender.sendWithParam("86", phone, Integer.parseInt(templateId), params, this.sign, "", "");
logger.debug(result);
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(true);
smsResult.setResult(result);
return smsResult;
} catch (HTTPException | IOException e) {
logger.error(e.getMessage(), e);
}
SmsResult smsResult = new SmsResult();
smsResult.setSuccessful(false);
return smsResult;
}
public void setSign(String sign) {
this.sign = sign;
}
}

View File

@ -0,0 +1,82 @@
package co.yixiang.modules.notify.config;
import co.yixiang.config.NotifyProperties;
import co.yixiang.modules.notify.AliyunSmsSender;
import co.yixiang.modules.notify.NotifyService;
import co.yixiang.modules.notify.TencentSmsSender;
import com.github.qcloudsms.SmsSingleSender;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
@Configuration
@EnableConfigurationProperties(NotifyProperties.class)
public class NotifyAutoConfiguration {
private final NotifyProperties properties;
public NotifyAutoConfiguration(NotifyProperties properties) {
this.properties = properties;
}
@Bean
public NotifyService notifyService() {
NotifyService notifyService = new NotifyService();
NotifyProperties.Mail mailConfig = properties.getMail();
if (mailConfig.isEnable()) {
notifyService.setMailSender(mailSender());
notifyService.setSendFrom(mailConfig.getSendfrom());
notifyService.setSendTo(mailConfig.getSendto());
}
NotifyProperties.Sms smsConfig = properties.getSms();
if (smsConfig.isEnable()) {
if(smsConfig.getActive().equals("tencent")) {
notifyService.setSmsSender(tencentSmsSender());
}
else if(smsConfig.getActive().equals("aliyun")) {
notifyService.setSmsSender(aliyunSmsSender());
}
notifyService.setSmsTemplate(smsConfig.getTemplate());
}
return notifyService;
}
@Bean
public JavaMailSender mailSender() {
NotifyProperties.Mail mailConfig = properties.getMail();
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(mailConfig.getHost());
mailSender.setUsername(mailConfig.getUsername());
mailSender.setPassword(mailConfig.getPassword());
return mailSender;
}
@Bean
public TencentSmsSender tencentSmsSender() {
NotifyProperties.Sms smsConfig = properties.getSms();
TencentSmsSender smsSender = new TencentSmsSender();
NotifyProperties.Sms.Tencent tencent = smsConfig.getTencent();
smsSender.setSender(new SmsSingleSender(tencent.getAppid(), tencent.getAppkey()));
smsSender.setSign(smsConfig.getSign());
return smsSender;
}
@Bean
public AliyunSmsSender aliyunSmsSender() {
NotifyProperties.Sms smsConfig = properties.getSms();
AliyunSmsSender smsSender = new AliyunSmsSender();
NotifyProperties.Sms.Aliyun aliyun = smsConfig.getAliyun();
smsSender.setSign(smsConfig.getSign());
smsSender.setRegionId(aliyun.getRegionId());
smsSender.setAccessKeyId(aliyun.getAccessKeyId());
smsSender.setAccessKeySecret(aliyun.getAccessKeySecret());
return smsSender;
}
}

View File

@ -2,6 +2,7 @@ package co.yixiang.modules.order.service.impl;
import cn.hutool.core.util.*;
import co.yixiang.common.constant.CacheKey;
import co.yixiang.common.constant.CommonConstant;
import co.yixiang.exception.ErrorRequestException;
import co.yixiang.modules.activity.service.YxStoreCombinationService;
import co.yixiang.modules.activity.service.YxStorePinkService;
@ -30,21 +31,18 @@ import co.yixiang.modules.shop.service.YxStoreProductService;
import co.yixiang.modules.shop.service.YxSystemConfigService;
import co.yixiang.modules.shop.web.vo.YxStoreCartQueryVo;
//import co.yixiang.modules.task.CancelOrderService;
import co.yixiang.modules.user.entity.YxUser;
import co.yixiang.modules.user.entity.YxUserAddress;
import co.yixiang.modules.user.entity.YxUserBill;
import co.yixiang.modules.user.entity.YxWechatUser;
import co.yixiang.modules.task.CancelOrderService;
import co.yixiang.modules.user.entity.*;
import co.yixiang.modules.user.mapper.YxUserMapper;
import co.yixiang.modules.user.service.YxUserAddressService;
import co.yixiang.modules.user.service.YxUserBillService;
import co.yixiang.modules.user.service.YxUserService;
import co.yixiang.modules.user.service.YxWechatUserService;
import co.yixiang.modules.user.service.*;
import co.yixiang.modules.user.web.controller.UserAddressController;
import co.yixiang.modules.user.web.vo.YxUserAddressQueryVo;
import co.yixiang.modules.user.web.vo.YxUserQueryVo;
import co.yixiang.modules.user.web.vo.YxWechatUserQueryVo;
//import co.yixiang.redisson.DelayJob;
//import co.yixiang.redisson.DelayJobService;
import co.yixiang.redisson.DelayJob;
import co.yixiang.redisson.DelayJobService;
import co.yixiang.utils.OrderUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@ -69,6 +67,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -137,15 +136,12 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
private YxStoreCouponUserMapper yxStoreCouponUserMapper;
@Autowired
private DelayJobService delayJobService;
private YxStoreCombinationService combinationService;
@Autowired
private YxStorePinkService pinkService;
// @Autowired
// private DelayJobService delayJobService;
// @Value("${job.unpayorder}")
// private String overtime;
@ -259,7 +255,7 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
public void cancelOrder(String orderId, int uid) {
YxStoreOrderQueryVo order = getOrderInfo(orderId,uid);
if(ObjectUtil.isNull(order)) throw new ErrorRequestException("订单不存在");
if(order.getIsDel() == 1)throw new ErrorRequestException("订单已取消");
regressionIntegral(order);
regressionStock(order);
@ -284,6 +280,8 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
if(ObjectUtil.isNull(order)) throw new ErrorRequestException("订单不存在");
if(order.getIsDel() == 1)throw new ErrorRequestException("订单已取消");
regressionIntegral(order);
regressionStock(order);
@ -638,11 +636,13 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
userService.incPayCount(orderInfo.getUid());
//增加状态
orderStatusService.create(orderInfo.getId(),"pay_success","用户付款成功");
//支付成功后取消延时队列
DelayJob delayJob = new DelayJob();
delayJob.setOderId(storeOrder.getId());
delayJob.setAClass(CancelOrderService.class);
delayJobService.cancelJob(delayJob);
//todo 拼团
pinkService.createPink(orderInfo);
//todo 模板消息推送
}
@ -909,18 +909,12 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
//增加状态
orderStatusService.create(storeOrder.getId(),"cache_key_create_order","订单生成");
// 订单支付超期任务
//String overtimeStr = systemConfigService.getData("order_cancel_job_time");
//没有配置不加入
// if(StrUtil.isNotBlank(overtimeStr)){
// // 订单支付超期任务
// DelayJob delayJob = new DelayJob();
// delayJob.setOrderId(storeOrder.getId());
// delayJob.setAClass(CancelOrderService.class);
// delayJobService.submitJob(delayJob,Long.valueOf(overtimeStr));
// }
// 添加订单支付超期延时任务
DelayJob delayJob = new DelayJob();
delayJob.setOderId(storeOrder.getId());
delayJob.setAClass(CancelOrderService.class);
delayJobService.submitJob(delayJob, CommonConstant.ORDER_OUTTIME_UNPAY);
return storeOrder;
}

View File

@ -1,38 +1,38 @@
//package co.yixiang.modules.task;
//
//import cn.hutool.core.util.ObjectUtil;
//import co.yixiang.modules.order.entity.YxStoreOrder;
//import co.yixiang.modules.order.service.YxStoreOrderService;
//import co.yixiang.redisson.DelayJob;
//import co.yixiang.redisson.ExecuteJob;
//import co.yixiang.utils.SpringContextHolder;
//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Component;
//
//
//@Component
//@Slf4j
//public class CancelOrderService implements ExecuteJob {
// @Override
// public void execute(DelayJob job) {
// log.info("系统开始处理延时任务---订单超时未付款---" + job.getOrderId());
//
// YxStoreOrderService yxorderService = SpringContextHolder.getBean(YxStoreOrderService.class);
//
// YxStoreOrder order = null;
// try {
// order = yxorderService.getOne(new QueryWrapper<YxStoreOrder>().eq("id", job.getOrderId()).eq("is_del",0));
// } catch (Exception e) {
// e.printStackTrace();
// }
// if(ObjectUtil.isNull(order)) {
// return;
// }
// if(order.getPaid() != 0){
// return;
// }
// yxorderService.cancelOrderByTask(job.getOrderId());
// log.info("系统结束处理延时任务---订单超时未付款取消---" + job.getOrderId());
// }
//}
package co.yixiang.modules.task;
import cn.hutool.core.util.ObjectUtil;
import co.yixiang.modules.order.entity.YxStoreOrder;
import co.yixiang.modules.order.service.YxStoreOrderService;
import co.yixiang.redisson.DelayJob;
import co.yixiang.redisson.ExecuteJob;
import co.yixiang.utils.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class CancelOrderService implements ExecuteJob {
@Override
public void execute(DelayJob job) {
log.info("系统开始处理延时任务---订单超时未付款---" + job.getOderId());
YxStoreOrderService yxorderService = BeanUtil.getBean(YxStoreOrderService.class);
YxStoreOrder order = null;
try {
order = yxorderService.getOne(new QueryWrapper<YxStoreOrder>().eq("id", job.getOderId()).eq("is_del",0));
} catch (Exception e) {
e.printStackTrace();
}
if(ObjectUtil.isNull(order)) {
return;
}
if(order.getPaid() != 0){
return;
}
yxorderService.cancelOrderByTask(job.getOderId());
log.info("系统结束处理延时任务---订单超时未付款取消---" + job.getOderId());
}
}

View File

@ -5,10 +5,10 @@ spring:
type: com.alibaba.druid.pool.DruidDataSource
#driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://localhost:3306/yxshop?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
url: jdbc:p6spy:mysql://106.12.82.39:3306/yxshop?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
#url: jdbc:log4jdbc:mysql://localhost:3306/yxshop?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root
password: root
password: Admin@123
# 初始化配置
initial-size: 3
@ -47,7 +47,7 @@ spring:
database: 0
host: 127.0.0.1
port: 6379
password:
password: root
#连接超时时间
timeout: 5000
@ -78,4 +78,88 @@ file:
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
localUrl: http://localhost:8000
localUrl: http://localhost:8000
yshop:
#通知相关配置
notify:
mail:
# 邮件通知配置,邮箱一般用于接收业务通知例如收到新的订单sendto 定义邮件接收者,通常为商城运营人员
enable: false
host: smtp.exmail.qq.com
username: ex@ex.com.cn
password: XXXXXXXXXXXXX
sendfrom: ex@ex.com.cn
sendto: ex@qq.com
# 短消息模版通知配置
# 短信息用于通知客户例如发货短信通知注意配置格式template-nametemplate-templateId 请参考 NotifyType 枚举值
sms:
enable: false
# 如果是腾讯云短信则设置active的值tencent
# 如果是阿里云短信则设置active的值aliyun
active: tencent
sign: litemall
template:
- name: paySucceed
templateId: 156349
- name: captcha
templateId: 156433
- name: ship
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
# 微信模版通知配置
# 微信模版用于通知客户或者运营者注意配置格式template-nametemplate-templateId 请参考 NotifyType 枚举值
wx:
enable: false
template:
- name: paySucceed
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: captcha
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: ship
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: refund
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 快鸟物流查询配置
express:
enable: false
appId: "XXXXXXXXX"
appKey: "XXXXXXXXXXXXXXXXXXXXXXXXX"
vendors:
- code: "ZTO"
name: "中通快递"
- code: "YTO"
name: "圆通速递"
- code: "YD"
name: "韵达速递"
- code: "YZPY"
name: "邮政快递包裹"
- code: "EMS"
name: "EMS"
- code: "DBL"
name: "德邦快递"
- code: "FAST"
name: "快捷快递"
- code: "ZJS"
name: "宅急送"
- code: "TNT"
name: "TNT快递"
- code: "UPS"
name: "UPS"
- code: "DHL"
name: "DHL"
- code: "FEDEX"
name: "FEDEX联邦(国内件)"
- code: "FEDEX_GJ"
name: "FEDEX联邦(国际件)"

View File

@ -86,4 +86,89 @@ file:
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
localUrl: http://localhost:8000
localUrl: http://localhost:8000
yshop:
#通知相关配置
notify:
mail:
# 邮件通知配置,邮箱一般用于接收业务通知例如收到新的订单sendto 定义邮件接收者,通常为商城运营人员
enable: false
host: smtp.exmail.qq.com
username: ex@ex.com.cn
password: XXXXXXXXXXXXX
sendfrom: ex@ex.com.cn
sendto: ex@qq.com
# 短消息模版通知配置
# 短信息用于通知客户例如发货短信通知注意配置格式template-nametemplate-templateId 请参考 NotifyType 枚举值
sms:
enable: false
# 如果是腾讯云短信则设置active的值tencent
# 如果是阿里云短信则设置active的值aliyun
active: tencent
sign: litemall
template:
- name: paySucceed
templateId: 156349
- name: captcha
templateId: 156433
- name: ship
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
# 微信模版通知配置
# 微信模版用于通知客户或者运营者注意配置格式template-nametemplate-templateId 请参考 NotifyType 枚举值
wx:
enable: false
template:
- name: paySucceed
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: captcha
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: ship
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: refund
templateId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 快鸟物流查询配置
express:
enable: false
appId: "XXXXXXXXX"
appKey: "XXXXXXXXXXXXXXXXXXXXXXXXX"
vendors:
- code: "ZTO"
name: "中通快递"
- code: "YTO"
name: "圆通速递"
- code: "YD"
name: "韵达速递"
- code: "YZPY"
name: "邮政快递包裹"
- code: "EMS"
name: "EMS"
- code: "DBL"
name: "德邦快递"
- code: "FAST"
name: "快捷快递"
- code: "ZJS"
name: "宅急送"
- code: "TNT"
name: "TNT快递"
- code: "UPS"
name: "UPS"
- code: "DHL"
name: "DHL"
- code: "FEDEX"
name: "FEDEX联邦(国内件)"
- code: "FEDEX_GJ"
name: "FEDEX联邦(国际件)"

View File

@ -23,9 +23,11 @@ import java.util.Map;
public class CodeGenerator {
private static final String USER_NAME = "root";
private static final String PASSWORD = "root";
private static final String PASSWORD = "Admin@123";
private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
private static final String DRIVER_URL = "jdbc:mysql://127.0.0.1:3306/yxshop?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8";
private static final String DRIVER_URL = "jdbc:mysql://106.12.82.39:3306/yxshop?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8";
private static final String PARENT_PACKAGE = "co.yixiang";
private static final String SUPER_ENTITY = PARENT_PACKAGE + ".common.entity.BaseEntity";
@ -45,8 +47,7 @@ public class CodeGenerator {
// 作者
private static final String AUTHOR = "hupeng";
// 生成的表名称
private static final String TABLE_NAME = "yx_store_pink";
// 主键数据库列名称
private static final String TABLE_NAME = "yx_system_attachment"; // 主键数据库列名称
private static final String PK_ID_COLUMN_NAME = "id";
// 代码生成策略 trueAll/false:SIMPLE
private static final boolean GENERATOR_STRATEGY = true;

View File

@ -1,17 +1,12 @@
package co.yixiang.redis;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
@ -19,6 +14,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
/**
@ -31,7 +27,7 @@ import java.time.Duration;
// 自动配置
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
public class RedisConfig {
/**
* 设置 redis 数据默认过期时间默认1天
@ -75,52 +71,5 @@ public class RedisConfig extends CachingConfigurerSupport {
return template;
}
/**
* 自定义缓存key生成策略默认将使用该策略
* 使用方法 @Cacheable
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(JSON.toJSONString(obj).hashCode());
}
return sb.toString();
};
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
// 异常处理当Redis发生异常时打印日志但是程序正常走
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheGetErrorkey -> [{}]", key, e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutErrorkey -> [{}]value -> [{}]", key, value, e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictErrorkey -> [{}]", key, e);
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.error("Redis occur handleCacheClearError", e);
}
};
return cacheErrorHandler;
}
}

View File

@ -0,0 +1,16 @@
package co.yixiang.redisson;
import lombok.Data;
import java.io.Serializable;
/**
* Created by kl on 2018/7/20.
* Content :延时job
*/
@Data
public class DelayJob implements Serializable {
private Integer oderId;//job执行参数
private Class aClass;//具体执行实例实现
}

View File

@ -0,0 +1,44 @@
package co.yixiang.redisson;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* Created by kl on 2018/7/20.
* Content :订单延时job服务
*/
@Component
public class DelayJobService {
@Autowired
private RedissonClient client;
/**
* 添加超时任务到redis队列
* @param job 任务
* @param delay 超时时间
*/
public void submitJob(DelayJob job, Long delay){
RBlockingQueue blockingQueue = client.getBlockingQueue(JobTimer.CUSTOMER_JOB_TIMER_JOBS);
RDelayedQueue delayedQueue = client.getDelayedQueue(blockingQueue);
delayedQueue.offer(job,delay,TimeUnit.MILLISECONDS);
delayedQueue.destroy();
}
/**
* 用户付款后取消队列
* @param job 任务
*/
public void cancelJob(DelayJob job){
RBlockingQueue blockingQueue = client.getBlockingQueue(JobTimer.CUSTOMER_JOB_TIMER_JOBS);
RDelayedQueue delayedQueue = client.getDelayedQueue(blockingQueue);
delayedQueue.remove(job);
delayedQueue.destroy();
}
}

View File

@ -0,0 +1,10 @@
package co.yixiang.redisson;
/**
* Created by kl on 2018/7/20.
* Content :延时job执行器接口
*/
public interface ExecuteJob {
void execute(DelayJob job);
}

View File

@ -0,0 +1,68 @@
package co.yixiang.redisson;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 消费已经到点的延时job服务通过job参数调用业务执行器实现
*/
@Component
public class JobTimer {
static final String CUSTOMER_JOB_TIMER_JOBS = "customer_job_timer_jobs";
@Autowired
private RedissonClient client;
@Autowired
private ApplicationContext context;
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
@PostConstruct
public void startJobTimer() {
RBlockingQueue blockingQueue = client.getBlockingQueue(CUSTOMER_JOB_TIMER_JOBS);
RDelayedQueue delayedQueue = client.getDelayedQueue(blockingQueue);
new Thread(() -> {
while (true) {
try {
DelayJob job = (DelayJob) blockingQueue.take();
executorService.execute(new ExecutorTask(context, job));
} catch (Exception e) {
e.printStackTrace();
try {
TimeUnit.SECONDS.sleep(60);
} catch (Exception ex) {
}
}finally {
delayedQueue.destroy();
}
}
}).start();
}
class ExecutorTask implements Runnable {
private ApplicationContext context;
private DelayJob delayJob;
public ExecutorTask(ApplicationContext context, DelayJob delayJob) {
this.context = context;
this.delayJob = delayJob;
}
@Override
public void run() {
ExecuteJob service = (ExecuteJob) context.getBean(delayJob.getAClass());
service.execute(delayJob);
}
}
}

View File

@ -0,0 +1,108 @@
package co.yixiang.redisson;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.spring.cache.CacheConfig;
import org.redisson.spring.cache.RedissonSpringCacheManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* redisson 配置类
* Created on 2018/6/19
*/
@Configuration
@EnableCaching
@Slf4j
public class RedissonConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private String port;
@Value("${spring.redis.password}")
private String password;
@Bean
public RedissonClient getRedisson(){
Config config = new Config();
config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
//添加主从配置
// config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"",""});
return Redisson.create(config);
}
@Bean
CacheManager cacheManager(RedissonClient redissonClient){
Map<String, CacheConfig> config = new HashMap<>(16);
// create "testMap" cache with ttl = 24 minutes and maxIdleTime = 12 minutes
config.put("testMap",new CacheConfig(24*60*1000,12*60*1000));
return new RedissonSpringCacheManager(redissonClient,config);
}
/**
* 自定义缓存key生成策略默认将使用该策略
* 使用方法 @Cacheable
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(JSON.toJSONString(obj).hashCode());
}
return sb.toString();
};
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
// 异常处理当Redis发生异常时打印日志但是程序正常走
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheGetErrorkey -> [{}]", key, e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutErrorkey -> [{}]value -> [{}]", key, value, e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictErrorkey -> [{}]", key, e);
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.error("Redis occur handleCacheClearError", e);
}
};
return cacheErrorHandler;
}
}

View File

@ -0,0 +1,24 @@
package co.yixiang.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class BeanUtil implements ApplicationContextAware {
protected static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static Object getBean(String name) {
return context.getBean(name);
}
public static <T> T getBean(Class<T> c){
return context.getBean(c);
}
}

View File

@ -4,9 +4,9 @@ spring:
druid:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/yxshop?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
url: jdbc:log4jdbc:mysql://106.12.82.39:3306/yxshop?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root
password: root
password: Admin@123
# 初始化配置
initial-size: 3
@ -46,7 +46,7 @@ spring:
database: 0
host: 127.0.0.1
port: 6379
password:
password: root
#连接超时时间
timeout: 5000

View File

@ -46,6 +46,7 @@
<artifactId>alipay-sdk-java</artifactId>
<version>${alipay.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>

View File

@ -0,0 +1,145 @@
package co.yixiang.express;
import cn.hutool.http.HttpUtil;
import co.yixiang.express.config.ExpressProperties;
import co.yixiang.express.dao.ExpressInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Base64Utils;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
/**
* 物流查询服务
* <p>
* 快递鸟即时查询API http://www.kdniao.com/api-track
*/
public class ExpressService {
private final Log logger = LogFactory.getLog(ExpressService.class);
//请求url
private String ReqURL = "http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";
private ExpressProperties properties;
public ExpressProperties getProperties() {
return properties;
}
public void setProperties(ExpressProperties properties) {
this.properties = properties;
}
/**
* 获取物流供应商名
*
* @param vendorCode
* @return
*/
public String getVendorName(String vendorCode) {
for (Map<String, String> item : properties.getVendors()) {
if (item.get("code").equals(vendorCode))
return item.get("name");
}
return null;
}
/**
* 获取物流信息
*
* @param expCode
* @param expNo
* @return
*/
public ExpressInfo getExpressInfo(String expCode, String expNo) {
try {
String result = getOrderTracesByJson(expCode, expNo);
ObjectMapper objMap = new ObjectMapper();
ExpressInfo ei = objMap.readValue(result, ExpressInfo.class);
ei.setShipperName(getVendorName(expCode));
return ei;
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
/**
* Json方式 查询订单物流轨迹
*
* @throws Exception
*/
private String getOrderTracesByJson(String expCode, String expNo) throws Exception {
if (!properties.isEnable()) {
return null;
}
String requestData = "{'OrderCode':'','ShipperCode':'" + expCode + "','LogisticCode':'" + expNo + "'}";
Map<String, Object> params = new HashMap<>();
params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));
params.put("EBusinessID", properties.getAppId());
params.put("RequestType", "1002");
String dataSign = encrypt(requestData, properties.getAppKey(), "UTF-8");
params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));
params.put("DataType", "2");
String result = HttpUtil.post(ReqURL, params);
//根据公司业务处理返回的信息......
return result;
}
/**
* MD5加密
*
* @param str 内容
* @param charset 编码方式
* @throws Exception
*/
private String MD5(String str, String charset) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes(charset));
byte[] result = md.digest();
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < result.length; i++) {
int val = result[i] & 0xff;
if (val <= 0xf) {
sb.append("0");
}
sb.append(Integer.toHexString(val));
}
return sb.toString().toLowerCase();
}
/**
* Sign签名生成
*
* @param content 内容
* @param keyValue Appkey
* @param charset 编码方式
* @return DataSign签名
*/
private String encrypt(String content, String keyValue, String charset) {
if (keyValue != null) {
content = content + keyValue;
}
byte[] src;
try {
src = MD5(content, charset).getBytes(charset);
return Base64Utils.encodeToString(src);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
}

View File

@ -0,0 +1,25 @@
package co.yixiang.express.config;
import co.yixiang.express.ExpressService;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(ExpressProperties.class)
public class ExpressAutoConfiguration {
private final ExpressProperties properties;
public ExpressAutoConfiguration(ExpressProperties properties) {
this.properties = properties;
}
@Bean
public ExpressService expressService() {
ExpressService expressService = new ExpressService();
expressService.setProperties(properties);
return expressService;
}
}

View File

@ -0,0 +1,47 @@
package co.yixiang.express.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ConfigurationProperties(prefix = "yshop.express")
public class ExpressProperties {
private boolean enable;
private String appId;
private String appKey;
private List<Map<String, String>> vendors = new ArrayList<>();
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public List<Map<String, String>> getVendors() {
return vendors;
}
public void setVendors(List<Map<String, String>> vendors) {
this.vendors = vendors;
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
}

View File

@ -0,0 +1,112 @@
/**
* Copyright 2018 bejson.com
*/
package co.yixiang.express.dao;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
/**
* Auto-generated: 2018-07-19 22:27:22
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
public class ExpressInfo {
@JsonProperty("LogisticCode")
private String LogisticCode;
@JsonProperty("ShipperCode")
private String ShipperCode;
@JsonProperty("Traces")
private List<Traces> Traces;
@JsonProperty("State")
private String State;
@JsonProperty("EBusinessID")
private String EBusinessID;
@JsonProperty("Success")
private boolean Success;
@JsonProperty("Reason")
private String Reason;
private String ShipperName;
public String getLogisticCode() {
return LogisticCode;
}
public void setLogisticCode(String LogisticCode) {
this.LogisticCode = LogisticCode;
}
public String getShipperCode() {
return ShipperCode;
}
public void setShipperCode(String ShipperCode) {
this.ShipperCode = ShipperCode;
}
public List<Traces> getTraces() {
return Traces;
}
public void setTraces(List<Traces> Traces) {
this.Traces = Traces;
}
public String getState() {
return State;
}
public void setState(String State) {
this.State = State;
}
public String getEBusinessID() {
return EBusinessID;
}
public void setEBusinessID(String EBusinessID) {
this.EBusinessID = EBusinessID;
}
public boolean getSuccess() {
return Success;
}
public void setSuccess(boolean Success) {
this.Success = Success;
}
public String getReason() {
return Reason;
}
public void setReason(String Reason) {
this.Reason = Reason;
}
public String getShipperName() {
return ShipperName;
}
public void setShipperName(String shipperName) {
ShipperName = shipperName;
}
@Override
public String toString() {
return "ExpressInfo{" +
"LogisticCode='" + LogisticCode + '\'' +
", ShipperCode='" + ShipperCode + '\'' +
", Traces=" + Traces +
", State='" + State + '\'' +
", EBusinessID='" + EBusinessID + '\'' +
", Success=" + Success +
", Reason=" + Reason +
", ShipperName='" + ShipperName + '\'' +
'}';
}
}

View File

@ -0,0 +1,37 @@
/**
* Copyright 2018 bejson.com
*/
package co.yixiang.express.dao;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Auto-generated: 2018-07-19 22:27:22
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
public class Traces {
@JsonProperty("AcceptStation")
private String AcceptStation;
@JsonProperty("AcceptTime")
private String AcceptTime;
public String getAcceptStation() {
return AcceptStation;
}
public void setAcceptStation(String AcceptStation) {
this.AcceptStation = AcceptStation;
}
public String getAcceptTime() {
return AcceptTime;
}
public void setAcceptTime(String AcceptTime) {
this.AcceptTime = AcceptTime;
}
}

View File

@ -0,0 +1,174 @@
package co.yixiang.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class JacksonUtil {
private static final Log logger = LogFactory.getLog(JacksonUtil.class);
public static String parseString(String body, String field) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
JsonNode leaf = node.get(field);
if (leaf != null)
return leaf.asText();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static List<String> parseStringList(String body, String field) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
JsonNode leaf = node.get(field);
if (leaf != null)
return mapper.convertValue(leaf, new TypeReference<List<String>>() {
});
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static Integer parseInteger(String body, String field) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
JsonNode leaf = node.get(field);
if (leaf != null)
return leaf.asInt();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static List<Integer> parseIntegerList(String body, String field) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
JsonNode leaf = node.get(field);
if (leaf != null)
return mapper.convertValue(leaf, new TypeReference<List<Integer>>() {
});
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static Boolean parseBoolean(String body, String field) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
JsonNode leaf = node.get(field);
if (leaf != null)
return leaf.asBoolean();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static Short parseShort(String body, String field) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
JsonNode leaf = node.get(field);
if (leaf != null) {
Integer value = leaf.asInt();
return value.shortValue();
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static Byte parseByte(String body, String field) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
JsonNode leaf = node.get(field);
if (leaf != null) {
Integer value = leaf.asInt();
return value.byteValue();
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static <T> T parseObject(String body, String field, Class<T> clazz) {
ObjectMapper mapper = new ObjectMapper();
JsonNode node;
try {
node = mapper.readTree(body);
node = node.get(field);
return mapper.treeToValue(node, clazz);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static Object toNode(String json) {
if (json == null) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.readTree(json);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static Map<String, String> toMap(String data) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.readValue(data, new TypeReference<Map<String, String>>() {
});
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public static String toJson(Object data) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(data);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}