├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── cn │ │ └── imlxy │ │ ├── SellApplication.java │ │ ├── VO │ │ ├── ProductInfoVO.java │ │ ├── ProductVO.java │ │ └── ResultVO.java │ │ ├── aspect │ │ └── SellerAuthorize.java │ │ ├── config │ │ ├── ProjectUrlConfig.java │ │ ├── WebSocketConfig.java │ │ ├── WechatAccountConfig.java │ │ ├── WechatMpConfig.java │ │ ├── WechatOpenConfig.java │ │ └── WechatPayConfig.java │ │ ├── constant │ │ ├── CookieConstant.java │ │ └── RedisConstant.java │ │ ├── controller │ │ ├── BuyerOrderController.java │ │ ├── BuyerProductController.java │ │ ├── PayController.java │ │ ├── SecKillController.java │ │ ├── SellerCategoryController.java │ │ ├── SellerOrderController.java │ │ ├── SellerProductController.java │ │ ├── SellerUserController.java │ │ └── WeChatController.java │ │ ├── converter │ │ ├── OrderForm2OrderDTOConverter.java │ │ └── OrderMaster2OrderDTOConverter.java │ │ ├── dao │ │ ├── OrderDetailDao.java │ │ ├── OrderMasterDao.java │ │ ├── ProductCategoryDao.java │ │ ├── ProductInfoDao.java │ │ └── SellerInfoDao.java │ │ ├── dto │ │ ├── CartDTO.java │ │ └── OrderDTO.java │ │ ├── entity │ │ ├── OrderDetail.java │ │ ├── OrderMaster.java │ │ ├── ProductCategory.java │ │ ├── ProductInfo.java │ │ ├── SellerInfo.java │ │ ├── dao │ │ │ └── ProductCategoryDao.java │ │ └── mapper │ │ │ └── ProductCategoryMapper.java │ │ ├── enums │ │ ├── CodeEnum.java │ │ ├── OrderStatusEnum.java │ │ ├── PayStatusEnum.java │ │ ├── ProductStatusEnum.java │ │ └── ResultEnum.java │ │ ├── exception │ │ ├── ResponseBankException.java │ │ ├── SellException.java │ │ └── SellerAuthorizeException.java │ │ ├── form │ │ ├── CategoryForm.java │ │ ├── OrderForm.java │ │ └── ProductForm.java │ │ ├── handler │ │ └── SellerExceptionHandler.java │ │ ├── service │ │ ├── BuyerService.java │ │ ├── OrderService.java │ │ ├── PayService.java │ │ ├── ProductCategoryService.java │ │ ├── ProductService.java │ │ ├── PushMessageService.java │ │ ├── RedisLock.java │ │ ├── SecKillService.java │ │ ├── SellerService.java │ │ ├── WebSocket.java │ │ └── impl │ │ │ ├── BuyerServiceImpl.java │ │ │ ├── OrderServiceImpl.java │ │ │ ├── PayServiceImpl.java │ │ │ ├── ProductCategoryServiceImpl.java │ │ │ ├── ProductServiceImpl.java │ │ │ ├── PushMessageServiceImpl.java │ │ │ ├── SecKillServiceImpl.java │ │ │ └── SellerServiceImpl.java │ │ └── utils │ │ ├── EnumUtil.java │ │ ├── JsonUtil.java │ │ ├── KeyUtil.java │ │ ├── MathUtil.java │ │ ├── ResultVOUtil.java │ │ └── serializer │ │ ├── CookieUtil.java │ │ └── Date2LongSerializer.java └── resources │ ├── application-dev.yml │ ├── application-prod.yml │ ├── application.yml │ ├── logback-spring.xml │ ├── mapper │ └── ProductCategoryMapper.xml │ ├── static │ ├── api │ │ ├── ratings.json │ │ └── seller.json │ ├── css │ │ └── style.css │ ├── mp3 │ │ └── song.mp3 │ └── pay.html │ └── templates │ ├── category │ ├── index.ftl │ └── list.ftl │ ├── common │ ├── error.ftl │ ├── header.ftl │ ├── nav.ftl │ └── success.ftl │ ├── order │ ├── detail.ftl │ └── list.ftl │ ├── pay │ ├── create.ftl │ └── success.ftl │ └── product │ ├── index.ftl │ └── list.ftl └── test └── java └── cn └── imlxy ├── LoggerTest.java ├── SellApplicationTests.java ├── dao ├── OrderDetailDaoTest.java ├── OrderMasterDaoTest.java ├── ProductCategoryDaoTest.java ├── ProductInfoDaoTest.java └── SellerInfoDaoTest.java ├── entity └── mapper │ └── ProductCategoryMapperTest.java └── service └── impl ├── OrderServiceImplTest.java ├── PayServiceImplTest.java ├── ProductCategoryServiceImplTest.java ├── ProductServiceImplTest.java ├── PushMessageServiceImplTest.java └── SellerServiceImplTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imleonmax/springboot-sell/4cb97c07fbc648615549b42fa72479153e544989/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # springboot-sell 2 | 3 | ## 此项目是基于Spring Boot为主线的技术栈,采用RESTful风格架构的微信点餐系统。 -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 1.5.3.RELEASE 9 | 10 | 11 | cn.imlxy 12 | sell 13 | 0.0.1-SNAPSHOT 14 | sell 15 | Demo project for Spring Boot 16 | 17 | 18 | UTF-8 19 | UTF-8 20 | 1.8 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-test 32 | test 33 | 34 | 35 | org.projectlombok 36 | lombok 37 | 38 | 39 | mysql 40 | mysql-connector-java 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-data-jpa 45 | 46 | 47 | com.google.code.gson 48 | gson 49 | 50 | 51 | com.github.binarywang 52 | weixin-java-mp 53 | 2.7.0 54 | 55 | 56 | 57 | cn.springboot 58 | best-pay-sdk 59 | 1.1.0 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-starter-freemarker 64 | 65 | 66 | org.springframework.boot 67 | spring-boot-starter-data-redis 68 | 69 | 70 | org.springframework.boot 71 | spring-boot-starter-websocket 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-starter-cache 76 | 77 | 78 | org.mybatis.spring.boot 79 | mybatis-spring-boot-starter 80 | 1.2.0 81 | 82 | 83 | 84 | 85 | sell 86 | 87 | 88 | org.springframework.boot 89 | spring-boot-maven-plugin 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/SellApplication.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy; 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.cache.annotation.EnableCaching; 7 | 8 | @SpringBootApplication 9 | @EnableCaching 10 | @MapperScan(basePackages = "cn.imlxy.entity.mapper") 11 | public class SellApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(SellApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/VO/ProductInfoVO.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.VO; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * @ClassName : ProductInfoVO 11 | * @Description : 商品详情 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-11 15:38 15 | */ 16 | @Data 17 | public class ProductInfoVO implements Serializable { 18 | 19 | private static final long serialVersionUID = -3450721267209548811L; 20 | @JsonProperty("id") 21 | private String productId; 22 | 23 | @JsonProperty("name") 24 | private String productName; 25 | 26 | @JsonProperty("price") 27 | private BigDecimal productPrice; 28 | 29 | @JsonProperty("description") 30 | private String productDescription; 31 | 32 | @JsonProperty("icon") 33 | private String productIcon; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/VO/ProductVO.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.VO; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | * @ClassName : ProductVO 11 | * @Description : 商品(包含类目) 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-11 15:28 15 | */ 16 | @Data 17 | public class ProductVO implements Serializable { 18 | 19 | 20 | private static final long serialVersionUID = -3007538267787120097L; 21 | 22 | @JsonProperty("name") 23 | private String categoryName; 24 | 25 | @JsonProperty("type") 26 | private Integer categoryType; 27 | 28 | @JsonProperty("foods") 29 | private List productInfoVOList; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/VO/ResultVO.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.VO; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @ClassName : ResultVO 9 | * @Description : http请求返回的最外层对象 10 | * @Author : LiuXinyu 11 | * @Site : www.imlxy.cn 12 | * @Date: 2020-05-11 15:09 13 | */ 14 | @Data 15 | //@JsonInclude(JsonInclude.Include.NON_NULL) 16 | public class ResultVO implements Serializable { 17 | 18 | private static final long serialVersionUID = 6446653270811670838L; 19 | /**错误码**/ 20 | private Integer code; 21 | 22 | /**提示信息**/ 23 | private String msg; 24 | 25 | /**具体内容**/ 26 | private T data; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/aspect/SellerAuthorize.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.aspect; 2 | 3 | import cn.imlxy.constant.CookieConstant; 4 | import cn.imlxy.constant.RedisConstant; 5 | import cn.imlxy.exception.SellerAuthorizeException; 6 | import cn.imlxy.utils.serializer.CookieUtil; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.aspectj.lang.annotation.Aspect; 9 | import org.aspectj.lang.annotation.Before; 10 | import org.aspectj.lang.annotation.Pointcut; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.data.redis.core.StringRedisTemplate; 13 | import org.springframework.stereotype.Component; 14 | import org.springframework.util.StringUtils; 15 | import org.springframework.web.context.request.RequestAttributes; 16 | import org.springframework.web.context.request.RequestContextHolder; 17 | import org.springframework.web.context.request.ServletRequestAttributes; 18 | 19 | import javax.servlet.http.Cookie; 20 | import javax.servlet.http.HttpServletRequest; 21 | 22 | /** 23 | * @ClassName : SellerAuthorize 24 | * @Description : 25 | * @Author : LiuXinyu 26 | * @Site : www.imlxy.cn 27 | * @Date: 2020-05-21 10:14 28 | */ 29 | @Aspect 30 | @Component 31 | @Slf4j 32 | public class SellerAuthorize { 33 | @Autowired 34 | private StringRedisTemplate redisTemplate; 35 | // 36 | // @Pointcut("execution(public * cn.imlxy.controller.Seller*.*(..))" + 37 | // "&& !execution(public * cn.imlxy.controller.SellerUserController.*(..))") 38 | // public void verify() { 39 | // } 40 | // 41 | // @Before("verify()") 42 | // public void doVerify() { 43 | // ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 44 | // HttpServletRequest request = attributes.getRequest(); 45 | // //查询cookie 46 | // Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); 47 | // if (cookie == null) { 48 | // log.warn("【登录校验】Cookie中找不到token"); 49 | // throw new SellerAuthorizeException(); 50 | // } 51 | // 52 | // //去redis里查 53 | // String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue())); 54 | // if (StringUtils.isEmpty(tokenValue)) { 55 | // log.warn("【登录校验】Redis中查不到token"); 56 | // throw new SellerAuthorizeException(); 57 | // } 58 | // } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/config/ProjectUrlConfig.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * @ClassName : ProjectUrl 9 | * @Description : 10 | * @Author : LiuXinyu 11 | * @Site : www.imlxy.cn 12 | * @Date: 2020-05-20 17:25 13 | */ 14 | @Data 15 | @ConfigurationProperties(prefix = "projectUrl") 16 | @Component 17 | public class ProjectUrlConfig { 18 | 19 | /** 20 | * 微信公众平台授权url 21 | */ 22 | public String wechatMpAuthorize; 23 | 24 | /** 25 | * 微信开放平台授权url 26 | */ 27 | public String wechatOpenAuthorize; 28 | 29 | /** 30 | * 点餐系统 31 | */ 32 | public String sell; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.socket.server.standard.ServerEndpointExporter; 6 | 7 | /** 8 | * @ClassName : WebSocketConfig 9 | * @Description : 10 | * @Author : LiuXinyu 11 | * @Site : www.imlxy.cn 12 | * @Date: 2020-05-21 16:58 13 | */ 14 | @Component 15 | public class WebSocketConfig { 16 | 17 | @Bean 18 | public ServerEndpointExporter serverEndpointExporter() { 19 | return new ServerEndpointExporter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/config/WechatAccountConfig.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * @ClassName : WeChatAccountConfig 11 | * @Description : 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-15 22:44 15 | */ 16 | @Data 17 | @Component 18 | @ConfigurationProperties(prefix = "wechat") 19 | public class WechatAccountConfig { 20 | /** 21 | * 公众平台id 22 | */ 23 | private String mpAppId; 24 | /** 25 | * 公众平台密钥 26 | */ 27 | private String mpAppSecret; 28 | 29 | /** 30 | * 开放平台id 31 | */ 32 | private String openAppId; 33 | /** 34 | * 开放平台密钥 35 | */ 36 | private String openAppSecret; 37 | 38 | /** 39 | * 商户号 40 | */ 41 | private String mchId; 42 | 43 | /** 44 | * 商户密钥 45 | */ 46 | private String mchKey; 47 | 48 | /** 49 | * 商户证书路径 50 | */ 51 | private String keyPath; 52 | /** 53 | * 微信支付异步通知地址 54 | */ 55 | private String notifyUrl; 56 | 57 | /** 58 | * 微信模板id 59 | */ 60 | private Map templateId; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/config/WechatMpConfig.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.config; 2 | 3 | import cn.imlxy.config.WechatAccountConfig; 4 | import me.chanjar.weixin.mp.api.WxMpConfigStorage; 5 | import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; 6 | import me.chanjar.weixin.mp.api.WxMpService; 7 | import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class WechatMpConfig { 14 | 15 | @Autowired 16 | private WechatAccountConfig accountConfig; 17 | 18 | @Bean 19 | public WxMpService wxMpService() { 20 | WxMpService wxMpService = new WxMpServiceImpl(); 21 | wxMpService.setWxMpConfigStorage(wxMpConfigStorage()); 22 | return wxMpService; 23 | } 24 | 25 | @Bean 26 | public WxMpConfigStorage wxMpConfigStorage() { 27 | WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage(); 28 | wxMpConfigStorage.setAppId(accountConfig.getMpAppId()); 29 | wxMpConfigStorage.setSecret(accountConfig.getMpAppSecret()); 30 | return wxMpConfigStorage; 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/config/WechatOpenConfig.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.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 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class WechatOpenConfig { 13 | 14 | @Autowired 15 | private WechatAccountConfig accountConfig; 16 | 17 | @Bean 18 | public WxMpService wxOpenService() { 19 | WxMpService wxOpenService = new WxMpServiceImpl(); 20 | wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage()); 21 | return wxOpenService; 22 | } 23 | 24 | @Bean 25 | public WxMpConfigStorage wxOpenConfigStorage() { 26 | WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage(); 27 | wxMpInMemoryConfigStorage.setAppId(accountConfig.getOpenAppId()); 28 | wxMpInMemoryConfigStorage.setSecret(accountConfig.getOpenAppSecret()); 29 | return wxMpInMemoryConfigStorage; 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/config/WechatPayConfig.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.config; 2 | 3 | import com.lly835.bestpay.config.WxPayH5Config; 4 | import com.lly835.bestpay.service.impl.BestPayServiceImpl; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @ClassName : WechatPayConfig 11 | * @Description : 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-16 15:30 15 | */ 16 | @Component 17 | public class WechatPayConfig { 18 | @Autowired 19 | private WechatAccountConfig accountConfig; 20 | 21 | @Bean 22 | public WxPayH5Config wxPayH5Config(){ 23 | WxPayH5Config wxPayH5Config = new WxPayH5Config(); 24 | //TODO:修改 25 | // wxPayH5Config.setAppId(accountConfig.getMpAppId()); 26 | wxPayH5Config.setAppId("wxd898fcb01713c658"); 27 | wxPayH5Config.setAppSecret(accountConfig.getMpAppSecret()); 28 | wxPayH5Config.setMchId(accountConfig.getMchId()); 29 | wxPayH5Config.setMchKey(accountConfig.getMchKey()); 30 | wxPayH5Config.setKeyPath(accountConfig.getKeyPath()); 31 | wxPayH5Config.setNotifyUrl(accountConfig.getNotifyUrl()); 32 | return wxPayH5Config; 33 | } 34 | @Bean 35 | public BestPayServiceImpl bestPayService(){ 36 | 37 | BestPayServiceImpl bestPayService=new BestPayServiceImpl(); 38 | bestPayService.setWxPayH5Config(wxPayH5Config()); 39 | return bestPayService; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/constant/CookieConstant.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.constant; 2 | 3 | /** 4 | * cookie常量 5 | */ 6 | public interface CookieConstant { 7 | 8 | String TOKEN = "token"; 9 | 10 | Integer EXPIRE = 7200; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/constant/RedisConstant.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.constant; 2 | 3 | /** 4 | * @ClassName : RedisConstant 5 | * @Description : Redis常量 6 | * @Author : LiuXinyu 7 | * @Site : www.imlxy.cn 8 | * @Date: 2020-05-20 18:14 9 | */ 10 | public interface RedisConstant { 11 | 12 | String TOKEN_PREFIX = "token_%s"; 13 | 14 | Integer EXPIRE = 7200;//2小时 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/BuyerOrderController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.VO.ResultVO; 4 | import cn.imlxy.converter.OrderForm2OrderDTOConverter; 5 | import cn.imlxy.dto.OrderDTO; 6 | import cn.imlxy.enums.ResultEnum; 7 | import cn.imlxy.exception.SellException; 8 | import cn.imlxy.form.OrderForm; 9 | import cn.imlxy.service.BuyerService; 10 | import cn.imlxy.service.OrderService; 11 | import cn.imlxy.utils.ResultVOUtil; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.data.domain.Page; 15 | import org.springframework.data.domain.PageRequest; 16 | import org.springframework.util.CollectionUtils; 17 | import org.springframework.util.StringUtils; 18 | import org.springframework.validation.BindingResult; 19 | import org.springframework.web.bind.annotation.*; 20 | 21 | import javax.validation.Valid; 22 | import java.sql.ResultSet; 23 | import java.util.HashMap; 24 | import java.util.List; 25 | import java.util.Map; 26 | 27 | /** 28 | * @ClassName : BuyerOrderController 29 | * @Description : 30 | * @Author : LiuXinyu 31 | * @Site : www.imlxy.cn 32 | * @Date: 2020-05-13 15:35 33 | */ 34 | @RestController 35 | @RequestMapping("/buyer/order") 36 | @Slf4j 37 | public class BuyerOrderController { 38 | @Autowired 39 | private OrderService orderService; 40 | 41 | @Autowired 42 | BuyerService buyerService; 43 | //创建订单 44 | @PostMapping("/create") 45 | public ResultVO> create(@Valid OrderForm orderForm, BindingResult bindingResult) { 46 | if (bindingResult.hasErrors()) { 47 | log.info("【创建订单】参数不正确,orderForm={}", orderForm); 48 | throw new SellException(ResultEnum.PARAM_ERROR.getCode(), 49 | bindingResult.getFieldError().getDefaultMessage()); 50 | } 51 | OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm); 52 | if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())) { 53 | log.error("【创建订单】 购物车不能为空,"); 54 | throw new SellException(ResultEnum.CART_EMPTY); 55 | } 56 | OrderDTO creatResult = orderService.create(orderDTO); 57 | Map map = new HashMap<>(); 58 | map.put("orderId", creatResult.getOrderId()); 59 | return ResultVOUtil.success(map); 60 | } 61 | 62 | //订单列表 63 | @GetMapping("/list") 64 | public ResultVO> list(@RequestParam("openid") String openid, 65 | @RequestParam(value = "page",defaultValue = "0") Integer page, 66 | @RequestParam(value = "size",defaultValue = "10") Integer size) { 67 | if (StringUtils.isEmpty(openid)) { 68 | log.error("【查询订单列表】openid为空"); 69 | throw new SellException(ResultEnum.PARAM_ERROR); 70 | } 71 | PageRequest request = new PageRequest(page, size); 72 | Page orderDTOPage = orderService.findList(openid, request); 73 | return ResultVOUtil.success(orderDTOPage.getContent()); 74 | } 75 | 76 | //订单详情 77 | @GetMapping("/detail") 78 | public ResultVO detail(@RequestParam("openid") String openid, 79 | @RequestParam("orderId") String orderId) { 80 | //TODO:修改 81 | // OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId); 82 | openid = "oTgZpwaFaMRnRuIEcat2LJJhjlBI"; 83 | OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId); 84 | return ResultVOUtil.success(orderDTO); 85 | } 86 | 87 | //取消订单 88 | @PostMapping("/cancel") 89 | public ResultVO cancel(@RequestParam("openid") String openid, 90 | @RequestParam("orderId") String orderId) { 91 | buyerService.cancelOrder(openid, orderId); 92 | return ResultVOUtil.success(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/BuyerProductController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.VO.ProductInfoVO; 4 | import cn.imlxy.VO.ProductVO; 5 | import cn.imlxy.VO.ResultVO; 6 | import cn.imlxy.entity.ProductCategory; 7 | import cn.imlxy.entity.ProductInfo; 8 | import cn.imlxy.service.ProductCategoryService; 9 | import cn.imlxy.service.ProductService; 10 | import cn.imlxy.utils.ResultVOUtil; 11 | import org.springframework.beans.BeanUtils; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.cache.annotation.Cacheable; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | import sun.net.idn.Punycode; 18 | 19 | import java.lang.reflect.Array; 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.List; 23 | import java.util.stream.Collectors; 24 | 25 | /** 26 | * @ClassName : BuyerProductController 27 | * @Description : 买家商品 28 | * @Author : LiuXinyu 29 | * @Site : www.imlxy.cn 30 | * @Date: 2020-05-11 15:00 31 | */ 32 | @RestController 33 | @RequestMapping("/buyer/product") 34 | public class BuyerProductController { 35 | 36 | @Autowired 37 | private ProductService productService; 38 | 39 | @Autowired 40 | private ProductCategoryService productCategoryService; 41 | 42 | @GetMapping("/list") 43 | @Cacheable(cacheNames = "product",key = "123",unless = "#result.getCode()!=0") 44 | public ResultVO list() { 45 | //1.查询所有的上架的商品 46 | List productInfoList=productService.findUpAll(); 47 | 48 | //2.查询在架商品所属类目(一次性查询) 49 | // List categoryTypeList=new ArrayList<>(); 50 | // //传统方法 51 | // for(ProductInfo productInfo: productInfoList){ 52 | // categoryTypeList.add(productInfo.getCategoryType()); 53 | // } 54 | //精简方法lamba表达式 55 | List categoryTypeList=productInfoList.stream() 56 | .map(e->e.getCategoryType()).collect(Collectors.toList()); 57 | 58 | List productCategoryList=productCategoryService.findByCategoryTypeIn(categoryTypeList); 59 | 60 | //3. 数据拼装 61 | List productVOList=new ArrayList<>(); 62 | for(ProductCategory productCategory: productCategoryList){ 63 | ProductVO productVO=new ProductVO(); 64 | productVO.setCategoryName(productCategory.getCategoryName()); 65 | productVO.setCategoryType(productCategory.getCategoryType()); 66 | 67 | List productInfoVOList=new ArrayList<>(); 68 | for(ProductInfo productInfo: productInfoList){ 69 | if(productInfo.getCategoryType().equals(productCategory.getCategoryType())){ 70 | ProductInfoVO productInfoVO=new ProductInfoVO(); 71 | BeanUtils.copyProperties(productInfo,productInfoVO); 72 | productInfoVOList.add(productInfoVO); 73 | } 74 | } 75 | productVO.setProductInfoVOList(productInfoVOList); 76 | productVOList.add(productVO); 77 | } 78 | 79 | // ResultVO resultVO=new ResultVO(); 80 | // resultVO.setData(productVOList); 81 | // resultVO.setCode(0); 82 | // resultVO.setMsg("成功"); 83 | ResultVO resultVO= ResultVOUtil.success(productVOList); 84 | return resultVO; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/PayController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.enums.ResultEnum; 5 | import cn.imlxy.exception.SellException; 6 | import cn.imlxy.service.OrderService; 7 | import cn.imlxy.service.PayService; 8 | import com.lly835.bestpay.model.PayResponse; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.bind.annotation.*; 12 | import org.springframework.web.servlet.ModelAndView; 13 | 14 | import java.io.UnsupportedEncodingException; 15 | import java.net.URLDecoder; 16 | import java.net.URLEncoder; 17 | import java.util.Map; 18 | 19 | /** 20 | * @ClassName : PayController 21 | * @Description : 22 | * @Author : LiuXinyu 23 | * @Site : www.imlxy.cn 24 | * @Date: 2020-05-16 14:25 25 | */ 26 | @Controller 27 | @RequestMapping("/pay") 28 | public class PayController { 29 | 30 | @Autowired 31 | private OrderService orderService; 32 | @Autowired 33 | private PayService payService; 34 | 35 | @GetMapping("/create") 36 | public ModelAndView create(@RequestParam("orderId") String orderId, 37 | @RequestParam("returnUrl") String returnUrl, 38 | Map map) throws UnsupportedEncodingException { 39 | //1、查询订单 40 | OrderDTO orderDTO = orderService.findOne(orderId); 41 | if (orderDTO == null) { 42 | throw new SellException(ResultEnum.ORDER_NOT_EXIST); 43 | } 44 | //2、发起支付 45 | PayResponse payResponse = payService.create(orderDTO); 46 | map.put("payResponse", payResponse); 47 | // map.put("returnUrl", returnUrl); 48 | // map.put("returnUrl", returnUrl.startsWith("http://") ? returnUrl : URLEncoder.encode(returnUrl, "utf-8")); 49 | map.put("returnUrl", URLDecoder.decode(returnUrl)); 50 | return new ModelAndView("pay/create", map); 51 | } 52 | 53 | @PostMapping("/notify") 54 | public ModelAndView notify(@RequestBody String notifyData) { 55 | payService.notify(notifyData); 56 | // 返回给微信处理结果 57 | return new ModelAndView("pay/success"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/SecKillController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.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 | @RestController 12 | @RequestMapping("/skill") 13 | @Slf4j 14 | public class SecKillController { 15 | 16 | @Autowired 17 | private SecKillService secKillService; 18 | 19 | /** 20 | * 查询秒杀活动特价商品的信息 21 | * @param productId 22 | * @return 23 | */ 24 | @GetMapping("/query/{productId}") 25 | public String query(@PathVariable String productId)throws Exception 26 | { 27 | return secKillService.querySecKillProductInfo(productId); 28 | } 29 | 30 | 31 | /** 32 | * 秒杀,没有抢到获得"哎呦喂,xxxxx",抢到了会返回剩余的库存量 33 | * @param productId 34 | * @return 35 | * @throws Exception 36 | */ 37 | @GetMapping("/order/{productId}") 38 | public String skill(@PathVariable String productId)throws Exception 39 | { 40 | log.info("@skill request, productId:" + productId); 41 | secKillService.orderProductMockDiffUser(productId); 42 | return secKillService.querySecKillProductInfo(productId); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/SellerCategoryController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.entity.ProductCategory; 4 | import cn.imlxy.entity.ProductInfo; 5 | import cn.imlxy.exception.SellException; 6 | import cn.imlxy.form.CategoryForm; 7 | import cn.imlxy.form.ProductForm; 8 | import cn.imlxy.service.ProductCategoryService; 9 | import cn.imlxy.utils.KeyUtil; 10 | import org.apache.log4j.Category; 11 | import org.hibernate.annotations.Fetch; 12 | import org.springframework.beans.BeanUtils; 13 | import org.springframework.beans.BeansException; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Controller; 16 | import org.springframework.util.StringUtils; 17 | import org.springframework.validation.BindingResult; 18 | import org.springframework.web.bind.annotation.GetMapping; 19 | import org.springframework.web.bind.annotation.PostMapping; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RequestParam; 22 | import org.springframework.web.servlet.ModelAndView; 23 | 24 | import javax.validation.Valid; 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | /** 29 | * @ClassName : SellerCategoryController 30 | * @Description : 卖家类目 31 | * @Author : LiuXinyu 32 | * @Site : www.imlxy.cn 33 | * @Date: 2020-05-20 14:30 34 | */ 35 | @Controller 36 | @RequestMapping("/seller/category") 37 | public class SellerCategoryController { 38 | @Autowired 39 | private ProductCategoryService categoryService; 40 | 41 | @GetMapping("/list") 42 | public ModelAndView list(Map map) { 43 | List categoryList = categoryService.findAll(); 44 | map.put("categoryList", categoryList); 45 | return new ModelAndView("category/list", map); 46 | } 47 | 48 | @GetMapping("/index") 49 | public ModelAndView index(@RequestParam(value = "categoryId", required = false) Integer categoryId, 50 | Map map) { 51 | if (categoryId != null) { 52 | 53 | ProductCategory productCategory = categoryService.findOne(categoryId); 54 | map.put("category", productCategory); 55 | } 56 | return new ModelAndView("category/index", map); 57 | } 58 | 59 | /** 60 | * 保存/更新 61 | * @param form 62 | * @param bindingResult 63 | * @param map 64 | * @return 65 | */ 66 | @PostMapping("/save") 67 | public ModelAndView save(@Valid CategoryForm form, 68 | BindingResult bindingResult, 69 | Map map) { 70 | if (bindingResult.hasErrors()) { 71 | map.put("msg", bindingResult.getFieldError().getDefaultMessage()); 72 | map.put("url", "/sell/seller/category/index"); 73 | return new ModelAndView("common/error",map); 74 | } 75 | ProductCategory productCategory = new ProductCategory(); 76 | try { 77 | if (form.getCategoryId() != null) { 78 | productCategory = categoryService.findOne(form.getCategoryId()); 79 | } 80 | BeanUtils.copyProperties(form, productCategory); 81 | categoryService.save(productCategory); 82 | } catch (SellException e) { 83 | map.put("msg", e.getMessage()); 84 | map.put("url", "/sell/seller/category/index"); 85 | return new ModelAndView("common/error",map); 86 | } 87 | map.put("url", "/sell/seller/category/list"); 88 | return new ModelAndView("common/success", map); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/SellerOrderController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.enums.ResultEnum; 5 | import cn.imlxy.exception.SellException; 6 | import cn.imlxy.service.OrderService; 7 | import com.lly835.bestpay.rest.type.Delete; 8 | import com.lly835.bestpay.rest.type.Get; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.data.domain.Page; 12 | import org.springframework.data.domain.PageRequest; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.web.bind.annotation.*; 15 | import org.springframework.web.servlet.ModelAndView; 16 | 17 | import java.util.Map; 18 | 19 | /** 20 | * @ClassName : SellerOrderController 21 | * @Description : 卖家端 22 | * @Author : LiuXinyu 23 | * @Site : www.imlxy.cn 24 | * @Date: 2020-05-18 15:25 25 | */ 26 | @Controller 27 | @RequestMapping("/seller/order") 28 | @Slf4j 29 | public class SellerOrderController { 30 | 31 | @Autowired 32 | private OrderService orderService; 33 | 34 | @GetMapping("/list") 35 | public ModelAndView list(@RequestParam(value = "page", defaultValue = "1") Integer page, 36 | @RequestParam(value = "size", defaultValue = "10") Integer size, 37 | Map map) { 38 | PageRequest request = new PageRequest(page - 1, size); 39 | Page orderDTOPage = orderService.findList(request); 40 | map.put("orderDTOPage", orderDTOPage); 41 | map.put("currentPage", page); 42 | map.put("size", size); 43 | return new ModelAndView("order/list", map); 44 | } 45 | 46 | /** 47 | * 取消订单 48 | * 49 | * @param orderId 50 | * @return 51 | */ 52 | @GetMapping("/cancel") 53 | public ModelAndView cancel(@RequestParam("orderId") String orderId, 54 | Map map) { 55 | try { 56 | OrderDTO orderDTO = orderService.findOne(orderId); 57 | orderService.cancel(orderDTO); 58 | } catch (SellException e) { 59 | log.error("【卖家端取消订单】发生异常{}", e); 60 | map.put("msg", e.getMessage()); 61 | map.put("url", "/sell/seller/order/list"); 62 | return new ModelAndView("common/error", map); 63 | } 64 | map.put("msg", ResultEnum.ORDER_CANCEL_SUCCESS.getMessage()); 65 | map.put("url", "/sell/seller/order/list"); 66 | return new ModelAndView("common/success", map); 67 | } 68 | 69 | @GetMapping("/detail") 70 | public ModelAndView detail(@RequestParam("orderId") String orderId, 71 | Map map) { 72 | OrderDTO orderDTO; 73 | try { 74 | orderDTO = orderService.findOne(orderId); 75 | } catch (SellException e) { 76 | log.error("【卖家端查询订单详情】发生异常{}", e); 77 | map.put("msg", e.getMessage()); 78 | map.put("url", "/sell/seller/order/list"); 79 | return new ModelAndView("common/error", map); 80 | } 81 | map.put("orderDTO", orderDTO); 82 | return new ModelAndView("order/detail", map); 83 | } 84 | 85 | /** 86 | * 完结订单 87 | * @param orderId 88 | * @param map 89 | * @return 90 | */ 91 | @GetMapping("/finish") 92 | public ModelAndView finish(@RequestParam("orderId") String orderId, 93 | Map map) { 94 | try { 95 | OrderDTO orderDTO = orderService.findOne(orderId); 96 | orderService.finish(orderDTO); 97 | } catch (SellException e) { 98 | log.error("【卖家端完结订单】发生异常{}", e); 99 | map.put("msg", e.getMessage()); 100 | map.put("url", "/sell/seller/order/list"); 101 | return new ModelAndView("common/error", map); 102 | } 103 | map.put("msg", ResultEnum.ORDER_FINISH_SUCCESS.getMessage()); 104 | map.put("url", "/sell/seller/order/list"); 105 | return new ModelAndView("common/success", map); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/SellerProductController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.entity.ProductCategory; 5 | import cn.imlxy.entity.ProductInfo; 6 | import cn.imlxy.exception.SellException; 7 | import cn.imlxy.form.ProductForm; 8 | import cn.imlxy.service.OrderService; 9 | import cn.imlxy.service.ProductCategoryService; 10 | import cn.imlxy.service.ProductService; 11 | import cn.imlxy.utils.KeyUtil; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.BeanUtils; 14 | import org.springframework.beans.factory.BeanFactory; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.cache.annotation.CacheEvict; 17 | import org.springframework.cache.annotation.CachePut; 18 | import org.springframework.data.domain.Page; 19 | import org.springframework.data.domain.PageRequest; 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.util.StringUtils; 22 | import org.springframework.validation.BindingResult; 23 | import org.springframework.web.bind.annotation.GetMapping; 24 | import org.springframework.web.bind.annotation.PostMapping; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | import org.springframework.web.bind.annotation.RequestParam; 27 | import org.springframework.web.servlet.ModelAndView; 28 | 29 | import javax.validation.Valid; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.Properties; 33 | 34 | /** 35 | * @ClassName : SellerProductController 36 | * @Description : 37 | * @Author : LiuXinyu 38 | * @Site : www.imlxy.cn 39 | * @Date: 2020-05-20 11:03 40 | */ 41 | @Controller 42 | @Slf4j 43 | @RequestMapping("/seller/product") 44 | public class SellerProductController { 45 | @Autowired 46 | private ProductService productService; 47 | 48 | @Autowired 49 | ProductCategoryService productCategoryService; 50 | 51 | @GetMapping("/list") 52 | public ModelAndView list(@RequestParam(value = "page", defaultValue = "1") Integer page, 53 | @RequestParam(value = "size", defaultValue = "10") Integer size, 54 | Map map) { 55 | PageRequest request = new PageRequest(page - 1, size); 56 | Page productInfoPage = productService.findAll(request); 57 | map.put("productInfoPage", productInfoPage); 58 | map.put("currentPage", page); 59 | map.put("size", size); 60 | return new ModelAndView("product/list", map); 61 | } 62 | 63 | @GetMapping("/on_sale") 64 | public ModelAndView onSale(@RequestParam("productId") String productId, 65 | Map map) { 66 | try { 67 | productService.onSale(productId); 68 | } catch (SellException e) { 69 | map.put("msg", e.getMessage()); 70 | map.put("url", "/sell/seller/product/list"); 71 | return new ModelAndView("/common/error", map); 72 | } 73 | map.put("url", "/sell/seller/product/list"); 74 | return new ModelAndView("common/success", map); 75 | } 76 | 77 | @GetMapping("/off_sale") 78 | public ModelAndView offSale(@RequestParam("productId") String productId, 79 | Map map) { 80 | try { 81 | productService.offSale(productId); 82 | } catch (SellException e) { 83 | map.put("msg", e.getMessage()); 84 | map.put("url", "/sell/seller/product/list"); 85 | return new ModelAndView("common/error", map); 86 | } 87 | map.put("url", "/sell/seller/product/list"); 88 | // map.put() 89 | return new ModelAndView("common/success", map); 90 | } 91 | 92 | @GetMapping("/index") 93 | public ModelAndView index(@RequestParam(value = "productId", required = false) String ProductId, 94 | Map map) { 95 | if (!StringUtils.isEmpty(ProductId)) { 96 | ProductInfo productInfo = productService.findOne(ProductId); 97 | map.put("productInfo", productInfo); 98 | } 99 | //查询所有类目 100 | List categoryList = productCategoryService.findAll(); 101 | map.put("categoryList", categoryList); 102 | return new ModelAndView("product/index", map); 103 | 104 | } 105 | 106 | @PostMapping("/save") 107 | // @CachePut(cacheNames = "product",key = "123") 108 | @CacheEvict(cacheNames = "product",key = "123") 109 | public ModelAndView save(@Valid ProductForm form, 110 | BindingResult bindingResult, 111 | Map map) { 112 | if (bindingResult.hasErrors()) { 113 | map.put("msg", bindingResult.getFieldError().getDefaultMessage()); 114 | map.put("url", "/sell/seller/product/index"); 115 | return new ModelAndView("common/error",map); 116 | } 117 | ProductInfo productInfo = new ProductInfo(); 118 | try { 119 | if (!StringUtils.isEmpty(form.getProductId())) { 120 | productInfo = productService.findOne(form.getProductId()); 121 | }else { 122 | form.setProductId(KeyUtil.genUniqueKey()); 123 | } 124 | BeanUtils.copyProperties(form, productInfo); 125 | productService.save(productInfo); 126 | } catch (SellException e) { 127 | map.put("msg", e.getMessage()); 128 | map.put("url", "/sell/seller/product/index"); 129 | return new ModelAndView("common/error",map); 130 | } 131 | map.put("url", "/sell/seller/product/list"); 132 | return new ModelAndView("common/success", map); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/SellerUserController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.config.ProjectUrlConfig; 4 | import cn.imlxy.constant.CookieConstant; 5 | import cn.imlxy.constant.RedisConstant; 6 | import cn.imlxy.entity.SellerInfo; 7 | import cn.imlxy.enums.ResultEnum; 8 | import cn.imlxy.service.SellerService; 9 | import cn.imlxy.utils.serializer.CookieUtil; 10 | import org.apache.http.HttpRequest; 11 | import org.apache.http.HttpResponse; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.data.redis.core.StringRedisTemplate; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.RequestMapping; 17 | import org.springframework.web.bind.annotation.RequestParam; 18 | import org.springframework.web.servlet.ModelAndView; 19 | 20 | import javax.servlet.http.Cookie; 21 | import javax.servlet.http.HttpServletRequest; 22 | import javax.servlet.http.HttpServletResponse; 23 | import java.util.Map; 24 | import java.util.UUID; 25 | import java.util.concurrent.TimeUnit; 26 | 27 | /** 28 | * @ClassName : SellerUserController 29 | * @Description : 卖家用户 30 | * @Author : LiuXinyu 31 | * @Site : www.imlxy.cn 32 | * @Date: 2020-05-20 17:43 33 | */ 34 | @Controller 35 | @RequestMapping("/seller") 36 | public class SellerUserController { 37 | 38 | @Autowired 39 | private SellerService sellerService; 40 | 41 | @Autowired 42 | private StringRedisTemplate redisTemplate; 43 | 44 | @Autowired 45 | private ProjectUrlConfig projectUrlConfig; 46 | 47 | @GetMapping("/login") 48 | public ModelAndView login(@RequestParam("openid") String openid, 49 | HttpServletResponse response, 50 | Map map) { 51 | //1.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 | //2.设置token至redis 60 | String token = UUID.randomUUID().toString(); 61 | Integer expire = RedisConstant.EXPIRE; 62 | redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX,token),openid,expire, TimeUnit.SECONDS); 63 | 64 | //3.设置token至cookie 65 | CookieUtil.set(response, CookieConstant.TOKEN, token, expire); 66 | return new ModelAndView("redirect:"+projectUrlConfig.getSell()+"/sell/seller/order/list"); 67 | } 68 | 69 | 70 | @GetMapping("/logout") 71 | public ModelAndView logout(HttpServletRequest request, 72 | HttpServletResponse response, 73 | Map map) { 74 | //1.从cookie查询 75 | Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); 76 | if (cookie != null) { 77 | //2.清除Redis 78 | redisTemplate.opsForValue().getOperations().delete(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue())); 79 | //3.清除cookie 80 | CookieUtil.set(response, CookieConstant.TOKEN, null, 0); 81 | } 82 | map.put("msg", ResultEnum.LOGOUT_SUCCESS); 83 | map.put("url", "/sell/seller/order/list"); 84 | return new ModelAndView("common/success", map); 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/controller/WeChatController.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.controller; 2 | 3 | import cn.imlxy.config.ProjectUrlConfig; 4 | import cn.imlxy.enums.ResultEnum; 5 | import cn.imlxy.exception.SellException; 6 | import lombok.extern.slf4j.Slf4j; 7 | import me.chanjar.weixin.common.api.WxConsts; 8 | import me.chanjar.weixin.common.exception.WxErrorException; 9 | import me.chanjar.weixin.mp.api.WxMpService; 10 | import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.beans.factory.annotation.Value; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RequestParam; 17 | 18 | import java.net.URLEncoder; 19 | 20 | /** 21 | * @ClassName : WeChatController 22 | * @Description : 23 | * @Author : LiuXinyu 24 | * @Site : www.imlxy.cn 25 | * @Date: 2020-05-15 22:23 26 | */ 27 | @Controller 28 | @RequestMapping("/wechat") 29 | @Slf4j 30 | public class WeChatController { 31 | @Autowired 32 | private WxMpService wxMpService; 33 | 34 | @Autowired 35 | private WxMpService wxOpenService; 36 | 37 | @Autowired 38 | private ProjectUrlConfig projectUrlConfig; 39 | 40 | @GetMapping("/authorize") 41 | public String authorize(@RequestParam("returnUrl") String returnUrl) { 42 | //1. 配置 43 | //2. 调用方法 44 | String url = projectUrlConfig.getWechatMpAuthorize() + "/sell/wechat/userInfo"; 45 | String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAUTH2_SCOPE_BASE, URLEncoder.encode(returnUrl)); 46 | return "redirect:" + redirectUrl; 47 | } 48 | 49 | @GetMapping("/userInfo") 50 | public String userInfo(@RequestParam("code") String code, 51 | @RequestParam("state") String returnUrl) { 52 | WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken(); 53 | try { 54 | wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code); 55 | } catch (WxErrorException e) { 56 | log.error("【微信网页授权】{}", e); 57 | throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(), e.getError().getErrorMsg()); 58 | } 59 | 60 | String openId = wxMpOAuth2AccessToken.getOpenId(); 61 | 62 | return "redirect:" + returnUrl + "?openid=" + openId; 63 | } 64 | 65 | @GetMapping("/qrAuthorize") 66 | public String qrAuthorize(@RequestParam("returnUrl") String returnUrl) { 67 | String url = projectUrlConfig.getWechatOpenAuthorize() + "/sell/wechat/qrUserInfo"; 68 | String redirectUrl = wxOpenService.buildQrConnectUrl(url, WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN, URLEncoder.encode(returnUrl)); 69 | return "redirect:" + redirectUrl;//重定向到下面一个方法 70 | 71 | } 72 | 73 | /* //TODO:修改 74 | @GetMapping("/qrUserInfo") 75 | public String qrUserInfo(@RequestParam("code") String code, 76 | @RequestParam("state") String returnUrl) {*/ 77 | @GetMapping("/qrUserInfo") 78 | public String qrUserInfo(@RequestParam("code") String code, 79 | @RequestParam(value = "state", required = false) String returnUrl) { 80 | WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken(); 81 | try { 82 | wxMpOAuth2AccessToken = wxOpenService.oauth2getAccessToken(code); 83 | } catch (WxErrorException e) { 84 | log.error("【微信网页授权】{}", e); 85 | throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(), e.getError().getErrorMsg()); 86 | } 87 | log.info(returnUrl); 88 | String openId = wxMpOAuth2AccessToken.getOpenId(); 89 | // return "redirect:" + returnUrl + "?openid=" + openId; 90 | return "redirect:http://lxy123.natapp1.cc/sell/seller/login?openid=" + openId; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/converter/OrderForm2OrderDTOConverter.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.converter; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.entity.OrderDetail; 5 | import cn.imlxy.enums.ResultEnum; 6 | import cn.imlxy.exception.SellException; 7 | import cn.imlxy.form.OrderForm; 8 | import com.google.gson.Gson; 9 | import com.google.gson.JsonSyntaxException; 10 | import com.google.gson.reflect.TypeToken; 11 | import lombok.extern.slf4j.Slf4j; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * @ClassName : OrderForm2OrderDTOConverter 18 | * @Description : 转换 19 | * @Author : LiuXinyu 20 | * @Site : www.imlxy.cn 21 | * @Date: 2020-05-13 21:24 22 | */ 23 | @Slf4j 24 | public class OrderForm2OrderDTOConverter { 25 | public static OrderDTO convert(OrderForm orderForm) { 26 | Gson gson = new Gson(); 27 | 28 | OrderDTO orderDTO = new OrderDTO(); 29 | orderDTO.setBuyerName(orderForm.getName()); 30 | orderDTO.setBuyerPhone(orderForm.getPhone()); 31 | orderDTO.setBuyerAddress(orderForm.getAddress()); 32 | //TODO:修改 33 | // orderDTO.setBuyerOpenid(orderForm.getOpenid()); 34 | orderDTO.setBuyerOpenid("oTgZpwaFaMRnRuIEcat2LJJhjlBI"); 35 | List orderDetailList = new ArrayList<>(); 36 | try { 37 | orderDetailList = gson.fromJson(orderForm.getItems(), new TypeToken>() { 38 | }.getType()); 39 | } catch (JsonSyntaxException e) { 40 | log.error("【对象转换】错误,string={}", orderForm.getItems()); 41 | throw new SellException(ResultEnum.PARAM_ERROR); 42 | } 43 | orderDTO.setOrderDetailList(orderDetailList); 44 | return orderDTO; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/converter/OrderMaster2OrderDTOConverter.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.converter; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.entity.OrderMaster; 5 | import org.springframework.beans.BeanUtils; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | /** 11 | * @ClassName : OrderMaster2OrderDTOConverter 12 | * @Description : 转换器 13 | * @Author : LiuXinyu 14 | * @Site : www.imlxy.cn 15 | * @Date: 2020-05-12 13:25 16 | */ 17 | public class OrderMaster2OrderDTOConverter { 18 | public static OrderDTO convert(OrderMaster orderMaster) { 19 | OrderDTO orderDTO = new OrderDTO(); 20 | BeanUtils.copyProperties(orderMaster, orderDTO); 21 | return orderDTO; 22 | } 23 | 24 | public static List convert(List orderMasterList) { 25 | return orderMasterList.stream() 26 | .map(e -> convert(e)) 27 | .collect(Collectors.toList()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/dao/OrderDetailDao.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.OrderDetail; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface OrderDetailDao extends JpaRepository { 9 | 10 | List findByOrOrderId(String orderId); 11 | 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/dao/OrderMasterDao.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.OrderMaster; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | public interface OrderMasterDao extends JpaRepository { 9 | 10 | Page findByBuyerOpenid(String buyerOpenid, Pageable pageable); 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/dao/ProductCategoryDao.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.ProductCategory; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @ClassName : ProductCategoryDao 10 | * @Description : 11 | * @Author : LiuXinyu 12 | * @Site : www.imlxy.cn 13 | * @Date: 2020-05-10 16:05 14 | */ 15 | public interface ProductCategoryDao extends JpaRepository { 16 | 17 | List findByCategoryTypeIn(List categoryTypeList); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/dao/ProductInfoDao.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.ProductInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @ClassName : ProductInfoDao 10 | * @Description : 商品 11 | * @Author : LiuXinyu 12 | * @Site : www.imlxy.cn 13 | * @Date: 2020-05-10 21:20 14 | */ 15 | public interface ProductInfoDao extends JpaRepository { 16 | 17 | List findByProductStatus(Integer productStatus); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/dao/SellerInfoDao.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.SellerInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface SellerInfoDao extends JpaRepository { 7 | 8 | SellerInfo findByOpenid(String openid); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/dto/CartDTO.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @ClassName : CartDto 7 | * @Description : 购物车 8 | * @Author : LiuXinyu 9 | * @Site : www.imlxy.cn 10 | * @Date: 2020-05-12 10:09 11 | */ 12 | @Data 13 | public class CartDTO { 14 | 15 | /**商品*/ 16 | private String productId; 17 | 18 | /** 数量*/ 19 | private Integer productQuantity; 20 | 21 | public CartDTO(String productId, Integer productQuantity) { 22 | this.productId = productId; 23 | this.productQuantity = productQuantity; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/dto/OrderDTO.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dto; 2 | 3 | import cn.imlxy.entity.OrderDetail; 4 | import cn.imlxy.enums.OrderStatusEnum; 5 | import cn.imlxy.enums.PayStatusEnum; 6 | import cn.imlxy.utils.EnumUtil; 7 | import cn.imlxy.utils.serializer.Date2LongSerializer; 8 | import com.fasterxml.jackson.annotation.JsonIgnore; 9 | import com.fasterxml.jackson.annotation.JsonInclude; 10 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 11 | import lombok.Data; 12 | 13 | import java.math.BigDecimal; 14 | import java.util.Date; 15 | import java.util.List; 16 | 17 | /** 18 | * @ClassName : OrderDto 19 | * @Description : 数据传输对象 20 | * @Author : LiuXinyu 21 | * @Site : www.imlxy.cn 22 | * @Date: 2020-05-11 21:41 23 | */ 24 | @Data 25 | //@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)//旧版本,废弃 26 | //@JsonInclude(JsonInclude.Include.NON_NULL)//新版本 27 | public class OrderDTO { 28 | 29 | /**订单**/ 30 | private String orderId; 31 | 32 | /**买家名字 **/ 33 | private String buyerName; 34 | 35 | /**卖家手机号**/ 36 | private String buyerPhone; 37 | 38 | /**卖家地址**/ 39 | private String buyerAddress; 40 | 41 | /**买家微信Openid*/ 42 | private String buyerOpenid; 43 | 44 | /**订单金额*/ 45 | private BigDecimal orderAmount; 46 | 47 | /**订单状态,默认为新下单*/ 48 | private Integer orderStatus; 49 | 50 | /**支付状态,默认为0未支付*/ 51 | private Integer payStatus; 52 | 53 | /**创建时间*/ 54 | @JsonSerialize(using=Date2LongSerializer.class) 55 | private Date createTime; 56 | 57 | /**更新时间*/ 58 | @JsonSerialize(using= Date2LongSerializer.class) 59 | private Date updateTime; 60 | 61 | List orderDetailList;//=new ArrayList<>(); 62 | 63 | @JsonIgnore 64 | public OrderStatusEnum getOrderStatusEnum(){ 65 | return EnumUtil.getByCode(orderStatus,OrderStatusEnum.class); 66 | } 67 | 68 | @JsonIgnore 69 | public PayStatusEnum getPayStatusEnum(){ 70 | return EnumUtil.getByCode(payStatus,PayStatusEnum.class); 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/entity/OrderDetail.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.Id; 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * @ClassName : OrderDetail 11 | * @Description : 订单详情 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-11 19:39 15 | */ 16 | @Entity 17 | @Data 18 | public class OrderDetail { 19 | @Id 20 | private String detailId; 21 | 22 | /**订单id*/ 23 | private String orderId; 24 | 25 | /**商品id*/ 26 | private String productId; 27 | 28 | /**商品名称*/ 29 | private String productName; 30 | 31 | /**商品单价*/ 32 | private BigDecimal productPrice; 33 | 34 | /**商品数量*/ 35 | private Integer productQuantity; 36 | 37 | /**商品小图*/ 38 | private String productIcon; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/entity/OrderMaster.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity; 2 | 3 | import cn.imlxy.enums.OrderStatusEnum; 4 | import cn.imlxy.enums.PayStatusEnum; 5 | import lombok.Data; 6 | import org.hibernate.annotations.DynamicUpdate; 7 | 8 | import javax.persistence.Entity; 9 | import javax.persistence.Id; 10 | import java.math.BigDecimal; 11 | import java.util.Date; 12 | 13 | /** 14 | * @ClassName : OrderMaster 15 | * @Description : 16 | * @Author : LiuXinyu 17 | * @Site : www.imlxy.cn 18 | * @Date: 2020-05-11 19:23 19 | */ 20 | @Entity 21 | @Data 22 | @DynamicUpdate 23 | public class OrderMaster { 24 | 25 | /**订单**/ 26 | @Id 27 | private String orderId; 28 | 29 | /**买家名字 **/ 30 | private String buyerName; 31 | 32 | /**卖家手机号**/ 33 | private String buyerPhone; 34 | 35 | /**卖家地址**/ 36 | private String buyerAddress; 37 | 38 | /**买家微信Openid*/ 39 | private String buyerOpenid; 40 | 41 | /**订单金额*/ 42 | private BigDecimal orderAmount; 43 | 44 | /**订单状态,默认为新下单*/ 45 | private Integer orderStatus= OrderStatusEnum.NEW.getCode(); 46 | 47 | /**支付状态,默认为0未支付*/ 48 | private Integer payStatus= PayStatusEnum.WAIT.getCode(); 49 | 50 | /**创建时间*/ 51 | private Date createTime; 52 | 53 | /**更新时间*/ 54 | private Date updateTime; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/entity/ProductCategory.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity; 2 | 3 | import lombok.Data; 4 | import org.hibernate.annotations.DynamicUpdate; 5 | 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.Id; 9 | import java.util.Date; 10 | 11 | /** 12 | * @ClassName : ProductCategory 13 | * @Description : 类目 14 | * @Author : LiuXinyu 15 | * @Site : www.imlxy.cn 16 | * @Date: 2020-05-10 20:19 17 | */ 18 | @Data 19 | @DynamicUpdate 20 | @Entity 21 | public class ProductCategory { 22 | /**类目id.**/ 23 | @Id 24 | @GeneratedValue 25 | private Integer categoryId; 26 | /**类目名字**/ 27 | private String categoryName; 28 | /** 类目编号**/ 29 | private Integer categoryType; 30 | 31 | private Date createTime; 32 | 33 | private Date updateTime; 34 | 35 | public ProductCategory() { 36 | } 37 | 38 | public ProductCategory(String categoryName, Integer categoryType) { 39 | this.categoryName = categoryName; 40 | this.categoryType = categoryType; 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/entity/ProductInfo.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity; 2 | 3 | import cn.imlxy.enums.ProductStatusEnum; 4 | import cn.imlxy.utils.EnumUtil; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import lombok.Data; 7 | import org.hibernate.annotations.DynamicUpdate; 8 | 9 | import javax.persistence.Entity; 10 | import javax.persistence.Id; 11 | import java.io.Serializable; 12 | import java.math.BigDecimal; 13 | import java.util.Date; 14 | 15 | /** 16 | * @ClassName : ProductInfo 17 | * @Description : 商品 18 | * @Author : LiuXinyu 19 | * @Site : www.imlxy.cn 20 | * @Date: 2020-05-10 21:17 21 | */ 22 | @Entity 23 | @DynamicUpdate 24 | @Data 25 | public class ProductInfo implements Serializable{ 26 | private static final long serialVersionUID = 8209277437135944434L; 27 | @Id 28 | private String productId; 29 | 30 | /**名字**/ 31 | private String productName; 32 | 33 | /**单价**/ 34 | private BigDecimal productPrice; 35 | 36 | /**库存**/ 37 | private Integer productStock; 38 | 39 | /**描述**/ 40 | private String productDescription; 41 | 42 | /**小图**/ 43 | private String productIcon; 44 | 45 | /**状态,0正常,1下架**/ 46 | private Integer productStatus=ProductStatusEnum.UP.getCode(); 47 | 48 | /**类目编号**/ 49 | private Integer categoryType; 50 | 51 | private Date createTime; 52 | 53 | private Date updateTime; 54 | 55 | @JsonIgnore 56 | public ProductStatusEnum getProductStatusEnum(){ 57 | return EnumUtil.getByCode(productStatus,ProductStatusEnum.class); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/entity/SellerInfo.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.Id; 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @ClassName : SellerInfo 11 | * @Description : 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-20 15:30 15 | */ 16 | @Data 17 | @Entity 18 | public class SellerInfo implements Serializable { 19 | 20 | private static final long serialVersionUID = -2095637530402267420L; 21 | @Id 22 | private String sellerId; 23 | 24 | private String username; 25 | 26 | private String password; 27 | 28 | private String openid; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/entity/dao/ProductCategoryDao.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity.dao; 2 | 3 | import cn.imlxy.entity.mapper.ProductCategoryMapper; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | import java.util.Map; 7 | 8 | public class ProductCategoryDao { 9 | 10 | @Autowired 11 | ProductCategoryMapper mapper; 12 | 13 | public int insertByMap(Map map) { 14 | return mapper.insertByMap(map); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/entity/mapper/ProductCategoryMapper.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity.mapper; 2 | 3 | import cn.imlxy.entity.ProductCategory; 4 | import org.apache.ibatis.annotations.*; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | 10 | public interface ProductCategoryMapper { 11 | 12 | @Insert("insert into product_category(category_name, category_type) values (#{categoryName, jdbcType=VARCHAR}, #{category_type, jdbcType=INTEGER})") 13 | int insertByMap(Map map); 14 | 15 | @Insert("insert into product_category(category_name, category_type) values (#{categoryName, jdbcType=VARCHAR}, #{categoryType, jdbcType=INTEGER})") 16 | int insertByObject(ProductCategory productCategory); 17 | 18 | @Select("select * from product_category where category_type = #{categoryType}") 19 | @Results({ 20 | @Result(column = "category_id", property = "categoryId"), 21 | @Result(column = "category_name", property = "categoryName"), 22 | @Result(column = "category_type", property = "categoryType") 23 | }) 24 | ProductCategory findByCategoryType(Integer categoryType); 25 | 26 | @Select("select * from product_category where category_name = #{categoryName}") 27 | @Results({ 28 | @Result(column = "category_id", property = "categoryId"), 29 | @Result(column = "category_name", property = "categoryName"), 30 | @Result(column = "category_type", property = "categoryType") 31 | }) 32 | List findByCategoryName(String categoryName); 33 | 34 | @Update("update product_category set category_name = #{categoryName} where category_type = #{categoryType}") 35 | int updateByCategoryType(@Param("categoryName") String categoryName, 36 | @Param("categoryType") Integer categoryType); 37 | 38 | @Update("update product_category set category_name = #{categoryName} where category_type = #{categoryType}") 39 | int updateByObject(ProductCategory productCategory); 40 | 41 | @Delete("delete from product_category where category_type = #{categoryType}") 42 | int deleteByCategoryType(Integer categoryType); 43 | 44 | ProductCategory selectByCategoryType(Integer categoryType); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/enums/CodeEnum.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.enums; 2 | 3 | /** 4 | * @ClassName : CodeEnmu 5 | * @Description : 6 | * @Author : LiuXinyu 7 | * @Site : www.imlxy.cn 8 | * @Date: 2020-05-10 21:44 9 | */ 10 | public interface CodeEnum { 11 | Integer getCode(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/enums/OrderStatusEnum.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.enums; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum OrderStatusEnum implements CodeEnum { 7 | 8 | NEW(0, "新订单"), 9 | FINISHED(1, "完结"), 10 | CANCLE(2, "已取消"), 11 | ; 12 | private Integer code; 13 | 14 | private String message; 15 | 16 | OrderStatusEnum(Integer code, String message) { 17 | this.code = code; 18 | this.message = message; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/enums/PayStatusEnum.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.enums; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum PayStatusEnum implements CodeEnum{ 7 | WAIT(0,"未支付"), 8 | SUCCESS(1,"支付成功"), 9 | ; 10 | 11 | private Integer code; 12 | 13 | private String message; 14 | 15 | PayStatusEnum(Integer code, String message) { 16 | this.code = code; 17 | this.message = message; 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/enums/ProductStatusEnum.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 商品状态 7 | */ 8 | @Getter 9 | public enum ProductStatusEnum implements CodeEnum{ 10 | 11 | UP(0,"在架"), 12 | DOWN(1,"下架"); 13 | 14 | private Integer code; 15 | private String message; 16 | 17 | ProductStatusEnum(Integer code,String message){ 18 | this.code=code; 19 | this.message=message; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/enums/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.enums; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum ResultEnum { 7 | 8 | SUCCESS(0,"成功"), 9 | 10 | PARAM_ERROR(1,"参数不正确"), 11 | 12 | PRODUCT_NOT_EXIT(10,"商品不存在"), 13 | PRODUCT_STOCK_ERROR(11,"商品库存不正确"), 14 | ORDER_NOT_EXIST(12,"订单不存在"), 15 | ORDERDETAIL_NOT_EXIST(13,"订单详情不存在"), 16 | ORDER_STATUS_ERROR(14,"订单状态不正确"), 17 | ORDER_UPDATE_FAIL(15,"订单更新失败"), 18 | ORDER_DETAIL_EMPTY(16,"订单详情为空"), 19 | ORDER_PAY_STATUS_ERROR(17,"订单支付状态不正确"), 20 | CART_EMPTY(18,"购物车不能为空"), 21 | ORDER_OWNER_ERROR(19,"该订单不属于当前用户"), 22 | 23 | WECHAT_MP_ERROR(20,"微信公众账号方面错误"), 24 | WXPAY_NOTIFY_MONEY_VERIFY(21,"微信支付异步通知金额校验不通过"), 25 | 26 | ORDER_CANCEL_SUCCESS(22,"订单取消成功"), 27 | 28 | ORDER_FINISH_SUCCESS(23,"订单完结成功"), 29 | 30 | PRODUCT_STATUS_ERROR(24,"商品状态不正确"), 31 | 32 | LOGIN_FAIL(25,"登录失败,登录信息不正确"), 33 | 34 | LOGOUT_SUCCESS(26,"登出成功"), 35 | ; 36 | 37 | private Integer code; 38 | 39 | private String message; 40 | 41 | ResultEnum(Integer code, String message) { 42 | this.code = code; 43 | this.message = message; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/exception/ResponseBankException.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.exception; 2 | 3 | /** 4 | * @ClassName : ResponseBankException 5 | * @Description : 6 | * @Author : LiuXinyu 7 | * @Site : www.imlxy.cn 8 | * @Date: 2020-05-21 18:46 9 | */ 10 | public class ResponseBankException extends RuntimeException { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/exception/SellException.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.exception; 2 | 3 | import cn.imlxy.enums.ResultEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @ClassName : SellExceptiopn 8 | * @Description : 9 | * @Author : LiuXinyu 10 | * @Site : www.imlxy.cn 11 | * @Date: 2020-05-11 21:54 12 | */ 13 | @Getter 14 | public class SellException extends RuntimeException { 15 | private Integer code; 16 | 17 | public SellException(ResultEnum resultEnum) { 18 | super(resultEnum.getMessage()); 19 | this.code = resultEnum.getCode(); 20 | } 21 | 22 | public SellException(Integer code, String message) { 23 | super(message); 24 | this.code = code; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/exception/SellerAuthorizeException.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.exception; 2 | 3 | /** 4 | * @ClassName : SellerAuthorizeException 5 | * @Description : 6 | * @Author : LiuXinyu 7 | * @Site : www.imlxy.cn 8 | * @Date: 2020-05-21 10:29 9 | */ 10 | public class SellerAuthorizeException extends RuntimeException { 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/form/CategoryForm.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.form; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @ClassName : CategoryForm 7 | * @Description : 8 | * @Author : LiuXinyu 9 | * @Site : www.imlxy.cn 10 | * @Date: 2020-05-20 14:48 11 | */ 12 | @Data 13 | public class CategoryForm { 14 | 15 | private Integer categoryId; 16 | 17 | /** 类目名字. */ 18 | private String categoryName; 19 | 20 | /** 类目编号. */ 21 | private Integer categoryType; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/form/OrderForm.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.form; 2 | 3 | import lombok.Data; 4 | import org.hibernate.validator.constraints.NotEmpty; 5 | 6 | /** 7 | * @ClassName : OrderForm 8 | * @Description : 表单验证 9 | * @Author : LiuXinyu 10 | * @Site : www.imlxy.cn 11 | * @Date: 2020-05-13 21:00 12 | */ 13 | @Data 14 | public class OrderForm { 15 | /** 16 | * 买家姓名 17 | */ 18 | @NotEmpty(message = "姓名必填") 19 | private String name; 20 | 21 | /** 22 | * 买家手机号 23 | */ 24 | @NotEmpty(message = "手机号必填") 25 | private String phone; 26 | 27 | /** 28 | * 买家地址 29 | */ 30 | @NotEmpty(message = "地址必填") 31 | private String address; 32 | 33 | /** 34 | * 买家微信openid 35 | */ 36 | @NotEmpty(message = "openid必填") 37 | private String openid; 38 | 39 | /** 40 | * 购物车 41 | */ 42 | @NotEmpty(message = "购物车不能为空") 43 | private String items; 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/form/ProductForm.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.form; 2 | 3 | import lombok.Data; 4 | 5 | import java.math.BigDecimal; 6 | 7 | /** 8 | * @ClassName : ProductForm 9 | * @Description : 10 | * @Author : LiuXinyu 11 | * @Site : www.imlxy.cn 12 | * @Date: 2020-05-20 13:52 13 | */ 14 | @Data 15 | public class ProductForm { 16 | 17 | private String productId; 18 | 19 | /**名字**/ 20 | private String productName; 21 | 22 | /**单价**/ 23 | private BigDecimal productPrice; 24 | 25 | /**库存**/ 26 | private Integer productStock; 27 | 28 | /**描述**/ 29 | private String productDescription; 30 | 31 | /**小图**/ 32 | private String productIcon; 33 | 34 | /**类目编号**/ 35 | private Integer categoryType; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/handler/SellerExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.handler; 2 | 3 | import cn.imlxy.VO.ResultVO; 4 | import cn.imlxy.config.ProjectUrlConfig; 5 | import cn.imlxy.exception.ResponseBankException; 6 | import cn.imlxy.exception.SellException; 7 | import cn.imlxy.exception.SellerAuthorizeException; 8 | import cn.imlxy.utils.ResultVOUtil; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.web.bind.annotation.ControllerAdvice; 12 | import org.springframework.web.bind.annotation.ExceptionHandler; 13 | import org.springframework.web.bind.annotation.ResponseBody; 14 | import org.springframework.web.bind.annotation.ResponseStatus; 15 | import org.springframework.web.servlet.ModelAndView; 16 | 17 | import java.net.URLEncoder; 18 | 19 | /** 20 | * @ClassName : ExceptioonHandler 21 | * @Description : 22 | * @Author : LiuXinyu 23 | * @Site : www.imlxy.cn 24 | * @Date: 2020-05-21 10:33 25 | */ 26 | @ControllerAdvice 27 | public class SellerExceptionHandler { 28 | @Autowired 29 | private ProjectUrlConfig projectUrlConfig; 30 | 31 | //拦截登录异常 32 | //(暂时不用这个地址)http://lxy123.natapp1.cc/sell/wechat/qrAuthorize?returnUrl=http://sell.natapp4.cc/sell/seller/login 33 | @ExceptionHandler(value = SellerAuthorizeException.class) 34 | public ModelAndView handlerAuthorizeException() { 35 | return new ModelAndView("redirect:" 36 | .concat(projectUrlConfig.getWechatOpenAuthorize()) 37 | .concat("/sell/wechat/qrAuthorize") 38 | .concat("?returnUrl=") 39 | .concat(projectUrlConfig.getSell()) 40 | .concat("/sell/seller/login")); 41 | } 42 | 43 | @ExceptionHandler(value = SellException.class) 44 | @ResponseBody 45 | public ResultVO handlerSellerException(SellException e) { 46 | return ResultVOUtil.error(e.getCode(), e.getMessage()); 47 | } 48 | @ExceptionHandler(value = ResponseBankException.class) 49 | @ResponseStatus(HttpStatus.FORBIDDEN) 50 | public void handleResponseBankException() { 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/BuyerService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | 5 | public interface BuyerService { 6 | //查询一个订单 7 | OrderDTO findOrderOne(String openid, String orderId); 8 | 9 | //取消订单 10 | OrderDTO cancelOrder(String openid, String orderId); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | 7 | public interface OrderService { 8 | /**创建订单*/ 9 | OrderDTO create(OrderDTO orderDTO); 10 | 11 | /**查询单个订单*/ 12 | OrderDTO findOne(String orderId); 13 | 14 | /**查询订单列表*/ 15 | Page findList(String buyerOpenid, Pageable pageable); 16 | 17 | /**取消订单*/ 18 | OrderDTO cancel(OrderDTO orderDTO); 19 | 20 | /**完结订单*/ 21 | OrderDTO finish(OrderDTO orderDTO); 22 | 23 | /**支付订单*/ 24 | OrderDTO paid(OrderDTO orderDTO); 25 | 26 | /**查询订单列表*/ 27 | Page findList(Pageable pageable); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/PayService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import com.lly835.bestpay.model.PayResponse; 5 | import com.lly835.bestpay.model.RefundResponse; 6 | 7 | public interface PayService { 8 | PayResponse create(OrderDTO orderDTO); 9 | 10 | PayResponse notify(String notifyData); 11 | 12 | RefundResponse refund(OrderDTO orderDTO); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/ProductCategoryService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import cn.imlxy.entity.ProductCategory; 4 | import org.springframework.stereotype.Service; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @ClassName : ProductCategoryService 10 | * @Description : 类目 11 | * @Author : LiuXinyu 12 | * @Site : www.imlxy.cn 13 | * @Date: 2020-05-10 20:54 14 | */ 15 | public interface ProductCategoryService { 16 | 17 | ProductCategory findOne(Integer categoryId); 18 | 19 | List findAll(); 20 | 21 | List findByCategoryTypeIn(List categoryTypeList); 22 | 23 | ProductCategory save(ProductCategory productCategory); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import cn.imlxy.dto.CartDTO; 4 | import cn.imlxy.entity.ProductInfo; 5 | import javafx.scene.control.ProgressIndicator; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | 9 | import java.util.List; 10 | 11 | public interface ProductService { 12 | 13 | ProductInfo findOne(String productId); 14 | 15 | /** 16 | * 查询所有在架商品列表 17 | * 18 | * @return 19 | */ 20 | List findUpAll(); 21 | 22 | Page findAll(Pageable pageable); 23 | 24 | ProductInfo save(ProductInfo productInfo); 25 | 26 | //加库存 27 | void increaseStock(List cartDTOList); 28 | 29 | //减库存 30 | void decreaseStock(List cartDTOList); 31 | 32 | //上架 33 | ProductInfo onSale(String productId); 34 | 35 | //下架 36 | ProductInfo offSale(String productId); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/PushMessageService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | 5 | public interface PushMessageService { 6 | 7 | /** 8 | * 订单状态变更消息 9 | * @param orderDTO 10 | */ 11 | void orderStatus(OrderDTO orderDTO); 12 | } -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/RedisLock.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.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 | import org.springframework.util.StringUtils; 8 | 9 | @Component 10 | @Slf4j 11 | public class RedisLock { 12 | 13 | @Autowired 14 | private StringRedisTemplate redisTemplate; 15 | 16 | /** 17 | * 加锁 18 | * @param key 19 | * @param value 当前时间+超时时间 20 | * @return 21 | */ 22 | //下面代码解决了 死锁问题 和 保证只有一个线程拿锁。 23 | /**1.死锁 。当相关代码之前上锁后,如果执行代码的过程中抛错了, 24 | 那么就会出现没有解锁的问题,后续线程无法获得锁,也就出现了死锁的问题。 25 | 而以下代码后有返回true的可能,也就解决了死锁问题。 26 | */ 27 | /**2.保证只有一个线程拿锁。比如两个线程同时进入下面代码,并且其value都为B,currentValue = A。 28 | 一条代码只可能一个线程执行。 29 | 当第一个线程执行时,oldvalue = A,如果符合if条件成功拿锁。 30 | 当第二个执行时oldValue就已经是B了,所以保证了只有一个线程拿锁。 31 | */ 32 | public boolean lock(String key, String value) { 33 | //如果键不存在则新增,存在则不改变已经有的值。 34 | if(redisTemplate.opsForValue().setIfAbsent(key, value)) { 35 | return true; 36 | } 37 | //currentValue=A 这两个线程的value都是B 其中一个线程拿到锁 38 | String currentValue = redisTemplate.opsForValue().get(key); 39 | //如果锁过期 40 | if (!StringUtils.isEmpty(currentValue) 41 | && Long.parseLong(currentValue) < System.currentTimeMillis()) { 42 | //获取上一个锁的时间 43 | //设置指定 key 的值,并返回 key 的旧值。 44 | String oldValue = redisTemplate.opsForValue().getAndSet(key, value); 45 | if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) { 46 | return true; 47 | } 48 | } 49 | 50 | return false; 51 | } 52 | 53 | /** 54 | * 解锁 55 | * @param key 56 | * @param value 57 | */ 58 | public void unlock(String key, String value) { 59 | try { 60 | String currentValue = redisTemplate.opsForValue().get(key); 61 | if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) { 62 | redisTemplate.opsForValue().getOperations().delete(key); 63 | } 64 | }catch (Exception e) { 65 | log.error("【redis分布式锁】解锁异常, {}", e); 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/SecKillService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | 4 | public interface SecKillService { 5 | 6 | /** 7 | * 查询秒杀活动特价商品的信息 8 | * @param productId 9 | * @return 10 | */ 11 | String querySecKillProductInfo(String productId); 12 | 13 | /** 14 | * 模拟不同用户秒杀同一商品的请求 15 | * @param productId 16 | * @return 17 | */ 18 | void orderProductMockDiffUser(String productId); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/SellerService.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import cn.imlxy.entity.SellerInfo; 4 | 5 | public interface SellerService { 6 | 7 | /** 8 | * 通过openid查询 9 | * @param openid 10 | * @return 11 | */ 12 | SellerInfo findSellerInfoByOpenid(String openid); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/WebSocket.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.stereotype.Component; 5 | 6 | import javax.websocket.OnClose; 7 | import javax.websocket.OnMessage; 8 | import javax.websocket.OnOpen; 9 | import javax.websocket.Session; 10 | import javax.websocket.server.ServerEndpoint; 11 | import java.util.concurrent.CopyOnWriteArraySet; 12 | 13 | /** 14 | * @ClassName : WebSocket 15 | * @Description : 16 | * @Author : LiuXinyu 17 | * @Site : www.imlxy.cn 18 | * @Date: 2020-05-21 17:00 19 | */ 20 | @Component 21 | @ServerEndpoint("/webSocket") 22 | @Slf4j 23 | public class WebSocket { 24 | 25 | private Session session; 26 | 27 | private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>(); 28 | 29 | @OnOpen 30 | public void onOpen(Session session) { 31 | this.session = session; 32 | webSocketSet.add(this); 33 | log.info("【websocket消息】有新的连接, 总数:{}", webSocketSet.size()); 34 | } 35 | 36 | @OnClose 37 | public void onClose() { 38 | webSocketSet.remove(this); 39 | log.info("【websocket消息】连接断开, 总数:{}", webSocketSet.size()); 40 | } 41 | 42 | @OnMessage 43 | public void onMessage(String message) { 44 | log.info("【websocket消息】收到客户端发来的消息:{}", message); 45 | } 46 | 47 | 48 | public void sendMessage(String message) { 49 | for (WebSocket webSocket: webSocketSet) { 50 | log.info("【websocket消息】广播消息, message={}", message); 51 | try { 52 | webSocket.session.getBasicRemote().sendText(message); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/BuyerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import ch.qos.logback.classic.Logger; 4 | import cn.imlxy.dto.OrderDTO; 5 | import cn.imlxy.enums.ResultEnum; 6 | import cn.imlxy.exception.SellException; 7 | import cn.imlxy.service.BuyerService; 8 | import cn.imlxy.service.OrderService; 9 | import cn.imlxy.utils.ResultVOUtil; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | 14 | /** 15 | * @ClassName : BuyerServiceImpl 16 | * @Description : 17 | * @Author : LiuXinyu 18 | * @Site : www.imlxy.cn 19 | * @Date: 2020-05-13 23:48 20 | */ 21 | @Service 22 | @Slf4j 23 | public class BuyerServiceImpl implements BuyerService { 24 | @Autowired 25 | private OrderService orderService; 26 | @Override 27 | public OrderDTO findOrderOne(String openid, String orderId) { 28 | return checkOrderOwner(openid, orderId); 29 | } 30 | 31 | @Override 32 | public OrderDTO cancelOrder(String openid, String orderId) { 33 | openid = "oTgZpwaFaMRnRuIEcat2LJJhjlBI"; 34 | OrderDTO orderDTO = checkOrderOwner(openid, orderId); 35 | if (orderDTO == null) { 36 | log.error("【取消订单】查不到该订单,orderId", orderId); 37 | } 38 | return orderService.cancel(orderDTO); 39 | } 40 | 41 | private OrderDTO checkOrderOwner(String openid, String orderId) { 42 | OrderDTO orderDTO = orderService.findOne(orderId); 43 | if (orderDTO == null) { 44 | return null; 45 | } 46 | //判断是否是自己的订单 47 | if (!orderDTO.getBuyerOpenid().equalsIgnoreCase(openid)) { 48 | log.error("【查询订单】订单的openid不一致,openid={},orderDTO={}", openid, orderDTO); 49 | throw new SellException(ResultEnum.ORDER_OWNER_ERROR); 50 | } 51 | return orderDTO; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.converter.OrderMaster2OrderDTOConverter; 4 | import cn.imlxy.dao.OrderDetailDao; 5 | import cn.imlxy.dao.OrderMasterDao; 6 | import cn.imlxy.dto.CartDTO; 7 | import cn.imlxy.dto.OrderDTO; 8 | import cn.imlxy.entity.OrderDetail; 9 | import cn.imlxy.entity.OrderMaster; 10 | import cn.imlxy.entity.ProductInfo; 11 | import cn.imlxy.enums.OrderStatusEnum; 12 | import cn.imlxy.enums.PayStatusEnum; 13 | import cn.imlxy.enums.ResultEnum; 14 | import cn.imlxy.exception.SellException; 15 | import cn.imlxy.service.*; 16 | import cn.imlxy.utils.KeyUtil; 17 | import lombok.extern.slf4j.Slf4j; 18 | import org.springframework.beans.BeanUtils; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.data.domain.Page; 21 | import org.springframework.data.domain.PageImpl; 22 | import org.springframework.data.domain.Pageable; 23 | import org.springframework.stereotype.Service; 24 | import org.springframework.transaction.annotation.Transactional; 25 | import org.springframework.util.CollectionUtils; 26 | 27 | import javax.persistence.Transient; 28 | import java.math.BigDecimal; 29 | import java.math.BigInteger; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | import java.util.stream.Collectors; 33 | 34 | /** 35 | * @ClassName : OrderServiceImpl 36 | * @Description : 订单 37 | * @Author : LiuXinyu 38 | * @Site : www.imlxy.cn 39 | * @Date: 2020-05-11 21:46 40 | */ 41 | @Service 42 | @Slf4j 43 | public class OrderServiceImpl implements OrderService { 44 | @Autowired 45 | private ProductService productService; 46 | @Autowired 47 | private OrderDetailDao orderDetailDao; 48 | 49 | @Autowired 50 | private OrderMasterDao orderMasterDao; 51 | 52 | @Autowired 53 | private PayService payService; 54 | 55 | @Autowired 56 | private PushMessageService pushMessageService; 57 | 58 | @Autowired 59 | private WebSocket webSocket; 60 | 61 | @Override 62 | @Transactional 63 | public OrderDTO create(OrderDTO orderDTO) { 64 | String orderId = KeyUtil.genUniqueKey(); 65 | BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO); 66 | //1、查询商品(数量、价格) 67 | for (OrderDetail orderDetail : orderDTO.getOrderDetailList()) { 68 | ProductInfo productInfo = productService.findOne(orderDetail.getProductId()); 69 | if (productInfo == null) { 70 | throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); 71 | // throw new ResponseBankException(); 72 | } 73 | //2、计算订单总价 74 | orderAmount=productInfo.getProductPrice() 75 | .multiply(new BigDecimal(orderDetail.getProductQuantity())) 76 | .add(orderAmount); 77 | //订单详情入库 78 | orderDetail.setDetailId(KeyUtil.genUniqueKey()); 79 | orderDetail.setOrderId(orderId); 80 | BeanUtils.copyProperties(productInfo, orderDetail); 81 | orderDetailDao.save(orderDetail); 82 | } 83 | //3、写入订单数据库(orderMaster和orderDetail) 84 | OrderMaster orderMaster = new OrderMaster(); 85 | orderDTO.setOrderId(orderId); 86 | BeanUtils.copyProperties(orderDTO, orderMaster); 87 | orderMaster.setOrderAmount(orderAmount); 88 | orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode()); 89 | orderMaster.setPayStatus(PayStatusEnum.WAIT.getCode()); 90 | 91 | orderMasterDao.save(orderMaster); 92 | //4、扣库存 93 | List cartDTOList = orderDTO.getOrderDetailList() 94 | .stream().map(e -> new CartDTO(e.getProductId(), e.getProductQuantity())) 95 | .collect(Collectors.toList()); 96 | productService.decreaseStock(cartDTOList); 97 | 98 | //发送websocket消息 99 | webSocket.sendMessage(orderDTO.getOrderId()); 100 | 101 | return orderDTO; 102 | } 103 | 104 | @Override 105 | public OrderDTO findOne(String orderId) { 106 | OrderMaster orderMaster = orderMasterDao.findOne(orderId); 107 | if (orderMaster == null) { 108 | throw new SellException(ResultEnum.ORDER_NOT_EXIST); 109 | } 110 | List orderDetailList = orderDetailDao.findByOrOrderId(orderId); 111 | if (CollectionUtils.isEmpty(orderDetailList)) { 112 | throw new SellException(ResultEnum.ORDERDETAIL_NOT_EXIST); 113 | } 114 | OrderDTO orderDTO = new OrderDTO(); 115 | BeanUtils.copyProperties(orderMaster, orderDTO); 116 | orderDTO.setOrderDetailList(orderDetailList); 117 | return orderDTO; 118 | } 119 | 120 | @Override 121 | public Page findList(String buyerOpenid, Pageable pageable) { 122 | Page orderMasterPage = orderMasterDao.findByBuyerOpenid(buyerOpenid, pageable); 123 | //List getContent(); //将所有数据返回为List 124 | List orderDTOList = OrderMaster2OrderDTOConverter.convert(orderMasterPage.getContent()); 125 | return new PageImpl(orderDTOList, pageable, orderMasterPage.getTotalElements()); 126 | } 127 | 128 | @Override 129 | @Transactional 130 | public OrderDTO cancel(OrderDTO orderDTO) { 131 | OrderMaster orderMaster=new OrderMaster(); 132 | // BeanUtils.copyProperties(orderDTO,orderMaster); 133 | 134 | //判断订单状态 135 | if(!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){ 136 | log.error("【取消订单】订单状态不正确, orderId={},orderStatus={}",orderDTO.getOrderId(),orderDTO.getOrderStatus()); 137 | throw new SellException(ResultEnum.ORDER_STATUS_ERROR); 138 | } 139 | //修改订单状态 140 | orderDTO.setOrderStatus(OrderStatusEnum.CANCLE.getCode()); 141 | BeanUtils.copyProperties(orderDTO,orderMaster); 142 | OrderMaster updateResult=orderMasterDao.save(orderMaster); 143 | if(updateResult==null){ 144 | log.error("【取消订单】更新失败,orderMaster={}",orderMaster); 145 | throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); 146 | } 147 | 148 | //返还库存 149 | if(CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){ 150 | log.error("【取消订单】订单中无商品详情,orderDTO={}",orderDTO); 151 | throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY); 152 | } 153 | List cartDTOList=orderDTO.getOrderDetailList().stream() 154 | .map(e->new CartDTO(e.getProductId(),e.getProductQuantity())) 155 | .collect(Collectors.toList()); 156 | productService.increaseStock(cartDTOList); 157 | 158 | //如果已支付,需要退款 159 | if (orderDTO.getPayStatus().equals(PayStatusEnum.SUCCESS.getCode())) { 160 | payService.refund(orderDTO); 161 | } 162 | 163 | return orderDTO; 164 | } 165 | 166 | @Override 167 | @Transactional 168 | public OrderDTO finish(OrderDTO orderDTO) { 169 | //判断订单状态 170 | if (orderDTO.getOrderStatus().equals(OrderStatusEnum.FINISHED.getCode())) { 171 | log.error("【完结订单】订单状态不正确,orderId={},orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus()); 172 | throw new SellException(ResultEnum.ORDER_STATUS_ERROR); 173 | } 174 | 175 | //修改订单状态 176 | orderDTO.setOrderStatus(OrderStatusEnum.FINISHED.getCode()); 177 | OrderMaster orderMaster = new OrderMaster(); 178 | BeanUtils.copyProperties(orderDTO, orderMaster); 179 | OrderMaster updateResult = orderMasterDao.save(orderMaster); 180 | if (updateResult == null) { 181 | log.error("【完结订单】 更新失败,orderMaster={}", orderMaster); 182 | throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); 183 | } 184 | //推送微信模板消息 185 | pushMessageService.orderStatus(orderDTO); 186 | 187 | return orderDTO; 188 | } 189 | 190 | @Override 191 | @Transactional 192 | public OrderDTO paid(OrderDTO orderDTO) { 193 | //判断订单状态 194 | if (!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())) { 195 | log.error("【订单支付成功】订单状态不正确, orderId={},orderStatus={}",orderDTO.getOrderId(),orderDTO.getOrderStatus()); 196 | throw new SellException(ResultEnum.ORDER_STATUS_ERROR); 197 | } 198 | //判断支付状态 199 | if (!orderDTO.getPayStatus().equals(PayStatusEnum.WAIT.getCode())) { 200 | log.error("【订单支付完成】订单状态不正确,orderDTO={}", orderDTO); 201 | throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR); 202 | } 203 | //修改支付状态 204 | orderDTO.setPayStatus(PayStatusEnum.SUCCESS.getCode()); 205 | OrderMaster orderMaster = new OrderMaster(); 206 | BeanUtils.copyProperties(orderDTO, orderMaster); 207 | OrderMaster updateResult = orderMasterDao.save(orderMaster); 208 | if (updateResult == null) { 209 | log.error("【订单支付成功】更新失败,orderMaster={}", orderMaster); 210 | throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); 211 | } 212 | return orderDTO; 213 | } 214 | 215 | @Override 216 | public Page findList(Pageable pageable) { 217 | Page orderMasterPage = orderMasterDao.findAll(pageable); 218 | List orderDTOList = OrderMaster2OrderDTOConverter.convert(orderMasterPage.getContent()); 219 | return new PageImpl<>(orderDTOList, pageable, orderMasterPage.getTotalElements()); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/PayServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.enums.ResultEnum; 5 | import cn.imlxy.exception.SellException; 6 | import cn.imlxy.service.OrderService; 7 | import cn.imlxy.service.PayService; 8 | import cn.imlxy.utils.JsonUtil; 9 | import cn.imlxy.utils.MathUtil; 10 | import com.lly835.bestpay.enums.BestPayTypeEnum; 11 | import com.lly835.bestpay.model.PayRequest; 12 | import com.lly835.bestpay.model.PayResponse; 13 | import com.lly835.bestpay.model.RefundRequest; 14 | import com.lly835.bestpay.model.RefundResponse; 15 | import com.lly835.bestpay.service.impl.BestPayServiceImpl; 16 | import lombok.extern.slf4j.Slf4j; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.stereotype.Service; 19 | 20 | import javax.swing.plaf.basic.BasicTreeUI; 21 | import java.math.BigDecimal; 22 | 23 | /** 24 | * @ClassName : PayServiceImpl 25 | * @Description : 26 | * @Author : LiuXinyu 27 | * @Site : www.imlxy.cn 28 | * @Date: 2020-05-16 14:52 29 | */ 30 | @Service 31 | @Slf4j 32 | public class PayServiceImpl implements PayService { 33 | public static final String ORDER_NAME = "微信点餐订单"; 34 | @Autowired 35 | private BestPayServiceImpl bestPayService; 36 | 37 | @Autowired 38 | private OrderService orderService; 39 | 40 | @Override 41 | public PayResponse create(OrderDTO orderDTO) { 42 | PayRequest payRequest = new PayRequest(); 43 | //TODO:修改 44 | // payRequest.setOpenid(orderDTO.getBuyerOpenid()); 45 | payRequest.setOpenid("oTgZpwaFaMRnRuIEcat2LJJhjlBI"); 46 | payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue()); 47 | payRequest.setOrderId(orderDTO.getOrderId()); 48 | payRequest.setOrderName(ORDER_NAME); 49 | payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5); 50 | log.info("【微信支付】发起支付,request={}", JsonUtil.toJson(payRequest)); 51 | PayResponse payResponse = bestPayService.pay(payRequest); 52 | log.info("【微信支付】发起支付,response={}", JsonUtil.toJson(payResponse)); 53 | return payResponse; 54 | 55 | 56 | } 57 | 58 | @Override 59 | public PayResponse notify(String notifyData) { 60 | //1.验证签名 61 | //2.支付的状态 62 | //3.支付金额 63 | //4.支付人(下单人==支付人) 64 | PayResponse payResponse = bestPayService.asyncNotify(notifyData); 65 | log.info("【微信支付】异步通知,payResponse={}", JsonUtil.toJson(payResponse)); 66 | //查询订单 67 | OrderDTO orderDTO = orderService.findOne(payResponse.getOrderId()); 68 | if (orderDTO == null) { 69 | log.info("【微信支付】异步通知,订单不存在,orderId={}", payResponse.getOrderId()); 70 | throw new SellException(ResultEnum.ORDER_NOT_EXIST); 71 | } 72 | //判断金额是否一致(0.10 0.1) 73 | if (!MathUtil.equals(payResponse.getOrderAmount(), orderDTO.getOrderAmount().doubleValue())) { 74 | log.info("【微信支付】异步通知,订单金额不一致,orderId={},微信通知金额={},系统金额={}", 75 | payResponse.getOrderId(), payResponse.getOrderAmount(), orderDTO.getOrderAmount()); 76 | throw new SellException(ResultEnum.WXPAY_NOTIFY_MONEY_VERIFY); 77 | } 78 | //修改订单的支付状态 79 | orderService.paid(orderDTO); 80 | return payResponse; 81 | } 82 | 83 | /** 84 | * 退款 85 | * @param orderDTO 86 | */ 87 | @Override 88 | public RefundResponse refund(OrderDTO orderDTO) { 89 | RefundRequest refundRequest = new RefundRequest(); 90 | refundRequest.setOrderId(orderDTO.getOrderId()); 91 | refundRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue()); 92 | refundRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5); 93 | log.info("【微信退款】request={}", JsonUtil.toJson(refundRequest)); 94 | RefundResponse refundResponse = bestPayService.refund(refundRequest); 95 | log.info("【微信退款】response={}", JsonUtil.toJson(refundResponse)); 96 | return refundResponse; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/ProductCategoryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.dao.ProductCategoryDao; 4 | import cn.imlxy.entity.ProductCategory; 5 | import cn.imlxy.service.ProductCategoryService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @ClassName : ProductCategoryServiceImpl 13 | * @Description : 类目 14 | * @Author : LiuXinyu 15 | * @Site : www.imlxy.cn 16 | * @Date: 2020-05-10 20:58 17 | */ 18 | @Service 19 | public class ProductCategoryServiceImpl implements ProductCategoryService { 20 | @Autowired 21 | private ProductCategoryDao productCategoryDao; 22 | @Override 23 | public ProductCategory findOne(Integer categoryId) { 24 | return productCategoryDao.findOne(categoryId); 25 | } 26 | 27 | @Override 28 | public List findAll() { 29 | return productCategoryDao.findAll(); 30 | } 31 | 32 | @Override 33 | public List findByCategoryTypeIn(List categoryTypeList) { 34 | return productCategoryDao.findByCategoryTypeIn(categoryTypeList); 35 | } 36 | 37 | @Override 38 | public ProductCategory save(ProductCategory productCategory) { 39 | return productCategoryDao.save(productCategory); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/ProductServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.dao.ProductInfoDao; 4 | import cn.imlxy.dto.CartDTO; 5 | import cn.imlxy.entity.ProductInfo; 6 | import cn.imlxy.enums.ProductStatusEnum; 7 | import cn.imlxy.enums.ResultEnum; 8 | import cn.imlxy.exception.SellException; 9 | import cn.imlxy.service.ProductService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.cache.annotation.CacheConfig; 12 | import org.springframework.cache.annotation.CachePut; 13 | import org.springframework.cache.annotation.Cacheable; 14 | import org.springframework.data.domain.Page; 15 | import org.springframework.data.domain.Pageable; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.transaction.annotation.Transactional; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @ClassName : ProductServiceImpl 23 | * @Description : 商品 24 | * @Author : LiuXinyu 25 | * @Site : www.imlxy.cn 26 | * @Date: 2020-05-11 14:30 27 | */ 28 | @Service 29 | //@CacheConfig(cacheNames = "product") 30 | public class ProductServiceImpl implements ProductService { 31 | 32 | @Autowired 33 | private ProductInfoDao productInfoDao; 34 | 35 | @Override 36 | // @Cacheable(key = "1234") 37 | public ProductInfo findOne(String productId) { 38 | return productInfoDao.findOne(productId); 39 | } 40 | 41 | @Override 42 | public List findUpAll() { 43 | return productInfoDao.findByProductStatus(ProductStatusEnum.UP.getCode()); 44 | } 45 | 46 | @Override 47 | public Page findAll(Pageable pageable) { 48 | return productInfoDao.findAll(pageable); 49 | } 50 | 51 | @Override 52 | // @CachePut(key = "1234") 53 | public ProductInfo save(ProductInfo productInfo) { 54 | return productInfoDao.save(productInfo); 55 | } 56 | 57 | @Override 58 | @Transactional 59 | public void increaseStock(List cartDTOList) { 60 | for (CartDTO cartDTO : cartDTOList) { 61 | ProductInfo productInfo = productInfoDao.findOne(cartDTO.getProductId()); 62 | if (productInfo == null) { 63 | throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); 64 | } 65 | Integer result = productInfo.getProductStock() + cartDTO.getProductQuantity(); 66 | productInfo.setProductStock(result); 67 | productInfoDao.save(productInfo); 68 | } 69 | } 70 | 71 | @Override 72 | @Transactional 73 | public void decreaseStock(List cartDTOList) { 74 | for (CartDTO cartDTO : cartDTOList) { 75 | ProductInfo productInfo = productInfoDao.findOne(cartDTO.getProductId()); 76 | if (productInfo == null) { 77 | throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); 78 | } 79 | Integer result = productInfo.getProductStock() - cartDTO.getProductQuantity(); 80 | if (result < 0) { 81 | throw new SellException(ResultEnum.PRODUCT_STOCK_ERROR); 82 | }else { 83 | productInfo.setProductStock(result); 84 | productInfoDao.save(productInfo); 85 | } 86 | } 87 | } 88 | 89 | @Override 90 | public ProductInfo onSale(String productId) { 91 | ProductInfo productInfo = productInfoDao.findOne(productId); 92 | if (productInfo == null) { 93 | throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); 94 | } 95 | if (productInfo.getProductStatusEnum() == ProductStatusEnum.UP) { 96 | throw new SellException(ResultEnum.PRODUCT_STATUS_ERROR); 97 | } 98 | productInfo.setProductStatus(ProductStatusEnum.UP.getCode()); 99 | return productInfoDao.save(productInfo); 100 | } 101 | 102 | /** 103 | * 下架 104 | * @param productId 105 | * @return 106 | */ 107 | @Override 108 | public ProductInfo offSale(String productId) { 109 | ProductInfo productInfo = productInfoDao.findOne(productId); 110 | if (productInfo == null) { 111 | throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); 112 | } 113 | if (productInfo.getProductStatusEnum() == ProductStatusEnum.DOWN) { 114 | throw new SellException(ResultEnum.PRODUCT_STATUS_ERROR); 115 | } 116 | productInfo.setProductStatus(ProductStatusEnum.DOWN.getCode()); 117 | return productInfoDao.save(productInfo); 118 | } 119 | 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/PushMessageServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.config.WechatAccountConfig; 4 | import cn.imlxy.dto.OrderDTO; 5 | import cn.imlxy.service.PushMessageService; 6 | import lombok.extern.slf4j.Slf4j; 7 | import me.chanjar.weixin.common.exception.WxErrorException; 8 | import me.chanjar.weixin.mp.api.WxMpService; 9 | import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; 10 | import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | /** 18 | * @ClassName : PushMessageServiceImpl 19 | * @Description : 20 | * @Author : LiuXinyu 21 | * @Site : www.imlxy.cn 22 | * @Date: 2020-05-21 11:21 23 | */ 24 | @Service 25 | @Slf4j 26 | public class PushMessageServiceImpl implements PushMessageService { 27 | 28 | @Autowired 29 | private WxMpService wxMpService; 30 | 31 | @Autowired 32 | private WechatAccountConfig accountConfig; 33 | 34 | @Override 35 | public void orderStatus(OrderDTO orderDTO) { 36 | 37 | WxMpTemplateMessage templateMessage=new WxMpTemplateMessage(); 38 | //TODO:修改 39 | templateMessage.setTemplateId(accountConfig.getTemplateId().get("orderStatus"));//模板id: 40 | //TODO:修改 41 | // templateMessage.setToUser(orderDTO.getBuyerOpenid());//openid 42 | templateMessage.setToUser("o4NjLw7KtXBgfiT8MvqeGTi96j2Y");//openid 43 | 44 | List data = Arrays.asList( 45 | new WxMpTemplateData("first", "亲,请记得收货。"), 46 | new WxMpTemplateData("keyword1", "微信点餐"), 47 | new WxMpTemplateData("keyword2", "15704041176"), 48 | new WxMpTemplateData("keyword3", orderDTO.getOrderId()), 49 | new WxMpTemplateData("keyword4", orderDTO.getOrderStatusEnum().getMessage()), 50 | new WxMpTemplateData("keyword5", "¥" + orderDTO.getOrderAmount()), 51 | new WxMpTemplateData("remark", "欢迎再次光临!") 52 | ); 53 | templateMessage.setData(data); 54 | try { 55 | wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage); 56 | }catch (WxErrorException e) { 57 | log.error("【微信模版消息】发送失败, {}", e); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/SecKillServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.exception.SellException; 4 | import cn.imlxy.service.RedisLock; 5 | import cn.imlxy.service.SecKillService; 6 | import cn.imlxy.utils.KeyUtil; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | @Service 14 | public class SecKillServiceImpl implements SecKillService { 15 | 16 | private static final int TIMEOUT = 10 * 1000; //超时时间 10s 17 | 18 | @Autowired 19 | private RedisLock redisLock; 20 | 21 | /** 22 | * 国庆活动,皮蛋粥特价,限量100000份 23 | */ 24 | static Map products; 25 | static Map stock; 26 | static Map orders; 27 | 28 | static { 29 | /** 30 | * 模拟多个表,商品信息表,库存表,秒杀成功订单表 31 | */ 32 | products = new HashMap<>(); 33 | stock = new HashMap<>(); 34 | orders = new HashMap<>(); 35 | products.put("123456", 100000); 36 | stock.put("123456", 100000); 37 | } 38 | 39 | private String queryMap(String productId) { 40 | return "国庆活动,皮蛋粥特价,限量份" 41 | + products.get(productId) 42 | + " 还剩:" + stock.get(productId) + " 份" 43 | + " 该商品成功下单用户数目:" 44 | + orders.size() + " 人"; 45 | } 46 | 47 | @Override 48 | public String querySecKillProductInfo(String productId) { 49 | return this.queryMap(productId); 50 | } 51 | 52 | 53 | 54 | @Override 55 | public synchronized void orderProductMockDiffUser(String productId) { 56 | //加锁 57 | long time = System.currentTimeMillis() + TIMEOUT; 58 | if (!redisLock.lock(productId, String.valueOf(time))) { 59 | throw new SellException(101, "哎呦,人太多了,换个姿势在试试~~~"); 60 | } 61 | //1.查询该商品库存,为0则活动结束。 62 | int stockNum = stock.get(productId); 63 | if (stockNum == 0) { 64 | throw new SellException(100, "活动结束"); 65 | } else { 66 | //2.下单(模拟不同用户openid不同) 67 | orders.put(KeyUtil.genUniqueKey(), productId); 68 | //3.减库存 69 | stockNum = stockNum - 1; 70 | try { 71 | Thread.sleep(100); 72 | } catch (InterruptedException e) { 73 | e.printStackTrace(); 74 | } 75 | stock.put(productId, stockNum); 76 | } 77 | 78 | //解锁 79 | redisLock.unlock(productId, String.valueOf(time)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/service/impl/SellerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.dao.SellerInfoDao; 4 | import cn.imlxy.entity.SellerInfo; 5 | import cn.imlxy.service.SellerService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @ClassName : SellerServiceImpl 11 | * @Description : 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-20 16:12 15 | */ 16 | @Service 17 | public class SellerServiceImpl implements SellerService { 18 | 19 | @Autowired 20 | private SellerInfoDao sellerInfoDao; 21 | 22 | @Override 23 | public SellerInfo findSellerInfoByOpenid(String openid) { 24 | return sellerInfoDao.findByOpenid(openid); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/utils/EnumUtil.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.utils; 2 | 3 | import cn.imlxy.enums.CodeEnum; 4 | 5 | /** 6 | * @ClassName : EnmuUtil 7 | * @Description : 8 | * @Author : LiuXinyu 9 | * @Site : www.imlxy.cn 10 | * @Date: 2020-05-10 21:43 11 | */ 12 | public class EnumUtil { 13 | 14 | public static T getByCode(Integer code, Class enumClass){ 15 | for (T each:enumClass.getEnumConstants()){ 16 | if(code.equals(each.getCode())){ 17 | return each; 18 | } 19 | } 20 | return null; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.utils; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | /** 7 | * @ClassName : JsonUtil 8 | * @Description : 9 | * @Author : LiuXinyu 10 | * @Site : www.imlxy.cn 11 | * @Date: 2020-05-17 13:37 12 | */ 13 | public class JsonUtil { 14 | public static String toJson(Object object) { 15 | GsonBuilder gsonBuilder = new GsonBuilder(); 16 | gsonBuilder.setPrettyPrinting(); 17 | Gson gson = gsonBuilder.create(); 18 | return gson.toJson(object); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/utils/KeyUtil.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.utils; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @ClassName : KeyUtil 7 | * @Description : 8 | * @Author : LiuXinyu 9 | * @Site : www.imlxy.cn 10 | * @Date: 2020-05-11 22:20 11 | */ 12 | public class KeyUtil { 13 | /** 14 | * 生成唯一主键 15 | * 格式:时间+随机数 16 | */ 17 | public static synchronized String genUniqueKey() { 18 | Random random = new Random(); 19 | Integer number = random.nextInt(900000) + 100000; 20 | return System.currentTimeMillis() + String.valueOf(number); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/utils/MathUtil.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.utils; 2 | 3 | /** 4 | * @ClassName : MathUtil 5 | * @Description : 6 | * @Author : LiuXinyu 7 | * @Site : www.imlxy.cn 8 | * @Date: 2020-05-18 12:44 9 | */ 10 | public class MathUtil { 11 | public static final Double MONEY_RANGE = 0.01; 12 | /** 13 | * @Description 比较两个金额是否相等 14 | * @Date 2020/5/18 12:45 15 | * @Param [d1, d2] 16 | * @return java.lang.Boolean 17 | * @throws 18 | **/ 19 | public static Boolean equals(Double d1, Double d2) { 20 | double result = Math.abs(d1 - d2); 21 | if (result < MONEY_RANGE) { 22 | return true; 23 | } else { 24 | return false; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/utils/ResultVOUtil.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.utils; 2 | 3 | import cn.imlxy.VO.ResultVO; 4 | 5 | /** 6 | * @ClassName : ResultVOUtil 7 | * @Description : 8 | * @Author : LiuXinyu 9 | * @Site : www.imlxy.cn 10 | * @Date: 2020-05-11 16:58 11 | */ 12 | public class ResultVOUtil { 13 | 14 | public static ResultVO success(Object object){ 15 | ResultVO resultVO=new ResultVO(); 16 | resultVO.setData(object); 17 | resultVO.setCode(0); 18 | resultVO.setMsg("成功"); 19 | return resultVO; 20 | } 21 | 22 | public static ResultVO success(){ 23 | return success(null); 24 | } 25 | 26 | public static ResultVO error(Integer code,String msg){ 27 | ResultVO resultVO=new ResultVO(); 28 | resultVO.setCode(code); 29 | resultVO.setMsg(msg); 30 | return resultVO; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/utils/serializer/CookieUtil.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.utils.serializer; 2 | 3 | import javax.servlet.http.Cookie; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * @ClassName : CookieUtil 11 | * @Description : cookie工具类 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-20 19:06 15 | */ 16 | public class CookieUtil { 17 | /** 18 | * 设置cookie 19 | * @param response 20 | * @param name 21 | * @param value 22 | * @param maxAge 23 | */ 24 | public static void set(HttpServletResponse response, 25 | String name, 26 | String value, 27 | int maxAge) { 28 | Cookie cookie=new Cookie(name, value); 29 | cookie.setPath("/"); 30 | cookie.setMaxAge(maxAge); 31 | response.addCookie(cookie); 32 | } 33 | 34 | /** 35 | * 获取cookie 36 | * @param request 37 | * @param name 38 | * @return 39 | */ 40 | public static Cookie get(HttpServletRequest request, 41 | String name) { 42 | Map cookieMap = readCookieMap(request); 43 | if (cookieMap.containsKey(name)) { 44 | return cookieMap.get(name); 45 | }else { 46 | return null; 47 | } 48 | } 49 | 50 | /** 51 | * 将cookie封装成Map 52 | * @param request 53 | * @return 54 | */ 55 | private static Map readCookieMap(HttpServletRequest request) { 56 | Map cookieMap = new HashMap<>(); 57 | Cookie[] cookies = request.getCookies(); 58 | if (cookies != null) { 59 | for (Cookie cookie : cookies) { 60 | cookieMap.put(cookie.getName(), cookie); 61 | } 62 | } 63 | return cookieMap; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/cn/imlxy/utils/serializer/Date2LongSerializer.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.utils.serializer; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.JsonSerializer; 6 | import com.fasterxml.jackson.databind.SerializerProvider; 7 | 8 | import java.io.IOException; 9 | import java.util.Date; 10 | 11 | /** 12 | * @ClassName : Date2LongSerializer 13 | * @Description : 14 | * @Author : LiuXinyu 15 | * @Site : www.imlxy.cn 16 | * @Date: 2020-05-13 22:46 17 | */ 18 | public class Date2LongSerializer extends JsonSerializer { 19 | @Override 20 | public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 21 | jsonGenerator.writeNumber(date.getTime() / 1000); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.jdbc.Driver 4 | username: root 5 | password: 123456 6 | url: jdbc:mysql://192.168.1.125:3306/sell?characterEncoding=utf-8&useSSL=false 7 | jpa: 8 | show-sql: true 9 | jackson: 10 | default-property-inclusion: non_null 11 | redis: 12 | host: 192.168.1.125 13 | port: 6379 14 | server: 15 | context-path: /sell 16 | wechat: 17 | # 公众账号(授权) 18 | mpAppId: wx4ee980********89 19 | mpAppSecret: e2939f352a86805e20********09181d 20 | # 开放平台,卖家扫码登陆 21 | openAppId: wx6ad144e54af67d87 22 | openAppSecret: 91a2ff6d38a2bbc********079108e2e 23 | templateId: 24 | orderStatus: p-b5LPziSMukAE8QJAtAEGCGWG********weXCDbjKI 25 | # 支付/商户号 26 | mchId: 1483469312 27 | mchKey: 098F6BCD4621D373********2627B4F6 28 | # 发起支付不需要证书,退款需要 29 | keyPath: C:/h5.p12 30 | # 异步通知 31 | notifyUrl: http://lxy123.natapp1.cc/sell/pay/notify 32 | 33 | 34 | projectUrl: 35 | wechatMpAuthorize: http://lxy123.natapp1.cc 36 | wechatOpenAuthorize: http://lxy123.natapp1.cc 37 | sell: http://lxy123.natapp1.cc 38 | logging: 39 | level: 40 | cn.imlxy.entity.mapper: trace 41 | mybatis: 42 | mapper-locations: classpath:mapper/*.xml 43 | -------------------------------------------------------------------------------- /src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.jdbc.Driver 4 | username: root 5 | password: 123456 6 | url: jdbc:mysql://192.168.1.125:3306/sell?characterEncoding=utf-8&useSSL=false 7 | jackson: 8 | default-property-inclusion: non_null 9 | redis: 10 | host: 192.168.1.125 11 | port: 6379 12 | server: 13 | context-path: /sell 14 | wechat: 15 | # 公众账号(授权) 16 | mpAppId: wx4ee980********89 17 | mpAppSecret: e2939f352a86805e20********09181d 18 | # 开放平台,卖家扫码登陆 19 | openAppId: wx6ad144e54af67d87 20 | openAppSecret: 91a2ff6d38a2bbc********079108e2e 21 | templateId: 22 | orderStatus: p-b5LPziSMukAE8QJAtAEGCGWG********weXCDbjKI 23 | # 支付/商户号 24 | mchId: 1483469312 25 | mchKey: 098F6BCD4621D373********2627B4F6 26 | # 发起支付不需要证书,退款需要 27 | keyPath: C:/h5.p12 28 | # 异步通知 29 | notifyUrl: http://lxy123.natapp1.cc/sell/pay/notify 30 | 31 | 32 | projectUrl: 33 | wechatMpAuthorize: http://lxy123.natapp1.cc 34 | wechatOpenAuthorize: http://lxy123.natapp1.cc 35 | sell: http://lxy123.natapp1.cc 36 | logging: 37 | level: 38 | cn.imlxy.entity.mapper: trace 39 | mybatis: 40 | mapper-locations: classpath:mapper/*.xml 41 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: prod 4 | -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | %d - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ERROR 18 | DENY 19 | ACCEPT 20 | 21 | 22 | 23 | %msg%n 24 | 25 | 26 | 27 | 28 | H:/LearnProj/日志/sell/info.%d.log 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | ERROR 37 | 38 | 39 | 40 | %msg%n 41 | 42 | 43 | 44 | 45 | H:/LearnProj/日志/sell/error.%d.log 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/main/resources/mapper/ProductCategoryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /src/main/resources/static/api/ratings.json: -------------------------------------------------------------------------------- 1 | { 2 | "errno": 0, 3 | "data": [ 4 | { 5 | "username": "3******c", 6 | "rateTime": 1469281964000, 7 | "deliveryTime": 30, 8 | "score": 5, 9 | "rateType": 0, 10 | "text": "不错,粥很好喝,我经常吃这一家,非常赞,以后也会常来吃,强烈推荐.", 11 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 12 | "recommend": [ 13 | "南瓜粥", 14 | "皮蛋瘦肉粥", 15 | "扁豆焖面", 16 | "娃娃菜炖豆腐", 17 | "牛肉馅饼" 18 | ] 19 | }, 20 | { 21 | "username": "2******3", 22 | "rateTime": 1469271264000, 23 | "deliveryTime": "", 24 | "score": 4, 25 | "rateType": 0, 26 | "text": "服务态度不错", 27 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 28 | "recommend": [ 29 | "扁豆焖面" 30 | ] 31 | }, 32 | { 33 | "username": "3******b", 34 | "rateTime": 1469261964000, 35 | "score": 3, 36 | "rateType": 1, 37 | "text": "", 38 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 39 | "recommend": [] 40 | }, 41 | { 42 | "username": "1******c", 43 | "rateTime": 1469261864000, 44 | "deliveryTime": 20, 45 | "score": 5, 46 | "rateType": 0, 47 | "text": "良心店铺", 48 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 49 | "recommend": [] 50 | }, 51 | { 52 | "username": "2******d", 53 | "rateTime": 1469251264000, 54 | "deliveryTime": 10, 55 | "score": 4, 56 | "rateType": 0, 57 | "text": "", 58 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 59 | "recommend": [] 60 | }, 61 | { 62 | "username": "9******0", 63 | "rateTime": 1469241964000, 64 | "deliveryTime": 70, 65 | "score": 1, 66 | "rateType": 1, 67 | "text": "送货速度蜗牛一样", 68 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 69 | "recommend": [] 70 | }, 71 | { 72 | "username": "d******c", 73 | "rateTime": 1469231964000, 74 | "deliveryTime": 30, 75 | "score": 5, 76 | "rateType": 0, 77 | "text": "很喜欢的粥店", 78 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 79 | "recommend": [] 80 | }, 81 | { 82 | "username": "2******3", 83 | "rateTime": 1469221264000, 84 | "deliveryTime": "", 85 | "score": 4, 86 | "rateType": 0, 87 | "text": "量给的还可以", 88 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 89 | "recommend": [] 90 | }, 91 | { 92 | "username": "3******8", 93 | "rateTime": 1469211964000, 94 | "deliveryTime": "", 95 | "score": 3, 96 | "rateType": 1, 97 | "text": "", 98 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 99 | "recommend": [] 100 | }, 101 | { 102 | "username": "a******a", 103 | "rateTime": 1469201964000, 104 | "deliveryTime": "", 105 | "score": 4, 106 | "rateType": 0, 107 | "text": "孩子喜欢吃这家", 108 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 109 | "recommend": [ 110 | "南瓜粥" 111 | ] 112 | }, 113 | { 114 | "username": "3******3", 115 | "rateTime": 1469191264000, 116 | "deliveryTime": "", 117 | "score": 4, 118 | "rateType": 0, 119 | "text": "粥挺好吃的", 120 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 121 | "recommend": [] 122 | }, 123 | { 124 | "username": "t******b", 125 | "rateTime": 1469181964000, 126 | "deliveryTime": "", 127 | "score": 3, 128 | "rateType": 1, 129 | "text": "", 130 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 131 | "recommend": [] 132 | }, 133 | { 134 | "username": "f******c", 135 | "rateTime": 1469171964000, 136 | "deliveryTime": 15, 137 | "score": 5, 138 | "rateType": 0, 139 | "text": "送货速度很快", 140 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 141 | "recommend": [] 142 | }, 143 | { 144 | "username": "k******3", 145 | "rateTime": 1469161264000, 146 | "deliveryTime": "", 147 | "score": 4, 148 | "rateType": 0, 149 | "text": "", 150 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 151 | "recommend": [] 152 | }, 153 | { 154 | "username": "u******b", 155 | "rateTime": 1469151964000, 156 | "deliveryTime": "", 157 | "score": 4, 158 | "rateType": 0, 159 | "text": "下雨天给快递小哥点个赞", 160 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 161 | "recommend": [] 162 | }, 163 | { 164 | "username": "s******c", 165 | "rateTime": 1469141964000, 166 | "deliveryTime": "", 167 | "score": 4, 168 | "rateType": 0, 169 | "text": "好", 170 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 171 | "recommend": [] 172 | }, 173 | { 174 | "username": "z******3", 175 | "rateTime": 1469131264000, 176 | "deliveryTime": "", 177 | "score": 5, 178 | "rateType": 0, 179 | "text": "吃了还想再吃", 180 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 181 | "recommend": [] 182 | }, 183 | { 184 | "username": "n******b", 185 | "rateTime": 1469121964000, 186 | "deliveryTime": "", 187 | "score": 3, 188 | "rateType": 1, 189 | "text": "发票开的不对", 190 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 191 | "recommend": [] 192 | }, 193 | { 194 | "username": "m******c", 195 | "rateTime": 1469111964000, 196 | "deliveryTime": 30, 197 | "score": 5, 198 | "rateType": 0, 199 | "text": "好吃", 200 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 201 | "recommend": [] 202 | }, 203 | { 204 | "username": "l******3", 205 | "rateTime": 1469101264000, 206 | "deliveryTime": 40, 207 | "score": 5, 208 | "rateType": 0, 209 | "text": "还不错吧", 210 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 211 | "recommend": [] 212 | }, 213 | { 214 | "username": "3******o", 215 | "rateTime": 1469091964000, 216 | "deliveryTime": "", 217 | "score": 2, 218 | "rateType": 1, 219 | "text": "", 220 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 221 | "recommend": [] 222 | }, 223 | { 224 | "username": "3******p", 225 | "rateTime": 1469081964000, 226 | "deliveryTime": "", 227 | "score": 4, 228 | "rateType": 0, 229 | "text": "很喜欢的粥", 230 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 231 | "recommend": [] 232 | }, 233 | { 234 | "username": "o******k", 235 | "rateTime": 1469071264000, 236 | "deliveryTime": "", 237 | "score": 5, 238 | "rateType": 0, 239 | "text": "", 240 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 241 | "recommend": [] 242 | }, 243 | { 244 | "username": "k******b", 245 | "rateTime": 1469061964000, 246 | "deliveryTime": "", 247 | "score": 4, 248 | "rateType": 0, 249 | "text": "", 250 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png", 251 | "recommend": [] 252 | } 253 | ] 254 | } -------------------------------------------------------------------------------- /src/main/resources/static/api/seller.json: -------------------------------------------------------------------------------- 1 | { 2 | "errno": 0, 3 | "data": { 4 | "name": "星海美食", 5 | "description": "美团专送", 6 | "deliveryTime": 38, 7 | "score": 4.2, 8 | "serviceScore": 4.1, 9 | "foodScore": 4.3, 10 | "rankRate": 69.2, 11 | "minPrice": 0, 12 | "deliveryPrice": 0, 13 | "ratingCount": 24, 14 | "sellCount": 90, 15 | "bulletin": "粥品香坊其烹饪粥料的秘方源于中国千年古法,在融和现代制作工艺,由世界烹饪大师屈浩先生领衔研发。坚守纯天然、0添加的良心品质深得消费者青睐,发展至今成为粥类的引领品牌。是2008年奥运会和2013年园博会指定餐饮服务商。", 16 | "supports": [ 17 | { 18 | "type": 0, 19 | "description": "在线支付满28减5" 20 | }, 21 | { 22 | "type": 1, 23 | "description": "VC无限橙果汁全场8折" 24 | }, 25 | { 26 | "type": 2, 27 | "description": "单人精彩套餐" 28 | }, 29 | { 30 | "type": 3, 31 | "description": "该商家支持发票,请下单写好发票抬头" 32 | }, 33 | { 34 | "type": 4, 35 | "description": "已加入“外卖保”计划,食品安全保障" 36 | } 37 | ], 38 | "avatar": "http://static.galileo.xiaojukeji.com/static/tms/seller_avatar_256px.jpg", 39 | "pics": [ 40 | "http://fuss10.elemecdn.com/8/71/c5cf5715740998d5040dda6e66abfjpeg.jpeg?imageView2/1/w/180/h/180", 41 | "http://fuss10.elemecdn.com/b/6c/75bd250e5ba69868f3b1178afbda3jpeg.jpeg?imageView2/1/w/180/h/180", 42 | "http://fuss10.elemecdn.com/f/96/3d608c5811bc2d902fc9ab9a5baa7jpeg.jpeg?imageView2/1/w/180/h/180", 43 | "http://fuss10.elemecdn.com/6/ad/779f8620ff49f701cd4c58f6448b6jpeg.jpeg?imageView2/1/w/180/h/180" 44 | ], 45 | "infos": [ 46 | "该商家支持发票,请下单写好发票抬头", 47 | "品类:其他菜系,包子粥店", 48 | "北京市昌平区回龙观西大街龙观置业大厦底商B座102单元1340", 49 | "营业时间:10:00-20:30" 50 | ] 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/resources/static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | position: relative; 3 | overflow-x: hidden; 4 | } 5 | body, 6 | html { 7 | height: 100%; 8 | /*background-color: #583e7e;*/ 9 | } 10 | .nav .open > a { 11 | background-color: transparent; 12 | } 13 | .nav .open > a:hover { 14 | background-color: transparent; 15 | } 16 | .nav .open > a:focus { 17 | background-color: transparent; 18 | } 19 | /*-------------------------------*/ 20 | /* Wrappers */ 21 | /*-------------------------------*/ 22 | #wrapper { 23 | -moz-transition: all 0.5s ease; 24 | -o-transition: all 0.5s ease; 25 | -webkit-transition: all 0.5s ease; 26 | padding-left: 0; 27 | transition: all 0.5s ease; 28 | } 29 | #wrapper.toggled { 30 | padding-left: 180px; 31 | } 32 | #wrapper.toggled #sidebar-wrapper { 33 | width: 180px; 34 | } 35 | #sidebar-wrapper { 36 | -moz-transition: all 0.5s ease; 37 | -o-transition: all 0.5s ease; 38 | -webkit-transition: all 0.5s ease; 39 | background: #1a1a1a; 40 | height: 100%; 41 | left: 220px; 42 | margin-left: -220px; 43 | overflow-x: hidden; 44 | overflow-y: auto; 45 | transition: all 0.5s ease; 46 | width: 0; 47 | z-index: 1000; 48 | } 49 | #sidebar-wrapper::-webkit-scrollbar { 50 | display: none; 51 | } 52 | #page-content-wrapper { 53 | padding-top: 70px; 54 | width: 100%; 55 | } 56 | /*-------------------------------*/ 57 | /* Sidebar nav styles */ 58 | /*-------------------------------*/ 59 | .sidebar-nav { 60 | list-style: none; 61 | margin: 0; 62 | padding: 0; 63 | position: absolute; 64 | top: 0; 65 | width: 220px; 66 | } 67 | .sidebar-nav li { 68 | display: inline-block; 69 | line-height: 20px; 70 | position: relative; 71 | width: 100%; 72 | } 73 | .sidebar-nav li:before { 74 | background-color: #1c1c1c; 75 | content: ''; 76 | height: 100%; 77 | left: 0; 78 | position: absolute; 79 | top: 0; 80 | -webkit-transition: width 0.2s ease-in; 81 | transition: width 0.2s ease-in; 82 | width: 3px; 83 | z-index: -1; 84 | } 85 | .sidebar-nav li:first-child a { 86 | background-color: #1a1a1a; 87 | color: #ffffff; 88 | } 89 | .sidebar-nav li:nth-child(2):before { 90 | background-color: #402d5c; 91 | } 92 | .sidebar-nav li:nth-child(3):before { 93 | background-color: #4c366d; 94 | } 95 | .sidebar-nav li:nth-child(4):before { 96 | background-color: #583e7e; 97 | } 98 | .sidebar-nav li:nth-child(5):before { 99 | background-color: #64468f; 100 | } 101 | .sidebar-nav li:nth-child(6):before { 102 | background-color: #704fa0; 103 | } 104 | .sidebar-nav li:nth-child(7):before { 105 | background-color: #7c5aae; 106 | } 107 | .sidebar-nav li:nth-child(8):before { 108 | background-color: #8a6cb6; 109 | } 110 | .sidebar-nav li:nth-child(9):before { 111 | background-color: #987dbf; 112 | } 113 | .sidebar-nav li:hover:before { 114 | -webkit-transition: width 0.2s ease-in; 115 | transition: width 0.2s ease-in; 116 | width: 100%; 117 | } 118 | .sidebar-nav li a { 119 | color: #dddddd; 120 | display: block; 121 | padding: 10px 15px 10px 30px; 122 | text-decoration: none; 123 | } 124 | .sidebar-nav li.open:hover before { 125 | -webkit-transition: width 0.2s ease-in; 126 | transition: width 0.2s ease-in; 127 | width: 100%; 128 | } 129 | .sidebar-nav .dropdown-menu { 130 | background-color: #222222; 131 | border-radius: 0; 132 | border: none; 133 | box-shadow: none; 134 | margin: 0; 135 | padding: 0; 136 | position: relative; 137 | width: 100%; 138 | } 139 | .sidebar-nav li a:hover, 140 | .sidebar-nav li a:active, 141 | .sidebar-nav li a:focus, 142 | .sidebar-nav li.open a:hover, 143 | .sidebar-nav li.open a:active, 144 | .sidebar-nav li.open a:focus { 145 | background-color: transparent; 146 | color: #ffffff; 147 | text-decoration: none; 148 | } 149 | .sidebar-nav > .sidebar-brand { 150 | font-size: 20px; 151 | height: 65px; 152 | line-height: 44px; 153 | } 154 | /*-------------------------------*/ 155 | /* Hamburger-Cross */ 156 | /*-------------------------------*/ 157 | .hamburger { 158 | background: transparent; 159 | border: none; 160 | display: block; 161 | height: 32px; 162 | margin-left: 15px; 163 | position: fixed; 164 | top: 20px; 165 | width: 32px; 166 | z-index: 999; 167 | } 168 | .hamburger:hover { 169 | outline: none; 170 | } 171 | .hamburger:focus { 172 | outline: none; 173 | } 174 | .hamburger:active { 175 | outline: none; 176 | } 177 | .hamburger.is-closed:before { 178 | -webkit-transform: translate3d(0, 0, 0); 179 | -webkit-transition: all 0.35s ease-in-out; 180 | color: #ffffff; 181 | content: ''; 182 | display: block; 183 | font-size: 14px; 184 | line-height: 32px; 185 | opacity: 0; 186 | text-align: center; 187 | width: 100px; 188 | } 189 | .hamburger.is-closed:hover before { 190 | -webkit-transform: translate3d(-100px, 0, 0); 191 | -webkit-transition: all 0.35s ease-in-out; 192 | display: block; 193 | opacity: 1; 194 | } 195 | .hamburger.is-closed:hover .hamb-top { 196 | -webkit-transition: all 0.35s ease-in-out; 197 | top: 0; 198 | } 199 | .hamburger.is-closed:hover .hamb-bottom { 200 | -webkit-transition: all 0.35s ease-in-out; 201 | bottom: 0; 202 | } 203 | .hamburger.is-closed .hamb-top { 204 | -webkit-transition: all 0.35s ease-in-out; 205 | background-color: rgba(255, 255, 255, 0.7); 206 | top: 5px; 207 | } 208 | .hamburger.is-closed .hamb-middle { 209 | background-color: rgba(255, 255, 255, 0.7); 210 | margin-top: -2px; 211 | top: 50%; 212 | } 213 | .hamburger.is-closed .hamb-bottom { 214 | -webkit-transition: all 0.35s ease-in-out; 215 | background-color: rgba(255, 255, 255, 0.7); 216 | bottom: 5px; 217 | } 218 | .hamburger.is-closed .hamb-top, 219 | .hamburger.is-closed .hamb-middle, 220 | .hamburger.is-closed .hamb-bottom, 221 | .hamburger.is-open .hamb-top, 222 | .hamburger.is-open .hamb-middle, 223 | .hamburger.is-open .hamb-bottom { 224 | height: 4px; 225 | left: 0; 226 | position: absolute; 227 | width: 100%; 228 | } 229 | .hamburger.is-open .hamb-top { 230 | -webkit-transform: rotate(45deg); 231 | -webkit-transition: -webkit-transform 0.2s cubic-bezier(0.73, 1, 0.28, 0.08); 232 | background-color: #ffffff; 233 | margin-top: -2px; 234 | top: 50%; 235 | } 236 | .hamburger.is-open .hamb-middle { 237 | background-color: #ffffff; 238 | display: none; 239 | } 240 | .hamburger.is-open .hamb-bottom { 241 | -webkit-transform: rotate(-45deg); 242 | -webkit-transition: -webkit-transform 0.2s cubic-bezier(0.73, 1, 0.28, 0.08); 243 | background-color: #ffffff; 244 | margin-top: -2px; 245 | top: 50%; 246 | } 247 | .hamburger.is-open:before { 248 | -webkit-transform: translate3d(0, 0, 0); 249 | -webkit-transition: all 0.35s ease-in-out; 250 | color: #ffffff; 251 | content: ''; 252 | display: block; 253 | font-size: 14px; 254 | line-height: 32px; 255 | opacity: 0; 256 | text-align: center; 257 | width: 100px; 258 | } 259 | .hamburger.is-open:hover before { 260 | -webkit-transform: translate3d(-100px, 0, 0); 261 | -webkit-transition: all 0.35s ease-in-out; 262 | display: block; 263 | opacity: 1; 264 | } 265 | -------------------------------------------------------------------------------- /src/main/resources/static/mp3/song.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imleonmax/springboot-sell/4cb97c07fbc648615549b42fa72479153e544989/src/main/resources/static/mp3/song.mp3 -------------------------------------------------------------------------------- /src/main/resources/static/pay.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/templates/category/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 | 5 |
6 | 7 | <#--边栏sidebar--> 8 | <#include "../common/nav.ftl"> 9 | 10 | <#--主要内容content--> 11 |
12 |
13 |
14 |
15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 | 25 | 26 |
27 |
28 |
29 |
30 |
31 | 32 |
33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/templates/category/list.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 | 5 |
6 | 7 | <#--边栏sidebar--> 8 | <#include "../common/nav.ftl"> 9 | 10 | <#--主要内容content--> 11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | <#list categoryList as category> 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
类目id名字type创建时间修改时间操作
${category.categoryId}${category.categoryName}${category.categoryType}${category.createTime}${category.updateTime}修改
40 |
41 |
42 |
43 |
44 | 45 |
46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/error.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 错误提示 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 | 14 |

