diff --git a/pom.xml b/pom.xml index ba843b9..53f1d37 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,14 @@ org.springframework.boot spring-boot-starter-freemarker + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-websocket + diff --git a/src/main/java/com/imooc/aspect/SellerAuthorizeAspect.java b/src/main/java/com/imooc/aspect/SellerAuthorizeAspect.java index 33f4447..8c9399c 100644 --- a/src/main/java/com/imooc/aspect/SellerAuthorizeAspect.java +++ b/src/main/java/com/imooc/aspect/SellerAuthorizeAspect.java @@ -1,7 +1,56 @@ package com.imooc.aspect; +import com.imooc.constant.CookieConstant; +import com.imooc.constant.RedisConstant; +import com.imooc.exception.SellerAuthorizeException; +import com.imooc.utils.CookieUtil; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; + /** * Created by SqMax on 2018/4/2. */ +@Aspect +@Component +@Slf4j public class SellerAuthorizeAspect { + + @Autowired + private StringRedisTemplate redisTemplate; + +// @Pointcut("execution(public * com.imooc.controller.Seller*.*(..))"+ +// "&& !execution(public * com.imooc.controller.SellerUserController.*(..))") +// public void verify(){} +// +// @Before("verify()") +// public void doVerify(){ +// ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); +// HttpServletRequest request=attributes.getRequest(); +// +// //查询cookie +// Cookie cookie= CookieUtil.get(request,CookieConstant.TOKEN); +// if (cookie==null){ +// log.warn("【登录校验】Cookie中查不到token"); +// throw new SellerAuthorizeException(); +// } +// +// //去redis查询 +// String tokenValue=redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX,cookie.getValue())); +// if (StringUtils.isEmpty(tokenValue)){ +// log.warn("【登录校验】 Redis中查不到token"); +// throw new SellerAuthorizeException(); +// } +// } + } diff --git a/src/main/java/com/imooc/config/ProjectUrlConfig.java b/src/main/java/com/imooc/config/ProjectUrlConfig.java index 2250fec..e73737b 100644 --- a/src/main/java/com/imooc/config/ProjectUrlConfig.java +++ b/src/main/java/com/imooc/config/ProjectUrlConfig.java @@ -1,7 +1,30 @@ package com.imooc.config; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + /** * Created by SqMax on 2018/4/1. */ -public class ProjectUrl { +@Data +@ConfigurationProperties(prefix = "projectUrl") +@Component +public class ProjectUrlConfig { + + /** + * 微信公众平台授权url + */ + public String wechatMpAuthorize; + + /** + * 微信开放平台授权url + */ + public String wechatOpenAuthorize; + + /** + * 点餐系统 + */ + public String sell; + } diff --git a/src/main/java/com/imooc/config/WebSocketConfig.java b/src/main/java/com/imooc/config/WebSocketConfig.java index 56210b5..3c81939 100644 --- a/src/main/java/com/imooc/config/WebSocketConfig.java +++ b/src/main/java/com/imooc/config/WebSocketConfig.java @@ -1,7 +1,17 @@ package com.imooc.config; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + /** * Created by SqMax on 2018/4/2. */ +@Component public class WebSocketConfig { + +// @Bean +// public ServerEndpointExporter serverEndpointExporter(){ +// return new ServerEndpointExporter(); +// } } diff --git a/src/main/java/com/imooc/config/WechatAccountConfig.java b/src/main/java/com/imooc/config/WechatAccountConfig.java index 9b3e8b0..72615f0 100644 --- a/src/main/java/com/imooc/config/WechatAccountConfig.java +++ b/src/main/java/com/imooc/config/WechatAccountConfig.java @@ -4,6 +4,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; +import java.util.Map; + /** * Created by SqMax on 2018/3/23. */ @@ -12,9 +14,24 @@ @ConfigurationProperties(prefix = "wechat") public class WechatAccountConfig { + /** + * 公众平台id + */ private String mpAppId; + /** + * 公众平台密钥 + */ private String mpAppSecret; + /** + * 开放平台id + */ + private String openAppId; + /** + * 开放平台密钥 + */ + private String openAppSecret; + /** * 商户号 */ @@ -35,4 +52,10 @@ public class WechatAccountConfig { */ private String notifyUrl; + /** + * 微信模板id + */ + private Map templateId; + + } diff --git a/src/main/java/com/imooc/config/WechatOpenConfig.java b/src/main/java/com/imooc/config/WechatOpenConfig.java index 0e4b03c..65ba32a 100644 --- a/src/main/java/com/imooc/config/WechatOpenConfig.java +++ b/src/main/java/com/imooc/config/WechatOpenConfig.java @@ -1,7 +1,33 @@ package com.imooc.config; +import me.chanjar.weixin.mp.api.WxMpConfigStorage; +import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + /** * Created by SqMax on 2018/4/1. */ +@Component public class WechatOpenConfig { + + @Autowired + private WechatAccountConfig accountConfig; + + @Bean + public WxMpService wxOpenService(){ + WxMpService wxOpenService=new WxMpServiceImpl(); + wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage()); + return wxOpenService; + } + @Bean + public WxMpConfigStorage wxOpenConfigStorage(){ + WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage=new WxMpInMemoryConfigStorage(); + wxMpInMemoryConfigStorage.setAppId(accountConfig.getOpenAppId()); + wxMpInMemoryConfigStorage.setSecret(accountConfig.getOpenAppSecret()); + return wxMpInMemoryConfigStorage; + } } diff --git a/src/main/java/com/imooc/constant/CookieConstant.java b/src/main/java/com/imooc/constant/CookieConstant.java index 6d6d8d2..181b47f 100644 --- a/src/main/java/com/imooc/constant/CookieConstant.java +++ b/src/main/java/com/imooc/constant/CookieConstant.java @@ -4,4 +4,8 @@ * Created by SqMax on 2018/4/1. */ public interface CookieConstant { + + String TOKEN="token"; + + Integer EXPIRE=7200; } diff --git a/src/main/java/com/imooc/constant/RedisConstant.java b/src/main/java/com/imooc/constant/RedisConstant.java index 9a967d1..b4979a2 100644 --- a/src/main/java/com/imooc/constant/RedisConstant.java +++ b/src/main/java/com/imooc/constant/RedisConstant.java @@ -1,7 +1,12 @@ package com.imooc.constant; /** + * redis常量 * Created by SqMax on 2018/4/1. */ -public class RedisConstant { +public interface RedisConstant { + + String TOKEN_PREFIX="token_%s"; + + Integer EXPIRE=7200;//2小时 } diff --git a/src/main/java/com/imooc/controller/PayController.java b/src/main/java/com/imooc/controller/PayController.java index d2cd378..6468349 100644 --- a/src/main/java/com/imooc/controller/PayController.java +++ b/src/main/java/com/imooc/controller/PayController.java @@ -5,9 +5,14 @@ import com.imooc.exception.SellException; import com.imooc.service.OrderService; import com.imooc.service.PayService; +import com.imooc.utils.JsonUtil; +import com.lly835.bestpay.enums.BestPayTypeEnum; +import com.lly835.bestpay.model.PayRequest; import com.lly835.bestpay.model.PayResponse; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @@ -17,7 +22,8 @@ * Created by SqMax on 2018/3/26. */ @Controller -@RequestMapping("/pay") +//@RequestMapping("/pay") +@Slf4j public class PayController { @Autowired @@ -26,6 +32,28 @@ public class PayController { @Autowired private PayService payService; + @GetMapping("/pay") + public ModelAndView index(@RequestParam("openid") String openid, + @RequestParam("orderId") String orderId, + @RequestParam("returnUrl") String returnUrl, + Map map){ + log.info("openid={}",openid); + //1.查询订单 +// String orderId="1234563"; + OrderDTO orderDTO=orderService.findOne(orderId); + if(orderDTO==null){ + throw new SellException(ResultEnum.ORDER_NOT_EXIST); + } + //2.发起支付 + orderDTO.setBuyerOpenid(openid); + PayResponse payResponse=payService.create(orderDTO); + + map.put("payResponse",payResponse); + map.put("returnUrl","http://www.imooc.com"); + + return new ModelAndView("pay/create",map); + } + @GetMapping("/create") public ModelAndView create(@RequestParam("orderId") String orderId, @RequestParam("returnUrl") String returnUrl, @@ -51,6 +79,7 @@ public ModelAndView create(@RequestParam("orderId") String orderId, @PostMapping("/notify") public ModelAndView notify(@RequestBody String notifyData){ + log.info("notifyData:{}",notifyData); payService.notify(notifyData); //返回给微信处理结果 diff --git a/src/main/java/com/imooc/controller/SellerUserController.java b/src/main/java/com/imooc/controller/SellerUserController.java index 5ce12b8..54794f9 100644 --- a/src/main/java/com/imooc/controller/SellerUserController.java +++ b/src/main/java/com/imooc/controller/SellerUserController.java @@ -1,7 +1,82 @@ package com.imooc.controller; +import com.imooc.config.ProjectUrlConfig; +import com.imooc.constant.CookieConstant; +import com.imooc.constant.RedisConstant; +import com.imooc.dataobject.SellerInfo; +import com.imooc.enums.ResultEnum; +import com.imooc.service.SellerService; +import com.imooc.utils.CookieUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + /** * Created by SqMax on 2018/4/1. */ +@Controller +@RequestMapping("/seller") public class SellerUserController { + + @Autowired + private SellerService sellerService; + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private ProjectUrlConfig projectUrlConfig; + + @GetMapping("/login") + public ModelAndView login(@RequestParam("openid") String openid, + HttpServletResponse response, + Map map){ + + //1.openid去和数据库里的数据匹配 + SellerInfo sellerInfo=sellerService.findSellerInfoByOpenid(openid); + if(sellerInfo==null){ + map.put("msg", ResultEnum.LOGIN_FAIL.getMessage()); + map.put("url","/sell/seller/order/list"); + return new ModelAndView("common/error"); + } + //2.设置token至redis + String token= UUID.randomUUID().toString(); + Integer expire= RedisConstant.EXPIRE; + redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX,token),openid,expire, TimeUnit.SECONDS); + + //3.设置token至cookie + CookieUtil.set(response, CookieConstant.TOKEN,token,expire); + + return new ModelAndView("redirect:"+projectUrlConfig.getSell()+"/sell/seller/order/list"); + } + + @GetMapping("/logout") + public ModelAndView logout(HttpServletRequest request, + HttpServletResponse response, + Map map){ + + //1.从cookie里查询 + Cookie cookie=CookieUtil.get(request,CookieConstant.TOKEN); + if(cookie!=null){ + //2.清除redis + redisTemplate.opsForValue().getOperations().delete(String.format(RedisConstant.TOKEN_PREFIX,cookie.getValue())); + //3.清除cookie + CookieUtil.set(response,CookieConstant.TOKEN,null,0); + } + map.put("msg",ResultEnum.LOGOUT_SUCCESS.getMessage()); + map.put("url","/sell/seller/order/list"); + return new ModelAndView("common/success",map); + + } } diff --git a/src/main/java/com/imooc/controller/WechatController.java b/src/main/java/com/imooc/controller/WechatController.java index 5cea33f..b73496c 100644 --- a/src/main/java/com/imooc/controller/WechatController.java +++ b/src/main/java/com/imooc/controller/WechatController.java @@ -1,20 +1,18 @@ package com.imooc.controller; -import com.imooc.SellApplication; +import com.imooc.config.ProjectUrlConfig; import com.imooc.enums.ResultEnum; import com.imooc.exception.SellException; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; import java.net.URLEncoder; @@ -29,12 +27,18 @@ public class WechatController { @Autowired private WxMpService wxMpService; + @Autowired + private WxMpService wxOpenService; + + @Autowired + private ProjectUrlConfig projectUrlConfig; + @GetMapping("/authorize") public String authorize(@RequestParam("returnUrl") String returnUrl){ // WxMpService wxMpService=new WxMpServiceImpl(); //1. 配置 //2.调用方法 - String url="http://sqmax.natapp1.cc/sell/wechat/userInfo"; + String url=projectUrlConfig.getWechatMpAuthorize()+"/sell/wechat/userInfo"; String redirectUrl=wxMpService.oauth2buildAuthorizationUrl(url,WxConsts.OAUTH2_SCOPE_BASE, URLEncoder.encode(returnUrl)); log.info("【微信网页授权】获取code,redirectUrl={}",redirectUrl); return "redirect:"+redirectUrl; @@ -55,4 +59,25 @@ public String userInfo(@RequestParam("code") String code, return "redirect:"+ returnUrl+"?openid="+openId; } + + @GetMapping("/qrAuthorize") + public String qrAuthorize(@RequestParam("returnUrl") String returnUrl){ + String url=projectUrlConfig.getWechatOpenAuthorize()+"/sell/wechat/userInfo"; + String redirectUrl=wxOpenService.buildQrConnectUrl(url,WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN,URLEncoder.encode(returnUrl)); + return "redirect:"+redirectUrl; + } + @GetMapping("qrUserInfo") + public String qrUserInfo(@RequestParam("code") String code, + @RequestParam("state") String returnUrl){ + WxMpOAuth2AccessToken wxMpOAuth2AccessToken=new WxMpOAuth2AccessToken(); + try{ + wxMpOAuth2AccessToken=wxOpenService.oauth2getAccessToken(code); + }catch (WxErrorException e){ + log.error("【微信网页】{}",e); + throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(),e.getError().getErrorMsg()); + } + log.info("wxMpOAuth2AccessToken={}",wxMpOAuth2AccessToken); + String openId=wxMpOAuth2AccessToken.getOpenId(); + return "redirect:"+returnUrl+"?openid="+openId; + } } diff --git a/src/main/java/com/imooc/dataobject/SellerInfo.java b/src/main/java/com/imooc/dataobject/SellerInfo.java index cba2cc9..d9e60eb 100644 --- a/src/main/java/com/imooc/dataobject/SellerInfo.java +++ b/src/main/java/com/imooc/dataobject/SellerInfo.java @@ -1,7 +1,24 @@ package com.imooc.dataobject; +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; + /** * Created by SqMax on 2018/3/31. */ +@Data +@Entity public class SellerInfo { + + @Id + private String sellerId; + + private String username; + + private String password; + + private String openid; + } diff --git a/src/main/java/com/imooc/enums/ResultEnum.java b/src/main/java/com/imooc/enums/ResultEnum.java index de74b48..1011f50 100644 --- a/src/main/java/com/imooc/enums/ResultEnum.java +++ b/src/main/java/com/imooc/enums/ResultEnum.java @@ -28,9 +28,13 @@ public enum ResultEnum { ORDER_CANCEL_SUCCESS(22,"订单取消成功"), - ORDER_FINISH_SUCCESS(22,"订单完结成功"), + ORDER_FINISH_SUCCESS(23,"订单完结成功"), - PRODUCT_STATUS_ERROR(23,"商品状态不正确"), + PRODUCT_STATUS_ERROR(24,"商品状态不正确"), + + LOGIN_FAIL(25,"登录失败,登录信息不正确"), + + LOGOUT_SUCCESS(26,"登出成功"), ; private Integer code; diff --git a/src/main/java/com/imooc/exception/ResponseBankException.java b/src/main/java/com/imooc/exception/ResponseBankException.java index db2a33c..61f4ccb 100644 --- a/src/main/java/com/imooc/exception/ResponseBankException.java +++ b/src/main/java/com/imooc/exception/ResponseBankException.java @@ -3,5 +3,5 @@ /** * Created by SqMax on 2018/4/3. */ -public class ResponseBankException { +public class ResponseBankException extends RuntimeException{ } diff --git a/src/main/java/com/imooc/exception/SellException.java b/src/main/java/com/imooc/exception/SellException.java index 0edb15d..5c76a4c 100644 --- a/src/main/java/com/imooc/exception/SellException.java +++ b/src/main/java/com/imooc/exception/SellException.java @@ -1,10 +1,12 @@ package com.imooc.exception; import com.imooc.enums.ResultEnum; +import lombok.Getter; /** * Created by SqMax on 2018/3/18. */ +@Getter public class SellException extends RuntimeException { private Integer code; diff --git a/src/main/java/com/imooc/exception/SellerAuthorizeException.java b/src/main/java/com/imooc/exception/SellerAuthorizeException.java index 82797d4..c254167 100644 --- a/src/main/java/com/imooc/exception/SellerAuthorizeException.java +++ b/src/main/java/com/imooc/exception/SellerAuthorizeException.java @@ -3,5 +3,6 @@ /** * Created by SqMax on 2018/4/2. */ -public class SellerAuthorizeAspectException { +public class SellerAuthorizeException extends RuntimeException { + } diff --git a/src/main/java/com/imooc/handler/SellerExceptionHandler.java b/src/main/java/com/imooc/handler/SellerExceptionHandler.java index 1421c92..ff83c96 100644 --- a/src/main/java/com/imooc/handler/SellerExceptionHandler.java +++ b/src/main/java/com/imooc/handler/SellerExceptionHandler.java @@ -1,7 +1,46 @@ package com.imooc.handler; +import com.imooc.VO.ResultVO; +import com.imooc.config.ProjectUrlConfig; +import com.imooc.exception.ResponseBankException; +import com.imooc.exception.SellException; +import com.imooc.exception.SellerAuthorizeException; +import com.imooc.utils.ResultVOUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + /** * Created by SqMax on 2018/4/2. */ -public class ExceptionHandler { +@ControllerAdvice +public class SellerExceptionHandler { + + @Autowired + private ProjectUrlConfig projectUrlConfig; + + //拦截登录异常 + //http://sqmax.natapp1.cc/sell/wechat/qrAuthorize?returnUrl=http://sqmax.natapp1.cc/sell/seller/login + @ExceptionHandler(value = SellerAuthorizeException.class) + public ModelAndView handlerAuthorizeException(){ + return new ModelAndView("redirect:" + .concat(projectUrlConfig.getWechatOpenAuthorize()) + .concat("/sell/wechat/qrAuthorize") + .concat("?returnUrl=") + .concat(projectUrlConfig.getSell()) + .concat("/sell/seller/login")); + } + + @ExceptionHandler(value = SellException.class) + @ResponseBody + public ResultVO handlerSellerException(SellException e){ + return ResultVOUtil.error(e.getCode(),e.getMessage()); + } + + @ExceptionHandler(value = ResponseBankException.class) + @ResponseStatus(HttpStatus.FORBIDDEN) + public void handleResponseBankException(){ + + } } diff --git a/src/main/java/com/imooc/repository/SellerInfoRepository.java b/src/main/java/com/imooc/repository/SellerInfoRepository.java index f38a388..0330a59 100644 --- a/src/main/java/com/imooc/repository/SellerInfoRepository.java +++ b/src/main/java/com/imooc/repository/SellerInfoRepository.java @@ -1,7 +1,12 @@ package com.imooc.repository; +import com.imooc.dataobject.SellerInfo; +import org.springframework.data.jpa.repository.JpaRepository; + /** * Created by SqMax on 2018/3/31. */ -public interface SellerInfoRepository { +public interface SellerInfoRepository extends JpaRepository { + + SellerInfo findByOpenid(String openid); } diff --git a/src/main/java/com/imooc/service/PushMessageService.java b/src/main/java/com/imooc/service/PushMessageService.java index bb9ca0b..d91a06f 100644 --- a/src/main/java/com/imooc/service/PushMessageService.java +++ b/src/main/java/com/imooc/service/PushMessageService.java @@ -6,7 +6,7 @@ * 推送消息 * Created by SqMax on 2018/4/2. */ -public interface PushMessage { +public interface PushMessageService { /** * 订单状态变更消息 diff --git a/src/main/java/com/imooc/service/SellerService.java b/src/main/java/com/imooc/service/SellerService.java index 823d3a7..bab064b 100644 --- a/src/main/java/com/imooc/service/SellerService.java +++ b/src/main/java/com/imooc/service/SellerService.java @@ -1,7 +1,17 @@ package com.imooc.service; +import com.imooc.dataobject.SellerInfo; + /** + * 卖家端 * Created by SqMax on 2018/4/1. */ public interface SellerService { + + /** + * 通过openid查询 + * @param openid + * @return + */ + SellerInfo findSellerInfoByOpenid(String openid); } diff --git a/src/main/java/com/imooc/service/WebSocket.java b/src/main/java/com/imooc/service/WebSocket.java index ba7d53f..b74f721 100644 --- a/src/main/java/com/imooc/service/WebSocket.java +++ b/src/main/java/com/imooc/service/WebSocket.java @@ -1,7 +1,54 @@ package com.imooc.service; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.websocket.OnClose; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.ServerEndpoint; +import java.util.concurrent.CopyOnWriteArraySet; + /** * Created by SqMax on 2018/4/2. */ +@Component +@ServerEndpoint("/webSocket") +@Slf4j public class WebSocket { + + private Session session; + + private static CopyOnWriteArraySet webSocketSet=new CopyOnWriteArraySet<>(); + + @OnOpen + public void opOpen(Session session){ + this.session=session; + webSocketSet.add(this); + log.info("【websocket消息】 有新的连接,总数:{}",webSocketSet.size()); + } + + @OnClose + public void onClose(){ + webSocketSet.remove(this); + log.info("【websocket消息】 连接断开,总数:{}",webSocketSet.size()); + } + + @OnMessage + public void onMessage(String message){ + log.info("【websocket消息】 收到客户端发来的消息:{}",message); + } + + public void sendMessage(String message){ + for(WebSocket webSocket:webSocketSet){ + log.info("【websocket消息】 广播消息,message={}",message); + try { + webSocket.session.getBasicRemote().sendText(message); + }catch (Exception e){ + e.printStackTrace(); + } + } + } + } diff --git a/src/main/java/com/imooc/service/impl/OrderServiceImpl.java b/src/main/java/com/imooc/service/impl/OrderServiceImpl.java index 2b82539..ab7a413 100644 --- a/src/main/java/com/imooc/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/imooc/service/impl/OrderServiceImpl.java @@ -9,12 +9,11 @@ import com.imooc.enums.OrderStatusEnum; import com.imooc.enums.PayStatusEnum; import com.imooc.enums.ResultEnum; +import com.imooc.exception.ResponseBankException; import com.imooc.exception.SellException; import com.imooc.repository.OrderDetailRepository; import com.imooc.repository.OrderMasterRepository; -import com.imooc.service.OrderService; -import com.imooc.service.PayService; -import com.imooc.service.ProductService; +import com.imooc.service.*; import com.imooc.utils.KeyUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; @@ -52,6 +51,12 @@ public class OrderServiceImpl implements OrderService { @Autowired private PayService payService; + @Autowired + private PushMessageService pushMessageService; + + @Autowired + private WebSocket webSocket; + @Override @Transactional public OrderDTO create(OrderDTO orderDTO) { @@ -64,7 +69,8 @@ public OrderDTO create(OrderDTO orderDTO) { for(OrderDetail orderDetail:orderDTO.getOrderDetailList()){ ProductInfo productInfo=productService.findOne(orderDetail.getProductId()); if(productInfo==null){ - throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); +// throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); + throw new ResponseBankException(); } //2.计算订单总价 orderAmount=productInfo.getProductPrice() @@ -97,6 +103,9 @@ public OrderDTO create(OrderDTO orderDTO) { .collect(Collectors.toList()); productService.decreaseStock(cartDTOList); + //发送websocket消息 + webSocket.sendMessage(orderDTO.getOrderId()); + return orderDTO; } @@ -181,6 +190,8 @@ public OrderDTO finish(OrderDTO orderDTO) { log.error("【完结订单】更新失败,orderMaster={}",orderMaster); throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); } + //推送微信模板消息 + pushMessageService.orderStatus(orderDTO); return orderDTO; } diff --git a/src/main/java/com/imooc/service/impl/PushMessageServiceImpl.java b/src/main/java/com/imooc/service/impl/PushMessageServiceImpl.java index 3de9704..90b9282 100644 --- a/src/main/java/com/imooc/service/impl/PushMessageServiceImpl.java +++ b/src/main/java/com/imooc/service/impl/PushMessageServiceImpl.java @@ -1,30 +1,49 @@ package com.imooc.service.impl; +import com.imooc.config.WechatAccountConfig; import com.imooc.dto.OrderDTO; -import com.imooc.service.PushMessage; +import com.imooc.service.PushMessageService; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.Arrays; +import java.util.List; + /** * Created by SqMax on 2018/4/2. */ @Service @Slf4j -public class PushMessageImpl implements PushMessage { +public class PushMessageServiceImpl implements PushMessageService { @Autowired private WxMpService wxMpService; + @Autowired + private WechatAccountConfig accountConfig; + @Override public void orderStatus(OrderDTO orderDTO) { WxMpTemplateMessage templateMessage=new WxMpTemplateMessage(); - templateMessage.setTemplateId("GoCullfix05R-rCibvoyI87ZUg50cyieKA5AyX7pPzo"); - templateMessage.setToUser(""); + templateMessage.setTemplateId(accountConfig.getTemplateId().get("orderStatus"));//模板id:"GoCullfix05R-rCibvoyI87ZUg50cyieKA5AyX7pPzo" + templateMessage.setToUser(orderDTO.getBuyerOpenid());//openid:"ozswp1Ojl2rA57ZK97ntGw2WQ2CA" + + List data= Arrays.asList( + new WxMpTemplateData("first","亲,记得收货"), + new WxMpTemplateData("keyword1","微信点餐"), + new WxMpTemplateData("keyword2","15712363915"), + new WxMpTemplateData("keyword3",orderDTO.getOrderId()), + new WxMpTemplateData("keyword4",orderDTO.getOrderStatusEnum().getMessage()), + new WxMpTemplateData("keyword5","¥"+orderDTO.getOrderAmount()), + new WxMpTemplateData("remark","欢迎再次光临")); + templateMessage.setData(data); + try { wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage); }catch (WxErrorException e){ diff --git a/src/main/java/com/imooc/service/impl/SellerServiceImpl.java b/src/main/java/com/imooc/service/impl/SellerServiceImpl.java index 040db89..9c8424c 100644 --- a/src/main/java/com/imooc/service/impl/SellerServiceImpl.java +++ b/src/main/java/com/imooc/service/impl/SellerServiceImpl.java @@ -1,7 +1,22 @@ package com.imooc.service.impl; +import com.imooc.dataobject.SellerInfo; +import com.imooc.repository.SellerInfoRepository; +import com.imooc.service.SellerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + /** * Created by SqMax on 2018/4/1. */ -public class SellerServiceImpl { +@Service +public class SellerServiceImpl implements SellerService{ + + @Autowired + private SellerInfoRepository repository; + + @Override + public SellerInfo findSellerInfoByOpenid(String openid) { + return repository.findByOpenid(openid); + } } diff --git a/src/main/java/com/imooc/utils/CookieUtil.java b/src/main/java/com/imooc/utils/CookieUtil.java index 2c99b15..1aa2ad5 100644 --- a/src/main/java/com/imooc/utils/CookieUtil.java +++ b/src/main/java/com/imooc/utils/CookieUtil.java @@ -1,7 +1,59 @@ package com.imooc.utils; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.MalformedParameterizedTypeException; +import java.util.HashMap; +import java.util.Map; + /** + * Cookie工具类 * Created by SqMax on 2018/4/1. */ public class CookieUtil { + + public static void set(HttpServletResponse response, + String name, + String value, + int maxAge){ + Cookie cookie=new Cookie(name,value); + cookie.setPath("/"); + cookie.setMaxAge(maxAge); + response.addCookie(cookie); + } + + /** + * 获取cookie + * @param request + * @param name + * @return + */ + public static Cookie get(HttpServletRequest request, + String name){ + + Map cookieMap=readCookieMap(request); + if(cookieMap.containsKey(name)){ + return cookieMap.get(name); + }else{ + return null; + } + + } + + /** + * 将Cookie封装成Map + * @param request + * @return + */ + private static Map readCookieMap(HttpServletRequest request){ + Map cookieMap=new HashMap<>(); + Cookie[] cookies=request.getCookies(); + if(cookies!=null){ + for(Cookie cookie:cookies){ + cookieMap.put(cookie.getName(),cookie); + } + } + return cookieMap; + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fbce7b3..78d4118 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -3,13 +3,16 @@ spring: driver-class-name: com.mysql.jdbc.Driver username: root password: 123456 - url: jdbc:mysql://192.168.0.102/sell?characterEncoding=utf-8&useSSL=false + url: jdbc:mysql://192.168.0.104/sell?characterEncoding=utf-8&useSSL=false jpa: show-sql: true jackson: default-property-inclusion: non_null -server: - context-path: /sell + redis: + host: 192.168.0.104 + port: 6379 +#server: +# context-path: /sell #logging: # pattern: # console: "%d - %msg%n" @@ -19,11 +22,20 @@ server: # com.imooc.LoggerTest: debug wechat: - mpAppId: wxdcf91e9f784bfad0 - mpAppSecret: c467c06d98a2447f5ddef6ca8f47f268 -# mpAppId: wxd898fcb01713c658 -# mpAppSecret: 29d8a650db31472aa87800e3b0d739f2 +# mpAppId: wxdcf91e9f784bfad0 +# mpAppSecret: c467c06d98a2447f5ddef6ca8f47f268 #测试号appId,appSecret + mpAppId: wxd898fcb01713c658 + mpAppSecret: xxxxxxxxx #借用号appId,appSecret + openAppId: wx6ad144e54af67d87 + openAppSecret: 91a2ff6d38a2bbccfb7e9f9079108e2e #开放平台测试号appId,appSecret mchId: 1483469312 - mchKey: 06C56A89949D617DEF52F371C357B6DB - keyPath: F:\\h5.p12 - nofifyUrl: http://sqmax.natapp1.cc/sell/pay/notify \ No newline at end of file + mchKey: C5245D70627C1F8E9964D494B0735025 + keyPath: C:/Users/Administrator/Downloads/h5.p12 + notifyUrl: http://sqmax.natapp1.cc/notify + templateId: + orderStatus: GoCullfix05R-rCibvoyI87ZUg50cyieKA5AyX7pPzo + +projectUrl: + wechatMpAuthorize: http://sqmax.natapp1.cc + wechatOpenAuthorize: http://sqmax.natapp1.cc + sell: http://sqmax.natapp1.cc diff --git a/src/main/resources/static/mp3/song.mp3 b/src/main/resources/static/mp3/song.mp3 new file mode 100644 index 0000000..e4c1c89 Binary files /dev/null and b/src/main/resources/static/mp3/song.mp3 differ diff --git a/src/main/resources/static/pay.html b/src/main/resources/static/pay.html index 1d8452f..ebe6183 100644 --- a/src/main/resources/static/pay.html +++ b/src/main/resources/static/pay.html @@ -3,12 +3,12 @@ function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { - "appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入 - "timeStamp":"1395712654", //时间戳,自1970年以来的秒数 - "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串 - "package":"prepay_id=u802345jgfjsdfgsdg888", + "appId":"wxd898fcb01713c658", //公众号名称,由商户传入 + "timeStamp":"1523064168", //时间戳,自1970年以来的秒数 + "nonceStr":"tOsmcPkfsyagBLGS", //随机串 + "package":"prepay_id=wx07092243803051870a4424bd0916479791", "signType":"MD5", //微信签名方式: - "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 + "paySign":"E5238611FBB1777BD7426393E472083F" //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 diff --git a/src/main/resources/templates/order/list.ftl b/src/main/resources/templates/order/list.ftl index 91486a6..641d2eb 100644 --- a/src/main/resources/templates/order/list.ftl +++ b/src/main/resources/templates/order/list.ftl @@ -77,7 +77,57 @@ + + +<#--播放音乐--> + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/pay/create.ftl b/src/main/resources/templates/pay/create.ftl index d811294..5654fec 100644 --- a/src/main/resources/templates/pay/create.ftl +++ b/src/main/resources/templates/pay/create.ftl @@ -8,12 +8,21 @@ "nonceStr":"${payResponse.nonceStr}", //随机串 "package":"${payResponse.packAge}", "signType":"MD5", //微信签名方式: - "paySign":"${payResponse.packAge}" //微信签名 + "paySign":"${payResponse.paySign}" //微信签名 }, function(res){ - if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 - location.href="${returnUrl}" - } + if(res.err_msg == "get_brand_wcpay_request:ok" ) { + alert('支付成功'); + }else if(res.err_msg == "get_brand_wcpay_request:cancel") { + alert('支付过程中用户取消'); + }else if(res.err_msg == "get_brand_wcpay_request:fail") { + alert('支付失败'); + }else { + alert('未知异常'); + } + <#--if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。--> + <#--location.href="${returnUrl}"--> + } ); } if (typeof WeixinJSBridge == "undefined"){ diff --git a/src/test/java/com/imooc/repository/SellerInfoRepositoryTest.java b/src/test/java/com/imooc/repository/SellerInfoRepositoryTest.java index 901ad96..ae9ee2e 100644 --- a/src/test/java/com/imooc/repository/SellerInfoRepositoryTest.java +++ b/src/test/java/com/imooc/repository/SellerInfoRepositoryTest.java @@ -1,8 +1,42 @@ +package com.imooc.repository; + +import com.imooc.dataobject.SellerInfo; +import com.imooc.utils.KeyUtil; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + import static org.junit.Assert.*; /** * Created by SqMax on 2018/3/31. */ +@RunWith(SpringRunner.class) +@SpringBootTest public class SellerInfoRepositoryTest { + @Autowired + private SellerInfoRepository repository; + + @Test + public void save(){ + SellerInfo sellerInfo=new SellerInfo(); + sellerInfo.setSellerId(KeyUtil.genUniqueKey()); + sellerInfo.setUsername("admin"); + sellerInfo.setPassword("admin"); + sellerInfo.setOpenid("abc"); + + SellerInfo result=repository.save(sellerInfo); + Assert.assertNotNull(result); + } + + @Test + public void findByOpenid() throws Exception{ + SellerInfo result=repository.findByOpenid("abc"); + Assert.assertEquals("abc",result.getOpenid()); + + } } \ No newline at end of file diff --git a/src/test/java/com/imooc/service/impl/PayServiceImplTest.java b/src/test/java/com/imooc/service/impl/PayServiceImplTest.java index a38d1ea..39e16f0 100644 --- a/src/test/java/com/imooc/service/impl/PayServiceImplTest.java +++ b/src/test/java/com/imooc/service/impl/PayServiceImplTest.java @@ -28,13 +28,13 @@ public class PayServiceImplTest { @Test public void create() throws Exception{ - OrderDTO orderDTO=orderService.findOne("1521459886722321539"); + OrderDTO orderDTO=orderService.findOne("1234561"); payService.create(orderDTO); } @Test public void refund(){ - OrderDTO orderDTO=orderService.findOne("1521459886722321539"); + OrderDTO orderDTO=orderService.findOne("1234561"); payService.refund(orderDTO); } } \ No newline at end of file diff --git a/src/test/java/com/imooc/service/impl/PushMessageServiceImplTest.java b/src/test/java/com/imooc/service/impl/PushMessageServiceImplTest.java index c756217..88864b9 100644 --- a/src/test/java/com/imooc/service/impl/PushMessageServiceImplTest.java +++ b/src/test/java/com/imooc/service/impl/PushMessageServiceImplTest.java @@ -1,8 +1,33 @@ +package com.imooc.service.impl; + +import com.imooc.dto.OrderDTO; +import com.imooc.enums.OrderStatusEnum; +import com.imooc.service.OrderService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + import static org.junit.Assert.*; /** * Created by SqMax on 2018/4/2. */ -public class PushMessageImplTest { +@RunWith(SpringRunner.class) +@SpringBootTest +public class PushMessageServiceImplTest { + + @Autowired + private PushMessageServiceImpl pushMessageService; + + @Autowired + private OrderService orderService; + + @Test + public void orderStatus() { + OrderDTO orderDTO=orderService.findOne("123456"); + pushMessageService.orderStatus(orderDTO); + } } \ No newline at end of file diff --git a/src/test/java/com/imooc/service/impl/SellerServiceImplTest.java b/src/test/java/com/imooc/service/impl/SellerServiceImplTest.java index bcea6c6..ccca4ef 100644 --- a/src/test/java/com/imooc/service/impl/SellerServiceImplTest.java +++ b/src/test/java/com/imooc/service/impl/SellerServiceImplTest.java @@ -1,8 +1,33 @@ +package com.imooc.service.impl; + +import com.imooc.dataobject.SellerInfo; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + import static org.junit.Assert.*; /** * Created by SqMax on 2018/4/1. */ +@RunWith(SpringRunner.class) +@SpringBootTest +@Slf4j public class SellerServiceImplTest { -} \ No newline at end of file + private static final String openid="abc"; + + @Autowired + private SellerServiceImpl sellerService; + @Test + public void findSellerInfoByOpenid() { + SellerInfo result=sellerService.findSellerInfoByOpenid(openid); + Assert.assertEquals(openid,result.getOpenid()); + } +} + +