├── src ├── test │ ├── resources │ │ └── .gitkeep │ └── java │ │ └── com │ │ └── imooc │ │ └── sell │ │ ├── Demo.java │ │ ├── dto │ │ └── SceneInfoDTOTest.java │ │ ├── service │ │ └── impl │ │ │ ├── SellerServiceImplTest.java │ │ │ ├── PayServiceImplTest.java │ │ │ ├── PushMessageServiceImplTest.java │ │ │ ├── OrderDetailServiceImplTest.java │ │ │ └── CategoryServiceImplTest.java │ │ ├── LoggerTest.java │ │ ├── repository │ │ ├── SellerInfoRepositoryTest.java │ │ ├── OrderDetailRepositoryTest.java │ │ ├── OrderMasterRepositoryTest.java │ │ └── ProductInfoRepositoryTest.java │ │ ├── jedis │ │ └── JedisDemo.java │ │ └── dataobject │ │ └── mapper │ │ └── ProductCategoryMapperTest.java └── main │ ├── resources │ ├── static │ │ ├── MP_verify_XQxncxNm3NuoTwNa.txt │ │ ├── favicon.ico │ │ ├── mp3 │ │ │ └── song.mp3 │ │ ├── js │ │ │ └── model │ │ │ │ └── upload.js │ │ ├── pay.html │ │ ├── api │ │ │ └── seller.json │ │ └── css │ │ │ ├── listProd.css │ │ │ ├── pay.css │ │ │ └── precreate.css │ ├── cert │ │ └── h5.p12 │ ├── templates │ │ ├── pay │ │ │ ├── success.ftl │ │ │ └── create.ftl │ │ ├── common │ │ │ ├── header.ftl │ │ │ ├── error.ftl │ │ │ ├── success.ftl │ │ │ └── nav.ftl │ │ ├── category │ │ │ └── index.ftl │ │ ├── book │ │ │ ├── category │ │ │ │ └── index.ftl │ │ │ └── info │ │ │ │ └── index.ftl │ │ └── product │ │ │ └── index.ftl │ └── mapper │ │ └── ProductCategoryMapper.xml │ └── java │ └── com │ └── imooc │ └── sell │ ├── handler │ ├── ScanHandler.java │ ├── AbstractHandler.java │ ├── NullHandler.java │ ├── KfSessionHandler.java │ ├── UnsubscribeHandler.java │ ├── StoreCheckNotifyHandler.java │ ├── EOFExceptionHandler.java │ ├── LogHandler.java │ ├── MenuHandler.java │ ├── LocationHandler.java │ ├── MsgHandler.java │ ├── SellerExceptionHandler.java │ └── SubscribeHandler.java │ ├── constant │ ├── RedisConstant.java │ └── CookieConstant.java │ ├── repository │ ├── SellerInfoRepository.java │ ├── OrderDetailRepository.java │ ├── OrderMasterRepository.java │ ├── ProductCategoryRepository.java │ └── ProductInfoRepository.java │ ├── exception │ ├── SellerAuthorizeException.java │ ├── ResponseBankException.java │ └── SellException.java │ ├── service │ ├── SellerService.java │ ├── SecKillService.java │ ├── PushMessageService.java │ ├── impl │ │ ├── SellerServiceImpl.java │ │ ├── OrderDetailServiceImpl.java │ │ ├── BuyerServiceImpl.java │ │ ├── PayH5ServiceImpl.java │ │ └── SecKillServiceImpl.java │ ├── BuyerService.java │ ├── PayService.java │ ├── OrderDetailService.java │ ├── PayH5Service.java │ ├── ProductService.java │ ├── RedisLock.java │ ├── CategoryService.java │ ├── OrderService.java │ └── WebSocket.java │ ├── builder │ ├── AbstractBuilder.java │ ├── ImageBuilder.java │ ├── TextBuilder.java │ └── NewsBuilder.java │ ├── enums │ ├── CategoryDeletedEnum.java │ ├── CodeEnum.java │ ├── OrderStatusEnum.java │ ├── ProductStatusEnum.java │ ├── PayStatusEnum.java │ ├── BookStatusEnum.java │ └── ResultEnum.java │ ├── dto │ ├── SceneInfoDTO.java │ ├── AppInfoDTO.java │ ├── CartDTO.java │ └── OrderDTO.java │ ├── converter │ ├── ProductForm2CartDTOConverter.java │ ├── OrderMaster2OrderDTOConverter.java │ └── OrderForm2OrderDTOConverter.java │ ├── dataobject │ ├── dao │ │ └── ProductCategoryDao.java │ ├── SellerInfo.java │ ├── ProductCategory.java │ ├── OrderDetail.java │ └── OrderMaster.java │ ├── utils │ ├── ShellExcutorUtil.java │ ├── KeyUtil.java │ ├── EnumUtil.java │ ├── MathUtil.java │ ├── BookStoreResultVOUtils.java │ ├── ResultVOUtil.java │ ├── JsonUtils.java │ ├── UUIDUtil.java │ ├── serializer │ │ └── Date2LongSerializer.java │ ├── CookieUtil.java │ └── MD5Util.java │ ├── VO │ ├── BookVO.java │ ├── ProductVO.java │ ├── ResultVO.java │ ├── BookStoreResultVO.java │ ├── ProductInfoVO.java │ └── BookInfoVO.java │ ├── SellApplication.java │ ├── config │ ├── WebSocketConfig.java │ ├── WechatOpenConfig.java │ ├── WechatPayConfig.java │ ├── WechatScanPayConfig.java │ ├── prop │ │ ├── ProjectUrlProperties.java │ │ └── WechatMpProperties.java │ └── WechatPayH5Config.java │ ├── controller │ ├── AliF2FPayController.java │ ├── SecKillController.java │ ├── MyOrderController.java │ ├── PayController.java │ └── SellerUserController.java │ ├── form │ ├── CategoryForm.java │ ├── BookCategoryForm.java │ ├── OrderForm.java │ └── ProductForm.java │ └── aspect │ ├── SellerAuthorizeAspect.java │ └── HttpAspect.java ├── deploy.sh ├── doc ├── 数据库文档.docx └── 访问路径.txt ├── .gitignore └── ReadMe.md /src/test/resources/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | -------------------------------------------------------------------------------- /src/main/resources/static/MP_verify_XQxncxNm3NuoTwNa.txt: -------------------------------------------------------------------------------- 1 | XQxncxNm3NuoTwNa -------------------------------------------------------------------------------- /doc/数据库文档.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wangyanjunai/sell_fe_seller/HEAD/doc/数据库文档.docx -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | *.iml 3 | .idea 4 | log/ 5 | *.conf 6 | *.yml 7 | /doc/ 8 | logback-spring.xml -------------------------------------------------------------------------------- /src/main/resources/cert/h5.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wangyanjunai/sell_fe_seller/HEAD/src/main/resources/cert/h5.p12 -------------------------------------------------------------------------------- /src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wangyanjunai/sell_fe_seller/HEAD/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/static/mp3/song.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wangyanjunai/sell_fe_seller/HEAD/src/main/resources/static/mp3/song.mp3 -------------------------------------------------------------------------------- /src/main/resources/templates/pay/success.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/ScanHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | /** 4 | * @author Binary Wang(https://github.com/binarywang) 5 | */ 6 | public abstract class ScanHandler extends AbstractHandler { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/static/js/model/upload.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | $('#inputFile').change(function () { 3 | var fileName = $(this).val() 4 | alert(fileName) 5 | $('#inputFile').fileupload({ 6 | }) 7 | }) 8 | }) -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/constant/RedisConstant.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.constant; 2 | 3 | /** 4 | * redis常量 5 | */ 6 | public interface RedisConstant { 7 | 8 | Integer EXPIRE = 7200;//2小时 9 | 10 | String TOKEN_PREFIX = "TOKEN_%s";//token前缀 11 | 12 | String CART_COOKIE_PREFIX = "CART_COOKIE%s";//cart前缀 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/constant/CookieConstant.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.constant; 2 | 3 | /** 4 | * Cookie常量 5 | * @Author 王艳军 6 | * @Date 2017-12-17 16:24 7 | */ 8 | public interface CookieConstant { 9 | 10 | String TOKEN = "token"; 11 | 12 | String Cart_Cookie = "cart_cookie_"; 13 | 14 | Integer EXPIRE = 7200; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/repository/SellerInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.repository; 2 | 3 | import com.imooc.sell.dataobject.SellerInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface SellerInfoRepository extends JpaRepository { 7 | SellerInfo findByOpenid(String openid); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/exception/SellerAuthorizeException.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.exception; 2 | 3 | /** 4 | * describe: 5 | * 6 | * @Author 王艳军 7 | * @Date 2017/12/18 17:34:03 8 | */ 9 | public class SellerAuthorizeException extends RuntimeException{ 10 | 11 | /** 12 | * serialVersionUID:序列号 13 | */ 14 | private static final long serialVersionUID = -1464905525932369416L; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/SellerService.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service; 2 | 3 | import com.imooc.sell.dataobject.SellerInfo; 4 | 5 | /** 6 | * 卖家端Service 7 | * Create By 王艳军 8 | */ 9 | public interface SellerService { 10 | 11 | /** 12 | * 根据卖家微信openid查找卖家信息 13 | * @param openid 14 | * @return 15 | */ 16 | SellerInfo findSellerInfoByOpenid(String openid); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/builder/AbstractBuilder.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.builder; 2 | 3 | import me.chanjar.weixin.mp.api.WxMpService; 4 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 6 | 7 | public abstract class AbstractBuilder { 8 | 9 | public abstract WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/AbstractHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import me.chanjar.weixin.mp.api.WxMpMessageHandler; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * @author Binary Wang(https://github.com/binarywang) 9 | */ 10 | public abstract class AbstractHandler implements WxMpMessageHandler { 11 | protected Logger logger = LoggerFactory.getLogger(getClass()); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/enums/CategoryDeletedEnum.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Getter 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public enum CategoryDeletedEnum implements CodeEnum{ 11 | 12 | NOT_DELETE(0, "否"), 13 | 14 | DELETE(1, "是"), 15 | 16 | ; 17 | 18 | private Integer code; 19 | 20 | private String message; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dto/SceneInfoDTO.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | *
10 |  * @description:场景信息DTO
11 |  * @author 王艳军
12 |  * @version 1.0
13 |  * @since JDK 1.6
14 |  * 
15 | */ 16 | @Data 17 | @Builder 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class SceneInfoDTO { 21 | 22 | private AppInfoDTO appInfoDTO; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/SecKillService.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service; 2 | 3 | /** 4 | * Describe: 5 | * 6 | * @Author 王艳军 7 | * @Date 2017/12/20 11:12:40 8 | */ 9 | public interface SecKillService { 10 | 11 | /** 12 | * 查询秒杀活动特价商品的信息 13 | * @param productId 14 | * @return 15 | */ 16 | String querySecKillProductInfo(String productId); 17 | 18 | /** 19 | * 模拟不同用户秒杀同一商品的请求 20 | * @param productId 21 | * @return 22 | */ 23 | void orderProductMockDiffUser(String productId); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/header.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 卖家后台管理系统 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/converter/ProductForm2CartDTOConverter.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.converter; 2 | 3 | import com.imooc.sell.dto.CartDTO; 4 | import com.imooc.sell.form.ProductForm; 5 | 6 | /** 7 | * Created by IntelliJ IDEA 8 | * 9 | * @Author 王艳军 10 | * @Date 2018-01-10 17:20 11 | * @Description 12 | */ 13 | public class ProductForm2CartDTOConverter { 14 | 15 | public static CartDTO convert(ProductForm productForm){ 16 | CartDTO cartDTO = new CartDTO(); 17 | cartDTO.setProductId(productForm.getProductId()); 18 | cartDTO.setProductQuantity(productForm.getProductQuantity()); 19 | return cartDTO; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/builder/ImageBuilder.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.builder; 2 | 3 | import me.chanjar.weixin.mp.api.WxMpService; 4 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 7 | 8 | public class ImageBuilder extends AbstractBuilder { 9 | 10 | @Override 11 | public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service) { 12 | 13 | WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content).fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).build(); 14 | 15 | return m; 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/builder/TextBuilder.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.builder; 2 | 3 | import me.chanjar.weixin.mp.api.WxMpService; 4 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; 7 | 8 | public class TextBuilder extends AbstractBuilder { 9 | 10 | @Override 11 | public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service) { 12 | 13 | WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content).fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).build(); 14 | 15 | return m; 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/PushMessageService.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service; 2 | 3 | import com.imooc.sell.dto.OrderDTO; 4 | 5 | /** 6 | * Describe:模板消息推送 7 | * 8 | * @Author 王艳军 9 | * @Date 2017/12/18 19:16:38 10 | */ 11 | public interface PushMessageService { 12 | 13 | /** 14 | * 推送订单状态变更模板消息 15 | * @param orderDTO 16 | */ 17 | void pushOrderStatus(OrderDTO orderDTO, String first, String remark); 18 | 19 | /** 20 | * 推送下单成功模板消息 21 | * @param orderDTO 22 | */ 23 | void pushOrderSuccess(OrderDTO orderDTO); 24 | 25 | /** 26 | * 推送订单支付成功模板消息 27 | * @param orderDTO 28 | */ 29 | void pushPaySuccess(OrderDTO orderDTO); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/enums/CodeEnum.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:CodeEnum.java.
5 | * Package Name:com.imooc.sell.enums.
6 | * Date:2017年12月11日上午10:19:06.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.enums; 11 | 12 | 13 | /** 14 | * ClassName: CodeEnum.
15 | * Function: ADD FUNCTION.
16 | * Reason: ADD REASON(可选).
17 | * Date: 2017年12月11日 上午10:19:06.
18 | * Desc: ADD DESC(可选).
19 | * @author 王艳军 20 | * @version 21 | * @since JDK 1.6 22 | */ 23 | 24 | public interface CodeEnum { 25 | T getCode(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dataobject/dao/ProductCategoryDao.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ProductCategoryDao.java.
5 | * Package Name:com.imooc.sell.dataobject.dao.
6 | * Date:2017年12月19日下午10:49:22.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.dataobject.dao; 11 | 12 | /** 13 | * ClassName: ProductCategoryDao.
14 | * Function: ADD FUNCTION.
15 | * Reason: ADD REASON(可选).
16 | * Date: 2017年12月19日 下午10:49:22.
17 | * Desc: ADD DESC(可选).
18 | * @author 王艳军 19 | * @version 20 | * @since JDK 1.6 21 | */ 22 | 23 | public class ProductCategoryDao { 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/Demo.java: -------------------------------------------------------------------------------- 1 | /** 2 | *
 3 |  * Project Name: sell
 4 |  * File Name: Demo.java 
 5 |  * Package Name: com.imooc.sell
 6 |  * Create Date: 2018年10月18日 下午2:05:36
 7 |  * Copyright (c) 2018, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved
 8 |  * 
9 | */ 10 | 11 | package com.imooc.sell; 12 | 13 | /** 14 | *
15 |  * @PackageName com.imooc.sell
16 |  * @ClassName Demo
17 |  * @Desc 测试Java代码模板
18 |  * @WebSite https://www.potato369.com
19 |  * @Author 王艳军
20 |  * @Date 2018年10月18日 下午2:05:36
21 |  * @CreateBy Eclipse IDEA Neon.3 Release(4.6.3)
22 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
23 |  * 
24 | */ 25 | 26 | public class Demo { 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/ShellExcutorUtil.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.utils; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | /** 6 | *
 7 |  * @PackageName com.imooc.sell.utils
 8 |  * @ClassName ShellExcutorUtil
 9 |  * @Desc Java执行Shell脚本工具类
10 |  * @WebSite https://www.potato369.com
11 |  * @Author 王艳军
12 |  * @Date 2018/12/04 10:27
13 |  * @CreateBy IntellJ IDEA 2018.2.6
14 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
15 |  * 
16 | */ 17 | @Slf4j 18 | public class ShellExcutorUtil { 19 | 20 | /** 21 | * Java执行shell脚本入口 22 | * @param shellName 脚本文件名 23 | * @throws Exception 24 | */ 25 | public static void service(String shellName) throws Exception { 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dto/AppInfoDTO.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | *
11 |  * @description:app信息
12 |  * @author 王艳军
13 |  * @version  1.0
14 |  * @since JDK 1.6
15 |  * 
16 | */ 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | //@JsonInclude(JsonInclude.Include.NON_NULL) 22 | public class AppInfoDTO { 23 | 24 | @JsonProperty(value = "type") 25 | private String type; 26 | 27 | @JsonProperty(value = "wap_url") 28 | private String wapUrl; 29 | 30 | @JsonProperty(value = "wap_name") 31 | private String wapName; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/NullHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; 4 | import me.chanjar.weixin.mp.api.WxMpService; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * @author Binary Wang(https://github.com/binarywang) 13 | */ 14 | @Component 15 | public class NullHandler extends AbstractHandler { 16 | 17 | @Override 18 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 19 | Map context, WxMpService wxMpService, 20 | WxSessionManager sessionManager) { 21 | return null; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/dto/SceneInfoDTOTest.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.dto; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.junit.Test; 5 | 6 | import com.lly835.bestpay.utils.JsonUtil; 7 | 8 | @Slf4j 9 | public class SceneInfoDTOTest { 10 | 11 | @Test 12 | public void testJson() { 13 | SceneInfoDTO sceneInfoDTO = SceneInfoDTO.builder().build(); 14 | AppInfoDTO appInfoDTO = AppInfoDTO.builder().build(); 15 | appInfoDTO.setType("wap"); 16 | appInfoDTO.setWapName("腾讯充值"); 17 | appInfoDTO.setWapUrl("https://pay.qq.com"); 18 | sceneInfoDTO.setAppInfoDTO(appInfoDTO); 19 | String jsonSceneInfo = JsonUtil.toJson(sceneInfoDTO); 20 | log.info("jsonSceneInfo={}", jsonSceneInfo); 21 | } 22 | 23 | @Test 24 | public void test() { 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/exception/ResponseBankException.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ResponseBankException.java.
5 | * Package Name:com.imooc.sell.exception.
6 | * Date:2017年12月19日下午8:44:52.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.exception; 11 | 12 | 13 | /** 14 | * ClassName: ResponseBankException.
15 | * Function: ADD FUNCTION.
16 | * Reason: 返回给银行的Exception.
17 | * Date: 2017年12月19日 下午8:44:52.
18 | * Desc: ADD DESC(可选).
19 | * @author 王艳军 20 | * @version 21 | * @since JDK 1.6 22 | */ 23 | public class ResponseBankException extends RuntimeException { 24 | 25 | private static final long serialVersionUID = 2423255521637133159L; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/KfSessionHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; 4 | import me.chanjar.weixin.mp.api.WxMpService; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * @author Binary Wang(https://github.com/binarywang) 13 | */ 14 | @Component 15 | public class KfSessionHandler extends AbstractHandler { 16 | 17 | @Override 18 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 19 | Map context, WxMpService wxMpService, 20 | WxSessionManager sessionManager) { 21 | //TODO 对会话做处理 22 | return null; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/VO/BookVO.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.VO; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | *
10 |  * @PackageName com.imooc.sell.VO
11 |  * @ClassName BookVO
12 |  * @Desc 书籍信息列表
13 |  * @WebSite https://www.potato369.com
14 |  * @Author 王艳军
15 |  * @Date 2018/11/14 17:33
16 |  * @CreateBy IntellJ IDEA 2018.2.4
17 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
18 |  * 
19 | */ 20 | @Data 21 | public class BookVO { 22 | @JsonProperty(value = "name") 23 | private String categoryName; 24 | 25 | @JsonProperty(value = "type") 26 | private Integer categoryType; 27 | 28 | @JsonProperty(value = "foods") 29 | private List bookInfoVOInfoVOs; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/impl/SellerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service.impl; 2 | 3 | import com.imooc.sell.dataobject.SellerInfo; 4 | import com.imooc.sell.repository.SellerInfoRepository; 5 | import com.imooc.sell.service.SellerService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @Author 王艳军 11 | * @Date 2017-12-17 13:57 12 | */ 13 | @Service 14 | public class SellerServiceImpl implements SellerService { 15 | 16 | @Autowired 17 | private SellerInfoRepository sellerInfoRepository; 18 | /** 19 | * 根据卖家微信openid查找卖家信息 20 | * 21 | * @param openid 22 | * @return 23 | */ 24 | @Override 25 | public SellerInfo findSellerInfoByOpenid(String openid) { 26 | return sellerInfoRepository.findByOpenid(openid); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/UnsubscribeHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; 4 | import me.chanjar.weixin.mp.api.WxMpService; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * @author Binary Wang(https://github.com/binarywang) 13 | */ 14 | @Component 15 | public class UnsubscribeHandler extends AbstractHandler { 16 | 17 | @Override 18 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, WxMpService wxMpService, WxSessionManager sessionManager) { 19 | String openId = wxMessage.getFromUser(); 20 | this.logger.info("取消关注用户 OPENID: " + openId); 21 | // TODO 可以更新本地数据库为取消关注状态 22 | return null; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/StoreCheckNotifyHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; 4 | import me.chanjar.weixin.mp.api.WxMpService; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * 门店审核事件处理 13 | * 14 | * @author Binary Wang(https://github.com/binarywang) 15 | */ 16 | @Component 17 | public class StoreCheckNotifyHandler extends AbstractHandler { 18 | 19 | @Override 20 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 21 | Map context, WxMpService wxMpService, 22 | WxSessionManager sessionManager) { 23 | // TODO 处理门店审核事件 24 | return null; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/KeyUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:KeyUtil.java 4 | * Package Name:com.imooc.sell.utils 5 | * Date:2017年12月12日上午6:15:50 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | 10 | package com.imooc.sell.utils; 11 | 12 | import java.util.Random; 13 | 14 | /** 15 | * ClassName:KeyUtil
16 | * Function: TODO ADD FUNCTION.
17 | * Reason: TODO ADD REASON.
18 | * Date: 2017年12月12日 上午6:15:50
19 | * @author admin 20 | * @version 21 | * @since JDK 1.6 22 | * @see 23 | */ 24 | public class KeyUtil { 25 | 26 | public static synchronized String genUniquKey(){ 27 | Random random = new Random(); 28 | Integer number = random.nextInt(900000) + 100000; 29 | return System.currentTimeMillis() + String.valueOf(number); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/SellApplication.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.builder.SpringApplicationBuilder; 7 | import org.springframework.boot.web.support.SpringBootServletInitializer; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | 10 | @EnableCaching 11 | @SpringBootApplication 12 | @MapperScan(basePackages = "com.imooc.sell.dataobject.mapper") 13 | public class SellApplication extends SpringBootServletInitializer { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(SellApplication.class, args); 17 | } 18 | 19 | @Override 20 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 21 | return super.configure(builder); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/mapper/ProductCategoryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/EOFExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import com.imooc.sell.exception.ResponseBankException; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.servlet.ModelAndView; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * Describe: 12 | * 13 | * @Author 王艳军 14 | * @Date 2017/12/22 15:08:42 15 | */ 16 | @ControllerAdvice 17 | public class EOFExceptionHandler { 18 | 19 | @ExceptionHandler(value = ResponseBankException.class) 20 | public ModelAndView handlerEOFExceptionHandler() { 21 | Map map = new HashMap(); 22 | map.put("msg", "页面加载出现错误"); 23 | map.put("url", "/sell/seller/product/list"); 24 | return new ModelAndView("common/error:", map); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/repository/OrderDetailRepository.java: -------------------------------------------------------------------------------- 1 | /** 2 | *
 3 |  * Project Name:sell
 4 |  * File Name:OrderDetailRepository.java
 5 |  * Package Name:com.imooc.sell.repository
 6 |  * Date:2017年12月11日下午3:53:36
 7 |  * Copyright (c) 2018 版权所有 (C) 2016-2036  土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved
 8 |  * 
9 | */ 10 | package com.imooc.sell.repository; 11 | 12 | import java.util.List; 13 | import org.springframework.data.jpa.repository.JpaRepository; 14 | import com.imooc.sell.dataobject.OrderDetail; 15 | /** 16 | *
17 |   * @className:OrderDetailRepository
18 |   * @function:
19 |   * @reason:
20 |   * @date:2017年12月11日 下午3:53:36
21 |   * @Desc:
22 |   * @author: 王艳军
23 |   * @version:  
24 |   * @since: JDK 1.6
25 |   * 
26 | */ 27 | public interface OrderDetailRepository extends JpaRepository { 28 | List findByOrderId(String orderId); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/LogHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.imooc.sell.utils.JsonUtils; 8 | 9 | import me.chanjar.weixin.common.session.WxSessionManager; 10 | import me.chanjar.weixin.mp.api.WxMpService; 11 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 12 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 13 | 14 | /** 15 | * @author Binary Wang(https://github.com/binarywang) 16 | */ 17 | @Component 18 | public class LogHandler extends AbstractHandler { 19 | @Override 20 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 21 | Map context, WxMpService wxMpService, 22 | WxSessionManager sessionManager) { 23 | this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage)); 24 | return null; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/repository/OrderMasterRepository.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:OrderMasterRepository.java 4 | * Package Name:com.imooc.sell.repository 5 | * Date:2017年12月11日下午3:48:15 6 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved 7 | */ 8 | package com.imooc.sell.repository; 9 | 10 | import org.springframework.data.domain.Page; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.data.jpa.repository.JpaRepository; 13 | import com.imooc.sell.dataobject.OrderMaster; 14 | /** 15 | *
16 |  * @className:OrderMasterRepository
17 |  * @function:
18 |  * @reason:
19 |  * @date:2017年12月11日 下午3:48:15 
20 |  * @Desc:
21 |  * @author: 王艳军
22 |  * @version:
23 |  * @since: JDK 1.6
24 |  * 
25 | */ 26 | public interface OrderMasterRepository extends JpaRepository { 27 | Page findByBuyerOpenid(String buyerOpenid, Pageable pageable); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/EnumUtil.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:EnumUtil.java.
5 | * Package Name:com.imooc.sell.utils.
6 | * Date:2017年12月11日上午10:41:50.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.utils; 11 | 12 | import com.imooc.sell.enums.CodeEnum; 13 | 14 | /** 15 | * ClassName: EnumUtil.
16 | * Function: ADD FUNCTION.
17 | * Reason: ADD REASON(可选).
18 | * Date: 2017年12月11日 上午10:41:50.
19 | * Desc: ADD DESC(可选).
20 | * @author 王艳军 21 | * @version 22 | * @since JDK 1.6 23 | */ 24 | public class EnumUtil { 25 | 26 | public static > T getByCode(Integer code, Class enumClass) { 27 | for (T each: enumClass.getEnumConstants()) { 28 | if (code.equals(each.getCode())) { 29 | return each; 30 | } 31 | } 32 | return null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/builder/NewsBuilder.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.builder; 2 | 3 | import me.chanjar.weixin.mp.api.WxMpService; 4 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage; 7 | 8 | /** 9 | *
10 |  * @PackageName com.imooc.sell.builder
11 |  * @ClassName NewsBuilder
12 |  * @Desc 图文消息Builder
13 |  * @WebSite https://www.potato369.com
14 |  * @Author 王艳军
15 |  * @Date 2018/11/29 17:49
16 |  * @CreateBy IntellJ IDEA 2018.2.6
17 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
18 |  * 
19 | */ 20 | public class NewsBuilder extends AbstractBuilder { 21 | 22 | @Override 23 | public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service) { 24 | 25 | WxMpXmlOutNewsMessage m = WxMpXmlOutMessage.NEWS().build(); 26 | 27 | return m; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 7 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 8 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 9 | import org.springframework.web.socket.server.standard.ServerEndpointExporter; 10 | 11 | /** 12 | * Describe:Websocket配置 13 | * 14 | * @Author 王艳军 15 | * @Date 2017/12/19 11:33:14 16 | */ 17 | @Component 18 | @Configuration 19 | @EnableWebSocket 20 | public class WebSocketConfig implements WebSocketConfigurer { 21 | 22 | @Bean 23 | public ServerEndpointExporter serverEndpointExporter() { 24 | return new ServerEndpointExporter(); 25 | } 26 | 27 | @Override 28 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/enums/OrderStatusEnum.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderStatusEnum.java.
5 | * Package Name:com.imooc.sell.enums.
6 | * Date:2017年12月11日下午3:21:06.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.enums; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Getter; 14 | import lombok.NoArgsConstructor; 15 | 16 | /** 17 | * ClassName: OrderStatusEnum.
18 | * Function: ADD FUNCTION.
19 | * Reason: ADD REASON(可选).
20 | * Date: 2017年12月11日 下午3:21:06.
21 | * Desc: ADD DESC(可选).
22 | * @author 王艳军 23 | * @version 24 | * @since JDK 1.6 25 | */ 26 | @Getter 27 | @NoArgsConstructor 28 | @AllArgsConstructor 29 | public enum OrderStatusEnum implements CodeEnum{ 30 | 31 | NEW(0,"新下单"), 32 | FINISHED(1,"已完结"), 33 | CANCEL(2,"已取消"); 34 | 35 | private Integer code; 36 | 37 | private String message; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/enums/ProductStatusEnum.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ProductStatusEnum.java.
5 | * Package Name:com.imooc.sell.enums.
6 | * Date:2017年12月11日上午10:18:19.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.enums; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Getter; 14 | import lombok.NoArgsConstructor; 15 | 16 | /** 17 | * ClassName: ProductStatusEnum.
18 | * Function: ADD FUNCTION.
19 | * Reason: ADD REASON(可选).
20 | * Date: 2017年12月11日 上午10:18:19.
21 | * Desc: ADD DESC(可选).
22 | * 23 | * @author 王艳军 24 | * @version 1.0 25 | * @since JDK 1.6 26 | */ 27 | @Getter 28 | @NoArgsConstructor 29 | @AllArgsConstructor 30 | public enum ProductStatusEnum implements CodeEnum { 31 | 32 | UP(0, "在架"), 33 | 34 | DOWN(1, "下架"), 35 | 36 | ; 37 | 38 | private Integer code; 39 | 40 | private String message; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/enums/PayStatusEnum.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:PayStatusEnum.java.
5 | * Package Name:com.imooc.sell.enums.
6 | * Date:2017年12月11日下午3:29:29.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.enums; 11 | 12 | 13 | import lombok.AllArgsConstructor; 14 | import lombok.Getter; 15 | import lombok.NoArgsConstructor; 16 | 17 | /** 18 | * ClassName: PayStatusEnum.
19 | * Function: ADD FUNCTION.
20 | * Reason: ADD REASON(可选).
21 | * Date: 2017年12月11日 下午3:29:29.
22 | * Desc: ADD DESC(可选).
23 | * @author 王艳军 24 | * @version 25 | * @since JDK 1.6 26 | */ 27 | @Getter 28 | @NoArgsConstructor 29 | @AllArgsConstructor 30 | public enum PayStatusEnum implements CodeEnum{ 31 | 32 | WAITING(0, "等待支付"), 33 | 34 | SUCCESS(1, "支付成功"), 35 | 36 | ; 37 | 38 | private Integer code; 39 | 40 | private String message; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/MathUtil.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:MathUtil.java.
5 | * Package Name:com.imooc.sell.utils.
6 | * Date:2017年12月14日下午6:10:32.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.utils; 11 | 12 | 13 | /** 14 | *
15 |  * ClassName:MathUtil
16 |  * Function:数字比较工具类
17 |  * Reason:
18 |  * Date:2017年12月14日 下午6:10:32
19 |  * Desc:
20 |  * @author 王艳军
21 |  * @version  
22 |  * @since JDK 1.6
23 |  * 
24 | */ 25 | 26 | public class MathUtil { 27 | 28 | private static final Double MONEY_RANG = 0.01; 29 | /** 30 | * 比较两个金额是否相等 31 | * @param double1 金额1 32 | * @param double2 金额2 33 | * @return Boolean 34 | */ 35 | public static Boolean equals(Double double1, Double double2){ 36 | Double result = Math.abs(double1 - double2); 37 | if (result < MONEY_RANG) { 38 | return true; 39 | } else { 40 | return false; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/controller/AliF2FPayController.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.servlet.ModelAndView; 6 | 7 | /** 8 | *
 9 |  * @PackageName com.imooc.sell.controller
10 |  * @ClassName AliF2FPayController
11 |  * @Desc 支付宝当面付Controller
12 |  * @WebSite https://www.potato369.com
13 |  * @Author 王艳军
14 |  * @Date 2018/10/10 16:23
15 |  * @CreateBy IntellJ IDEA 2018.2.4
16 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
17 |  * 
18 | */ 19 | @Controller 20 | @RequestMapping(value = "/pay/alif2f") 21 | public class AliF2FPayController { 22 | 23 | @RequestMapping(value = "/index") 24 | public ModelAndView index() { 25 | return new ModelAndView("pay/alipay/f2fpay/index"); 26 | } 27 | 28 | @RequestMapping("/f2fpay") 29 | public ModelAndView f2fpay() { 30 | return new ModelAndView("pay/alipay/f2fpay/pay"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/repository/ProductCategoryRepository.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:ProductCategoryRepository.java 4 | * Package Name:com.imooc.sell.repository 5 | * Date:2017年12月8日上午12:23:22 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | package com.imooc.sell.repository; 10 | 11 | import java.util.List; 12 | import org.springframework.data.jpa.repository.JpaRepository; 13 | import com.imooc.sell.dataobject.ProductCategory; 14 | 15 | /** 16 | * ClassName:ProductCategoryRepository
17 | * Function: TODO ADD FUNCTION.
18 | * Reason: TODO ADD REASON.
19 | * Date: 2017年12月8日 上午12:23:22
20 | * 21 | * @author admin 22 | * @version 23 | * @since JDK 1.6 24 | * @see 25 | */ 26 | public interface ProductCategoryRepository extends JpaRepository { 27 | /** 28 | * 通过类目type列表查询商品类目列表 29 | * 30 | * @param categoryTypeList 31 | * @return List 32 | */ 33 | List findByCategoryTypeIn(List categoryTypeList); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/BuyerService.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:BuyerService.java.
5 | * Package Name:com.imooc.sell.service.
6 | * Date:2017年12月12日下午10:36:19.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.service; 11 | 12 | import com.imooc.sell.dto.OrderDTO; 13 | 14 | /** 15 | * ClassName: BuyerService.
16 | * Function: ADD FUNCTION.
17 | * Reason: ADD REASON(可选).
18 | * Date: 2017年12月12日 下午10:36:19.
19 | * Desc: ADD DESC(可选).
20 | * @author 王艳军 21 | * @version 22 | * @since JDK 1.6 23 | */ 24 | public interface BuyerService { 25 | 26 | /** 27 | * 根据买家微信openid查询一个订单 28 | * @param openid 29 | * @param orderid 30 | * @return 31 | */ 32 | OrderDTO findOrderOne(String openid,String orderid); 33 | 34 | /** 35 | * 根据买家微信openid取消订单 36 | * @param openid 37 | * @param orderid 38 | * @return 39 | */ 40 | OrderDTO cancelOrder(String openid,String orderid); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/error.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 |
5 | <#--边栏 sidebar--> 6 | <#include "../common/nav.ftl"> 7 | <#--主体内容区域 content--> 8 |
9 |
10 |
11 |
12 |
13 | 14 |

15 | 错误! 16 |

${msg}3s后自动跳转 17 |
18 |
19 |
20 |
21 | 24 |
25 |
26 | 27 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/converter/OrderMaster2OrderDTOConverter.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.converter; 2 | 3 | import com.imooc.sell.dataobject.OrderMaster; 4 | import com.imooc.sell.dto.OrderDTO; 5 | import org.springframework.beans.BeanUtils; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | /** 11 | * describe: 12 | * 13 | * @author 王艳军 14 | * @date 2017/12/12 14:36:55 15 | */ 16 | public class OrderMaster2OrderDTOConverter { 17 | /** 18 | * 将oderMaster对象转换为OrderDTO对象 19 | * @param orderMaster 20 | * @return OrderDTO对象 21 | */ 22 | public static OrderDTO convert(OrderMaster orderMaster){ 23 | OrderDTO orderDTO = new OrderDTO(); 24 | BeanUtils.copyProperties(orderMaster,orderDTO); 25 | return orderDTO; 26 | } 27 | 28 | /** 29 | * 将List对象转换为List对象 30 | * @param orderMasterList 31 | * @return List 32 | */ 33 | public static List convert(List orderMasterList){ 34 | return orderMasterList.stream().map(master -> convert(master)).collect(Collectors.toList()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dto/CartDTO.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:CartDTO.java.
5 | * Package Name:com.imooc.sell.dto.
6 | * Date:2017年12月11日上午10:25:35.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.dto; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | 17 | import java.io.Serializable; 18 | 19 | /** 20 | *
21 |  * ClassName:CartDTO
22 |  * Function:ADD FUNCTION
23 |  * Reason:购物车
24 |  * Date:2017年12月11日 上午10:25:35
25 |  * Desc:ADD DESC(可选)
26 |  * @author 王艳军
27 |  * @version  1.0
28 |  * @since JDK 1.6
29 |  * 
30 | */ 31 | @Data 32 | @Builder 33 | @NoArgsConstructor 34 | @AllArgsConstructor 35 | public class CartDTO implements Serializable{ 36 | 37 | /**serialVersionUID:序列号*/ 38 | private static final long serialVersionUID = 8300837976789349474L; 39 | 40 | /** productId:商品Id. */ 41 | private String productId; 42 | 43 | /** productQuantity:商品数量. */ 44 | private Integer productQuantity; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/VO/ProductVO.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ProductVO.java.
5 | * Package Name:com.imooc.sell.VO.
6 | * Date:2017年12月11日上午11:32:49.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.VO; 11 | 12 | import java.io.Serializable; 13 | import java.util.List; 14 | 15 | import com.fasterxml.jackson.annotation.JsonProperty; 16 | 17 | import lombok.Data; 18 | 19 | /** 20 | *
21 |  * @ClassName:ProductVO
22 |  * @Function:ADD FUNCTION
23 |  * @Reason:商品类目
24 |  * @Date:2017年12月11日 上午11:32:49
25 |  * @Desc:ADD DESC(可选)
26 |  * @Author 王艳军 
27 |  * @Version 1.0 
28 |  * @Since JDK 1.6
29 |  * 
30 | */ 31 | @Data 32 | public class ProductVO implements Serializable { 33 | 34 | private static final long serialVersionUID = -1619866944061488544L; 35 | 36 | @JsonProperty(value = "name") 37 | private String categoryName; 38 | 39 | @JsonProperty(value = "type") 40 | private Integer categoryType; 41 | 42 | @JsonProperty(value = "foods") 43 | private List productInfoVOs; 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/VO/ResultVO.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ResultVO.java.
5 | * Package Name:com.imooc.sell.VO.
6 | * Date:2017年12月11日上午11:25:48.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.VO; 11 | 12 | //import com.fasterxml.jackson.annotation.JsonInclude; 13 | 14 | import lombok.Data; 15 | 16 | import java.io.Serializable; 17 | 18 | /** 19 | *
20 |  * @ClassName:ResultVO
21 |  * @Function:ADD FUNCTION
22 |  * @Reason:Http请求返回的最外层对象
23 |  * @Date:2017年12月11日 上午11:25:48
24 |  * @Desc:ADD DESC(可选)
25 |  * @Author 王艳军
26 |  * @Version
27 |  * @Since JDK 1.6
28 |  * 
29 |  */
30 | @Data
31 | //@JsonInclude(JsonInclude.Include.NON_NULL)
32 | public class ResultVO implements Serializable{
33 | 
34 |   private static final long serialVersionUID = 8848731630266574133L;
35 | 
36 |   /**
37 |    * code:返回的错误码
38 |    */
39 |   private Integer code;
40 |   
41 |   /**
42 |    * msg:返回的提示信息
43 |    */
44 |   private String msg;
45 |   
46 |   /**
47 |    * data:返回的具体内容
48 |    */
49 |   private T data;
50 | }
51 | 


--------------------------------------------------------------------------------
/src/main/java/com/imooc/sell/service/PayService.java:
--------------------------------------------------------------------------------
 1 | 
 2 | /**
 3 |  * Project Name:sell.
4 | * File Name:PayService.java.
5 | * Package Name:com.imooc.sell.service.
6 | * Date:2017年12月13日下午9:29:35.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.service; 11 | 12 | import com.imooc.sell.dto.OrderDTO; 13 | import com.lly835.bestpay.model.PayResponse; 14 | import com.lly835.bestpay.model.RefundResponse; 15 | 16 | /** 17 | * ClassName: PayService 18 | * Function: ADD FUNCTION 19 | * Reason: 支付订单
20 | * Date: 2017年12月13日 下午9:29:35 21 | * Desc: ADD DESC(可选) 22 | * @author 王艳军 23 | * @version 24 | * @since JDK 1.6 25 | */ 26 | public interface PayService { 27 | 28 | /** 29 | * 微信公众号支付订单 30 | * @param orderDTO 31 | * @return 32 | */ 33 | PayResponse create(OrderDTO orderDTO); 34 | 35 | /** 36 | * 微信公众号支付异步通知结果 37 | * @param notifyData 38 | */ 39 | PayResponse notify(String notifyData); 40 | 41 | /** 42 | * 微信公众号支付退款 43 | * @param orderDTO 44 | */ 45 | RefundResponse refund(OrderDTO orderDTO); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/VO/BookStoreResultVO.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.VO; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | *
10 |  * @PackageName com.imooc.sell.VO
11 |  * @ClassName BookStoreResultVO
12 |  * @Desc 返回书城书籍数据结果
13 |  * @WebSite https://www.potato369.com
14 |  * @Author 王艳军
15 |  * @Date 2018/11/14 17:00
16 |  * @CreateBy IntellJ IDEA 2018.2.4
17 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
18 |  * 
19 | */ 20 | @Data 21 | public class BookStoreResultVO implements Serializable { 22 | 23 | /** 24 | * errorCode:返回的错误码信息 25 | */ 26 | @JsonProperty(value = "error_code") 27 | private Integer errorCode; 28 | 29 | /** 30 | * message:返回的提示信息 31 | */ 32 | @JsonProperty(value = "msg") 33 | private String message; 34 | 35 | /** 36 | * data:返回的具体数据信息 37 | */ 38 | @JsonProperty(value = "data") 39 | private T data; 40 | 41 | /** 42 | * total:返回的数据总条数 43 | */ 44 | @JsonProperty(value = "total") 45 | private Long total; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/form/CategoryForm.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.form; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import java.util.Date; 8 | /** 9 | *
10 |  * @Description 卖家商品类目表单From
11 |  * @Author 王艳军
12 |  * @Date 2017-12-17 10:41
13 |  * 
14 | */ 15 | @Data 16 | @Builder 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | public class CategoryForm { 20 | 21 | /** 22 | *
23 |    * categoryId:类目id
24 |    * 
25 | */ 26 | private Integer categoryId; 27 | 28 | /** 29 | *
30 |    * categoryName:类目名称
31 |    * 
32 | */ 33 | private String categoryName; 34 | 35 | /** 36 | *
37 |    * categoryType:类目编号
38 |    * 
39 | */ 40 | private Integer categoryType; 41 | 42 | /** 43 | *
44 |    * isDeleted:此类目是否标记已删除,默认否
45 |    * 
46 | */ 47 | private Integer isDeleted; 48 | 49 | /** 50 | *
51 |    * createTime:创建时间
52 |    * 
53 | */ 54 | private Date createTime; 55 | 56 | /** 57 | *
58 |    * updateTime:修改时间
59 |    * 
60 | */ 61 | private Date updateTime; 62 | } 63 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/success.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 |
5 | <#--边栏 sidebar--> 6 | <#include "../common/nav.ftl"> 7 | <#--主体内容区域 content--> 8 |
9 |
10 |
11 |
12 |
13 | 14 |

15 | 成功! 16 |

${msg}3s后自动跳转 17 |
18 |
19 |
20 |
21 | 24 |
25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/service/impl/SellerServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service.impl; 2 | 3 | import com.imooc.sell.SellApplication; 4 | import com.imooc.sell.dataobject.SellerInfo; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.annotation.Rollback; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import static org.junit.Assert.*; 14 | @Rollback 15 | @Transactional 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 18 | public class SellerServiceImplTest { 19 | 20 | @Autowired 21 | private SellerServiceImpl sellerService; 22 | 23 | public static final String SELLER_OPENID = "oSkiNv4fBXYxidv0wU_U0UDHNP4M"; 24 | 25 | @Test 26 | public void findSellerInfoByOpenidTest() { 27 | SellerInfo result = sellerService.findSellerInfoByOpenid(SELLER_OPENID); 28 | assertEquals(SELLER_OPENID, result.getOpenid()); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/exception/SellException.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:SellException.java.
5 | * Package Name:com.imooc.sell.exception.
6 | * Date:2017年12月11日上午10:33:22.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.exception; 11 | 12 | import com.imooc.sell.enums.ResultEnum; 13 | 14 | import lombok.Getter; 15 | 16 | /** 17 | * ClassName: SellException.
18 | * Function: ADD FUNCTION.
19 | * Reason: ADD REASON(可选).
20 | * Date: 2017年12月11日 上午10:33:22.
21 | * Desc: ADD DESC(可选).
22 | * @author 王艳军 23 | * @version 24 | * @since JDK 1.6 25 | */ 26 | @Getter 27 | public class SellException extends RuntimeException{ 28 | 29 | private static final long serialVersionUID = -3170669599060979531L; 30 | 31 | private Integer code; 32 | 33 | public SellException(ResultEnum resultEnum) { 34 | super(resultEnum.getMessage()); 35 | this.code = resultEnum.getCode(); 36 | } 37 | 38 | public SellException(Integer code, String message) { 39 | super(message); 40 | this.code = code; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/LoggerTest.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.test.context.junit4.SpringRunner; 8 | 9 | /** 10 | *
11 |  * @PackageName com.imooc.sell
12 |  * @ClassName LoggerTest
13 |  * @Desc 测试日志输出框架slog4j和logback
14 |  * @WebSite https://www.potato369.com
15 |  * @Author 王艳军
16 |  * @Date 2018/10/10 11:05
17 |  * @CreateBy IntellJ IDEA 2018.2.4
18 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
19 |  * 
20 | */ 21 | @Slf4j 22 | @RunWith(SpringRunner.class) 23 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 24 | public class LoggerTest { 25 | 26 | @Test 27 | public void test() { 28 | log.debug("debug......"); 29 | log.info("info......"); 30 | log.error("error......"); 31 | String name = "imooc", password ="123456"; 32 | log.info("name = {}, password = {}", name, password); 33 | log.info("name: {}, password: {}", name, password); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/OrderDetailService.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderDetailService.java.
5 | * Package Name:com.imooc.sell.service.impl.
6 | * Date:2017年12月18日下午9:01:22.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.service; 11 | 12 | import java.util.List; 13 | 14 | import com.imooc.sell.dataobject.OrderDetail; 15 | import com.imooc.sell.dataobject.ProductInfo; 16 | 17 | /** 18 | * 订单详情service 19 | * ClassName: OrderDetailService.
20 | * Function: ADD FUNCTION.
21 | * Reason: ADD REASON(可选).
22 | * Date: 2017年12月18日 下午9:01:22.
23 | * Desc: ADD DESC(可选).
24 | * @author 王艳军 25 | * @version 26 | * @since JDK 1.6 27 | */ 28 | 29 | public interface OrderDetailService { 30 | 31 | /** 32 | * 根据订单id查询订单详情列表信息 33 | * @param orderId 34 | * @return 35 | */ 36 | List findOrderDetailByOrderId(String orderId); 37 | 38 | /** 39 | * 根据订单id查询订购的商品信息 40 | * @param orderId 41 | * @return 42 | */ 43 | List findProductInfoByOrderId(String orderId); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/form/BookCategoryForm.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.form; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | *
10 |  * @PackageName com.imooc.sell.form
11 |  * @ClassName BookCategoryForm
12 |  * @Desc 书籍类目数据Form
13 |  * @WebSite https://www.potato369.com
14 |  * @Author 王艳军
15 |  * @Date 2018/11/14 19:12
16 |  * @CreateBy IntellJ IDEA 2018.2.4
17 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
18 |  * 
19 | */ 20 | @Data 21 | @Builder 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | public class BookCategoryForm { 25 | 26 | /** 27 | * categoryId:类目id,主键 28 | */ 29 | private Integer categoryId; 30 | 31 | /** 32 | * parentCategoryId:父级类目id 33 | */ 34 | private Integer parentCategoryId; 35 | 36 | /** 37 | * categoryName:类目名称 38 | */ 39 | private String categoryName; 40 | 41 | /** 42 | * categoryType:类目编号 43 | */ 44 | private Integer categoryType; 45 | 46 | /** 47 | * isDeleted:类目是否删除,0-否;1-是,“默认:0-否” 48 | */ 49 | private Integer isDeleted; 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/BookStoreResultVOUtils.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.utils; 2 | 3 | import com.imooc.sell.VO.BookStoreResultVO; 4 | import com.imooc.sell.VO.ResultVO; 5 | 6 | /** 7 | *
 8 |  * @PackageName com.imooc.sell.utils
 9 |  * @ClassName BookStoreResultVOUtils
10 |  * @Desc 返回结果数据工具类
11 |  * @WebSite https://www.potato369.com
12 |  * @Author 王艳军
13 |  * @Date 2018/11/14 17:08
14 |  * @CreateBy IntellJ IDEA 2018.2.4
15 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
16 |  * 
17 | */ 18 | public class BookStoreResultVOUtils { 19 | public static BookStoreResultVO success(Object object){ 20 | BookStoreResultVO resultVO = new BookStoreResultVO(); 21 | resultVO.setErrorCode(0); 22 | resultVO.setMessage("获取成功"); 23 | resultVO.setData(object); 24 | return resultVO; 25 | } 26 | 27 | public static BookStoreResultVO success(){ 28 | return success(null); 29 | } 30 | 31 | public static BookStoreResultVO error(Integer code, String msg){ 32 | BookStoreResultVO resultVO = new BookStoreResultVO(); 33 | resultVO.setErrorCode(code); 34 | resultVO.setMessage(msg); 35 | return resultVO; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/MenuHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import me.chanjar.weixin.common.session.WxSessionManager; 4 | import me.chanjar.weixin.mp.api.WxMpService; 5 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 6 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Map; 10 | 11 | import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; 12 | 13 | /** 14 | * @author Binary Wang(https://github.com/binarywang) 15 | */ 16 | @Component 17 | public class MenuHandler extends AbstractHandler { 18 | 19 | @Override 20 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 21 | Map context, WxMpService weixinService, 22 | WxSessionManager sessionManager) { 23 | 24 | String msg = String.format("type:%s, event:%s, key:%s", 25 | wxMessage.getMsgType(), wxMessage.getEvent(), 26 | wxMessage.getEventKey()); 27 | if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) { 28 | return null; 29 | } 30 | 31 | return WxMpXmlOutMessage.TEXT().content(msg) 32 | .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) 33 | .build(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/ResultVOUtil.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ResultVOUtil.java.
5 | * Package Name:com.imooc.sell.utils.
6 | * Date:2017年12月11日下午2:25:03.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.utils; 11 | 12 | import com.imooc.sell.VO.ResultVO; 13 | 14 | /** 15 | * ClassName: ResultVOUtil.
16 | * Function: ADD FUNCTION.
17 | * Reason: ADD REASON(可选).
18 | * Date: 2017年12月11日 下午2:25:03.
19 | * Desc: ADD DESC(可选).
20 | * @author 王艳军 21 | * @version 22 | * @since JDK 1.6 23 | */ 24 | 25 | public class ResultVOUtil{ 26 | 27 | public static ResultVO success(Object object){ 28 | ResultVO resultVO = new ResultVO(); 29 | resultVO.setCode(0); 30 | resultVO.setMsg("成功"); 31 | resultVO.setData(object); 32 | return resultVO; 33 | } 34 | 35 | public static ResultVO success(){ 36 | return success(null); 37 | } 38 | 39 | public static ResultVO error(Integer code, String msg){ 40 | ResultVO resultVO = new ResultVO(); 41 | resultVO.setCode(code); 42 | resultVO.setMsg(msg); 43 | return resultVO; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # 微信开放平台的开发使用 2 | > 本文档仅针对问我借用账号的情况, 如果自己有开放账号, 可直接按照慕课网视频或者微信文档开发 3 | 1、 准备好openid和网址, openid是之前邮件发给我的那个,网址的host保证与之前发的一样, 比如之前发给我的网址是`http://abc.natapp.cc`, 那么这次使用的网址必须是`http://abc.natapp.cc`开头 4 | 2. 电脑浏览器下面的链接, 注意替换openid和你的网址(需要urlEncode) 5 | 6 | ``` 7 | https://open.weixin.qq.com/connect/qrconnect?appid=wx6ad144e54af67d87&redirect_uri=http%3A%2F%2Fsell.springboot.cn%2Fsell%2Fqr%2F{OPENID}&response_type=code&scope=snsapi_login&state={你的网址} 8 | ``` 9 | 3、 最后会重定向到`你的网址?code=xxxxxxxxxxx` 10 | 4、例子 11 | 12 | openid是oTgZpweNnfivA9ER9EIXoHAjlrWQ 13 | 之前邮件发送的网址是http://coding.imooc.com 14 | 这次使用的网址是http://coding.imooc.com/class/117.html 15 | 那么访问的地址为 16 | 17 | ``` 18 | https://open.weixin.qq.com/connect/qrconnect?appid=wx6ad144e54af67d87&redirect_uri=http%3A%2F%2Fsell.springboot.cn%2Fsell%2Fqr%2FoTgZpweNnfivA9ER9EIXoHAjlrWQ&response_type=code&scope=snsapi_login&state=http%3A%2F%2Fcoding.imooc.com%2Fclass%2F117.html 19 | ``` 20 | 21 | 最后会重定向到 22 | 23 | ``` 24 | http://coding.imooc.com/class/117.html?code=001bitQu0uteYd13BsQu0TetQu0bitQ 25 | ``` 26 | 拿到code之后即可获取扫码者的openid了, 还不清楚? 请观看慕课网《Spring Boot企业微信点餐系统》第12章卖家扫码登录部分 27 | 5、 问:扫码之后, pc端不会跳转是什么原因? 28 | 答:{你的网址}不能访问 29 | 30 | 6、有兴趣的童鞋可以共同参与开发,可以添加我的微信号:wx406151651,QQ:406151651共同参与开发讨论。谢谢合作!!! 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/JsonUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | *
 3 |  * Project Name: sell
 4 |  * File Name: JsonUtils.java 
 5 |  * Package Name: com.imooc.sell.utils
 6 |  * Create Date: 2018年11月29日 下午12:12:50
 7 |  * Copyright (c) 2018, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved
 8 |  * 
9 | */ 10 | package com.imooc.sell.utils; 11 | 12 | import com.google.gson.Gson; 13 | import com.google.gson.GsonBuilder; 14 | 15 | import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; 16 | 17 | /** 18 | *
19 |  * @PackageName com.imooc.sell.utils
20 |  * @ClassName JsonUtils
21 |  * @Desc Json字符串或者对象处理工具类
22 |  * @WebSite https://www.potato369.com
23 |  * @Author 王艳军
24 |  * @Date 2018年11月29日 下午12:12:50
25 |  * @CreateBy Eclipse IDEA Neon.3 Release(4.6.3)
26 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
27 |  * 
28 | */ 29 | public class JsonUtils { 30 | public static String toJson(Object obj) { 31 | return WxMpGsonBuilder.create().toJson(obj); 32 | } 33 | 34 | public static String toJsonStr(Object object) { 35 | GsonBuilder gsonBuilder = new GsonBuilder(); 36 | gsonBuilder.setPrettyPrinting(); 37 | Gson gson = gsonBuilder.create(); 38 | return gson.toJson(object); 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/main/resources/static/pay.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/config/WechatOpenConfig.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.config; 2 | 3 | import me.chanjar.weixin.mp.api.WxMpConfigStorage; 4 | import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; 5 | import me.chanjar.weixin.mp.api.WxMpService; 6 | import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import com.imooc.sell.config.prop.WechatMpProperties; 11 | 12 | /** 13 | * @Author 王艳军 14 | * @Date 2017-12-17 14:38 15 | */ 16 | public class WechatOpenConfig { 17 | 18 | @Autowired 19 | private WechatMpProperties wechatMpConfig; 20 | 21 | @Bean 22 | public WxMpService wxOpenService(){ 23 | WxMpService wxOpenService = new WxMpServiceImpl(); 24 | wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage()); 25 | return wxOpenService; 26 | } 27 | 28 | @Bean 29 | private WxMpConfigStorage wxOpenConfigStorage(){ 30 | WxMpInMemoryConfigStorage wxOpenInMemoryConfigStorage = new WxMpInMemoryConfigStorage(); 31 | wxOpenInMemoryConfigStorage.setAppId(wechatMpConfig.getOpenAppid()); 32 | wxOpenInMemoryConfigStorage.setSecret(wechatMpConfig.getOpenAppSecret()); 33 | return wxOpenInMemoryConfigStorage; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/enums/BookStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | *
 9 |  * @PackageName com.imooc.sell.enums
10 |  * @EnumName BookStatusEnum
11 |  * @Desc 书籍状态枚举
12 |  * @WebSite https://www.potato369.com
13 |  * @Author 王艳军
14 |  * @Date 2018/11/14 18:29
15 |  * @CreateBy IntellJ IDEA 2018.2.4
16 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
17 |  * 
18 | */ 19 | @Getter 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public enum BookStatusEnum implements CodeEnum { 23 | 24 | 25 | 26 | NOT_SELECTED(0, false, "否"), 27 | 28 | SELECTED(1, true, "是"), 29 | 30 | NOT_PRIVATED(0, false, "否"), 31 | 32 | PRIVATED(1, true, "是"), 33 | 34 | NOT_CACHE(0, false, "否"), 35 | 36 | CACHE(1, true, "是"), 37 | 38 | NOT_DELETE(0, false, "否"), 39 | 40 | DELETE(1, true, "是"), 41 | 42 | LANG_CN(86, true, "cn"), 43 | 44 | LANG_EN(44, true, "en"), 45 | 46 | NO_READ(0, false, "否"), 47 | 48 | HAVE_READ(1, true, "是"), 49 | 50 | ; 51 | 52 | private Integer code; 53 | 54 | private Boolean status; 55 | 56 | private String message; 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/UUIDUtil.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:UUIDUtil.java.
5 | * Package Name:com.imooc.sell.utils.
6 | * Date:2017年12月11日上午10:54:51.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.utils; 11 | 12 | import java.util.UUID; 13 | 14 | /** 15 | * ClassName: UUIDUtil.
16 | * Function: ADD FUNCTION.
17 | * Reason: ADD REASON(可选).
18 | * Date: 2017年12月11日 上午10:54:51.
19 | * Desc: ADD DESC(可选).
20 | * @author 王艳军 21 | * @version 22 | * @since JDK 1.6 23 | */ 24 | 25 | public class UUIDUtil { 26 | 27 | /** 28 | * 创建订单号,订单详情 29 | * @return 30 | */ 31 | public static synchronized String genTimstampUUID(){ 32 | return DateUtil.getTimestamp().concat(UUID.randomUUID().toString().replaceAll("-", "").substring(0, 15).toLowerCase()); 33 | } 34 | 35 | /** 36 | * 创建产品id,商品id 37 | * @return 38 | */ 39 | public static synchronized String gen32UUID(){ 40 | return UUID.randomUUID().toString().replaceAll("-", "").toLowerCase(); 41 | } 42 | 43 | public static void main(String[] args) { 44 | System.out.println(UUIDUtil.genTimstampUUID()); 45 | System.out.println(UUIDUtil.gen32UUID()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/VO/ProductInfoVO.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ProductInfoVO.java.
5 | * Package Name:com.imooc.sell.VO.
6 | * Date:2017年12月11日上午11:35:38.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.VO; 11 | 12 | import java.io.Serializable; 13 | import java.math.BigDecimal; 14 | 15 | import com.fasterxml.jackson.annotation.JsonProperty; 16 | 17 | import lombok.Data; 18 | 19 | /** 20 | *
21 |  * @ClassName:ProductInfoVO
22 |  * @Function:ADD FUNCTION
23 |  * @Reason:商品类目详情
24 |  * @Date:2017年12月11日 上午11:35:38 
25 |  * @Desc:ADD DESC(可选)
26 |  * @Author 王艳军
27 |  * @Version 1.0
28 |  * @Since JDK 1.6
29 |  * 
30 | */ 31 | @Data 32 | public class ProductInfoVO implements Serializable { 33 | 34 | private static final long serialVersionUID = 1192721805912686397L; 35 | 36 | @JsonProperty(value = "id") 37 | private String productId; 38 | 39 | @JsonProperty(value = "name") 40 | private String productName; 41 | 42 | @JsonProperty(value = "price") 43 | private BigDecimal productPrice; 44 | 45 | @JsonProperty(value = "description") 46 | private String productDescription; 47 | 48 | @JsonProperty(value = "icon") 49 | private String productIcon; 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/repository/ProductInfoRepository.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:ProductInfoRepository.java 4 | * Package Name:com.imooc.sell.repository 5 | * Date:2017年12月8日下午11:52:26 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | package com.imooc.sell.repository; 10 | 11 | import java.util.List; 12 | import org.springframework.data.jpa.repository.JpaRepository; 13 | import com.imooc.sell.dataobject.ProductInfo; 14 | /** 15 | * ClassName:ProductInfoRepository
16 | * Function: TODO ADD FUNCTION.
17 | * Reason: TODO ADD REASON.
18 | * Date: 2017年12月8日 下午11:52:26
19 | * 20 | * @author admin 21 | * @version 22 | * @since JDK 1.6 23 | * @see 24 | */ 25 | public interface ProductInfoRepository extends JpaRepository { 26 | 27 | /** 28 | * 29 | * findByProductStatus:(根据productStatus商品状态查询所有的商品信息).
30 | * 31 | * @author admin 32 | * @param productStatus 33 | * @return 34 | * @since JDK 1.6 35 | */ 36 | List findByProductStatus(Integer productStatus); 37 | 38 | /** 39 | * findByCategoryType:(根据categoryType类目Type查询商品信息) 40 | * 41 | * @param categoryType 42 | * @return 43 | */ 44 | List findByCategoryType(Integer categoryType); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/service/impl/PayServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service.impl; 2 | 3 | import com.imooc.sell.SellApplication; 4 | import com.imooc.sell.dto.OrderDTO; 5 | import com.imooc.sell.service.OrderService; 6 | import com.imooc.sell.service.PayService; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.annotation.Rollback; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | @Rollback 16 | @Transactional 17 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 18 | @RunWith(SpringRunner.class) 19 | public class PayServiceImplTest { 20 | 21 | @Autowired 22 | private PayService payService; 23 | 24 | @Autowired 25 | private OrderService orderService; 26 | 27 | @Test 28 | public void createTest() { 29 | OrderDTO orderDTO = orderService.findOne("20180927155540703020eb3d4f0e74db"); 30 | payService.create(orderDTO); 31 | } 32 | @Test 33 | public void refundTest(){ 34 | OrderDTO orderDTO = orderService.findOne("20180927155540703020eb3d4f0e74db"); 35 | payService.refund(orderDTO); 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/serializer/Date2LongSerializer.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:Date2LongSerializer.java.
5 | * Package Name:com.imooc.sell.utils.serializer.
6 | * Date:2017年12月12日下午9:31:30.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.utils.serializer; 11 | 12 | import java.io.IOException; 13 | import java.util.Date; 14 | 15 | import com.fasterxml.jackson.core.JsonGenerator; 16 | import com.fasterxml.jackson.core.JsonProcessingException; 17 | import com.fasterxml.jackson.databind.JsonSerializer; 18 | import com.fasterxml.jackson.databind.SerializerProvider; 19 | 20 | /** 21 | * ClassName: Date2LongSerializer.
22 | * Function: ADD FUNCTION.
23 | * Reason: ADD REASON(可选).
24 | * Date: 2017年12月12日 下午9:31:30.
25 | * Desc: ADD DESC(可选).
26 | * @author 王艳军 27 | * @version 28 | * @since JDK 1.6 29 | */ 30 | 31 | public class Date2LongSerializer extends JsonSerializer{ 32 | 33 | /* (non-Javadoc) 34 | * @see com.fasterxml.jackson.databind.JsonSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider) 35 | */ 36 | @Override 37 | public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializers) 38 | throws IOException, JsonProcessingException { 39 | jsonGenerator.writeNumber(date.getTime() / 1000); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/resources/static/api/seller.json: -------------------------------------------------------------------------------- 1 | { 2 | "errno": 0, 3 | "msg": "成功", 4 | "data": { 5 | "name": "粥品香坊(回龙观)", 6 | "description": "蜂鸟专送", 7 | "deliveryTime": 38, 8 | "score": 4.2, 9 | "serviceScore": 4.1, 10 | "foodScore": 4.3, 11 | "rankRate": 69.2, 12 | "minPrice": 0, 13 | "deliveryPrice": 0, 14 | "ratingCount": 24, 15 | "sellCount": 90, 16 | "bulletin": "粥品香坊其烹饪粥料的秘方源于中国千年古法,在融和现代制作工艺,由世界烹饪大师屈浩先生领衔研发。坚守纯天然、0添加的良心品质深得消费者青睐,发展至今成为粥类的引领品牌。是2008年奥运会和2013年园博会指定餐饮服务商。", 17 | "supports": [ 18 | { 19 | "type": 0, 20 | "description": "在线支付满28减5" 21 | }, 22 | { 23 | "type": 1, 24 | "description": "VC无限橙果汁全场8折" 25 | }, 26 | { 27 | "type": 2, 28 | "description": "单人精彩套餐" 29 | }, 30 | { 31 | "type": 3, 32 | "description": "该商家支持发票,请下单写好发票抬头" 33 | }, 34 | { 35 | "type": 4, 36 | "description": "已加入“外卖保”计划,食品安全保障" 37 | } 38 | ], 39 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/seller_avatar_256px.jpg", 40 | "pics": [ 41 | "http://fuss10.elemecdn.com/8/71/c5cf5715740998d5040dda6e66abfjpeg.jpeg?imageView2/1/w/180/h/180", 42 | "http://fuss10.elemecdn.com/b/6c/75bd250e5ba69868f3b1178afbda3jpeg.jpeg?imageView2/1/w/180/h/180", 43 | "http://fuss10.elemecdn.com/f/96/3d608c5811bc2d902fc9ab9a5baa7jpeg.jpeg?imageView2/1/w/180/h/180", 44 | "http://fuss10.elemecdn.com/6/ad/779f8620ff49f701cd4c58f6448b6jpeg.jpeg?imageView2/1/w/180/h/180" 45 | ], 46 | "infos": [ 47 | "该商家支持发票,请下单写好发票抬头", 48 | "品类:其他菜系,包子粥店", 49 | "北京市昌平区回龙观西大街龙观置业大厦底商B座102单元1340", 50 | "营业时间:10:00-20:30" 51 | ] 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/resources/templates/category/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 |
5 | <#--边栏 sidebar--> 6 | <#include "../common/nav.ftl"> 7 | <#--主体内容区域 content--> 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 26 |
27 | 28 | 29 |
30 |
31 |
32 |
33 |
34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/controller/SecKillController.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.controller; 2 | 3 | import com.imooc.sell.service.SecKillService; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | /** 12 | * Describe: 13 | * 14 | * @Author 王艳军 15 | * @Date 2017/12/20 11:11:45 16 | */ 17 | @RestController 18 | @RequestMapping("/skill") 19 | @Slf4j 20 | public class SecKillController { 21 | 22 | @Autowired 23 | private SecKillService secKillService; 24 | 25 | /** 26 | * 查询秒杀活动特价商品的信息 27 | * @param productId 28 | * @return 29 | */ 30 | @GetMapping("/query/{productId}") 31 | public String query(@PathVariable String productId)throws Exception 32 | { 33 | return secKillService.querySecKillProductInfo(productId); 34 | } 35 | 36 | 37 | /** 38 | * 秒杀,没有抢到获得"哎呦喂,xxxxx",抢到了会返回剩余的库存量 39 | * @param productId 40 | * @return 41 | * @throws Exception 42 | */ 43 | @GetMapping("/order/{productId}") 44 | public String skill(@PathVariable String productId)throws Exception 45 | { 46 | log.info("@skill request, productId:" + productId); 47 | secKillService.orderProductMockDiffUser(productId); 48 | return secKillService.querySecKillProductInfo(productId); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/PayH5Service.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:PayService.java.
5 | * Package Name:com.imooc.sell.service.
6 | * Date:2017年12月13日下午9:29:35.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.service; 11 | 12 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; 13 | import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; 14 | import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; 15 | import com.github.binarywang.wxpay.exception.WxPayException; 16 | import com.imooc.sell.dto.OrderDTO; 17 | 18 | /** 19 | * ClassName: PayService.
20 | * Function: ADD FUNCTION.
21 | * Reason: 支付订单
22 | * Date: 2017年12月13日 下午9:29:35.
23 | * Desc: ADD DESC(可选).
24 | * @author 王艳军 25 | * @version 26 | * @since JDK 1.6 27 | */ 28 | 29 | public interface PayH5Service { 30 | 31 | /** 32 | * 微信H5支付 33 | * @param orderDTO 34 | * @return 35 | * @throws WxPayException 36 | */ 37 | WxPayUnifiedOrderResult create(OrderDTO orderDTO) throws WxPayException; 38 | 39 | /** 40 | * 微信H5支付异步通知结果 41 | * @param notifyData 42 | * @throws WxPayException 43 | */ 44 | WxPayOrderNotifyResult notify(String notifyData) throws WxPayException; 45 | 46 | /** 47 | * 微信H5支付退款 48 | * @param orderDTO 49 | * @throws WxPayException 50 | */ 51 | WxPayRefundResult refund(OrderDTO orderDTO) throws WxPayException; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/LocationHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import java.util.Map; 4 | 5 | import com.imooc.sell.builder.TextBuilder; 6 | import org.springframework.stereotype.Component; 7 | 8 | import me.chanjar.weixin.common.api.WxConsts.XmlMsgType; 9 | import me.chanjar.weixin.common.session.WxSessionManager; 10 | import me.chanjar.weixin.mp.api.WxMpService; 11 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 12 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 13 | 14 | /** 15 | * @author Binary Wang(https://github.com/binarywang) 16 | */ 17 | @Component 18 | public class LocationHandler extends AbstractHandler { 19 | 20 | @Override 21 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 22 | Map context, WxMpService wxMpService, 23 | WxSessionManager sessionManager) { 24 | if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { 25 | //TODO 接收处理用户发送的地理位置消息 26 | try { 27 | String content = "感谢反馈,您的的地理位置已收到!"; 28 | return new TextBuilder().build(content, wxMessage, null); 29 | } catch (Exception e) { 30 | this.logger.error("位置消息接收处理失败", e); 31 | return null; 32 | } 33 | } 34 | 35 | //上报地理位置事件 36 | this.logger.info("\n上报地理位置 。。。 "); 37 | this.logger.info("\n纬度 : " + wxMessage.getLatitude()); 38 | this.logger.info("\n经度 : " + wxMessage.getLongitude()); 39 | this.logger.info("\n精度 : " + String.valueOf(wxMessage.getPrecision())); 40 | 41 | //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 42 | 43 | return null; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/form/OrderForm.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | *
 4 |  * Project Name:sell
 5 |  * File Name:OrderForm.java
 6 |  * Package Name:com.imooc.sell.form
 7 |  * Date:2017年12月12日下午4:32:46
 8 |  * Copyright (c) 2017, 版权所有 (C) 2016-2036  土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved
 9 |  * 
10 | */ 11 | 12 | package com.imooc.sell.form; 13 | 14 | import lombok.AllArgsConstructor; 15 | import lombok.Builder; 16 | import lombok.Data; 17 | import lombok.NoArgsConstructor; 18 | import org.hibernate.validator.constraints.NotEmpty; 19 | 20 | /** 21 | *
22 |  * ClassName:OrderForm
23 |  * Function:
24 |  * Reason:
25 |  * Date: 2017年12月12日 下午4:32:46
26 |  * Desc:
27 |  * @author 王艳军
28 |  * @version
29 |  * @since JDK 1.6
30 |  * 
31 | */ 32 | @Data 33 | @Builder 34 | @NoArgsConstructor 35 | @AllArgsConstructor 36 | public class OrderForm { 37 | 38 | /** 39 | *
40 |    *  name:买家姓名
41 |    * 
42 | */ 43 | @NotEmpty(message = "姓名必填") 44 | private String name; 45 | 46 | /** 47 | *
48 |    *  phone:买家手机号
49 |    * 
50 | */ 51 | @NotEmpty(message = "手机号必填") 52 | private String phone; 53 | 54 | /** 55 | *
56 |    *  address:买家收获地址
57 |    * 
58 | */ 59 | @NotEmpty(message = "地址必填") 60 | private String address; 61 | 62 | /** 63 | *
64 |    *  openid:买家微信openid
65 |    * 
66 | */ 67 | @NotEmpty(message = "微信openid必填") 68 | private String openid; 69 | 70 | /** 71 | *
72 |    * items:买家购物车
73 |    * 
74 | */ 75 | @NotEmpty(message = "购物车不能为空") 76 | private String items; 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/config/WechatPayConfig.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.config; 2 | 3 | import com.imooc.sell.config.prop.ProjectUrlProperties; 4 | import com.imooc.sell.config.prop.WechatMpProperties; 5 | import com.lly835.bestpay.config.WxPayH5Config; 6 | import com.lly835.bestpay.service.impl.BestPayServiceImpl; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.stereotype.Component; 10 | 11 | /** 12 | * describe: 13 | * 14 | * @author 王艳军 15 | * @date 2017/12/13 21:48:55 16 | */ 17 | @Component 18 | public class WechatPayConfig { 19 | 20 | @Autowired 21 | private WechatMpProperties wechatMpConfig; 22 | 23 | @Autowired 24 | private ProjectUrlProperties projectUrlProperties; 25 | 26 | @Bean 27 | public BestPayServiceImpl bestPayService(){ 28 | BestPayServiceImpl bestPayService = new BestPayServiceImpl(); 29 | bestPayService.setWxPayH5Config(wxPayH5Config()); 30 | return bestPayService; 31 | } 32 | 33 | @Bean 34 | private WxPayH5Config wxPayH5Config(){ 35 | WxPayH5Config wxPayH5Config = new WxPayH5Config(); 36 | wxPayH5Config.setAppId(wechatMpConfig.getMpAppId()); 37 | wxPayH5Config.setAppSecret(wechatMpConfig.getMpAppSecret()); 38 | wxPayH5Config.setMchId(wechatMpConfig.getMchId()); 39 | wxPayH5Config.setMchKey(wechatMpConfig.getMchKey()); 40 | wxPayH5Config.setKeyPath(wechatMpConfig.getKeyPath()); 41 | wxPayH5Config.setNotifyUrl(projectUrlProperties.getDomainUrl() + projectUrlProperties.getProjectName() + wechatMpConfig.getNotifyUrl()); 42 | return wxPayH5Config; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/service/impl/PushMessageServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service.impl; 2 | 3 | import com.imooc.sell.SellApplication; 4 | import com.imooc.sell.dto.OrderDTO; 5 | import com.imooc.sell.service.OrderService; 6 | import com.imooc.sell.service.PushMessageService; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.annotation.Rollback; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | @Rollback 16 | @Transactional 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 19 | public class PushMessageServiceImplTest { 20 | 21 | @Autowired 22 | private PushMessageService pushMessageService; 23 | 24 | @Autowired 25 | private OrderService orderService; 26 | 27 | @Test 28 | public void pushOrderStatusTest() { 29 | OrderDTO orderDTO = orderService.findOne("2017121815032306058ef3f1a6d5b4d5"); 30 | pushMessageService.pushOrderStatus(orderDTO, "", ""); 31 | } 32 | @Test 33 | public void pushOrderSuccessTest() { 34 | OrderDTO orderDTO = orderService.findOne("2017121815032306058ef3f1a6d5b4d5"); 35 | pushMessageService.pushOrderSuccess(orderDTO); 36 | } 37 | @Test 38 | public void pushPaySuccessTest() { 39 | OrderDTO orderDTO = orderService.findOne("2017121815032306058ef3f1a6d5b4d5"); 40 | pushMessageService.pushPaySuccess(orderDTO); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/config/WechatScanPayConfig.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.config; 2 | 3 | import com.github.binarywang.wxpay.config.WxPayConfig; 4 | import com.github.binarywang.wxpay.constant.WxPayConstants; 5 | import com.github.binarywang.wxpay.service.WxPayService; 6 | import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; 7 | import com.imooc.sell.config.prop.WechatMpProperties; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | *
14 |  * @PackageName com.imooc.sell.config
15 |  * @ClassName WechatScanPayConfig
16 |  * @Desc 微信刷卡支付Bean配置
17 |  * @WebSite https://www.potato369.com
18 |  * @Author 王艳军
19 |  * @Date 2018/10/10 15:52
20 |  * @CreateBy IntellJ IDEA 2018.2.4
21 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
22 |  * 
23 | */ 24 | @Component 25 | public class WechatScanPayConfig { 26 | 27 | @Autowired 28 | private WechatMpProperties wechatMpConfig; 29 | 30 | @Bean 31 | public WxPayService wxPayService() { 32 | WxPayService wxPayService = new WxPayServiceImpl(); 33 | wxPayService.setConfig(wxPayConfig()); 34 | return wxPayService; 35 | } 36 | 37 | @Bean 38 | public WxPayConfig wxPayConfig() { 39 | WxPayConfig wxPayConfig = new WxPayConfig(); 40 | wxPayConfig.setAppId(this.wechatMpConfig.getMpAppId()); 41 | wxPayConfig.setMchId(this.wechatMpConfig.getMchId()); 42 | wxPayConfig.setMchKey(this.wechatMpConfig.getMchKey()); 43 | wxPayConfig.setTradeType(WxPayConstants.TradeType.MICROPAY); 44 | return wxPayConfig; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/MsgHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import java.util.Map; 4 | 5 | import com.imooc.sell.builder.TextBuilder; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.imooc.sell.utils.JsonUtils; 10 | 11 | import me.chanjar.weixin.common.api.WxConsts.XmlMsgType; 12 | import me.chanjar.weixin.common.error.WxErrorException; 13 | import me.chanjar.weixin.common.session.WxSessionManager; 14 | import me.chanjar.weixin.mp.api.WxMpService; 15 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 16 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 17 | 18 | /** 19 | * @author Binary Wang(https://github.com/binarywang) 20 | */ 21 | @Component 22 | public class MsgHandler extends AbstractHandler { 23 | 24 | @Override 25 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 26 | Map context, WxMpService weixinService, 27 | WxSessionManager sessionManager) { 28 | 29 | if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) { 30 | //TODO 可以选择将消息保存到本地 31 | } 32 | 33 | //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服 34 | try { 35 | if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服") 36 | && weixinService.getKefuService().kfOnlineList() 37 | .getKfOnlineList().size() > 0) { 38 | return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE() 39 | .fromUser(wxMessage.getToUser()) 40 | .toUser(wxMessage.getFromUser()).build(); 41 | } 42 | } catch (WxErrorException e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | //TODO 组装回复消息 47 | String content = "收到信息内容:" + JsonUtils.toJson(wxMessage); 48 | 49 | return new TextBuilder().build(content, wxMessage, weixinService); 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/repository/SellerInfoRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.repository; 2 | 3 | import com.imooc.sell.SellApplication; 4 | import com.imooc.sell.dataobject.SellerInfo; 5 | import com.imooc.sell.utils.UUIDUtil; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.annotation.Rollback; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import static org.junit.Assert.*; 15 | @Rollback 16 | @Transactional 17 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 18 | @RunWith(SpringRunner.class) 19 | public class SellerInfoRepositoryTest { 20 | 21 | @Autowired 22 | private SellerInfoRepository sellerInfoRepository; 23 | 24 | public static final String SELLER_OPENID = "oSkiNv4fBXYxidv0wU_U0UDHNP4M"; 25 | 26 | @Test 27 | public void saveTest(){ 28 | SellerInfo sellerInfo = new SellerInfo("admin","123456", SELLER_OPENID); 29 | sellerInfo.setSellerId(UUIDUtil.gen32UUID()); 30 | SellerInfo result = sellerInfoRepository.save(sellerInfo); 31 | assertNotNull(result); 32 | } 33 | 34 | @Test 35 | public void deleteTest(){ 36 | String sellerId = "57a676a648484920ad6b6c715ef45fa1"; 37 | sellerInfoRepository.delete(sellerId); 38 | SellerInfo result = sellerInfoRepository.findOne(sellerId); 39 | assertNull(result); 40 | } 41 | 42 | @Test 43 | public void findByOpenidTest() { 44 | SellerInfo sellerInfo = sellerInfoRepository.findByOpenid(SELLER_OPENID); 45 | assertEquals(SELLER_OPENID,sellerInfo.getOpenid()); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/ProductService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell.
3 | * File Name:ProductService.java.
4 | * Package Name:com.imooc.sell.service.
5 | * Date:2017年12月11日上午10:24:02.
6 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
7 | */ 8 | package com.imooc.sell.service; 9 | 10 | import java.util.List; 11 | 12 | import org.springframework.data.domain.Page; 13 | import org.springframework.data.domain.Pageable; 14 | 15 | import com.imooc.sell.dataobject.ProductInfo; 16 | import com.imooc.sell.dto.CartDTO; 17 | 18 | /** 19 | * ClassName: ProductService.
20 | * Function: ADD FUNCTION.
21 | * Reason: 商品service.
22 | * Date: 2017年12月11日 上午10:24:02.
23 | * Desc: 商品service.
24 | * @author 王艳军 25 | * @version 1.0 26 | * @since JDK 1.6 27 | */ 28 | public interface ProductService { 29 | 30 | ProductInfo findOne(String productId); 31 | 32 | /** 33 | * 查询所有在架商品列表 34 | * @return 35 | */ 36 | List findUpAll(); 37 | 38 | /** 39 | * 查询所有商品列表(分页) 40 | * @param pageable 41 | * @return 42 | */ 43 | Page findAll(Pageable pageable); 44 | 45 | /** 46 | * 添加一个商品信息到数据库 47 | * @param productInfo 48 | * @return 49 | */ 50 | ProductInfo save(ProductInfo productInfo); 51 | 52 | /** 53 | * 加库存 54 | * @param cartDTOList 55 | */ 56 | void increaseStock(List cartDTOList); 57 | 58 | /** 59 | * 减库存 60 | * @param cartDTOList 61 | */ 62 | void decreaseStock(List cartDTOList); 63 | 64 | 65 | /** 66 | * 上架 67 | * @param productId 68 | * @return 69 | */ 70 | ProductInfo onSale(String productId); 71 | 72 | /** 73 | * 下架 74 | * @param productId 75 | * @return 76 | */ 77 | ProductInfo offSale(String productId); 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dataobject/SellerInfo.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.dataobject; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import javax.persistence.Column; 7 | import javax.persistence.Entity; 8 | import javax.persistence.Id; 9 | 10 | import lombok.NoArgsConstructor; 11 | import org.hibernate.annotations.DynamicUpdate; 12 | import java.io.Serializable; 13 | import java.util.Date; 14 | 15 | /** 16 | * @Author 王艳军 17 | * @Date 2017-12-17 13:24 18 | */ 19 | @Data 20 | @Entity 21 | @Builder 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @DynamicUpdate 25 | public class SellerInfo implements Serializable { 26 | 27 | /** 28 | *@Fields serialVersionUID:序列号 29 | */ 30 | private static final long serialVersionUID = 2291413426974623929L; 31 | 32 | /** 33 | *@Fields sellerId:卖家用户id 34 | */ 35 | @Id 36 | @Column(name = "seller_id", nullable=false, length=32) 37 | private String sellerId; 38 | 39 | /** 40 | *@Fields username:卖家用户名字 41 | */ 42 | @Column(name = "username", nullable=false, length=32) 43 | private String username; 44 | 45 | /** 46 | *@Fields password:登录密码 47 | */ 48 | @Column(name = "password", nullable=false, length=32) 49 | private String password; 50 | 51 | /** 52 | *@Fields openid:微信openid 53 | */ 54 | @Column(name = "openid", nullable=false, length=64) 55 | private String openid; 56 | 57 | /** 58 | *@Fields createTime:创建时间 59 | */ 60 | @Column(name = "create_time", nullable=false) 61 | private Date createTime; 62 | 63 | /** 64 | *@Fields updateTime:修改时间 65 | */ 66 | @Column(name = "update_time", nullable=false) 67 | private Date updateTime; 68 | 69 | public SellerInfo(String username, String password, String openid) { 70 | super(); 71 | this.username = username; 72 | this.password = password; 73 | this.openid = openid; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/resources/templates/pay/create.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/converter/OrderForm2OrderDTOConverter.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderForm2OrderDTOConverter.java.
5 | * Package Name:com.imooc.sell.converter.
6 | * Date:2017年12月12日下午4:51:32.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.converter; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import com.google.gson.Gson; 16 | import com.google.gson.reflect.TypeToken; 17 | import com.imooc.sell.dataobject.OrderDetail; 18 | import com.imooc.sell.dto.OrderDTO; 19 | import com.imooc.sell.enums.ResultEnum; 20 | import com.imooc.sell.exception.SellException; 21 | import com.imooc.sell.form.OrderForm; 22 | 23 | import lombok.extern.slf4j.Slf4j; 24 | 25 | /** 26 | * ClassName: OrderForm2OrderDTOConverter.
27 | * Function: ADD FUNCTION.
28 | * Reason: ADD REASON(可选).
29 | * Date: 2017年12月12日 下午4:51:32.
30 | * Desc: ADD DESC(可选).
31 | * 32 | * @author 王艳军 33 | * @version 34 | * @since JDK 1.6 35 | */ 36 | @Slf4j 37 | public class OrderForm2OrderDTOConverter { 38 | 39 | public static OrderDTO convert(OrderForm orderForm) { 40 | Gson gson = new Gson(); 41 | OrderDTO orderDTO = new OrderDTO(); 42 | orderDTO.setBuyerName(orderForm.getName()); 43 | orderDTO.setBuyerAddress(orderForm.getAddress()); 44 | orderDTO.setBuyerOpenid(orderForm.getOpenid()); 45 | orderDTO.setBuyerPhone(orderForm.getPhone()); 46 | List orderDetailList = new ArrayList(); 47 | try { 48 | orderDetailList = gson.fromJson(orderForm.getItems(), new TypeToken>() {}.getType()); 49 | } catch (Exception e) { 50 | log.error("转换出错,string={}", orderForm.getItems()); 51 | throw new SellException(ResultEnum.PARAM_ERROR); 52 | } 53 | orderDTO.setOrderDetailList(orderDetailList); 54 | return orderDTO; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/config/prop/ProjectUrlProperties.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.config.prop; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @Author 王艳军 12 | * @Date 2017-12-17 15:00 13 | */ 14 | @Data 15 | @Builder 16 | @Component 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @ConfigurationProperties(prefix = "projectUrl") 20 | public class ProjectUrlProperties { 21 | 22 | /** 23 | *
24 |    * projectName:项目名字
25 |    * 
26 | */ 27 | private String projectName; 28 | 29 | /** 30 | *
31 |    * domainUrl:项目部署解析的域名地址URL
32 |    * 
33 | */ 34 | private String domainUrl; 35 | 36 | /** 37 | *
38 |    * wechatMpAuthorizeUrl:微信公众平台授权地址URL
39 |    * 
40 | */ 41 | private String wechatMpAuthorizeUrl; 42 | 43 | /** 44 | *
45 |    * wechatMpAuthorizeUrlUserInfo:微信公众平台授权获取用户信息地址URL
46 |    * 
47 | */ 48 | private String wechatMpAuthorizeUrlUserInfo; 49 | 50 | /** 51 | *
52 |    * wechatOpenAuthorizeUrl:微信开放平台授权登录地址URL
53 |    * 
54 | */ 55 | private String wechatOpenAuthorizeUrl; 56 | 57 | /** 58 | *
59 |    * wechatOpenAuthorizeUrlUserInfo:微信开放平台授权登录获取用户信息地址URL
60 |    * 
61 | */ 62 | private String wechatOpenAuthorizeUrlUserInfo; 63 | 64 | /** 65 | *
66 |    * loginUrl:跳转登录地址URL
67 |    * 
68 | */ 69 | private String loginUrl; 70 | 71 | /** 72 | *
73 |    * logoutUrl:跳转登出地址URL
74 |    * 
75 | */ 76 | private String logoutUrl; 77 | 78 | /** 79 | *
80 |    * errorUrl:错误页面地址URL
81 |    * 
82 | */ 83 | private String errorUrl; 84 | 85 | /** 86 | *
87 |    * successUrl:成功页面地址URL
88 |    * 
89 | */ 90 | private String successUrl; 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/RedisLock.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.redis.core.StringRedisTemplate; 6 | import org.springframework.stereotype.Component; 7 | 8 | import org.springframework.util.StringUtils; 9 | 10 | /** 11 | * Describe: 12 | * 13 | * @Author 王艳军 14 | * @Date 2017/12/20 11:16:12 15 | */ 16 | @Component 17 | @Slf4j 18 | public class RedisLock { 19 | 20 | @Autowired 21 | private StringRedisTemplate redisTemplate; 22 | 23 | /** 24 | * 加锁 25 | * @param key 26 | * @param value 当前时间+超时时间 27 | * @return 28 | */ 29 | public boolean lock(String key, String value) { 30 | if(redisTemplate.opsForValue().setIfAbsent(key, value)) { 31 | return true; 32 | } 33 | //currentValue=A 这两个线程的value都是B 其中一个线程拿到锁 34 | String currentValue = redisTemplate.opsForValue().get(key); 35 | //如果锁过期 36 | if (!StringUtils.isEmpty(currentValue) 37 | && Long.parseLong(currentValue) < System.currentTimeMillis()) { 38 | //获取上一个锁的时间 39 | String oldValue = redisTemplate.opsForValue().getAndSet(key, value); 40 | if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) { 41 | return true; 42 | } 43 | } 44 | 45 | return false; 46 | } 47 | 48 | /** 49 | * 解锁 50 | * @param key 51 | * @param value 52 | */ 53 | public void unlock(String key, String value) { 54 | try { 55 | String currentValue = redisTemplate.opsForValue().get(key); 56 | if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) { 57 | redisTemplate.opsForValue().getOperations().delete(key); 58 | } 59 | }catch (Exception e) { 60 | log.error("【redis分布式锁】解锁异常, {}", e); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/config/WechatPayH5Config.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.config; 2 | 3 | import com.github.binarywang.wxpay.config.WxPayConfig; 4 | import com.github.binarywang.wxpay.constant.WxPayConstants; 5 | import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; 6 | import com.imooc.sell.config.prop.ProjectUrlProperties; 7 | import com.imooc.sell.config.prop.WechatMpProperties; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.stereotype.Component; 12 | 13 | /** 14 | *
15 |  * Describe:H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付
16 | * 主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付
17 | * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1
18 | * 发起微信客户端外的移动端网页H5调起支付配置
19 | *
20 |  * @author 王艳军
21 |  * @date 2017/12/13 21:48:55
22 |  */
23 | @Component
24 | public class WechatPayH5Config {
25 | 
26 |     @Autowired
27 |     private WechatMpProperties wechatMpConfig;
28 | 
29 |     @Autowired
30 |     private ProjectUrlProperties projectUrlProperties;
31 | 
32 |     @Bean
33 |     public WxPayServiceImpl wxPayH5Service() {
34 |         WxPayServiceImpl wxPayH5Service = new WxPayServiceImpl();
35 |         wxPayH5Service.setConfig(wxPayH5Config());
36 |         return wxPayH5Service;
37 |     }
38 | 
39 |     @Bean
40 |     private WxPayConfig wxPayH5Config() {
41 |         WxPayConfig wxPayH5Config = new  WxPayConfig();
42 |         wxPayH5Config.setAppId(wechatMpConfig.getMpAppId());
43 |         wxPayH5Config.setMchId(wechatMpConfig.getMchId());
44 |         wxPayH5Config.setMchKey(wechatMpConfig.getMchKey());
45 |         wxPayH5Config.setTradeType(WxPayConstants.TradeType.MWEB);//H5支付
46 |         wxPayH5Config.setKeyPath(wechatMpConfig.getKeyPath());
47 |         wxPayH5Config.setUseSandboxEnv(false);
48 |         wxPayH5Config.setNotifyUrl(projectUrlProperties.getDomainUrl() + projectUrlProperties.getProjectName() + wechatMpConfig.getNotifyUrl());
49 |         return wxPayH5Config;
50 |     }
51 | }
52 | 


--------------------------------------------------------------------------------
/src/main/resources/static/css/listProd.css:
--------------------------------------------------------------------------------
 1 | /* 重置 [[*/
 2 | body,p,ul,li,h1,h2,form,input{margin:0;padding:0;}
 3 | h1,h2{font-size:100%;}
 4 | ul{list-style:none;}
 5 | body{-webkit-user-select:none;-webkit-text-size-adjust:none;font-family:Helvetica;background:#ECECEC;}
 6 | html,body{height:100%;}
 7 | a,button,input,img{-webkit-touch-callout:none;outline:none;}
 8 | a{text-decoration:none;}
 9 | /* 重置 ]]*/
10 | /* 功能 [[*/
11 | .hide{display:none!important;}
12 | .cf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}
13 | /* 功能 ]]*/
14 | /* 按钮 [[*/
15 | a[class*="btn"]{display:block;height:42px;line-height:42px;color:#FFFFFF;text-align:center;border-radius:5px;}
16 | .btn-blue{background:#3D87C3;border:1px solid #1C5E93;}
17 | .btn-green{background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #43C750), color-stop(1, #31AB40));border:1px solid #2E993C;box-shadow:0 1px 0 0 #69D273 inset;}
18 | /* 按钮 [[*/
19 | /* 充值页 [[*/
20 | .charge{font-family:Helvetica;padding-bottom:10px;-webkit-user-select:none;}
21 | .charge h1{height:44px;line-height:44px;color:#FFFFFF;background:#3D87C3;text-align:center;font-size:20px;-webkit-box-sizing:border-box;box-sizing:border-box;}
22 | .charge h2{font-size:14px;color:#777777;margin:5px 0;text-align:center;}
23 | .charge .content{padding:10px 12px;}
24 | .charge .select li{position:relative;display:block;float:left;width:100%;margin-right:2%;height:150px;line-height:150px;text-align:center;border:1px solid #BBBBBB;color:#666666;font-size:16px;margin-bottom:5px;border-radius:3px;background-color:#FFFFFF;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;}
25 | .charge .price{border-bottom:1px dashed #C9C9C9;padding:10px 10px 15px;margin-bottom:20px;color:#666666;font-size:12px;}
26 | .charge .price strong{font-weight:normal;color:#EE6209;font-size:26px;font-family:Helvetica;}
27 | .charge .showaddr{border:1px dashed #C9C9C9;padding:10px 10px 15px;margin-bottom:20px;color:#666666;font-size:12px;text-align:center;}
28 | .charge .showaddr strong{font-weight:normal;color:#9900FF;font-size:26px;font-family:Helvetica;}
29 | .charge .copy-right{margin:5px 0; font-size:12px;color:#848484;text-align:center;}
30 | /* 充值页 ]]*/


--------------------------------------------------------------------------------
/src/test/java/com/imooc/sell/service/impl/OrderDetailServiceImplTest.java:
--------------------------------------------------------------------------------
 1 | 
 2 | /**
 3 |  * Project Name:sell.
4 | * File Name:OrderDetailServiceImplTest.java.
5 | * Package Name:com.imooc.sell.service.impl.
6 | * Date:2017年12月19日上午10:18:48.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.service.impl; 11 | 12 | import static org.junit.Assert.*; 13 | 14 | import java.util.List; 15 | 16 | import com.imooc.sell.SellApplication; 17 | import org.junit.Test; 18 | import org.junit.runner.RunWith; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.boot.test.context.SpringBootTest; 21 | import org.springframework.test.annotation.Rollback; 22 | import org.springframework.test.context.junit4.SpringRunner; 23 | 24 | import com.imooc.sell.dataobject.OrderDetail; 25 | import com.imooc.sell.dataobject.ProductInfo; 26 | import com.imooc.sell.service.OrderDetailService; 27 | import org.springframework.transaction.annotation.Transactional; 28 | 29 | /** 30 | * ClassName: OrderDetailServiceImplTest.
31 | * Function: ADD FUNCTION.
32 | * Reason: ADD REASON(可选).
33 | * Date: 2017年12月19日 上午10:18:48.
34 | * Desc: ADD DESC(可选).
35 | * @author 王艳军 36 | * @version 37 | * @since JDK 1.6 38 | */ 39 | @Rollback 40 | @Transactional 41 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 42 | @RunWith(SpringRunner.class) 43 | public class OrderDetailServiceImplTest { 44 | 45 | @Autowired 46 | private OrderDetailService orderDetailService; 47 | 48 | @Test 49 | public void findOrderDetailByOrderIdTest(){ 50 | List orderDetailList = orderDetailService.findOrderDetailByOrderId("201712190947304742542a3593097460"); 51 | assertNotEquals(0, orderDetailList.size()); 52 | } 53 | 54 | @Test 55 | public void findProductInfoByOrderIdTest(){ 56 | List productInfoList = orderDetailService.findProductInfoByOrderId("20171219094059415fb762f2d1d5e4d4"); 57 | assertEquals(1, productInfoList.size()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:CategoryService.java 4 | * Package Name:com.imooc.sell.service 5 | * Date:2017年12月8日下午10:54:28 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | 10 | package com.imooc.sell.service; 11 | /** 12 | * ClassName:CategoryService
13 | * Function: TODO ADD FUNCTION.
14 | * Reason: TODO ADD REASON.
15 | * Date: 2017年12月8日 下午10:54:28
16 | * @author admin 17 | * @version 18 | * @since JDK 1.6 19 | * @see 20 | */ 21 | 22 | import java.util.List; 23 | 24 | import com.imooc.sell.dataobject.ProductCategory; 25 | import org.springframework.data.domain.Page; 26 | import org.springframework.data.domain.Pageable; 27 | 28 | public interface CategoryService { 29 | 30 | /** 31 | * 32 | * findOne:(根据categoryId查询一个商品信息).
33 | * 34 | * @author admin 35 | * @param categoryId 36 | * @return 37 | * @since JDK 1.6 38 | */ 39 | ProductCategory findOne(Integer categoryId); 40 | 41 | /** 42 | * 43 | * findAll:(查询所有的ProductCategory商品信息).
44 | * 45 | * @author admin 46 | * @return 47 | * @since JDK 1.6 48 | */ 49 | List findAll(); 50 | 51 | /** 52 | * 53 | * findAll:(分页查询所有的ProductCategory商品信息).
54 | * 55 | * @author admin 56 | * @return 57 | * @since JDK 1.6 58 | */ 59 | Page findAll(Pageable pageable); 60 | /** 61 | * 62 | * findByCategoryTypeIn:(通过categoryType查询商品信息).
63 | * @author admin 64 | * @param categoryTypeList 65 | * @return 66 | * @since JDK 1.6 67 | */ 68 | List findByCategoryTypeIn(List categoryTypeList); 69 | /** 70 | * 71 | * save:(新增一个ProductCategory商品信息).
72 | * 73 | * @author admin 74 | * @param productCategory 75 | * @return 76 | * @since JDK 1.6 77 | */ 78 | ProductCategory save(ProductCategory productCategory); 79 | 80 | /** 81 | * 82 | * deleteOne:(根据categoryI删除一个类目,不是真正物理上的删除,只是逻辑删除,修改为是否删除状态,).
83 | * 84 | * @author admin 85 | * @param categoryId 86 | * @return 87 | * @since JDK 1.6 88 | */ 89 | ProductCategory deleteOne(Integer categoryId); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/aspect/SellerAuthorizeAspect.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.aspect; 2 | 3 | import com.imooc.sell.constant.CookieConstant; 4 | import com.imooc.sell.constant.RedisConstant; 5 | import com.imooc.sell.exception.SellerAuthorizeException; 6 | import com.imooc.sell.utils.CookieUtil; 7 | import com.imooc.sell.utils.StringUtil; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.aspectj.lang.annotation.Aspect; 10 | import org.aspectj.lang.annotation.Before; 11 | import org.aspectj.lang.annotation.Pointcut; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.data.redis.core.StringRedisTemplate; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.web.context.request.RequestContextHolder; 16 | import org.springframework.web.context.request.ServletRequestAttributes; 17 | import javax.servlet.http.Cookie; 18 | import javax.servlet.http.HttpServletRequest; 19 | 20 | /** 21 | * @Describe: 22 | * @Author 王艳军 23 | * @Date 2017/12/18 17:19:01 24 | */ 25 | @Aspect 26 | @Component 27 | @Slf4j 28 | public class SellerAuthorizeAspect { 29 | 30 | @Autowired 31 | private StringRedisTemplate redisTemplate; 32 | 33 | @Pointcut("execution(public * com.imooc.sell.controller.Seller*.*(..)) && !execution(public * com.imooc.sell.controller.SellerUserController.*(..)) && !execution(public * com.imooc.sell.controller.PayH5Controller.*(..))") 34 | public void verify() {} 35 | 36 | @Before(value = "verify()") 37 | public void doVerify() { 38 | ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 39 | HttpServletRequest request = requestAttributes.getRequest(); 40 | //1、查询cookie 41 | Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); 42 | if (cookie == null) { 43 | log.warn("【登录校验】 Cookie中查询不到token"); 44 | throw new SellerAuthorizeException(); 45 | } 46 | //2、去redis里面查询 47 | String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue())); 48 | if (StringUtil.isEmpty(tokenValue)) { 49 | log.warn("【登录校验】 Redis中查询不到token"); 50 | throw new SellerAuthorizeException(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/jedis/JedisDemo.java: -------------------------------------------------------------------------------- 1 | /** 2 | *
 3 |  * Project Name: sell
 4 |  * File Name: JedisDemo.java
 5 |  * Package Name: com.imooc.sell.jedis
 6 |  * Create Date: 2018年10月27日 下午7:44:57
 7 |  * Copyright (c) 2018, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved。
 8 |  * 
9 | */ 10 | package com.imooc.sell.jedis; 11 | 12 | import org.junit.Test; 13 | 14 | import lombok.extern.slf4j.Slf4j; 15 | import redis.clients.jedis.Jedis; 16 | import redis.clients.jedis.JedisPool; 17 | import redis.clients.jedis.JedisPoolConfig; 18 | 19 | /** 20 | *
21 |  * @PackageName com.imooc.sell.jedis
22 |  * @ClassName JedisDemo
23 |  * @Desc 描述此类实现的功能
24 |  * @WebSite https://www.potato369.com
25 |  * @Author Administrator
26 |  * @Date 2018年10月27日 下午7:44:57
27 |  * @CreateBy Eclipse IDEA Neon.3 Release(4.6.3)
28 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
29 |  * 
30 | */ 31 | @Slf4j 32 | public class JedisDemo { 33 | 34 | /** 35 | * 36 | * test1:(单例的方式获取Jedis资源) 37 | * 38 | * @author Administrator 39 | * @since JDK 1.6 40 | */ 41 | @Test 42 | public void test1() { 43 | //设置主机地址和端口号 44 | Jedis jedis = new Jedis("192.168.1.8", 6379); 45 | //保存数据 46 | jedis.set("website", "https://www.imooc.com"); 47 | //获取数据 48 | String value = jedis.get("name"); 49 | log.info("【获取到的数据】value={}", value); 50 | if (jedis != null) { 51 | jedis.close(); 52 | } 53 | } 54 | 55 | /** 56 | * 57 | * test2:(连接池的方式获取Jedis资源) 58 | * 59 | * @author Administrator 60 | * @since JDK 1.6 61 | */ 62 | @Test 63 | public void test2() { 64 | JedisPoolConfig config = new JedisPoolConfig(); 65 | config.setMaxTotal(30); 66 | config.setMaxIdle(10); 67 | 68 | Jedis jedis = null; 69 | JedisPool jedisPool = null; 70 | 71 | try { 72 | jedisPool = new JedisPool("192.168.1.8", 6379); 73 | jedis = jedisPool.getResource(); 74 | jedis.set("site", "https://www.potato369.com"); 75 | String value = jedis.get("name"); 76 | log.info("【获取到的数据】value={}", value); 77 | } catch (Exception e) { 78 | log.error("【获取Jedis连接】出现错误", e); 79 | } finally { 80 | if (jedis != null) { 81 | jedis.close(); 82 | } 83 | if (jedisPool != null) { 84 | jedisPool.close(); 85 | } 86 | } 87 | 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/OrderService.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | *
  4 |  * Project Name:sell
  5 |  * File Name:OrderService.java
  6 |  * Package Name:com.imooc.sell.service
  7 |  * Date:2017年12月11日下午4:57:22
  8 |  * Copyright (c) 2017, 版权所有 (C) 2016-2036  土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
9 | *
10 | */ 11 | 12 | package com.imooc.sell.service; 13 | 14 | import org.springframework.data.domain.Page; 15 | import org.springframework.data.domain.Pageable; 16 | 17 | import com.imooc.sell.dto.OrderDTO; 18 | 19 | /** 20 | *
 21 |   * ClassName: OrderService
 22 |   * Function:   ADD FUNCTION
 23 |   * Reason:  ADD REASON(可选)
 24 |   * Date: 2017年12月11日 下午4:57:22
 25 |   * Desc:  ADD DESC(可选)
 26 |   * @author 王艳军
 27 |   * @version
 28 |   * @since JDK 1.6
 29 |   * 
30 | */ 31 | public interface OrderService { 32 | 33 | /*1.创建订单*/ 34 | /** 35 | * 创建订单 36 | * @param orderDTO 37 | * @return OrderDTO 38 | * @throws Exception 39 | */ 40 | OrderDTO create(OrderDTO orderDTO); 41 | 42 | /*2.查询单个订单*/ 43 | /** 44 | * 查询单个订单 45 | * @param orderId 46 | * @return OrderDTO 47 | * @throws Exception 48 | */ 49 | OrderDTO findOne(String orderId); 50 | 51 | /*3.查询订单列表*/ 52 | /** 53 | * 查询订单列表 54 | * @param buyerOpenid 55 | * @param pageable 56 | * @return Page 57 | * @throws Exception 58 | */ 59 | Page findList(String buyerOpenid, Pageable pageable); 60 | 61 | /*4.取消订单*/ 62 | /** 63 | * 取消订单 64 | * @param orderDTO 65 | * @return OrderDTO 66 | * @throws Exception 67 | */ 68 | OrderDTO cancel(OrderDTO orderDTO); 69 | 70 | /*5.完结订单*/ 71 | /** 72 | * 完结订单 73 | * @param orderDTO 74 | * @return orderDTO 75 | * @throws Exception 76 | */ 77 | OrderDTO finsh(OrderDTO orderDTO); 78 | 79 | /*6.支付订单*/ 80 | /** 81 | * 支付订单 82 | * @param orderDTO 83 | * @return OrderDTO 84 | * @throws Exception 85 | */ 86 | OrderDTO paid(OrderDTO orderDTO); 87 | 88 | /*7.查询订单列表*/ 89 | /** 90 | * 91 | * findList:(查询订单列表) 92 | * 93 | * @author admin 94 | * @param pageable 95 | * @return 96 | * @since JDK 1.6 97 | */ 98 | Page findList(Pageable pageable); 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/impl/OrderDetailServiceImpl.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderDetailServiceImpl.java.
5 | * Package Name:com.imooc.sell.service.impl.
6 | * Date:2017年12月18日下午9:06:30.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.service.impl; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Service; 17 | 18 | import com.imooc.sell.dataobject.OrderDetail; 19 | import com.imooc.sell.dataobject.ProductInfo; 20 | import com.imooc.sell.repository.OrderDetailRepository; 21 | import com.imooc.sell.service.OrderDetailService; 22 | 23 | /** 24 | * ClassName: OrderDetailServiceImpl.
25 | * Function: ADD FUNCTION.
26 | * Reason: ADD REASON(可选).
27 | * Date: 2017年12月18日 下午9:06:30.
28 | * Desc: ADD DESC(可选).
29 | * @author 王艳军 30 | * @version 31 | * @since JDK 1.6 32 | */ 33 | @Service 34 | public class OrderDetailServiceImpl implements OrderDetailService { 35 | 36 | @Autowired 37 | private OrderDetailRepository orderDetailRepository; 38 | 39 | 40 | /* (non-Javadoc) 41 | * @see com.imooc.sell.service.impl.OrderDetailService#findOrderDetailByOrderId(java.lang.String) 42 | */ 43 | @Override 44 | public List findOrderDetailByOrderId(String orderId) { 45 | return orderDetailRepository.findByOrderId(orderId); 46 | } 47 | 48 | /* (non-Javadoc) 49 | * @see com.imooc.sell.service.impl.OrderDetailService#findProductInfoByOrderId(java.lang.String) 50 | */ 51 | @Override 52 | public List findProductInfoByOrderId(String orderId) { 53 | List orderDetailList = orderDetailRepository.findByOrderId(orderId); 54 | List productInfoList = new ArrayList(); 55 | if (orderDetailList != null) { 56 | for (OrderDetail orderDetail : orderDetailList) { 57 | ProductInfo productInfo = new ProductInfo(); 58 | productInfo.setProductId(orderDetail.getProductId()); 59 | productInfo.setProductName(orderDetail.getProductName()); 60 | productInfoList.add(productInfo); 61 | } 62 | } 63 | return productInfoList; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/form/ProductForm.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:ProductForm.java 4 | * Package Name:com.imooc.sell.form 5 | * Date:2017年12月16日下午9:03:19 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | 10 | package com.imooc.sell.form; 11 | 12 | import java.math.BigDecimal; 13 | import javax.validation.constraints.DecimalMin; 14 | import javax.validation.constraints.Min; 15 | import javax.validation.constraints.NotNull; 16 | import javax.validation.constraints.Size; 17 | import org.hibernate.validator.constraints.NotBlank; 18 | import lombok.AllArgsConstructor; 19 | import lombok.Builder; 20 | import lombok.Data; 21 | import lombok.NoArgsConstructor; 22 | 23 | /** 24 | *
 25 |  * @ClassName:
 26 |  * @Function:
 27 |  * @Reason:
 28 |  * @Date: 2017年12月16日 下午9:03:19
 29 |  * @author admin
 30 |  * @version
 31 |  * @since JDK 1.6
 32 |  * @see
 33 |  * 
34 | */ 35 | @Data 36 | @Builder 37 | @NoArgsConstructor 38 | @AllArgsConstructor 39 | public class ProductForm { 40 | 41 | /** 42 | *
 43 |    * productId:商品编号:主键
 44 |    * 
45 | */ 46 | private String productId; 47 | 48 | /** 49 | *
 50 |    * productName:商品名称
 51 |    * 
52 | */ 53 | @NotBlank(message = "商品名称不能为空") 54 | private String productName; 55 | 56 | /** 57 | *
 58 |    * productPrice:商品单价
 59 |    * 
60 | */ 61 | @DecimalMin(value = "0.00", message = "商品单价必须大于0.00") 62 | private BigDecimal productPrice; 63 | 64 | /** 65 | *
 66 |    * productStock:商品库存
 67 |    * 
68 | */ 69 | @Min(value = 0, message = "商品库存不能为负数") 70 | private Integer productStock; 71 | 72 | /** 73 | *
 74 |    * procductDescription:商品描述
 75 |    * 
76 | */ 77 | @Size(min = 0, max = 64) 78 | private String productDescription; 79 | 80 | /** 81 | *
 82 |    * procductIcon:小图片
 83 |    * 
84 | */ 85 | private String productIcon; 86 | 87 | /** 88 | *
 89 |    * categoryType:类目编号
 90 |    * 
91 | */ 92 | @NotNull(message = "类目编号不能为空") 93 | private Integer categoryType; 94 | 95 | /** 96 | *
 97 |    * productQuantity:商品数量
 98 |    * 
99 | */ 100 | private Integer productQuantity; 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/SellerExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import com.imooc.sell.VO.ResultVO; 4 | import com.imooc.sell.config.prop.ProjectUrlProperties; 5 | import com.imooc.sell.exception.ResponseBankException; 6 | import com.imooc.sell.exception.SellException; 7 | import com.imooc.sell.exception.SellerAuthorizeException; 8 | import com.imooc.sell.utils.ResultVOUtil; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.web.bind.annotation.ControllerAdvice; 13 | import org.springframework.web.bind.annotation.ExceptionHandler; 14 | import org.springframework.web.bind.annotation.ResponseBody; 15 | import org.springframework.web.bind.annotation.ResponseStatus; 16 | import org.springframework.web.servlet.ModelAndView; 17 | 18 | /** 19 | * describe: 20 | * 21 | * @Author 王艳军 22 | * @Date 2017/12/18 17:41:05 23 | */ 24 | @ControllerAdvice 25 | public class SellerExceptionHandler { 26 | 27 | @Autowired 28 | private ProjectUrlProperties projectUrlConfig; 29 | /** 30 | * 拦截登录异常:未在客户端查询到token,通过token查询不到redis缓存里面的对应openid,则使用微信扫码登录用户直接跳转url: 31 | * http://potato369.natapp1.cc/sell/wechat/qrAuthorize?returnUrl=http://potato369.natapp1.cc/sell/seller/login 32 | */ 33 | @ExceptionHandler(value = SellerAuthorizeException.class) 34 | public ModelAndView handlerSellerAuthorizeException(){ 35 | return new ModelAndView("redirect:" 36 | .concat(projectUrlConfig.getDomainUrl() 37 | .concat(projectUrlConfig.getProjectName()) 38 | .concat(projectUrlConfig.getWechatOpenAuthorizeUrl()) 39 | .concat("?returnUrl=") 40 | .concat(projectUrlConfig.getDomainUrl()) 41 | .concat(projectUrlConfig.getProjectName()) 42 | .concat(projectUrlConfig.getLoginUrl()))); 43 | } 44 | 45 | @ResponseBody 46 | @ExceptionHandler(value = SellException.class) 47 | public ResultVO handlerSellerException(SellException e) { 48 | return ResultVOUtil.error(e.getCode(), e.getMessage()); 49 | } 50 | 51 | @ExceptionHandler(value = ResponseBankException.class) 52 | @ResponseStatus(code = HttpStatus.FORBIDDEN) 53 | public void handlerResponseBankException(){ 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/resources/templates/book/category/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../../common/header.ftl"> 3 | 4 |
5 | <#--边栏 sidebar--> 6 | <#include "../../common/nav.ftl"> 7 | <#--主体内容区域 content--> 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 | 24 |
25 |
26 | 27 | disabled="disabled"/> 28 |
29 |
30 | 31 | 35 |
36 | 37 | 38 |
39 |
40 |
41 |
42 |
43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/resources/templates/product/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 |
5 | <#--边栏 sidebar--> 6 | <#include "../common/nav.ftl"> 7 | <#--主体内容区域 content--> 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 | 24 |
25 |
26 | 27 | 29 | ${productInfo.productIcon} 30 | <#else> 31 | http://static.galileo.xiaojukeji.com/static/tms/seller_avatar_256px.jpg 32 | " alt="商品默认小图片"> 33 | 34 |
35 |
36 | 37 | 46 |
47 | 48 | 49 |
50 |
51 |
52 |
53 |
54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/impl/BuyerServiceImpl.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:BuyerServiceImpl.java.
5 | * Package Name:com.imooc.sell.service.impl.
6 | * Date:2017年12月12日下午10:39:25.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.service.impl; 11 | 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | 15 | import com.imooc.sell.dto.OrderDTO; 16 | import com.imooc.sell.enums.ResultEnum; 17 | import com.imooc.sell.exception.SellException; 18 | import com.imooc.sell.service.BuyerService; 19 | import com.imooc.sell.service.OrderService; 20 | 21 | import lombok.extern.slf4j.Slf4j; 22 | 23 | /** 24 | * ClassName: BuyerServiceImpl 25 | * Function: 26 | * Reason: 27 | * Date: 2017年12月12日 下午10:39:25 28 | * Desc: 29 | * @author 王艳军 30 | * @version 31 | * @since JDK 1.6 32 | */ 33 | @Service 34 | @Slf4j 35 | public class BuyerServiceImpl implements BuyerService { 36 | 37 | @Autowired 38 | private OrderService orderService; 39 | 40 | /* (non-Javadoc) 41 | * @see com.imooc.sell.service.BuyerService#findOrderOne(java.lang.String, java.lang.String) 42 | */ 43 | @Override 44 | public OrderDTO findOrderOne(String openid, String orderId) { 45 | return checkOrderOwner(openid,orderId); 46 | } 47 | 48 | /* (non-Javadoc) 49 | * @see com.imooc.sell.service.BuyerService#cancelOrder(java.lang.String, java.lang.String) 50 | */ 51 | @Override 52 | public OrderDTO cancelOrder(String openid, String orderId) { 53 | OrderDTO orderDTO = checkOrderOwner(openid, orderId); 54 | if (orderDTO == null) { 55 | log.error("【取消订单】查询不到该订单。orderId={}", orderId); 56 | throw new SellException(ResultEnum.ORDER_NOT_EXIST); 57 | } 58 | return orderService.cancel(orderDTO); 59 | } 60 | 61 | /** 62 | * 检查该订单的拥有者是否属于该用户 63 | * @param openid 64 | * @param orderId 65 | * @return 66 | */ 67 | private OrderDTO checkOrderOwner(String openid, String orderId){ 68 | OrderDTO orderDTO = orderService.findOne(orderId); 69 | if (orderDTO == null) { 70 | return null; 71 | } 72 | if (!orderDTO.getBuyerOpenid().equalsIgnoreCase(openid)) { 73 | log.error("【查询订单】订单的openid不一致。openid={},orderId={}", openid, orderId); 74 | throw new SellException(ResultEnum.ORDER_OWNER_ERROR); 75 | } 76 | return orderDTO; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/VO/BookInfoVO.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.VO; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | 6 | /** 7 | *
  8 |  * @PackageName com.imooc.sell.VO
  9 |  * @ClassName BookInfoVO
 10 |  * @Desc 书籍信息数据
 11 |  * @WebSite https://www.potato369.com
 12 |  * @Author 王艳军
 13 |  * @Date 2018/11/14 17:15
 14 |  * @CreateBy IntellJ IDEA 2018.2.4
 15 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
 16 |  * 
17 | */ 18 | @Data 19 | public class BookInfoVO { 20 | 21 | /** 22 | * id:此书在本书城的编号 23 | */ 24 | @JsonProperty(value = "id") 25 | private Integer id; 26 | 27 | /** 28 | * fileName:书名 29 | */ 30 | @JsonProperty(value = "fileName") 31 | private String fileName; 32 | 33 | /** 34 | * cover:书封面图片地址 35 | */ 36 | @JsonProperty(value = "cover") 37 | private String cover; 38 | 39 | /** 40 | * title:标题 41 | */ 42 | @JsonProperty(value = "title") 43 | private String title; 44 | 45 | /** 46 | * author:作者 47 | */ 48 | @JsonProperty(value = "author") 49 | private String author; 50 | 51 | /** 52 | * publisher:出版社 53 | */ 54 | @JsonProperty(value = "publisher") 55 | private String publisher; 56 | 57 | /** 58 | * bookId:书编号唯一 59 | */ 60 | @JsonProperty(value = "bookId") 61 | private String bookId; 62 | 63 | /** 64 | * categoryTypeId:分类id 65 | */ 66 | @JsonProperty(value = "category") 67 | private Integer categoryTypeId; 68 | 69 | /** 70 | * categoryText:分类名称 71 | */ 72 | @JsonProperty(value = "categoryText") 73 | private String categoryText; 74 | 75 | /** 76 | * language:语言 77 | */ 78 | @JsonProperty(value = "language") 79 | private String language; 80 | 81 | /** 82 | * selected:是否收藏 83 | */ 84 | @JsonProperty(value = "selected") 85 | private Boolean selected; 86 | 87 | /** 88 | * author:是否私阅 89 | */ 90 | @JsonProperty(value = "private") 91 | private Boolean privated; 92 | 93 | /** 94 | * cache:离线缓存 95 | */ 96 | @JsonProperty(value = "cache") 97 | private Boolean cache; 98 | 99 | /** 100 | * haveRead:已经阅读数 101 | */ 102 | @JsonProperty(value = "haveRead") 103 | private Integer haveRead; 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/config/prop/WechatMpProperties.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.config.prop; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import java.util.Map; 10 | 11 | /** 12 | * describe:微信相关配置属性 13 | * 14 | * @author 王艳军 15 | * @date 2017/12/13 17:06:17 16 | */ 17 | @Data 18 | @Builder 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @ConfigurationProperties(prefix = "wechat.mp") 22 | public class WechatMpProperties { 23 | 24 | /** 25 | *
 26 |    * @serialField 1、mpAppId:微信公众平台appid
 27 |    * 
28 | */ 29 | private String mpAppId; 30 | 31 | /** 32 | *
 33 |    * @serialField 2、mpAppSecret:微信公众平台密钥
 34 |    * 
35 | */ 36 | private String mpAppSecret; 37 | 38 | /** 39 | *
 40 |    * @serialField 3、openAppid:微信开放平台appid
 41 |    * 
42 | */ 43 | private String openAppid; 44 | 45 | /** 46 | *
 47 |    * @serialField 4、openAppSecret:微信开放平台密钥
 48 |    * 
49 | */ 50 | private String openAppSecret; 51 | 52 | /** 53 | *
 54 |    * @serialField 5、mchId:微信商户号
 55 |    * 
56 | */ 57 | private String mchId; 58 | 59 | /** 60 | *
 61 |    * @serialField 6、mchKey:微信商户密钥
 62 |    * 
63 | */ 64 | private String mchKey; 65 | 66 | /** 67 | *
 68 |    * @serialField 7、subAppId:服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
 69 |    * 
70 | */ 71 | private String subAppId; 72 | 73 | /** 74 | *
 75 |    * @serialField 8、subMchId:服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
 76 |    * 
77 | */ 78 | private String subMchId; 79 | 80 | /** 81 | *
 82 |    * @serialField 9、keyPath:微信商户证书路径
 83 |    * 
84 | */ 85 | private String keyPath; 86 | 87 | /** 88 | *
 89 |    * @serialField 10、notifyUrl:微信支付异步通知地址URL
 90 |    * 
91 | */ 92 | private String notifyUrl; 93 | 94 | /** 95 | *
 96 |    * @serialField 11、微信模板id
 97 |    * 
98 | */ 99 | private Map templateId; 100 | 101 | /** 102 | *
103 |    * @serialField 12、 公众平台服务器验证token
104 |    * 
105 | */ 106 | private String token; 107 | 108 | /** 109 | *
110 |    * @serialField 13、 公众平台消息加密密钥
111 |    * 
112 | */ 113 | private String aesKey; 114 | } 115 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/repository/OrderDetailRepositoryTest.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderDetailRepositoryTest.java.
5 | * Package Name:com.imooc.sell.repository.
6 | * Date:2017年12月11日下午4:22:55.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.repository; 11 | 12 | import static org.junit.Assert.assertNotEquals; 13 | import static org.junit.Assert.assertNotNull; 14 | 15 | import java.math.BigDecimal; 16 | import java.util.List; 17 | 18 | import com.imooc.sell.SellApplication; 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.boot.test.context.SpringBootTest; 23 | import org.springframework.test.annotation.Rollback; 24 | import org.springframework.test.context.junit4.SpringRunner; 25 | import org.springframework.transaction.annotation.Transactional; 26 | 27 | import com.imooc.sell.dataobject.OrderDetail; 28 | import com.imooc.sell.utils.UUIDUtil; 29 | 30 | /** 31 | * ClassName: OrderDetailRepositoryTest.
32 | * Function: ADD FUNCTION.
33 | * Reason: ADD REASON(可选).
34 | * Date: 2017年12月11日 下午4:22:55.
35 | * Desc: ADD DESC(可选).
36 | * @author 王艳军 37 | * @version 38 | * @since JDK 1.6 39 | */ 40 | @Rollback 41 | @Transactional 42 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 43 | @RunWith(SpringRunner.class) 44 | public class OrderDetailRepositoryTest { 45 | 46 | @Autowired 47 | private OrderDetailRepository orderDetailRepository; 48 | 49 | @Test 50 | public void saveOneTest(){ 51 | OrderDetail orderDetail = new OrderDetail(); 52 | orderDetail.setDetailId(UUIDUtil.gen32UUID()); 53 | orderDetail.setOrderId("41bd5932c2e748f388b672a8f5e2984c"); 54 | orderDetail.setProductId("bd34d70c13c244b08907a753ef11a2ad"); 55 | orderDetail.setProductIcon("http://www.potato369.com/upload/images/fznr.png"); 56 | orderDetail.setProductName("腐竹牛腩饭"); 57 | orderDetail.setProductQuantity(2); 58 | orderDetail.setProductPrice(new BigDecimal(51.00)); 59 | OrderDetail result = orderDetailRepository.save(orderDetail); 60 | assertNotNull(result); 61 | } 62 | 63 | @Test 64 | public void findByOrderIdTest(){ 65 | List orderDetailList = orderDetailRepository.findByOrderId("41bd5932c2e748f388b672a8f5e2984c"); 66 | assertNotEquals(0, orderDetailList.size()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/CookieUtil.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.utils; 2 | 3 | import com.imooc.sell.constant.CookieConstant; 4 | import com.imooc.sell.dto.CartDTO; 5 | 6 | import javax.servlet.http.Cookie; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * @Author 王艳军 14 | * @Date 2017-12-17 16:22 15 | */ 16 | public class CookieUtil { 17 | 18 | /** 19 | * 设置保存Cookie到客户端浏览器 20 | * @param response 21 | * @param name 22 | * @param value 23 | * @param maxAge 24 | */ 25 | public static void set(HttpServletResponse response, String name, String value, Integer maxAge){ 26 | Cookie cookie = new Cookie(name, value); 27 | cookie.setPath("/"); 28 | cookie.setMaxAge(maxAge); 29 | response.addCookie(cookie); 30 | } 31 | /** 32 | * 设置CartDTO购物车对象信息保存Cookie到客户端浏览器 33 | * @param response 34 | * @param cartDTO 35 | * @param maxAge 36 | */ 37 | public static void set(HttpServletResponse response, CartDTO cartDTO, Integer maxAge){ 38 | Cookie cookie1 = new Cookie(CookieConstant.Cart_Cookie+"productId", cartDTO.getProductId()); 39 | Cookie cookie2 = new Cookie(CookieConstant.Cart_Cookie+"quantity", String.valueOf(cartDTO.getProductQuantity())); 40 | cookie1.setPath("/"); 41 | cookie1.setMaxAge(maxAge); 42 | response.addCookie(cookie1); 43 | 44 | cookie2.setPath("/"); 45 | cookie2.setMaxAge(maxAge); 46 | response.addCookie(cookie2); 47 | } 48 | 49 | /** 50 | * 从客户端浏览器获取Cookie 51 | * @param request 52 | * @param name 53 | */ 54 | public static Cookie get(HttpServletRequest request, String name){ 55 | Map cookieMap = readCookieMap(request); 56 | if (cookieMap.containsKey(name)){ 57 | return cookieMap.get(name); 58 | } else { 59 | return null; 60 | } 61 | } 62 | 63 | /** 64 | * 从客户端浏览器遍历cookie,将cookie封装为map 65 | * @param request 66 | * @return 67 | */ 68 | private static Map readCookieMap(HttpServletRequest request){ 69 | Map cookieMap = new HashMap(); 70 | Cookie[] cookies = request.getCookies(); 71 | if(cookies != null && cookies.length >0){ 72 | for (Cookie cookie:cookies){ 73 | cookieMap.put(cookie.getName(), cookie); 74 | } 75 | } 76 | return cookieMap; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/controller/MyOrderController.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.controller; 2 | 3 | import com.imooc.sell.dto.OrderDTO; 4 | import com.imooc.sell.enums.ResultEnum; 5 | import com.imooc.sell.exception.SellException; 6 | import com.imooc.sell.service.OrderService; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.data.domain.PageRequest; 11 | import org.springframework.data.domain.Sort; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.util.StringUtils; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | import org.springframework.web.servlet.ModelAndView; 17 | 18 | import java.util.Map; 19 | 20 | /** 21 | *
22 |  * @PackageName com.imooc.sell.controller
23 |  * @ClassName MyOrderController
24 |  * @Desc 我的订单信息列表
25 |  * @WebSite https://www.potato369.com
26 |  * @Author 王艳军
27 |  * @Date 2018/10/11 11:54
28 |  * @CreateBy IntellJ IDEA 2018.2.4
29 |  * @Copyright Copyright (c) 2016 ~ 2020 版权所有 (C) 土豆互联科技(深圳)有限公司 https://www.potato369.com All Rights Reserved。
30 |  * 
31 | */ 32 | @Slf4j 33 | @Controller 34 | @RequestMapping(value = "/my/order") 35 | public class MyOrderController { 36 | 37 | @Autowired 38 | private OrderService orderService; 39 | 40 | @RequestMapping(value = "/maList") 41 | public ModelAndView findMaList(@RequestParam(name = "openid", required = true) String openid, 42 | @RequestParam(name = "page", required = true, defaultValue = "0") Integer page, 43 | @RequestParam(name = "size", required = true, defaultValue = "10") Integer size, 44 | Map map) { 45 | if (StringUtils.isEmpty(openid)) { 46 | log.error("【查询订单列表】openid为空"); 47 | throw new SellException(ResultEnum.PARAM_ERROR); 48 | } 49 | Sort sort = new Sort(Sort.Direction.DESC, "createTime"); 50 | PageRequest pageRequest = new PageRequest(page, size, sort); 51 | Page orderDTOPage = null; 52 | try { 53 | orderDTOPage = orderService.findList(openid, pageRequest); 54 | } catch (Exception e) { 55 | log.error("【查询订单列表】 失败,出现错误,或者是数据库链接错误"); 56 | throw new SellException(ResultEnum.OTHER_ERROR); 57 | } 58 | map.put("orderDTOPage", orderDTOPage); 59 | return new ModelAndView("order/malist", map); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/nav.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/repository/OrderMasterRepositoryTest.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderMasterRepositoryTest.java.
5 | * Package Name:com.imooc.sell.repository.
6 | * Date:2017年12月11日下午3:55:30.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.repository; 11 | 12 | import static org.junit.Assert.*; 13 | 14 | import java.math.BigDecimal; 15 | 16 | import com.imooc.sell.SellApplication; 17 | import org.junit.Test; 18 | import org.junit.runner.RunWith; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.boot.test.context.SpringBootTest; 21 | import org.springframework.data.domain.Page; 22 | import org.springframework.data.domain.PageRequest; 23 | import org.springframework.test.annotation.Rollback; 24 | import org.springframework.test.context.junit4.SpringRunner; 25 | import org.springframework.transaction.annotation.Transactional; 26 | 27 | import com.imooc.sell.dataobject.OrderMaster; 28 | import com.imooc.sell.utils.UUIDUtil; 29 | 30 | /** 31 | * ClassName: OrderMasterRepositoryTest.
32 | * Function: ADD FUNCTION.
33 | * Reason: ADD REASON(可选).
34 | * Date: 2017年12月11日 下午3:55:30.
35 | * Desc: ADD DESC(可选).
36 | * @author 王艳军 37 | * @version 38 | * @since JDK 1.6 39 | */ 40 | @Rollback 41 | @Transactional 42 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 43 | @RunWith(SpringRunner.class) 44 | public class OrderMasterRepositoryTest { 45 | 46 | @Autowired 47 | private OrderMasterRepository orderMasterRepository; 48 | 49 | private static final String OPENID = "1101202assd"; 50 | 51 | @Test 52 | public void saveTest(){ 53 | OrderMaster orderMaster = new OrderMaster(); 54 | orderMaster.setOrderId(UUIDUtil.genTimstampUUID()); 55 | orderMaster.setBuyerName("廖师兄"); 56 | orderMaster.setBuyerPhone("18575586895"); 57 | orderMaster.setBuyerAddress("慕课网"); 58 | orderMaster.setBuyerOpenid(OPENID); 59 | orderMaster.setOrderAmount(new BigDecimal(39.00)); 60 | OrderMaster result = orderMasterRepository.save(orderMaster); 61 | assertNotNull(result); 62 | } 63 | 64 | @Test 65 | public void findByBuyerOpenidTest(){ 66 | PageRequest pageRequest = new PageRequest(1, 6); 67 | Page result = orderMasterRepository.findByBuyerOpenid(OPENID, pageRequest); 68 | System.out.println(result.getTotalElements()); 69 | assertNotEquals(0, result.getTotalElements()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/impl/PayH5ServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service.impl; 2 | 3 | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; 4 | import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; 5 | import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; 6 | import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; 7 | import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; 8 | import com.github.binarywang.wxpay.exception.WxPayException; 9 | import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; 10 | import com.imooc.sell.dto.OrderDTO; 11 | import com.imooc.sell.service.PayH5Service; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | /** 15 | * Describe: 16 | * 17 | * @Author 王艳军 18 | * @Date 2017/12/26 16:33:37 19 | */ 20 | @Service 21 | public class PayH5ServiceImpl implements PayH5Service { 22 | 23 | @Autowired 24 | private WxPayServiceImpl wxPayService; 25 | 26 | /** 27 | * 微信H5支付订单 28 | * 29 | * @param orderDTO 30 | * @return WxPayUnifiedOrderResult 31 | * @throws WxPayException 32 | */ 33 | @Override 34 | public WxPayUnifiedOrderResult create(OrderDTO orderDTO) throws WxPayException { 35 | WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() 36 | .fingerprint(orderDTO.getFingerPrint()) 37 | .body("土豆互联科技(深圳)有限公司--微信点餐") 38 | .spbillCreateIp(orderDTO.getCip()) 39 | .openid(orderDTO.getBuyerOpenid()) 40 | .build(); 41 | request.setOutTradeNo(orderDTO.getOrderId()); 42 | request.setTotalFee(orderDTO.getOrderAmount().intValue() * 100); 43 | WxPayUnifiedOrderResult wxPayUnifiedOrderResult = wxPayService.unifiedOrder(request); 44 | return wxPayUnifiedOrderResult; 45 | } 46 | 47 | /** 48 | * 微信H5支付异步通知结果 49 | * 50 | * @param notifyData 51 | * @return WxPayOrderNotifyResult 52 | * @throws WxPayException 53 | */ 54 | @Override 55 | public WxPayOrderNotifyResult notify(String notifyData) throws WxPayException { 56 | return wxPayService.parseOrderNotifyResult(notifyData); 57 | } 58 | 59 | /** 60 | * 微信H5支付退款 61 | * 62 | * @param orderDTO 63 | * @return WxPayRefundResult 64 | * @throws WxPayException 65 | */ 66 | @Override 67 | public WxPayRefundResult refund(OrderDTO orderDTO) throws WxPayException { 68 | WxPayRefundRequest request = new WxPayRefundRequest(); 69 | return wxPayService.refund(request); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/aspect/HttpAspect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell.
3 | * File Name:HttpAspect.java.
4 | * Package Name:com.imooc.sell.aspect.
5 | * Date:2018年1月3日下午5:33:28.
6 | * Copyright (c) 2018, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
7 | */ 8 | package com.imooc.sell.aspect; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | import com.imooc.sell.utils.WwwUtil; 13 | import org.aspectj.lang.JoinPoint; 14 | import org.aspectj.lang.annotation.After; 15 | import org.aspectj.lang.annotation.AfterReturning; 16 | import org.aspectj.lang.annotation.Aspect; 17 | import org.aspectj.lang.annotation.Before; 18 | import org.aspectj.lang.annotation.Pointcut; 19 | import org.springframework.stereotype.Component; 20 | import org.springframework.web.context.request.RequestContextHolder; 21 | import org.springframework.web.context.request.ServletRequestAttributes; 22 | import lombok.extern.slf4j.Slf4j; 23 | /** 24 | *
25 |   * @className:HttpAspect
26 |   * @function:ADD FUNCTION
27 |   * @reason:Http请求拦截切面对象
28 |   * @date:2018年1月3日 下午5:33:28
29 |   * @desc:ADD DESC(可选)
30 |   * @author 王艳军
31 |   * @version 1.0
32 |   * @since JDK 1.6
33 |   * 
34 | */ 35 | @Aspect 36 | @Component 37 | @Slf4j 38 | public class HttpAspect { 39 | 40 | @Pointcut(value = "execution(public * com.imooc.sell.controller.*.*(..))") 41 | private void log() { 42 | } 43 | 44 | @Before(value = "log()") 45 | public void doBefore(JoinPoint joinpoint) { 46 | log.info("【拦截http请求】doBefore:拦截http请求日志"); 47 | ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 48 | HttpServletRequest request = requestAttributes.getRequest(); 49 | // url:请求URL 50 | log.info("【拦截http请求】url={}", request.getRequestURL()); 51 | // method:请求方式 52 | log.info("【拦截http请求】method={}", request.getMethod()); 53 | // ip:请求IP地址 54 | log.info("【拦截http请求】代理ip={}", WwwUtil.getIpAddr1(request)); 55 | // 客户端真实ip 56 | log.info("【拦截http请求】真实ip={}", WwwUtil.getIpAddr4(request)); 57 | // class method:请求类的方法 58 | log.info("【拦截http请求】class method name={}", joinpoint.getSignature().getDeclaringTypeName() + "." + joinpoint.getSignature().getName() + "()"); 59 | // args:请求参数 60 | for (int i = 0; i < joinpoint.getArgs().length; i++) { 61 | log.info("【拦截http请求】 args[" + i + "]={}", joinpoint.getArgs()[i]); 62 | } 63 | } 64 | 65 | @After(value = "log()") 66 | public void doAfter() { 67 | log.info("【拦截http请求】doAfter: 拦截http请求日志"); 68 | } 69 | 70 | @AfterReturning(returning = "object", pointcut = "log()") 71 | public void doAfterReturning(Object object) { 72 | log.info("【拦截http请求】doAfterReturning: 拦截http请求返回response={}", object); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/service/impl/CategoryServiceImplTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:CategoryServiceImplTest.java 4 | * Package Name:com.imooc.sell.service.impl 5 | * Date:2017年12月8日下午11:08:13 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | 10 | package com.imooc.sell.service.impl; 11 | 12 | import static org.junit.Assert.*; 13 | 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | import com.imooc.sell.SellApplication; 18 | import com.imooc.sell.enums.CategoryDeletedEnum; 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.boot.test.context.SpringBootTest; 23 | import org.springframework.test.annotation.Rollback; 24 | import org.springframework.test.context.junit4.SpringRunner; 25 | 26 | import com.imooc.sell.dataobject.ProductCategory; 27 | import org.springframework.transaction.annotation.Transactional; 28 | 29 | /** 30 | * ClassName:CategoryServiceImplTest
31 | * Function: TODO ADD FUNCTION.
32 | * Reason: TODO ADD REASON.
33 | * Date: 2017年12月8日 下午11:08:13
34 | * @author admin 35 | * @version 36 | * @since JDK 1.6 37 | * @see 38 | */ 39 | @Rollback 40 | @Transactional 41 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 42 | @RunWith(SpringRunner.class) 43 | public class CategoryServiceImplTest { 44 | 45 | @Autowired 46 | private CategoryServiceImpl categoryService; 47 | 48 | @Test 49 | public void findOneTest() { 50 | ProductCategory category = categoryService.findOne(1); 51 | // assertNotNull(category); 52 | // assertEquals(new Integer(1), category.getCategoryId()); 53 | assertEquals(new Integer(1), category.getCategoryId()); 54 | // assertNotNull(category); 55 | } 56 | @Test 57 | public void findAllTest() { 58 | List pCategories = categoryService.findAll(); 59 | assertNotEquals(0, pCategories.size()); 60 | } 61 | @Test 62 | public void findByCategoryTypeInTest() { 63 | List productCategories = 64 | categoryService.findByCategoryTypeIn(Arrays.asList(1,2,22,222,3,22223333,22233322,4)); 65 | assertNotEquals(0, productCategories.size()); 66 | } 67 | @Test 68 | public void saveTest() { 69 | ProductCategory productCategory = new ProductCategory("少妇不最爱",111); 70 | ProductCategory result = categoryService.save(productCategory); 71 | assertNotNull(result); 72 | } 73 | @Test 74 | public void deleteOneTest() throws Exception{ 75 | ProductCategory productCategory = categoryService.deleteOne(54); 76 | assertEquals(productCategory.getIsDeleted(), CategoryDeletedEnum.DELETE); 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /doc/访问路径.txt: -------------------------------------------------------------------------------- 1 | 产品信息列表:https://potato369.mynatapp.cc/sell/buyer/product/list 2 | 订单信息列表:https://potato369.mynatapp.cc/sell/buyer/order/list?openid=110110110 3 | 微信授权回调:https://potato369.mynatapp.cc/sell/weixin/auth 4 | 5 | 授权地址: 6 | https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx53762126dcb961f9&redirect_uri=https://potato369.mynatapp.cc/sell/weixin/auth&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect 7 | https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx53762126dcb961f9&redirect\_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4\_2030\_5\_1194\_60&response\_type=code&scope=snsapi\_base&state=123#wechat\_redirect 8 | scope 9 | 10 | "access_token":"4_3SAqkiP_K5IPz3jzg1H0f9pensf2LaulSNRZRuUR2vSxfn_Yal7sE6Xzl0GxExWMIGikluFpmyWw-fW4CM_VBTg2B6JSAu3EgaBmwEKMjyM","expires_in":7200,"refresh_token":"4_S9qpC0IcE6GqlhBxtg55ufhUdtKsFI030hHkCtWrX2a2dJW2-vve5jyztHGfUDLt6EZGWOs59wAexB-2SIKDqBTF1mphF3-Tq4Jb1Tn8Xzg","openid":"oSkiNv4fBXYxidv0wU_U0UDHNP4M","scope":"snsapi_userinfo" 11 | 12 | 启动natapp内网穿透工具:natapp.exe -authtoken=99f7af6e31464c91 13 | 14 | Win10系统hosts文件路径:C:/WINDOWS/system32/drivers/etc/hosts 15 | Linux/Uinux系统hosts文件路径:/etc/hosts 16 | 17 | 买家订单列表路径:http://sell.com/sell/seller/order/list 18 | 卖家后台管理系统路径:https://potato369.mynatapp.cc/sell/seller/product/list 19 | 20 | https://potato369.mynatapp.cc/sell/seller/order/list?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 21 | 22 | http://127.0.0.1:8080/sell/seller/order/list?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 23 | 24 | 后台登录地址Url: 25 | https://potato369.mynatapp.cc/sell/seller/login?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 26 | https://www.potato369.com/sell/seller/login?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 27 | https://www.potato369.com/sell/seller/product/list?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 28 | http://www.potato369.com:8080/sell/seller/login?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 29 | https://www.potato369.com/sell/seller/login?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 30 | http://www.potato369.com:8080/sell/seller/order/list?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 31 | 32 | http://127.0.0.1:8080/sell/seller/login?openid=oSkiNv4fBXYxidv0wU_U0UDHNP4M 33 | 34 | http://blog.csdn.net/LPFSuperMan/article/details/78287265 35 | 36 | http://blog.csdn.net/opengl_es/article/details/47399317 37 | 38 | IntelliJ IDEA注册地址:http://idea.lanyus.com 39 | 40 | IntelliJ IDEA常用快捷键文档地址:https://www.cnblogs.com/zhangpengshou/p/5366413.html 41 | 42 | 微信支付wiki文档地址:https://pay.weixin.qq.com/wiki/doc/api/index.html 43 | 44 | 微信相关第三方sdk路径:https://github.com/Wechat-Group/weixin-java-tools 45 | 46 | 微信公众接口测试号申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login&token=&lang=zh_CN 47 | 48 | 访问地址:https://potato369.mynatapp.cc/sell/wechat/authorize?returnUrl=https://www.potato369.com 49 | 50 | 打包命令: 51 | 项目发布需要把 WebSocketConfig类注释 52 | mvn clean package -Dmaven.test.skip=true -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/impl/SecKillServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service.impl; 2 | 3 | import com.imooc.sell.exception.SellException; 4 | import com.imooc.sell.service.RedisLock; 5 | import com.imooc.sell.service.SecKillService; 6 | import com.imooc.sell.utils.UUIDUtil; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | import java.util.Map; 10 | import java.util.HashMap; 11 | 12 | /** 13 | * Describe: 14 | * 15 | * @Author 王艳军 16 | * @Date 2017/12/20 11:13:18 17 | */ 18 | @Service 19 | public class SecKillServiceImpl implements SecKillService { 20 | 21 | private static final int TIMEOUT = 10 * 1000; //超时时间 10s 22 | 23 | @Autowired 24 | private RedisLock redisLock; 25 | 26 | /** 27 | * 国庆活动,皮蛋粥特价,限量100000份 28 | */ 29 | static Map products; 30 | static Map stock; 31 | static Map orders; 32 | static 33 | { 34 | /** 35 | * 模拟多个表,商品信息表,库存表,秒杀成功订单表 36 | */ 37 | products = new HashMap(); 38 | stock = new HashMap(); 39 | orders = new HashMap(); 40 | products.put("123456", 100000); 41 | stock.put("123456", 100000); 42 | } 43 | 44 | private String queryMap(String productId) 45 | { 46 | return "国庆活动,皮蛋粥特价,限量份" 47 | + products.get(productId) 48 | +" 还剩:" + stock.get(productId)+" 份" 49 | +" 该商品成功下单用户数目:" 50 | + orders.size() +" 人" ; 51 | } 52 | 53 | @Override 54 | public String querySecKillProductInfo(String productId) 55 | { 56 | return this.queryMap(productId); 57 | } 58 | 59 | @Override 60 | public synchronized void orderProductMockDiffUser(String productId) 61 | { 62 | //加锁 63 | long time = System.currentTimeMillis() + TIMEOUT; 64 | if (!redisLock.lock(productId, String.valueOf(time))) { 65 | throw new SellException(101, "哎呦喂,人也太多了,换个姿势再试试~~~~~"); 66 | } 67 | //1.查询该商品库存,为0则活动结束。 68 | int stockNum = stock.get(productId); 69 | if(stockNum == 0) { 70 | throw new SellException(100, "活动已经结束"); 71 | } else { 72 | //2.下单(模拟不同用户openid不同) 73 | orders.put(UUIDUtil.gen32UUID(), productId); 74 | //3.减库存 75 | stockNum = stockNum - 1; 76 | try { 77 | Thread.sleep(100); 78 | } catch (InterruptedException e) { 79 | e.printStackTrace(); 80 | } 81 | stock.put(productId,stockNum); 82 | } 83 | //解锁 84 | redisLock.unlock(productId, String.valueOf(time)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dataobject/ProductCategory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:ProductCategory.java 4 | * Package Name:com.imooc.sell.dataobject 5 | * Date:2017年12月8日上午12:14:26 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | 10 | package com.imooc.sell.dataobject; 11 | 12 | import java.io.Serializable; 13 | import java.util.Date; 14 | 15 | import javax.persistence.Column; 16 | import javax.persistence.Entity; 17 | import javax.persistence.GeneratedValue; 18 | import javax.persistence.Id; 19 | import javax.persistence.Table; 20 | 21 | import com.imooc.sell.enums.CategoryDeletedEnum; 22 | import lombok.AllArgsConstructor; 23 | import lombok.Builder; 24 | import lombok.Data; 25 | import org.hibernate.annotations.DynamicUpdate; 26 | 27 | /** 28 | *
 29 |  * @ClassName:ProductCategory
 30 |  * @Function:
 31 |  * @Reason:
 32 |  * @Date:2017年12月8日 上午12:14:26
 33 |  * @author: admin
 34 |  * @version: 1.0
 35 |  * @since: JDK 1.6
 36 |  * @see: 1.0
 37 |  * 
38 | */ 39 | @Data 40 | @Builder 41 | @DynamicUpdate 42 | @AllArgsConstructor 43 | @Entity(name = "ProductCategory") 44 | @Table(name = "product_category") 45 | public class ProductCategory implements Serializable { 46 | 47 | /** 48 | *@Fields serialVersionUID:序列号 49 | */ 50 | private static final long serialVersionUID = 3486046846836931032L; 51 | 52 | /** 53 | *@Fields categoryId:类目id,主键 54 | */ 55 | @Id 56 | @GeneratedValue 57 | @Column(name = "category_id", nullable = false, length = 11) 58 | private Integer categoryId; 59 | 60 | /** 61 | * categoryName:类目名称 62 | */ 63 | @Column(name = "category_name", nullable = false, length = 64) 64 | private String categoryName; 65 | 66 | /** 67 | *@Fields categoryType:类目编号 68 | */ 69 | @Column(name = "category_type", nullable = false, length = 11) 70 | private Integer categoryType; 71 | 72 | /** 73 | *@Fields isDeleted:类目是否删除,0-否;1-是,“默认:0-否” 74 | */ 75 | @Builder.Default 76 | @Column(name = "is_deleted", nullable = false, length = 3) 77 | private Integer isDeleted = CategoryDeletedEnum.NOT_DELETE.getCode(); 78 | 79 | /** 80 | *@Fields createTime:创建时间 81 | */ 82 | @Column(name = "create_time", nullable = false) 83 | private Date createTime; 84 | 85 | /** 86 | *@Fields updateTime:更新时间 87 | */ 88 | @Column(name = "update_time", nullable = false) 89 | private Date updateTime; 90 | 91 | public ProductCategory() { 92 | super(); 93 | } 94 | 95 | public ProductCategory(String categoryName, Integer categoryType) { 96 | super(); 97 | this.categoryName = categoryName; 98 | this.categoryType = categoryType; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/resources/static/css/pay.css: -------------------------------------------------------------------------------- 1 | @CHARSET "UTF-8"; 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | ul, ol { 8 | list-style: none; 9 | } 10 | 11 | .title { 12 | color: #ADADAD; 13 | font-size: 14px; 14 | font-weight: bold; 15 | padding: 8px 16px 5px 10px; 16 | } 17 | 18 | .hidden { 19 | display: none; 20 | } 21 | 22 | .new-btn-login-sp { 23 | border: 1px solid #D74C00; 24 | padding: 1px; 25 | display: inline-block; 26 | } 27 | 28 | .new-btn-login { 29 | background-color: transparent; 30 | background-image: url("../images/new-btn-fixed.png"); 31 | border: medium none; 32 | } 33 | 34 | .new-btn-login { 35 | background-position: 0 -198px; 36 | width: 82px; 37 | color: #FFFFFF; 38 | font-weight: bold; 39 | height: 28px; 40 | line-height: 28px; 41 | padding: 0 10px 3px; 42 | } 43 | 44 | .new-btn-login:hover { 45 | background-position: 0 -167px; 46 | width: 82px; 47 | color: #FFFFFF; 48 | font-weight: bold; 49 | height: 28px; 50 | line-height: 28px; 51 | padding: 0 10px 3px; 52 | } 53 | 54 | .bank-list { 55 | overflow: hidden; 56 | margin-top: 5px; 57 | } 58 | 59 | .bank-list li { 60 | float: left; 61 | width: 153px; 62 | margin-bottom: 5px; 63 | } 64 | 65 | #main { 66 | width: 750px; 67 | margin: 0 auto; 68 | font-size: 14px; 69 | font-family: '宋体'; 70 | } 71 | 72 | #logo { 73 | background-color: transparent; 74 | background-image: url("../images/new-btn-fixed.png"); 75 | border: medium none; 76 | background-position: 0 0; 77 | width: 166px; 78 | height: 35px; 79 | float: left; 80 | } 81 | 82 | .red-star { 83 | color: #f00; 84 | width: 10px; 85 | display: inline-block; 86 | } 87 | 88 | .null-star { 89 | color: #fff; 90 | } 91 | 92 | .content { 93 | margin-top: 5px; 94 | } 95 | 96 | .content dt { 97 | width: 160px; 98 | display: inline-block; 99 | text-align: right; 100 | float: left; 101 | } 102 | 103 | .content dd { 104 | margin-left: 100px; 105 | margin-bottom: 5px; 106 | } 107 | 108 | #foot { 109 | margin-top: 10px; 110 | } 111 | 112 | .foot-ul li { 113 | text-align: center; 114 | } 115 | 116 | .note-help { 117 | color: #999999; 118 | font-size: 12px; 119 | line-height: 130%; 120 | padding-left: 3px; 121 | } 122 | 123 | .cashier-nav { 124 | font-size: 14px; 125 | margin: 15px 0 10px; 126 | text-align: left; 127 | height: 30px; 128 | border-bottom: solid 2px #CFD2D7; 129 | } 130 | 131 | .cashier-nav ol li { 132 | float: left; 133 | } 134 | 135 | .cashier-nav li.current { 136 | color: #AB4400; 137 | font-weight: bold; 138 | } 139 | 140 | .cashier-nav li.last { 141 | clear: right; 142 | } 143 | 144 | .alipay_link { 145 | text-align: right; 146 | } 147 | 148 | .alipay_link a:link { 149 | text-decoration: none; 150 | color: #8D8D8D; 151 | } 152 | 153 | .alipay_link a:visited { 154 | text-decoration: none; 155 | color: #8D8D8D; 156 | } -------------------------------------------------------------------------------- /src/main/resources/static/css/precreate.css: -------------------------------------------------------------------------------- 1 | @CHARSET "UTF-8"; 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | ul, ol { 9 | list-style: none; 10 | } 11 | 12 | .title { 13 | color: #ADADAD; 14 | font-size: 14px; 15 | font-weight: bold; 16 | padding: 8px 16px 5px 10px; 17 | } 18 | 19 | .hidden { 20 | display: none; 21 | } 22 | 23 | .new-btn-login-sp { 24 | border: 1px solid #D74C00; 25 | padding: 1px; 26 | display: inline-block; 27 | } 28 | 29 | .new-btn-login { 30 | background-color: transparent; 31 | background-image: url("../images/new-btn-fixed.png"); 32 | border: medium none; 33 | } 34 | 35 | .new-btn-login { 36 | background-position: 0 -198px; 37 | width: 82px; 38 | color: #FFFFFF; 39 | font-weight: bold; 40 | height: 28px; 41 | line-height: 28px; 42 | padding: 0 10px 3px; 43 | } 44 | 45 | .new-btn-login:hover { 46 | background-position: 0 -167px; 47 | width: 82px; 48 | color: #FFFFFF; 49 | font-weight: bold; 50 | height: 28px; 51 | line-height: 28px; 52 | padding: 0 10px 3px; 53 | } 54 | 55 | .bank-list { 56 | overflow: hidden; 57 | margin-top: 5px; 58 | } 59 | 60 | .bank-list li { 61 | float: left; 62 | width: 153px; 63 | margin-bottom: 5px; 64 | } 65 | 66 | #main { 67 | width: 750px; 68 | margin: 0 auto; 69 | font-size: 14px; 70 | font-family: '宋体'; 71 | } 72 | 73 | #logo { 74 | background-color: transparent; 75 | background-image: url("../images/new-btn-fixed.png"); 76 | border: medium none; 77 | background-position: 0 0; 78 | width: 166px; 79 | height: 35px; 80 | float: left; 81 | } 82 | 83 | .red-star { 84 | color: #f00; 85 | width: 10px; 86 | display: inline-block; 87 | } 88 | 89 | .null-star { 90 | color: #fff; 91 | } 92 | 93 | .content { 94 | margin-top: 5px; 95 | } 96 | 97 | .content dt { 98 | width: 160px; 99 | display: inline-block; 100 | text-align: right; 101 | float: left; 102 | } 103 | 104 | .content dd { 105 | margin-left: 100px; 106 | margin-bottom: 5px; 107 | } 108 | 109 | #foot { 110 | margin-top: 10px; 111 | } 112 | 113 | .foot-ul li { 114 | text-align: center; 115 | } 116 | 117 | .note-help { 118 | color: #999999; 119 | font-size: 12px; 120 | line-height: 130%; 121 | padding-left: 3px; 122 | } 123 | 124 | .cashier-nav { 125 | font-size: 14px; 126 | margin: 15px 0 10px; 127 | text-align: left; 128 | height: 30px; 129 | border-bottom: solid 2px #CFD2D7; 130 | } 131 | 132 | .cashier-nav ol li { 133 | float: left; 134 | } 135 | 136 | .cashier-nav li.current { 137 | color: #AB4400; 138 | font-weight: bold; 139 | } 140 | 141 | .cashier-nav li.last { 142 | clear: right; 143 | } 144 | 145 | .alipay_link { 146 | text-align: right; 147 | } 148 | 149 | .alipay_link a:link { 150 | text-decoration: none; 151 | color: #8D8D8D; 152 | } 153 | 154 | .alipay_link a:visited { 155 | text-decoration: none; 156 | color: #8D8D8D; 157 | } -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/enums/ResultEnum.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:ResultEnum.java.
5 | * Package Name:com.imooc.sell.enums.
6 | * Date:2017年12月11日上午10:31:55.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.enums; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Getter; 14 | import lombok.NoArgsConstructor; 15 | 16 | /** 17 | * ClassName: ResultEnum.
18 | * Function: ADD FUNCTION.
19 | * Reason: 返回给前端的消息.
20 | * Date: 2017年12月11日 上午10:31:55.
21 | * Desc: ADD DESC(可选).
22 | * 23 | * @author 王艳军 24 | * @version 25 | * @since JDK 1.6 26 | */ 27 | @Getter 28 | @NoArgsConstructor 29 | @AllArgsConstructor 30 | public enum ResultEnum implements CodeEnum{ 31 | 32 | SUCCESS(0, "成功"), 33 | 34 | PARAM_ERROR(1, "参数不正确"), 35 | 36 | PRODUCT_NOT_EXIST(10, "商品不存在"), 37 | 38 | PRODUCT_STOCK_ERROR(11, "商品库存不正确"), 39 | 40 | ORDER_NOT_EXIST(12, "订单不存在"), 41 | 42 | ORDERDETAIL_NOT_EXIST(13, "订单详情不存在"), 43 | 44 | ORDER_STATUS_ERROR(14, "订单状态不正确"), 45 | 46 | ORDER_UPDATE_FAIL(15, "订单更新失败"), 47 | 48 | ORDER_DETAIL_EMPTY(16, "订单详情为空"), 49 | 50 | ORDER_PAY_STATUS_ERROR(17, "订单支付状态不正确"), 51 | 52 | CART_EMPTY(18, "购物车为空"), 53 | 54 | ORDER_OWNER_ERROR(19, "该订单不属于当前用户"), 55 | 56 | WECHAT_MP_ERROR(20, "微信公众账号方面错误"), 57 | 58 | WXPAY_NOTIFY_MONEY_VERIFY_ERROR(21, "微信支付异步通知金额校验不通过"), 59 | 60 | ORDER_CANCEL_SUCCESS(22, "订单取消成功"), 61 | 62 | ORDER_FINISH_SUCCESS(23, "订单完结成功"), 63 | 64 | PRODUCT_STATUS_ERROR(24, "商品状态不正确"), 65 | 66 | LOGIN_FAIL(25, "登录失败, 登录信息不正确"), 67 | 68 | LOGOUT_SUCCESS(26, "登出成功"), 69 | 70 | OTHER_ERROR(27, "其他系统错误"), 71 | 72 | PRODUCT_ON_SALE_SUCCESS(28, "商品上架成功"), 73 | 74 | PRODUCT_ON_SALE_FAIL(29, "商品上架失败"), 75 | 76 | PRODUCT_OFF_SALE_SUCCESS(30, "商品下架成功"), 77 | 78 | PRODUCT_OFF_SALE_FAIL(31, "商品下架失败"), 79 | 80 | PRODUCT_SAVE_SUCCESS(32, "新增商品成功"), 81 | 82 | PRODUCT_SAVE_FAIL(33, "新增商品失败"), 83 | 84 | PRODUCT_UPDATE_SUCCESS(34, "修改商品成功"), 85 | 86 | PRODUCT_UPDATE_FAIL(35, "修改商品失败"), 87 | 88 | PRODUCT_SAVE_OR_UPDATE_SUCCESS(36, "新增或者修改商品成功"), 89 | 90 | PRODUCT_SAVE_OR_UPDATE_FAIL(37, "新增或者修改商品失败"), 91 | 92 | CATEGORY_SAVE_OR_UPDATE_SUCCESS(38, "新增或者修改商品类目成功"), 93 | 94 | CATEGORY_SAVE_OR_UPDATE_FAIL(39, "新增或者修改商品类目失败"), 95 | 96 | CATEGORY_SAVE_SUCCESS(40, "新增商品类目成功"), 97 | 98 | CATEGORY_UPDATE_SUCCESS(41, "修改商品类目成功"), 99 | 100 | CATEGORY_NOT_EXIST(42, "商品类目不存在"), 101 | 102 | CATEGORY_NOT_DELETED(43, "此商品类目下存在一个或者多个商品信息,不允许删除此类目"), 103 | 104 | CATEGORY_WHETHER_OR_NOT_TO_DELETED_STATUS_ERROR(44, "此商品类目是否标记已删除状态已经是已标记为是删除状态"), 105 | 106 | ENCODING_UNSUPPORT_ERROR(45, "编码格式不支持错误"), 107 | 108 | MP_OTHER_ERROR(46, "微信公众平台其他方面错误"), 109 | 110 | ; 111 | 112 | private Integer code; 113 | 114 | private String message; 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/handler/SubscribeHandler.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.handler; 2 | 3 | import java.util.Map; 4 | 5 | import com.imooc.sell.builder.NewsBuilder; 6 | import com.imooc.sell.utils.JsonUtils; 7 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage; 8 | import org.springframework.stereotype.Component; 9 | 10 | import me.chanjar.weixin.common.error.WxErrorException; 11 | import me.chanjar.weixin.common.session.WxSessionManager; 12 | import me.chanjar.weixin.mp.api.WxMpService; 13 | import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; 14 | import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; 15 | import me.chanjar.weixin.mp.bean.result.WxMpUser; 16 | 17 | @Component 18 | public class SubscribeHandler extends AbstractHandler { 19 | 20 | /** 21 | * 一般处理 22 | * @param wxMessage 23 | * @param context 24 | * @param weixinService 25 | * @param sessionManager 26 | * @return 27 | * @throws WxErrorException 28 | */ 29 | @Override 30 | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, WxMpService weixinService, WxSessionManager sessionManager) throws WxErrorException { 31 | 32 | 33 | if (this.logger.isDebugEnabled()) { 34 | this.logger.info("【普通(搜索或者消息推送关注的)】新关注用户 OPENID: " + wxMessage.getFromUser()); 35 | } 36 | 37 | // 获取微信用户基本信息 38 | WxMpUser userWxInfo = weixinService.getUserService().userInfo(wxMessage.getFromUser(), null); 39 | if (this.logger.isDebugEnabled()) { 40 | this.logger.info("【新关注用户】 WxMpUser={}" + JsonUtils.toJson(userWxInfo)); 41 | } 42 | if (userWxInfo != null) { 43 | // 添加关注用户到本地数据库 44 | //userInfoService.add(WxMpUser2UserInfo(userWxInfo)); 45 | } 46 | 47 | WxMpXmlOutMessage responseResult = null; 48 | try { 49 | responseResult = handleSpecial(wxMessage); 50 | } catch (Exception e) { 51 | this.logger.error(e.getMessage(), e); 52 | } 53 | 54 | if (responseResult != null) { 55 | return responseResult; 56 | } 57 | 58 | try { 59 | NewsBuilder newsBuilder = new NewsBuilder(); 60 | WxMpXmlOutNewsMessage.Item item1 = new WxMpXmlOutNewsMessage.Item(); 61 | item1.setTitle("亲,终于等到您了!推荐几本热门小说,给您看看:"); 62 | item1.setDescription(""); 63 | item1.setUrl("https://www.potato369.com"); 64 | return newsBuilder.build("", wxMessage, weixinService); 65 | } catch (Exception e) { 66 | this.logger.error(e.getMessage(), e); 67 | } 68 | 69 | return null; 70 | } 71 | 72 | /** 73 | * 处理特殊请求,比如如果是扫码进来的,可以做相应处理 74 | * @param wxMessage 75 | * @return 76 | * @throws Exception 77 | */ 78 | private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) throws Exception { 79 | return null; 80 | } 81 | 82 | /** 83 | * 84 | * @param wxMpUser 85 | * @return 86 | */ 87 | /* 88 | private UserInfo WxMpUser2UserInfo(WxMpUser wxMpUser) { 89 | UserInfo userInfo = UserInfo.builder().build(); 90 | userInfo.setId(UUIDUtil.gen32UUID()); 91 | userInfo.setOpenId(wxMpUser.getOpenId()); 92 | userInfo.setNickName(wxMpUser.getNickname()); 93 | return userInfo; 94 | } 95 | */ 96 | } 97 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/dataobject/mapper/ProductCategoryMapperTest.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.dataobject.mapper; 2 | 3 | import com.imooc.sell.SellApplication; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.annotation.Rollback; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import com.imooc.sell.dataobject.ProductCategory; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | import static org.junit.Assert.*; 17 | 18 | @Rollback 19 | @Transactional 20 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 21 | @RunWith(SpringRunner.class) 22 | public class ProductCategoryMapperTest { 23 | 24 | @Autowired 25 | private ProductCategoryMapper productCategoryMapper; 26 | 27 | @Test 28 | public void insertByMapTest() { 29 | Map map = new HashMap(); 30 | map.put("category_name", "精美快餐"); 31 | map.put("category_type", 100); 32 | int result = productCategoryMapper.insertByMap(map); 33 | assertEquals(1, result); 34 | } 35 | 36 | @Test 37 | public void insertByMapTest1() { 38 | Map map = new HashMap(); 39 | map.put("category_name", "美味快餐"); 40 | map.put("category_type", 300); 41 | int result = productCategoryMapper.insertByMap(map); 42 | assertEquals(1, result); 43 | } 44 | 45 | @Test 46 | public void insertByObjectTest() { 47 | ProductCategory productCategory = new ProductCategory("经典快餐", 200); 48 | int result = productCategoryMapper.insertByObject(productCategory); 49 | assertEquals(1, result); 50 | } 51 | 52 | @Test 53 | public void findByCategoryTypeTest() { 54 | ProductCategory result = productCategoryMapper.findByCategoryType(100); 55 | assertNotNull(result); 56 | } 57 | 58 | @Test 59 | public void findByCategoryNameTest() { 60 | List result = productCategoryMapper.findByCategoryName("师兄最不爱"); 61 | assertNotEquals(0, result.size()); 62 | } 63 | 64 | @Test 65 | public void updateByCategoryTypeTest() { 66 | int result = productCategoryMapper.updateByCategoryType("师兄最不爱的分类", 101); 67 | assertEquals(1, result); 68 | } 69 | 70 | @Test 71 | public void updateByObjectTest() { 72 | ProductCategory productCategory = new ProductCategory("师兄最不爱", 101); 73 | int result = productCategoryMapper.updateByObject(productCategory); 74 | assertEquals(1, result); 75 | } 76 | 77 | @Test 78 | public void deleteByCategoryTypeTest() { 79 | int result = productCategoryMapper.deleteByCategoryType(10); 80 | assertEquals(1, result); 81 | } 82 | 83 | @Test 84 | public void selectByCategoryTypeTest() { 85 | ProductCategory result = productCategoryMapper.selectByCategoryType(100); 86 | assertNotNull(result); 87 | } 88 | } -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:MD5Util.java.
5 | * Package Name:com.imooc.sell.utils.
6 | * Date:2017年12月12日下午12:29:41.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.utils; 11 | 12 | import java.security.MessageDigest; 13 | 14 | /** 15 | * ClassName: MD5Util.
16 | * Function: ADD FUNCTION.
17 | * Reason: ADD REASON(可选).
18 | * Date: 2017年12月12日 下午12:29:41.
19 | * Desc: ADD DESC(可选).
20 | * 21 | * @author 王艳军 22 | * @version 23 | * @since JDK 1.6 24 | */ 25 | 26 | public class MD5Util { 27 | 28 | private static String byteArrayToHexString(byte b[]) { 29 | StringBuffer resultSb = new StringBuffer(); 30 | for (int i = 0; i < b.length; i++) { 31 | resultSb.append(byteToHexString(b[i])); 32 | } 33 | 34 | return resultSb.toString(); 35 | } 36 | 37 | private static String byteToHexString(byte b) { 38 | int n = b; 39 | if (n < 0) 40 | n += 256; 41 | int d1 = n / 16; 42 | int d2 = n % 16; 43 | return hexDigits[d1] + hexDigits[d2]; 44 | } 45 | 46 | public static String MD5Encode(String origin, String charsetname) { 47 | String resultString = null; 48 | try { 49 | resultString = new String(origin); 50 | MessageDigest md = MessageDigest.getInstance("MD5"); 51 | if (charsetname == null || "".equals(charsetname)) 52 | resultString = byteArrayToHexString(md.digest(resultString.getBytes())); 53 | else 54 | resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); 55 | } catch (Exception exception) { 56 | } 57 | return resultString; 58 | } 59 | 60 | private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; 61 | 62 | public static String md5(String str) { 63 | try { 64 | MessageDigest md = MessageDigest.getInstance("MD5"); 65 | md.update(str.getBytes()); 66 | byte b[] = md.digest(); 67 | int i; 68 | StringBuffer buf = new StringBuffer(""); 69 | for (int offset = 0; offset < b.length; offset++) { 70 | i = b[offset]; 71 | if (i < 0) { 72 | i += 256; 73 | } 74 | if (i < 16) { 75 | buf.append("0"); 76 | } 77 | buf.append(Integer.toHexString(i)); 78 | } 79 | str = buf.toString(); 80 | } catch (Exception e) { 81 | e.printStackTrace(); 82 | 83 | } 84 | return str; 85 | } 86 | 87 | public static void main(String[] args) { 88 | System.out.println(md5("31119@qq.com" + "123456")); 89 | System.out.println(MD5Encode("dbf49f5eb8254b8bc4cbb044f915e59d", null)); 90 | System.out.println(md5("mj1")); 91 | System.out.println(md5("123456!@#")); 92 | System.out.println(MD5Encode("b814b812ec4b322e19fae7bb78d4d330", null)); 93 | System.out.println(md5("123456!@#").equals("b814b812ec4b322e19fae7bb78d4d330")); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dataobject/OrderDetail.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderDetail.java.
5 | * Package Name:com.imooc.sell.dataobject.
6 | * Date:2017年12月11日下午3:35:56.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.dataobject; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | import org.hibernate.annotations.DynamicUpdate; 17 | import javax.persistence.Column; 18 | import javax.persistence.Entity; 19 | import javax.persistence.Id; 20 | import javax.persistence.Table; 21 | import java.io.Serializable; 22 | import java.math.BigDecimal; 23 | import java.util.Date; 24 | 25 | /** 26 | *
 27 |  * @className:OrderDetail
 28 |  * @function:
 29 |  * @reason:
 30 |  * @date:2017年12月11日 下午3:35:56
 31 |  * @desc:
 32 |  * @author 王艳军
 33 |  * @version 1.0
 34 |  * @since JDK 1.6
 35 |  * 
36 | */ 37 | @Data 38 | @Builder 39 | @DynamicUpdate 40 | @AllArgsConstructor 41 | @NoArgsConstructor 42 | @Entity(name = "OrderDetail") 43 | @Table(name = "order_detail") 44 | public class OrderDetail implements Serializable { 45 | 46 | /** 47 | *@Fields serialVersionUID:序列号 48 | */ 49 | private static final long serialVersionUID = -2922952467636846483L; 50 | 51 | /** 52 | *@Fields detailId:详情id,主键 53 | */ 54 | @Id 55 | @Column(name = "detail_id", nullable = false, length = 32) 56 | private String detailId; 57 | 58 | /** 59 | *@Fields orderId:订单id,外键 60 | */ 61 | @Column(name = "order_id", nullable = false, length = 32) 62 | private String orderId; 63 | 64 | /** 65 | *@Fields productId:产品id,外键 66 | */ 67 | @Column(name = "product_id", nullable = false, length = 32) 68 | private String productId; 69 | 70 | /** 71 | * productCategory:类目编号,外键 72 | */ 73 | @Column(name = "product_category", nullable = false, length = 11) 74 | private Integer productCategory; 75 | 76 | /** 77 | *@Fields buyerOpenid:买家微信openid,外键 78 | */ 79 | @Column(name = "buyer_openid", nullable = false, length = 64) 80 | private String buyerOpenid; 81 | 82 | /** 83 | *@Fields productName:产品名称 84 | */ 85 | @Column(name = "product_name", nullable = false, length = 64) 86 | private String productName; 87 | 88 | /** 89 | *@Fields productPrice:产品单价 90 | */ 91 | @Column(name = "product_price", nullable = false, length = 8) 92 | private BigDecimal productPrice; 93 | 94 | /** 95 | *@Fields productQuantity:购买数量 96 | */ 97 | @Column(name = "product_quantity", nullable = false, length = 11) 98 | private Integer productQuantity; 99 | 100 | /** 101 | *@Fields productIcon:产品小图 102 | */ 103 | @Column(name = "product_icon", nullable = true, length = 512) 104 | private String productIcon; 105 | 106 | /** 107 | *@Fields createTime:创建时间 108 | */ 109 | @Column(name = "create_time", nullable = false) 110 | private Date createTime; 111 | 112 | /** 113 | *@Fields updateTime:更新时间 114 | */ 115 | @Column(name = "update_time", nullable = false) 116 | private Date updateTime; 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dto/OrderDTO.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Project Name:sell.
4 | * File Name:OrderDTO.java.
5 | * Package Name:com.imooc.sell.dto.
6 | * Date:2017年12月11日下午5:03:28.
7 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
8 | */ 9 | 10 | package com.imooc.sell.dto; 11 | 12 | import java.math.BigDecimal; 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | import javax.persistence.Id; 17 | import javax.persistence.Transient; 18 | 19 | import com.fasterxml.jackson.annotation.JsonIgnore; 20 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 21 | import com.imooc.sell.dataobject.OrderDetail; 22 | import com.imooc.sell.enums.OrderStatusEnum; 23 | import com.imooc.sell.enums.PayStatusEnum; 24 | import com.imooc.sell.utils.EnumUtil; 25 | import com.imooc.sell.utils.serializer.Date2LongSerializer; 26 | 27 | import lombok.AllArgsConstructor; 28 | import lombok.Builder; 29 | import lombok.Data; 30 | import lombok.NoArgsConstructor; 31 | 32 | /** 33 | *
 34 |  * @ClassName:OrderDTO
 35 |  * @Function:
 36 |  * @Reason:
 37 |  * @Date: 2017年12月11日 下午5:03:28
 38 |  * @Desc:
 39 |  * @author 王艳军
 40 |  * @version
 41 |  * @since JDK 1.6
 42 |  * 
43 | */ 44 | @Data 45 | @Builder 46 | @NoArgsConstructor 47 | @AllArgsConstructor 48 | //@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) 49 | //@JsonInclude(JsonInclude.Include.NON_NULL) 50 | public class OrderDTO { 51 | 52 | /** 53 | * orderId:订单编号 54 | */ 55 | @Id 56 | private String orderId; 57 | 58 | /** 59 | * buyerName:买家名字 60 | */ 61 | private String buyerName; 62 | 63 | /** 64 | * buyerPhone:买家电话 65 | */ 66 | private String buyerPhone; 67 | 68 | /** 69 | * buyerAddress:买家地址 70 | */ 71 | private String buyerAddress; 72 | 73 | /** 74 | * buyerOpenid:买家微信openid 75 | */ 76 | private String buyerOpenid; 77 | 78 | /** 79 | * orderAmount:订单总金额 80 | */ 81 | private BigDecimal orderAmount; 82 | 83 | /** 84 | * orderStatus:订单状态,默认是新下单 85 | */ 86 | private Integer orderStatus; 87 | 88 | /** 89 | * payStatus:支付状态,默认0为未支付 90 | */ 91 | private Integer payStatus; 92 | 93 | /** 94 | * createTime:创建时间 95 | */ 96 | @JsonSerialize(using = Date2LongSerializer.class) 97 | private Date createTime; 98 | 99 | /** 100 | * updateTime:更新时间 101 | */ 102 | @JsonSerialize(using = Date2LongSerializer.class) 103 | private Date updateTime; 104 | 105 | @Transient 106 | private List orderDetailList; 107 | 108 | @JsonIgnore 109 | public OrderStatusEnum getOrderStatusEnum(){ 110 | return EnumUtil.getByCode(orderStatus, OrderStatusEnum.class); 111 | } 112 | 113 | @JsonIgnore 114 | public PayStatusEnum getPayStatusEnum(){ 115 | return EnumUtil.getByCode(payStatus, PayStatusEnum.class); 116 | } 117 | 118 | /** 119 | * cip:买家微信客户端ip 120 | */ 121 | private String cip; 122 | 123 | /** 124 | * fingerPrint:浏览器指纹 125 | */ 126 | private String fingerPrint; 127 | 128 | /** 129 | * jsonSceneInfo:json格式场景信息字符串 130 | */ 131 | private String jsonSceneInfo; 132 | } 133 | -------------------------------------------------------------------------------- /src/test/java/com/imooc/sell/repository/ProductInfoRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell 3 | * File Name:ProductInfoRepositoryTest.java 4 | * Package Name:com.imooc.sell.repository 5 | * Date:2017年12月8日下午11:56:50 6 | * Copyright (c) 2017,版权所有 (C) 2000-2016 卓望数码技术(深圳)有限公司 www.aspirecn.com All Rights Reserved. 7 | * 8 | */ 9 | 10 | package com.imooc.sell.repository; 11 | 12 | import static org.junit.Assert.*; 13 | import java.math.BigDecimal; 14 | import java.util.List; 15 | 16 | import com.imooc.sell.SellApplication; 17 | import org.junit.Test; 18 | import org.junit.runner.RunWith; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.boot.test.context.SpringBootTest; 21 | import org.springframework.test.annotation.Rollback; 22 | import org.springframework.test.context.junit4.SpringRunner; 23 | import org.springframework.transaction.annotation.Transactional; 24 | 25 | import com.imooc.sell.dataobject.ProductInfo; 26 | import com.imooc.sell.enums.ProductStatusEnum; 27 | import com.imooc.sell.utils.UUIDUtil; 28 | 29 | /** 30 | * ClassName:ProductInfoRepositoryTest
31 | * Function: TODO ADD FUNCTION.
32 | * Reason: TODO ADD REASON.
33 | * Date: 2017年12月8日 下午11:56:50
34 | * 35 | * @author admin 36 | * @version 37 | * @since JDK 1.6 38 | * @see 39 | */ 40 | @Rollback 41 | @Transactional 42 | @SpringBootTest(classes = SellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 43 | @RunWith(SpringRunner.class) 44 | public class ProductInfoRepositoryTest { 45 | 46 | @Autowired 47 | private ProductInfoRepository productInfoRepository; 48 | 49 | @Test 50 | public void saveTest() { 51 | ProductInfo productInfo = new ProductInfo("农家一碗香", new BigDecimal(18.30), 100, 1, 0); 52 | productInfo.setProductId(UUIDUtil.gen32UUID()); 53 | productInfo.setProductDescription("农家一碗香,里面加了鸡蛋和瘦肉,一起炒的,味道非常棒的哈!!!!"); 54 | ProductInfo result = productInfoRepository.save(productInfo); 55 | assertNotNull(result); 56 | } 57 | 58 | @Test 59 | public void deleteByIdTest() { 60 | productInfoRepository.delete("28da29e01a2d401abbc3bbd8cce47019"); 61 | ProductInfo result = productInfoRepository.findOne("28da29e01a2d401abbc3bbd8cce47019"); 62 | assertNull(result); 63 | } 64 | 65 | @Test 66 | public void updateByIdTest() { 67 | ProductInfo productInfo = new ProductInfo("农家一碗香", new BigDecimal(20.00), 200, 2, ProductStatusEnum.DOWN.getCode()); 68 | productInfo.setProductId("61ae83410ed64850bb3d334845d83bde"); 69 | productInfo.setProductIcon("http://www.potato369.com/upload/images/ywx.png"); 70 | productInfo.setProductDescription("农家一碗香,里面加了鸡蛋和瘦肉,一起炒的,味道非常棒的哈!!!!"); 71 | ProductInfo result = productInfoRepository.save(productInfo); 72 | assertEquals("http://www.potato369.com/upload/images/ywx.png", result.getProductIcon()); 73 | } 74 | 75 | @Test 76 | public void findOneTest() { 77 | ProductInfo result = productInfoRepository.findOne("61ae83410ed64850bb3d334845d83bde"); 78 | assertEquals("61ae83410ed64850bb3d334845d83bde", result.getProductId()); 79 | } 80 | 81 | @Test 82 | public void findByProductStatusTest() { 83 | List productInfoList = productInfoRepository.findByProductStatus(ProductStatusEnum.UP.getCode()); 84 | assertNotEquals(0, productInfoList.size()); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/dataobject/OrderMaster.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | *
  4 |  * @ProjectName:sell 
  5 |  * @FileName:OrderMaster.java 
  6 |  * @PackageName:com.imooc.sell.dataobject
  7 |  * @Date:2017年12月11日下午3:12:04 
  8 |  * @Copyright (c) 2018版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved
  9 |  * 
10 | */ 11 | package com.imooc.sell.dataobject; 12 | 13 | import java.io.Serializable; 14 | import java.math.BigDecimal; 15 | import java.util.Date; 16 | import javax.persistence.Column; 17 | import javax.persistence.Entity; 18 | import javax.persistence.Id; 19 | import javax.persistence.Table; 20 | import lombok.AllArgsConstructor; 21 | import lombok.Builder; 22 | import lombok.NoArgsConstructor; 23 | import org.hibernate.annotations.DynamicUpdate; 24 | import com.imooc.sell.enums.OrderStatusEnum; 25 | import com.imooc.sell.enums.PayStatusEnum; 26 | import lombok.Data; 27 | 28 | /** 29 | *
 30 |  * @ClassName: OrderMaster
 31 |  * @Function:
 32 |  * @Reason:
 33 |  * @Date: 2017年12月11日 下午3:12:04
 34 |  * @Desc:
 35 |  * @author 王艳军
 36 |  * @version 1.0
 37 |  * @since JDK 1.6
 38 |  * 
39 | */ 40 | @Data 41 | @Builder 42 | @DynamicUpdate 43 | @AllArgsConstructor 44 | @NoArgsConstructor 45 | @Entity(name = "OrderMaster") 46 | @Table(name = "order_master") 47 | public class OrderMaster implements Serializable { 48 | 49 | /** 50 | *@Fields serialVersionUID:序列号 51 | */ 52 | private static final long serialVersionUID = 3765541505739277088L; 53 | 54 | /** 55 | *@Fields orderId:订单id,主键 56 | */ 57 | @Id 58 | @Column(name = "order_id", nullable = false, length = 32) 59 | private String orderId; 60 | 61 | /** 62 | *@Fields buyerName:买家名字 63 | */ 64 | @Column(name = "buyer_name", nullable = false, length = 32) 65 | private String buyerName; 66 | 67 | /** 68 | *@Fields buyerPhone:买家电话 69 | */ 70 | @Column(name = "buyer_phone", nullable = false, length = 15) 71 | private String buyerPhone; 72 | 73 | /** 74 | *@Fields buyerAddress:买家地址 75 | */ 76 | @Column(name = "buyer_address", nullable = false, length = 128) 77 | private String buyerAddress; 78 | 79 | /** 80 | *@Fields buyerOpenid:买家微信openId 81 | */ 82 | @Column(name = "buyer_openid", nullable = false, length = 64) 83 | private String buyerOpenid; 84 | 85 | /** 86 | *@Fields orderAmount:订单总金额 87 | */ 88 | @Column(name = "order_amount", nullable = false, length = 8) 89 | private BigDecimal orderAmount; 90 | 91 | /** 92 | *@Fields orderStatus:订单状态,0-新订单;1-已完结;2-已取消,“默认:0-新订单” 93 | */ 94 | @Builder.Default 95 | @Column(name = "order_status", nullable = false, length = 3) 96 | private Integer orderStatus = OrderStatusEnum.NEW.getCode(); 97 | 98 | /** 99 | *@Fields payStatus:订单支付状态,0-等待支付;1-支付成功,“默认:0-等待支付” 100 | */ 101 | @Builder.Default 102 | @Column(name = "pay_status", nullable = false, length = 3) 103 | private Integer payStatus = PayStatusEnum.WAITING.getCode(); 104 | 105 | /** 106 | *@Fields createTime:创建时间 107 | */ 108 | @Column(name = "create_time", nullable = false) 109 | private Date createTime; 110 | 111 | /** 112 | *@Fields updateTime:更新时间 113 | */ 114 | @Column(name = "update_time", nullable = false) 115 | private Date updateTime; 116 | } 117 | -------------------------------------------------------------------------------- /src/main/resources/templates/book/info/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../../common/header.ftl"> 3 | 4 |
5 | <#--边栏 sidebar--> 6 | <#include "../../common/nav.ftl"> 7 | <#--主体内容区域 content--> 8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
style="display: none" > 17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 |
35 | 36 | 37 |
38 |
39 | 40 | 41 |
42 | 43 |
44 |
45 |
46 |
47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/controller/PayController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Project Name:sell.
3 | * File Name:PayController.java.
4 | * Package Name:com.imooc.sell.controller.
5 | * Date:2017年12月13日下午9:21:13.
6 | * Copyright (c) 2017, 版权所有 (C) 2016-2036 土豆互联科技(深圳)有限公司 www.potato369.com All Rights Reserved.
7 | */ 8 | package com.imooc.sell.controller; 9 | 10 | import com.imooc.sell.dto.OrderDTO; 11 | import com.imooc.sell.enums.OrderStatusEnum; 12 | import com.imooc.sell.enums.PayStatusEnum; 13 | import com.imooc.sell.enums.ResultEnum; 14 | import com.imooc.sell.exception.SellException; 15 | import com.imooc.sell.service.OrderService; 16 | import com.imooc.sell.service.PayService; 17 | import com.lly835.bestpay.model.PayResponse; 18 | import lombok.extern.slf4j.Slf4j; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.*; 22 | import org.springframework.web.servlet.ModelAndView; 23 | 24 | import java.util.Map; 25 | 26 | /** 27 | *
28 |  * ClassName: PayController
29 |  * Function: ADD FUNCTION
30 |  * Reason: ADD REASON(可选)
31 |  * Date: 2017年12月13日 下午9:21:13
32 |  * Desc: ADD DESC(可选)
33 |  * @author 王艳军
34 |  * @version 1.0
35 |  * @since JDK 1.6
36 |  * 
37 | */ 38 | @Controller 39 | @RequestMapping(value = "/pay") 40 | @Slf4j 41 | public class PayController { 42 | 43 | @Autowired 44 | private OrderService orderService; 45 | 46 | @Autowired 47 | private PayService payService; 48 | 49 | /** 50 | * 发起微信内H5调起支付 51 | * @param orderId 52 | * @param returnUrl 53 | * @param map 54 | * @return 55 | */ 56 | @GetMapping(value = "/create") 57 | public ModelAndView create(@RequestParam(name = "orderId", required = true) String orderId, 58 | @RequestParam(name = "returnUrl", required = true) String returnUrl, 59 | Map map) { 60 | // 1、查询订单信息是否存在 61 | OrderDTO orderDTO = orderService.findOne(orderId); 62 | if (orderDTO == null) { 63 | log.error("【支付订单】 订单信息不存在,订单id={},返回前端URL={}", orderId, returnUrl); 64 | throw new SellException(ResultEnum.ORDER_NOT_EXIST); 65 | } 66 | // 2、查询订单状态 67 | if (orderDTO.getOrderStatus() != OrderStatusEnum.NEW.getCode()) { 68 | log.error("【支付订单】 订单状态不正确,订单id={},订单状态={},返回前端URL={}, ", orderId, orderDTO.getOrderStatusEnum().getMessage(), returnUrl); 69 | throw new SellException(ResultEnum.ORDER_NOT_EXIST); 70 | } 71 | // 3、查询订单支付状态 72 | if (orderDTO.getPayStatus() != PayStatusEnum.WAITING.getCode()) { 73 | log.error("【支付订单】 订单支付状态不正确,订单id={},订单支付状态={},返回前端URL={}, ", orderId, orderDTO.getPayStatusEnum().getMessage(), returnUrl); 74 | throw new SellException(ResultEnum.ORDER_NOT_EXIST); 75 | } 76 | // 4、发起微信支付 77 | PayResponse payResponse = payService.create(orderDTO); 78 | map.put("payResponse", payResponse); 79 | map.put("returnUrl", returnUrl); 80 | return new ModelAndView("pay/create", map); 81 | } 82 | 83 | /** 84 | * 微信异步通知 85 | * @param notifyData 86 | * @return 87 | */ 88 | @PostMapping(value = "/notify") 89 | public ModelAndView notify(@RequestBody String notifyData) { 90 | 91 | payService.notify(notifyData); 92 | 93 | //3、返回给微信处理结果 94 | return new ModelAndView("pay/success"); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/service/WebSocket.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.service; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.stereotype.Component; 5 | 6 | import javax.websocket.OnClose; 7 | import javax.websocket.OnError; 8 | import javax.websocket.OnMessage; 9 | import javax.websocket.OnOpen; 10 | import javax.websocket.Session; 11 | import javax.websocket.server.ServerEndpoint; 12 | 13 | import java.util.concurrent.CopyOnWriteArraySet; 14 | 15 | /** 16 | * Describe: 17 | * 18 | * @Author 王艳军 19 | * @Date 2017/12/19 11:36:56 20 | */ 21 | @Component 22 | @Slf4j 23 | @ServerEndpoint(value = "/websocket") 24 | public class WebSocket { 25 | 26 | // 与某个客户端的连接会话,需要通过它来给客户端发送数据。 27 | private Session session; 28 | 29 | // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 30 | private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet(); 31 | 32 | /** 33 | * @Title: onOpen 34 | * @Description 连接建立成功调用的方法 35 | * @param session 36 | * @return void 返回值类型 37 | * @throws Exception 38 | */ 39 | @OnOpen 40 | public void onOpen(Session session) throws Exception { 41 | try { 42 | this.session = session; 43 | webSocketSet.add(this); 44 | log.info("【WebSocket消息】 有新的连接,连接总数:{}。", webSocketSet.size()); 45 | } catch (Exception e) { 46 | log.error("【WebSocket消息】有新的连接,将其添加到WebSocket出现错误。", e); 47 | } 48 | } 49 | 50 | /** 51 | * @Title onClose 52 | * @Description 连接关闭调用方法 53 | * @param session 传入参数 54 | * @return void 返回值类型 55 | */ 56 | @OnClose 57 | public void onClose(Session session) { 58 | try { 59 | this.session = session; 60 | webSocketSet.remove(this); 61 | this.session.close(); 62 | log.info("【WebSocket消息】 连接断开,连接总数:{}", webSocketSet.size()); 63 | } catch (Exception e) { 64 | log.error("【WebSocket消息】连接断开,将其从WebSocket删除出现错误。", e); 65 | } 66 | } 67 | 68 | /** 69 | * @Title onMessage 70 | * @Description 收到客户端消息后调用的方法 71 | * @param message 客户端消息 72 | * @return void 返回值类型 73 | */ 74 | @OnMessage 75 | public void onMessage(String message) { 76 | log.info("【WebSocket消息】 收到客户端发来的消息:{}。", message); 77 | } 78 | 79 | /** 80 | * @Title onError 81 | * @Description WebSocket发生错误时调用 82 | * @param session 83 | * @param error 84 | * @return void 返回值类型 85 | */ 86 | @OnError 87 | public void onError(Session session, Throwable error) { 88 | log.error("【WebSocket消息】WebSocket出现错误。", error); 89 | try { 90 | this.session = session; 91 | this.session.close(); 92 | } catch (Exception e) { 93 | log.error("【WebSocket消息】WebSocket关闭session出现错误。", error); 94 | } 95 | } 96 | 97 | /** 98 | * @Title: sendMessage 99 | * @Description 群发 WebSocket自定义消息 100 | * @param message 传入参数 101 | * @return void 返回值类型 102 | */ 103 | public void sendMessage(String message) { 104 | for (WebSocket webSocket : webSocketSet) { 105 | log.info("【WebSocket消息】 广播消息:message={}。", message); 106 | try { 107 | webSocket.session.getBasicRemote().sendText(message); 108 | } catch (Exception e) { 109 | log.error("【WebSocket消息】 广播消息出现错误。", e.getLocalizedMessage()); 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/imooc/sell/controller/SellerUserController.java: -------------------------------------------------------------------------------- 1 | package com.imooc.sell.controller; 2 | 3 | import com.imooc.sell.config.prop.ProjectUrlProperties; 4 | import com.imooc.sell.constant.CookieConstant; 5 | import com.imooc.sell.constant.RedisConstant; 6 | import com.imooc.sell.enums.ResultEnum; 7 | import com.imooc.sell.service.SellerService; 8 | import com.imooc.sell.dataobject.SellerInfo; 9 | import com.imooc.sell.utils.CookieUtil; 10 | import com.imooc.sell.utils.UUIDUtil; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.data.redis.core.StringRedisTemplate; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | import org.springframework.web.servlet.ModelAndView; 17 | import javax.servlet.http.Cookie; 18 | import javax.servlet.http.HttpServletRequest; 19 | import javax.servlet.http.HttpServletResponse; 20 | import java.util.Map; 21 | import java.util.concurrent.TimeUnit; 22 | 23 | /** 24 | * Description:卖家用户相关操作 25 | * @Author 王艳军 26 | * @Date 2017-12-17 15:17 27 | */ 28 | @Controller 29 | @RequestMapping(value = "/seller") 30 | public class SellerUserController { 31 | 32 | @Autowired 33 | private SellerService sellerService; 34 | 35 | @Autowired 36 | private StringRedisTemplate redisTemplate; 37 | 38 | @Autowired 39 | private ProjectUrlProperties projectUrlConfig; 40 | 41 | /** 42 | * 点餐系统卖家端后台系统网站应用微信扫码登录 43 | * @param openid 44 | * @param response 45 | * @param map 46 | * @return 47 | */ 48 | @RequestMapping(value = "/login") 49 | public ModelAndView login(@RequestParam(name = "openid", required = true) String openid, HttpServletResponse response, Map map){ 50 | 51 | //第一步:用openid和数据库里的数据匹配 52 | SellerInfo sellerInfo = sellerService.findSellerInfoByOpenid(openid); 53 | if (sellerInfo == null){ 54 | map.put("msg", ResultEnum.LOGIN_FAIL.getMessage()); 55 | map.put("url", "/sell/seller/order/list"); 56 | return new ModelAndView("common/error"); 57 | } 58 | 59 | //第二步:设置Token保存到Redis缓存 60 | String token = UUIDUtil.gen32UUID(); 61 | //设置Redis缓存过期时间为2小时 62 | Integer expire = RedisConstant.EXPIRE; 63 | redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX , token), openid, expire, TimeUnit.SECONDS); 64 | 65 | //第三步:设置Token保存到客户端浏览器Cookie 66 | CookieUtil.set(response, CookieConstant.TOKEN, token, expire); 67 | return new ModelAndView("redirect:" + projectUrlConfig.getDomainUrl() + projectUrlConfig.getProjectName() + "/seller/order/list", map); 68 | } 69 | 70 | /** 71 | * 点餐系统卖家端后台系统网站应用登出 72 | * @param request 73 | * @param response 74 | */ 75 | @RequestMapping(value = "/logout") 76 | public ModelAndView logout(HttpServletRequest request, HttpServletResponse response, Map map){ 77 | //1、从cookie里面查询 78 | Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); 79 | if (cookie != null){ 80 | //2、清除Redis 81 | redisTemplate.opsForValue().getOperations().delete(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue())); 82 | //3、清除cookie 83 | CookieUtil.set(response, CookieConstant.TOKEN, null, 0); 84 | } 85 | map.put("msg", ResultEnum.LOGOUT_SUCCESS.getMessage()); 86 | map.put("url","/sell/seller/order/list"); 87 | return new ModelAndView("common/success",map); 88 | } 89 | } 90 | --------------------------------------------------------------------------------