15 | 错误! 16 |

${msg}3s后自动跳转 17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/header.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 卖家后端管理系统 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/nav.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/templates/common/success.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 成功提示 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 | 14 |

15 | 成功! 16 |

${msg!""}3s后自动跳转 17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/resources/templates/order/detail.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../common/header.ftl"> 4 | 5 | 6 |
7 | 8 | <#--边栏sidebar--> 9 | <#include "../common/nav.ftl"> 10 | 11 | 12 | <#--主要内容content--> 13 |
14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
订单id订单总金额
${orderDTO.orderId}${orderDTO.orderAmount}
31 |
32 | 33 | <#--订单详情表数据--> 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | <#list orderDTO.orderDetailList as orderDetail> 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
商品id商品名称价格数量总额
${orderDetail.productId}${orderDetail.productName}${orderDetail.productPrice}${orderDetail.productQuantity}${orderDetail.productQuantity * orderDetail.productPrice}
57 |
58 | 59 | <#--操作--> 60 |
61 | <#if orderDTO.getOrderStatusEnum().message == "新订单"> 62 | 完结订单 63 | 取消订单 64 | 65 |
66 |
67 |
68 |
69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /src/main/resources/templates/order/list.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <#include "../common/header.ftl"> 4 | 5 | 6 |
7 | 8 | <#--边栏sidebar--> 9 | <#include "../common/nav.ftl"> 10 | 11 | <#--主要内容content--> 12 |
13 |
14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | <#list orderDTOPage.content as orderDTO> 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 48 | 49 | 50 | 51 |
订单id姓名手机号地址金额订单状态支付状态创建时间操作
${orderDTO.orderId}${orderDTO.buyerName}${orderDTO.buyerPhone}${orderDTO.buyerAddress}${orderDTO.orderAmount}${orderDTO.getOrderStatusEnum().message}${orderDTO.getPayStatusEnum().message}${orderDTO.createTime}详情 44 | <#if orderDTO.getOrderStatusEnum().message == "新订单"> 45 | 取消 46 | 47 |
52 |
53 | 54 | <#--分页--> 55 |
56 |
    57 | <#if currentPage lte 1> 58 |
  • 上一页
  • 59 | <#else> 60 |
  • 上一页
  • 61 | 62 | 63 | <#list 1..orderDTOPage.getTotalPages() as index> 64 | <#if currentPage == index> 65 |
  • ${index}
  • 66 | <#else> 67 |
  • ${index}
  • 68 | 69 | 70 | 71 | <#if currentPage gte orderDTOPage.getTotalPages()> 72 |
  • 下一页
  • 73 | <#else> 74 |
  • 下一页
  • 75 | 76 |
77 |
78 |
79 |
80 |
81 | 82 |
83 | <#--弹窗--> 84 | 103 | 104 | <#--播放音乐--> 105 | 108 | 109 | 110 | 111 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /src/main/resources/templates/pay/create.ftl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/templates/pay/success.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/templates/product/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 | 5 |
6 | 7 | <#--边栏sidebar--> 8 | <#include "../common/nav.ftl"> 9 | 10 | <#--主要内容content--> 11 |
12 |
13 |
14 |
15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 |
29 | 30 | 31 |
32 |
33 | 34 | 35 | 36 |
37 |
38 | 39 | 50 |
51 | 52 | 53 | 54 |
55 |
56 |
57 |
58 |
59 | 60 |
61 | 62 | -------------------------------------------------------------------------------- /src/main/resources/templates/product/list.ftl: -------------------------------------------------------------------------------- 1 | 2 | <#include "../common/header.ftl"> 3 | 4 | 5 |
6 | 7 | <#--边栏sidebar--> 8 | <#include "../common/nav.ftl"> 9 | 10 | <#--主要内容content--> 11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | <#list productInfoPage.content as productInfo> 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 51 | 52 | 53 | 54 |
商品id名称图片单价库存描述类目创建时间修改时间操作
${productInfo.productId}${productInfo.productName}${productInfo.productPrice}${productInfo.productStock}${productInfo.productDescription}${productInfo.categoryType}${productInfo.createTime}${productInfo.updateTime}修改 45 | <#if productInfo.getProductStatusEnum().message == "在架"> 46 | 下架 47 | <#else> 48 | 上架 49 | 50 |
55 |
56 | 57 | <#--分页--> 58 |
59 |
    60 | <#if currentPage lte 1> 61 |
  • 上一页
  • 62 | <#else> 63 |
  • 上一页
  • 64 | 65 | 66 | <#list 1..productInfoPage.getTotalPages() as index> 67 | <#if currentPage == index> 68 |
  • ${index}
  • 69 | <#else> 70 |
  • ${index}
  • 71 | 72 | 73 | 74 | <#if currentPage gte productInfoPage.getTotalPages()> 75 |
  • 下一页
  • 76 | <#else> 77 |
  • 下一页
  • 78 | 79 |
80 |
81 |
82 |
83 |
84 | 85 |
86 | 87 | -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/LoggerTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy; 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 | * @ClassName : LoggerTest 11 | * @Description : 日志测试 12 | * @Author : LiuXinyu 13 | * @Site : www.imlxy.cn 14 | * @Date: 2020-05-10 20:31 15 | */ 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | @Slf4j 19 | public class LoggerTest { 20 | 21 | // private final Logger logger= LoggerFactory.getLogger(LoggerTest.class); 22 | @Test 23 | public void test1(){ 24 | String name="imooc"; 25 | String password="123456"; 26 | //要安裝Lombok插件,才能直接用log 27 | log.debug("debug......"); 28 | log.info("name: {} , password: {}",name,password); 29 | log.error("error......"); 30 | log.warn("warning....."); 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/SellApplicationTests.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SellApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/dao/OrderDetailDaoTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.OrderDetail; 4 | import cn.imlxy.entity.OrderMaster; 5 | import org.junit.Assert; 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.context.junit4.SpringRunner; 11 | 12 | import java.math.BigDecimal; 13 | import java.util.List; 14 | 15 | import static org.junit.Assert.*; 16 | 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class OrderDetailDaoTest { 20 | 21 | @Autowired 22 | private OrderDetailDao orderDetailDao; 23 | 24 | @Test 25 | public void save() { 26 | OrderDetail orderDetail = new OrderDetail(); 27 | orderDetail.setDetailId("1234567810"); 28 | orderDetail.setOrderId("11111112"); 29 | orderDetail.setProductIcon("http://xxx.jpc"); 30 | orderDetail.setProductId("11111112"); 31 | orderDetail.setProductName("小饼干"); 32 | orderDetail.setProductPrice(new BigDecimal(2.7)); 33 | orderDetail.setProductQuantity(2); 34 | OrderDetail result = orderDetailDao.save(orderDetail); 35 | Assert.assertNotNull(result); 36 | 37 | } 38 | 39 | @Test 40 | public void findByOrOrderId() { 41 | List orderDetailList = orderDetailDao.findByOrOrderId("11111111"); 42 | Assert.assertNotEquals(0,orderDetailList.size()); 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/dao/OrderMasterDaoTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.OrderMaster; 4 | import org.junit.Assert; 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.data.domain.Page; 10 | import org.springframework.data.domain.PageRequest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | import java.math.BigDecimal; 14 | 15 | import static org.junit.Assert.*; 16 | 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class OrderMasterDaoTest { 20 | @Autowired 21 | private OrderMasterDao orderMasterDao; 22 | 23 | private final String OPENID = "1717171"; 24 | @Test 25 | public void findByBuyerOpenid() { 26 | PageRequest pageRequest = new PageRequest(1, 3); 27 | Page result = orderMasterDao.findByBuyerOpenid(OPENID, pageRequest); 28 | Assert.assertNotEquals(0,result.getTotalElements()); 29 | System.out.println(result.getTotalElements()); 30 | } 31 | 32 | @Test 33 | public void save() { 34 | OrderMaster orderMaster = new OrderMaster(); 35 | orderMaster.setOrderId("123457"); 36 | orderMaster.setBuyerName("小宇"); 37 | orderMaster.setBuyerPhone("12345678910"); 38 | orderMaster.setBuyerAddress("imlxy.cn"); 39 | orderMaster.setBuyerOpenid(OPENID); 40 | orderMaster.setOrderAmount(new BigDecimal(23.1)); 41 | 42 | OrderMaster result = orderMasterDao.save(orderMaster); 43 | Assert.assertNotNull(result); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/dao/ProductCategoryDaoTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.ProductCategory; 4 | import org.junit.Assert; 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.context.junit4.SpringRunner; 10 | 11 | import javax.transaction.Transactional; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class ProductCategoryDaoTest { 18 | @Autowired 19 | private ProductCategoryDao productCategoryDao; 20 | 21 | @Test 22 | public void findOneTest() { 23 | ProductCategory productCategory = productCategoryDao.findOne(1); 24 | System.out.println(productCategory); 25 | } 26 | 27 | @Test 28 | @Transactional 29 | public void saveTest() { 30 | ProductCategory productCategory = new ProductCategory("女生最爱", 3); 31 | ProductCategory result = productCategoryDao.save(productCategory); 32 | Assert.assertNotNull(result); 33 | } 34 | 35 | @Test 36 | public void findByCategoryTypeIn() { 37 | List list = Arrays.asList(2, 3, 4); 38 | List result = productCategoryDao.findByCategoryTypeIn(list); 39 | Assert.assertNotEquals(0, result.size()); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/dao/ProductInfoDaoTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.ProductInfo; 4 | import org.junit.Assert; 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.context.junit4.SpringRunner; 10 | 11 | import java.math.BigDecimal; 12 | import java.util.List; 13 | 14 | import static org.junit.Assert.*; 15 | 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | public class ProductInfoDaoTest { 19 | 20 | @Autowired 21 | private ProductInfoDao productInfoDao; 22 | 23 | @Test 24 | public void save() { 25 | ProductInfo productInfo = new ProductInfo(); 26 | productInfo.setProductId("123456"); 27 | productInfo.setProductName("小饼干"); 28 | productInfo.setProductPrice(new BigDecimal(3.2)); 29 | productInfo.setProductStock(100); 30 | productInfo.setProductDescription("好吃,好吃"); 31 | productInfo.setProductIcon("xxxx.jpg"); 32 | productInfo.setProductStatus(0); 33 | productInfo.setCategoryType(2); 34 | ProductInfo result = productInfoDao.save(productInfo); 35 | Assert.assertNotNull(result); 36 | 37 | } 38 | 39 | @Test 40 | public void findByProductStatus() { 41 | List productInfoList = productInfoDao.findByProductStatus(0); 42 | Assert.assertNotEquals(0,productInfoList.size()); 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/dao/SellerInfoDaoTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.dao; 2 | 3 | import cn.imlxy.entity.SellerInfo; 4 | import cn.imlxy.utils.KeyUtil; 5 | import com.sun.org.apache.xml.internal.security.keys.KeyUtils; 6 | import org.junit.Assert; 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.context.junit4.SpringRunner; 12 | 13 | import static org.junit.Assert.*; 14 | 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class SellerInfoDaoTest { 18 | 19 | @Autowired 20 | private SellerInfoDao sellerInfoDao; 21 | 22 | @Test 23 | public void save() { 24 | SellerInfo sellerInfo = new SellerInfo(); 25 | sellerInfo.setSellerId(KeyUtil.genUniqueKey()); 26 | sellerInfo.setUsername("admin"); 27 | sellerInfo.setPassword("admin"); 28 | sellerInfo.setOpenid("abc"); 29 | SellerInfo result = sellerInfoDao.save(sellerInfo); 30 | Assert.assertNotNull(result); 31 | } 32 | 33 | @Test 34 | public void findByOpenid() { 35 | SellerInfo result = sellerInfoDao.findByOpenid("abc"); 36 | Assert.assertEquals("abc", result.getOpenid()); 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/entity/mapper/ProductCategoryMapperTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.entity.mapper; 2 | 3 | import cn.imlxy.entity.ProductCategory; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.junit.Assert; 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.context.junit4.SpringRunner; 11 | 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | import static org.junit.Assert.*; 17 | 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest 20 | @Slf4j 21 | public class ProductCategoryMapperTest { 22 | @Autowired 23 | private ProductCategoryMapper mapper; 24 | 25 | @Test 26 | public void insertByMap() throws Exception { 27 | Map map = new HashMap<>(); 28 | map.put("categoryName", "小狗最爱"); 29 | map.put("category_type", 101); 30 | int result = mapper.insertByMap(map); 31 | Assert.assertEquals(1, result); 32 | } 33 | 34 | @Test 35 | public void insertByObject() { 36 | ProductCategory productCategory = new ProductCategory(); 37 | productCategory.setCategoryName("饮料"); 38 | productCategory.setCategoryType(102); 39 | int result = mapper.insertByObject(productCategory); 40 | Assert.assertEquals(1, result); 41 | } 42 | 43 | @Test 44 | public void findByCategoryType() { 45 | ProductCategory result = mapper.findByCategoryType(102); 46 | Assert.assertNotNull(result); 47 | } 48 | 49 | @Test 50 | public void findByCategoryName() { 51 | List result = mapper.findByCategoryName("饮料"); 52 | Assert.assertNotEquals(0, result.size()); 53 | } 54 | 55 | @Test 56 | public void updateByCategoryType() { 57 | int result = mapper.updateByCategoryType("小猫最爱", 102); 58 | Assert.assertEquals(1, result); 59 | } 60 | 61 | @Test 62 | public void updateByObject() { 63 | ProductCategory productCategory = new ProductCategory(); 64 | productCategory.setCategoryName("饮料"); 65 | productCategory.setCategoryType(102); 66 | int result = mapper.updateByObject(productCategory); 67 | Assert.assertEquals(1, result); 68 | } 69 | 70 | @Test 71 | public void deleteByCategoryType() { 72 | int result = mapper.deleteByCategoryType(102); 73 | Assert.assertEquals(1, result); 74 | } 75 | 76 | @Test 77 | public void selectByCategoryType() { 78 | ProductCategory productCategory = mapper.selectByCategoryType(101); 79 | Assert.assertNotNull(productCategory); 80 | } 81 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/service/impl/OrderServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.entity.OrderDetail; 5 | import cn.imlxy.enums.OrderStatusEnum; 6 | import cn.imlxy.enums.PayStatusEnum; 7 | import cn.imlxy.service.OrderService; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.junit.Assert; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.boot.test.context.SpringBootTest; 14 | import org.springframework.data.domain.Page; 15 | import org.springframework.data.domain.PageRequest; 16 | import org.springframework.test.context.junit4.SpringRunner; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import static org.junit.Assert.*; 22 | 23 | @RunWith(SpringRunner.class) 24 | @SpringBootTest 25 | @Slf4j 26 | public class OrderServiceImplTest { 27 | 28 | @Autowired 29 | private OrderServiceImpl orderService; 30 | 31 | private final String BUYER_OPENID = "1101110"; 32 | 33 | private final String ORDER_ID = "1589259537051192259"; 34 | @Test 35 | public void create() { 36 | OrderDTO orderDTO = new OrderDTO(); 37 | orderDTO.setBuyerName("小宇"); 38 | orderDTO.setBuyerAddress("imlxy.cn"); 39 | orderDTO.setBuyerPhone("12345678910"); 40 | orderDTO.setBuyerOpenid(BUYER_OPENID); 41 | 42 | List orderDetailList = new ArrayList<>(); 43 | OrderDetail o1 = new OrderDetail(); 44 | o1.setProductId("123456"); 45 | o1.setProductQuantity(1); 46 | orderDetailList.add(o1); 47 | 48 | OrderDetail o2 = new OrderDetail(); 49 | o2.setProductId("123457"); 50 | o2.setProductQuantity(2); 51 | orderDetailList.add(o2); 52 | 53 | orderDTO.setOrderDetailList(orderDetailList); 54 | OrderDTO result = orderService.create(orderDTO); 55 | log.info("【创建订单】result={}",result); 56 | Assert.assertNotNull(result); 57 | 58 | } 59 | 60 | @Test 61 | public void findOne() { 62 | OrderDTO result = orderService.findOne(ORDER_ID); 63 | log.info("【查询单个·订单】 result={}", result); 64 | Assert.assertEquals(ORDER_ID, result.getOrderId()); 65 | 66 | } 67 | 68 | @Test 69 | public void findList() { 70 | PageRequest request = new PageRequest(0, 2); 71 | Page orderDTOPage = orderService.findList(BUYER_OPENID, request); 72 | Assert.assertNotEquals(0, orderDTOPage.getTotalElements()); 73 | } 74 | 75 | @Test 76 | public void cancel() { 77 | OrderDTO orderDTO = orderService.findOne(ORDER_ID); 78 | OrderDTO result = orderService.cancel(orderDTO); 79 | Assert.assertEquals(OrderStatusEnum.CANCLE.getCode(), result.getOrderStatus()); 80 | } 81 | 82 | @Test 83 | public void finish() { 84 | OrderDTO orderDTO = orderService.findOne(ORDER_ID); 85 | OrderDTO result = orderService.finish(orderDTO); 86 | Assert.assertEquals(OrderStatusEnum.FINISHED.getCode(), result.getOrderStatus()); 87 | } 88 | 89 | @Test 90 | public void paid() { 91 | OrderDTO orderDTO = orderService.findOne(ORDER_ID); 92 | OrderDTO result = orderService.paid(orderDTO); 93 | Assert.assertEquals(PayStatusEnum.SUCCESS.getCode(), result.getPayStatus()); 94 | } 95 | 96 | @Test 97 | public void testFindList() { 98 | PageRequest request = new PageRequest(0, 2); 99 | Page orderDTOPage = orderService.findList(request); 100 | // Assert.assertNotEquals(0, orderDTOPage.getTotalElements()); 101 | Assert.assertTrue("查询所有订单列表", orderDTOPage.getTotalElements() > 0); 102 | 103 | 104 | } 105 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/service/impl/PayServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.service.OrderService; 5 | import cn.imlxy.service.PayService; 6 | import lombok.extern.slf4j.Slf4j; 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.context.junit4.SpringRunner; 12 | 13 | import static org.junit.Assert.*; 14 | 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | @Slf4j 18 | public class PayServiceImplTest { 19 | 20 | @Autowired 21 | private PayService payService; 22 | @Autowired 23 | private OrderService orderService; 24 | 25 | @Test 26 | public void create() { 27 | OrderDTO orderDTO = orderService.findOne("1589259199992503701"); 28 | payService.create(orderDTO); 29 | } 30 | 31 | @Test 32 | public void refund() { 33 | OrderDTO orderDTO = orderService.findOne("1589777859990827397"); 34 | payService.refund(orderDTO); 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/service/impl/ProductCategoryServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.entity.ProductCategory; 4 | import junit.framework.TestCase; 5 | import org.junit.Assert; 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.context.junit4.SpringRunner; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class ProductCategoryServiceImplTest extends TestCase { 18 | 19 | @Autowired 20 | private ProductCategoryServiceImpl categoryService; 21 | 22 | @Test 23 | public void testFindOne() { 24 | ProductCategory productCategory = categoryService.findOne(9); 25 | Assert.assertEquals(new Integer(1),productCategory.getCategoryId()); 26 | } 27 | 28 | @Test 29 | public void testFindAll() { 30 | List productCategoryList = categoryService.findAll(); 31 | Assert.assertNotEquals(0,productCategoryList.size()); 32 | } 33 | 34 | @Test 35 | public void testFindByCategoryTypeIn() { 36 | List productCategoryList = categoryService.findByCategoryTypeIn(Arrays.asList(1, 2, 3, 4)); 37 | Assert.assertNotEquals(0,productCategoryList.size()); 38 | 39 | } 40 | 41 | @Test 42 | public void testSave() { 43 | ProductCategory productCategory = new ProductCategory("男生专享", 7); 44 | ProductCategory result = categoryService.save(productCategory); 45 | Assert.assertNotNull(result); 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/service/impl/ProductServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.entity.ProductInfo; 4 | import cn.imlxy.enums.ProductStatusEnum; 5 | import org.aspectj.weaver.ast.Var; 6 | import org.junit.Assert; 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.data.domain.Page; 12 | import org.springframework.data.domain.PageRequest; 13 | import org.springframework.data.domain.Pageable; 14 | import org.springframework.test.context.junit4.SpringRunner; 15 | 16 | import java.math.BigDecimal; 17 | import java.util.List; 18 | 19 | import static org.junit.Assert.*; 20 | 21 | @RunWith(SpringRunner.class) 22 | @SpringBootTest 23 | public class ProductServiceImplTest { 24 | 25 | @Autowired 26 | private ProductServiceImpl productService; 27 | 28 | @Test 29 | public void findOne() { 30 | ProductInfo productInfo = productService.findOne("123456"); 31 | Assert.assertEquals("123456", productInfo.getProductId()); 32 | } 33 | 34 | @Test 35 | public void findUpAll() { 36 | List productInfoList = productService.findUpAll(); 37 | Assert.assertNotEquals(0, productInfoList.size()); 38 | } 39 | 40 | @Test 41 | public void findAll() { 42 | PageRequest request = new PageRequest(0, 2); 43 | Page productInfoPage = productService.findAll(request); 44 | // System.out.println(productInfoPage.getTotalElements()); 45 | Assert.assertNotEquals(0, productInfoPage.getTotalElements()); 46 | } 47 | 48 | @Test 49 | public void save() { 50 | ProductInfo productInfo = new ProductInfo(); 51 | productInfo.setProductId("123457"); 52 | productInfo.setProductName("皮皮虾"); 53 | productInfo.setProductPrice(new BigDecimal(3.2)); 54 | productInfo.setProductStock(100); 55 | productInfo.setProductDescription("虾好吃"); 56 | productInfo.setProductIcon("xxxx.jpg"); 57 | productInfo.setProductStatus(ProductStatusEnum.DOWN.getCode()); 58 | productInfo.setCategoryType(2); 59 | ProductInfo result = productService.save(productInfo); 60 | Assert.assertNotNull(result); 61 | } 62 | 63 | @Test 64 | public void onSale() { 65 | ProductInfo result = productService.onSale("123456"); 66 | Assert.assertEquals(ProductStatusEnum.UP, result.getProductStatusEnum()); 67 | } 68 | @Test 69 | public void offSale() { 70 | ProductInfo result = productService.offSale("123456"); 71 | Assert.assertEquals(ProductStatusEnum.DOWN, result.getProductStatusEnum()); 72 | } 73 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/service/impl/PushMessageServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.dto.OrderDTO; 4 | import cn.imlxy.service.OrderService; 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.context.junit4.SpringRunner; 10 | @RunWith(SpringRunner.class) 11 | @SpringBootTest 12 | public class PushMessageServiceImplTest { 13 | 14 | @Autowired 15 | private PushMessageServiceImpl pushMessageService; 16 | 17 | @Autowired 18 | private OrderService orderService; 19 | 20 | @Test 21 | public void orderStatus() { 22 | OrderDTO orderDTO = orderService.findOne("1589779503019487072"); 23 | pushMessageService.orderStatus(orderDTO); 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/java/cn/imlxy/service/impl/SellerServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package cn.imlxy.service.impl; 2 | 3 | import cn.imlxy.entity.SellerInfo; 4 | import org.junit.Assert; 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.context.junit4.SpringRunner; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | @RunWith(SpringRunner.class) 14 | @SpringBootTest 15 | public class SellerServiceImplTest { 16 | 17 | @Autowired 18 | private SellerServiceImpl sellerService; 19 | 20 | public static final String OPENID = "abc"; 21 | 22 | 23 | @Test 24 | public void findSellerInfoByOpenid() { 25 | SellerInfo result = sellerService.findSellerInfoByOpenid(OPENID); 26 | Assert.assertEquals(OPENID, result.getOpenid()); 27 | } 28 | } --------------------------------------------------------------------------------