diff --git a/.gitignore b/.gitignore index 4ee3979b..f50d5eb3 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ Temporary Items .apdisk /.sonar/ sonar-project.properties + +!/.mvn/wrapper/maven-wrapper.jar +*.versionsBackup diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..c6feb8bb Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..a447c9fa --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index b0ff29de..2f01901c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,15 +8,15 @@ language: java jdk: - oraclejdk8 -script: "mvn clean package -Dmaven.test.skip=true" - +script: "./mvnw clean package -DskipTests=true" + #script: # - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar - + branches: only: - develop - + cache: directories: - '$HOME/.m2/repository' diff --git a/check-dependency-updates.sh b/check-dependency-updates.sh new file mode 100755 index 00000000..13e8f0ef --- /dev/null +++ b/check-dependency-updates.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +./mvnw org.codehaus.mojo:versions-maven-plugin:display-dependency-updates diff --git a/check-plugin-updates.sh b/check-plugin-updates.sh new file mode 100755 index 00000000..0ce88b4d --- /dev/null +++ b/check-plugin-updates.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +./mvnw org.codehaus.mojo:versions-maven-plugin:display-plugin-updates diff --git a/check-property-updates.sh b/check-property-updates.sh new file mode 100755 index 00000000..4dd46a17 --- /dev/null +++ b/check-property-updates.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +./mvnw org.codehaus.mojo:versions-maven-plugin:display-property-updates diff --git a/mvnw b/mvnw new file mode 100755 index 00000000..6ecc150a --- /dev/null +++ b/mvnw @@ -0,0 +1,236 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # + # Look for the Apple JDKs first to preserve the existing behaviour, and then look + # for the new JDKs provided by Oracle. + # + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then + # + # Oracle JDKs + # + export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then + # + # Apple JDKs + # + export JAVA_HOME=`/usr/libexec/java_home` + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + local basedir=$(pwd) + local wdir=$(pwd) + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + wdir=$(cd "$wdir/.."; pwd) + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# avoid using MAVEN_CMD_LINE_ARGS below since that would loose parameter escaping in $@ +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 00000000..8bb82754 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,146 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%MAVEN_CONFIG% %* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR=""%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# avoid using MAVEN_CMD_LINE_ARGS below since that would loose parameter escaping in %* +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index 6a683db1..10d2beb9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,9 +6,9 @@ 4.0.0 com.github.binarywang weixin-java-parent - 2.9.0 + 2.9.9.BETA pom - WeiXin Java Tools - Parent + Weixin Java Tools - Parent 微信公众号、企业号上级POM https://github.com/wechat-group/weixin-java-tools @@ -108,8 +108,6 @@ 1.7 UTF-8 - true - true 4.5 9.3.0.RC0 @@ -225,6 +223,13 @@ ${jetty.version} test + + org.assertj + assertj-guava + 3.0.0 + test + + redis.clients jedis @@ -235,7 +240,7 @@ org.projectlombok lombok 1.16.18 - compile + provided @@ -353,15 +358,6 @@ deploy - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.0 - - UTF-8 - - - org.apache.maven.plugins maven-checkstyle-plugin diff --git a/quality-checks/google_checks.xml b/quality-checks/google_checks.xml index af449802..654e7cc8 100644 --- a/quality-checks/google_checks.xml +++ b/quality-checks/google_checks.xml @@ -32,7 +32,7 @@ - + @@ -69,9 +69,9 @@ + value="WhitespaceAround: ''{0}''后面没有空格。Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/> + value="WhitespaceAround: ''{0}''前面没有加空格。"/> @@ -100,11 +100,11 @@ + value="包名 ''{0}'' 必须匹配模式:''{1}''。"/> + value="类型名 ''{0}'' 必须匹配模式:''{1}''。"/> @@ -114,28 +114,28 @@ + value="参数名''{0}'' 必须匹配模式:''{1}''。"/> + value="本地变量名 ''{0}'' 必须匹配模式:''{1}''。"/> + value="类的类型名 ''{0}'' 必须匹配模式:''{1}''。"/> + value="方法类型名 ''{0}'' 必须匹配模式:''{1}''。"/> + value="Interface type name ''{0}'' 必须匹配模式:''{1}''。"/> @@ -148,14 +148,6 @@ - - - - - - - - @@ -186,7 +178,6 @@ - @@ -207,7 +198,7 @@ + value="方法名 ''{0}'' 必须匹配模式:''{1}''."/> @@ -215,6 +206,5 @@ - diff --git a/weixin-java-common/pom.xml b/weixin-java-common/pom.xml index 7dcff6ad..4572c070 100644 --- a/weixin-java-common/pom.xml +++ b/weixin-java-common/pom.xml @@ -7,11 +7,11 @@ com.github.binarywang weixin-java-parent - 2.9.0 + 2.9.9.BETA weixin-java-common - WeiXin Java Tools - Common + Weixin Java Tools - Common 微信公众号、企业号Java SDK Common diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java index f30a0ae0..98d45e31 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,9 +23,6 @@ package me.chanjar.weixin.common.session; * * @author Craig R. McClanahan */ - public class Constants { - - public static final String Package = "me.chanjar.weixin.common.session"; - + public static final String PACKAGE = "me.chanjar.weixin.common.session"; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java index f9d61707..62b60927 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java @@ -11,13 +11,12 @@ public class StandardSession implements WxSession, InternalSession { /** * The string manager for this package. */ - protected static final StringManager sm = StringManager.getManager(Constants.Package); + protected static final StringManager SM = StringManager.getManager(Constants.PACKAGE); /** * Type array. */ private static final String[] EMPTY_ARRAY = new String[0]; - // ------------------------------ WxSession protected Map attributes = new ConcurrentHashMap<>(); /** * The session identifier of this Session. @@ -73,7 +72,7 @@ public class StandardSession implements WxSession, InternalSession { if (!isValidInternal()) { throw new IllegalStateException - (sm.getString("sessionImpl.getAttribute.ise")); + (SM.getString("sessionImpl.getAttribute.ise")); } if (name == null) { @@ -86,7 +85,7 @@ public class StandardSession implements WxSession, InternalSession { @Override public Enumeration getAttributeNames() { if (!isValidInternal()) { - throw new IllegalStateException(sm.getString("sessionImpl.getAttributeNames.ise")); + throw new IllegalStateException(SM.getString("sessionImpl.getAttributeNames.ise")); } Set names = new HashSet<>(); @@ -98,7 +97,7 @@ public class StandardSession implements WxSession, InternalSession { public void setAttribute(String name, Object value) { // Name cannot be null if (name == null) { - throw new IllegalArgumentException(sm.getString("sessionImpl.setAttribute.namenull")); + throw new IllegalArgumentException(SM.getString("sessionImpl.setAttribute.namenull")); } // Null value is the same as removeAttribute() @@ -109,7 +108,7 @@ public class StandardSession implements WxSession, InternalSession { // Validate our current state if (!isValidInternal()) { - throw new IllegalStateException(sm.getString("sessionImpl.setAttribute.ise", getIdInternal())); + throw new IllegalStateException(SM.getString("sessionImpl.setAttribute.ise", getIdInternal())); } this.attributes.put(name, value); @@ -123,8 +122,9 @@ public class StandardSession implements WxSession, InternalSession { @Override public void invalidate() { - if (!isValidInternal()) - throw new IllegalStateException(sm.getString("sessionImpl.invalidate.ise")); + if (!isValidInternal()) { + throw new IllegalStateException(SM.getString("sessionImpl.invalidate.ise")); + } // Cause this session to expire expire(); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java index f20fd5c2..bfc0d010 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java @@ -13,8 +13,7 @@ import java.util.concurrent.atomic.AtomicBoolean; */ public class StandardSessionManager implements WxSessionManager, InternalSessionManager { - protected static final StringManager sm = - StringManager.getManager(Constants.Package); + protected static final StringManager SM = StringManager.getManager(Constants.PACKAGE); /** * The descriptive name of this Manager implementation (for logging). */ @@ -82,7 +81,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession public WxSession getSession(String sessionId, boolean create) { if (sessionId == null) { throw new IllegalStateException - (sm.getString("sessionManagerImpl.getSession.ise")); + (SM.getString("sessionManagerImpl.getSession.ise")); } InternalSession session = findSession(sessionId); @@ -124,25 +123,24 @@ public class StandardSessionManager implements WxSessionManager, InternalSession @Override public InternalSession findSession(String id) { - - if (id == null) + if (id == null) { return (null); + } return this.sessions.get(id); - } @Override public InternalSession createSession(String sessionId) { if (sessionId == null) { throw new IllegalStateException - (sm.getString("sessionManagerImpl.createSession.ise")); + (SM.getString("sessionManagerImpl.createSession.ise")); } if ((this.maxActiveSessions >= 0) && (getActiveSessions() >= this.maxActiveSessions)) { this.rejectedSessions++; throw new TooManyActiveSessionsException( - sm.getString("sessionManagerImpl.createSession.tmase"), + SM.getString("sessionManagerImpl.createSession.tmase"), this.maxActiveSessions); } @@ -192,7 +190,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession while (true) { try { // 每秒清理一次 - Thread.sleep(StandardSessionManager.this.backgroundProcessorDelay * 1000l); + Thread.sleep(StandardSessionManager.this.backgroundProcessorDelay * 1000L); backgroundProcess(); } catch (InterruptedException e) { StandardSessionManager.this.log.error("SessionManagerImpl.backgroundProcess error", e); @@ -230,8 +228,9 @@ public class StandardSessionManager implements WxSessionManager, InternalSession @Override public void backgroundProcess() { this.count = (this.count + 1) % this.processExpiresFrequency; - if (this.count == 0) + if (this.count == 0) { processExpires(); + } } /** @@ -243,16 +242,18 @@ public class StandardSessionManager implements WxSessionManager, InternalSession InternalSession sessions[] = findSessions(); int expireHere = 0; - if (this.log.isDebugEnabled()) + if (this.log.isDebugEnabled()) { this.log.debug("Start expire sessions {} at {} sessioncount {}", getName(), timeNow, sessions.length); - for (int i = 0; i < sessions.length; i++) { - if (sessions[i] != null && !sessions[i].isValid()) { + } + for (InternalSession session : sessions) { + if (session != null && !session.isValid()) { expireHere++; } } long timeEnd = System.currentTimeMillis(); - if (this.log.isDebugEnabled()) + if (this.log.isDebugEnabled()) { this.log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere); + } this.processingTime += (timeEnd - timeNow); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java index 12ce3a4e..fb031e23 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java @@ -32,7 +32,6 @@ public class BeanUtils { * 检查bean里标记为@Required的field是否为空,为空则抛异常 * * @param bean 要检查的bean对象 - * @throws WxErrorException */ public static void checkRequiredFields(Object bean) throws WxErrorException { List requiredFields = Lists.newArrayList(); @@ -68,39 +67,4 @@ public class BeanUtils { } } - /** - * 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象 - * - * @param bean 包含@XStreamAlias的xml bean对象 - * @return map对象 - */ - public static Map xmlBean2Map(Object bean) { - Map result = Maps.newHashMap(); - List fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields())); - fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields())); - for (Field field : fields) { - try { - boolean isAccessible = field.isAccessible(); - field.setAccessible(true); - if (field.get(bean) == null) { - field.setAccessible(isAccessible); - continue; - } - - if (field.isAnnotationPresent(XStreamAlias.class)) { - result.put(field.getAnnotation(XStreamAlias.class).value(), field.get(bean).toString()); - } else if (!Modifier.isStatic(field.getModifiers())) { - //忽略掉静态成员变量 - result.put(field.getName(), field.get(bean).toString()); - } - - field.setAccessible(isAccessible); - } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { - log.error(e.getMessage(), e); - } - - } - - return result; - } } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java index c91e8ac0..f16d3bd3 100755 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java @@ -28,10 +28,10 @@ import java.util.Random; */ public class WxCryptUtil { - private static final Base64 base64 = new Base64(); + private static final Base64 BASE64 = new Base64(); private static final Charset CHARSET = StandardCharsets.UTF_8; - private static final ThreadLocal builderLocal = new ThreadLocal() { + private static final ThreadLocal BUILDER_LOCAL = new ThreadLocal() { @Override protected DocumentBuilder initialValue() { try { @@ -65,7 +65,7 @@ public class WxCryptUtil { static String extractEncryptPart(String xml) { try { - DocumentBuilder db = builderLocal.get(); + DocumentBuilder db = BUILDER_LOCAL.get(); Document document = db.parse(new InputSource(new StringReader(xml))); Element root = document.getDocumentElement(); @@ -192,7 +192,7 @@ public class WxCryptUtil { byte[] encrypted = cipher.doFinal(unencrypted); // 使用BASE64对加密后的字符串进行编码 - return base64.encodeToString(encrypted); + return BASE64.encodeToString(encrypted); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java index 9d24d6d3..234422b0 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java @@ -8,7 +8,7 @@ import java.nio.file.Files; public class FileUtils { /** - * 创建临时文件 + * 创建临时文件. * * @param inputStream 输入文件流 * @param name 文件名 @@ -24,7 +24,7 @@ public class FileUtils { } /** - * 创建临时文件 + * 创建临时文件. * * @param inputStream 输入文件流 * @param name 文件名 diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java index c692eb91..eff5907f 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java @@ -4,5 +4,16 @@ package me.chanjar.weixin.common.util.http; * Created by ecoolper on 2017/4/28. */ public enum HttpType { - JODD_HTTP, APACHE_HTTP, OK_HTTP; + /** + * jodd-http. + */ + JODD_HTTP, + /** + * apache httpclient. + */ + APACHE_HTTP, + /** + * okhttp. + */ + OK_HTTP } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java index 80f81992..b3ddaf3c 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java @@ -56,11 +56,14 @@ public class OkHttpMediaDownloadRequestExecutor extends BaseMediaDownloadRequest return null; } - File file = File.createTempFile(FilenameUtils.getBaseName(fileName), FilenameUtils.getExtension(fileName), - super.tmpDirFile); + File file = File.createTempFile( + FilenameUtils.getBaseName(fileName), "." + FilenameUtils.getExtension(fileName), super.tmpDirFile + ); + try (BufferedSink sink = Okio.buffer(Okio.sink(file))) { sink.writeAll(response.body().source()); } + file.deleteOnExit(); return file; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java index 6166da9e..88285394 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java @@ -1,14 +1,5 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; - import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -16,7 +7,6 @@ import com.google.gson.JsonObject; import java.util.List; - public class GsonHelper { public static boolean isNull(JsonElement element) { @@ -77,7 +67,7 @@ public class GsonHelper { public static long getAsPrimitiveLong(JsonElement element) { Long r = getAsLong(element); - return r == null ? 0l : r; + return r == null ? 0L : r; } public static Integer getAsInteger(JsonElement element) { @@ -95,7 +85,7 @@ public class GsonHelper { public static boolean getAsPrimitiveBool(JsonElement element) { Boolean r = getAsBoolean(element); - return r != null && r.booleanValue(); + return r != null && r; } public static Double getAsDouble(JsonElement element) { @@ -130,6 +120,20 @@ public class GsonHelper { return result.toArray(new Integer[0]); } + public static String[] getStringArray(JsonObject o, String string) { + JsonArray jsonArray = getAsJsonArray(o.getAsJsonArray(string)); + if (jsonArray == null) { + return null; + } + + List result = Lists.newArrayList(); + for (int i = 0; i < jsonArray.size(); i++) { + result.add(jsonArray.get(i).getAsString()); + } + + return result.toArray(new String[0]); + } + public static Long[] getLongArray(JsonObject o, String string) { JsonArray jsonArray = getAsJsonArray(o.getAsJsonArray(string)); if (jsonArray == null) { diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java index e7d700e9..4d19ec3a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; import com.google.gson.*; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java index abd0da60..6646ed8d 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; import com.google.gson.*; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java index 662b7442..f33e90d5 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.common.util.json; import com.google.gson.*; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java index 3d66125e..e3f4aa05 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java @@ -46,8 +46,7 @@ import java.util.*; */ public class StringManager { - private static final Map> managers = - new Hashtable<>(); + private static final Map> MANAGERS = new Hashtable<>(); private static int LOCALE_CACHE_SIZE = 10; /** * The ResourceBundle for this StringManager. @@ -118,16 +117,16 @@ public class StringManager { public static final synchronized StringManager getManager( String packageName, Locale locale) { - Map map = managers.get(packageName); + Map map = MANAGERS.get(packageName); if (map == null) { - /* - * Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE. - * Expansion occurs when size() exceeds capacity. Therefore keep - * size at or below capacity. - * removeEldestEntry() executes after insertion therefore the test - * for removal needs to use one less than the maximum desired size - * - */ + /* + * Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE. + * Expansion occurs when size() exceeds capacity. Therefore keep + * size at or below capacity. + * removeEldestEntry() executes after insertion therefore the test + * for removal needs to use one less than the maximum desired size + * + */ map = new LinkedHashMap(LOCALE_CACHE_SIZE, 1, true) { private static final long serialVersionUID = 1L; @@ -137,7 +136,7 @@ public class StringManager { return size() > (LOCALE_CACHE_SIZE - 1); } }; - managers.put(packageName, map); + MANAGERS.put(packageName, map); } StringManager mgr = map.get(locale); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java index aa2ce176..e1a00c33 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.common.util.xml; import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider; import com.thoughtworks.xstream.core.util.QuickWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; @@ -13,7 +14,7 @@ import java.io.Writer; public class XStreamInitializer { public static XStream getInstance() { - XStream xstream = new XStream(new XppDriver() { + XStream xstream = new XStream(new PureJavaReflectionProvider(), new XppDriver() { @Override public HierarchicalStreamWriter createWriter(Writer out) { @@ -42,6 +43,7 @@ public class XStreamInitializer { }; } }); + xstream.ignoreUnknownElements(); xstream.setMode(XStream.NO_REFERENCES); xstream.addPermission(NullPermission.NULL); diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java index 8599b29f..6f98b3d9 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java @@ -3,15 +3,17 @@ package me.chanjar.weixin.common.api; import org.testng.Assert; import org.testng.annotations.Test; +import java.util.concurrent.TimeUnit; + import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; @Test public class WxMessageInMemoryDuplicateCheckerTest { - private WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000l, 1000l); + private WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000L, 1000L); public void test() throws InterruptedException { - Long[] msgIds = new Long[]{1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l}; + Long[] msgIds = new Long[]{1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L}; // 第一次检查 for (Long msgId : msgIds) { @@ -20,14 +22,14 @@ public class WxMessageInMemoryDuplicateCheckerTest { } // 过1秒再检查 - Thread.sleep(1000l); + TimeUnit.SECONDS.sleep(1); for (Long msgId : msgIds) { boolean result = checker.isDuplicate(String.valueOf(msgId)); assertTrue(result); } // 过1.5秒再检查 - Thread.sleep(1500l); + TimeUnit.MILLISECONDS.sleep(1500L); for (Long msgId : msgIds) { boolean result = checker.isDuplicate(String.valueOf(msgId)); assertFalse(result); diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java index 93ad2bfc..84d80eab 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java @@ -80,7 +80,7 @@ public class SessionTest { InternalSession abc = ism.createSession("abc"); abc.endAccess(); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -99,7 +99,7 @@ public class SessionTest { abc.setMaxInactiveInterval(1); abc.endAccess(); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } diff --git a/weixin-java-cp/pom.xml b/weixin-java-cp/pom.xml index f589bbe0..9c744eac 100644 --- a/weixin-java-cp/pom.xml +++ b/weixin-java-cp/pom.xml @@ -7,11 +7,11 @@ com.github.binarywang weixin-java-parent - 2.9.0 + 2.9.9.BETA weixin-java-cp - WeiXin Java Tools - CP + Weixin Java Tools - CP 微信企业号Java SDK @@ -69,6 +69,16 @@ logback-classic test + + org.projectlombok + lombok + + + + org.assertj + assertj-guava + test + diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpDepartmentService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpDepartmentService.java index 7ca1ade3..f981f035 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpDepartmentService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpDepartmentService.java @@ -29,11 +29,12 @@ public interface WxCpDepartmentService { /** *
-   * 部门管理接口 - 查询所有部门
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=部门管理接口
+   * 部门管理接口 - 查询部门
+   * 详情请见: http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AE%A1%E7%90%86%E9%83%A8%E9%97%A8#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E5.88.97.E8.A1.A8
    * 
+ * @param id 部门id。获取指定部门及其下的子部门。非必需,可为null */ - List listAll() throws WxErrorException; + List list(Integer id) throws WxErrorException; /** *
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
index 03df947d..3a63de98 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
@@ -19,9 +19,9 @@ import java.util.List;
 
 /**
  * 微信API的Service
+ * @author chanjaster
  */
 public interface WxCpService {
-
   /**
    * 
    * 验证推送过来的消息的正确性
@@ -85,42 +85,6 @@ public interface WxCpService {
    */
   WxJsapiSignature createJsapiSignature(String url) throws WxErrorException;
 
-  /**
-   * @deprecated  请使用 {@link WxCpMenuService#create(WxMenu)}
-   */
-  @Deprecated
-  void menuCreate(WxMenu menu) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMenuService#create(Integer, WxMenu)}
-   */
-  @Deprecated
-  void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMenuService#delete()}  }
-   */
-  @Deprecated
-  void menuDelete() throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMenuService#delete(Integer)}
-   */
-  @Deprecated
-  void menuDelete(Integer agentId) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMenuService#get() }
-   */
-  @Deprecated
-  WxMenu menuGet() throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMenuService#get(Integer)}
-   */
-  @Deprecated
-  WxMenu menuGet(Integer agentId) throws WxErrorException;
-
   /**
    * 
    * 发送消息
@@ -131,175 +95,6 @@ public interface WxCpService {
    */
   WxCpMessageSendResult messageSend(WxCpMessage message) throws WxErrorException;
 
-  /**
-   * @deprecated  请使用 {@link WxCpDepartmentService#create(WxCpDepart)}
-   */
-  @Deprecated
-  Integer departCreate(WxCpDepart depart) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpDepartmentService#update(WxCpDepart)}
-   */
-  @Deprecated
-  void departUpdate(WxCpDepart group) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpDepartmentService#delete(Integer)}
-   */
-  @Deprecated
-  void departDelete(Integer departId) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpDepartmentService#listAll() }
-   */
-  @Deprecated
-  List departGet() throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMediaService#upload(String, String, InputStream)}
-   */
-  @Deprecated
-  WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream)
-    throws WxErrorException, IOException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMediaService#upload(String, File)}
-   */
-  @Deprecated
-  WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpMediaService#download(String)}
-   */
-  @Deprecated
-  File mediaDownload(String mediaId) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#authenticate(String)}
-   */
-  @Deprecated
-  void userAuthenticated(String userId) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#create(WxCpUser)}
-   */
-  @Deprecated
-  void userCreate(WxCpUser user) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#update(WxCpUser)}
-   */
-  @Deprecated
-  void userUpdate(WxCpUser user) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#delete(String...)}
-   */
-  @Deprecated
-  void userDelete(String userid) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#delete(String...)}
-   */
-  @Deprecated
-  void userDelete(String[] userids) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#getById(String)}
-   */
-  @Deprecated
-  WxCpUser userGet(String userid) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#listByDepartment(Integer, Boolean, Integer)}
-   */
-  @Deprecated
-  List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpUserService#listSimpleByDepartment(Integer, Boolean, Integer)}
-   */
-  @Deprecated
-  List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpTagService#create(String)}
-   */
-  @Deprecated
-  String tagCreate(String tagName) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpTagService#update(String, String)}
-   */
-  @Deprecated
-  void tagUpdate(String tagId, String tagName) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpTagService#delete(String)}
-   */
-  @Deprecated
-  void tagDelete(String tagId) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpTagService#listAll()}
-   */
-  @Deprecated
-  List tagGet() throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpTagService#listUsersByTagId(String)}
-   */
-  @Deprecated
-  List tagGetUsers(String tagId) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpTagService#addUsers2Tag(String, List, List)}
-   */
-  @Deprecated
-  void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpTagService#removeUsersFromTag(String, List)}
-   */
-  @Deprecated
-  void tagRemoveUsers(String tagId, List userIds) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpOAuth2Service#buildAuthorizationUrl(String)}
-   */
-  @Deprecated
-  String oauth2buildAuthorizationUrl(String state);
-
-  /**
-   * @deprecated  请使用 {@link WxCpOAuth2Service#buildAuthorizationUrl(String, String)}
-   */
-  @Deprecated
-  String oauth2buildAuthorizationUrl(String redirectUri, String state);
-
-  /**
-   * @deprecated  请使用 {@link WxCpOAuth2Service#getUserInfo(String)}
-   */
-  @Deprecated
-  String[] oauth2getUserInfo(String code) throws WxErrorException;
-
-  /**
-   * @deprecated  请使用 {@link WxCpOAuth2Service#getUserInfo(Integer, String)}
-   */
-  @Deprecated
-  String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException;
-
-  /**
-   * 
-   * 邀请成员关注
-   * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8
-   * 
- * - * @param userId 用户的userid - * @param inviteTips 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。 - * @return 1:微信邀请 2.邮件邀请 - */ - int invite(String userId, String inviteTips) throws WxErrorException; - /** *
    * 获取微信服务器的ip段
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java
index 49ef9134..93333fef 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java
@@ -4,6 +4,7 @@ import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.cp.bean.WxCpUser;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 
@@ -80,4 +81,56 @@ public interface WxCpUserService {
    * @param userid 用户id
    */
   WxCpUser getById(String userid) throws WxErrorException;
+
+  /**
+   * 
+   * 邀请成员关注
+   * http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8
+   * 
+ * + * @param userId 用户的userid + * @param inviteTips 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。 + * @return 1:微信邀请 2.邮件邀请 + * @deprecated api obsoleted. 邀请关注的功能微信企业号已经下线了, + * 详细请参考该链接点击查看 https://qy.weixin.qq.com/cgi-bin/homepagenotify?action=get&id=46 + */ + @Deprecated + int invite(String userId, String inviteTips) throws WxErrorException; + + /** + *
+   *  userid转openid.
+   *  该接口使用场景为微信支付、微信红包和企业转账。
+   *
+   * 在使用微信支付的功能时,需要自行将企业微信的userid转成openid。
+   * 在使用微信红包功能时,需要将应用id和userid转成appid和openid才能使用。
+   * 注:需要成员使用微信登录企业微信或者关注微信插件才能转成openid
+   *
+   * 文档地址:https://work.weixin.qq.com/api/doc#11279
+   * 
+ * + * @param userId 企业内的成员id + * @param agentId 非必填,整型,仅用于发红包。其它场景该参数不要填,如微信支付、企业转账、电子发票 + * @return map对象,可能包含以下值: + * - openid 企业微信成员userid对应的openid,若有传参agentid,则是针对该agentid的openid。否则是针对企业微信corpid的openid + * - appid 应用的appid,若请求包中不包含agentid则不返回appid。该appid在使用微信红包时会用到 + */ + Map userId2Openid(String userId, Integer agentId) throws WxErrorException; + + /** + *
+   * openid转userid
+   *
+   * 该接口主要应用于使用微信支付、微信红包和企业转账之后的结果查询。
+   * 开发者需要知道某个结果事件的openid对应企业微信内成员的信息时,可以通过调用该接口进行转换查询。
+   * 权限说明:
+   * 管理组需对openid对应的企业微信成员有查看权限。
+   *
+   * 文档地址:https://work.weixin.qq.com/api/doc#11279
+   * 
+ * + * @param openid 在使用微信支付、微信红包和企业转账之后,返回结果的openid + * @return userid 该openid在企业微信对应的成员userid + */ + String openid2UserId(String openid) throws WxErrorException; } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java index 82cd8c34..d836517f 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java @@ -48,13 +48,13 @@ public class WxCpDepartmentServiceImpl implements WxCpDepartmentService { } @Override - public List listAll() throws WxErrorException { + public List list(Integer id) throws WxErrorException { String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; + if (id != null) { + url += "?id=" + id; + } + String responseContent = this.mainService.get(url, null); - /* - * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } - * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } - */ JsonElement tmpJsonElement = new JsonParser().parse(responseContent); return WxCpGsonBuilder.INSTANCE.create() .fromJson(tmpJsonElement.getAsJsonObject().get("department"), diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java index a317bfb4..123d7507 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java @@ -47,7 +47,7 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service { @Override public String[] getUserInfo(String code) throws WxErrorException { - return getUserInfo(this.mainService.getWxCpConfigStorage().getAgentId(), code); + return this.getUserInfo(this.mainService.getWxCpConfigStorage().getAgentId(), code); } @Override diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java index aac09e34..797e4a4c 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java @@ -138,188 +138,6 @@ public abstract class WxCpServiceAbstractImpl implements WxCpService, Requ return WxCpMessageSendResult.fromJson(this.post(url, message.toJson())); } - @Override - @Deprecated - public void menuCreate(WxMenu menu) throws WxErrorException { - this.getMenuService().create(menu); - } - - @Override - @Deprecated - public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { - this.getMenuService().create(agentId, menu); - } - - @Override - @Deprecated - public void menuDelete() throws WxErrorException { - this.getMenuService().delete(); - } - - @Override - @Deprecated - public void menuDelete(Integer agentId) throws WxErrorException { - this.getMenuService().delete(agentId); - } - - @Override - @Deprecated - public WxMenu menuGet() throws WxErrorException { - return this.getMenuService().get(); - } - - @Override - @Deprecated - public WxMenu menuGet(Integer agentId) throws WxErrorException { - return this.getMenuService().get(agentId); - } - - @Override - @Deprecated - public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) - throws WxErrorException, IOException { - return this.getMediaService().upload(mediaType, fileType, inputStream); - } - - @Override - @Deprecated - public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { - return this.getMediaService().upload(mediaType, file); - } - - @Override - @Deprecated - public File mediaDownload(String mediaId) throws WxErrorException { - return this.getMediaService().download(mediaId); - } - - @Override - @Deprecated - public void userAuthenticated(String userId) throws WxErrorException { - this.getUserService().authenticate(userId); - } - - @Override - @Deprecated - public void userCreate(WxCpUser user) throws WxErrorException { - this.getUserService().create(user); - } - - @Override - @Deprecated - public void userUpdate(WxCpUser user) throws WxErrorException { - this.getUserService().update(user); - } - - @Override - @Deprecated - public void userDelete(String userid) throws WxErrorException { - this.getUserService().delete(userid); - } - - @Override - @Deprecated - public void userDelete(String[] userids) throws WxErrorException { - this.getUserService().delete(userids); - } - - @Override - @Deprecated - public WxCpUser userGet(String userid) throws WxErrorException { - return this.getUserService().getById(userid); - } - - @Override - @Deprecated - public List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - return this.getUserService().listByDepartment(departId, fetchChild, status); - } - - @Override - @Deprecated - public List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { - return this.getUserService().listSimpleByDepartment(departId, fetchChild, status); - } - - @Override - @Deprecated - public String tagCreate(String tagName) throws WxErrorException { - return this.getTagService().create(tagName); - } - - @Override - @Deprecated - public void tagUpdate(String tagId, String tagName) throws WxErrorException { - this.getTagService().update(tagId, tagName); - } - - @Override - @Deprecated - public void tagDelete(String tagId) throws WxErrorException { - this.getTagService().delete(tagId); - } - - @Override - @Deprecated - public List tagGet() throws WxErrorException { - return this.getTagService().listAll(); - } - - @Override - @Deprecated - public List tagGetUsers(String tagId) throws WxErrorException { - return this.getTagService().listUsersByTagId(tagId); - } - - @Override - @Deprecated - public void tagAddUsers(String tagId, List userIds, List partyIds) throws WxErrorException { - this.getTagService().addUsers2Tag(tagId, userIds, partyIds); - } - - @Override - @Deprecated - public void tagRemoveUsers(String tagId, List userIds) throws WxErrorException { - this.getTagService().removeUsersFromTag(tagId, userIds); - } - - @Override - @Deprecated - public String oauth2buildAuthorizationUrl(String state) { - return this.getOauth2Service().buildAuthorizationUrl(state); - } - - @Override - @Deprecated - public String oauth2buildAuthorizationUrl(String redirectUri, String state) { - return this.getOauth2Service().buildAuthorizationUrl(redirectUri, state); - } - - @Override - @Deprecated - public String[] oauth2getUserInfo(String code) throws WxErrorException { - return this.getOauth2Service().getUserInfo(code); - } - - @Override - @Deprecated - public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { - return this.getOauth2Service().getUserInfo(agentId, code); - } - - @Override - public int invite(String userId, String inviteTips) throws WxErrorException { - String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("userid", userId); - if (StringUtils.isNotEmpty(inviteTips)) { - jsonObject.addProperty("invite_tips", inviteTips); - } - String responseContent = post(url, jsonObject.toString()); - JsonElement tmpJsonElement = new JsonParser().parse(responseContent); - return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); - } - @Override public String[] getCallbackIp() throws WxErrorException { String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; @@ -516,30 +334,6 @@ public abstract class WxCpServiceAbstractImpl implements WxCpService, Requ return userService; } - @Override - @Deprecated - public Integer departCreate(WxCpDepart depart) throws WxErrorException { - return this.getDepartmentService().create(depart); - } - - @Override - @Deprecated - public void departUpdate(WxCpDepart depart) throws WxErrorException { - this.getDepartmentService().update(depart); - } - - @Override - @Deprecated - public void departDelete(Integer departId) throws WxErrorException { - this.getDepartmentService().delete(departId); - } - - @Override - @Deprecated - public List departGet() throws WxErrorException { - return this.getDepartmentService().listAll(); - } - @Override public RequestHttp getRequestHttp() { return this; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java index 13009427..f0249e8e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.cp.api.impl; +import com.google.common.collect.Maps; import com.google.gson.*; import com.google.gson.reflect.TypeToken; import me.chanjar.weixin.common.exception.WxErrorException; @@ -7,8 +8,10 @@ import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.api.WxCpUserService; import me.chanjar.weixin.cp.bean.WxCpUser; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import org.apache.commons.lang3.StringUtils; import java.util.List; +import java.util.Map; /** *
@@ -112,4 +115,50 @@ public class WxCpUserServiceImpl implements WxCpUserService {
       );
   }
 
+  @Override
+  @Deprecated
+  public int invite(String userId, String inviteTips) throws WxErrorException {
+    String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send";
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("userid", userId);
+    if (StringUtils.isNotEmpty(inviteTips)) {
+      jsonObject.addProperty("invite_tips", inviteTips);
+    }
+    String responseContent = this.mainService.post(url, jsonObject.toString());
+    JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
+    return tmpJsonElement.getAsJsonObject().get("type").getAsInt();
+  }
+
+  @Override
+  public Map userId2Openid(String userId, Integer agentId) throws WxErrorException {
+    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid";
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("userid", userId);
+    if (agentId != null) {
+      jsonObject.addProperty("agentid", agentId);
+    }
+
+    String responseContent = this.mainService.post(url, jsonObject.toString());
+    JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
+    Map result = Maps.newHashMap();
+    if (tmpJsonElement.getAsJsonObject().get("openid") != null) {
+      result.put("openid", tmpJsonElement.getAsJsonObject().get("openid").getAsString());
+    }
+
+    if (tmpJsonElement.getAsJsonObject().get("appid") != null) {
+      result.put("appid", tmpJsonElement.getAsJsonObject().get("appid").getAsString());
+    }
+
+    return result;
+  }
+
+  @Override
+  public String openid2UserId(String openid) throws WxErrorException {
+    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_userid";
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("openid", openid);
+    String responseContent = this.mainService.post(url, jsonObject.toString());
+    JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
+    return tmpJsonElement.getAsJsonObject().get("userid").getAsString();
+  }
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java
index 0a3aaeb7..0acbb49b 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java
@@ -16,8 +16,14 @@ import java.util.List;
 @Data
 public class WxCpUser implements Serializable {
   public enum Gender {
+    /**
+     * 男
+     */
     MALE("男", "1"),
-    FEMAIL("女", "2");
+    /**
+     * 女
+     */
+    FEMALE("女", "2");
 
     private String genderName;
     private String code;
@@ -40,7 +46,7 @@ public class WxCpUser implements Serializable {
         return Gender.MALE;
       }
       if ("2".equals(code)) {
-        return Gender.FEMAIL;
+        return Gender.FEMALE;
       }
 
       return null;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java
index dc77875e..cbef3f87 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java
@@ -3,11 +3,13 @@ package me.chanjar.weixin.cp.bean;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import com.thoughtworks.xstream.annotations.XStreamConverter;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import me.chanjar.weixin.common.api.WxConsts;
 import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
 
 @XStreamAlias("xml")
 @Data
+@EqualsAndHashCode(callSuper = false)
 public class WxCpXmlOutImageMessage extends WxCpXmlOutMessage {
   private static final long serialVersionUID = -1099446240667237313L;
 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java
index 1c354a12..6589b0b3 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java
@@ -3,11 +3,13 @@ package me.chanjar.weixin.cp.bean;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import com.thoughtworks.xstream.annotations.XStreamConverter;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import me.chanjar.weixin.common.api.WxConsts;
 import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
 
 @XStreamAlias("xml")
 @Data
+@EqualsAndHashCode(callSuper = false)
 public class WxCpXmlOutTextMessage extends WxCpXmlOutMessage {
   private static final long serialVersionUID = 2569239617185930232L;
 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java
index 6d3bd0b4..f4aabd18 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java
@@ -3,11 +3,13 @@ package me.chanjar.weixin.cp.bean;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import com.thoughtworks.xstream.annotations.XStreamConverter;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import me.chanjar.weixin.common.api.WxConsts;
 import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
 
 @XStreamAlias("xml")
 @Data
+@EqualsAndHashCode(callSuper = false)
 public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage {
   private static final long serialVersionUID = -8672761162722733622L;
 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java
index c880bccf..efe4a86f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java
@@ -3,11 +3,13 @@ package me.chanjar.weixin.cp.bean;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import com.thoughtworks.xstream.annotations.XStreamConverter;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import me.chanjar.weixin.common.api.WxConsts;
 import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
 
 @XStreamAlias("xml")
 @Data
+@EqualsAndHashCode(callSuper = false)
 public class WxCpXmlOutVoiceMessage extends WxCpXmlOutMessage {
   private static final long serialVersionUID = -7947384031546099340L;
 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java
index 03eb8f54..303ed3c4 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java
@@ -23,7 +23,7 @@ public abstract class BaseBuilder {
   public void setCommon(WxCpXmlOutMessage m) {
     m.setToUserName(this.toUserName);
     m.setFromUserName(this.fromUserName);
-    m.setCreateTime(System.currentTimeMillis() / 1000l);
+    m.setCreateTime(System.currentTimeMillis() / 1000L);
   }
 
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java
index 1b57f83b..2ce56e7d 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java
@@ -63,7 +63,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
   @Override
   public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
     this.accessToken = accessToken;
-    this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
+    this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
   }
 
   @Override
@@ -92,7 +92,7 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
   public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
     this.jsapiTicket = jsapiTicket;
     // 预留200秒的时间
-    this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
+    this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
   }
 
   @Override
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java
index 5ef99a3c..133fe2ef 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java
@@ -19,12 +19,16 @@ import java.io.File;
  */
 public class WxCpJedisConfigStorage implements WxCpConfigStorage {
 
-  /* Redis keys here */
+  /**
+   * Redis keys here
+   */
   private static final String ACCESS_TOKEN_KEY = "WX_CP_ACCESS_TOKEN";
   private static final String ACCESS_TOKEN_EXPIRES_TIME_KEY = "WX_CP_ACCESS_TOKEN_EXPIRES_TIME";
   private static final String JS_API_TICKET_KEY = "WX_CP_JS_API_TICKET";
   private static final String JS_API_TICKET_EXPIRES_TIME_KEY = "WX_CP_JS_API_TICKET_EXPIRES_TIME";
-  /* Redis clients pool */
+  /**
+   * Redis clients pool
+   */
   private final JedisPool jedisPool;
   private volatile String corpId;
   private volatile String corpSecret;
@@ -196,8 +200,7 @@ public class WxCpJedisConfigStorage implements WxCpConfigStorage {
       String expiresTimeStr = jedis.get(ACCESS_TOKEN_EXPIRES_TIME_KEY);
 
       if (expiresTimeStr != null) {
-        Long expiresTime = Long.parseLong(expiresTimeStr);
-        return expiresTime;
+        return Long.parseLong(expiresTimeStr);
       }
 
       return 0L;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java
index e08ef4df..fdc78ace 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java
@@ -1,13 +1,19 @@
 package me.chanjar.weixin.cp.util.xml;
 
-import com.thoughtworks.xstream.XStream;
-import me.chanjar.weixin.common.util.xml.XStreamInitializer;
-import me.chanjar.weixin.cp.bean.*;
-
 import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.thoughtworks.xstream.XStream;
+import me.chanjar.weixin.common.util.xml.XStreamInitializer;
+import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
+import me.chanjar.weixin.cp.bean.WxCpXmlOutImageMessage;
+import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
+import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage;
+import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage;
+import me.chanjar.weixin.cp.bean.WxCpXmlOutVideoMessage;
+import me.chanjar.weixin.cp.bean.WxCpXmlOutVoiceMessage;
+
 public class XStreamTransformer {
 
   protected static final Map CLASS_2_XSTREAM_INSTANCE = configXStreamInstance();
@@ -38,7 +44,7 @@ public class XStreamTransformer {
   }
 
   /**
-   * pojo -> xml
+   * pojo -> xml.
    */
   public static  String toXml(Class clazz, T object) {
     return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java
index d37f4535..a2134889 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java
@@ -69,7 +69,7 @@ public class WxCpMessageRouterTest {
     WxCpMessageRouter router = new WxCpMessageRouter(null);
     prepare(true, sb, router);
     router.route(message);
-    Thread.sleep(500l);
+    Thread.sleep(500);
     Assert.assertEquals(sb.toString(), expected);
   }
 
@@ -89,7 +89,7 @@ public class WxCpMessageRouterTest {
       public void run() {
         router.route(m);
         try {
-          Thread.sleep(1000l);
+          Thread.sleep(1000);
         } catch (InterruptedException e) {
         }
       }
@@ -98,7 +98,7 @@ public class WxCpMessageRouterTest {
       new Thread(r).start();
     }
 
-    Thread.sleep(1000l * 2);
+    Thread.sleep(2000);
   }
 
   @DataProvider(name = "messages-1")
@@ -184,7 +184,7 @@ public class WxCpMessageRouterTest {
     msg.setFromUserName("abc");
     router.route(msg);
 
-    Thread.sleep(2000l);
+    Thread.sleep(2000);
     Assert.assertEquals(ism.getActiveSessions(), 0);
 
   }
@@ -204,7 +204,7 @@ public class WxCpMessageRouterTest {
       msg.setFromUserName("abc");
       router.route(msg);
 
-      Thread.sleep(2000l);
+      Thread.sleep(2000);
       Assert.assertEquals(ism.getActiveSessions(), 0);
     }
     {
@@ -218,7 +218,7 @@ public class WxCpMessageRouterTest {
       msg.setFromUserName("abc");
       router.route(msg);
 
-      Thread.sleep(2000l);
+      Thread.sleep(2000);
       Assert.assertEquals(ism.getActiveSessions(), 0);
     }
 
@@ -238,7 +238,7 @@ public class WxCpMessageRouterTest {
     msg.setFromUserName("abc");
     router.route(msg);
 
-    Thread.sleep(2000l);
+    Thread.sleep(2000);
     Assert.assertEquals(ism.getActiveSessions(), 0);
 
   }
@@ -257,7 +257,7 @@ public class WxCpMessageRouterTest {
       msg.setFromUserName("abc");
       router.route(msg);
 
-      Thread.sleep(2000l);
+      Thread.sleep(2000);
       Assert.assertEquals(ism.getActiveSessions(), 0);
     }
 
@@ -271,7 +271,7 @@ public class WxCpMessageRouterTest {
       msg.setFromUserName("abc");
       router.route(msg);
 
-      Thread.sleep(2000l);
+      Thread.sleep(2000);
       Assert.assertEquals(ism.getActiveSessions(), 0);
     }
   }
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java
index 5e250208..522d169c 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java
@@ -8,6 +8,7 @@ import org.testng.annotations.*;
 
 import java.util.List;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.testng.Assert.*;
 
 /**
@@ -34,16 +35,24 @@ public class WxCpDepartmentServiceImplTest {
     System.out.println(departId);
   }
 
-  @Test
-  public void testListAll() throws Exception {
+  @DataProvider
+  public Object[][] departIds(){
+    return new Object[][]{
+      {null},
+      {1},
+      {5}
+    };
+  }
+
+  @Test(dataProvider = "departIds")
+  public void testList(Integer id) throws Exception {
     System.out.println("=================获取部门");
-    List departList = this.wxCpService.getDepartmentService().listAll();
-    assertNotNull(departList);
-    assertTrue(departList.size() > 0);
+    List departList = this.wxCpService.getDepartmentService().list(id);
+    assertThat(departList).isNotEmpty();
     for (WxCpDepart g : departList) {
       this.depart = g;
       System.out.println(this.depart.getId() + ":" + this.depart.getName());
-      assertNotNull(g.getName());
+      assertThat(g.getName()).isNotBlank();
     }
   }
 
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java
index a01f0343..bbb5dcab 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java
@@ -6,11 +6,14 @@ import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.WxCpUser;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
-import org.testng.annotations.*;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
 
 import java.util.List;
+import java.util.Map;
 
-import static org.testng.Assert.*;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
 
 /**
  * 
@@ -37,7 +40,7 @@ public class WxCpUserServiceImplTest {
     user.setName("Some Woman");
     user.setDepartIds(new Integer[]{2});
     user.setEmail("none@none.com");
-    user.setGender(WxCpUser.Gender.FEMAIL);
+    user.setGender(WxCpUser.Gender.FEMALE);
     user.setMobile("13560084979");
     user.setPosition("woman");
     user.setTelephone("3300393");
@@ -83,4 +86,24 @@ public class WxCpUserServiceImplTest {
     }
   }
 
+  @Test
+  @Deprecated
+  public void testInvite() throws Exception {
+    int result = this.wxCpService.getUserService().invite(userId, "");
+    System.out.println(result);
+  }
+
+  @Test
+  public void testUserId2Openid() throws Exception {
+    Map result = this.wxCpService.getUserService().userId2Openid(userId, null);
+    System.out.println(result);
+    assertNotNull(result);
+  }
+
+  @Test
+  public void testOpenid2UserId() throws Exception {
+    String result = this.wxCpService.getUserService().openid2UserId(userId);
+    System.out.println(result);
+    assertNotNull(result);
+  }
 }
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java
index e320d8cb..68c57c3d 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java
@@ -57,10 +57,10 @@ public class WxCpXmlMessageTest {
     WxCpXmlMessage wxMessage = WxCpXmlMessage.fromXml(xml);
     assertEquals(wxMessage.getToUserName(), "toUser");
     assertEquals(wxMessage.getFromUserName(), "fromUser");
-    assertEquals(wxMessage.getCreateTime(), new Long(1348831860l));
+    assertEquals(wxMessage.getCreateTime(), new Long(1348831860));
     assertEquals(wxMessage.getMsgType(), WxConsts.XmlMsgType.TEXT);
     assertEquals(wxMessage.getContent(), "this is a test");
-    assertEquals(wxMessage.getMsgId(), new Long(1234567890123456l));
+    assertEquals(wxMessage.getMsgId(), new Long(1234567890123456L));
     assertEquals(wxMessage.getPicUrl(), "this is a url");
     assertEquals(wxMessage.getMediaId(), "media_id");
     assertEquals(wxMessage.getFormat(), "Format");
@@ -80,7 +80,7 @@ public class WxCpXmlMessageTest {
     assertEquals(wxMessage.getPrecision(), 119.385040);
     assertEquals(wxMessage.getScanCodeInfo().getScanType(), "qrcode");
     assertEquals(wxMessage.getScanCodeInfo().getScanResult(), "1");
-    assertEquals(wxMessage.getSendPicsInfo().getCount(), new Long(1l));
+    assertEquals(wxMessage.getSendPicsInfo().getCount(), new Long(1));
     assertEquals(wxMessage.getSendPicsInfo().getPicList().get(0).getPicMd5Sum(), "1b5f7c23b5bf75682a53e7b6d163e185");
     assertEquals(wxMessage.getSendLocationInfo().getLocationX(), "23");
     assertEquals(wxMessage.getSendLocationInfo().getLocationY(), "113");
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java
index 6f366988..87c9454c 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java
@@ -9,7 +9,7 @@ public class WxCpXmlOutImageMessageTest {
   public void test() {
     WxCpXmlOutImageMessage m = new WxCpXmlOutImageMessage();
     m.setMediaId("ddfefesfsdfef");
-    m.setCreateTime(1122l);
+    m.setCreateTime(1122L);
     m.setFromUserName("from");
     m.setToUserName("to");
 
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java
index 71dbf412..128bc9a4 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java
@@ -8,7 +8,7 @@ public class WxCpXmlOutNewsMessageTest {
 
   public void test() {
     WxCpXmlOutNewsMessage m = new WxCpXmlOutNewsMessage();
-    m.setCreateTime(1122l);
+    m.setCreateTime(1122L);
     m.setFromUserName("fromUser");
     m.setToUserName("toUser");
 
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java
index 4d73b27f..fd09ed6b 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java
@@ -9,7 +9,7 @@ public class WxCpXmlOutTextMessageTest {
   public void test() {
     WxCpXmlOutTextMessage m = new WxCpXmlOutTextMessage();
     m.setContent("content");
-    m.setCreateTime(1122l);
+    m.setCreateTime(1122L);
     m.setFromUserName("from");
     m.setToUserName("to");
 
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java
index b4124c61..c5551dec 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java
@@ -11,7 +11,7 @@ public class WxCpXmlOutVideoMessageTest {
     m.setMediaId("media_id");
     m.setTitle("title");
     m.setDescription("ddfff");
-    m.setCreateTime(1122l);
+    m.setCreateTime(1122L);
     m.setFromUserName("fromUser");
     m.setToUserName("toUser");
 
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java
index f414256a..a3c9688c 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java
@@ -9,7 +9,7 @@ public class WxCpXmlOutVoiceMessageTest {
   public void test() {
     WxCpXmlOutVoiceMessage m = new WxCpXmlOutVoiceMessage();
     m.setMediaId("ddfefesfsdfef");
-    m.setCreateTime(1122l);
+    m.setCreateTime(1122L);
     m.setFromUserName("from");
     m.setToUserName("to");
 
diff --git a/weixin-java-miniapp/pom.xml b/weixin-java-miniapp/pom.xml
index d10de236..3d361324 100644
--- a/weixin-java-miniapp/pom.xml
+++ b/weixin-java-miniapp/pom.xml
@@ -7,10 +7,10 @@
   
     com.github.binarywang
     weixin-java-parent
-    2.9.0
+    2.9.9.BETA
   
   weixin-java-miniapp
-  WeiXin Java Tools - MiniApp
+  Weixin Java Tools - MiniApp
   微信小程序Java SDK
 
   
@@ -61,10 +61,19 @@
       joda-time
       test
     
+    
+      org.assertj
+      assertj-guava
+      test
+    
     
       redis.clients
       jedis
     
+    
+      org.projectlombok
+      lombok
+    
   
 
   
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java
index 4b3ec5fe..6fbeb96d 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java
@@ -7,7 +7,7 @@ import java.io.File;
 
 /**
  * 
- * 二维码相关操作接口
+ * 二维码相关操作接口.
  *
  * 接口A(createWxCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。
  *
@@ -22,9 +22,8 @@ public interface WxMaQrcodeService {
   String GET_WXACODE_UNLIMIT_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";
 
   /**
-   * 接口C
+   * 接口C: 获取小程序页面二维码.
    * 
-   * 获取小程序页面二维码
    * 适用于需要的码数量较少的业务场景
    * 通过该接口,仅能生成已发布的小程序的二维码。
    * 可以在开发者工具预览时生成开发版的带参二维码。
@@ -39,8 +38,7 @@ public interface WxMaQrcodeService {
   File createQrcode(String path) throws WxErrorException;
 
   /**
-   * 接口A
-   * 获取小程序码
+   * 接口A: 获取小程序码.
    *
    * @param path      不能为空,最大长度 128 字节
    * @param width     默认430 二维码的宽度
@@ -54,14 +52,13 @@ public interface WxMaQrcodeService {
   File createWxCode(String path) throws WxErrorException;
 
   /**
-   * 接口B
-   * 获取小程序码(永久有效、数量暂无限制)
-   * 

+ * 接口B: 获取小程序码(永久有效、数量暂无限制). + *

    * 通过该接口生成的小程序码,永久有效,数量暂无限制。
    * 用户扫描该码进入小程序后,将统一打开首页,开发者需在对应页面根据获取的码中 scene 字段的值,再做处理逻辑。
    * 使用如下代码可以获取到二维码中的 scene 字段的值。
    * 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode
-   *
+   * 
* @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) * @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面 * @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java index 9098d4ac..c437966e 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java @@ -1,5 +1,6 @@ package cn.binarywang.wx.miniapp.api; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.config.WxMaConfig; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; @@ -11,20 +12,27 @@ import me.chanjar.weixin.common.util.http.RequestHttp; */ public interface WxMaService { /** - * 获取access_token + * 获取access_token. */ String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; + String JSCODE_TO_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session"; + /** + * 获取登录后的session信息 + * + * @param jsCode 登录时获取的 code + */ + WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException; /** *
-   * 验证消息的确来自微信服务器
+   * 验证消息的确来自微信服务器.
    * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
    * 
*/ boolean checkSignature(String timestamp, String nonce, String signature); /** - * 获取access_token, 不强制刷新access_token + * 获取access_token, 不强制刷新access_token. * * @see #getAccessToken(boolean) */ @@ -32,7 +40,7 @@ public interface WxMaService { /** *
-   * 获取access_token,本方法线程安全
+   * 获取access_token,本方法线程安全.
    * 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
    *
    * 另:本service的所有方法都会在access_token过期是调用此方法
@@ -47,12 +55,12 @@ public interface WxMaService {
   String getAccessToken(boolean forceRefresh) throws WxErrorException;
 
   /**
-   * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
+   * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求.
    */
   String get(String url, String queryParam) throws WxErrorException;
 
   /**
-   * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求
+   * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求.
    */
   String post(String url, String postData) throws WxErrorException;
 
@@ -67,7 +75,7 @@ public interface WxMaService {
 
   /**
    * 
-   * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试
+   * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试.
    * 默认:1000ms
    * 
*/ @@ -75,59 +83,65 @@ public interface WxMaService { /** *
-   * 设置当微信系统响应系统繁忙时,最大重试次数
+   * 设置当微信系统响应系统繁忙时,最大重试次数.
    * 默认:5次
    * 
*/ void setMaxRetryTimes(int maxRetryTimes); /** - * 获取WxMaConfig 对象 + * 获取WxMaConfig 对象. * * @return WxMaConfig */ WxMaConfig getWxMaConfig(); /** - * 注入 {@link WxMaConfig} 的实现 + * 注入 {@link WxMaConfig} 的实现. */ void setWxMaConfig(WxMaConfig wxConfigProvider); /** - * 返回消息(客服消息和模版消息)发送接口方法实现类,以方便调用其各个接口 + * 返回消息(客服消息和模版消息)发送接口方法实现类,以方便调用其各个接口. * * @return WxMaMsgService */ WxMaMsgService getMsgService(); /** - * 返回素材相关接口方法的实现类对象,以方便调用其各个接口 + * 返回素材相关接口方法的实现类对象,以方便调用其各个接口. * * @return WxMaMediaService */ WxMaMediaService getMediaService(); /** - * 返回用户相关接口方法的实现类对象,以方便调用其各个接口 + * 返回用户相关接口方法的实现类对象,以方便调用其各个接口. * * @return WxMaUserService */ WxMaUserService getUserService(); /** - * 返回二维码相关接口方法的实现类对象,以方便调用其各个接口 + * 返回二维码相关接口方法的实现类对象,以方便调用其各个接口. * * @return WxMaQrcodeService */ WxMaQrcodeService getQrcodeService(); /** - * 初始化http请求对象 + * 返回模板配置相关接口方法的实现类对象, 以方便调用其各个接口. + * @return WxMaTemplateService + */ + WxMaTemplateService getTemplateService(); + + /** + * 初始化http请求对象. */ void initHttp(); /** - * 请求http请求相关信息 + * 请求http请求相关信息. */ RequestHttp getRequestHttp(); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java new file mode 100644 index 00000000..62be40ed --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java @@ -0,0 +1,89 @@ +package cn.binarywang.wx.miniapp.api; + +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; +import me.chanjar.weixin.common.exception.WxErrorException; + +import java.util.List; + +public interface WxMaTemplateService { + + //获取小程序模板库标题列表 + String TEMPLATE_LIBRARY_LIST_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list"; + + //获取模板库某个模板标题下关键词库 + String TEMPLATE_LIBRARY_KEYWORD_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get"; + + //组合模板并添加至帐号下的个人模板库 + String TEMPLATE_ADD_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/add"; + + //获取帐号下已存在的模板列表 + String TEMPLATE_LIST_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/list"; + + //删除帐号下的某个模板 + String TEMPLATE_DEL_URL = "https://api.weixin.qq.com/cgi-bin/wxopen/template/del"; + + /** + *
+   * 获取小程序模板库标题列表
+   *
+   * 详情请见: 获取小程序模板库标题列表
+   * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list?access_token=ACCESS_TOKEN
+   * 
+ * @param offset + * @param count + * @return + */ + WxMaTemplateLibraryListResult findTemplateLibraryList(int offset, int count) throws WxErrorException; + + /** + *
+   * 获取模板库某个模板标题下关键词库
+   *
+   * 详情请见: 获取小程序模板库标题列表
+   * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token=ACCESS_TOKEN
+   * 
+ * @param id + * @return + */ + WxMaTemplateLibraryGetResult findTemplateLibraryKeywordList(String id) throws WxErrorException; + + /** + *
+   * 组合模板并添加至帐号下的个人模板库
+   *
+   * 详情请见: 获取小程序模板库标题列表
+   * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/add?access_token=ACCESS_TOKEN
+   * 
+ * @param id + * @param keywordIdList + * @return + */ + WxMaTemplateAddResult addTemplate(String id, List keywordIdList) throws WxErrorException; + + /** + *
+   * 获取帐号下已存在的模板列表
+   *
+   * 详情请见: 获取小程序模板库标题列表
+   * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=ACCESS_TOKEN
+   * 
+ * @param offset + * @param count + * @return + */ + WxMaTemplateListResult findTemplateList(int offset, int count) throws WxErrorException; + + /** + *
+   * 删除帐号下的某个模板
+   *
+   * 详情请见: 获取小程序模板库标题列表
+   * 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=ACCESS_TOKEN
+   * 
+ * @param templateId + */ + boolean delTemplate(String templateId) throws WxErrorException; +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java index 84b17378..7cf449fb 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java @@ -1,26 +1,26 @@ package cn.binarywang.wx.miniapp.api; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import me.chanjar.weixin.common.exception.WxErrorException; /** - * 用户信息相关操作接口 + * 用户信息相关操作接口. * * @author Binary Wang */ public interface WxMaUserService { - String JSCODE_TO_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session"; /** - * 获取登录后的session信息 + * 获取登录后的session信息. * * @param jsCode 登录时获取的 code */ WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException; /** - * 解密用户敏感数据 + * 解密用户敏感数据. * * @param sessionKey 会话密钥 * @param encryptedData 消息密文 @@ -29,7 +29,16 @@ public interface WxMaUserService { WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr); /** - * 验证用户信息完整性 + * 解密用户手机号信息. + * + * @param sessionKey 会话密钥 + * @param encryptedData 消息密文 + * @param ivStr 加密算法的初始向量 + */ + WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr); + + /** + * 验证用户信息完整性. * * @param sessionKey 会话密钥 * @param rawData 微信用户基本信息 diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java index 806e0e99..b2ddfae7 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java @@ -54,7 +54,8 @@ public class WxMaQrcodeServiceImpl implements WxMaQrcodeService { } @Override - public File createWxCodeLimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor) throws WxErrorException { + public File createWxCodeLimit(String scene, String page, int width, boolean autoColor, WxMaCodeLineColor lineColor) + throws WxErrorException { WxMaWxcodeLimit wxMaWxcodeLimit = new WxMaWxcodeLimit(); wxMaWxcodeLimit.setScene(scene); wxMaWxcodeLimit.setPage(page); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java index df3fad8e..1ec7801d 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java @@ -1,16 +1,10 @@ package cn.binarywang.wx.miniapp.api.impl; -import cn.binarywang.wx.miniapp.api.*; -import cn.binarywang.wx.miniapp.config.WxMaConfig; -import cn.binarywang.wx.miniapp.constant.WxMaConstants; -import com.google.gson.JsonParser; -import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.result.WxError; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.*; -import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; + import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -20,14 +14,32 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.concurrent.locks.Lock; +import cn.binarywang.wx.miniapp.api.WxMaMediaService; +import cn.binarywang.wx.miniapp.api.WxMaMsgService; +import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.WxMaTemplateService; +import cn.binarywang.wx.miniapp.api.WxMaUserService; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.config.WxMaConfig; +import cn.binarywang.wx.miniapp.constant.WxMaConstants; +import com.google.common.base.Joiner; +import me.chanjar.weixin.common.bean.WxAccessToken; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.crypto.SHA1; +import me.chanjar.weixin.common.util.http.HttpType; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; /** * @author Binary Wang */ public class WxMaServiceImpl implements WxMaService, RequestHttp { - private static final JsonParser JSON_PARSER = new JsonParser(); private final Logger log = LoggerFactory.getLogger(this.getClass()); private CloseableHttpClient httpClient; @@ -38,6 +50,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp params = new HashMap<>(8); + params.put("appid", config.getAppid()); + params.put("secret", config.getSecret()); + params.put("js_code", jsCode); + params.put("grant_type", "authorization_code"); + + String result = get(JSCODE_TO_SESSION_URL, Joiner.on("&").withKeyValueSeparator("=").join(params)); + return WxMaJscode2SessionResult.fromJson(result); + } + @Override public boolean checkSignature(String timestamp, String nonce, String signature) { try { @@ -259,4 +285,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp params = new HashMap<>(); + params.put("offset", offset); + params.put("count", count); + + String responseText = this.wxMaService.post(TEMPLATE_LIBRARY_LIST_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateLibraryListResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMaTemplateLibraryGetResult findTemplateLibraryKeywordList(String id) throws WxErrorException { + + Map params = new HashMap<>(); + params.put("id", id); + + String responseText = this.wxMaService.post(TEMPLATE_LIBRARY_KEYWORD_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateLibraryGetResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMaTemplateAddResult addTemplate(String id, List keywordIdList) throws WxErrorException { + + Map params = new HashMap<>(); + params.put("id", id); + params.put("keyword_id_list", keywordIdList.toArray()); + + String responseText = this.wxMaService.post(TEMPLATE_ADD_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateAddResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public WxMaTemplateListResult findTemplateList(int offset, int count) throws WxErrorException { + + Map params = new HashMap<>(); + params.put("offset", offset); + params.put("count", count); + + String responseText = this.wxMaService.post(TEMPLATE_LIST_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return WxMaTemplateListResult.fromJson(responseText); + }else { + throw new WxErrorException(wxError); + } + } + + @Override + public boolean delTemplate(String templateId) throws WxErrorException { + Map params = new HashMap<>(); + params.put("template_id", templateId); + + String responseText = this.wxMaService.post(TEMPLATE_DEL_URL, WxGsonBuilder.create().toJson(params)); + WxError wxError = WxError.fromJson(responseText); + if(wxError.getErrorCode() == 0){ + return true; + }else { + throw new WxErrorException(wxError); + } + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java index 8dbc139a..28491019 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java @@ -1,17 +1,14 @@ package cn.binarywang.wx.miniapp.api.impl; +import org.apache.commons.codec.digest.DigestUtils; + import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaUserService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; -import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils; -import com.google.common.base.Joiner; import me.chanjar.weixin.common.exception.WxErrorException; -import org.apache.commons.codec.digest.DigestUtils; - -import java.util.HashMap; -import java.util.Map; /** * @author Binary Wang @@ -25,15 +22,7 @@ public class WxMaUserServiceImpl implements WxMaUserService { @Override public WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException { - final WxMaConfig config = service.getWxMaConfig(); - Map params = new HashMap<>(8); - params.put("appid", config.getAppid()); - params.put("secret", config.getSecret()); - params.put("js_code", jsCode); - params.put("grant_type", "authorization_code"); - - String result = this.service.get(JSCODE_TO_SESSION_URL, Joiner.on("&").withKeyValueSeparator("=").join(params)); - return WxMaJscode2SessionResult.fromJson(result); + return service.jsCode2SessionInfo(jsCode); } @Override @@ -41,10 +30,14 @@ public class WxMaUserServiceImpl implements WxMaUserService { return WxMaUserInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); } + @Override + public WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr) { + return WxMaPhoneNumberInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)); + } + @Override public boolean checkUserInfo(String sessionKey, String rawData, String signature) { final String generatedSignature = DigestUtils.sha1Hex(rawData + sessionKey); - System.out.println(generatedSignature); return generatedSignature.equals(signature); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java index f329dd30..cb444c94 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java @@ -8,10 +8,12 @@ import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; * @author Element */ public abstract class AbstractWxMaQrcodeWrapper { + public String toJson() { + return WxMaGsonBuilder.create().toJson(this); + } @Override public String toString() { - return WxMaGsonBuilder.create().toJson(this); + return this.toJson(); } - } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java index 7d3e2d8d..85b47677 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java @@ -8,8 +8,11 @@ import lombok.EqualsAndHashCode; import java.io.Serializable; /** - * {"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","expires_in":2592000,"openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"} - * + *
+ * code换取session_key接口的响应
+ * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject
+ * 微信返回报文:{"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"}
+ * 
* @author Binary Wang */ @Data @@ -20,9 +23,6 @@ public class WxMaJscode2SessionResult implements Serializable { @SerializedName("session_key") private String sessionKey; - @SerializedName("expires_in") - private Integer expiresin; - @SerializedName("openid") private String openid; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java index ec1728db..85fece8b 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java @@ -1,14 +1,19 @@ package cn.binarywang.wx.miniapp.bean; -import cn.binarywang.wx.miniapp.builder.ImageBuilder; -import cn.binarywang.wx.miniapp.builder.TextBuilder; -import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import cn.binarywang.wx.miniapp.builder.ImageMessageBuilder; +import cn.binarywang.wx.miniapp.builder.LinkMessageBuilder; +import cn.binarywang.wx.miniapp.builder.MaPageMessageBuilder; +import cn.binarywang.wx.miniapp.builder.TextMessageBuilder; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import java.io.Serializable; /** - * 客服消息 + * 客服消息. * * @author Binary Wang */ @@ -16,30 +21,90 @@ import java.io.Serializable; public class WxMaKefuMessage implements Serializable { private static final long serialVersionUID = -9196732086954365246L; + @SerializedName("touser") private String toUser; + + @SerializedName("msgtype") private String msgType; - private String content; - private String mediaId; - private String thumbMediaId; - private String title; - private String description; + + @SerializedName("text") + private KfText text; + + @SerializedName("image") + private KfImage image; + + @SerializedName("link") + private KfLink link; + + @SerializedName("miniprogrampage") + private KfMaPage maPage; + + @Data + @AllArgsConstructor + public static class KfText { + private String content; + } + + @Data + @AllArgsConstructor + public static class KfImage { + @SerializedName("media_id") + private String mediaId; + } + + @Data + @Builder + public static class KfLink { + private String title; + private String description; + private String url; + + @SerializedName("thumb_url") + private String thumbUrl; + } + + @Data + @Builder + public static class KfMaPage { + private String title; + + @SerializedName("pagepath") + private String pagePath; + + @SerializedName("thumb_media_id") + private String thumbMediaId; + } + + /** + * 获得文本消息builder. + */ + public static TextMessageBuilder newTextBuilder() { + return new TextMessageBuilder(); + } + + /** + * 获得图片消息builder. + */ + public static ImageMessageBuilder newImageBuilder() { + return new ImageMessageBuilder(); + } /** - * 获得文本消息builder + * 获得图文链接消息builder. */ - public static TextBuilder newTextBuilder() { - return new TextBuilder(); + public static LinkMessageBuilder newLinkBuilder() { + return new LinkMessageBuilder(); } /** - * 获得图片消息builder + * 获得图文链接消息builder. */ - public static ImageBuilder newImageBuilder() { - return new ImageBuilder(); + public static MaPageMessageBuilder newMaPageBuilder() { + return new MaPageMessageBuilder(); } public String toJson() { - return WxMaGsonBuilder.create().toJson(this); + return new GsonBuilder().create().toJson(this); } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java index cb1fed69..60b19bf9 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java @@ -45,12 +45,16 @@ public class WxMaMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private Integer createTime; + @SerializedName("MsgType") + @XStreamAlias("MsgType") + @XStreamConverter(value = XStreamCDataConverter.class) + private String msgType; + @SerializedName("MsgDataFormat") @XStreamAlias("MsgDataFormat") @XStreamConverter(value = XStreamCDataConverter.class) - private String msgType; + private String msgDataFormat; - // 文本消息 @SerializedName("Content") @XStreamAlias("Content") @XStreamConverter(value = XStreamCDataConverter.class) @@ -61,7 +65,6 @@ public class WxMaMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private Long msgId; - // 图片消息 @SerializedName("PicUrl") @XStreamAlias("PicUrl") @XStreamConverter(value = XStreamCDataConverter.class) @@ -72,7 +75,6 @@ public class WxMaMessage implements Serializable { @XStreamConverter(value = XStreamCDataConverter.class) private String mediaId; - // 事件消息 @SerializedName("Event") @XStreamAlias("Event") @XStreamConverter(value = XStreamCDataConverter.class) @@ -92,7 +94,7 @@ public class WxMaMessage implements Serializable { } /** - * 从加密字符串转换 + * 从加密字符串转换. * * @param encryptedXml 密文 * @param wxMaConfig 配置存储器对象 diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java new file mode 100644 index 00000000..6b39a3d7 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java @@ -0,0 +1,30 @@ +package cn.binarywang.wx.miniapp.bean; + +import java.io.Serializable; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import lombok.Data; + +/** + * 微信用户绑定的手机号相关信息 + * @author Binary Wang + */ +@Data +public class WxMaPhoneNumberInfo implements Serializable { + private static final long serialVersionUID = 6719822331555402137L; + + private String phoneNumber; + private String purePhoneNumber; + private String countryCode; + private Watermark watermark; + + public static WxMaPhoneNumberInfo fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaPhoneNumberInfo.class); + } + + @Data + public static class Watermark { + private String timestamp; + private String appid; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java index 32268b4c..23f3988f 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java @@ -1,24 +1,28 @@ package cn.binarywang.wx.miniapp.bean; import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; -import lombok.Builder; -import lombok.Data; +import lombok.*; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** + * 模板消息. * 参考 https://mp.weixin.qq.com/debug/wxadoc/dev/api/notice.html#接口说明 模板消息部分 * * @author Binary Wang */ -@Data +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor @Builder public class WxMaTemplateMessage implements Serializable { private static final long serialVersionUID = 5063374783759519418L; /** + * 接收者(用户)的 openid. *
    * 参数:touser
    * 是否必填: 是
@@ -28,6 +32,7 @@ public class WxMaTemplateMessage implements Serializable {
   private String toUser;
 
   /**
+   * 所需下发的模板消息的id.
    * 
    * 参数:template_id
    * 是否必填: 是
@@ -37,6 +42,7 @@ public class WxMaTemplateMessage implements Serializable {
   private String templateId;
 
   /**
+   * 点击模板卡片后的跳转页面,仅限本小程序内的页面.
    * 
    * 参数:page
    * 是否必填: 否
@@ -46,6 +52,7 @@ public class WxMaTemplateMessage implements Serializable {
   private String page;
 
   /**
+   * 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id.
    * 
    * 参数:form_id
    * 是否必填: 是
@@ -55,16 +62,17 @@ public class WxMaTemplateMessage implements Serializable {
   private String formId;
 
   /**
+   * 模板内容,不填则下发空模板.
    * 
    * 参数:data
    * 是否必填: 是
    * 描述: 模板内容,不填则下发空模板
    * 
*/ - @Builder.Default - private final List data = new ArrayList<>(); + private List data; /** + * 模板内容字体的颜色,不填默认黑色. *
    * 参数:color
    * 是否必填: 否
@@ -74,6 +82,7 @@ public class WxMaTemplateMessage implements Serializable {
   private String color;
 
   /**
+   * 模板需要放大的关键词,不填则默认无放大.
    * 
    * 参数:emphasis_keyword
    * 是否必填: 否
@@ -82,6 +91,15 @@ public class WxMaTemplateMessage implements Serializable {
    */
   private String emphasisKeyword;
 
+  public WxMaTemplateMessage addData(Data datum) {
+    if (this.data == null) {
+      this.data = new ArrayList<>();
+    }
+    this.data.add(datum);
+
+    return this;
+  }
+
   public String toJson() {
     return WxMaGsonBuilder.create().toJson(this);
   }
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java
index 5f76273b..a251f054 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java
@@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode;
 import java.io.Serializable;
 
 /**
+ * 小程序码接口B.
  *
  * @author Element
  * @date 2017/7/27
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java
new file mode 100644
index 00000000..4b30870d
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java
@@ -0,0 +1,20 @@
+package cn.binarywang.wx.miniapp.bean.template;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+
+import java.io.Serializable;
+
+@Data
+public class WxMaTemplateAddResult implements Serializable{
+
+  private static final long serialVersionUID = 872250961973834465L;
+
+  @SerializedName("template_id")
+  private String templateId;
+
+  public static WxMaTemplateAddResult fromJson(String json){
+    return WxGsonBuilder.create().fromJson(json, WxMaTemplateAddResult.class);
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java
new file mode 100644
index 00000000..e55ed0d5
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java
@@ -0,0 +1,31 @@
+package cn.binarywang.wx.miniapp.bean.template;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class WxMaTemplateLibraryGetResult implements Serializable{
+
+  private static final long serialVersionUID = -190847592776636744L;
+  private String id;
+  private String title;
+  @SerializedName("keyword_list")
+  private List keywordList;
+
+  @Data
+  public static class KeywordInfo{
+
+    @SerializedName("keyword_id")
+    private int keywordId;
+    private String name;
+    private String example;
+  }
+
+  public static WxMaTemplateLibraryGetResult fromJson(String json){
+    return WxGsonBuilder.create().fromJson(json, WxMaTemplateLibraryGetResult.class);
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java
new file mode 100644
index 00000000..1926971b
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java
@@ -0,0 +1,28 @@
+package cn.binarywang.wx.miniapp.bean.template;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class WxMaTemplateLibraryListResult implements Serializable{
+  private static final long serialVersionUID = -2780782521447602209L;
+
+  @SerializedName("total_count")
+  private int totalCount;
+  private List list;
+
+  public static WxMaTemplateLibraryListResult fromJson(String json){
+    return WxGsonBuilder.create().fromJson(json, WxMaTemplateLibraryListResult.class);
+  }
+
+  @Data
+  public static class TemplateItem{
+
+    private String id;
+    private String title;
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java
new file mode 100644
index 00000000..0537fefc
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java
@@ -0,0 +1,29 @@
+package cn.binarywang.wx.miniapp.bean.template;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class WxMaTemplateListResult implements Serializable{
+
+  private static final long serialVersionUID = -7430535579782184537L;
+  private List list;
+
+  public static WxMaTemplateListResult fromJson(String json){
+    return WxGsonBuilder.create().fromJson(json, WxMaTemplateListResult.class);
+  }
+
+  @Data
+  public static class TemplateInfo{
+
+    @SerializedName("template_id")
+    private String templateId;
+    private String title;
+    private String content;
+    private String example;
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java
deleted file mode 100644
index d4bd0688..00000000
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package cn.binarywang.wx.miniapp.builder;
-
-import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
-import cn.binarywang.wx.miniapp.constant.WxMaConstants;
-
-/**
- * @author Binary Wang
- */
-public final class ImageBuilder extends BaseBuilder {
-  private String mediaId;
-
-  public ImageBuilder() {
-    this.msgType = WxMaConstants.KefuMsgType.IMAGE;
-  }
-
-  public ImageBuilder mediaId(String mediaId) {
-    this.mediaId = mediaId;
-    return this;
-  }
-
-  @Override
-  public WxMaKefuMessage build() {
-    WxMaKefuMessage m = super.build();
-    m.setMediaId(this.mediaId);
-    return m;
-  }
-}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java
new file mode 100644
index 00000000..bcd2290f
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java
@@ -0,0 +1,30 @@
+package cn.binarywang.wx.miniapp.builder;
+
+import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
+
+import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType;
+
+/**
+ * 图片消息builder.
+ *
+ * @author Binary Wang
+ */
+public final class ImageMessageBuilder extends BaseBuilder {
+  private String mediaId;
+
+  public ImageMessageBuilder() {
+    this.msgType = KefuMsgType.IMAGE;
+  }
+
+  public ImageMessageBuilder mediaId(String mediaId) {
+    this.mediaId = mediaId;
+    return this;
+  }
+
+  @Override
+  public WxMaKefuMessage build() {
+    WxMaKefuMessage m = super.build();
+    m.setImage(new WxMaKefuMessage.KfImage(this.mediaId));
+    return m;
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java
new file mode 100644
index 00000000..f4927e16
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java
@@ -0,0 +1,53 @@
+package cn.binarywang.wx.miniapp.builder;
+
+import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
+
+import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType;
+
+/**
+ * 图文链接消息builder
+ *
+ * @author Binary Wang
+ */
+public class LinkMessageBuilder extends BaseBuilder {
+  private String title;
+  private String description;
+  private String url;
+  private String thumbUrl;
+
+  public LinkMessageBuilder() {
+    this.msgType = KefuMsgType.LINK;
+  }
+
+  public LinkMessageBuilder title(String title) {
+    this.title = title;
+    return this;
+  }
+
+  public LinkMessageBuilder description(String description) {
+    this.description = description;
+    return this;
+  }
+
+  public LinkMessageBuilder url(String url) {
+    this.url = url;
+    return this;
+  }
+
+  public LinkMessageBuilder thumbUrl(String thumbUrl) {
+    this.thumbUrl = thumbUrl;
+    return this;
+  }
+
+  @Override
+  public WxMaKefuMessage build() {
+    WxMaKefuMessage m = super.build();
+    m.setLink(WxMaKefuMessage.KfLink.builder().title(this.title)
+      .description(this.description)
+      .url(this.url)
+      .thumbUrl(this.thumbUrl)
+      .build()
+    );
+    return m;
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java
new file mode 100644
index 00000000..238a6014
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java
@@ -0,0 +1,47 @@
+package cn.binarywang.wx.miniapp.builder;
+
+import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
+
+import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType;
+
+/**
+ * 小程序卡片消息builder
+ *
+ * @author Binary Wang
+ */
+public class MaPageMessageBuilder extends BaseBuilder {
+  private String title;
+  private String pagePath;
+  private String thumbMediaId;
+
+  public MaPageMessageBuilder() {
+    this.msgType = KefuMsgType.MA_PAGE;
+  }
+
+  public MaPageMessageBuilder title(String title) {
+    this.title = title;
+    return this;
+  }
+
+  public MaPageMessageBuilder pagePath(String pagePath) {
+    this.pagePath = pagePath;
+    return this;
+  }
+
+  public MaPageMessageBuilder thumbMediaId(String thumbMediaId) {
+    this.thumbMediaId = thumbMediaId;
+    return this;
+  }
+
+  @Override
+  public WxMaKefuMessage build() {
+    WxMaKefuMessage m = super.build();
+    m.setMaPage(WxMaKefuMessage.KfMaPage.builder()
+      .title(this.title)
+      .pagePath(this.pagePath)
+      .thumbMediaId(this.thumbMediaId)
+      .build()
+    );
+    return m;
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java
deleted file mode 100644
index 35c58a67..00000000
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package cn.binarywang.wx.miniapp.builder;
-
-import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
-import cn.binarywang.wx.miniapp.constant.WxMaConstants;
-
-/**
- * @author Binary Wang
- */
-public final class TextBuilder extends BaseBuilder {
-  private String content;
-
-  public TextBuilder() {
-    this.msgType = WxMaConstants.KefuMsgType.TEXT;
-  }
-
-  public TextBuilder content(String content) {
-    this.content = content;
-    return this;
-  }
-
-  @Override
-  public WxMaKefuMessage build() {
-    WxMaKefuMessage m = super.build();
-    m.setContent(this.content);
-    return m;
-  }
-}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java
new file mode 100644
index 00000000..d0da3257
--- /dev/null
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java
@@ -0,0 +1,30 @@
+package cn.binarywang.wx.miniapp.builder;
+
+import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
+
+import static cn.binarywang.wx.miniapp.constant.WxMaConstants.KefuMsgType;
+
+/**
+ * 文本消息builder.
+ *
+ * @author Binary Wang
+ */
+public final class TextMessageBuilder extends BaseBuilder {
+  private String content;
+
+  public TextMessageBuilder() {
+    this.msgType = KefuMsgType.TEXT;
+  }
+
+  public TextMessageBuilder content(String content) {
+    this.content = content;
+    return this;
+  }
+
+  @Override
+  public WxMaKefuMessage build() {
+    WxMaKefuMessage m = super.build();
+    m.setText(new WxMaKefuMessage.KfText(this.content));
+    return m;
+  }
+}
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java
index ccc492d1..1ea3595e 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java
@@ -2,29 +2,29 @@ package cn.binarywang.wx.miniapp.constant;
 
 /**
  * 
- *  小程序常量
+ *  小程序常量.
  * 
* * @author Binary Wang */ public class WxMaConstants { /** - * 微信接口返回的参数errcode + * 微信接口返回的参数errcode. */ public static final String ERRCODE = "errcode"; /** - * 素材类型 + * 素材类型. */ public static class MediaType { /** - * 图片 + * 图片. */ public static final String IMAGE = "image"; } /** - * 消息格式 + * 消息格式. */ public static class MsgDataFormat { public static final String XML = "XML"; @@ -32,32 +32,40 @@ public class WxMaConstants { } /** - * 客服消息的消息类型 + * 客服消息的消息类型. */ public static class KefuMsgType { /** - * 文本消息 + * 文本消息. */ public static final String TEXT = "text"; /** - * 图片消息 + * 图片消息. */ public static final String IMAGE = "image"; + /** + * 图文链接. + */ + public static final String LINK = "link"; + /** + * 小程序卡片消息. + */ + public static final String MA_PAGE = "miniprogrampage"; } public static final class ErrorCode { /** - * 40001 获取access_token时AppSecret错误,或者access_token无效 + * 40001 获取access_token时AppSecret错误,或者access_token无效. */ public static final int ERR_40001 = 40001; /** - * 42001 access_token超时 + * 42001 access_token超时. */ public static final int ERR_42001 = 42001; /** - * 40014 不合法的access_token,请开发者认真比对access_token的有效性(如是否过期) + * 40014 不合法的access_token,请开发者认真比对access_token的有效性(如是否过期). */ public static final int ERR_40014 = 40014; } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java index 9b35df89..1b64ec63 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java @@ -37,17 +37,17 @@ public class QrCodeRequestExecutor implements RequestExecutor 0 - && ContentType.APPLICATION_JSON.getMimeType() - .equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) { + && ContentType.APPLICATION_JSON.getMimeType() + .equals(ContentType.parse(contentTypeHeader[0].getValue()).getMimeType())) { String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); throw new WxErrorException(WxError.fromJson(responseContent)); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java index 4eb3a8ad..5a08a39a 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java @@ -1,6 +1,5 @@ package cn.binarywang.wx.miniapp.util.json; -import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -13,7 +12,6 @@ public class WxMaGsonBuilder { static { INSTANCE.disableHtmlEscaping(); - INSTANCE.registerTypeAdapter(WxMaKefuMessage.class, new WxMaKefuMessageGsonAdapter()); INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter()); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java deleted file mode 100644 index 829469f8..00000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ -package cn.binarywang.wx.miniapp.util.json; - -import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; -import cn.binarywang.wx.miniapp.constant.WxMaConstants; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -import java.lang.reflect.Type; - -/** - * @author Binary Wang - */ -public class WxMaKefuMessageGsonAdapter implements JsonSerializer { - - @Override - public JsonElement serialize(WxMaKefuMessage message, Type typeOfSrc, JsonSerializationContext context) { - JsonObject messageJson = new JsonObject(); - messageJson.addProperty("touser", message.getToUser()); - messageJson.addProperty("msgtype", message.getMsgType()); - - if (WxMaConstants.KefuMsgType.TEXT.equals(message.getMsgType())) { - JsonObject text = new JsonObject(); - text.addProperty("content", message.getContent()); - messageJson.add("text", text); - } - - if (WxMaConstants.KefuMsgType.IMAGE.equals(message.getMsgType())) { - JsonObject image = new JsonObject(); - image.addProperty("media_id", message.getMediaId()); - messageJson.add("image", image); - } - - return messageJson; - } - -} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java index 578bf68c..500b173a 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java @@ -1,12 +1,16 @@ package cn.binarywang.wx.miniapp.util.xml; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import cn.binarywang.wx.miniapp.bean.WxMaMessage; import com.thoughtworks.xstream.XStream; import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import java.io.InputStream; -import java.util.*; - /** * @author Binary Wang */ @@ -45,7 +49,7 @@ public class XStreamTransformer { * @param clz 类型 * @param xStream xml解析器 */ - private static void register(Class clz, XStream xStream) { + public static void register(Class clz, XStream xStream) { CLASS_2_XSTREAM_INSTANCE.put(clz, xStream); } diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java index d6aa31a7..8ad7a728 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java @@ -7,16 +7,14 @@ import cn.binarywang.wx.miniapp.test.ApiTestModule; import cn.binarywang.wx.miniapp.test.TestConfig; import com.google.common.collect.Lists; import com.google.inject.Inject; -import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.exception.WxErrorException; -import org.testng.annotations.Guice; -import org.testng.annotations.Test; +import org.testng.annotations.*; import java.text.SimpleDateFormat; import java.util.Date; /** - * 测试客服相关接口 + * 测试消息相关接口 * * @author Binary Wang */ @@ -25,26 +23,14 @@ import java.util.Date; public class WxMaMsgServiceImplTest { @Inject - protected WxMaService wxService; - - public void testSendKefuMpNewsMessage() throws WxErrorException { - TestConfig configStorage = (TestConfig) this.wxService - .getWxMaConfig(); - WxMaKefuMessage message = new WxMaKefuMessage(); - message.setMsgType(WxConsts.KefuMsgType.MPNEWS); - message.setToUser(configStorage.getOpenid()); - - this.wxService.getMsgService().sendKefuMsg(message); - } + private WxMaService wxService; public void testSendKefuMessage() throws WxErrorException { - TestConfig config = (TestConfig) this.wxService - .getWxMaConfig(); - WxMaKefuMessage message = new WxMaKefuMessage(); - message.setMsgType(WxConsts.KefuMsgType.TEXT); - message.setToUser(config.getOpenid()); - message.setContent( - "欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); + TestConfig config = (TestConfig) this.wxService.getWxMaConfig(); + WxMaKefuMessage message = WxMaKefuMessage.newTextBuilder() + .toUser(config.getOpenid()) + .content("欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World") + .build(); this.wxService.getMsgService().sendKefuMsg(message); } @@ -66,7 +52,7 @@ public class WxMaMsgServiceImplTest { .templateId(config.getTemplateId()) .emphasisKeyword("keyword1.DATA") .build(); - + //templateMessage.addData( new WxMaTemplateMessage.Data("keyword1", "339208499", "#173177")); this.wxService.getMsgService().sendTemplateMsg(templateMessage); } diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImplTest.java new file mode 100644 index 00000000..5dfa86a8 --- /dev/null +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImplTest.java @@ -0,0 +1,70 @@ +package cn.binarywang.wx.miniapp.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateAddResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryGetResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateLibraryListResult; +import cn.binarywang.wx.miniapp.bean.template.WxMaTemplateListResult; +import cn.binarywang.wx.miniapp.test.ApiTestModule; +import com.google.inject.Inject; +import org.assertj.core.util.Lists; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.List; + +@Test +@Guice(modules = ApiTestModule.class) +public class WxMaTemplateServiceImplTest { + + @Inject + protected WxMaService wxService; + + @Test + public void testFindTemplateLibraryList() throws Exception { + WxMaTemplateLibraryListResult result = this.wxService.getTemplateService().findTemplateLibraryList(0, 20); + Assert.assertEquals(20, result.getList().size()); + } + + @Test + public void testFindTemplateLibraryKeywordList() throws Exception { + WxMaTemplateLibraryGetResult result = this.wxService.getTemplateService().findTemplateLibraryKeywordList("AT0004"); + Assert.assertEquals("AT0004", result.getId()); + Assert.assertEquals("交易提醒", result.getTitle()); + Assert.assertEquals(100, result.getKeywordList().size()); + } + + @Test + public void testAddTemplate() throws Exception{ + List list = Lists.newArrayList(); + list.add(1); + list.add(20); + list.add(84); + + WxMaTemplateAddResult result = this.wxService.getTemplateService().addTemplate("AT0004", list); + Assert.assertNotNull(result.getTemplateId()); + System.out.println(result); + } + + @Test + public void testFindTemplateList() throws Exception{ + WxMaTemplateListResult result = this.wxService.getTemplateService().findTemplateList(0, 20); + System.out.println(result); + } + + @Test + public void testDelTemplate() throws Exception { + + //add + List list = Lists.newArrayList(); + list.add(1); + list.add(20); + list.add(84); + + WxMaTemplateAddResult result = this.wxService.getTemplateService().addTemplate("AT0004", list); + + //delete + this.wxService.getTemplateService().delTemplate(result.getTemplateId()); + } +} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java index a1969276..33e39a6b 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java @@ -1,14 +1,14 @@ package cn.binarywang.wx.miniapp.api.impl; +import org.testng.annotations.*; + import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import cn.binarywang.wx.miniapp.test.ApiTestModule; import com.google.inject.Inject; -import org.testng.annotations.Guice; -import org.testng.annotations.Test; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; +import static org.testng.Assert.*; /** * 测试用户相关的接口 @@ -28,7 +28,7 @@ public class WxMaUserServiceImplTest { } @Test - public void testGetUserInfo() throws Exception { + public void testGetUserInfo() { WxMaUserInfo userInfo = this.wxService.getUserService().getUserInfo("tiihtNczf5v6AKRyjwEUhQ==", "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==", "r7BXXKkLb8qrSNn05n0qiA=="); @@ -37,10 +37,21 @@ public class WxMaUserServiceImplTest { } @Test - public void testCheckUserInfo() throws Exception { + public void testCheckUserInfo() { assertTrue(this.wxService.getUserService().checkUserInfo("HyVFkGl5F5OQWJZZaNzBBg==", "{\"nickName\":\"Band\",\"gender\":1,\"language\":\"zh_CN\",\"city\":\"Guangzhou\",\"province\":\"Guangdong\",\"country\":\"CN\",\"avatarUrl\":\"http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0\"}", "75e81ceda165f4ffa64f4068af58c64b8f54b88c")); } + /** + * TODO 测试数据有问题,需要替换为正确的数据 + */ + @Test + public void testGetPhoneNoInfo() { + WxMaPhoneNumberInfo phoneNoInfo = this.wxService.getUserService().getPhoneNoInfo("tiihtNczf5v6AKRyjwEUhQ==", + "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==", + "r7BXXKkLb8qrSNn05n0qiA=="); + assertNotNull(phoneNoInfo); + System.out.println(phoneNoInfo.toString()); + } } diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessageTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessageTest.java index 667ab2de..d32dfca7 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessageTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessageTest.java @@ -1,8 +1,8 @@ package cn.binarywang.wx.miniapp.bean; -import me.chanjar.weixin.common.api.WxConsts; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.testng.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; /** * @author Binary Wang @@ -10,30 +10,47 @@ import org.testng.annotations.Test; @Test public class WxMaKefuMessageTest { - public void testTextReply() { - WxMaKefuMessage reply = new WxMaKefuMessage(); - reply.setToUser("OPENID"); - reply.setMsgType(WxConsts.KefuMsgType.TEXT); - reply.setContent("sfsfdsdf"); - Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); + public void testTextBuilder() { + WxMaKefuMessage reply = WxMaKefuMessage.newTextBuilder() + .toUser("OPENID") + .content("sfsfdsdf") + .build(); + assertThat(reply.toJson()) + .isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); } - public void testTextBuild() { - WxMaKefuMessage reply = WxMaKefuMessage.newTextBuilder().toUser("OPENID").content("sfsfdsdf").build(); - Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); + public void testImageBuilder() { + WxMaKefuMessage reply = WxMaKefuMessage.newImageBuilder() + .toUser("OPENID") + . mediaId("MEDIA_ID") + .build(); + assertThat(reply.toJson()) + .isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); } - public void testImageReply() { - WxMaKefuMessage reply = new WxMaKefuMessage(); - reply.setToUser("OPENID"); - reply.setMsgType(WxConsts.KefuMsgType.IMAGE); - reply.setMediaId("MEDIA_ID"); - Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); + public void testLinkBuilder() { + WxMaKefuMessage reply = WxMaKefuMessage.newLinkBuilder() + .toUser("OPENID") + .url("url") + .description("description") + .title("title") + .thumbUrl("thumbUrl") + .build(); + assertThat(reply.toJson()) + .isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"link\"," + + "\"link\":{\"title\":\"title\",\"description\":\"description\",\"url\":\"url\",\"thumb_url\":\"thumbUrl\"}}"); } - public void testImageBuild() { - WxMaKefuMessage reply = WxMaKefuMessage.newImageBuilder().toUser("OPENID").mediaId("MEDIA_ID").build(); - Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); + public void testMaPageBuilder() { + WxMaKefuMessage reply = WxMaKefuMessage.newMaPageBuilder() + .toUser("OPENID") + .title("title") + .pagePath("pagePath") + .thumbMediaId("thumbMediaId") + .build(); + assertThat(reply.toJson()) + .isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"miniprogrampage\"," + + "\"miniprogrampage\":{\"title\":\"title\",\"pagepath\":\"pagePath\",\"thumb_media_id\":\"thumbMediaId\"}}"); } diff --git a/weixin-java-miniapp/src/test/resources/test-config.sample.xml b/weixin-java-miniapp/src/test/resources/test-config-sample.xml similarity index 100% rename from weixin-java-miniapp/src/test/resources/test-config.sample.xml rename to weixin-java-miniapp/src/test/resources/test-config-sample.xml diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index a135b6dd..4dc1a99d 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -7,10 +7,10 @@ com.github.binarywang weixin-java-parent - 2.9.0 + 2.9.9.BETA weixin-java-mp - WeiXin Java Tools - MP + Weixin Java Tools - MP 微信公众号Java SDK @@ -65,6 +65,15 @@ logback-classic test + + org.assertj + assertj-guava + test + + + org.projectlombok + lombok + diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java index dbff2a7a..ea21c80b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java @@ -85,6 +85,8 @@ public interface WxMpConfigStorage { String getAesKey(); + String getTemplateId(); + long getExpiresTime(); String getOauth2redirectUri(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java index e74f5188..46a22fa8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java @@ -18,6 +18,7 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { protected volatile String appId; protected volatile String secret; protected volatile String token; + protected volatile String templateId; protected volatile String accessToken; protected volatile String aesKey; protected volatile long expiresTime; @@ -173,6 +174,15 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { this.token = token; } + @Override + public String getTemplateId() { + return this.templateId; + } + + public void setTemplateId(String templateId) { + this.templateId = templateId; + } + @Override public long getExpiresTime() { return this.expiresTime; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java index 6974221c..e20d1e3f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java @@ -51,7 +51,7 @@ public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage { @Override public String getAccessToken() { try (Jedis jedis = this.jedisPool.getResource()) { - return jedis.get(accessTokenKey); + return jedis.get(this.accessTokenKey); } } @@ -65,70 +65,70 @@ public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage { @Override public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { try (Jedis jedis = this.jedisPool.getResource()) { - jedis.setex(accessTokenKey, expiresInSeconds - 200, accessToken); + jedis.setex(this.accessTokenKey, expiresInSeconds - 200, accessToken); } } @Override public void expireAccessToken() { try (Jedis jedis = this.jedisPool.getResource()) { - jedis.expire(accessTokenKey, 0); + jedis.expire(this.accessTokenKey, 0); } } @Override public String getJsapiTicket() { try (Jedis jedis = this.jedisPool.getResource()) { - return jedis.get(jsapiTicketKey); + return jedis.get(this.jsapiTicketKey); } } @Override public boolean isJsapiTicketExpired() { try (Jedis jedis = this.jedisPool.getResource()) { - return jedis.ttl(jsapiTicketKey) < 2; + return jedis.ttl(this.jsapiTicketKey) < 2; } } @Override public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { try (Jedis jedis = this.jedisPool.getResource()) { - jedis.setex(jsapiTicketKey, expiresInSeconds - 200, jsapiTicket); + jedis.setex(this.jsapiTicketKey, expiresInSeconds - 200, jsapiTicket); } } @Override public void expireJsapiTicket() { try (Jedis jedis = this.jedisPool.getResource()) { - jedis.expire(jsapiTicketKey, 0); + jedis.expire(this.jsapiTicketKey, 0); } } @Override public String getCardApiTicket() { try (Jedis jedis = this.jedisPool.getResource()) { - return jedis.get(cardapiTicketKey); + return jedis.get(this.cardapiTicketKey); } } @Override public boolean isCardApiTicketExpired() { try (Jedis jedis = this.jedisPool.getResource()) { - return jedis.ttl(cardapiTicketKey) < 2; + return jedis.ttl(this.cardapiTicketKey) < 2; } } @Override public synchronized void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { try (Jedis jedis = this.jedisPool.getResource()) { - jedis.setex(cardapiTicketKey, expiresInSeconds - 200, cardApiTicket); + jedis.setex(this.cardapiTicketKey, expiresInSeconds - 200, cardApiTicket); } } @Override public void expireCardApiTicket() { try (Jedis jedis = this.jedisPool.getResource()) { - jedis.expire(cardapiTicketKey, 0); + jedis.expire(this.cardapiTicketKey, 0); } } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java index a7aacd54..669dfd7d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java @@ -7,7 +7,7 @@ import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; /** *
- * 群发消息服务类
+ * 群发消息服务类.
  * Created by Binary Wang on 2017-8-16.
  * 
* @@ -15,33 +15,33 @@ import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; */ public interface WxMpMassMessageService { /** - * 上传群发用的图文消息 + * 上传群发用的图文消息. */ String MEDIA_UPLOAD_NEWS_URL = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; /** - * 上传群发用的视频 + * 上传群发用的视频. */ String MEDIA_UPLOAD_VIDEO_URL = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; /** - * 分组群发消息 + * 分组群发消息. */ String MESSAGE_MASS_SENDALL_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; /** - * 按openId列表群发消息 + * 按openId列表群发消息. */ String MESSAGE_MASS_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; /** - * 群发消息预览接口 + * 群发消息预览接口. */ String MESSAGE_MASS_PREVIEW_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; /** - * 删除群发接口 + * 删除群发接口. */ String MESSAGE_MASS_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/delete"; /** *
-   * 上传群发用的图文消息,上传后才能群发图文消息
+   * 上传群发用的图文消息,上传后才能群发图文消息.
    *
    * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
    * 
@@ -53,7 +53,7 @@ public interface WxMpMassMessageService { /** *
-   * 上传群发用的视频,上传后才能群发视频消息
+   * 上传群发用的视频,上传后才能群发视频消息.
    * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
    * 
* @@ -64,7 +64,7 @@ public interface WxMpMassMessageService { /** *
-   * 分组群发消息
+   * 分组群发消息.
    * 如果发送图文消息,必须先使用 {@link #massNewsUpload(WxMpMassNews)} 获得media_id,然后再发送
    * 如果发送视频消息,必须先使用 {@link #massVideoUpload(WxMpMassVideo)} 获得media_id,然后再发送
    * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
@@ -74,7 +74,7 @@ public interface WxMpMassMessageService {
 
   /**
    * 
-   * 按openId列表群发消息
+   * 按openId列表群发消息.
    * 如果发送图文消息,必须先使用 {@link #massNewsUpload(WxMpMassNews)} 获得media_id,然后再发送
    * 如果发送视频消息,必须先使用 {@link #massVideoUpload(WxMpMassVideo)} 获得media_id,然后再发送
    * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
@@ -84,7 +84,7 @@ public interface WxMpMassMessageService {
 
   /**
    * 
-   * 群发消息预览接口
+   * 群发消息预览接口.
    * 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版。为了满足第三方平台开发者的需求,在保留对openID预览能力的同时,增加了对指定微信号发送预览的能力,但该能力每日调用次数有限制(100次),请勿滥用。
    * 接口调用请求说明
    *  http请求方式: POST
@@ -98,7 +98,7 @@ public interface WxMpMassMessageService {
 
   /**
    * 
-   * 删除群发
+   * 删除群发.
    * 群发之后,随时可以通过该接口删除群发。
    * 请注意:
    * 1、只有已经发送成功的消息才能删除
@@ -114,6 +114,6 @@ public interface WxMpMassMessageService {
    * @param msgId        发送出去的消息ID
    * @param articleIndex 要删除的文章在图文消息中的位置,第一篇编号为1,该字段不填或填0会删除全部文章
    */
-  void delete(Integer msgId, Integer articleIndex) throws WxErrorException;
+  void delete(Long msgId, Integer articleIndex) throws WxErrorException;
 
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java
index 6b7ddd08..9cf43b77 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java
@@ -130,6 +130,16 @@ public class WxMpMessageRouter {
    * 处理微信消息
    */
   public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage, final Map context) {
+    return route(wxMessage, context, null);
+  }
+  /**
+   * 处理微信消息
+   */
+  public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage, final Map context, WxMpService wxMpService) {
+    if(wxMpService == null){
+      wxMpService = this.wxMpService;
+    }
+    final WxMpService mpService = wxMpService;
     if (isMsgDuplicated(wxMessage)) {
       // 如果是重复消息,那么就不做处理
       return null;
@@ -159,12 +169,12 @@ public class WxMpMessageRouter {
           this.executorService.submit(new Runnable() {
             @Override
             public void run() {
-              rule.service(wxMessage, context, WxMpMessageRouter.this.wxMpService, WxMpMessageRouter.this.sessionManager, WxMpMessageRouter.this.exceptionHandler);
+              rule.service(wxMessage, context, mpService, WxMpMessageRouter.this.sessionManager, WxMpMessageRouter.this.exceptionHandler);
             }
           })
         );
       } else {
-        res = rule.service(wxMessage, context, this.wxMpService, this.sessionManager, this.exceptionHandler);
+        res = rule.service(wxMessage, context, mpService, this.sessionManager, this.exceptionHandler);
         // 在同步操作结束,session访问结束
         this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUser());
         sessionEndAccess(wxMessage);
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
index 0dd5a66b..5cbce570 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
@@ -90,7 +90,7 @@ public interface WxMpService {
    * 获取access_token,本方法线程安全
    * 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
    *
-   * 另:本service的所有方法都会在access_token过期是调用此方法
+   * 另:本service的所有方法都会在access_token过期时调用此方法
    *
    * 程序员在非必要情况下尽量不要主动调用此方法
    *
@@ -363,6 +363,13 @@ public interface WxMpService {
    */
   WxMpTemplateMsgService getTemplateMsgService();
 
+  /**
+   * 返回一次性订阅消息相关接口方法的实现类对象,以方便调用其各个接口
+   *
+   * @return WxMpSubscribeMsgService
+   */
+  WxMpSubscribeMsgService getSubscribeMsgService();
+
   /**
    * 返回硬件平台相关接口方法的实现类对象,以方便调用其各个接口
    *
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpSubscribeMsgService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpSubscribeMsgService.java
new file mode 100644
index 00000000..9e3b45e0
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpSubscribeMsgService.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.mp.api;
+
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.mp.bean.subscribe.WxMpSubscribeMessage;
+
+/**
+ * 
+ * 一次性订阅消息接口
+ * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1500374289_66bvB
+ * 
+ * + * @author Mklaus + * @date 2018-01-22 上午11:07 + */ +public interface WxMpSubscribeMsgService { + + /** + *
+   * 构造用户订阅一条模板消息授权的url连接
+   * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1500374289_66bvB
+   * 
+ * + * @param redirectURI 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode + * @param scene 重定向后会带上scene参数,开发者可以填0-10000的整形值,用来标识订阅场景值 + * @param reserved 用于保持请求和回调的状态,授权请后原样带回给第三方 (最多128字节,要求做urlencode) + * @return url + */ + String subscribeMsgAuthorizationUrl(String redirectURI, int scene, String reserved); + + /** + *
+   * 发送一次性订阅消息
+   * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1500374289_66bvB
+   * 
+ * + * @return 消息Id + */ + boolean sendSubscribeMessage(WxMpSubscribeMessage message) throws WxErrorException; + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java index 49ed7589..9a1d470b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java @@ -213,7 +213,7 @@ public class WxMpCardServiceImpl implements WxMpCardService { WxMpCardResult cardResult = WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement, new TypeToken() { }.getType()); - if (!cardResult.getErrorCode().equals("0")) { + if (!"0".equals(cardResult.getErrorCode())) { this.log.warn("朋友的券mark失败:{}", cardResult.getErrorMsg()); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java index 779bbc4d..266f79ed 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java @@ -57,7 +57,7 @@ public class WxMpMassMessageServiceImpl implements WxMpMassMessageService { } @Override - public void delete(Integer msgId, Integer articleIndex) throws WxErrorException { + public void delete(Long msgId, Integer articleIndex) throws WxErrorException { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("msg_id", msgId); jsonObject.addProperty("article_idx", articleIndex); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java index 520f69ea..67e9c37a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java @@ -34,10 +34,16 @@ public class WxMpMaterialServiceImpl implements WxMpMaterialService { @Override public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException { + File tmpFile = null; try { - return this.mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); + tmpFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType); + return this.mediaUpload(mediaType, tmpFile); } catch (IOException e) { throw new WxErrorException(WxError.builder().errorCode(-1).errorMsg(e.getMessage()).build(), e); + } finally { + if (tmpFile != null) { + tmpFile.delete(); + } } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceAbstractImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceBaseImpl.java similarity index 92% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceAbstractImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceBaseImpl.java index d81018da..0800f0a9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceAbstractImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceBaseImpl.java @@ -13,8 +13,11 @@ import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.mp.api.*; -import me.chanjar.weixin.mp.bean.*; -import me.chanjar.weixin.mp.bean.result.*; +import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; +import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo; +import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; +import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; +import me.chanjar.weixin.mp.bean.result.WxMpUser; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,7 +25,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.locks.Lock; -public abstract class WxMpServiceAbstractImpl implements WxMpService, RequestHttp { +public abstract class WxMpServiceBaseImpl implements WxMpService, RequestHttp { private static final JsonParser JSON_PARSER = new JsonParser(); @@ -40,6 +43,7 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ private WxMpDataCubeService dataCubeService = new WxMpDataCubeServiceImpl(this); private WxMpUserBlacklistService blackListService = new WxMpUserBlacklistServiceImpl(this); private WxMpTemplateMsgService templateMsgService = new WxMpTemplateMsgServiceImpl(this); + private WxMpSubscribeMsgService subscribeMsgService = new WxMpSubscribeMsgServiceImpl(this); private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); private WxMpShakeService shakeService = new WxMpShakeServiceImpl(this); private WxMpMemberCardService memberCardService = new WxMpMemberCardServiceImpl(this); @@ -91,14 +95,14 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ @Override public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { long timestamp = System.currentTimeMillis() / 1000; - String noncestr = RandomUtils.getRandomStr(); + String randomStr = RandomUtils.getRandomStr(); String jsapiTicket = getJsapiTicket(false); String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, - "noncestr=" + noncestr, "timestamp=" + timestamp, "url=" + url); + "noncestr=" + randomStr, "timestamp=" + timestamp, "url=" + url); WxJsapiSignature jsapiSignature = new WxJsapiSignature(); jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); jsapiSignature.setTimestamp(timestamp); - jsapiSignature.setNonceStr(noncestr); + jsapiSignature.setNonceStr(randomStr); jsapiSignature.setUrl(url); jsapiSignature.setSignature(signature); return jsapiSignature; @@ -110,10 +114,10 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ } @Override - public String shortUrl(String long_url) throws WxErrorException { + public String shortUrl(String longUrl) throws WxErrorException { JsonObject o = new JsonObject(); o.addProperty("action", "long2short"); - o.addProperty("long_url", long_url); + o.addProperty("long_url", longUrl); String responseContent = this.post(WxMpService.SHORTURL_API_URL, o.toString()); JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent); return tmpJsonElement.getAsJsonObject().get("short_url").getAsString(); @@ -160,12 +164,12 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ } @Override - public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { + public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken token, String lang) throws WxErrorException { if (lang == null) { lang = "zh_CN"; } - String url = String.format(WxMpService.OAUTH2_USERINFO_URL, oAuth2AccessToken.getAccessToken(), oAuth2AccessToken.getOpenId(), lang); + String url = String.format(WxMpService.OAUTH2_USERINFO_URL, token.getAccessToken(), token.getOpenId(), lang); try { RequestExecutor executor = SimpleGetRequestExecutor.create(this); @@ -177,8 +181,8 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ } @Override - public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { - String url = String.format(WxMpService.OAUTH2_VALIDATE_TOKEN_URL, oAuth2AccessToken.getAccessToken(), oAuth2AccessToken.getOpenId()); + public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken token) { + String url = String.format(WxMpService.OAUTH2_VALIDATE_TOKEN_URL, token.getAccessToken(), token.getOpenId()); try { SimpleGetRequestExecutor.create(this).execute(url, null); @@ -225,8 +229,9 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ } /** - * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 + * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求. */ + @Override public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { int retryTimes = 0; do { @@ -263,6 +268,7 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ if (uri.contains("access_token=")) { throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); } + String accessToken = getAccessToken(false); String uriWithAccessToken = uri + (uri.contains("?") ? "&" : "?") + "access_token=" + accessToken; @@ -294,7 +300,7 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ return null; } catch (IOException e) { this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【异常信息】:{}", uriWithAccessToken, data, e.getMessage()); - throw new RuntimeException(e); + throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e); } } @@ -374,6 +380,11 @@ public abstract class WxMpServiceAbstractImpl implements WxMpService, Requ return this.templateMsgService; } + @Override + public WxMpSubscribeMsgService getSubscribeMsgService() { + return this.subscribeMsgService; + } + @Override public WxMpDeviceService getDeviceService() { return this.deviceService; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceApacheHttpClientImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClientImpl.java similarity index 96% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceApacheHttpClientImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClientImpl.java index dd8aaf61..9a357ba5 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceApacheHttpClientImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpClientImpl.java @@ -19,9 +19,9 @@ import java.io.IOException; import java.util.concurrent.locks.Lock; /** - * apache-http方式实现 + * apache http client方式实现. */ -public class WxMpServiceApacheHttpClientImpl extends WxMpServiceAbstractImpl { +public class WxMpServiceHttpClientImpl extends WxMpServiceBaseImpl { private CloseableHttpClient httpClient; private HttpHost httpProxy; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java index 79317f99..79c3fad2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java @@ -8,5 +8,5 @@ package me.chanjar.weixin.mp.api.impl; * * @author Binary Wang */ -public class WxMpServiceImpl extends WxMpServiceApacheHttpClientImpl { +public class WxMpServiceImpl extends WxMpServiceHttpClientImpl { } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java index f146c365..fc4976be 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java @@ -14,7 +14,7 @@ import java.util.concurrent.locks.Lock; /** * jodd-http方式实现 */ -public class WxMpServiceJoddHttpImpl extends WxMpServiceAbstractImpl { +public class WxMpServiceJoddHttpImpl extends WxMpServiceBaseImpl { private HttpConnectionProvider httpClient; private ProxyInfo httpProxy; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java index b5135ceb..e0999241 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java @@ -11,7 +11,10 @@ import okhttp3.*; import java.io.IOException; import java.util.concurrent.locks.Lock; -public class WxMpServiceOkHttpImpl extends WxMpServiceAbstractImpl { +/** + * okhttp实现 + */ +public class WxMpServiceOkHttpImpl extends WxMpServiceBaseImpl { private OkHttpClient httpClient; private OkHttpProxyInfo httpProxy; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpSubscribeMsgServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpSubscribeMsgServiceImpl.java new file mode 100644 index 00000000..4cf17bd2 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpSubscribeMsgServiceImpl.java @@ -0,0 +1,42 @@ +package me.chanjar.weixin.mp.api.impl; + +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.URIUtil; +import me.chanjar.weixin.mp.api.WxMpConfigStorage; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.WxMpSubscribeMsgService; +import me.chanjar.weixin.mp.bean.subscribe.WxMpSubscribeMessage; + +/** + * @author Mklaus + * @date 2018-01-22 上午11:19 + */ +public class WxMpSubscribeMsgServiceImpl implements WxMpSubscribeMsgService { + private static final String SUBSCRIBE_MESSAGE_AUTHORIZE_URL = + "https://mp.weixin.qq.com/mp/subscribemsg?action=get_confirm&appid=%s&scene=%d&template_id=%s&redirect_url=%s&reserved=%s#wechat_redirect"; + private static final String SEND_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/subscribe"; + + + private WxMpService wxMpService; + + public WxMpSubscribeMsgServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public String subscribeMsgAuthorizationUrl(String redirectURI, int scene, String reserved) { + WxMpConfigStorage storage = this.wxMpService.getWxMpConfigStorage(); + return String.format(SUBSCRIBE_MESSAGE_AUTHORIZE_URL, + storage.getAppId(), scene, storage.getTemplateId(), URIUtil.encodeURIComponent(redirectURI), reserved); + } + + @Override + public boolean sendSubscribeMessage(WxMpSubscribeMessage message) throws WxErrorException { + if (message.getTemplateId() == null) { + message.setTemplateId(this.wxMpService.getWxMpConfigStorage().getTemplateId()); + } + + String responseContent = this.wxMpService.post(SEND_MESSAGE_URL, message.toJson()); + return responseContent != null; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java index 273282a6..f20c34d7 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java @@ -1,32 +1,38 @@ package me.chanjar.weixin.mp.bean.kefu.request; +import java.io.Serializable; + +import org.apache.commons.lang3.builder.ToStringBuilder; + import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; -import org.apache.commons.lang3.builder.ToStringBuilder; - -import java.io.Serializable; @Data @Builder +@AllArgsConstructor public class WxMpKfAccountRequest implements Serializable { private static final long serialVersionUID = -5451863610674856927L; /** - * kf_account 完整客服账号,格式为:账号前缀@公众号微信号 + * kf_account. + * 完整客服账号,格式为:账号前缀@公众号微信号 */ @SerializedName("kf_account") private String kfAccount; /** - * nickname 客服昵称,最长6个汉字或12个英文字符 + * nickname. + * 客服昵称,最长6个汉字或12个英文字符 */ @SerializedName("nickname") private String nickName; /** - * invite_wx 接收绑定邀请的客服微信号 + * invite_wx. + * 接收绑定邀请的客服微信号 */ @SerializedName("invite_wx") private String inviteWx; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java index d9232844..9b1ac647 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java @@ -58,7 +58,7 @@ public class WxMpMemberCardActivatedMessage implements Serializable { * 初始余额,不填为0。 */ @SerializedName("init_balance") - private Integer initBalance; + private Double initBalance; /** * 创建时字段custom_field1定义类型的初始值,限制为4个汉字,12字节。 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java index f666e655..d4323e09 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java @@ -52,12 +52,12 @@ public class WxMpMemberCardUpdateMessage implements Serializable { /** * 需要设置的余额全量值,传入的数值会直接显示在卡面 */ - private Integer balance; + private Double balance; /** * 本次余额变动值,传负数代表减少 */ @SerializedName("add_balance") - private Integer addBalance; + private Double addBalance; /** * 商家自定义金额消耗记录,不超过14个汉字。 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java index 7ceac8e8..355b67df 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java @@ -28,7 +28,7 @@ public class WxMpMemberCardUpdateResult implements Serializable { private Integer resultBonus; - private Integer resultBalance; + private Double resultBalance; @Override public String toString() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java index a0ad47f3..d87f4ba3 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java @@ -33,6 +33,8 @@ public class WxMpMemberCardUserInfoResult implements Serializable { private Integer bonus; + private Double balance; + private String sex; private MemberCardUserInfo userInfo; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java index 0193efee..b0429cf7 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java @@ -6,6 +6,9 @@ import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; import java.io.Serializable; +/** + * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 + */ @Data public class WxMpOAuth2AccessToken implements Serializable { private static final long serialVersionUID = -1345910558078620805L; @@ -20,6 +23,10 @@ public class WxMpOAuth2AccessToken implements Serializable { private String scope; + /** + * https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&announce_id=11513156443eZYea&version=&lang=zh_CN. + * 本接口在scope参数为snsapi_base时不再提供unionID字段。 + */ private String unionId; public static WxMpOAuth2AccessToken fromJson(String json) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUser.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUser.java index ec969e28..6cd9ca06 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUser.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUser.java @@ -12,7 +12,7 @@ import java.lang.reflect.Type; import java.util.List; /** - * 微信用户信息 + * 微信用户信息. * * @author chanjarster */ @@ -23,7 +23,14 @@ public class WxMpUser implements Serializable { private Boolean subscribe; private String openId; private String nickname; - private String sex; + /** + * 性别描述信息:男、女、未知等. + */ + private String sexDesc; + /** + * 性别表示:1,2等数字. + */ + private Integer sex; private String language; private String city; private String province; @@ -31,14 +38,24 @@ public class WxMpUser implements Serializable { private String headImgUrl; private Long subscribeTime; /** + * https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&announce_id=11513156443eZYea&version=&lang=zh_CN + *
    * 只有在将公众号绑定到微信开放平台帐号后,才会出现该字段。
+   * 另外,在用户未关注公众号时,将不返回用户unionID信息。
+   * 已关注的用户,开发者可使用“获取用户基本信息接口”获取unionID;
+   * 未关注用户,开发者可使用“微信授权登录接口”并将scope参数设置为snsapi_userinfo,获取用户unionID
+   * 
*/ private String unionId; - private Integer sexId; private String remark; private Integer groupId; private Long[] tagIds; + /** + * 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom). + */ + private String[] privileges; + public static WxMpUser fromJson(String json) { return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpUser.class); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/subscribe/WxMpSubscribeMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/subscribe/WxMpSubscribeMessage.java new file mode 100644 index 00000000..8c784c66 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/subscribe/WxMpSubscribeMessage.java @@ -0,0 +1,82 @@ +package me.chanjar.weixin.mp.bean.subscribe; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Mklaus + * @date 2018-01-22 下午12:18 + */ +@Data +@NoArgsConstructor +@Builder +@AllArgsConstructor +public class WxMpSubscribeMessage { + + /** + * 接收者openid. + */ + private String toUser; + + /** + * 模板ID. + */ + private String templateId; + + /** + * 模板跳转链接. + *
+   * url和miniprogram都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。
+   * 开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。
+   * 
+ */ + private String url; + + /** + * 跳小程序所需数据,不需跳小程序可不用传该数据. + * + * @see #url + */ + private MiniProgram miniProgram; + + /** + * 订阅场景值 + */ + private String scene; + + /** + * 消息标题 (15字以内) + */ + private String title; + + /** + * 消息内容文本 (200字以内) + */ + private String contentValue; + + /** + * 消息内容文本颜色 + */ + private String contentColor; + + + public String toJson() { + return WxMpGsonBuilder.INSTANCE.create().toJson(this); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class MiniProgram implements Serializable { + private static final long serialVersionUID = -7945254706501974849L; + + private String appid; + private String pagePath; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java index aa5a1804..a7ef1802 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java @@ -1,54 +1,68 @@ package me.chanjar.weixin.mp.bean.template; -import lombok.Builder; -import lombok.Data; -import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; - import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + /** + * 模板消息. * 参考 http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277&token=&lang=zh_CN 发送模板消息接口部分 + * + * @author Binary Wang */ -@Data +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor @Builder public class WxMpTemplateMessage implements Serializable { private static final long serialVersionUID = 5063374783759519418L; /** - * 接收者openid + * 接收者openid. */ private String toUser; /** - * 模板ID + * 模板ID. */ private String templateId; /** + * 模板跳转链接. *
-   * 跳小程序所需数据,不需跳小程序可不用传该数据
    * url和miniprogram都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。
    * 开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。
    * 
*/ private String url; + /** - * 模板跳转链接 + * 跳小程序所需数据,不需跳小程序可不用传该数据. * * @see #url */ private MiniProgram miniProgram; /** - * 模板数据 + * 模板数据. */ - @Builder.Default - private final List data = new ArrayList<>(); + private List data; - public void addWxMpTemplateData(WxMpTemplateData datum) { + public WxMpTemplateMessage addData(WxMpTemplateData datum) { + if (this.data == null) { + this.data = new ArrayList<>(); + } this.data.add(datum); + return this; } public String toJson() { @@ -56,17 +70,13 @@ public class WxMpTemplateMessage implements Serializable { } @Data + @NoArgsConstructor + @AllArgsConstructor public static class MiniProgram implements Serializable { private static final long serialVersionUID = -7945254706501974849L; private String appid; - private String pagePath; - - public MiniProgram(String appid, String pagePath) { - this.appid = appid; - this.pagePath = pagePath; - } - + private String path; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java index 5b199cc5..741bffae 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java @@ -25,7 +25,7 @@ public abstract class BaseBuilder { public void setCommon(WxMpXmlOutMessage m) { m.setToUserName(this.toUserName); m.setFromUserName(this.fromUserName); - m.setCreateTime(System.currentTimeMillis() / 1000l); + m.setCreateTime(System.currentTimeMillis() / 1000L); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java index d001876d..c27165bf 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMediaImgUploadRequestExecutor.java @@ -55,6 +55,8 @@ public class ApacheMediaImgUploadRequestExecutor extends MediaImgUploadRequestEx } return WxMediaImgUploadResult.fromJson(responseContent); + } finally { + httpPost.releaseConnection(); } } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java index 124845ed..524e1531 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpGsonBuilder.java @@ -10,6 +10,7 @@ import me.chanjar.weixin.mp.bean.membercard.WxMpMemberCardUpdateResult; import me.chanjar.weixin.mp.bean.membercard.WxMpMemberCardUserInfoResult; import me.chanjar.weixin.mp.bean.material.*; import me.chanjar.weixin.mp.bean.result.*; +import me.chanjar.weixin.mp.bean.subscribe.WxMpSubscribeMessage; import me.chanjar.weixin.mp.bean.template.WxMpTemplateIndustry; import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; @@ -30,6 +31,7 @@ public class WxMpGsonBuilder { INSTANCE.registerTypeAdapter(WxMpMassUploadResult.class, new WxMpMassUploadResultAdapter()); INSTANCE.registerTypeAdapter(WxMpQrCodeTicket.class, new WxQrCodeTicketAdapter()); INSTANCE.registerTypeAdapter(WxMpTemplateMessage.class, new WxMpTemplateMessageGsonAdapter()); + INSTANCE.registerTypeAdapter(WxMpSubscribeMessage.class, new WxMpSubscribeMessageGsonAdapter()); INSTANCE.registerTypeAdapter(WxMpSemanticQueryResult.class, new WxMpSemanticQueryResultAdapter()); INSTANCE.registerTypeAdapter(WxMpOAuth2AccessToken.class, new WxMpOAuth2AccessTokenAdapter()); INSTANCE.registerTypeAdapter(WxDataCubeUserSummary.class, new WxMpUserSummaryGsonAdapter()); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpKefuMessageGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpKefuMessageGsonAdapter.java index 34b91e5a..fc44ee4d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpKefuMessageGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpKefuMessageGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsArticleGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsArticleGsonAdapter.java index e4d88403..03b14b4a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsArticleGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsArticleGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsGsonAdapter.java index fecf494d..b780300e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassNewsGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassOpenIdsMessageGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassOpenIdsMessageGsonAdapter.java index cbb5bf6b..3a7d3b2a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassOpenIdsMessageGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassOpenIdsMessageGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassSendResultAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassSendResultAdapter.java index 5a652f0a..aebbca5e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassSendResultAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassSendResultAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassTagMessageGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassTagMessageGsonAdapter.java index 75c7f4d6..f432c919 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassTagMessageGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassTagMessageGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.JsonElement; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassUploadResultAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassUploadResultAdapter.java index e20175d7..b526e8ce 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassUploadResultAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassUploadResultAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassVideoAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassVideoAdapter.java index e7bd8c39..f6570f48 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassVideoAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMassVideoAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.JsonElement; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialArticleUpdateGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialArticleUpdateGsonAdapter.java index 2705462e..bdbbde56 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialArticleUpdateGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialArticleUpdateGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.JsonElement; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialCountResultAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialCountResultAdapter.java index 3f96addf..ce002a28 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialCountResultAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialCountResultAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonAdapter.java index 1460813e..b19fa422 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonItemAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonItemAdapter.java index 7d73ca83..d17bb50c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonItemAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialFileBatchGetGsonItemAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsArticleGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsArticleGsonAdapter.java index 5a17a7bd..273cc39f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsArticleGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsArticleGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonAdapter.java index 2a88a8f2..203b1ad8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonItemAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonItemAdapter.java index e56ecf42..2c455e76 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonItemAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsBatchGetGsonItemAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsGsonAdapter.java index 084e355c..6d307c47 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialNewsGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialUploadResultAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialUploadResultAdapter.java index 0ccefd83..db279ce1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialUploadResultAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMaterialUploadResultAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMemberCardUpdateResultGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMemberCardUpdateResultGsonAdapter.java index dc068db1..0d459463 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMemberCardUpdateResultGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpMemberCardUpdateResultGsonAdapter.java @@ -29,7 +29,7 @@ public class WxMpMemberCardUpdateResultGsonAdapter implements JsonDeserializer { + + @Override + public JsonElement serialize(WxMpSubscribeMessage message, Type type, JsonSerializationContext jsonSerializationContext) { + JsonObject messageJson = new JsonObject(); + messageJson.addProperty("touser", message.getToUser()); + messageJson.addProperty("template_id", message.getTemplateId()); + + if (message.getUrl() != null) { + messageJson.addProperty("url", message.getUrl()); + } + + if (message.getMiniProgram() != null) { + JsonObject miniProgramJson = new JsonObject(); + miniProgramJson.addProperty("appid", message.getMiniProgram().getAppid()); + miniProgramJson.addProperty("pagepath", message.getMiniProgram().getPagePath()); + messageJson.add("miniprogram", miniProgramJson); + } + + messageJson.addProperty("scene", message.getScene()); + messageJson.addProperty("title", message.getTitle()); + + JsonObject data = new JsonObject(); + messageJson.add("data", data); + + JsonObject content = new JsonObject(); + data.add("content", content); + + if (message.getContentValue() != null) { + content.addProperty("value", message.getContentValue()); + } + + if (message.getContentColor() != null) { + content.addProperty("color", message.getContentColor()); + } + + return messageJson; + + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpTemplateMessageGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpTemplateMessageGsonAdapter.java index 9668a768..f79cd4ca 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpTemplateMessageGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpTemplateMessageGsonAdapter.java @@ -1,13 +1,7 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; +import java.lang.reflect.Type; + import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; @@ -15,8 +9,6 @@ import com.google.gson.JsonSerializer; import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; -import java.lang.reflect.Type; - public class WxMpTemplateMessageGsonAdapter implements JsonSerializer { @Override @@ -31,7 +23,7 @@ public class WxMpTemplateMessageGsonAdapter implements JsonSerializer { @Override public WxMpUser deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject o = json.getAsJsonObject(); - WxMpUser wxMpUser = new WxMpUser(); + WxMpUser user = new WxMpUser(); Integer subscribe = GsonHelper.getInteger(o, "subscribe"); if (subscribe != null) { - wxMpUser.setSubscribe(!new Integer(0).equals(subscribe)); + user.setSubscribe(!new Integer(0).equals(subscribe)); } - wxMpUser.setCity(GsonHelper.getString(o, "city")); - wxMpUser.setCountry(GsonHelper.getString(o, "country")); - wxMpUser.setHeadImgUrl(GsonHelper.getString(o, "headimgurl")); - wxMpUser.setLanguage(GsonHelper.getString(o, "language")); - wxMpUser.setNickname(GsonHelper.getString(o, "nickname")); - wxMpUser.setOpenId(GsonHelper.getString(o, "openid")); - wxMpUser.setProvince(GsonHelper.getString(o, "province")); - wxMpUser.setSubscribeTime(GsonHelper.getLong(o, "subscribe_time")); - wxMpUser.setUnionId(GsonHelper.getString(o, "unionid")); - Integer sexId = GsonHelper.getInteger(o, "sex"); - wxMpUser.setRemark(GsonHelper.getString(o, "remark")); - wxMpUser.setGroupId(GsonHelper.getInteger(o, "groupid")); - wxMpUser.setTagIds(GsonHelper.getLongArray(o, "tagid_list")); - wxMpUser.setSexId(sexId); - if (new Integer(1).equals(sexId)) { - wxMpUser.setSex("男"); - } else if (new Integer(2).equals(sexId)) { - wxMpUser.setSex("女"); - } else { - wxMpUser.setSex("未知"); + user.setCity(GsonHelper.getString(o, "city")); + user.setCountry(GsonHelper.getString(o, "country")); + user.setHeadImgUrl(GsonHelper.getString(o, "headimgurl")); + user.setLanguage(GsonHelper.getString(o, "language")); + user.setNickname(GsonHelper.getString(o, "nickname")); + user.setOpenId(GsonHelper.getString(o, "openid")); + user.setProvince(GsonHelper.getString(o, "province")); + user.setSubscribeTime(GsonHelper.getLong(o, "subscribe_time")); + user.setUnionId(GsonHelper.getString(o, "unionid")); + user.setRemark(GsonHelper.getString(o, "remark")); + user.setGroupId(GsonHelper.getInteger(o, "groupid")); + user.setTagIds(GsonHelper.getLongArray(o, "tagid_list")); + user.setPrivileges(GsonHelper.getStringArray(o, "privilege")); + + Integer sex = GsonHelper.getInteger(o, "sex"); + if (sex != null) { + user.setSex(sex); + switch (sex) { + case 1: + user.setSexDesc("男"); + break; + case 2: + user.setSexDesc("女"); + break; + default: + user.setSexDesc("未知"); + } + } - return wxMpUser; + return user; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpUserSummaryGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpUserSummaryGsonAdapter.java index b101e01f..b5a2a782 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpUserSummaryGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpUserSummaryGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxQrCodeTicketAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxQrCodeTicketAdapter.java index 80b5bc90..c052826b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxQrCodeTicketAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxQrCodeTicketAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxUserListGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxUserListGsonAdapter.java index e150a63f..619017e8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxUserListGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxUserListGsonAdapter.java @@ -1,11 +1,3 @@ -/* - * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved. - * - * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended - * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction - * arose from modification of the original source, or other redistribution of this source - * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD. - */ package me.chanjar.weixin.mp.util.json; import com.google.gson.*; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java index 68cd475c..6588cac3 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java @@ -1,11 +1,22 @@ package me.chanjar.weixin.mp.util.xml; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import com.thoughtworks.xstream.XStream; import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import me.chanjar.weixin.mp.bean.message.*; - -import java.io.InputStream; -import java.util.*; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMusicMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTransferKefuMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutVideoMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutVoiceMessage; public class XStreamTransformer { private static final Map, XStream> CLASS_2_XSTREAM_INSTANCE = new HashMap<>(); @@ -22,7 +33,7 @@ public class XStreamTransformer { } /** - * xml -> pojo + * xml -> pojo. */ @SuppressWarnings("unchecked") public static T fromXml(Class clazz, String xml) { @@ -37,24 +48,24 @@ public class XStreamTransformer { } /** - * pojo -> xml + * pojo -> xml. */ public static String toXml(Class clazz, T object) { return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object); } /** - * 注册扩展消息的解析器 + * 注册扩展消息的解析器. * * @param clz 类型 * @param xStream xml解析器 */ - private static void register(Class clz, XStream xStream) { + public static void register(Class clz, XStream xStream) { CLASS_2_XSTREAM_INSTANCE.put(clz, xStream); } /** - * 会自动注册该类及其子类 + * 会自动注册该类及其子类. * * @param clz 要注册的类 */ diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java index e8630dbc..2a07e3b9 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java @@ -3,7 +3,7 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.api.impl.WxMpServiceApacheHttpClientImpl; +import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl; import org.testng.annotations.*; import java.util.concurrent.ExecutionException; @@ -16,7 +16,7 @@ public class WxMpBusyRetryTest { @DataProvider(name = "getService") public Object[][] getService() { - WxMpService service = new WxMpServiceApacheHttpClientImpl() { + WxMpService service = new WxMpServiceHttpClientImpl() { @Override public synchronized T executeInternal( diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java index e6be8730..8e1c58d7 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java @@ -23,7 +23,7 @@ public class WxMpJsAPITest { public void test() { - long timestamp = 1419835025l; + long timestamp = 1419835025L; String url = "http://omstest.vmall.com:23568/thirdparty/wechat/vcode/gotoshare?quantity=1&batchName=MATE7"; String noncestr = "82693e11-b9bc-448e-892f-f5289f46cd0f"; String jsapiTicket = "bxLdikRXVbTPdHSM05e5u4RbEYQn7pNQMPrfzl8lJNb1foLDa3HIwI3BRMkQmSO_5F64VFa75uURcq6Uz7QHgA"; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMessageRouterTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMessageRouterTest.java index ba35e110..4b919a22 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMessageRouterTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMessageRouterTest.java @@ -66,7 +66,7 @@ public class WxMpMessageRouterTest { WxMpMessageRouter router = new WxMpMessageRouter(null); prepare(true, sb, router); router.route(message); - Thread.sleep(500l); + Thread.sleep(500); Assert.assertEquals(sb.toString(), expected); } @@ -86,7 +86,7 @@ public class WxMpMessageRouterTest { public void run() { router.route(m); try { - Thread.sleep(1000l); + Thread.sleep(1000); } catch (InterruptedException e) { } } @@ -95,7 +95,7 @@ public class WxMpMessageRouterTest { new Thread(r).start(); } - Thread.sleep(1000l * 2); + Thread.sleep(2000); } @DataProvider(name = "messages-1") @@ -180,7 +180,7 @@ public class WxMpMessageRouterTest { msg.setFromUser("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -200,7 +200,7 @@ public class WxMpMessageRouterTest { msg.setFromUser("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } { @@ -214,7 +214,7 @@ public class WxMpMessageRouterTest { msg.setFromUser("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -234,7 +234,7 @@ public class WxMpMessageRouterTest { msg.setFromUser("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -253,7 +253,7 @@ public class WxMpMessageRouterTest { msg.setFromUser("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } @@ -267,7 +267,7 @@ public class WxMpMessageRouterTest { msg.setFromUser("abc"); router.route(msg); - Thread.sleep(2000l); + Thread.sleep(2000); Assert.assertEquals(ism.getActiveSessions(), 0); } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index 309d3818..d0c3aac8 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -10,12 +10,13 @@ import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.result.*; import org.joda.time.DateTime; -import org.testng.*; import org.testng.annotations.*; import java.io.File; import java.util.Date; +import static org.assertj.core.api.Assertions.assertThat; + /** * 测试客服相关接口 * @@ -29,53 +30,50 @@ public class WxMpKefuServiceImplTest { protected WxMpService wxService; public void testSendKefuMpNewsMessage() throws WxErrorException { - TestConfigStorage configStorage = (TestConfigStorage) this.wxService - .getWxMpConfigStorage(); + TestConfigStorage configStorage = (TestConfigStorage) this.wxService.getWxMpConfigStorage(); WxMpKefuMessage message = new WxMpKefuMessage(); message.setMsgType(WxConsts.KefuMsgType.MPNEWS); message.setToUser(configStorage.getOpenid()); message.setMpNewsMediaId("52R6dL2FxDpM9N1rCY3sYBqHwq-L7K_lz1sPI71idMg"); - this.wxService.getKefuService().sendKefuMessage(message); + boolean result = this.wxService.getKefuService().sendKefuMessage(message); + assertThat(result).isTrue(); } public void testSendKefuMessage() throws WxErrorException { - TestConfigStorage configStorage = (TestConfigStorage) this.wxService - .getWxMpConfigStorage(); + TestConfigStorage configStorage = (TestConfigStorage) this.wxService.getWxMpConfigStorage(); WxMpKefuMessage message = new WxMpKefuMessage(); message.setMsgType(WxConsts.KefuMsgType.TEXT); message.setToUser(configStorage.getOpenid()); - message.setContent( - "欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); + message.setContent("欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); - this.wxService.getKefuService().sendKefuMessage(message); + boolean result = this.wxService.getKefuService().sendKefuMessage(message); + assertThat(result).isTrue(); } public void testSendKefuMessageWithKfAccount() throws WxErrorException { - TestConfigStorage configStorage = (TestConfigStorage) this.wxService - .getWxMpConfigStorage(); + TestConfigStorage configStorage = (TestConfigStorage) this.wxService.getWxMpConfigStorage(); WxMpKefuMessage message = new WxMpKefuMessage(); message.setMsgType(WxConsts.KefuMsgType.TEXT); message.setToUser(configStorage.getOpenid()); message.setKfAccount(configStorage.getKfAccount()); - message.setContent( - "欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); + message.setContent("欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); - this.wxService.getKefuService().sendKefuMessage(message); + boolean result = this.wxService.getKefuService().sendKefuMessage(message); + assertThat(result).isTrue(); } public void testKfList() throws WxErrorException { WxMpKfList kfList = this.wxService.getKefuService().kfList(); - Assert.assertNotNull(kfList); + assertThat(kfList).isNotNull(); for (WxMpKfInfo k : kfList.getKfList()) { System.err.println(k); } } public void testKfOnlineList() throws WxErrorException { - WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService() - .kfOnlineList(); - Assert.assertNotNull(kfOnlineList); + WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService().kfOnlineList(); + assertThat(kfOnlineList).isNotNull(); for (WxMpKfInfo k : kfOnlineList.getKfOnlineList()) { System.err.println(k); } @@ -83,8 +81,7 @@ public class WxMpKefuServiceImplTest { @DataProvider public Object[][] getKfAccount() { - TestConfigStorage configStorage = (TestConfigStorage) this.wxService - .getWxMpConfigStorage(); + TestConfigStorage configStorage = (TestConfigStorage) this.wxService.getWxMpConfigStorage(); return new Object[][]{{configStorage.getKfAccount()}}; } @@ -92,7 +89,7 @@ public class WxMpKefuServiceImplTest { public void testKfAccountAdd(String kfAccount) throws WxErrorException { WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() .kfAccount(kfAccount).nickName("我晕").build(); - Assert.assertTrue(this.wxService.getKefuService().kfAccountAdd(request)); + assertThat(this.wxService.getKefuService().kfAccountAdd(request)).isTrue(); } @Test(dependsOnMethods = { @@ -100,7 +97,7 @@ public class WxMpKefuServiceImplTest { public void testKfAccountUpdate(String kfAccount) throws WxErrorException { WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() .kfAccount(kfAccount).nickName("我晕").build(); - Assert.assertTrue(this.wxService.getKefuService().kfAccountUpdate(request)); + assertThat(this.wxService.getKefuService().kfAccountUpdate(request)).isTrue(); } @Test(dependsOnMethods = { @@ -108,71 +105,59 @@ public class WxMpKefuServiceImplTest { public void testKfAccountInviteWorker(String kfAccount) throws WxErrorException { WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() .kfAccount(kfAccount).inviteWx(" ").build(); - Assert.assertTrue(this.wxService.getKefuService().kfAccountInviteWorker(request)); + assertThat(this.wxService.getKefuService().kfAccountInviteWorker(request)).isTrue(); } - @Test(dependsOnMethods = { - "testKfAccountUpdate"}, dataProvider = "getKfAccount") - public void testKfAccountUploadHeadImg(String kfAccount) - throws WxErrorException { + @Test(dependsOnMethods = {"testKfAccountUpdate", "testKfAccountAdd"}, dataProvider = "getKfAccount") + public void testKfAccountUploadHeadImg(String kfAccount) throws WxErrorException { File imgFile = new File("src\\test\\resources\\mm.jpeg"); - boolean result = this.wxService.getKefuService() - .kfAccountUploadHeadImg(kfAccount, imgFile); - Assert.assertTrue(result); + boolean result = this.wxService.getKefuService().kfAccountUploadHeadImg(kfAccount, imgFile); + assertThat(result).isTrue(); } @Test(dataProvider = "getKfAccount") public void testKfAccountDel(String kfAccount) throws WxErrorException { boolean result = this.wxService.getKefuService().kfAccountDel(kfAccount); - Assert.assertTrue(result); + assertThat(result).isTrue(); } @DataProvider public Object[][] getKfAccountAndOpenid() { - TestConfigStorage configStorage = (TestConfigStorage) this.wxService - .getWxMpConfigStorage(); - return new Object[][]{ - {configStorage.getKfAccount(), configStorage.getOpenid()}}; + TestConfigStorage configStorage = (TestConfigStorage) this.wxService.getWxMpConfigStorage(); + return new Object[][]{{configStorage.getKfAccount(), configStorage.getOpenid()}}; } @Test(dataProvider = "getKfAccountAndOpenid") - public void testKfSessionCreate(String kfAccount, String openid) - throws WxErrorException { - boolean result = this.wxService.getKefuService().kfSessionCreate(openid, - kfAccount); - Assert.assertTrue(result); + public void testKfSessionCreate(String kfAccount, String openid) throws WxErrorException { + boolean result = this.wxService.getKefuService().kfSessionCreate(openid, kfAccount); + assertThat(result).isTrue(); } @Test(dataProvider = "getKfAccountAndOpenid") public void testKfSessionClose(String kfAccount, String openid) throws WxErrorException { - boolean result = this.wxService.getKefuService().kfSessionClose(openid, - kfAccount); - Assert.assertTrue(result); + boolean result = this.wxService.getKefuService().kfSessionClose(openid, kfAccount); + assertThat(result).isTrue(); } @Test(dataProvider = "getKfAccountAndOpenid") - public void testKfSessionGet(@SuppressWarnings("unused") String kfAccount, - String openid) throws WxErrorException { - WxMpKfSessionGetResult result = this.wxService.getKefuService() - .kfSessionGet(openid); - Assert.assertNotNull(result); + public void testKfSessionGet(@SuppressWarnings("unused") String kfAccount, String openid) throws WxErrorException { + WxMpKfSessionGetResult result = this.wxService.getKefuService().kfSessionGet(openid); + assertThat(result).isNotNull(); System.err.println(result); } @Test(dataProvider = "getKfAccount") public void testKfSessionList(String kfAccount) throws WxErrorException { - WxMpKfSessionList result = this.wxService.getKefuService() - .kfSessionList(kfAccount); - Assert.assertNotNull(result); + WxMpKfSessionList result = this.wxService.getKefuService().kfSessionList(kfAccount); + assertThat(result).isNotNull(); System.err.println(result); } @Test public void testKfSessionGetWaitCase() throws WxErrorException { - WxMpKfSessionWaitCaseList result = this.wxService.getKefuService() - .kfSessionGetWaitCase(); - Assert.assertNotNull(result); + WxMpKfSessionWaitCaseList result = this.wxService.getKefuService().kfSessionGetWaitCase(); + assertThat(result).isNotNull(); System.err.println(result); } @@ -181,7 +166,7 @@ public class WxMpKefuServiceImplTest { Date startTime = DateTime.now().minusDays(1).toDate(); Date endTime = DateTime.now().minusDays(0).toDate(); WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime, endTime, 1L, 50); - Assert.assertNotNull(result); + assertThat(result).isNotNull(); System.err.println(result); } @@ -190,7 +175,7 @@ public class WxMpKefuServiceImplTest { Date startTime = DateTime.now().minusDays(1).toDate(); Date endTime = DateTime.now().minusDays(0).toDate(); WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime, endTime); - Assert.assertNotNull(result); + assertThat(result).isNotNull(); System.err.println(result); } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImplTest.java index 92667e95..da025374 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImplTest.java @@ -183,7 +183,7 @@ public class WxMpMassMessageServiceImplTest { @Test public void testMassDelete() throws Exception { - this.wxService.getMassMessageService().delete(1,2); + this.wxService.getMassMessageService().delete(1L,2); } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpSubscribeMsgServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpSubscribeMsgServiceImplTest.java new file mode 100644 index 00000000..3db67ef6 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpSubscribeMsgServiceImplTest.java @@ -0,0 +1,48 @@ +package me.chanjar.weixin.mp.api.impl; + +import com.google.inject.Inject; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.test.ApiTestModule; +import me.chanjar.weixin.mp.api.test.TestConfigStorage; +import me.chanjar.weixin.mp.bean.subscribe.WxMpSubscribeMessage; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author Mklaus + * @date 2018-01-22 下午2:02 + */ +@Guice(modules = ApiTestModule.class) +public class WxMpSubscribeMsgServiceImplTest { + + @Inject + protected WxMpService wxService; + + @Test + public void testSendSubscribeMessage() throws WxErrorException { + TestConfigStorage configStorage = (TestConfigStorage) this.wxService + .getWxMpConfigStorage(); + + WxMpSubscribeMessage message = WxMpSubscribeMessage.builder() + .title("weixin test") + .toUser(configStorage.getOpenid()) + .scene("1000") + .contentColor("#FF0000") + .contentValue("Send subscribe message test") + .build(); + + try { + boolean send = this.wxService.getSubscribeMsgService().sendSubscribeMessage(message); + Assert.assertTrue(send); + } catch (WxErrorException e) { + // 当用户没有授权,获取之前的授权已使用。微信会返回错误代码 {"errcode":43101,"errmsg":"user refuse to accept the msg hint: [xxxxxxxxxxx]"} + if (e.getError().getErrorCode() != 43101) { + throw e; + } + } + + } + +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpTemplateMsgServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpTemplateMsgServiceImplTest.java index 96cab2c1..4457aeb3 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpTemplateMsgServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpTemplateMsgServiceImplTest.java @@ -10,8 +10,9 @@ import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; import me.chanjar.weixin.mp.bean.template.WxMpTemplateIndustry; import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; import org.apache.commons.lang3.RandomStringUtils; -import org.testng.*; -import org.testng.annotations.*; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; import java.text.SimpleDateFormat; import java.util.Date; @@ -37,12 +38,12 @@ public class WxMpTemplateMsgServiceImplTest { .getWxMpConfigStorage(); WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder() .toUser(configStorage.getOpenid()) - .templateId(configStorage.getTemplateId()).build(); - templateMessage.addWxMpTemplateData( - new WxMpTemplateData("first", dateFormat.format(new Date()), "#FF00FF")); - templateMessage.addWxMpTemplateData( - new WxMpTemplateData("remark", RandomStringUtils.randomAlphanumeric(100), "#FF00FF")); - templateMessage.setUrl(" "); + .templateId(configStorage.getTemplateId()) + .url(" ") + .build(); + + templateMessage.addData(new WxMpTemplateData("first", dateFormat.format(new Date()), "#FF00FF")) + .addData(new WxMpTemplateData("remark", RandomStringUtils.randomAlphanumeric(100), "#FF00FF")); String msgId = this.wxService.getTemplateMsgService().sendTemplateMsg(templateMessage); Assert.assertNotNull(msgId); System.out.println(msgId); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessageTest.java index ab732c31..8aaa3b28 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessageTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessageTest.java @@ -9,7 +9,7 @@ public class WxMpXmlOutImageMessageTest { public void test() { WxMpXmlOutImageMessage m = new WxMpXmlOutImageMessage(); m.setMediaId("ddfefesfsdfef"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("from"); m.setToUserName("to"); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java index f8f72c9e..26eb06a2 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java @@ -8,7 +8,7 @@ public class WxMpXmlOutNewsMessageTest { public void test() { WxMpXmlOutNewsMessage m = new WxMpXmlOutNewsMessage(); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("fromUser"); m.setToUserName("toUser"); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java index c005c261..605f4b25 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java @@ -9,7 +9,7 @@ public class WxMpXmlOutTextMessageTest { public void test() { WxMpXmlOutTextMessage m = new WxMpXmlOutTextMessage(); m.setContent("content"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("from"); m.setToUserName("to"); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java index 2ba9f549..a00cdc32 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java @@ -11,7 +11,7 @@ public class WxMpXmlOutVideoMessageTest { m.setMediaId("media_id"); m.setTitle("title"); m.setDescription("ddfff"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("fromUser"); m.setToUserName("toUser"); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java index d3f1346f..d426cbe3 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java @@ -9,7 +9,7 @@ public class WxMpXmlOutVoiceMessageTest { public void test() { WxMpXmlOutVoiceMessage m = new WxMpXmlOutVoiceMessage(); m.setMediaId("ddfefesfsdfef"); - m.setCreateTime(1122l); + m.setCreateTime(1122L); m.setFromUserName("from"); m.setToUserName("to"); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/subscribe/WxMpSubscribeMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/subscribe/WxMpSubscribeMessageTest.java new file mode 100644 index 00000000..c6ae4779 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/subscribe/WxMpSubscribeMessageTest.java @@ -0,0 +1,46 @@ +package me.chanjar.weixin.mp.bean.subscribe; + +import org.testng.annotations.*; + +import static org.testng.AssertJUnit.*; + +/** + * @author Mklaus + * @date 2018-01-22 下午1:41 + */ +public class WxMpSubscribeMessageTest { + @Test + public void testToJson() { + String actual = "{" + + "\"touser\":\"OPENID\"," + + "\"template_id\":\"TEMPLATE_ID\"," + + "\"url\":\"URL\"," + + "\"miniprogram\":{" + + "\"appid\":\"xiaochengxuappid12345\"," + + "\"pagepath\":\"index?foo=bar\"" + + "}," + + "\"scene\":\"SCENE\"," + + "\"title\":\"TITLE\"," + + "\"data\":{" + + "\"content\":{" + + "\"value\":\"VALUE\"," + + "\"color\":\"COLOR\"" + + "}" + + "}" + + "}"; + + WxMpSubscribeMessage message = WxMpSubscribeMessage.builder() + .toUser("OPENID") + .templateId("TEMPLATE_ID") + .url("URL") + .miniProgram(new WxMpSubscribeMessage.MiniProgram("xiaochengxuappid12345", "index?foo=bar")) + .scene("SCENE") + .title("TITLE") + .contentValue("VALUE") + .contentColor("COLOR") + .build(); + + assertEquals(message.toJson(), actual); + + } +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessageTest.java index 3bb804d5..dd0f1010 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessageTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessageTest.java @@ -1,8 +1,8 @@ package me.chanjar.weixin.mp.bean.template; -import org.testng.annotations.*; +import org.testng.annotations.Test; -import static org.testng.AssertJUnit.*; +import static org.testng.AssertJUnit.assertEquals; /** *
@@ -13,7 +13,7 @@ import static org.testng.AssertJUnit.*;
  */
 public class WxMpTemplateMessageTest {
   @Test
-  public void testToJson() throws Exception {
+  public void testToJson() {
     WxMpTemplateMessage tm = WxMpTemplateMessage.builder()
       .toUser("OPENID")
       .templateId("ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY")
@@ -21,9 +21,9 @@ public class WxMpTemplateMessageTest {
       .url("http://weixin.qq.com/download")
       .build();
 
-    tm.addWxMpTemplateData(
+    tm.addData(
       new WxMpTemplateData("first", "haahah", "#FF00FF"));
-    tm.addWxMpTemplateData(
+    tm.addData(
       new WxMpTemplateData("remark", "heihei", "#FF00FF"));
 
     assertEquals(tm.toJson(), "{\"touser\":\"OPENID\",\"template_id\":\"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY\",\"url\":\"http://weixin.qq.com/download\",\"miniprogram\":{\"appid\":\"xiaochengxuappid12345\",\"pagepath\":\"index?foo=bar\"},\"data\":{\"first\":{\"value\":\"haahah\",\"color\":\"#FF00FF\"},\"remark\":{\"value\":\"heihei\",\"color\":\"#FF00FF\"}}}");
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java
index e42a192b..257e5332 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoInMemoryConfigStorage.java
@@ -6,6 +6,7 @@ import me.chanjar.weixin.common.util.xml.XStreamInitializer;
 import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
 
 import java.io.InputStream;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * @author Daniel Qian
@@ -16,13 +17,17 @@ class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage {
   public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) {
     XStream xstream = XStreamInitializer.getInstance();
     xstream.processAnnotations(WxMpDemoInMemoryConfigStorage.class);
-    return (WxMpDemoInMemoryConfigStorage) xstream.fromXML(is);
+    WxMpDemoInMemoryConfigStorage wxMpDemoInMemoryConfigStorage = (WxMpDemoInMemoryConfigStorage) xstream.fromXML(is);
+    wxMpDemoInMemoryConfigStorage.accessTokenLock = new ReentrantLock();
+    wxMpDemoInMemoryConfigStorage.cardApiTicketLock = new ReentrantLock();
+    wxMpDemoInMemoryConfigStorage.jsapiTicketLock = new ReentrantLock();
+    return wxMpDemoInMemoryConfigStorage;
   }
 
   @Override
   public String toString() {
     return "SimpleWxConfigProvider [appId=" + this.appId + ", secret=" + this.secret + ", accessToken=" + this.accessToken
-      + ", expiresTime=" + this.expiresTime + ", token=" + this.token + ", aesKey=" + this.aesKey + "]";
+      + ", expiresTime=" + this.expiresTime + ", token=" + this.token + ", aesKey=" + this.aesKey + ", templateId=" + this.templateId + "]";
   }
 
 }
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java
index 2f5f25ee..d2f4fde8 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java
@@ -5,7 +5,7 @@ import me.chanjar.weixin.mp.api.WxMpConfigStorage;
 import me.chanjar.weixin.mp.api.WxMpMessageHandler;
 import me.chanjar.weixin.mp.api.WxMpMessageRouter;
 import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.api.impl.WxMpServiceApacheHttpClientImpl;
+import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.servlet.ServletHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
@@ -47,7 +47,7 @@ public class WxMpDemoServer {
         .fromXml(is1);
 
       wxMpConfigStorage = config;
-      wxMpService = new WxMpServiceApacheHttpClientImpl();
+      wxMpService = new WxMpServiceHttpClientImpl();
       wxMpService.setWxMpConfigStorage(config);
 
       WxMpMessageHandler logHandler = new DemoLogHandler();
diff --git a/weixin-java-open/pom.xml b/weixin-java-open/pom.xml
index 5dfd4308..1ba5d6a4 100644
--- a/weixin-java-open/pom.xml
+++ b/weixin-java-open/pom.xml
@@ -8,10 +8,10 @@
   
     com.github.binarywang
     weixin-java-parent
-    2.9.0
+    2.9.9.BETA
   
   weixin-java-open
-  WeiXin Java Tools - Open
+  Weixin Java Tools - Open
   微信开放平台Java SDK
   
     
@@ -31,6 +31,11 @@
       weixin-java-mp
       ${project.version}
     
+    
+      com.github.binarywang
+      weixin-java-miniapp
+      ${project.version}
+    
 
     
       org.jodd
@@ -77,6 +82,10 @@
       logback-classic
       test
     
+    
+      org.projectlombok
+      lombok
+    
   
 
   
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java
index 9dc5a6d3..9b077590 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenComponentService.java
@@ -1,6 +1,7 @@
 package me.chanjar.weixin.open.api;
 
-import me.chanjar.weixin.common.bean.result.WxError;
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
@@ -33,10 +34,14 @@ public interface WxOpenComponentService {
   /**
    * 刷新oauth2的access token
    */
-  String OAUTH2_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/component/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s&component_appid==%s";
+  String OAUTH2_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/component/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s&component_appid=%s";
+
+  String MINIAPP_JSCODE_2_SESSION = "https://api.weixin.qq.com/sns/component/jscode2session?appid=%s&js_code=%s&grant_type=authorization_code&component_appid=%s";
 
   WxMpService getWxMpServiceByAppid(String appid);
 
+  WxMaService getWxMaServiceByAppid(String appid);
+
   WxOpenConfigStorage getWxOpenConfigStorage();
 
   boolean checkSignature(String timestamp, String nonce, String signature);
@@ -68,7 +73,7 @@ public interface WxOpenComponentService {
   /**
    * 设置授权方的选项信息
    */
-  WxError setAuthorizerOption(String authorizerAppid, String optionName, String optionValue) throws WxErrorException;
+  void setAuthorizerOption(String authorizerAppid, String optionName, String optionValue) throws WxErrorException;
 
   String getAuthorizerAccessToken(String appid, boolean forceRefresh) throws WxErrorException;
 
@@ -80,4 +85,6 @@ public interface WxOpenComponentService {
 
   String oauth2buildAuthorizationUrl(String appid, String redirectURI, String scope, String state);
 
+  WxMaJscode2SessionResult miniappJscode2Session(String appId, String jsCode) throws WxErrorException;
+
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java
index 7e548253..07366475 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenConfigStorage.java
@@ -1,5 +1,6 @@
 package me.chanjar.weixin.open.api;
 
+import cn.binarywang.wx.miniapp.config.WxMaConfig;
 import me.chanjar.weixin.mp.api.WxMpConfigStorage;
 import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
 import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;
@@ -37,6 +38,8 @@ public interface WxOpenConfigStorage {
 
   WxMpConfigStorage getWxMpConfigStorage(String appId);
 
+  WxMaConfig getWxMaConfig(String appId);
+
   /**
    * 应该是线程安全的
    *
@@ -50,14 +53,12 @@ public interface WxOpenConfigStorage {
    */
   boolean autoRefreshToken();
 
-
   String getAuthorizerRefreshToken(String appId);
 
   void setAuthorizerRefreshToken(String appId, String authorizerRefreshToken);
 
   String getAuthorizerAccessToken(String appId);
 
-
   boolean isAuthorizerAccessTokenExpired(String appId);
 
   /**
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
index 45de69b1..14670916 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenComponentServiceImpl.java
@@ -1,7 +1,8 @@
 package me.chanjar.weixin.open.api.impl;
 
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import com.google.gson.JsonObject;
-import me.chanjar.weixin.common.bean.result.WxError;
 import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.common.util.crypto.SHA1;
 import me.chanjar.weixin.common.util.http.URIUtil;
@@ -30,7 +31,10 @@ import java.util.Map;
  * @author 007
  */
 public class WxOpenComponentServiceImpl implements WxOpenComponentService {
-  private static final Map wxOpenMpServiceMap = new Hashtable<>();
+
+  private static final Map WX_OPEN_MA_SERVICE_MAP = new Hashtable<>();
+  private static final Map WX_OPEN_MP_SERVICE_MAP = new Hashtable<>();
+
   protected final Logger log = LoggerFactory.getLogger(this.getClass());
   private WxOpenService wxOpenService;
 
@@ -40,20 +44,35 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
 
   @Override
   public WxMpService getWxMpServiceByAppid(String appId) {
-    WxMpService wxMpService = wxOpenMpServiceMap.get(appId);
+    WxMpService wxMpService = WX_OPEN_MP_SERVICE_MAP.get(appId);
     if (wxMpService == null) {
-      synchronized (wxOpenMpServiceMap) {
-        wxMpService = wxOpenMpServiceMap.get(appId);
+      synchronized (WX_OPEN_MP_SERVICE_MAP) {
+        wxMpService = WX_OPEN_MP_SERVICE_MAP.get(appId);
         if (wxMpService == null) {
           wxMpService = new WxOpenMpServiceImpl(this, appId, getWxOpenConfigStorage().getWxMpConfigStorage(appId));
 
-          wxOpenMpServiceMap.put(appId, wxMpService);
+          WX_OPEN_MP_SERVICE_MAP.put(appId, wxMpService);
         }
       }
     }
     return wxMpService;
   }
 
+  @Override
+  public WxMaService getWxMaServiceByAppid(String appId) {
+    WxMaService wxMaService = WX_OPEN_MA_SERVICE_MAP.get(appId);
+    if (wxMaService == null) {
+      synchronized (WX_OPEN_MA_SERVICE_MAP) {
+        wxMaService = WX_OPEN_MA_SERVICE_MAP.get(appId);
+        if (wxMaService == null) {
+          wxMaService = new WxOpenMaServiceImpl(this, appId, getWxOpenConfigStorage().getWxMaConfig(appId));
+          WX_OPEN_MA_SERVICE_MAP.put(appId, wxMaService);
+        }
+      }
+    }
+    return wxMaService;
+  }
+
   public WxOpenService getWxOpenService() {
     return wxOpenService;
   }
@@ -137,7 +156,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
       }
       return "success";
     }
-    return null;
+    return "";
   }
 
   @Override
@@ -169,14 +188,13 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
   }
 
   @Override
-  public WxError setAuthorizerOption(String authorizerAppid, String optionName, String optionValue) throws WxErrorException {
+  public void setAuthorizerOption(String authorizerAppid, String optionName, String optionValue) throws WxErrorException {
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("component_appid", getWxOpenConfigStorage().getComponentAppId());
     jsonObject.addProperty("authorizer_appid", authorizerAppid);
     jsonObject.addProperty("option_name", optionName);
     jsonObject.addProperty("option_value", optionValue);
-    String responseContent = post(API_SET_AUTHORIZER_OPTION_URL, jsonObject.toString());
-    return WxGsonBuilder.create().fromJson(responseContent, WxError.class);
+    post(API_SET_AUTHORIZER_OPTION_URL, jsonObject.toString());
   }
 
   @Override
@@ -220,4 +238,11 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService {
       appId, URIUtil.encodeURIComponent(redirectURI), scope, StringUtils.trimToEmpty(state), getWxOpenConfigStorage().getComponentAppId());
   }
 
+  @Override
+  public WxMaJscode2SessionResult miniappJscode2Session(String appId, String jsCode) throws WxErrorException {
+    String url = String.format(MINIAPP_JSCODE_2_SESSION, appId, jsCode, getWxOpenConfigStorage().getComponentAppId());
+    String responseContent = get(url);
+    return WxMaJscode2SessionResult.fromJson(responseContent);
+  }
+
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java
index 50cf8b6e..9950482c 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInMemoryConfigStorage.java
@@ -1,6 +1,7 @@
 package me.chanjar.weixin.open.api.impl;
 
 
+import cn.binarywang.wx.miniapp.config.WxMaConfig;
 import me.chanjar.weixin.common.bean.WxAccessToken;
 import me.chanjar.weixin.common.util.ToStringUtils;
 import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
@@ -101,7 +102,12 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
 
   @Override
   public WxMpConfigStorage getWxMpConfigStorage(String appId) {
-    return new WxOpenMpConfigStorage(this, appId);
+    return new WxOpenInnerConfigStorage(this, appId);
+  }
+
+  @Override
+  public WxMaConfig getWxMaConfig(String appId) {
+    return new WxOpenInnerConfigStorage(this, appId);
   }
 
   @Override
@@ -223,13 +229,14 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
     private Long expiresTime;
   }
 
-  private static class WxOpenMpConfigStorage implements WxMpConfigStorage {
+  private static class WxOpenInnerConfigStorage implements WxMpConfigStorage, WxMaConfig {
     private WxOpenConfigStorage wxOpenConfigStorage;
     private String appId;
     private Lock accessTokenLock = new ReentrantLock();
     private Lock jsapiTicketLock = new ReentrantLock();
     private Lock cardApiTicketLock = new ReentrantLock();
-    private WxOpenMpConfigStorage(WxOpenConfigStorage wxOpenConfigStorage, String appId) {
+
+    private WxOpenInnerConfigStorage(WxOpenConfigStorage wxOpenConfigStorage, String appId) {
       this.wxOpenConfigStorage = wxOpenConfigStorage;
       this.appId = appId;
     }
@@ -259,6 +266,11 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
       wxOpenConfigStorage.updateAuthorizerAccessToken(appId, accessToken, expiresInSeconds);
     }
 
+    @Override
+    public String getAppid() {
+      return this.appId;
+    }
+
     @Override
     public void expireAccessToken() {
       wxOpenConfigStorage.expireAuthorizerAccessToken(appId);
@@ -332,6 +344,11 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
       return wxOpenConfigStorage.getComponentToken();
     }
 
+    @Override
+    public String getTemplateId() {
+      return null;
+    }
+
     @Override
     public long getExpiresTime() {
       return 0;
@@ -343,6 +360,11 @@ public class WxOpenInMemoryConfigStorage implements WxOpenConfigStorage {
       return wxOpenConfigStorage.getComponentAesKey();
     }
 
+    @Override
+    public String getMsgDataFormat() {
+      return null;
+    }
+
     @Override
     public String getOauth2redirectUri() {
       return null;
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInRedisConfigStorage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInRedisConfigStorage.java
index c3bd6a2b..86404dfb 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInRedisConfigStorage.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenInRedisConfigStorage.java
@@ -7,7 +7,6 @@ import redis.clients.jedis.JedisPool;
  * @author 007
  */
 public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
-
   private final static String COMPONENT_VERIFY_TICKET_KEY = "wechat_component_verify_ticket:";
   private final static String COMPONENT_ACCESS_TOKEN_KEY = "wechat_component_access_token:";
 
@@ -16,7 +15,6 @@ public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
   private final static String JSAPI_TICKET_KEY = "wechat_jsapi_ticket:";
   private final static String CARD_API_TICKET_KEY = "wechat_card_api_ticket:";
 
-
   protected final JedisPool jedisPool;
   private String componentVerifyTicketKey;
   private String componentAccessTokenKey;
@@ -32,46 +30,46 @@ public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
   @Override
   public void setComponentAppId(String componentAppId) {
     super.setComponentAppId(componentAppId);
-    componentVerifyTicketKey = COMPONENT_VERIFY_TICKET_KEY.concat(componentAppId);
-    componentAccessTokenKey = COMPONENT_ACCESS_TOKEN_KEY.concat(componentAppId);
-    authorizerRefreshTokenKey = AUTHORIZER_REFRESH_TOKEN_KEY.concat(componentAppId);
-    authorizerAccessTokenKey = AUTHORIZER_ACCESS_TOKEN_KEY.concat(componentAppId);
-    jsapiTicketKey = JSAPI_TICKET_KEY.concat(componentAppId);
-    cardApiTicket = CARD_API_TICKET_KEY.concat(componentAppId);
+    this.componentVerifyTicketKey = COMPONENT_VERIFY_TICKET_KEY.concat(componentAppId);
+    this.componentAccessTokenKey = COMPONENT_ACCESS_TOKEN_KEY.concat(componentAppId);
+    this.authorizerRefreshTokenKey = AUTHORIZER_REFRESH_TOKEN_KEY.concat(componentAppId);
+    this.authorizerAccessTokenKey = AUTHORIZER_ACCESS_TOKEN_KEY.concat(componentAppId);
+    this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(componentAppId);
+    this.cardApiTicket = CARD_API_TICKET_KEY.concat(componentAppId);
   }
 
   @Override
   public String getComponentVerifyTicket() {
-    try (Jedis jedis = jedisPool.getResource()) {
-      return jedis.get(componentVerifyTicketKey);
+    try (Jedis jedis = this.jedisPool.getResource()) {
+      return jedis.get(this.componentVerifyTicketKey);
     }
   }
 
   @Override
   public void setComponentVerifyTicket(String componentVerifyTicket) {
-    try (Jedis jedis = jedisPool.getResource()) {
-      jedis.set(componentVerifyTicketKey, componentVerifyTicket);
+    try (Jedis jedis = this.jedisPool.getResource()) {
+      jedis.set(this.componentVerifyTicketKey, componentVerifyTicket);
     }
   }
 
   @Override
   public String getComponentAccessToken() {
-    try (Jedis jedis = jedisPool.getResource()) {
-      return jedis.get(componentAccessTokenKey);
+    try (Jedis jedis = this.jedisPool.getResource()) {
+      return jedis.get(this.componentAccessTokenKey);
     }
   }
 
   @Override
   public boolean isComponentAccessTokenExpired() {
-    try (Jedis jedis = jedisPool.getResource()) {
-      return jedis.ttl(componentAccessTokenKey) < 2;
+    try (Jedis jedis = this.jedisPool.getResource()) {
+      return jedis.ttl(this.componentAccessTokenKey) < 2;
     }
   }
 
   @Override
   public void updateComponentAccessTokent(String componentAccessToken, int expiresInSeconds) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.setex(componentAccessTokenKey, expiresInSeconds - 200, componentAccessToken);
+      jedis.setex(this.componentAccessTokenKey, expiresInSeconds - 200, componentAccessToken);
     }
   }
 
@@ -82,99 +80,98 @@ public class WxOpenInRedisConfigStorage extends WxOpenInMemoryConfigStorage {
   @Override
   public String getAuthorizerRefreshToken(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      return jedis.get(getKey(authorizerRefreshTokenKey, appId));
+      return jedis.get(this.getKey(this.authorizerRefreshTokenKey, appId));
     }
   }
 
   @Override
   public void setAuthorizerRefreshToken(String appId, String authorizerRefreshToken) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.set(getKey(authorizerRefreshTokenKey, appId), authorizerRefreshToken);
+      jedis.set(this.getKey(this.authorizerRefreshTokenKey, appId), authorizerRefreshToken);
     }
   }
 
   @Override
   public String getAuthorizerAccessToken(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      return jedis.get(getKey(authorizerAccessTokenKey, appId));
+      return jedis.get(this.getKey(this.authorizerAccessTokenKey, appId));
     }
   }
 
-
   @Override
   public boolean isAuthorizerAccessTokenExpired(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      return jedis.ttl(getKey(authorizerAccessTokenKey, appId)) < 2;
+      return jedis.ttl(this.getKey(this.authorizerAccessTokenKey, appId)) < 2;
     }
   }
 
   @Override
   public void expireAuthorizerAccessToken(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.expire(getKey(authorizerAccessTokenKey, appId), 0);
+      jedis.expire(this.getKey(this.authorizerAccessTokenKey, appId), 0);
     }
   }
 
   @Override
   public void updateAuthorizerAccessToken(String appId, String authorizerAccessToken, int expiresInSeconds) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.setex(getKey(authorizerAccessTokenKey, appId), expiresInSeconds - 200, authorizerAccessToken);
+      jedis.setex(this.getKey(this.authorizerAccessTokenKey, appId), expiresInSeconds - 200, authorizerAccessToken);
     }
   }
 
   @Override
   public String getJsapiTicket(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      return jedis.get(getKey(jsapiTicketKey, appId));
+      return jedis.get(this.getKey(this.jsapiTicketKey, appId));
     }
   }
 
   @Override
   public boolean isJsapiTicketExpired(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      return jedis.ttl(getKey(jsapiTicketKey, appId)) < 2;
+      return jedis.ttl(this.getKey(this.jsapiTicketKey, appId)) < 2;
     }
   }
 
   @Override
   public void expireJsapiTicket(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.expire(getKey(jsapiTicketKey, appId), 0);
+      jedis.expire(this.getKey(this.jsapiTicketKey, appId), 0);
     }
   }
 
   @Override
   public void updateJsapiTicket(String appId, String jsapiTicket, int expiresInSeconds) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.setex(getKey(jsapiTicketKey, appId), expiresInSeconds - 200, jsapiTicket);
+      jedis.setex(this.getKey(this.jsapiTicketKey, appId), expiresInSeconds - 200, jsapiTicket);
     }
   }
 
   @Override
   public String getCardApiTicket(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      return jedis.get(getKey(jsapiTicketKey, appId));
+      return jedis.get(this.getKey(this.cardApiTicket, appId));
     }
   }
 
   @Override
   public boolean isCardApiTicketExpired(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      return jedis.ttl(getKey(cardApiTicket, appId)) < 2;
+      return jedis.ttl(this.getKey(this.cardApiTicket, appId)) < 2;
     }
   }
 
   @Override
   public void expireCardApiTicket(String appId) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.expire(getKey(cardApiTicket, appId), 0);
+      jedis.expire(this.getKey(this.cardApiTicket, appId), 0);
     }
   }
 
   @Override
   public void updateCardApiTicket(String appId, String cardApiTicket, int expiresInSeconds) {
     try (Jedis jedis = this.jedisPool.getResource()) {
-      jedis.setex(getKey(cardApiTicket, appId), expiresInSeconds - 200, cardApiTicket);
+      jedis.setex(this.getKey(this.cardApiTicket, appId), expiresInSeconds - 200, cardApiTicket);
     }
   }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java
new file mode 100644
index 00000000..c0645d76
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java
@@ -0,0 +1,42 @@
+package me.chanjar.weixin.open.api.impl;
+
+import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
+import cn.binarywang.wx.miniapp.config.WxMaConfig;
+import com.google.common.base.Joiner;
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.open.api.WxOpenComponentService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author 007
+ */
+/* package */ class WxOpenMaServiceImpl extends WxMaServiceImpl {
+  private WxOpenComponentService wxOpenComponentService;
+  private WxMaConfig wxMaConfig;
+  private String appId;
+
+  public WxOpenMaServiceImpl(WxOpenComponentService wxOpenComponentService, String appId, WxMaConfig wxMaConfig) {
+    this.wxOpenComponentService = wxOpenComponentService;
+    this.appId = appId;
+    this.wxMaConfig = wxMaConfig;
+    initHttp();
+  }
+
+  @Override
+  public WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException {
+    return wxOpenComponentService.miniappJscode2Session(appId, jsCode);
+  }
+  @Override
+  public WxMaConfig getWxMaConfig() {
+    return wxMaConfig;
+  }
+
+  @Override
+  public String getAccessToken(boolean forceRefresh) throws WxErrorException {
+    return wxOpenComponentService.getAuthorizerAccessToken(appId, forceRefresh);
+  }
+
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMessageRouter.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMessageRouter.java
new file mode 100644
index 00000000..2e483fc0
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMessageRouter.java
@@ -0,0 +1,26 @@
+package me.chanjar.weixin.open.api.impl;
+
+import me.chanjar.weixin.mp.api.WxMpMessageRouter;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import me.chanjar.weixin.open.api.WxOpenService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class WxOpenMessageRouter extends WxMpMessageRouter {
+  private WxOpenService wxOpenService;
+
+  public WxOpenMessageRouter(WxOpenService wxOpenService) {
+    super(null);
+    this.wxOpenService = wxOpenService;
+  }
+
+  public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage, String appId) {
+    return route(wxMessage, new HashMap(), appId);
+  }
+
+  public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage, final Map context, String appId) {
+    return route(wxMessage, context, wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId));
+  }
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpServiceImpl.java
index 9c537bc9..6c61b1fc 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpServiceImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMpServiceImpl.java
@@ -36,11 +36,6 @@ import me.chanjar.weixin.open.api.WxOpenComponentService;
     return wxOpenComponentService.oauth2getAccessToken(appId, code);
   }
 
-//  @Override
-//  public boolean checkSignature(String timestamp, String nonce, String signature) {
-//    return wxOpenComponentService.checkSignature(appId, timestamp, nonce, signature);
-//  }
-
   @Override
   public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException {
     return wxOpenComponentService.oauth2refreshAccessToken(appId, refreshToken);
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java
index 3276c429..5ace633f 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenServiceAbstractImpl.java
@@ -30,6 +30,7 @@ public abstract class WxOpenServiceAbstractImpl implements WxOpenService,
     return wxOpenConfigStorage;
   }
 
+  @Override
   public void setWxOpenConfigStorage(WxOpenConfigStorage wxOpenConfigStorage) {
     this.wxOpenConfigStorage = wxOpenConfigStorage;
   }
@@ -41,18 +42,6 @@ public abstract class WxOpenServiceAbstractImpl implements WxOpenService,
       return result;
     } catch (WxErrorException e) {
       WxError error = e.getError();
-//      /*
-//       * 发生以下情况时尝试刷新access_token
-//       * 40001 获取access_token时AppSecret错误,或者access_token无效
-//       * 42001 access_token超时
-//       * 40014 不合法的access_token,请开发者认真比对access_token的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口
-//       */
-//      if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001 || error.getErrorCode() == 40014) {
-//        // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
-//        this.configStorage.expireAccessToken();
-//        return execute(executor, uri, data);
-//      }
-
       if (error.getErrorCode() != 0) {
         this.log.error("\n【请求地址】: {}\n【请求参数】:{}\n【错误信息】:{}", uri, data, error);
         throw new WxErrorException(error, e);
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java
index 86472403..a80dab03 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenAuthorizerInfo.java
@@ -1,8 +1,10 @@
 package me.chanjar.weixin.open.bean.auth;
 
+import com.google.gson.annotations.SerializedName;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -21,4 +23,44 @@ public class WxOpenAuthorizerInfo implements Serializable {
   private Map businessInfo;
   private String alias;
   private String qrcodeUrl;
+  /**
+   * 账号介绍
+   */
+  private String signature;
+
+  /**
+   * 可根据这个字段判断是否为小程序类型授权
+   */
+  private MiniProgramInfo miniProgramInfo;
+
+  @Data
+  public class MiniProgramInfo {
+    @SerializedName("visit_status")
+    private Integer visitStatus;
+    /**
+     * 小程序已设置的各个服务器域名.
+     */
+    private Network network;
+    private List categories;
+
+    @Data
+    public class Category {
+      private String first;
+      private String second;
+    }
+
+    @Data
+    public class Network {
+      @SerializedName("RequestDomain")
+      private List requestDomain;
+      @SerializedName("WsRequestDomain")
+      private List wsRequestDomain;
+      @SerializedName("UploadDomain")
+      private List uploadDomain;
+      @SerializedName("DownloadDomain")
+      private List downloadDomain;
+      @SerializedName("BizDomain")
+      private List bizDomain;
+    }
+  }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenMiniProgramInfo.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenMiniProgramInfo.java
new file mode 100644
index 00000000..44f56e6f
--- /dev/null
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/WxOpenMiniProgramInfo.java
@@ -0,0 +1,14 @@
+package me.chanjar.weixin.open.bean.auth;
+
+import lombok.Data;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class WxOpenMiniProgramInfo {
+  private Map> network;
+  private List> categories;
+  private Integer visitStatus;
+}
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java
index 8cb245ba..ac42696a 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java
@@ -53,7 +53,7 @@ public class WxOpenXmlMessage implements Serializable {
   @XStreamConverter(value = XStreamCDataConverter.class)
   private String preAuthCode;
 
-  public static String wxMpOutXmlMessageToEncryptedXml(WxMpXmlOutMessage message, WxOpenConfigStorage wxOpenConfigStorage){
+  public static String wxMpOutXmlMessageToEncryptedXml(WxMpXmlOutMessage message, WxOpenConfigStorage wxOpenConfigStorage) {
     String plainXml = message.toXml();
     WxOpenCryptUtil pc = new WxOpenCryptUtil(wxOpenConfigStorage);
     return pc.encrypt(plainXml);
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResult.java
index 7bccff5c..60dd065b 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResult.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenAuthorizerInfoResult.java
@@ -15,4 +15,8 @@ public class WxOpenAuthorizerInfoResult implements Serializable {
 
   private WxOpenAuthorizationInfo authorizationInfo;
   private WxOpenAuthorizerInfo authorizerInfo;
+
+  public boolean isMiniProgram() {
+    return authorizerInfo != null && authorizerInfo.getMiniProgramInfo() != null;
+  }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java
index cc03a82e..2fb4e795 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/json/WxOpenAuthorizerInfoGsonAdapter.java
@@ -23,6 +23,8 @@ public class WxOpenAuthorizerInfoGsonAdapter implements JsonDeserializer>() {
       }.getType());
     authorizationInfo.setBusinessInfo(businessInfo);
+    if (jsonObject.has("MiniProgramInfo")) {
+      WxOpenAuthorizerInfo.MiniProgramInfo miniProgramInfo = WxOpenGsonBuilder.create().fromJson(jsonObject.get("MiniProgramInfo"),
+        new TypeToken() {
+        }.getType());
+      authorizationInfo.setMiniProgramInfo(miniProgramInfo);
+    }
     return authorizationInfo;
   }
 }
diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/xml/XStreamTransformer.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/xml/XStreamTransformer.java
index 515c90de..95c70f10 100644
--- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/xml/XStreamTransformer.java
+++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/util/xml/XStreamTransformer.java
@@ -1,12 +1,16 @@
 package me.chanjar.weixin.open.util.xml;
 
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import com.thoughtworks.xstream.XStream;
 import me.chanjar.weixin.common.util.xml.XStreamInitializer;
 import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
 
-import java.io.InputStream;
-import java.util.*;
-
 /**
  * @author 007
  */
@@ -18,7 +22,7 @@ public class XStreamTransformer {
   }
 
   /**
-   * xml -> pojo
+   * xml -> pojo.
    */
   @SuppressWarnings("unchecked")
   public static  T fromXml(Class clazz, String xml) {
@@ -33,24 +37,24 @@ public class XStreamTransformer {
   }
 
   /**
-   * pojo -> xml
+   * pojo -> xml.
    */
   public static  String toXml(Class clazz, T object) {
     return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);
   }
 
   /**
-   * 注册扩展消息的解析器
+   * 注册扩展消息的解析器.
    *
    * @param clz     类型
    * @param xStream xml解析器
    */
-  private static void register(Class clz, XStream xStream) {
+  public static void register(Class clz, XStream xStream) {
     CLASS_2_XSTREAM_INSTANCE.put(clz, xStream);
   }
 
   /**
-   * 会自动注册该类及其子类
+   * 会自动注册该类及其子类.
    *
    * @param clz 要注册的类
    */
diff --git a/weixin-java-osgi/pom.xml b/weixin-java-osgi/pom.xml
index 91c84d24..693d5309 100644
--- a/weixin-java-osgi/pom.xml
+++ b/weixin-java-osgi/pom.xml
@@ -11,7 +11,7 @@
 
   weixin-java-osgi
   bundle
-  WeiXin Java Tools - OSGI
+  Weixin Java Tools - OSGI
   微信公众号Java SDK OSGI
 
   
diff --git a/weixin-java-pay/pom.xml b/weixin-java-pay/pom.xml
index f245bff2..b0946c96 100644
--- a/weixin-java-pay/pom.xml
+++ b/weixin-java-pay/pom.xml
@@ -5,12 +5,12 @@
   
     weixin-java-parent
     com.github.binarywang
-    2.9.0
+    2.9.9.BETA
   
   4.0.0
 
   weixin-java-pay
-  WeiXin Java Tools - PAY
+  Weixin Java Tools - PAY
   微信支付 Java SDK
 
   
@@ -27,7 +27,6 @@
     
       org.jodd
       jodd-http
-      provided
     
 
     
@@ -35,6 +34,17 @@
       commons-lang3
     
 
+    
+      commons-beanutils
+      commons-beanutils
+      1.9.3
+    
+    
+      org.bouncycastle
+      bcpkix-jdk15on
+      1.59
+    
+
     
       ch.qos.logback
       logback-classic
@@ -45,11 +55,20 @@
       testng
       test
     
+    
+      org.assertj
+      assertj-guava
+      test
+    
     
       com.google.inject
       guice
       test
     
+    
+      org.projectlombok
+      lombok
+    
   
 
 
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryRequest.java
index 54d16bd9..61726e04 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryRequest.java
@@ -1,6 +1,6 @@
 package com.github.binarywang.wxpay.bean.coupon;
 
-import com.github.binarywang.wxpay.bean.request.WxPayBaseRequest;
+import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import lombok.*;
 import me.chanjar.weixin.common.annotation.Required;
@@ -19,7 +19,7 @@ import me.chanjar.weixin.common.annotation.Required;
 @NoArgsConstructor
 @AllArgsConstructor
 @XStreamAlias("xml")
-public class WxPayCouponInfoQueryRequest extends WxPayBaseRequest {
+public class WxPayCouponInfoQueryRequest extends BaseWxPayRequest {
   /**
    * 
    * 字段名:代金券id
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryResult.java
index f7d91383..90bafc78 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponInfoQueryResult.java
@@ -1,6 +1,6 @@
 package com.github.binarywang.wxpay.bean.coupon;
 
-import com.github.binarywang.wxpay.bean.result.WxPayBaseResult;
+import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -18,7 +18,7 @@ import lombok.NoArgsConstructor;
 @EqualsAndHashCode(callSuper = true)
 @NoArgsConstructor
 @XStreamAlias("xml")
-public class WxPayCouponInfoQueryResult extends WxPayBaseResult {
+public class WxPayCouponInfoQueryResult extends BaseWxPayResult {
   /**
    * 
    * 字段名:设备号.
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendRequest.java
index 63b891d8..d6d9f73d 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendRequest.java
@@ -1,6 +1,6 @@
 package com.github.binarywang.wxpay.bean.coupon;
 
-import com.github.binarywang.wxpay.bean.request.WxPayBaseRequest;
+import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import lombok.*;
 import me.chanjar.weixin.common.annotation.Required;
@@ -20,7 +20,7 @@ import me.chanjar.weixin.common.annotation.Required;
 @NoArgsConstructor
 @AllArgsConstructor
 @XStreamAlias("xml")
-public class WxPayCouponSendRequest extends WxPayBaseRequest {
+public class WxPayCouponSendRequest extends BaseWxPayRequest {
   /**
    * 
    * 字段名:代金券批次id
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendResult.java
index fe26342e..314845e4 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponSendResult.java
@@ -1,6 +1,6 @@
 package com.github.binarywang.wxpay.bean.coupon;
 
-import com.github.binarywang.wxpay.bean.result.WxPayBaseResult;
+import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -18,7 +18,7 @@ import lombok.NoArgsConstructor;
 @EqualsAndHashCode(callSuper = true)
 @NoArgsConstructor
 @XStreamAlias("xml")
-public class WxPayCouponSendResult extends WxPayBaseResult {
+public class WxPayCouponSendResult extends BaseWxPayResult {
   /**
    * 
    * 字段名:设备号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryRequest.java
index c7b812d8..c7f7cadf 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryRequest.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryRequest.java
@@ -1,6 +1,6 @@
 package com.github.binarywang.wxpay.bean.coupon;
 
-import com.github.binarywang.wxpay.bean.request.WxPayBaseRequest;
+import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import lombok.*;
 import me.chanjar.weixin.common.annotation.Required;
@@ -20,7 +20,7 @@ import me.chanjar.weixin.common.annotation.Required;
 @NoArgsConstructor
 @AllArgsConstructor
 @XStreamAlias("xml")
-public class WxPayCouponStockQueryRequest extends WxPayBaseRequest {
+public class WxPayCouponStockQueryRequest extends BaseWxPayRequest {
   /**
    * 
    * 字段名:代金券批次id
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryResult.java
index 2f97618e..c4bbc705 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryResult.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/coupon/WxPayCouponStockQueryResult.java
@@ -1,6 +1,6 @@
 package com.github.binarywang.wxpay.bean.coupon;
 
-import com.github.binarywang.wxpay.bean.result.WxPayBaseResult;
+import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -20,7 +20,7 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 @AllArgsConstructor
 @XStreamAlias("xml")
-public class WxPayCouponStockQueryResult extends WxPayBaseResult {
+public class WxPayCouponStockQueryResult extends BaseWxPayResult {
   /**
    * 
    * 字段名:设备号
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankQueryRequest.java
new file mode 100644
index 00000000..804d305b
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankQueryRequest.java
@@ -0,0 +1,28 @@
+package com.github.binarywang.wxpay.bean.entpay;
+
+import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import lombok.*;
+import me.chanjar.weixin.common.annotation.Required;
+import me.chanjar.weixin.common.util.ToStringUtils;
+
+/**
+ * 
+ * 企业付款到银行卡的请求对象
+ * Created by Binary Wang on 2017/12/21.
+ * 
+ * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@XStreamAlias("xml") +public class EntPayBankQueryRequest extends EntPayQueryRequest { + private static final long serialVersionUID = -479088843124447119L; + + @Override + protected boolean ignoreAppid() { + return true; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankQueryResult.java new file mode 100644 index 00000000..6020dbed --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankQueryResult.java @@ -0,0 +1,96 @@ +package com.github.binarywang.wxpay.bean.entpay; + +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + *
+ * 企业付款到银行卡查询返回结果.
+ * Created by Binary Wang on 2017/12/21.
+ * 
+ * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@XStreamAlias("xml") +public class EntPayBankQueryResult extends BaseWxPayResult { + private static final long serialVersionUID = -8336631015989500746L; + + /** + * 商户企业付款单号 + */ + @XStreamAlias("partner_trade_no") + private String partnerTradeNo; + + /** + * 微信企业付款单号. + * 即为微信内部业务单号 + */ + @XStreamAlias("payment_no") + private String paymentNo; + + /** + * 银行卡号. + * 收款用户银行卡号(MD5加密) + */ + @XStreamAlias("bank_no_md5") + private String bankNoMd5; + + /** + * 用户真实姓名. + * 收款人真实姓名(MD5加密) + */ + @XStreamAlias("true_name_md5") + private String trueNameMd5; + + /** + * 付款金额. + */ + @XStreamAlias("amount") + private Integer amount; + + /** + * 代付单状态. + *
+   * PROCESSING(处理中,如有明确失败,则返回额外失败原因;否则没有错误原因)
+   * SUCCESS(付款成功)
+   * FAILED(付款失败)
+   * BANK_FAIL(银行退票,订单状态由付款成功流转至退票,退票时付款金额和手续费会自动退还)
+   * 
+ */ + @XStreamAlias("status") + private String status; + + /** + * 手续费金额 + */ + @XStreamAlias("cmms_amt") + private Integer cmmsAmount; + + /** + * 商户下单时间. + * 微信侧订单创建时间 + */ + @XStreamAlias("create_time") + private String createTime; + + /** + * 成功付款时间. + * 微信侧付款成功时间(但无法保证银行不会退票) + */ + @XStreamAlias("pay_succ_time") + private String paySuccessTime; + + /** + * 失败原因. + * 订单失败原因(如:余额不足) + */ + @XStreamAlias("reason") + private String failReason; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankRequest.java new file mode 100644 index 00000000..cae3ef92 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankRequest.java @@ -0,0 +1,115 @@ +package com.github.binarywang.wxpay.bean.entpay; + +import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.common.annotation.Required; + +/** + *
+ *  企业付款到银行卡的请求对象类
+ *  Created by BinaryWang on 2017/12/20.
+ * 
+ * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@XStreamAlias("xml") +public class EntPayBankRequest extends BaseWxPayRequest { + + /** + *
+   * 商户企业付款单号.
+   * 变量名:partner_trade_no
+   * 是否必填:是
+   * 示例值:1212121221227
+   * 类型:string(32)
+   * 描述:商户订单号,需保持唯一(只允许数字[0~9]或字母[A~Z]和[a~z],最短8位,最长32位)
+   */
+  @Required
+  @XStreamAlias("partner_trade_no")
+  private String partnerTradeNo;
+
+  /**
+   * 
+   * 收款方银行卡号.
+   * 传值时请传原始值
+   * 变量名:enc_bank_no
+   * 是否必填:是
+   * 示例值:8609cb22e1774a50a930e414cc71eca06121bcd266335cda230d24a7886a8d9f
+   * 类型:string(64)
+   * 描述:收款方银行卡号(采用标准RSA算法,公钥由微信侧提供),详见获取RSA加密公钥API
+   *
+   */
+  @Required
+  @XStreamAlias("enc_bank_no")
+  private String encBankNo;
+
+  /**
+   * 
+   * 收款方用户名.
+   * 传值时请传原始值
+   * 变量名:enc_true_name
+   * 是否必填:是
+   * 示例值:ca775af5f841bdf424b2e6eb86a6e21e
+   * 类型:string(64)
+   * 描述:收款方用户名(采用标准RSA算法,公钥由微信侧提供)详见获取RSA加密公钥API
+   */
+  @Required
+  @XStreamAlias("enc_true_name")
+  private String encTrueName;
+
+  /**
+   * 
+   * 收款方开户行.
+   * 变量名:bank_code
+   * 是否必填:是
+   * 示例值:1001
+   * 类型:string(64)
+   * 描述:银行卡所在开户行编号,详见银行编号列表
+   */
+  @Required
+  @XStreamAlias("bank_code")
+  private String bankCode;
+
+  /**
+   * 
+   * 付款金额.
+   * 变量名:amount
+   * 是否必填:是
+   * 示例值:100000
+   * 类型:int
+   * 描述:付款金额:RMB分(支付总额,不含手续费) 注:大于0的整数
+   */
+  @Required
+  @XStreamAlias("amount")
+  private Integer amount;
+
+  /**
+   * 
+   * 付款说明.
+   * 变量名:desc
+   * 是否必填:否
+   * 示例值:理财
+   * 类型:string
+   * 描述:企业付款到银行卡付款说明,即订单备注(UTF8编码,允许100个字符以内)
+   */
+  @Required
+  @XStreamAlias("desc")
+  private String description;
+
+  @Override
+  protected void checkConstraints() throws WxPayException {
+
+  }
+
+  @Override
+  protected boolean ignoreAppid() {
+    return true;
+  }
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankResult.java
new file mode 100644
index 00000000..ef75b814
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayBankResult.java
@@ -0,0 +1,51 @@
+package com.github.binarywang.wxpay.bean.entpay;
+
+import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * 
+ * 企业付款到银行卡的响应结果.
+ * Created by Binary Wang on 2017/12/21.
+ * 
+ * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@XStreamAlias("xml") +public class EntPayBankResult extends BaseWxPayResult { + private static final long serialVersionUID = 3449707749935227689L; + + /** + * 代付金额. + */ + @XStreamAlias("amount") + private Integer amount; + + /** + * 商户企业付款单号. + */ + @XStreamAlias("partner_trade_no") + private String partnerTradeNo; + + //############以下字段在return_code 和result_code都为SUCCESS的时候有返回############## + /** + * 微信企业付款单号. + * 代付成功后,返回的内部业务单号 + */ + @XStreamAlias("payment_no") + private String paymentNo; + + /** + * 手续费金额. + * RMB:分 + */ + @XStreamAlias("cmms_amt") + private String cmmsAmount; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayQueryRequest.java similarity index 62% rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayQueryRequest.java rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayQueryRequest.java index 5d48bb44..9dc74e75 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayQueryRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayQueryRequest.java @@ -1,5 +1,6 @@ -package com.github.binarywang.wxpay.bean.request; +package com.github.binarywang.wxpay.bean.entpay; +import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest; import com.thoughtworks.xstream.annotations.XStreamAlias; import lombok.*; import me.chanjar.weixin.common.annotation.Required; @@ -7,16 +8,9 @@ import me.chanjar.weixin.common.util.ToStringUtils; /** *
- * 企业付款请求对象
- * 注释中各行每个字段描述对应如下:
- * 
  • 字段名 - *
  • 变量名 - *
  • 是否必填 - *
  • 类型 - *
  • 示例值 - *
  • 描述 - *
  • + * 企业付款请求对象. * Created by Binary Wang on 2016/10/19. + *
    * * @author Binary Wang */ @@ -26,15 +20,17 @@ import me.chanjar.weixin.common.util.ToStringUtils; @NoArgsConstructor @AllArgsConstructor @XStreamAlias("xml") -public class WxEntPayQueryRequest extends WxPayBaseRequest { +public class EntPayQueryRequest extends BaseWxPayRequest { + private static final long serialVersionUID = 1972288742207813985L; + /** *
    -   * 商户订单号
    -   * partner_trade_no
    -   * 是
    -   * 10000098201411111234567890
    -   * String
    -   * 商户订单号
    +   * 字段名:商户订单号.
    +   * 变量名:partner_trade_no
    +   * 是否必填:是
    +   * 示例值:10000098201411111234567890
    +   * 类型:String
    +   * 描述商户订单号
        * 
    */ @Required diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayQueryResult.java new file mode 100644 index 00000000..e3cdba3b --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayQueryResult.java @@ -0,0 +1,78 @@ +package com.github.binarywang.wxpay.bean.entpay; + +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + *
    + * 企业付款查询返回结果.
    + * Created by Binary Wang on 2016/10/19.
    + * 
    + * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@XStreamAlias("xml") +public class EntPayQueryResult extends BaseWxPayResult { + private static final long serialVersionUID = 3948485732447456947L; + + /** + * 商户订单号 + */ + @XStreamAlias("partner_trade_no") + private String partnerTradeNo; + + /** + * 付款单号 + */ + @XStreamAlias("detail_id") + private String detailId; + + /** + * 转账状态 + */ + @XStreamAlias("status") + private String status; + + /** + * 失败原因 + */ + @XStreamAlias("reason") + private String reason; + + /** + * 收款用户openid + */ + @XStreamAlias("openid") + private String openid; + + /** + * 收款用户姓名 + */ + @XStreamAlias("transfer_name") + private String transferName; + + /** + * 付款金额 + */ + @XStreamAlias("payment_amount") + private Integer paymentAmount; + + /** + * 转账时间 + */ + @XStreamAlias("transfer_time") + private String transferTime; + + /** + * 付款描述 + */ + @XStreamAlias("desc") + private String desc; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayRequest.java similarity index 85% rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayRequest.java rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayRequest.java index ac588aa5..1ff25e78 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayRequest.java @@ -1,5 +1,6 @@ -package com.github.binarywang.wxpay.bean.request; +package com.github.binarywang.wxpay.bean.entpay; +import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest; import com.thoughtworks.xstream.annotations.XStreamAlias; import lombok.*; import me.chanjar.weixin.common.annotation.Required; @@ -7,9 +8,9 @@ import me.chanjar.weixin.common.util.ToStringUtils; /** *
    - * 企业付款请求对象
    - * 
    + * 企业付款请求对象. * Created by Binary Wang on 2016/10/02. + *
    * * @author Binary Wang */ @@ -20,10 +21,10 @@ import me.chanjar.weixin.common.util.ToStringUtils; @NoArgsConstructor @AllArgsConstructor @XStreamAlias("xml") -public class WxEntPayRequest extends WxPayBaseRequest { +public class EntPayRequest extends BaseWxPayRequest { /** *
    -   * 字段名:公众账号appid
    +   * 字段名:公众账号appid.
        * 变量名:mch_appid
        * 是否必填:是
        * 示例值:wx8888888888888888
    @@ -36,7 +37,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:商户号
    +   * 字段名:商户号.
        * 变量名:mchid
        * 是否必填:是
        * 示例值:1900000109
    @@ -49,7 +50,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:设备号
    +   * 字段名:设备号.
        * 变量名:device_info
        * 是否必填:否
        * 示例值:13467007045764
    @@ -62,7 +63,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:商户订单号
    +   * 字段名:商户订单号.
        * 变量名:partner_trade_no
        * 是否必填:是
        * 示例值:10000098201411111234567890
    @@ -76,7 +77,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:需保持唯一性 用户openid
    +   * 字段名:需保持唯一性 用户openid.
        * 变量名:openid
        * 是否必填:是
        * 示例值:oxTWIuGaIt6gTKsQRLau2M0yL16E
    @@ -90,7 +91,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:校验用户姓名选项
    +   * 字段名:校验用户姓名选项.
        * 变量名:check_name
        * 是否必填:是
        * 示例值:OPTION_CHECK
    @@ -106,7 +107,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:收款用户姓名
    +   * 字段名:收款用户姓名.
        * 变量名:re_user_name
        * 是否必填:可选
        * 示例值:马花花
    @@ -120,7 +121,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:金额
    +   * 字段名:金额.
        * 变量名:amount
        * 是否必填:是
        * 示例值:10099
    @@ -134,7 +135,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:企业付款描述信息
    +   * 字段名:企业付款描述信息.
        * 变量名:desc
        * 是否必填:是
        * 示例值:理赔
    @@ -148,7 +149,7 @@ public class WxEntPayRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:Ip地址
    +   * 字段名:Ip地址.
        * 变量名:spbill_create_ip
        * 是否必填:是
        * 示例值:192.168.0.1
    @@ -190,4 +191,8 @@ public class WxEntPayRequest extends WxPayBaseRequest {
         return ToStringUtils.toSimpleString(this);
       }
     
    +  @Override
    +  protected boolean ignoreSignType() {
    +    return true;
    +  }
     }
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayResult.java
    new file mode 100644
    index 00000000..17b30312
    --- /dev/null
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/EntPayResult.java
    @@ -0,0 +1,54 @@
    +package com.github.binarywang.wxpay.bean.entpay;
    +
    +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
    +import com.thoughtworks.xstream.annotations.XStreamAlias;
    +import lombok.Data;
    +import lombok.EqualsAndHashCode;
    +import lombok.NoArgsConstructor;
    +
    +/**
    + * 
    + * 企业付款返回结果
    + * Created by Binary Wang on 2016/10/02.
    + * 
    + * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@XStreamAlias("xml") +public class EntPayResult extends BaseWxPayResult { + + /** + * 商户appid + */ + @XStreamAlias("mch_appid") + private String mchAppid; + + /** + * 设备号 + */ + @XStreamAlias("device_info") + private String deviceInfo; + + //############以下字段在return_code 和result_code都为SUCCESS的时候有返回############## + /** + * 商户订单号 + */ + @XStreamAlias("partner_trade_no") + private String partnerTradeNo; + + /** + * 微信订单号 + */ + @XStreamAlias("payment_no") + private String paymentNo; + + /** + * 微信支付成功时间 + */ + @XStreamAlias("payment_time") + private String paymentTime; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/GetPublicKeyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/GetPublicKeyResult.java new file mode 100644 index 00000000..f7f62afb --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/entpay/GetPublicKeyResult.java @@ -0,0 +1,31 @@ +package com.github.binarywang.wxpay.bean.entpay; + +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *
    + *  企业付款获取RSA加密公钥接口返回结果类
    + *  Created by BinaryWang on 2017/12/20.
    + * 
    + * + * @author Binary Wang + */ +@Data +@EqualsAndHashCode(callSuper = true) +@XStreamAlias("xml") +public class GetPublicKeyResult extends BaseWxPayResult { + /** + * 商户号. + */ + @XStreamAlias("mch_id") + private String mchId; + + /** + * 密钥 + */ + @XStreamAlias("pub_key") + private String pubKey; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResult.java index 8cb94ee0..857859ed 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResult.java @@ -1,17 +1,16 @@ package com.github.binarywang.wxpay.bean.notify; -import com.github.binarywang.wxpay.bean.result.WxPayBaseResult; +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; import com.github.binarywang.wxpay.converter.WxPayOrderNotifyResultConverter; +import com.github.binarywang.wxpay.util.SignUtils; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import me.chanjar.weixin.common.util.BeanUtils; import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import java.io.Serializable; import java.util.List; import java.util.Map; @@ -25,12 +24,25 @@ import java.util.Map; @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @XStreamAlias("xml") -public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable { +public class WxPayOrderNotifyResult extends BaseWxPayResult { private static final long serialVersionUID = 5389718115223345496L; /** *
    -   * 字段名:设备号
    +   * 字段名:营销详情.
    +   * 变量名:promotion_detail
    +   * 是否必填:否,单品优惠才有
    +   * 类型:String(6000)
    +   * 示例值:[{"promotion_detail":[{"promotion_id":"109519","name":"单品惠-6","scope":"SINGLE","type":"DISCOUNT","amount":5,"activity_id":"931386","wxpay_contribute":0,"merchant_contribute":0,"other_contribute":5,"goods_detail":[{"goods_id":"a_goods1","goods_remark":"商品备注","quantity":7,"price":1,"discount_amount":4},{"goods_id":"a_goods2","goods_remark":"商品备注","quantity":1,"price":2,"discount_amount":1}]}]}
    +   * 描述:单品优惠专用参数,详见https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_203&index=4
    +   * 
    + */ + @XStreamAlias("promotion_detail") + private String promotionDetail; + + /** + *
    +   * 字段名:设备号.
        * 变量名:device_info
        * 是否必填:否
        * 类型:String(32)
    @@ -43,7 +55,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:用户标识
    +   * 字段名:用户标识.
        * 变量名:openid
        * 是否必填:是
        * 类型:String(128)
    @@ -56,7 +68,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:是否关注公众账号
    +   * 字段名:是否关注公众账号.
        * 变量名:is_subscribe
        * 是否必填:否
        * 类型:String(1)
    @@ -69,7 +81,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:用户子标识
    +   * 字段名:用户子标识.
        * 变量名:sub_openid
        * 是否必填:是
        * 类型:String(128)
    @@ -82,7 +94,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:是否关注子公众账号
    +   * 字段名:是否关注子公众账号.
        * 变量名:sub_is_subscribe
        * 是否必填:否
        * 类型:String(1)
    @@ -96,7 +108,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:交易类型
    +   * 字段名:交易类型.
        * 变量名:trade_type
        * 是否必填:是
        * 类型:String(16)
    @@ -107,10 +119,9 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
       @XStreamAlias("trade_type")
       private String tradeType;
     
    -
       /**
        * 
    -   * 字段名:付款银行
    +   * 字段名:付款银行.
        * 变量名:bank_type
        * 是否必填:是
        * 类型:String(16)
    @@ -123,7 +134,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:订单金额
    +   * 字段名:订单金额.
        * 变量名:total_fee
        * 是否必填:是
        * 类型:Int
    @@ -135,7 +146,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
       private Integer totalFee;
       /**
        * 
    -   * 字段名:应结订单金额
    +   * 字段名:应结订单金额.
        * 变量名:settlement_total_fee
        * 是否必填:否
        * 类型:Int
    @@ -147,7 +158,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
       private Integer settlementTotalFee;
       /**
        * 
    -   * 字段名:货币种类
    +   * 字段名:货币种类.
        * 变量名:fee_type
        * 是否必填:否
        * 类型:String(8)
    @@ -159,7 +170,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
       private String feeType;
       /**
        * 
    -   * 字段名:现金支付金额
    +   * 字段名:现金支付金额.
        * 变量名:cash_fee
        * 是否必填:是
        * 类型:Int
    @@ -171,7 +182,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
       private Integer cashFee;
       /**
        * 
    -   * 字段名:现金支付货币类型
    +   * 字段名:现金支付货币类型.
        * 变量名:cash_fee_type
        * 是否必填:否
        * 类型:String(16)
    @@ -183,7 +194,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
       private String cashFeeType;
       /**
        * 
    -   * 字段名:总代金券金额
    +   * 字段名:总代金券金额.
        * 变量名:coupon_fee
        * 是否必填:否
        * 类型:Int
    @@ -196,7 +207,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:代金券使用数量
    +   * 字段名:代金券使用数量.
        * 变量名:coupon_count
        * 是否必填:否
        * 类型:Int
    @@ -211,7 +222,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:微信支付订单号
    +   * 字段名:微信支付订单号.
        * 变量名:transaction_id
        * 是否必填:是
        * 类型:String(32)
    @@ -224,7 +235,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       /**
        * 
    -   * 字段名:商户订单号
    +   * 字段名:商户订单号.
        * 变量名:out_trade_no
        * 是否必填:是
        * 类型:String(32)
    @@ -236,7 +247,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
       private String outTradeNo;
       /**
        * 
    -   * 字段名:商家数据包
    +   * 字段名:商家数据包.
        * 变量名:attach
        * 是否必填:否
        * 类型:String(128)
    @@ -246,9 +257,10 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
        */
       @XStreamAlias("attach")
       private String attach;
    +
       /**
        * 
    -   * 字段名:支付完成时间
    +   * 字段名:支付完成时间.
        * 变量名:time_end
        * 是否必填:是
        * 类型:String(14)
    @@ -270,7 +282,7 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializa
     
       @Override
       public Map toMap() {
    -    Map resultMap = BeanUtils.xmlBean2Map(this);
    +    Map resultMap = SignUtils.xmlBean2Map(this);
         if (this.getCouponCount() != null && this.getCouponCount() > 0) {
           for (int i = 0; i < this.getCouponCount(); i++) {
             WxPayOrderNotifyCoupon coupon = couponList.get(i);
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResult.java
    index 7006c752..94e8492b 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResult.java
    @@ -1,6 +1,6 @@
     package com.github.binarywang.wxpay.bean.notify;
     
    -import com.github.binarywang.wxpay.bean.result.WxPayBaseResult;
    +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
     import com.github.binarywang.wxpay.exception.WxPayException;
     import com.thoughtworks.xstream.XStream;
     import com.thoughtworks.xstream.annotations.XStreamAlias;
    @@ -31,7 +31,7 @@ import java.security.MessageDigest;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayRefundNotifyResult extends WxPayBaseResult implements Serializable {
    +public class WxPayRefundNotifyResult extends BaseWxPayResult implements Serializable {
       private static final long serialVersionUID = 4651725860079259186L;
     
       /**
    @@ -41,7 +41,7 @@ public class WxPayRefundNotifyResult extends WxPayBaseResult implements Serializ
        * @param mchKey    商户密钥
        */
       public static WxPayRefundNotifyResult fromXML(String xmlString, String mchKey) throws WxPayException {
    -    WxPayRefundNotifyResult result = WxPayBaseResult.fromXML(xmlString, WxPayRefundNotifyResult.class);
    +    WxPayRefundNotifyResult result = BaseWxPayResult.fromXML(xmlString, WxPayRefundNotifyResult.class);
         String reqInfoString = result.getReqInfoString();
         try {
           Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxScanPayNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxScanPayNotifyResult.java
    index 6d08136d..a87adabe 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxScanPayNotifyResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxScanPayNotifyResult.java
    @@ -1,23 +1,48 @@
     package com.github.binarywang.wxpay.bean.notify;
     
    -import com.github.binarywang.wxpay.bean.result.WxPayBaseResult;
    +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
     import com.thoughtworks.xstream.annotations.XStreamAlias;
     import lombok.Data;
     import lombok.EqualsAndHashCode;
     import lombok.NoArgsConstructor;
     
    -import java.io.Serializable;
    -
    +/**
    + * 
    + * 扫码支付通知回调类.
    + * 具体定义,请查看文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
    + * 
    + * + * @author Binary Wang + */ @Data @EqualsAndHashCode(callSuper = true) @NoArgsConstructor -public class WxScanPayNotifyResult extends WxPayBaseResult implements Serializable { +@XStreamAlias("xml") +public class WxScanPayNotifyResult extends BaseWxPayResult { private static final long serialVersionUID = 3381324564266118986L; /** - * 预支付ID + * 用户标识. + */ + @XStreamAlias("openid") + private String openid; + + /** + *
    +   * 是否关注公众账号.
    +   * 仅在公众账号类型支付有效,取值范围:Y或N;Y-关注;N-未关注
    +   * 
    + */ + @XStreamAlias("is_subscribe") + private String isSubscribe; + + /** + *
    +   * 商品ID.
    +   * 商户定义的商品id 或者订单号
    +   * 
    */ - @XStreamAlias("prepay_id") - private String prepayId; + @XStreamAlias("product_id") + private String productId; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayBaseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/BaseWxPayRequest.java similarity index 89% rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayBaseRequest.java rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/BaseWxPayRequest.java index 7147adfe..63f4337b 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayBaseRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/BaseWxPayRequest.java @@ -12,20 +12,23 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.xml.XStreamInitializer; import org.apache.commons.lang3.StringUtils; +import java.io.Serializable; import java.math.BigDecimal; import static com.github.binarywang.wxpay.constant.WxPayConstants.SignType.ALL_SIGN_TYPES; /** *
    - * Created by Binary Wang on 2016-10-24.
      *  微信支付请求对象共用的参数存放类
    + * Created by Binary Wang on 2016-10-24.
      * 
    * * @author Binary Wang */ @Data -public abstract class WxPayBaseRequest { +public abstract class BaseWxPayRequest implements Serializable { + private static final long serialVersionUID = -4766915659779847060L; + /** *
        * 字段名:公众账号ID
    @@ -117,7 +120,7 @@ public abstract class WxPayBaseRequest {
        *
        * @param yuan 将要转换的元的数值字符串
        */
    -  public static Integer yuanToFee(String yuan) {
    +  public static Integer yuanToFen(String yuan) {
         return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
       }
     
    @@ -182,6 +185,20 @@ public abstract class WxPayBaseRequest {
         return xstream.toXML(this);
       }
     
    +  /**
    +   * 签名时,是否忽略signType
    +   */
    +  protected boolean ignoreSignType() {
    +    return false;
    +  }
    +
    +  /**
    +   * 签名时,是否忽略appid
    +   */
    +  protected boolean ignoreAppid() {
    +    return false;
    +  }
    +
       /**
        * 
        * 检查参数,并设置签名
    @@ -190,14 +207,15 @@ public abstract class WxPayBaseRequest {
        * 3、生成签名,并设置进去
        * 
    * - * @param config 支付配置对象,用于读取相应系统配置信息 - * @param isIgnoreSignType 签名时,是否忽略signType + * @param config 支付配置对象,用于读取相应系统配置信息 */ - public void checkAndSign(WxPayConfig config, boolean isIgnoreSignType) throws WxPayException { + public void checkAndSign(WxPayConfig config) throws WxPayException { this.checkFields(); - if (StringUtils.isBlank(getAppid())) { - this.setAppid(config.getAppId()); + if (!ignoreAppid()) { + if (StringUtils.isBlank(getAppid())) { + this.setAppid(config.getAppId()); + } } if (StringUtils.isBlank(getMchId())) { @@ -229,7 +247,6 @@ public abstract class WxPayBaseRequest { //设置签名字段的值 this.setSign(SignUtils.createSign(this, this.getSignType(), config.getMchKey(), - isIgnoreSignType)); + this.ignoreSignType())); } - } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayAuthcode2OpenidRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayAuthcode2OpenidRequest.java index 1187bf8d..3b156407 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayAuthcode2OpenidRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayAuthcode2OpenidRequest.java @@ -17,7 +17,7 @@ import lombok.*; @NoArgsConstructor @AllArgsConstructor @XStreamAlias("xml") -public class WxPayAuthcode2OpenidRequest extends WxPayBaseRequest { +public class WxPayAuthcode2OpenidRequest extends BaseWxPayRequest { /** *
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDefaultRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDefaultRequest.java
    index ff36bfaa..d37ed7ff 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDefaultRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDefaultRequest.java
    @@ -11,7 +11,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
      * @author Binary Wang
      */
     @XStreamAlias("xml")
    -public class WxPayDefaultRequest extends WxPayBaseRequest {
    +public class WxPayDefaultRequest extends BaseWxPayRequest {
       @Override
       protected void checkConstraints() {
         //do nothing
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java
    index 6dc7264b..e616224d 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java
    @@ -24,7 +24,7 @@ import java.util.Arrays;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayDownloadBillRequest extends WxPayBaseRequest {
    +public class WxPayDownloadBillRequest extends BaseWxPayRequest {
       private static final String[] BILL_TYPES = new String[]{BillType.ALL, BillType.SUCCESS, BillType.REFUND, BillType.RECHARGE_REFUND};
       private static final String TAR_TYPE_GZIP = "GZIP";
     
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayMicropayRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayMicropayRequest.java
    index ed85fe76..daa098f9 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayMicropayRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayMicropayRequest.java
    @@ -18,15 +18,30 @@ import me.chanjar.weixin.common.annotation.Required;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayMicropayRequest extends WxPayBaseRequest {
    +public class WxPayMicropayRequest extends BaseWxPayRequest {
       /**
        * 
    -   * 商品描述
    -   * body
    -   * 是
    -   * String(128)
    -   * image形象店-深圳腾大- QQ公仔
    -   * 商品简单描述,该字段须严格按照规范传递,具体请见参数规定
    +   * 字段名:接口版本号.
    +   * 变量名:version
    +   * 是否必填:单品优惠必填
    +   * 类型:String(32)
    +   * 示例值:1.0
    +   * 描述:单品优惠新增字段,区分原接口,固定填写1.0
    +   * 更多信息,详见文档:https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_101&index=1
    +   * 
    + */ + @XStreamAlias("version") + private String version; + + /** + *
    +   * 字段名:商品描述.
    +   * 变量名:body
    +   * 是否必填:是
    +   * 类型:String(128)
    +   * 示例值:image形象店-深圳腾大- QQ公仔
    +   * 描述:商品简单描述,该字段须严格按照规范传递,具体请见参数规定
    +   * 
    **/ @Required @XStreamAlias("body") @@ -34,36 +49,38 @@ public class WxPayMicropayRequest extends WxPayBaseRequest { /** *
    -   * 商品详情
    -   * detail
    -   * 否
    -   * String(6000)
    -   *
    -   * 单品优惠功能字段,需要接入请见详细说明
    +   * 字段名:商品详情.
    +   * 变量名:detail
    +   * 是否必填:否
    +   * 类型:String(6000)
    +   * 示例值:
    +   * 描述:单品优惠功能字段,需要接入请见详细说明
    **/ @XStreamAlias("detail") private String detail; /** *
    -   * 附加数据
    -   * attach
    -   * 否
    -   * String(127)
    -   * 说明
    -   * 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
    +   * 字段名:附加数据.
    +   * 变量名:attach
    +   * 是否必填:否
    +   * 类型:String(127)
    +   * 示例值:说明
    +   * 描述:附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
    +   * 
    **/ @XStreamAlias("attach") private String attach; /** *
    -   * 商户订单号
    -   * out_trade_no
    -   * 是
    -   * String(32)
    -   * 1217752501201407033233368018
    -   * 商户系统内部的订单号,32个字符内、可包含字母,其他说明见商户订单号
    +   * 字段名:商户订单号.
    +   * 变量名:out_trade_no
    +   * 是否必填:是
    +   * 类型:String(32)
    +   * 示例值:1217752501201407033233368018
    +   * 描述:商户系统内部的订单号,32个字符内、可包含字母,其他说明见商户订单号
    +   * 
    **/ @Required @XStreamAlias("out_trade_no") @@ -71,12 +88,13 @@ public class WxPayMicropayRequest extends WxPayBaseRequest { /** *
    -   * 订单金额
    -   * total_fee
    -   * 是
    -   * Int
    -   * 888
    -   * 订单总金额,单位为分,只能为整数,详见支付金额
    +   * 字段名:订单金额.
    +   * 变量名:total_fee
    +   * 是否必填:是
    +   * 类型:Int
    +   * 示例值:888
    +   * 描述:订单总金额,单位为分,只能为整数,详见支付金额
    +   * 
    **/ @Required @XStreamAlias("total_fee") @@ -84,24 +102,26 @@ public class WxPayMicropayRequest extends WxPayBaseRequest { /** *
    -   * 货币类型
    -   * fee_type
    -   * 否
    -   * String(16)
    -   * CNY
    -   * 符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
    +   * 字段名:货币类型.
    +   * 变量名:fee_type
    +   * 是否必填:否
    +   * 类型:String(16)
    +   * 示例值:CNY
    +   * 描述:符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
    +   * 
    **/ @XStreamAlias("fee_type") private String feeType; /** *
    -   * 终端IP
    -   * spbill_create_ip
    -   * 是
    -   * String(16)
    -   * 8.8.8.8
    -   * 调用微信支付API的机器IP
    +   * 字段名:终端IP.
    +   * 变量名:spbill_create_ip
    +   * 是否必填:是
    +   * 类型:String(16)
    +   * 示例值:8.8.8.8
    +   * 描述:调用微信支付API的机器IP
    +   * 
    **/ @Required @XStreamAlias("spbill_create_ip") @@ -109,36 +129,39 @@ public class WxPayMicropayRequest extends WxPayBaseRequest { /** *
    -   * 商品标记
    -   * goods_tag
    -   * 否
    -   * String(32)
    -   * 1234
    -   * 商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠
    +   * 字段名:商品标记.
    +   * 变量名:goods_tag
    +   * 是否必填:否
    +   * 类型:String(32)
    +   * 示例值:1234
    +   * 描述:商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠
    +   * 
    **/ @XStreamAlias("goods_tag") private String goodsTag; /** *
    -   * 指定支付方式
    -   * limit_pay
    -   * 否
    -   * String(32)
    -   * no_credit
    -   * no_credit--指定不能使用信用卡支付
    +   * 字段名:指定支付方式.
    +   * 变量名:limit_pay
    +   * 是否必填:否
    +   * 类型:String(32)
    +   * 示例值:no_credit
    +   * 描述:no_credit--指定不能使用信用卡支付
    +   * 
    **/ @XStreamAlias("limit_pay") private String limitPay; /** *
    -   * 授权码
    -   * auth_code
    -   * 是
    -   * String(128)
    -   * 120061098828009406
    -   * 扫码支付授权码,设备读取用户微信中的条码或者二维码信息注:用户刷卡条形码规则:18位纯数字,以10、11、12、13、14、15开头)
    +   * 字段名:授权码.
    +   * 变量名:auth_code
    +   * 是否必填:是
    +   * 类型:String(128)
    +   * 示例值:120061098828009406
    +   * 描述:扫码支付授权码,设备读取用户微信中的条码或者二维码信息注:用户刷卡条形码规则:18位纯数字,以10、11、12、13、14、15开头)
    +   * 
    **/ @Required @XStreamAlias("auth_code") diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderCloseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderCloseRequest.java index 29650537..e430460e 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderCloseRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderCloseRequest.java @@ -17,7 +17,7 @@ import lombok.*; @NoArgsConstructor @AllArgsConstructor @XStreamAlias("xml") -public class WxPayOrderCloseRequest extends WxPayBaseRequest { +public class WxPayOrderCloseRequest extends BaseWxPayRequest { /** *
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java
    index 4342fb95..221b04f1 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java
    @@ -26,7 +26,22 @@ import org.apache.commons.lang3.StringUtils;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayOrderQueryRequest extends WxPayBaseRequest {
    +public class WxPayOrderQueryRequest extends BaseWxPayRequest {
    +
    +  /**
    +   * 
    +   * 字段名:接口版本号.
    +   * 变量名:version
    +   * 是否必填:单品优惠必填
    +   * 类型:String(32)
    +   * 示例值:1.0
    +   * 描述:单品优惠新增字段,区分原接口,固定填写1.0,
    +   * 查单接口上传version后查询结果才返回单品信息,不上传不返回单品信息。
    +   * 更多信息,详见文档:https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_102&index=2
    +   * 
    + */ + @XStreamAlias("version") + private String version; /** *
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java
    index db681791..5394631b 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java
    @@ -19,7 +19,7 @@ import org.apache.commons.lang3.StringUtils;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayOrderReverseRequest extends WxPayBaseRequest {
    +public class WxPayOrderReverseRequest extends BaseWxPayRequest {
     
       /**
        * 
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayQueryCommentRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayQueryCommentRequest.java
    index e1117b0b..d052a26e 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayQueryCommentRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayQueryCommentRequest.java
    @@ -19,7 +19,12 @@ import me.chanjar.weixin.common.annotation.Required;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayQueryCommentRequest extends WxPayBaseRequest {
    +public class WxPayQueryCommentRequest extends BaseWxPayRequest {
    +  @Override
    +  protected boolean ignoreSignType() {
    +    return true;
    +  }
    +
       /**
        * 
        * 字段名:开始时间
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRedpackQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRedpackQueryRequest.java
    index e7b5f9c1..4bbee5aa 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRedpackQueryRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRedpackQueryRequest.java
    @@ -23,7 +23,7 @@ import lombok.*;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayRedpackQueryRequest extends WxPayBaseRequest {
    +public class WxPayRedpackQueryRequest extends BaseWxPayRequest {
       /**
        * 商户订单号
        * mch_billno
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java
    index e413377f..4df8a63d 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java
    @@ -18,7 +18,7 @@ import org.apache.commons.lang3.StringUtils;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayRefundQueryRequest extends WxPayBaseRequest {
    +public class WxPayRefundQueryRequest extends BaseWxPayRequest {
       /**
        * 
        * 设备号
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java
    index 1a3b85e8..1383e4f5 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java
    @@ -14,13 +14,6 @@ import java.util.Arrays;
     /**
      * 
      * 微信支付-申请退款请求参数
    - * 注释中各行每个字段描述对应如下:
    - * 
  • 字段名 - *
  • 变量名 - *
  • 是否必填 - *
  • 类型 - *
  • 示例值 - *
  • 描述 * Created by Binary Wang on 2016-10-08. *
  • * @@ -32,55 +25,54 @@ import java.util.Arrays; @NoArgsConstructor @AllArgsConstructor @XStreamAlias("xml") -public class WxPayRefundRequest extends WxPayBaseRequest { +public class WxPayRefundRequest extends BaseWxPayRequest { private static final String[] REFUND_ACCOUNT = new String[]{ - RefundAccountSource.RECHARGE_FUNDS, - RefundAccountSource.UNSETTLED_FUNDS - }; + RefundAccountSource.RECHARGE_FUNDS, RefundAccountSource.UNSETTLED_FUNDS}; + /** *
    -   * 设备号
    -   * device_info
    -   * 否
    -   * String(32)
    -   * 13467007045764
    -   * 终端设备号
    +   * 字段名:设备号.
    +   * 变量名:device_info
    +   * 是否必填:否
    +   * 类型:String(32)
    +   * 示例值:13467007045764
    +   * 描述:终端设备号
        * 
    */ @XStreamAlias("device_info") private String deviceInfo; /** *
    -   * 微信订单号
    -   * transaction_id
    -   * 跟out_trade_no二选一
    -   * String(28)
    -   * 1217752501201400000000000000
    -   * 微信生成的订单号,在支付通知中有返回
    +   * 字段名:微信订单号.
    +   * 变量名:transaction_id
    +   * 是否必填:跟out_trade_no二选一
    +   * 类型:String(28)
    +   * 示例值:1217752501201400000000000000
    +   * 描述:微信生成的订单号,在支付通知中有返回
        * 
    */ @XStreamAlias("transaction_id") private String transactionId; /** *
    -   * 商户订单号
    -   * out_trade_no
    -   * 跟transaction_id二选一
    -   * String(32)
    -   * 1217752501201400000000000000
    -   * 商户侧传给微信的订单号
    +   * 字段名:商户订单号.
    +   * 变量名:out_trade_no
    +   * 是否必填:跟transaction_id二选一
    +   * 类型:String(32)
    +   * 示例值:1217752501201400000000000000
    +   * 描述:商户侧传给微信的订单号
        * 
    */ @XStreamAlias("out_trade_no") private String outTradeNo; /** *
    -   * 商户退款单号
    -   * out_refund_no
    -   * 是
    -   * String(32)
    -   * 1217752501201400000000000000
    -   * 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
    +   * 字段名:商户退款单号.
    +   * 变量名:out_refund_no
    +   * 是否必填:是
    +   * 类型:String(32)
    +   * 示例值:1217752501201400000000000000
    +   * 描述:商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
        * 
    */ @Required @@ -88,12 +80,12 @@ public class WxPayRefundRequest extends WxPayBaseRequest { private String outRefundNo; /** *
    -   * 订单金额
    -   * total_fee
    -   * 是
    -   * Int
    -   * 100
    -   * 订单总金额,单位为分,只能为整数,详见支付金额
    +   * 字段名:订单金额.
    +   * 变量名:total_fee
    +   * 是否必填:是
    +   * 类型:Int
    +   * 示例值:100
    +   * 描述:订单总金额,单位为分,只能为整数,详见支付金额
        * 
    */ @Required @@ -101,12 +93,12 @@ public class WxPayRefundRequest extends WxPayBaseRequest { private Integer totalFee; /** *
    -   * 退款金额
    -   * refund_fee
    -   * 是
    -   * Int
    -   * 100
    -   * 退款总金额,订单总金额,单位为分,只能为整数,详见支付金额
    +   * 字段名:退款金额.
    +   * 变量名:refund_fee
    +   * 是否必填:是
    +   * 类型:Int
    +   * 示例值:100
    +   * 描述:退款总金额,订单总金额,单位为分,只能为整数,详见支付金额
        * 
    */ @Required @@ -114,24 +106,24 @@ public class WxPayRefundRequest extends WxPayBaseRequest { private Integer refundFee; /** *
    -   * 货币种类
    -   * refund_fee_type
    -   * 否
    -   * String(8)
    -   * CNY
    -   * 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
    +   * 字段名:货币种类.
    +   * 变量名:refund_fee_type
    +   * 是否必填:否
    +   * 类型:String(8)
    +   * 示例值:CNY
    +   * 描述:货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
        * 
    */ @XStreamAlias("refund_fee_type") private String refundFeeType; /** *
    -   * 操作员
    -   * op_user_id
    -   * 是
    -   * String(32)
    -   * 1900000109
    -   * 操作员帐号, 默认为商户号
    +   * 字段名:操作员.
    +   * 变量名:op_user_id
    +   * 是否必填:是
    +   * 类型:String(32)
    +   * 示例值:1900000109
    +   * 描述:操作员帐号, 默认为商户号
        * 
    */ //@Required @@ -139,46 +131,61 @@ public class WxPayRefundRequest extends WxPayBaseRequest { private String opUserId; /** *
    -   * 退款资金来源
    -   * refund_account
    -   * 否
    -   * String(30)
    -   * REFUND_SOURCE_RECHARGE_FUNDS
    -   * 仅针对老资金流商户使用,
    +   * 字段名:退款资金来源.
    +   * 变量名:refund_account
    +   * 是否必填:否
    +   * 类型:String(30)
    +   * 示例值:REFUND_SOURCE_RECHARGE_FUNDS
    +   * 描述:仅针对老资金流商户使用,
        * 
  • REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款), *
  • REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款 *
  • */ @XStreamAlias("refund_account") private String refundAccount; + /** *
    -   * 退款原因
    -   * refund_account
    -   * 否
    -   * String(80)
    -   * 商品已售完
    -   * 若商户传入,会在下发给用户的退款消息中体现退款原因
    +   * 字段名:退款原因.
    +   * 变量名:refund_account
    +   * 是否必填:否
    +   * 类型:String(80)
    +   * 示例值:商品已售完
    +   * 描述:若商户传入,会在下发给用户的退款消息中体现退款原因
        * 
    */ @XStreamAlias("refund_desc") private String refundDesc; + /** + *
    +   * 字段名:退款结果通知url.
    +   * 变量名:notify_url
    +   * 是否必填:否
    +   * 类型:String(256)
    +   * 示例值:https://weixin.qq.com/notify/
    +   * 描述:	异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数
    +   如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。
    +   * 
    + */ + @XStreamAlias("notify_url") + private String notifyUrl; + @Override - public void checkAndSign(WxPayConfig config, boolean isIgnoreSignType) throws WxPayException { + public void checkAndSign(WxPayConfig config) throws WxPayException { if (StringUtils.isBlank(this.getOpUserId())) { this.setOpUserId(config.getMchId()); } - super.checkAndSign(config, isIgnoreSignType); + super.checkAndSign(config); } @Override protected void checkConstraints() throws WxPayException { if (StringUtils.isNotBlank(this.getRefundAccount())) { if (!ArrayUtils.contains(REFUND_ACCOUNT, this.getRefundAccount())) { - throw new WxPayException(String.format("refund_account目前必须为%s其中之一,实际值:%s", - Arrays.toString(REFUND_ACCOUNT), this.getRefundAccount())); + throw new WxPayException( + String.format("refund_account目前必须为%s其中之一,实际值:%s", Arrays.toString(REFUND_ACCOUNT), this.getRefundAccount())); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayReportRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayReportRequest.java index 88532ad2..494ac1f3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayReportRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayReportRequest.java @@ -24,7 +24,7 @@ import me.chanjar.weixin.common.annotation.Required; @NoArgsConstructor @AllArgsConstructor @XStreamAlias("xml") -public class WxPayReportRequest extends WxPayBaseRequest { +public class WxPayReportRequest extends BaseWxPayRequest { /** *
        * 设备号
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPaySendRedpackRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPaySendRedpackRequest.java
    index bc621fc0..f97ade0c 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPaySendRedpackRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPaySendRedpackRequest.java
    @@ -15,7 +15,7 @@ import lombok.*;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPaySendRedpackRequest extends WxPayBaseRequest {
    +public class WxPaySendRedpackRequest extends BaseWxPayRequest {
       /**
        * mch_billno
        * 商户订单号(每个订单号必须唯一)  组成:mch_id+yyyymmdd+10位一天内不能重复的数字。  接口根据商户订单号支持重入,如出现超时可再调用。
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayShorturlRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayShorturlRequest.java
    index 3cc9302b..87ac4105 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayShorturlRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayShorturlRequest.java
    @@ -17,7 +17,7 @@ import lombok.*;
     @NoArgsConstructor
     @AllArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayShorturlRequest extends WxPayBaseRequest {
    +public class WxPayShorturlRequest extends BaseWxPayRequest {
       /**
        * 
        * URL链接
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java
    index c2bc9f45..4ef7ab44 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java
    @@ -10,7 +10,7 @@ import org.apache.commons.lang3.StringUtils;
     
     /**
      * 
    - * 统一下单请求参数对象
    + * 统一下单请求参数对象.
      * 参考文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
      * Created by Binary Wang on 2016/9/25.
      * 
    @@ -23,10 +23,27 @@ import org.apache.commons.lang3.StringUtils; @NoArgsConstructor @AllArgsConstructor @XStreamAlias("xml") -public class WxPayUnifiedOrderRequest extends WxPayBaseRequest { +public class WxPayUnifiedOrderRequest extends BaseWxPayRequest { + private static final long serialVersionUID = 4611350167813931828L; + /** *
    -   * 字段名:设备号
    +   * 字段名:接口版本号.
    +   * 变量名:version
    +   * 是否必填:单品优惠必填
    +   * 类型:String(32)
    +   * 示例值:1.0
    +   * 描述:单品优惠新增字段,接口版本号,区分原接口,默认填写1.0。
    +   * 入参新增version后,则支付通知接口也将返回单品优惠信息字段promotion_detail,请确保支付通知的签名验证能通过。
    +   * 更多信息,详见文档:https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_102&index=2
    +   * 
    + */ + @XStreamAlias("version") + private String version; + + /** + *
    +   * 字段名:设备号.
        * 变量名:device_info
        * 是否必填:否
        * 类型:String(32)
    @@ -39,7 +56,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:商品描述
    +   * 字段名:商品描述.
        * 变量名:body
        * 是否必填:是
        * 类型:String(128)
    @@ -53,7 +70,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:商品详情
    +   * 字段名:商品详情.
        * 变量名:detail
        * 是否必填:否
        * 类型:String(6000)
    @@ -94,7 +111,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:附加数据
    +   * 字段名:附加数据.
        * 变量名:attach
        * 是否必填:否
        * 类型:String(127)
    @@ -107,7 +124,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:商户订单号
    +   * 字段名:商户订单号.
        * 变量名:out_trade_no
        * 是否必填:是
        * 类型:String(32)
    @@ -121,7 +138,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:货币类型
    +   * 字段名:货币类型.
        * 变量名:fee_type
        * 是否必填:否
        * 类型:String(16)
    @@ -134,7 +151,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:总金额
    +   * 字段名:总金额.
        * 变量名:total_fee
        * 是否必填:是
        * 类型:Int
    @@ -148,7 +165,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:终端IP
    +   * 字段名:终端IP.
        * 变量名:spbill_create_ip
        * 是否必填:是
        * 类型:String(16)
    @@ -162,7 +179,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:交易起始时间
    +   * 字段名:交易起始时间.
        * 变量名:time_start
        * 是否必填:否
        * 类型:String(14)
    @@ -175,7 +192,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:交易结束时间
    +   * 字段名:交易结束时间.
        * 变量名:time_expire
        * 是否必填:否
        * 类型:String(14)
    @@ -189,7 +206,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:商品标记
    +   * 字段名:商品标记.
        * 变量名:goods_tag
        * 是否必填:否
        * 类型:String(32)
    @@ -202,7 +219,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:通知地址
    +   * 字段名:通知地址.
        * 变量名:notify_url
        * 是否必填:是
        * 类型:String(256)
    @@ -212,11 +229,11 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
        */
       @Required
       @XStreamAlias("notify_url")
    -  private String notifyURL;
    +  private String notifyUrl;
     
       /**
        * 
    -   * 字段名:交易类型
    +   * 字段名:交易类型.
        * 变量名:trade_type
        * 是否必填:是
        * 类型:String(16)
    @@ -231,7 +248,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:商品Id
    +   * 字段名:商品Id.
        * 变量名:product_id
        * 是否必填:否
        * 类型:String(32)
    @@ -244,7 +261,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:指定支付方式
    +   * 字段名:指定支付方式.
        * 变量名:limit_pay
        * 是否必填:否
        * 类型:String(32)
    @@ -257,7 +274,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:用户标识
    +   * 字段名:用户标识.
        * 变量名:openid
        * 是否必填:否
        * 类型:String(128)
    @@ -272,7 +289,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:用户子标识
    +   * 字段名:用户子标识.
        * 变量名:sub_openid
        * 是否必填:否
        * 类型:String(128)
    @@ -287,7 +304,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       /**
        * 
    -   * 字段名:场景信息
    +   * 字段名:场景信息.
        * 变量名:scene_info
        * 是否必填:否,对H5支付来说是必填
        * 类型:String(256)
    @@ -306,7 +323,7 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
       private String sceneInfo;
       /**
        * 
    -   * 字段名:浏览器指纹
    +   * 字段名:浏览器指纹.
        * 变量名:fingerprint
        * 是否必填:否
        * 详细参考 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_7&index=6
    @@ -316,14 +333,16 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
       private String fingerprint;
     
       /**
    -   * 如果配置中已经设置,可以不设置值
    +   * 如果配置中已经设置,可以不设置值.
    +   *
    +   * @param notifyUrl 支付回调通知地址
        */
    -  public void setNotifyURL(String notifyURL) {
    -    this.notifyURL = notifyURL;
    +  public void setNotifyUrl(String notifyUrl) {
    +    this.notifyUrl = notifyUrl;
       }
     
       /**
    -   * 如果配置中已经设置,可以不设置值
    +   * 如果配置中已经设置,可以不设置值.
        *
        * @param tradeType 交易类型
        */
    @@ -333,32 +352,22 @@ public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
     
       @Override
       protected void checkConstraints() throws WxPayException {
    -    if (TradeType.JSAPI.equals(this.getTradeType())) {
    -      if (StringUtils.isBlank(this.getSubAppId()) && StringUtils.isBlank(this.getOpenid())) {
    -        throw new WxPayException("当trade_type是'JSAPI'时,需指定非空的openid值");
    -      }
    -
    -      if (StringUtils.isNotBlank(this.getSubAppId()) && StringUtils.isBlank(this.getSubOpenid())) {
    -        throw new WxPayException("在服务商模式下,当trade_type是'JSAPI'时,需指定非空的sub_openid值");
    -      }
    -    }
    -
         if (TradeType.NATIVE.equals(this.getTradeType()) && StringUtils.isBlank(this.getProductId())) {
           throw new WxPayException("当trade_type是'NATIVE'时,需指定非空的product_id值");
         }
       }
     
       @Override
    -  public void checkAndSign(WxPayConfig config, boolean isIgnoreSignType) throws WxPayException {
    -    if (StringUtils.isBlank(this.getNotifyURL())) {
    -      this.setNotifyURL(config.getNotifyUrl());
    +  public void checkAndSign(WxPayConfig config) throws WxPayException {
    +    if (StringUtils.isBlank(this.getNotifyUrl())) {
    +      this.setNotifyUrl(config.getNotifyUrl());
         }
     
         if (StringUtils.isBlank(this.getTradeType())) {
           this.setTradeType(config.getTradeType());
         }
     
    -    super.checkAndSign(config, isIgnoreSignType);
    +    super.checkAndSign(config);
       }
     
     }
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/BaseWxPayResult.java
    similarity index 85%
    rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java
    rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/BaseWxPayResult.java
    index 1e0527eb..3a4d2f6a 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/BaseWxPayResult.java
    @@ -1,7 +1,7 @@
     package com.github.binarywang.wxpay.bean.result;
     
     import com.github.binarywang.wxpay.exception.WxPayException;
    -import com.github.binarywang.wxpay.service.impl.WxPayServiceAbstractImpl;
    +import com.github.binarywang.wxpay.service.WxPayService;
     import com.github.binarywang.wxpay.util.SignUtils;
     import com.google.common.base.Joiner;
     import com.google.common.collect.Lists;
    @@ -25,27 +25,28 @@ import javax.xml.xpath.XPathExpressionException;
     import javax.xml.xpath.XPathFactory;
     import java.io.ByteArrayInputStream;
     import java.io.IOException;
    +import java.io.Serializable;
     import java.math.BigDecimal;
     import java.util.List;
     import java.util.Map;
     
     /**
      * 
    - * 微信支付结果共用属性类
    + * 微信支付结果共用属性类.
      * Created by Binary Wang on 2016-10-24.
      * 
    * * @author Binary Wang */ @Data -public abstract class WxPayBaseResult { +public abstract class BaseWxPayResult implements Serializable { /** - * 返回状态码 + * 返回状态码. */ @XStreamAlias("return_code") protected String returnCode; /** - * 返回信息 + * 返回信息. */ @XStreamAlias("return_msg") protected String returnMsg; @@ -53,64 +54,64 @@ public abstract class WxPayBaseResult { //当return_code为SUCCESS的时候,还会包括以下字段: /** - * 业务结果 + * 业务结果. */ @XStreamAlias("result_code") private String resultCode; /** - * 错误代码 + * 错误代码. */ @XStreamAlias("err_code") private String errCode; /** - * 错误代码描述 + * 错误代码描述. */ @XStreamAlias("err_code_des") private String errCodeDes; /** - * 公众账号ID + * 公众账号ID. */ @XStreamAlias("appid") private String appid; /** - * 商户号 + * 商户号. */ @XStreamAlias("mch_id") private String mchId; /** - * 服务商模式下的子公众账号ID + * 服务商模式下的子公众账号ID. */ @XStreamAlias("sub_appid") private String subAppId; /** - * 服务商模式下的子商户号 + * 服务商模式下的子商户号. */ @XStreamAlias("sub_mch_id") private String subMchId; /** - * 随机字符串 + * 随机字符串. */ @XStreamAlias("nonce_str") private String nonceStr; /** - * 签名 + * 签名. */ @XStreamAlias("sign") private String sign; //以下为辅助属性 /** - * xml字符串 + * xml字符串. */ private String xmlString; /** - * xml的Document对象,用于解析xml文本 + * xml的Document对象,用于解析xml文本. */ private Document xmlDoc; /** - * 将单位分转换成单位圆 + * 将单位分转换成单位圆. * * @param fee 将要被转换为元的分的数值 */ @@ -119,9 +120,9 @@ public abstract class WxPayBaseResult { } /** - * 从xml字符串创建bean对象 + * 从xml字符串创建bean对象. */ - public static T fromXML(String xmlString, Class clz) { + public static T fromXML(String xmlString, Class clz) { XStream xstream = XStreamInitializer.getInstance(); xstream.processAnnotations(clz); T result = (T) xstream.fromXML(xmlString); @@ -139,7 +140,7 @@ public abstract class WxPayBaseResult { } /** - * 将bean通过保存的xml字符串转换成map + * 将bean通过保存的xml字符串转换成map. */ public Map toMap() { if (StringUtils.isBlank(this.xmlString)) { @@ -165,9 +166,9 @@ public abstract class WxPayBaseResult { } /** - * 将xml字符串转换成Document对象,以便读取其元素值 + * 将xml字符串转换成Document对象,以便读取其元素值. */ - protected Document getXmlDoc() { + private Document getXmlDoc() { if (this.xmlDoc != null) { return this.xmlDoc; } @@ -185,9 +186,9 @@ public abstract class WxPayBaseResult { } /** - * 获取xml中元素的值 + * 获取xml中元素的值. */ - protected String getXmlValue(String... path) { + String getXmlValue(String... path) { Document doc = this.getXmlDoc(); String expression = String.format("/%s//text()", Joiner.on("/").join(path)); try { @@ -202,9 +203,9 @@ public abstract class WxPayBaseResult { } /** - * 获取xml中元素的值,作为int值返回 + * 获取xml中元素的值,作为int值返回. */ - protected Integer getXmlValueAsInt(String... path) { + Integer getXmlValueAsInt(String... path) { String result = this.getXmlValue(path); if (StringUtils.isBlank(result)) { return null; @@ -214,12 +215,12 @@ public abstract class WxPayBaseResult { } /** - * 校验返回结果签名 + * 校验返回结果签名. * * @param signType 签名类型 * @param checkSuccess 是否同时检查结果是否成功 */ - public void checkResult(WxPayServiceAbstractImpl wxPayService, String signType, boolean checkSuccess) throws WxPayException { + public void checkResult(WxPayService wxPayService, String signType, boolean checkSuccess) throws WxPayException { //校验返回结果签名 Map map = toMap(); if (getSign() != null && !SignUtils.checkSign(map, signType, wxPayService.getConfig().getMchKey())) { diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayQueryResult.java index b5a0e043..bf106666 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayQueryResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayQueryResult.java @@ -1,74 +1,23 @@ package com.github.binarywang.wxpay.bean.result; +import com.github.binarywang.wxpay.bean.entpay.EntPayQueryResult; import com.thoughtworks.xstream.annotations.XStreamAlias; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import org.apache.commons.beanutils.BeanUtils; /** * 企业付款查询返回结果 - * Created by Binary Wang on 2016/10/19. - * - * @author Binary Wang + * 请使用{@link EntPayQueryResult} */ -@Data -@EqualsAndHashCode(callSuper = true) -@NoArgsConstructor @XStreamAlias("xml") -public class WxEntPayQueryResult extends WxPayBaseResult { - - /** - * 商户订单号 - */ - @XStreamAlias("partner_trade_no") - private String partnerTradeNo; - - /** - * 付款单号 - */ - @XStreamAlias("detail_id") - private String detailId; - - /** - * 转账状态 - */ - @XStreamAlias("status") - private String status; - - /** - * 失败原因 - */ - @XStreamAlias("reason") - private String reason; - - /** - * 收款用户openid - */ - @XStreamAlias("openid") - private String openid; - - /** - * 收款用户姓名 - */ - @XStreamAlias("transfer_name") - private String transferName; - - /** - * 付款金额 - */ - @XStreamAlias("payment_amount") - private Integer paymentAmount; - - /** - * 转账时间 - */ - @XStreamAlias("transfer_time") - private String transferTime; - - /** - * 付款描述 - */ - @XStreamAlias("desc") - private String desc; - +@Deprecated +public class WxEntPayQueryResult extends EntPayQueryResult { + public static WxEntPayQueryResult createFrom(EntPayQueryResult entPayQueryResult) { + WxEntPayQueryResult result = new WxEntPayQueryResult(); + try { + BeanUtils.copyProperties(result, entPayQueryResult); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayResult.java index 033f6e96..ce6847e8 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxEntPayResult.java @@ -1,51 +1,23 @@ package com.github.binarywang.wxpay.bean.result; +import com.github.binarywang.wxpay.bean.entpay.EntPayResult; import com.thoughtworks.xstream.annotations.XStreamAlias; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import org.apache.commons.beanutils.BeanUtils; /** * 企业付款返回结果 - * Created by Binary Wang on 2016/10/02. - * - * @author Binary Wang + * 请使用{@link EntPayResult} */ -@Data -@EqualsAndHashCode(callSuper = true) -@NoArgsConstructor @XStreamAlias("xml") -public class WxEntPayResult extends WxPayBaseResult { - - /** - * 商户appid - */ - @XStreamAlias("mch_appid") - private String mchAppid; - - /** - * 设备号 - */ - @XStreamAlias("device_info") - private String deviceInfo; - - //############以下字段在return_code 和result_code都为SUCCESS的时候有返回############## - /** - * 商户订单号 - */ - @XStreamAlias("partner_trade_no") - private String partnerTradeNo; - - /** - * 微信订单号 - */ - @XStreamAlias("payment_no") - private String paymentNo; - - /** - * 微信支付成功时间 - */ - @XStreamAlias("payment_time") - private String paymentTime; - +@Deprecated +public class WxEntPayResult extends EntPayResult { + public static WxEntPayResult createFrom(EntPayResult entPayResult) { + WxEntPayResult result = new WxEntPayResult(); + try { + BeanUtils.copyProperties(result, entPayResult); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayAuthcode2OpenidResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayAuthcode2OpenidResult.java index 3f1d53a7..2c36d32f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayAuthcode2OpenidResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayAuthcode2OpenidResult.java @@ -17,10 +17,10 @@ import lombok.NoArgsConstructor; @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @XStreamAlias("xml") -public class WxPayAuthcode2OpenidResult extends WxPayBaseResult { +public class WxPayAuthcode2OpenidResult extends BaseWxPayResult { /** *
    -   *   用户标识
    +   *   用户标识.
        *   openid
        *   是
        *   String(128)
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayCommonResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayCommonResult.java
    index 8c99c9df..242a30a1 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayCommonResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayCommonResult.java
    @@ -12,5 +12,5 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
      */
     
     @XStreamAlias("xml")
    -public class WxPayCommonResult extends WxPayBaseResult {
    +public class WxPayCommonResult extends BaseWxPayResult {
     }
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayMicropayResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayMicropayResult.java
    index 4f6b04cf..87aad5f4 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayMicropayResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayMicropayResult.java
    @@ -17,7 +17,7 @@ import lombok.NoArgsConstructor;
     @EqualsAndHashCode(callSuper = true)
     @NoArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayMicropayResult extends WxPayBaseResult {
    +public class WxPayMicropayResult extends BaseWxPayResult {
       /**
        * 
        * 用户标识
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderCloseResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderCloseResult.java
    index 5451c853..a71c8ab7 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderCloseResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderCloseResult.java
    @@ -17,7 +17,7 @@ import lombok.NoArgsConstructor;
     @EqualsAndHashCode(callSuper = true)
     @NoArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayOrderCloseResult extends WxPayBaseResult {
    +public class WxPayOrderCloseResult extends BaseWxPayResult {
     
       /**
        * 业务结果描述
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResult.java
    index 9da15f5a..dd37fa7a 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResult.java
    @@ -25,7 +25,20 @@ import java.util.List;
     @EqualsAndHashCode(callSuper = true)
     @NoArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayOrderQueryResult extends WxPayBaseResult {
    +public class WxPayOrderQueryResult extends BaseWxPayResult {
    +
    +  /**
    +   * 
    +   * 字段名:营销详情.
    +   * 变量名:promotion_detail
    +   * 是否必填:否,单品优惠才有
    +   * 类型:String(6000)
    +   * 示例值:[{"promotion_detail":[{"promotion_id":"109519","name":"单品惠-6","scope":"SINGLE","type":"DISCOUNT","amount":5,"activity_id":"931386","wxpay_contribute":0,"merchant_contribute":0,"other_contribute":5,"goods_detail":[{"goods_id":"a_goods1","goods_remark":"商品备注","quantity":7,"price":1,"discount_amount":4},{"goods_id":"a_goods2","goods_remark":"商品备注","quantity":1,"price":2,"discount_amount":1}]}]}
    +   * 描述:单品优惠专用参数,详见https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_201&index=3
    +   * 
    + */ + @XStreamAlias("promotion_detail") + private String promotionDetail; /** *
    设备号
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderReverseResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderReverseResult.java
    index bf36764f..57813992 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderReverseResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderReverseResult.java
    @@ -17,7 +17,7 @@ import lombok.NoArgsConstructor;
     @EqualsAndHashCode(callSuper = true)
     @NoArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayOrderReverseResult extends WxPayBaseResult {
    +public class WxPayOrderReverseResult extends BaseWxPayResult {
     
       /**
        * 
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRedpackQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRedpackQueryResult.java
    index 84030f17..3fdfe333 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRedpackQueryResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRedpackQueryResult.java
    @@ -1,5 +1,8 @@
     package com.github.binarywang.wxpay.bean.result;
     
    +import java.io.Serializable;
    +import java.util.List;
    +
     import com.thoughtworks.xstream.annotations.XStreamAlias;
     import lombok.Data;
     import lombok.EqualsAndHashCode;
    @@ -7,13 +10,6 @@ import lombok.NoArgsConstructor;
     
     /**
      * 
    - *   注释中各行对应含义:
    - *   字段名
    - *   字段
    - *   必填
    - *   示例值
    - *   类型
    - *   说明
      * Created by Binary Wang on 2016-11-28.
      * 
    * @@ -23,16 +19,17 @@ import lombok.NoArgsConstructor; @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @XStreamAlias("xml") -public class WxPayRedpackQueryResult extends WxPayBaseResult { +public class WxPayRedpackQueryResult extends BaseWxPayResult { + private static final long serialVersionUID = -3849864122189552906L; /** *
    -   * 商户订单号
    -   * mch_billno
    -   * 是
    -   * 10000098201411111234567890
    -   * String(28)
    -   * 商户使用查询API填写的商户单号的原路返回
    +   * 字段含义:商户订单号.
    +   * 字段名:mch_billno
    +   * 是否必填:是
    +   * 示例值:10000098201411111234567890
    +   * 类型:String(28)
    +   * 字段说明:商户使用查询API填写的商户单号的原路返回
        * 
    */ @XStreamAlias("mch_billno") @@ -40,12 +37,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包单号
    -   * detail_id
    -   * 是
    -   * 1000000000201503283103439304
    -   * String(32)
    -   * 使用API发放现金红包时返回的红包单号
    +   * 字段含义:红包单号.
    +   * 字段名:detail_id
    +   * 是否必填:是
    +   * 示例值:1000000000201503283103439304
    +   * 类型:String(32)
    +   * 字段说明:使用API发放现金红包时返回的红包单号
        * 
    */ @XStreamAlias("detail_id") @@ -53,12 +50,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包状态
    -   * status
    -   * 是
    -   * RECEIVED
    -   * string(16)
    -   * SENDING:发放中,
    +   * 字段含义:红包状态.
    +   * 字段名:status
    +   * 是否必填:是
    +   * 示例值:RECEIVED
    +   * 类型:string(16)
    +   * 字段说明:SENDING:发放中,
        * SENT:已发放待领取,
        * FAILED:发放失败,
        * RECEIVED:已领取,
    @@ -71,12 +68,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult {
     
       /**
        * 
    -   * 发放类型
    -   * send_type
    -   * 是
    -   * API
    -   * String(32)
    -   *  API:通过API接口发放,
    +   * 字段含义:发放类型.
    +   * 字段名:send_type
    +   * 是否必填:是
    +   * 示例值:API
    +   * 类型:String(32)
    +   * 字段说明:API:通过API接口发放,
        *  UPLOAD:通过上传文件方式发放,
        *  ACTIVITY:通过活动方式发放
        * 
    @@ -86,12 +83,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包类型
    -   * hb_type
    -   * 是
    -   * GROUP
    -   * String(32)
    -   *  GROUP:裂变红包,
    +   * 字段含义:红包类型.
    +   * 字段名:hb_type
    +   * 是否必填:是
    +   * 示例值:GROUP
    +   * 类型:String(32)
    +   * 字段说明:GROUP:裂变红包,
        *  NORMAL:普通红包
        * 
    */ @@ -100,12 +97,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包个数
    -   * total_num
    -   * 是
    -   * 1
    -   * int
    -   * 红包个数
    +   * 字段含义:红包个数.
    +   * 字段名:total_num
    +   * 是否必填:是
    +   * 示例值:1
    +   * 类型:int
    +   * 字段说明:红包个数
        * 
    */ @XStreamAlias("total_num") @@ -113,12 +110,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包金额
    -   * total_amount
    -   * 是
    -   * 5000
    -   * int
    -   * 红包总金额(单位分)
    +   * 字段含义:红包金额.
    +   * 字段名:total_amount
    +   * 是否必填:是
    +   * 示例值:5000
    +   * 类型:int
    +   * 字段说明:红包总金额(单位分)
        * 
    */ @XStreamAlias("total_amount") @@ -126,12 +123,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 失败原因
    -   * reason
    -   * 否
    -   * 余额不足
    -   * String(32)
    -   * 发送失败原因
    +   * 字段含义:失败原因.
    +   * 字段名:reason
    +   * 是否必填:否
    +   * 示例值:余额不足
    +   * 类型:String(32)
    +   * 字段说明:发送失败原因
        * 
    */ @XStreamAlias("reason") @@ -139,12 +136,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包发送时间
    -   * send_time
    -   * 是
    -   * 2015-04-21 20:00:00
    -   * String(32)
    -   * 红包的发送时间
    +   * 字段含义:红包发送时间.
    +   * 字段名:send_time
    +   * 是否必填:是
    +   * 示例值:2015-04-21 20:00:00
    +   * 类型:String(32)
    +   * 字段说明:红包的发送时间
        * 
    */ @XStreamAlias("send_time") @@ -152,12 +149,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包退款时间
    -   * refund_time
    -   * 否
    -   * 2015-04-21 23:03:00
    -   * String(32)
    -   * 红包的退款时间(如果其未领取的退款)
    +   * 字段含义:红包退款时间.
    +   * 字段名: refund_time
    +   * 是否必填:否
    +   * 示例值:2015-04-21 23:03:00
    +   * 类型:String(32)
    +   * 字段说明:红包的退款时间(如果其未领取的退款)
        * 
    */ @XStreamAlias("refund_time") @@ -165,12 +162,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 红包退款金额
    -   * refund_amount
    -   * 否
    -   * 8000
    -   * Int
    -   * 红包退款金额
    +   * 字段含义:红包退款金额.
    +   * 字段名:refund_amount
    +   * 是否必填:否
    +   * 示例值:8000
    +   * 类型:Int
    +   * 字段说明:红包退款金额
        * 
    */ @XStreamAlias("refund_amount") @@ -178,12 +175,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 祝福语
    -   * wishing
    -   * 否
    -   * 新年快乐
    -   * String(128)
    -   * 祝福语
    +   * 字段含义:祝福语.
    +   * 字段名:wishing
    +   * 是否必填:否
    +   * 示例值:新年快乐
    +   * 类型:String(128)
    +   * 字段说明:祝福语
        * 
    */ @XStreamAlias("wishing") @@ -191,12 +188,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 活动描述
    -   * remark
    -   * 否
    -   * 新年红包
    -   * String(256)
    -   * 活动描述,低版本微信可见
    +   * 字段含义:活动描述.
    +   * 字段名:remark
    +   * 是否必填:否
    +   * 示例值:新年红包
    +   * 类型:String(256)
    +   * 字段说明:活动描述,低版本微信可见
        * 
    */ @XStreamAlias("remark") @@ -204,12 +201,12 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 活动名称
    -   * act_name
    -   * 否
    -   * 新年红包
    -   * String(32)
    -   * 发红包的活动名称
    +   * 字段含义:活动名称.
    +   * 字段名:act_name
    +   * 是否必填:否
    +   * 示例值:新年红包
    +   * 类型:String(32)
    +   * 字段说明:发红包的活动名称
        * 
    */ @XStreamAlias("act_name") @@ -217,53 +214,57 @@ public class WxPayRedpackQueryResult extends WxPayBaseResult { /** *
    -   * 裂变红包领取列表
    -   * hblist
    -   * 否
    -   *
    -   *
    -   * 裂变红包的领取列表
    +   * 字段含义:裂变红包领取列表.
    +   * 字段名:redpackList
    +   * 是否必填:否
    +   * 字段说明: 裂变红包的领取列表
        * 
    */ @XStreamAlias("hblist") - private String hblist; + private List redpackList; - /** - *
    -   * 领取红包的Openid
    -   * openid
    -   * 是
    -   * ohO4GtzOAAYMp2yapORH3dQB3W18
    -   * String(32)
    -   * 领取红包的openid
    -   * 
    - */ - @XStreamAlias("openid") - private String openid; + @Data + @XStreamAlias("hbinfo") + public static class RedpackInfo implements Serializable { + private static final long serialVersionUID = 7829773321457772100L; + /** + *
    +     * 字段含义:领取红包的Openid.
    +     * 字段名: openid
    +     * 是否必填:是
    +     * 示例值:ohO4GtzOAAYMp2yapORH3dQB3W18
    +     * 类型:String(32)
    +     * 字段说明:领取红包的openid
    +     * 
    + */ + @XStreamAlias("openid") + private String openid; - /** - *
    -   * 金额
    -   * amount
    -   * 是
    -   * 100
    -   * int
    -   * 领取金额
    -   * 
    - */ - @XStreamAlias("amount") - private Integer amount; + /** + *
    +     * 字段含义:金额.
    +     * 字段名: amount
    +     * 是否必填:是
    +     * 示例值:100
    +     * 类型:int
    +     * 字段说明:领取金额
    +     * 
    + */ + @XStreamAlias("amount") + private Integer amount; + + /** + *
    +     * 字段含义:接收时间.
    +     * 字段名: rcv_time
    +     * 是否必填:是
    +     * 示例值:2015-04-21 20:00:00
    +     * 类型:String(32)
    +     * 字段说明:领取红包的时间
    +     * 
    + */ + @XStreamAlias("rcv_time") + private String receiveTime; + } - /** - *
    -   * 接收时间
    -   * rcv_time
    -   * 是
    -   * 2015-04-21 20:00:00
    -   * String(32)
    -   * 领取红包的时间
    -   * 
    - */ - @XStreamAlias("rcv_time") - private String receiveTime; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundQueryResult.java index f9733601..65514a72 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundQueryResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundQueryResult.java @@ -8,6 +8,7 @@ import java.util.List; /** *
    + * 微信支付-退款查询返回结果
      * Created by Binary Wang on 2016-11-24.
      * 
    * @@ -17,99 +18,107 @@ import java.util.List; @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @XStreamAlias("xml") -public class WxPayRefundQueryResult extends WxPayBaseResult { +public class WxPayRefundQueryResult extends BaseWxPayResult { /** *
    -   * 设备号
    -   * device_info
    -   * 否
    -   * String(32)
    -   * 013467007045764
    -   * 终端设备号
    +   * 字段名:设备号.
    +   * 变量名:device_info
    +   * 是否必填:否
    +   * 类型:String(32)
    +   * 示例值:013467007045764
    +   * 描述:终端设备号
    +   * 
    */ @XStreamAlias("device_info") private String deviceInfo; /** *
    -   * 微信订单号
    -   * transaction_id
    -   * 是
    -   * String(32)
    -   * 1217752501201407033233368018
    -   * 微信订单号
    +   * 字段名:微信订单号.
    +   * 变量名:transaction_id
    +   * 是否必填:是
    +   * 类型:String(32)
    +   * 示例值:1217752501201407033233368018
    +   * 描述:微信订单号
    +   * 
    */ @XStreamAlias("transaction_id") private String transactionId; /** *
    -   * 商户订单号
    -   * out_trade_no
    -   * 是
    -   * String(32)
    -   * 1217752501201407033233368018
    -   * 商户系统内部的订单号
    +   * 字段名:商户订单号.
    +   * 变量名:out_trade_no
    +   * 是否必填:是
    +   * 类型:String(32)
    +   * 示例值:1217752501201407033233368018
    +   * 描述:商户系统内部的订单号
    +   * 
    */ @XStreamAlias("out_trade_no") private String outTradeNo; /** *
    -   * 订单金额
    -   * total_fee
    -   * 是
    -   * Int
    -   * 100
    -   * 订单总金额,单位为分,只能为整数,详见支付金额
    +   * 字段名:订单金额.
    +   * 变量名:total_fee
    +   * 是否必填:是
    +   * 类型:Int
    +   * 示例值:100
    +   * 描述:订单总金额,单位为分,只能为整数,详见支付金额
    +   * 
    */ @XStreamAlias("total_fee") private Integer totalFee; /** *
    -   * 应结订单金额
    -   * settlement_total_fee
    -   * 否
    -   * Int
    -   * 100
    -   * 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
    +   * 字段名:应结订单金额.
    +   * 变量名:settlement_total_fee
    +   * 是否必填:否
    +   * 类型:Int
    +   * 示例值:100
    +   * 描述:应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
    +   * 
    */ @XStreamAlias("settlement_total_fee") private Integer settlementTotalFee; /** *
    -   * 货币种类
    -   * fee_type
    -   * 否
    -   * String(8)
    -   * CNY
    -   * 订单金额货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
    +   * 字段名:货币种类.
    +   * 变量名:fee_type
    +   * 是否必填:否
    +   * 类型:String(8)
    +   * 示例值:CNY
    +   * 描述:订单金额货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
    +   * 
    */ @XStreamAlias("fee_type") private String feeType; /** *
    -   * 现金支付金额
    -   * cash_fee
    -   * 是
    -   * Int
    -   * 100
    -   * 现金支付金额,单位为分,只能为整数,详见支付金额
    +   * 字段名:现金支付金额.
    +   * 变量名:cash_fee
    +   * 是否必填:是
    +   * 类型:Int
    +   * 示例值:100
    +   * 描述:现金支付金额,单位为分,只能为整数,详见支付金额
    +   * 
    */ @XStreamAlias("cash_fee") private Integer cashFee; /** *
    -   * 退款笔数
    -   * refund_count
    -   * 是
    -   * Int
    -   * 1
    -   * 退款记录数
    +   * 字段名:退款笔数.
    +   * 变量名:refund_count
    +   * 是否必填:是
    +   * 类型:Int
    +   * 示例值:1
    +   * 描述:退款记录数
    +   * 
    */ @XStreamAlias("refund_count") private Integer refundCount; @@ -117,7 +126,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { private List refundRecords; /** - * 组装生成退款记录属性的内容 + * 组装生成退款记录属性的内容. */ public void composeRefundRecords() { if (this.refundCount != null && this.refundCount > 0) { @@ -132,11 +141,11 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { refundRecord.setRefundChannel(this.getXmlValue("xml/refund_channel_" + i)); refundRecord.setRefundFee(this.getXmlValueAsInt("xml/refund_fee_" + i)); refundRecord.setSettlementRefundFee(this.getXmlValueAsInt("xml/settlement_refund_fee_" + i)); - refundRecord.setCouponType(this.getXmlValue("xml/coupon_type_" + i)); refundRecord.setCouponRefundFee(this.getXmlValueAsInt("xml/coupon_refund_fee_" + i)); refundRecord.setCouponRefundCount(this.getXmlValueAsInt("xml/coupon_refund_count_" + i)); refundRecord.setRefundStatus(this.getXmlValue("xml/refund_status_" + i)); refundRecord.setRefundRecvAccount(this.getXmlValue("xml/refund_recv_accout_" + i)); + refundRecord.setRefundSuccessTime(this.getXmlValue("xml/refund_success_time_" + i)); if (refundRecord.getCouponRefundCount() == null || refundRecord.getCouponRefundCount() == 0) { continue; @@ -147,10 +156,13 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { coupons.add( new RefundRecord.RefundCoupon( this.getXmlValue("xml/coupon_refund_id_" + i + "_" + j), - this.getXmlValueAsInt("xml/coupon_refund_fee_" + i + "_" + j) + this.getXmlValueAsInt("xml/coupon_refund_fee_" + i + "_" + j), + this.getXmlValue("xml/coupon_type_" + i + "_" + j) ) ); } + + refundRecord.setRefundCoupons(coupons); } } @@ -163,12 +175,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { public static class RefundRecord { /** *
    -     * 商户退款单号
    -     * out_refund_no_$n
    -     * 是
    -     * String(32)
    -     * 1217752501201407033233368018
    -     * 商户退款单号
    +     * 字段名:商户退款单号.
    +     * 变量名:out_refund_no_$n
    +     * 是否必填:是
    +     * 类型:String(32)
    +     * 示例值:1217752501201407033233368018
    +     * 描述:商户退款单号
          * 
    */ @XStreamAlias("out_refund_no") @@ -176,12 +188,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 微信退款单号
    -     * refund_id_$n
    -     * 是
    -     * String(28)
    -     * 1217752501201407033233368018
    -     * 微信退款单号
    +     * 字段名:微信退款单号.
    +     * 变量名:refund_id_$n
    +     * 是否必填:是
    +     * 类型:String(28)
    +     * 示例值:1217752501201407033233368018
    +     * 描述:微信退款单号
          * 
    */ @XStreamAlias("refund_id") @@ -189,12 +201,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 退款渠道
    -     * refund_channel_$n
    -     * 否
    -     * String(16)
    -     * ORIGINAL
    -     * ORIGINAL—原路退款 BALANCE—退回到余额
    +     * 字段名:退款渠道.
    +     * 变量名:refund_channel_$n
    +     * 是否必填:否
    +     * 类型:String(16)
    +     * 示例值:ORIGINAL
    +     * 描述:ORIGINAL—原路退款 BALANCE—退回到余额
          * 
    */ @XStreamAlias("refund_channel") @@ -202,12 +214,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 申请退款金额
    -     * refund_fee_$n
    -     * 是
    -     * Int
    -     * 100
    -     * 退款总金额,单位为分,可以做部分退款
    +     * 字段名:申请退款金额.
    +     * 变量名:refund_fee_$n
    +     * 是否必填:是
    +     * 类型:Int
    +     * 示例值:100
    +     * 描述:退款总金额,单位为分,可以做部分退款
          * 
    */ @XStreamAlias("refund_fee") @@ -215,12 +227,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 退款金额
    -     * settlement_refund_fee_$n
    -     * 否
    -     * Int
    -     * 100
    -     * 退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额
    +     * 字段名:退款金额.
    +     * 变量名:settlement_refund_fee_$n
    +     * 是否必填:否
    +     * 类型:Int
    +     * 示例值:100
    +     * 描述:退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额
          * 
    */ @XStreamAlias("settlement_refund_fee") @@ -228,12 +240,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 退款资金来源
    -     * refund_account
    -     * 否
    -     * String(30)
    -     * REFUND_SOURCE_RECHARGE_FUNDS
    -     * REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款/基本账户, REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款
    +     * 字段名:退款资金来源.
    +     * 变量名:refund_account
    +     * 是否必填:否
    +     * 类型:String(30)
    +     * 示例值:REFUND_SOURCE_RECHARGE_FUNDS
    +     * 描述:REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款/基本账户, REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款
          * 
    */ @XStreamAlias("refund_account") @@ -241,25 +253,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 代金券类型
    -     * coupon_type_$n
    -     * 否
    -     * Int
    -     * CASH
    -     * CASH--充值代金券 , NO_CASH---非充值代金券。订单使用代金券时有返回(取值:CASH、NO_CASH)。$n为下标,从0开始编号,举例:coupon_type_$0
    -     * 
    - */ - @XStreamAlias("coupon_type") - private String couponType; - - /** - *
    -     * 代金券退款金额
    -     * coupon_refund_fee_$n
    -     * 否
    -     * Int
    -     * 100
    -     * 代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠
    +     * 字段名:代金券退款金额.
    +     * 变量名:coupon_refund_fee_$n
    +     * 是否必填:否
    +     * 类型:Int
    +     * 示例值:100
    +     * 描述:代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠
          * 
    */ @XStreamAlias("coupon_refund_fee") @@ -267,12 +266,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 退款代金券使用数量
    -     * coupon_refund_count_$n
    -     * 否
    -     * Int
    -     * 1
    -     * 退款代金券使用数量 ,$n为下标,从0开始编号
    +     * 字段名:退款代金券使用数量.
    +     * 变量名:coupon_refund_count_$n
    +     * 是否必填:否
    +     * 类型:Int
    +     * 示例值:1
    +     * 描述:退款代金券使用数量 ,$n为下标,从0开始编号
          * 
    */ @XStreamAlias("coupon_refund_count") @@ -282,12 +281,12 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { /** *
    -     * 退款状态
    -     * refund_status_$n
    -     * 是
    -     * String(16)
    -     * SUCCESS
    -     * 退款状态:
    +     * 字段名:退款状态.
    +     * 变量名:refund_status_$n
    +     * 是否必填:是
    +     * 类型:String(16)
    +     * 示例值:SUCCESS
    +     * 描述:退款状态:
          *  SUCCESS—退款成功,
          *  FAIL—退款失败,
          *  PROCESSING—退款处理中,
    @@ -297,67 +296,78 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
          */
         @XStreamAlias("refund_status")
         private String refundStatus;
    +
         /**
          * 
    -     * 退款入账账户
    -     * refund_recv_accout_$n
    -     * 是
    -     * String(64)
    -     * 招商银行信用卡0403
    -     * 取当前退款单的退款入账方,1)退回银行卡:{银行名称}{卡类型}{卡尾号},2)退回支付用户零钱:支付用户零钱
    +     * 字段名:退款入账账户.
    +     * 变量名:refund_recv_accout_$n
    +     * 是否必填:是
    +     * 类型:String(64)
    +     * 示例值:招商银行信用卡0403
    +     * 描述:取当前退款单的退款入账方,1)退回银行卡:{银行名称}{卡类型}{卡尾号},2)退回支付用户零钱:支付用户零钱
          * 
    */ @XStreamAlias("refund_recv_accout") private String refundRecvAccount; + /** + *
    +     * 字段名:退款成功时间.
    +     * 变量名:refund_success_time_$n
    +     * 是否必填:否
    +     * 类型:String(20)
    +     * 示例值:2016-07-25 15:26:26
    +     * 描述:退款成功时间,当退款状态为退款成功时有返回。$n为下标,从0开始编号。
    +     * 
    + */ + @XStreamAlias("refund_success_time") + private String refundSuccessTime; + @Data @NoArgsConstructor + @AllArgsConstructor public static class RefundCoupon { /** *
    -       * 退款代金券批次ID
    -       * coupon_refund_batch_id_$n_$m
    -       * 否
    -       * String(20)
    -       * 100
    -       * 退款代金券批次ID ,$n为下标,$m为下标,从0开始编号
    +       * 字段名:退款代金券ID.
    +       * 变量名:coupon_refund_id_$n_$m
    +       * 是否必填:否
    +       * 类型:String(20)
    +       * 示例值:10000
    +       * 描述:退款代金券ID, $n为下标,$m为下标,从0开始编号
            * 
    - * - * @deprecated 貌似是被去掉了,但不知是何时! */ - @XStreamAlias("coupon_refund_batch_id") - private String couponRefundBatchId; + @XStreamAlias("coupon_refund_id") + private String couponRefundId; /** *
    -       * 退款代金券ID
    -       * coupon_refund_id_$n_$m
    -       * 否
    -       * String(20)
    -       * 10000
    -       * 退款代金券ID, $n为下标,$m为下标,从0开始编号
    +       * 字段名:单个退款代金券支付金额.
    +       * 变量名:coupon_refund_fee_$n_$m
    +       * 是否必填:否
    +       * 类型:Int
    +       * 示例值:100
    +       * 描述:单个退款代金券支付金额, $n为下标,$m为下标,从0开始编号
            * 
    */ - @XStreamAlias("coupon_refund_id") - private String couponRefundId; + @XStreamAlias("coupon_refund_fee") + private Integer couponRefundFee; /** *
    -       * 单个退款代金券支付金额
    -       * coupon_refund_fee_$n_$m
    -       * 否
    -       * Int
    -       * 100
    -       * 单个退款代金券支付金额, $n为下标,$m为下标,从0开始编号
    +       * 字段名:代金券类型.
    +       * 变量名:coupon_type_$n_$m
    +       * 是否必填:否
    +       * 类型:String(8)
    +       * 示例值:CASH
    +       * 描述:CASH--充值代金券 , NO_CASH---非充值代金券。
    +       * 开通免充值券功能,并且订单使用了优惠券后有返回(取值:CASH、NO_CASH)。
    +       * $n为下标,$m为下标,从0开始编号,举例:coupon_type_$0_$1
            * 
    */ - @XStreamAlias("coupon_refund_fee") - private Integer couponRefundFee; + @XStreamAlias("coupon_type") + private String couponType; - public RefundCoupon(String couponRefundId, Integer couponRefundFee) { - this.couponRefundId = couponRefundId; - this.couponRefundFee = couponRefundFee; - } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundResult.java index 2da31a37..5dde2c90 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayRefundResult.java @@ -19,7 +19,7 @@ import java.io.Serializable; @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @XStreamAlias("xml") -public class WxPayRefundResult extends WxPayBaseResult implements Serializable { +public class WxPayRefundResult extends BaseWxPayResult implements Serializable { private static final long serialVersionUID = 1L; @XStreamAlias("device_info") diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySandboxSignKeyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySandboxSignKeyResult.java index 792e00fd..cf3f9355 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySandboxSignKeyResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySandboxSignKeyResult.java @@ -16,7 +16,7 @@ import lombok.NoArgsConstructor; @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @XStreamAlias("xml") -public class WxPaySandboxSignKeyResult extends WxPayBaseResult { +public class WxPaySandboxSignKeyResult extends BaseWxPayResult { /** *
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySendRedpackResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySendRedpackResult.java
    index 560721f5..2855daef 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySendRedpackResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPaySendRedpackResult.java
    @@ -17,7 +17,7 @@ import java.io.Serializable;
     @EqualsAndHashCode(callSuper = true)
     @NoArgsConstructor
     @XStreamAlias("xml")
    -public class WxPaySendRedpackResult extends WxPayBaseResult implements Serializable {
    +public class WxPaySendRedpackResult extends BaseWxPayResult implements Serializable {
       private static final long serialVersionUID = -4837415036337132073L;
     
       @XStreamAlias("mch_billno")
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayShorturlResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayShorturlResult.java
    index 93e74a0c..1937004f 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayShorturlResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayShorturlResult.java
    @@ -17,7 +17,7 @@ import lombok.NoArgsConstructor;
     @EqualsAndHashCode(callSuper = true)
     @NoArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayShorturlResult extends WxPayBaseResult {
    +public class WxPayShorturlResult extends BaseWxPayResult {
       /**
        * 
        * URL链接
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java
    index 4f25421f..cf97f75a 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java
    @@ -17,7 +17,7 @@ import lombok.NoArgsConstructor;
     @EqualsAndHashCode(callSuper = true)
     @NoArgsConstructor
     @XStreamAlias("xml")
    -public class WxPayUnifiedOrderResult extends WxPayBaseResult {
    +public class WxPayUnifiedOrderResult extends BaseWxPayResult {
     
       /**
        * 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
    index 8e9eea95..9dbe9d05 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java
    @@ -1,10 +1,12 @@
     package com.github.binarywang.wxpay.constant;
     
    -import com.google.common.collect.Lists;
    -
    -import java.text.SimpleDateFormat;
    +import java.text.Format;
     import java.util.List;
     
    +import org.apache.commons.lang3.time.FastDateFormat;
    +
    +import com.google.common.collect.Lists;
    +
     /**
      * 
      * 微信支付常量类
    @@ -16,85 +18,96 @@ import java.util.List;
     public class WxPayConstants {
     
       /**
    -   * 拉取订单评价数据接口的参数中日期格式
    +   * 拉取订单评价数据接口的参数中日期格式.
        */
    -  public static final SimpleDateFormat QUERY_COMMENT_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
    +  public static final Format QUERY_COMMENT_DATE_FORMAT =  FastDateFormat.getInstance("yyyyMMddHHmmss");
     
       /**
    -   * 校验用户姓名选项,企业付款时使用
    +   * 校验用户姓名选项,企业付款时使用.
        */
       public static class CheckNameOption {
         /**
    -     * 不校验真实姓名
    +     * 不校验真实姓名.
          */
         public static final String NO_CHECK = "NO_CHECK";
     
         /**
    -     * 强校验真实姓名
    +     * 强校验真实姓名.
          */
         public static final String FORCE_CHECK = "FORCE_CHECK";
       }
     
       /**
    -   * 订单类型
    +   * 压缩账单的类型.
    +   */
    +  public static class TarType {
    +    /**
    +     * 固定值:GZIP,返回格式为.gzip的压缩包账单.
    +     */
    +    public static final String GZIP = "GZIP";
    +  }
    +
    +  /**
    +   * 账单类型.
        */
       public static class BillType {
         /**
    -     * 查询红包时使用:通过商户订单号获取红包信息
    +     * 查询红包时使用:通过商户订单号获取红包信息.
          */
         public static final String MCHT = "MCHT";
     
         //以下为下载对账单时的账单类型
         /**
    -     * 返回当日所有订单信息,默认值
    +     * 返回当日所有订单信息,默认值.
          */
         public static final String ALL = "ALL";
         /**
    -     * 返回当日成功支付的订单
    +     * 返回当日成功支付的订单.
          */
         public static final String SUCCESS = "SUCCESS";
         /**
    -     * 返回当日退款订单
    +     * 返回当日退款订单.
          */
         public static final String REFUND = "REFUND";
         /**
    -     * 返回当日充值退款订单(相比其他对账单多一栏“返还手续费”)
    +     * 返回当日充值退款订单(相比其他对账单多一栏“返还手续费”).
          */
         public static final String RECHARGE_REFUND = "RECHARGE_REFUND";
       }
     
       /**
    -   * 交易类型
    +   * 交易类型.
        */
       public static class TradeType {
         /**
    -     * 原生扫码支付
    +     * 原生扫码支付.
          */
         public static final String NATIVE = "NATIVE";
     
         /**
    -     * App支付
    +     * App支付.
          */
         public static final String APP = "APP";
     
         /**
    -     * 公众号支付
    +     * 公众号支付.
          */
         public static final String JSAPI = "JSAPI";
     
         /**
    -     * H5支付
    +     * H5支付.
          */
         public static final String MWEB = "MWEB";
     
         /**
    -     * 刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口
    +     * 刷卡支付.
    +     * 刷卡支付有单独的支付接口,不调用统一下单接口
          */
         public static final String MICROPAY = "MICROPAY";
       }
     
       /**
    -   * 签名类型
    +   * 签名类型.
        */
       public static class SignType {
         public static final String HMAC_SHA256 = "HMAC-SHA256";
    @@ -103,177 +116,178 @@ public class WxPayConstants {
       }
     
       /**
    -   * 限定支付方式
    +   * 限定支付方式.
        */
       public static class LimitPay {
         /**
    -     * no_credit--指定不能使用信用卡支付
    +     * no_credit--指定不能使用信用卡支付.
          */
         public static final String NO_CREDIT = "no_credit";
       }
     
       /**
    -   * 业务结果代码
    +   * 业务结果代码.
        */
       public static class ResultCode {
         /**
    -     * 成功
    +     * 成功.
          */
         public static final String SUCCESS = "SUCCESS";
     
         /**
    -     * 失败
    +     * 失败.
          */
         public static final String FAIL = "FAIL";
       }
     
       /**
    -   * 退款资金来源
    +   * 退款资金来源.
        */
       public static class RefundAccountSource {
         /**
    -     * 可用余额退款/基本账户
    +     * 可用余额退款/基本账户.
          */
         public static final String RECHARGE_FUNDS = "REFUND_SOURCE_RECHARGE_FUNDS";
     
         /**
    -     * 未结算资金退款
    +     * 未结算资金退款.
          */
         public static final String UNSETTLED_FUNDS = "REFUND_SOURCE_UNSETTLED_FUNDS";
     
       }
     
       /**
    -   * 退款渠道
    +   * 退款渠道.
        */
       public static class RefundChannel {
         /**
    -     * 原路退款
    +     * 原路退款.
          */
         public static final String ORIGINAL = "ORIGINAL";
     
         /**
    -     * 退回到余额
    +     * 退回到余额.
          */
         public static final String BALANCE = "BALANCE";
     
         /**
    -     * 原账户异常退到其他余额账户
    +     * 原账户异常退到其他余额账户.
          */
         public static final String OTHER_BALANCE = "OTHER_BALANCE";
     
         /**
    -     * 原银行卡异常退到其他银行卡
    +     * 原银行卡异常退到其他银行卡.
          */
         public static final String OTHER_BANKCARD = "OTHER_BANKCARD";
       }
     
       /**
    -   * 交易状态
    +   * 交易状态.
        */
       public static class WxpayTradeStatus {
         /**
    -     * 支付成功
    +     * 支付成功.
          */
         public static final String SUCCESS = "SUCCESS";
     
         /**
    -     * 支付失败(其他原因,如银行返回失败)
    +     * 支付失败(其他原因,如银行返回失败).
          */
         public static final String PAY_ERROR = "PAYERROR";
     
         /**
    -     * 用户支付中
    +     * 用户支付中.
          */
         public static final String USER_PAYING = "USERPAYING";
     
         /**
    -     * 已关闭
    +     * 已关闭.
          */
         public static final String CLOSED = "CLOSED";
     
         /**
    -     * 未支付
    +     * 未支付.
          */
         public static final String NOTPAY = "NOTPAY";
     
         /**
    -     * 转入退款
    +     * 转入退款.
          */
         public static final String REFUND = "REFUND";
     
         /**
    -     * 已撤销(刷卡支付)
    +     * 已撤销(刷卡支付).
          */
         public static final String REVOKED = "REVOKED";
       }
     
       /**
    -   * 退款状态
    +   * 退款状态.
        */
       public static class RefundStatus {
         /**
    -     * 退款成功
    +     * 退款成功.
          */
         public static final String SUCCESS = "SUCCESS";
     
         /**
    -     * 退款关闭
    +     * 退款关闭.
          */
         public static final String REFUND_CLOSE = "REFUNDCLOSE";
     
         /**
    -     * 退款处理中
    +     * 退款处理中.
          */
         public static final String PROCESSING = "PROCESSING";
     
         /**
    -     * 退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台(pay.weixin.qq.com)-交易中心,手动处理此笔退款。
    +     * 退款异常.
    +     * 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台(pay.weixin.qq.com)-交易中心,手动处理此笔退款。
          */
         public static final String CHANGE = "CHANGE";
       }
     
       /**
    -   * 关闭订单结果错误代码
    +   * 关闭订单结果错误代码.
        */
       public static class OrderCloseResultErrorCode {
         /**
    -     * 订单已支付
    +     * 订单已支付.
          */
         public static final String ORDER_PAID = "ORDERPAID";
     
         /**
    -     * 系统错误
    +     * 系统错误.
          */
         public static final String SYSTEM_ERROR = "SYSTEMERROR";
     
         /**
    -     * 订单不存在
    +     * 订单不存在.
          */
         public static final String ORDER_NOT_EXIST = "ORDERNOTEXIST";
     
         /**
    -     * 订单已关闭
    +     * 订单已关闭.
          */
         public static final String ORDER_CLOSED = "ORDERCLOSED";
     
         /**
    -     * 签名错误
    +     * 签名错误.
          */
         public static final String SIGN_ERROR = "SIGNERROR";
     
         /**
    -     * 未使用POST传递参数
    +     * 未使用POST传递参数.
          */
         public static final String REQUIRE_POST_METHOD = "REQUIRE_POST_METHOD";
     
         /**
    -     * XML格式错误
    +     * XML格式错误.
          */
         public static final String XML_FORMAT_ERROR = "XML_FORMAT_ERROR";
     
         /**
    -     * 订单状态错误
    +     * 订单状态错误.
          */
         public static final String TRADE_STATE_ERROR = "TRADE_STATE_ERROR";
       }
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java
    index fe35ed21..0498520a 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java
    @@ -57,11 +57,11 @@ public class WxPayOrderNotifyResultConverter extends AbstractReflectionConverter
     
       @Override
       protected void marshallField(MarshallingContext context, Object newObj, Field field) {
    -    if (field.getName().equals("couponList")) {
    +    if ("couponList".equals(field.getName())) {
           return;
    -    } else {
    -      super.marshallField(context, newObj, field);
         }
    +
    +    super.marshallField(context, newObj, field);
       }
     
       @Override
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/exception/WxPayException.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/exception/WxPayException.java
    index 948c7a49..5c7335d1 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/exception/WxPayException.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/exception/WxPayException.java
    @@ -1,6 +1,6 @@
     package com.github.binarywang.wxpay.exception;
     
    -import com.github.binarywang.wxpay.bean.result.WxPayBaseResult;
    +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
     import com.google.common.base.Joiner;
     
     /**
    @@ -60,7 +60,7 @@ public class WxPayException extends Exception {
         xmlString = builder.xmlString;
       }
     
    -  public static WxPayException from(WxPayBaseResult payBaseResult) {
    +  public static WxPayException from(BaseWxPayResult payBaseResult) {
         return WxPayException.newBuilder()
           .xmlString(payBaseResult.getXmlString())
           .returnMsg(payBaseResult.getReturnMsg())
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EntPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EntPayService.java
    new file mode 100644
    index 00000000..4ab7f31b
    --- /dev/null
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EntPayService.java
    @@ -0,0 +1,84 @@
    +package com.github.binarywang.wxpay.service;
    +
    +import com.github.binarywang.wxpay.bean.entpay.*;
    +import com.github.binarywang.wxpay.exception.WxPayException;
    +
    +/**
    + * 
    + *  企业付款相关服务类.
    + *  Created by BinaryWang on 2017/12/19.
    + * 
    + * + * @author Binary Wang + */ +public interface EntPayService { + /** + *
    +   * 企业付款API.
    +   * 企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。
    +   * 比如目前的保险行业向客户退保、给付、理赔。
    +   * 企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”https://pay.weixin.qq.com/进行操作。
    +   * 注意:与商户微信支付收款资金并非同一账户,需要单独充值。
    +   * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
    +   * 接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
    +   * 
    + * + * @param request 请求对象 + */ + EntPayResult entPay(EntPayRequest request) throws WxPayException; + + /** + *
    +   * 查询企业付款API.
    +   * 用于商户的企业付款操作进行结果查询,返回付款操作详细结果。
    +   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
    +   * 接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo
    +   * 
    + * + * @param partnerTradeNo 商户订单号 + */ + EntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException; + + /** + *
    +   * 获取RSA加密公钥API.
    +   * RSA算法使用说明(非对称加密算法,算法采用RSA/ECB/OAEPPadding模式)
    +   * 1、 调用获取RSA公钥API获取RSA公钥,落地成本地文件,假设为public.pem
    +   * 2、 确定public.pem文件的存放路径,同时修改代码中文件的输入路径,加载RSA公钥
    +   * 3、 用标准的RSA加密库对敏感信息进行加密,选择RSA_PKCS1_OAEP_PADDING填充模式
    +   * (eg:Java的填充方式要选 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING")
    +   * 4、 得到进行rsa加密并转base64之后的密文
    +   * 5、 将密文传给微信侧相应字段,如付款接口(enc_bank_no/enc_true_name)
    +   *
    +   * 接口默认输出PKCS#1格式的公钥,商户需根据自己开发的语言选择公钥格式
    +   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
    +   * 接口链接:https://fraud.mch.weixin.qq.com/risk/getpublickey
    +   * 
    + */ + String getPublicKey() throws WxPayException; + + /** + * 企业付款到银行卡. + *
    +   * 用于企业向微信用户银行卡付款
    +   * 目前支持接口API的方式向指定微信用户的银行卡付款。
    +   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2
    +   * 接口链接:https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
    +   * 
    + * + * @param request 请求对象 + */ + EntPayBankResult payBank(EntPayBankRequest request) throws WxPayException; + + /** + * 企业付款到银行卡查询. + *
    +   * 用于对商户企业付款到银行卡操作进行结果查询,返回付款操作详细结果。
    +   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3
    +   * 接口链接:https://api.mch.weixin.qq.com/mmpaysptrans/query_bank
    +   * 
    + * + * @param partnerTradeNo 商户订单号 + */ + EntPayBankQueryResult queryPayBank(String partnerTradeNo) throws WxPayException; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 33cd56c6..dbe23df1 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -1,21 +1,43 @@ package com.github.binarywang.wxpay.service; +import java.io.File; +import java.util.Date; +import java.util.Map; + import com.github.binarywang.wxpay.bean.WxPayApiData; -import com.github.binarywang.wxpay.bean.coupon.*; +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryRequest; +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryResult; +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendRequest; +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendResult; +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryRequest; +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryResult; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; -import com.github.binarywang.wxpay.bean.request.*; -import com.github.binarywang.wxpay.bean.result.*; +import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult; +import com.github.binarywang.wxpay.bean.request.WxPayAuthcode2OpenidRequest; +import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest; +import com.github.binarywang.wxpay.bean.request.WxPayOrderReverseRequest; +import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; +import com.github.binarywang.wxpay.bean.request.WxPayReportRequest; +import com.github.binarywang.wxpay.bean.request.WxPaySendRedpackRequest; +import com.github.binarywang.wxpay.bean.request.WxPayShorturlRequest; +import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; +import com.github.binarywang.wxpay.bean.result.WxPayBillResult; +import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult; +import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult; +import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult; +import com.github.binarywang.wxpay.bean.result.WxPayOrderReverseResult; +import com.github.binarywang.wxpay.bean.result.WxPayRedpackQueryResult; +import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult; +import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; +import com.github.binarywang.wxpay.bean.result.WxPaySendRedpackResult; +import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.exception.WxPayException; -import java.io.File; -import java.util.Date; -import java.util.Map; - /** *
    - * 微信支付相关接口
    + * 微信支付相关接口.
      * Created by Binary Wang on 2016/7/28.
      * 
    * @@ -23,9 +45,45 @@ import java.util.Map; */ public interface WxPayService { + /** + * 获取微信支付请求url前缀,沙箱环境可能不一样. + */ + String getPayBaseUrl(); + + /** + * 发送post请求,得到响应字节数组. + * + * @param url 请求地址 + * @param requestStr 请求信息 + * @param useKey 是否使用证书 + * @return 返回请求结果字节数组 + */ + byte[] postForBytes(String url, String requestStr, boolean useKey) throws WxPayException; + + /** + * 发送post请求,得到响应字符串. + * + * @param url 请求地址 + * @param requestStr 请求信息 + * @param useKey 是否使用证书 + * @return 返回请求结果字符串 + */ + String post(String url, String requestStr, boolean useKey) throws WxPayException; + + /** + * 获取企业付款服务类. + */ + EntPayService getEntPayService(); + + /** + * 设置企业付款服务类,允许开发者自定义实现类. + */ + void setEntPayService(EntPayService entPayService); + /** *
    -   * 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
    +   * 查询订单.
    +   * 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
        * 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
        * 需要调用查询接口的情况:
        * ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
    @@ -42,7 +100,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 关闭订单
    +   * 关闭订单.
        * 应用场景
        * 以下情况需要调用关单接口:
        * 1. 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
    @@ -57,7 +115,7 @@ public interface WxPayService {
       WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException;
     
       /**
    -   * 调用统一下单接口,并组装生成支付所需参数对象
    +   * 调用统一下单接口,并组装生成支付所需参数对象.
        *
        * @param request 统一下单请求参数
        * @param      请使用{@link com.github.binarywang.wxpay.bean.order}包下的类
    @@ -75,7 +133,7 @@ public interface WxPayService {
       WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException;
     
       /**
    -   * 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数
    +   * 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数.
        * 详见https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
        *
        * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置)
    @@ -85,18 +143,18 @@ public interface WxPayService {
       Map getPayInfo(WxPayUnifiedOrderRequest request) throws WxPayException;
     
       /**
    -   * 获取配置
    +   * 获取配置.
        */
       WxPayConfig getConfig();
     
       /**
    -   * 设置配置对象
    +   * 设置配置对象.
        */
       void setConfig(WxPayConfig config);
     
       /**
        * 
    -   * 微信支付-申请退款
    +   * 微信支付-申请退款.
        * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
        * 接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund
        * 
    @@ -108,7 +166,7 @@ public interface WxPayService { /** *
    -   * 微信支付-查询退款
    +   * 微信支付-查询退款.
        * 应用场景:
        *  提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,
        *  银行卡支付的退款3个工作日后重新查询退款状态。
    @@ -127,14 +185,14 @@ public interface WxPayService {
         throws WxPayException;
     
       /**
    -   * @see WxPayService#parseOrderNotifyResult(String)
    +   * @see WxPayService#parseOrderNotifyResult(String).
        * @deprecated use {@link WxPayService#parseOrderNotifyResult(String)} instead
        */
       @Deprecated
       WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayException;
     
       /**
    -   * 解析支付结果通知
    +   * 解析支付结果通知.
        * 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
        */
       WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) throws WxPayException;
    @@ -146,7 +204,13 @@ public interface WxPayService {
       WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) throws WxPayException;
     
       /**
    -   * 发送微信红包给个人用户
    +   * 解析扫码支付回调通知
    +   * 详见https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
    +   */
    +  WxScanPayNotifyResult parseScanPayNotifyResult(String xmlData) throws WxPayException;
    +
    +  /**
    +   * 发送微信红包给个人用户.
        * 
        * 文档详见:
        * 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
    @@ -161,11 +225,11 @@ public interface WxPayService {
     
       /**
        * 
    -   *   查询红包记录
    +   *   查询红包记录.
        *   用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包。
    -   *   请求Url	https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
    -   *   是否需要证书	是(证书及使用说明详见商户证书)
    -   *   请求方式	POST
    +   *   请求Url:https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
    +   *   是否需要证书:是(证书及使用说明详见商户证书)
    +   *   请求方式:POST
        * 
    * * @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890 @@ -174,33 +238,7 @@ public interface WxPayService { /** *
    -   * 企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。
    -   * 比如目前的保险行业向客户退保、给付、理赔。
    -   * 企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”https://pay.weixin.qq.com/进行操作。
    -   * 注意:与商户微信支付收款资金并非同一账户,需要单独充值。
    -   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
    -   * 接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
    -   * 
    - * - * @param request 请求对象 - */ - WxEntPayResult entPay(WxEntPayRequest request) throws WxPayException; - - /** - *
    -   * 查询企业付款API
    -   * 用于商户的企业付款操作进行结果查询,返回付款操作详细结果。
    -   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
    -   * 接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo
    -   * 
    - * - * @param partnerTradeNo 商户订单号 - */ - WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException; - - /** - *
    -   * 扫码支付模式一生成二维码的方法
    +   * 扫码支付模式一生成二维码的方法。
        * 二维码中的内容为链接,形式为:
        * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
        * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。
    @@ -216,7 +254,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 扫码支付模式一生成二维码的方法
    +   * 扫码支付模式一生成二维码的方法.
        * 二维码中的内容为链接,形式为:
        * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
        * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。
    @@ -230,7 +268,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 扫码支付模式二生成二维码的方法
    +   * 扫码支付模式二生成二维码的方法.
        * 对应链接格式:weixin://wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。
        * 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。
        * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
    @@ -245,7 +283,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 交易保障
    +   * 交易保障.
        * 应用场景:
        *  商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。
        *  为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口,
    @@ -258,7 +296,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 下载对账单
    +   * 下载对账单.
        * 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。
        * 注意:
        * 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED;
    @@ -269,17 +307,17 @@ public interface WxPayService {
        * 详情请见: 下载对账单
        * 
    * - * @param billDate 对账单日期 bill_date 下载对账单的日期,格式:20140603 - * @param billType 账单类型 bill_type ALL,返回当日所有订单信息,默认值,SUCCESS,返回当日成功支付的订单,REFUND,返回当日退款订单 - * @param tarType 压缩账单 tar_type 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 - * @param deviceInfo 设备号 device_info 非必传参数,终端设备号 + * @param billDate 对账单日期 bill_date 下载对账单的日期,格式:20140603 + * @param billType 账单类型 bill_type ALL,返回当日所有订单信息,默认值,SUCCESS,返回当日成功支付的订单,REFUND,返回当日退款订单 + * @param tarType 压缩账单 tar_type 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 + * @param deviceInfo 设备号 device_info 非必传参数,终端设备号 * @return 保存到本地的临时文件 */ WxPayBillResult downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxPayException; /** *
    -   * 提交刷卡支付
    +   * 提交刷卡支付.
        * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
        * 应用场景:
        * 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付。
    @@ -293,7 +331,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 撤销订单API
    +   * 撤销订单API.
        * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
        * 应用场景:
        *  支付交易返回失败或支付系统超时,调用该接口撤销交易。如果此订单用户支付失败,微信支付系统会将此订单关闭;
    @@ -309,7 +347,7 @@ public interface WxPayService {
     
       /**
        * 
    -   *  转换短链接
    +   *  转换短链接.
        *  文档地址:
        *     https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8
        *  应用场景:
    @@ -324,7 +362,7 @@ public interface WxPayService {
     
       /**
        * 
    -   *  转换短链接
    +   *  转换短链接.
        * 
    * * @param longUrl 需要被压缩的网址 @@ -334,7 +372,7 @@ public interface WxPayService { /** *
    -   * 授权码查询OPENID接口
    +   * 授权码查询OPENID接口.
        *    通过授权码查询公众号Openid,调用查询后,该授权码只能由此商户号发起扣款,直至授权码更新。
        * 文档地址:
        *    https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9
    @@ -349,7 +387,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 授权码查询OPENID接口
    +   * 授权码查询OPENID接口.
        * 
    * * @param authCode 授权码 @@ -360,7 +398,7 @@ public interface WxPayService { /** *
    -   * 获取仿真测试系统的验签密钥
    +   * 获取仿真测试系统的验签密钥.
        * 请求Url: https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey
        * 是否需要证书: 否
        * 请求方式: POST
    @@ -381,7 +419,7 @@ public interface WxPayService {
     
       /**
        * 
    -   * 查询代金券批次
    +   * 查询代金券批次.
        * 接口请求链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/query_coupon_stock
        * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_4
        * 
    @@ -390,7 +428,7 @@ public interface WxPayService { /** *
    -   * 查询代金券信息
    +   * 查询代金券信息.
        * 接口请求链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/querycouponsinfo
        * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_5
        * 
    @@ -398,13 +436,13 @@ public interface WxPayService { WxPayCouponInfoQueryResult queryCouponInfo(WxPayCouponInfoQueryRequest request) throws WxPayException; /** - * 获取微信请求数据,方便接口调用方获取处理 + * 获取微信请求数据,方便接口调用方获取处理. */ WxPayApiData getWxApiData(); /** *
    -   * 拉取订单评价数据
    +   * 拉取订单评价数据.
        * 商户可以通过该接口拉取用户在微信支付交易记录中针对你的支付记录进行的评价内容。商户可结合商户系统逻辑对该内容数据进行存储、分析、展示、客服回访以及其他使用。如商户业务对评价内容有依赖,可主动引导用户进入微信支付交易记录进行评价。
        * 注意:
        * 1. 该内容所有权为提供内容的微信用户,商户在使用内容的过程中应遵从用户意愿
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
    similarity index 73%
    rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java
    rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
    index 0eccb727..25d82850 100644
    --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
    @@ -1,31 +1,81 @@
     package com.github.binarywang.wxpay.service.impl;
     
    +import java.io.File;
    +import java.io.IOException;
    +import java.nio.charset.StandardCharsets;
    +import java.nio.file.Files;
    +import java.nio.file.Path;
    +import java.nio.file.Paths;
    +import java.util.Date;
    +import java.util.HashMap;
    +import java.util.LinkedList;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.zip.ZipException;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
    +
     import com.github.binarywang.utils.qrcode.QrcodeUtils;
     import com.github.binarywang.wxpay.bean.WxPayApiData;
    -import com.github.binarywang.wxpay.bean.coupon.*;
    +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryRequest;
    +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryResult;
    +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendRequest;
    +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendResult;
    +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryRequest;
    +import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryResult;
     import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
     import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
    +import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
     import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
     import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
     import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
    -import com.github.binarywang.wxpay.bean.request.*;
    -import com.github.binarywang.wxpay.bean.result.*;
    +import com.github.binarywang.wxpay.bean.request.WxPayAuthcode2OpenidRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayDefaultRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayDownloadBillRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayOrderCloseRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayOrderReverseRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayQueryCommentRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayRedpackQueryRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayRefundQueryRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayReportRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPaySendRedpackRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayShorturlRequest;
    +import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
    +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayAuthcode2OpenidResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayBillBaseResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayBillResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayCommonResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayOrderReverseResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayRedpackQueryResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
    +import com.github.binarywang.wxpay.bean.result.WxPaySandboxSignKeyResult;
    +import com.github.binarywang.wxpay.bean.result.WxPaySendRedpackResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayShorturlResult;
    +import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
     import com.github.binarywang.wxpay.config.WxPayConfig;
     import com.github.binarywang.wxpay.constant.WxPayConstants.BillType;
     import com.github.binarywang.wxpay.constant.WxPayConstants.SignType;
     import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType;
     import com.github.binarywang.wxpay.exception.WxPayException;
    +import com.github.binarywang.wxpay.service.EntPayService;
     import com.github.binarywang.wxpay.service.WxPayService;
     import com.github.binarywang.wxpay.util.SignUtils;
    +import com.google.common.base.Joiner;
     import com.google.common.collect.Maps;
    -import org.apache.commons.lang3.StringUtils;
    -import org.slf4j.Logger;
    -import org.slf4j.LoggerFactory;
    -
    -import java.io.File;
    -import java.util.*;
    +import jodd.io.ZipUtil;
     
     import static com.github.binarywang.wxpay.constant.WxPayConstants.QUERY_COMMENT_DATE_FORMAT;
    +import static com.github.binarywang.wxpay.constant.WxPayConstants.TarType;
     
     /**
      * 
    @@ -35,13 +85,25 @@ import static com.github.binarywang.wxpay.constant.WxPayConstants.QUERY_COMMENT_
      *
      * @author Binary Wang
      */
    -public abstract class WxPayServiceAbstractImpl implements WxPayService {
    +public abstract class BaseWxPayServiceImpl implements WxPayService {
       private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
       protected final Logger log = LoggerFactory.getLogger(this.getClass());
       protected static ThreadLocal wxApiData = new ThreadLocal<>();
     
    +  private EntPayService entPayService = new EntPayServiceImpl(this);
    +
       protected WxPayConfig config;
     
    +  @Override
    +  public EntPayService getEntPayService() {
    +    return entPayService;
    +  }
    +
    +  @Override
    +  public void setEntPayService(EntPayService entPayService) {
    +    this.entPayService = entPayService;
    +  }
    +
       @Override
       public WxPayConfig getConfig() {
         return this.config;
    @@ -52,7 +114,8 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         this.config = config;
       }
     
    -  private String getPayBaseUrl() {
    +  @Override
    +  public String getPayBaseUrl() {
         if (this.getConfig().useSandbox()) {
           return PAY_BASE_URL + "/sandboxnew";
         }
    @@ -60,23 +123,13 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         return PAY_BASE_URL;
       }
     
    -  /**
    -   * 发送post请求
    -   *
    -   * @param url        请求地址
    -   * @param requestStr 请求信息
    -   * @param useKey     是否使用证书
    -   * @return 返回请求结果字符串
    -   */
    -  protected abstract String post(String url, String requestStr, boolean useKey) throws WxPayException;
    -
       @Override
       public WxPayRefundResult refund(WxPayRefundRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/secapi/pay/refund";
         String responseContent = this.post(url, request.toXML(), true);
    -    WxPayRefundResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundResult.class);
    +    WxPayRefundResult result = BaseWxPayResult.fromXML(responseContent, WxPayRefundResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
    @@ -90,11 +143,11 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         request.setOutRefundNo(StringUtils.trimToNull(outRefundNo));
         request.setRefundId(StringUtils.trimToNull(refundId));
     
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/pay/refundquery";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayRefundQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundQueryResult.class);
    +    WxPayRefundQueryResult result = BaseWxPayResult.fromXML(responseContent, WxPayRefundQueryResult.class);
         result.composeRefundRecords();
         result.checkResult(this, request.getSignType(), true);
         return result;
    @@ -112,7 +165,7 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
           log.debug("微信支付异步通知请求参数:{}", xmlData);
           WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
           log.debug("微信支付异步通知请求解析后的对象:{}", result);
    -      result.checkResult(this, null, false);
    +      result.checkResult(this, this.getConfig().getSignType(), false);
           return result;
         } catch (WxPayException e) {
           log.error(e.getMessage(), e);
    @@ -136,9 +189,27 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         }
       }
     
    +  @Override
    +  public WxScanPayNotifyResult parseScanPayNotifyResult(String xmlData) throws WxPayException {
    +    try {
    +      log.debug("扫码支付回调通知请求参数:{}", xmlData);
    +      WxScanPayNotifyResult result = BaseWxPayResult.fromXML(xmlData,WxScanPayNotifyResult.class);
    +      log.debug("扫码支付回调通知解析后的对象:{}", result);
    +      result.checkResult(this, this.getConfig().getSignType(), false);
    +      return result;
    +    } catch (WxPayException e) {
    +      log.error(e.getMessage(), e);
    +      throw e;
    +    } catch (Exception e) {
    +      log.error(e.getMessage(), e);
    +      throw new WxPayException("发生异常," + e.getMessage(), e);
    +    }
    +
    +  }
    +
       @Override
       public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendredpack";
         if (request.getAmtType() != null) {
    @@ -148,7 +219,7 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
     
         String responseContent = this.post(url, request.toXML(), true);
         //无需校验,因为没有返回签名信息
    -    return WxPayBaseResult.fromXML(responseContent, WxPaySendRedpackResult.class);
    +    return BaseWxPayResult.fromXML(responseContent, WxPaySendRedpackResult.class);
       }
     
       @Override
    @@ -156,11 +227,11 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
         request.setMchBillNo(mchBillNo);
         request.setBillType(BillType.MCHT);
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo";
         String responseContent = this.post(url, request.toXML(), true);
    -    WxPayRedpackQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
    +    WxPayRedpackQueryResult result = BaseWxPayResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
    @@ -170,7 +241,7 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
         request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
         request.setTransactionId(StringUtils.trimToNull(transactionId));
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/pay/orderquery";
         String responseContent = this.post(url, request.toXML(), false);
    @@ -178,7 +249,7 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
           throw new WxPayException("无响应结果");
         }
     
    -    WxPayOrderQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderQueryResult.class);
    +    WxPayOrderQueryResult result = BaseWxPayResult.fromXML(responseContent, WxPayOrderQueryResult.class);
         result.composeCoupons();
         result.checkResult(this, request.getSignType(), true);
         return result;
    @@ -192,11 +263,11 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
     
         WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
         request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/pay/closeorder";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
    +    WxPayOrderCloseResult result = BaseWxPayResult.fromXML(responseContent, WxPayOrderCloseResult.class);
         result.checkResult(this, request.getSignType(), true);
     
         return result;
    @@ -274,11 +345,11 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
     
       @Override
       public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/pay/unifiedorder";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayUnifiedOrderResult result = WxPayBaseResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
    +    WxPayUnifiedOrderResult result = BaseWxPayResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
    @@ -332,30 +403,6 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         return payInfo;
       }
     
    -  @Override
    -  public WxEntPayResult entPay(WxEntPayRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    -    String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers";
    -
    -    String responseContent = this.post(url, request.toXML(), true);
    -    WxEntPayResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayResult.class);
    -    result.checkResult(this, request.getSignType(), true);
    -    return result;
    -  }
    -
    -  @Override
    -  public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException {
    -    WxEntPayQueryRequest request = new WxEntPayQueryRequest();
    -    request.setPartnerTradeNo(partnerTradeNo);
    -    request.checkAndSign(this.getConfig(), false);
    -
    -    String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo";
    -    String responseContent = this.post(url, request.toXML(), true);
    -    WxEntPayQueryResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayQueryResult.class);
    -    result.checkResult(this, request.getSignType(), true);
    -    return result;
    -  }
    -
       @Override
       public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
         String content = this.createScanPayQrcodeMode1(productId);
    @@ -400,34 +447,75 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
     
       @Override
       public void report(WxPayReportRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/payitil/report";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
    +    WxPayCommonResult result = BaseWxPayResult.fromXML(responseContent, WxPayCommonResult.class);
         result.checkResult(this, request.getSignType(), true);
       }
     
       @Override
       public WxPayBillResult downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxPayException {
    +    if (!BillType.ALL.equals(billType)) {
    +      throw new WxPayException("目前仅支持ALL类型的对账单下载");
    +    }
    +
         WxPayDownloadBillRequest request = new WxPayDownloadBillRequest();
         request.setBillType(billType);
         request.setBillDate(billDate);
         request.setTarType(tarType);
         request.setDeviceInfo(deviceInfo);
     
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/pay/downloadbill";
    -    String responseContent = this.post(url, request.toXML(), false);
    -    if (responseContent.startsWith("<")) {
    -      throw WxPayException.from(WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class));
    +
    +    String responseContent;
    +    if (TarType.GZIP.equals(tarType)) {
    +      responseContent = this.handleGzipBill(url, request.toXML());
    +    } else {
    +      responseContent = this.post(url, request.toXML(), false);
    +      if (responseContent.startsWith("<")) {
    +        throw WxPayException.from(BaseWxPayResult.fromXML(responseContent, WxPayCommonResult.class));
    +      }
         }
     
    -    return this.handleBillInformation(responseContent);
    +    return this.handleBill(billType, responseContent);
    +  }
    +
    +  private WxPayBillResult handleBill(String billType, String responseContent) {
    +    if (!BillType.ALL.equals(billType)) {
    +      return null;
    +    }
    +
    +    return this.handleAllBill(responseContent);
    +  }
    +
    +  private String handleGzipBill(String url, String requestStr) throws WxPayException {
    +    try {
    +      byte[] responseBytes = this.postForBytes(url, requestStr, false);
    +      Path tempDirectory = Files.createTempDirectory("bill");
    +      Path path = Paths.get(tempDirectory.toString(), System.currentTimeMillis() + ".gzip");
    +      Files.write(path, responseBytes);
    +      try {
    +        List allLines = Files.readAllLines(ZipUtil.ungzip(path.toFile()).toPath(), StandardCharsets.UTF_8);
    +        return Joiner.on("\n").join(allLines);
    +      } catch (ZipException e) {
    +        if (e.getMessage().contains("Not in GZIP format")) {
    +          throw WxPayException.from(BaseWxPayResult.fromXML(new String(responseBytes, StandardCharsets.UTF_8),
    +            WxPayCommonResult.class));
    +        } else {
    +          this.log.error("解压zip文件出错", e);
    +        }
    +      }
    +    }   catch (IOException e) {
    +      e.printStackTrace();
    +    }
    +    return null;
       }
     
    -  private WxPayBillResult handleBillInformation(String responseContent) {
    +  private WxPayBillResult handleAllBill(String responseContent) {
         WxPayBillResult wxPayBillResult = new WxPayBillResult();
     
         String listStr = "";
    @@ -444,11 +532,16 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
          * 参考以上格式进行取值
          */
         List wxPayBillBaseResultLst = new LinkedList<>();
    -    String newStr = listStr.replaceAll(",", " "); // 去空格
    -    String[] tempStr = newStr.split("`"); // 数据分组
    -    String[] t = tempStr[0].split(" ");// 分组标题
    -    int j = tempStr.length / t.length; // 计算循环次数
    -    int k = 1; // 纪录数组下标
    +    // 去空格
    +    String newStr = listStr.replaceAll(",", " ");
    +    // 数据分组
    +    String[] tempStr = newStr.split("`");
    +    // 分组标题
    +    String[] t = tempStr[0].split(" ");
    +    // 计算循环次数
    +    int j = tempStr.length / t.length;
    +    // 纪录数组下标
    +    int k = 1;
         for (int i = 0; i < j; i++) {
           WxPayBillBaseResult wxPayBillBaseResult = new WxPayBillBaseResult();
     
    @@ -498,33 +591,33 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
     
       @Override
       public WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/pay/micropay";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayMicropayResult result = WxPayBaseResult.fromXML(responseContent, WxPayMicropayResult.class);
    +    WxPayMicropayResult result = BaseWxPayResult.fromXML(responseContent, WxPayMicropayResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
     
       @Override
       public WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/secapi/pay/reverse";
         String responseContent = this.post(url, request.toXML(), true);
    -    WxPayOrderReverseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderReverseResult.class);
    +    WxPayOrderReverseResult result = BaseWxPayResult.fromXML(responseContent, WxPayOrderReverseResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
     
       @Override
       public String shorturl(WxPayShorturlRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/tools/shorturl";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayShorturlResult result = WxPayBaseResult.fromXML(responseContent, WxPayShorturlResult.class);
    +    WxPayShorturlResult result = BaseWxPayResult.fromXML(responseContent, WxPayShorturlResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result.getShortUrl();
       }
    @@ -536,11 +629,11 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
     
       @Override
       public String authcode2Openid(WxPayAuthcode2OpenidRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/tools/authcodetoopenid";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayAuthcode2OpenidResult result = WxPayBaseResult.fromXML(responseContent, WxPayAuthcode2OpenidResult.class);
    +    WxPayAuthcode2OpenidResult result = BaseWxPayResult.fromXML(responseContent, WxPayAuthcode2OpenidResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result.getOpenid();
       }
    @@ -553,44 +646,44 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
       @Override
       public String getSandboxSignKey() throws WxPayException {
         WxPayDefaultRequest request = new WxPayDefaultRequest();
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPaySandboxSignKeyResult result = WxPayBaseResult.fromXML(responseContent, WxPaySandboxSignKeyResult.class);
    +    WxPaySandboxSignKeyResult result = BaseWxPayResult.fromXML(responseContent, WxPaySandboxSignKeyResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result.getSandboxSignKey();
       }
     
       @Override
       public WxPayCouponSendResult sendCoupon(WxPayCouponSendRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/mmpaymkttransfers/send_coupon";
         String responseContent = this.post(url, request.toXML(), true);
    -    WxPayCouponSendResult result = WxPayBaseResult.fromXML(responseContent, WxPayCouponSendResult.class);
    +    WxPayCouponSendResult result = BaseWxPayResult.fromXML(responseContent, WxPayCouponSendResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
     
       @Override
       public WxPayCouponStockQueryResult queryCouponStock(WxPayCouponStockQueryRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/mmpaymkttransfers/query_coupon_stock";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayCouponStockQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayCouponStockQueryResult.class);
    +    WxPayCouponStockQueryResult result = BaseWxPayResult.fromXML(responseContent, WxPayCouponStockQueryResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
     
       @Override
       public WxPayCouponInfoQueryResult queryCouponInfo(WxPayCouponInfoQueryRequest request) throws WxPayException {
    -    request.checkAndSign(this.getConfig(), false);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/mmpaymkttransfers/querycouponsinfo";
         String responseContent = this.post(url, request.toXML(), false);
    -    WxPayCouponInfoQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayCouponInfoQueryResult.class);
    +    WxPayCouponInfoQueryResult result = BaseWxPayResult.fromXML(responseContent, WxPayCouponInfoQueryResult.class);
         result.checkResult(this, request.getSignType(), true);
         return result;
       }
    @@ -615,13 +708,13 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService {
         request.setLimit(limit);
         request.setSignType(SignType.HMAC_SHA256);
     
    -    request.checkAndSign(this.getConfig(), true);
    +    request.checkAndSign(this.getConfig());
     
         String url = this.getPayBaseUrl() + "/billcommentsp/batchquerycomment";
     
         String responseContent = this.post(url, request.toXML(), true);
         if (responseContent.startsWith("<")) {
    -      throw WxPayException.from(WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class));
    +      throw WxPayException.from(BaseWxPayResult.fromXML(responseContent, WxPayCommonResult.class));
         }
     
         return responseContent;
    diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImpl.java
    new file mode 100644
    index 00000000..b50a0786
    --- /dev/null
    +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImpl.java
    @@ -0,0 +1,149 @@
    +package com.github.binarywang.wxpay.service.impl;
    +
    +import com.github.binarywang.wxpay.bean.entpay.*;
    +import com.github.binarywang.wxpay.bean.request.WxPayDefaultRequest;
    +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
    +import com.github.binarywang.wxpay.exception.WxPayException;
    +import com.github.binarywang.wxpay.service.EntPayService;
    +import com.github.binarywang.wxpay.service.WxPayService;
    +import com.github.binarywang.wxpay.util.SignUtils;
    +import org.apache.commons.codec.binary.Base64;
    +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
    +import org.bouncycastle.jce.provider.BouncyCastleProvider;
    +import org.bouncycastle.openssl.PEMParser;
    +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
    +
    +import javax.crypto.Cipher;
    +import java.io.File;
    +import java.io.FileReader;
    +import java.io.IOException;
    +import java.nio.file.Files;
    +import java.nio.file.Path;
    +import java.security.PublicKey;
    +import java.security.Security;
    +
    +/**
    + * 
    + *  Created by BinaryWang on 2017/12/19.
    + * 
    + * + * @author Binary Wang + */ +public class EntPayServiceImpl implements EntPayService { + private WxPayService payService; + + public EntPayServiceImpl(WxPayService payService) { + this.payService = payService; + } + + @Override + public EntPayResult entPay(EntPayRequest request) throws WxPayException { + request.checkAndSign(this.payService.getConfig()); + String url = this.payService.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers"; + + String responseContent = this.payService.post(url, request.toXML(), true); + EntPayResult result = BaseWxPayResult.fromXML(responseContent, EntPayResult.class); + result.checkResult(this.payService, request.getSignType(), true); + return result; + } + + @Override + public EntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException { + EntPayQueryRequest request = new EntPayQueryRequest(); + request.setPartnerTradeNo(partnerTradeNo); + request.checkAndSign(this.payService.getConfig()); + + String url = this.payService.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo"; + String responseContent = this.payService.post(url, request.toXML(), true); + EntPayQueryResult result = BaseWxPayResult.fromXML(responseContent, EntPayQueryResult.class); + result.checkResult(this.payService, request.getSignType(), true); + return result; + } + + @Override + public String getPublicKey() throws WxPayException { + WxPayDefaultRequest request = new WxPayDefaultRequest(); + request.setMchId(this.payService.getConfig().getMchId()); + request.setNonceStr(String.valueOf(System.currentTimeMillis())); + request.setSign(SignUtils.createSign(request, null, this.payService.getConfig().getMchKey(), + true)); + + String url = "https://fraud.mch.weixin.qq.com/risk/getpublickey"; + String responseContent = this.payService.post(url, request.toXML(), true); + GetPublicKeyResult result = BaseWxPayResult.fromXML(responseContent, GetPublicKeyResult.class); + result.checkResult(this.payService, request.getSignType(), true); + return result.getPubKey(); + } + + @Override + public EntPayBankResult payBank(EntPayBankRequest request) throws WxPayException { + File publicKeyFile = this.buildPublicKeyFile(); + request.setEncBankNo(this.encryptRSA(publicKeyFile, request.getEncBankNo())); + request.setEncTrueName(this.encryptRSA(publicKeyFile, request.getEncTrueName())); + publicKeyFile.deleteOnExit(); + + request.checkAndSign(this.payService.getConfig()); + + String url = this.payService.getPayBaseUrl() + "/mmpaysptrans/pay_bank"; + String responseContent = this.payService.post(url, request.toXML(), true); + EntPayBankResult result = BaseWxPayResult.fromXML(responseContent, EntPayBankResult.class); + result.checkResult(this.payService, request.getSignType(), true); + return result; + } + + @Override + public EntPayBankQueryResult queryPayBank(String partnerTradeNo) throws WxPayException { + EntPayBankQueryRequest request = new EntPayBankQueryRequest(); + request.setPartnerTradeNo(partnerTradeNo); + request.checkAndSign(this.payService.getConfig()); + + String url = this.payService.getPayBaseUrl() + "/mmpaysptrans/query_bank"; + String responseContent = this.payService.post(url, request.toXML(), true); + EntPayBankQueryResult result = BaseWxPayResult.fromXML(responseContent, EntPayBankQueryResult.class); + result.checkResult(this.payService, request.getSignType(), true); + return result; + } + + private String encryptRSA(File publicKeyFile, String srcString) throws WxPayException { + try { + Security.addProvider(new BouncyCastleProvider()); + Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding"); + try (PEMParser reader = new PEMParser(new FileReader(publicKeyFile))) { + final PublicKey publicKey = new JcaPEMKeyConverter().setProvider("BC") + .getPublicKey((SubjectPublicKeyInfo) reader.readObject()); + + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + byte[] encrypt = cipher.doFinal(srcString.getBytes()); + return Base64.encodeBase64String(encrypt); + } + } catch (Exception e) { + throw new WxPayException("加密出错", e); + } + } + + private File buildPublicKeyFile() throws WxPayException { + try { + String publicKeyStr = this.getPublicKey(); + Path tmpFile = Files.createTempFile("payToBank", ".pem"); + Files.write(tmpFile, publicKeyStr.getBytes()); + return tmpFile.toFile(); + } catch (Exception e) { + throw new WxPayException("生成加密公钥文件时发生异常", e); + } + } + + public static void main(String[] args) throws WxPayException, IOException { + String key = "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAtEeUSop/YGqZ53Y++R9NapFSZmorj+SL/brmJUU7+hyClEnPOeG/\n" + + "v6/ZrX9qo25JAojrBDbqaW9L+HtzI141vusarRYIGPvVqTV30L5db0Yq7AmX7Hs9\n" + + "s+nEtoMAwMWUzQPXLUs2mt6rpu85HwAIK3F4Xb+OFIbXCJTbDvWYtQssn07lr+IY\n" + + "jPA00sON71egmuRrCoQClkhf0vgrhj7eHUCRZRJ2zf4UU31fHv+kO441hVD5TTP8\n" + + "bjJvFm6TW3sgQE8aCDbomtu+syk4Tv/4ONCqxG8d/kF1TlU+idGWEU179uR/KSjP\n" + + "p7kM7BoaY2goFgYAe4DsI8Fh33dCOiKyVwIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + Path tmpFile = Files.createTempFile("payToBank", ".pem"); + Files.write(tmpFile, key.getBytes()); + System.out.println(new EntPayServiceImpl(null).encryptRSA(tmpFile.toFile(), "111111")); + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java index 653c1a8d..1644d260 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java @@ -2,6 +2,7 @@ package com.github.binarywang.wxpay.service.impl; import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.exception.WxPayException; +import jodd.util.Base64; import org.apache.commons.lang3.StringUtils; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -19,53 +20,47 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; +import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; /** *
    - * 微信支付请求实现类,apache httpclient实现
    + * 微信支付请求实现类,apache httpclient实现.
      * Created by Binary Wang on 2016/7/28.
      * 
    * * @author Binary Wang */ -public class WxPayServiceApacheHttpImpl extends WxPayServiceAbstractImpl { - +public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl { @Override - protected String post(String url, String requestStr, boolean useKey) throws WxPayException { + public byte[] postForBytes(String url, String requestStr, boolean useKey) throws WxPayException { try { - HttpClientBuilder httpClientBuilder = HttpClients.custom(); - if (useKey) { - SSLContext sslContext = this.getConfig().getSslContext(); - if (null == sslContext) { - sslContext = this.getConfig().initSSLContext(); + HttpClientBuilder httpClientBuilder = createHttpClientBuilder(useKey); + HttpPost httpPost = this.createHttpPost(url, requestStr); + try (CloseableHttpClient httpclient = httpClientBuilder.build()) { + try (CloseableHttpResponse response = httpclient.execute(httpPost)) { + final byte[] bytes = EntityUtils.toByteArray(response.getEntity()); + final String responseData = Base64.encodeToString(bytes); + this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据(Base64编码后)】:{}", url, requestStr, responseData); + wxApiData.set(new WxPayApiData(url, requestStr, responseData, null)); + return bytes; } - - SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, - new String[]{"TLSv1"}, null, new DefaultHostnameVerifier()); - httpClientBuilder.setSSLSocketFactory(sslsf); - } - - HttpPost httpPost = new HttpPost(url); - - httpPost.setConfig(RequestConfig.custom() - .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) - .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) - .setSocketTimeout(this.getConfig().getHttpTimeout()) - .build()); - - if (StringUtils.isNotBlank(this.getConfig().getHttpProxyHost()) - && this.getConfig().getHttpProxyPort() > 0) { - // 使用代理服务器 需要用户认证的代理服务器 - CredentialsProvider provider = new BasicCredentialsProvider(); - provider.setCredentials( - new AuthScope(this.getConfig().getHttpProxyHost(), this.getConfig().getHttpProxyPort()), - new UsernamePasswordCredentials(this.getConfig().getHttpProxyUsername(), this.getConfig().getHttpProxyPassword())); - httpClientBuilder.setDefaultCredentialsProvider(provider); + } finally { + httpPost.releaseConnection(); } + } catch (Exception e) { + this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); + wxApiData.set(new WxPayApiData(url, requestStr, null, e.getMessage())); + throw new WxPayException(e.getMessage(), e); + } + } + @Override + public String post(String url, String requestStr, boolean useKey) throws WxPayException { + try { + HttpClientBuilder httpClientBuilder = this.createHttpClientBuilder(useKey); + HttpPost httpPost = this.createHttpPost(url, requestStr); try (CloseableHttpClient httpclient = httpClientBuilder.build()) { - httpPost.setEntity(new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1))); try (CloseableHttpResponse response = httpclient.execute(httpPost)) { String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); @@ -82,4 +77,56 @@ public class WxPayServiceApacheHttpImpl extends WxPayServiceAbstractImpl { } } + private StringEntity createEntry(String requestStr) { + try { + return new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); + } catch (UnsupportedEncodingException e) { + //cannot happen + this.log.error(e.getMessage(),e); + return null; + } + } + + private HttpClientBuilder createHttpClientBuilder(boolean useKey) throws WxPayException { + HttpClientBuilder httpClientBuilder = HttpClients.custom(); + if (useKey) { + this.setKey(httpClientBuilder); + } + + if (StringUtils.isNotBlank(this.getConfig().getHttpProxyHost()) + && this.getConfig().getHttpProxyPort() > 0) { + // 使用代理服务器 需要用户认证的代理服务器 + CredentialsProvider provider = new BasicCredentialsProvider(); + provider.setCredentials( + new AuthScope(this.getConfig().getHttpProxyHost(), this.getConfig().getHttpProxyPort()), + new UsernamePasswordCredentials(this.getConfig().getHttpProxyUsername(), this.getConfig().getHttpProxyPassword())); + httpClientBuilder.setDefaultCredentialsProvider(provider); + } + return httpClientBuilder; + } + + private HttpPost createHttpPost(String url, String requestStr) { + HttpPost httpPost = new HttpPost(url); + httpPost.setEntity(this.createEntry(requestStr)); + + httpPost.setConfig(RequestConfig.custom() + .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) + .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) + .setSocketTimeout(this.getConfig().getHttpTimeout()) + .build()); + + return httpPost; + } + + private void setKey(HttpClientBuilder httpClientBuilder) throws WxPayException { + SSLContext sslContext = this.getConfig().getSslContext(); + if (null == sslContext) { + sslContext = this.getConfig().initSSLContext(); + } + + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, + new String[]{"TLSv1"}, null, new DefaultHostnameVerifier()); + httpClientBuilder.setSSLSocketFactory(sslsf); + } + } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java index b342c5cd..2976e73f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java @@ -9,48 +9,39 @@ import jodd.http.ProxyInfo; import jodd.http.ProxyInfo.ProxyType; import jodd.http.net.SSLSocketHttpConnectionProvider; import jodd.http.net.SocketHttpConnectionProvider; +import jodd.util.Base64; import org.apache.commons.lang3.StringUtils; import javax.net.ssl.SSLContext; import java.nio.charset.StandardCharsets; /** - * 微信支付请求实现类,jodd-http实现 + * 微信支付请求实现类,jodd-http实现. * Created by Binary Wang on 2016/7/28. * * @author Binary Wang */ -public class WxPayServiceJoddHttpImpl extends WxPayServiceAbstractImpl { - +public class WxPayServiceJoddHttpImpl extends BaseWxPayServiceImpl { @Override - protected String post(String url, String requestStr, boolean useKey) throws WxPayException { + public byte[] postForBytes(String url, String requestStr, boolean useKey) throws WxPayException { try { - HttpRequest request = HttpRequest - .post(url) - .timeout(this.getConfig().getHttpTimeout()) - .connectionTimeout(this.getConfig().getHttpConnectionTimeout()) - .bodyText(requestStr); - - if (useKey) { - SSLContext sslContext = this.getConfig().getSslContext(); - if (null == sslContext) { - sslContext = this.getConfig().initSSLContext(); - } - final SSLSocketHttpConnectionProvider provider = new SSLSocketHttpConnectionProvider(sslContext); - request.withConnectionProvider(provider); - } - - if (StringUtils.isNotBlank(this.getConfig().getHttpProxyHost()) && this.getConfig().getHttpProxyPort() > 0) { - ProxyInfo httpProxy = new ProxyInfo(ProxyType.HTTP, this.getConfig().getHttpProxyHost(), this.getConfig().getHttpProxyPort(), - this.getConfig().getHttpProxyUsername(), this.getConfig().getHttpProxyPassword()); - HttpConnectionProvider provider = request.connectionProvider(); - if (null == provider) { - provider = new SocketHttpConnectionProvider(); - } - provider.useProxy(httpProxy); - request.withConnectionProvider(provider); - } + HttpRequest request = this.buildHttpRequest(url, requestStr, useKey); + byte[] responseBytes = request.send().bodyBytes(); + final String responseString = Base64.encodeToString(responseBytes); + this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据(Base64编码后)】:{}", url, requestStr, responseString); + wxApiData.set(new WxPayApiData(url, requestStr, responseString, null)); + return responseBytes; + } catch (Exception e) { + this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); + wxApiData.set(new WxPayApiData(url, requestStr, null, e.getMessage())); + throw new WxPayException(e.getMessage(), e); + } + } + @Override + public String post(String url, String requestStr, boolean useKey) throws WxPayException { + try { + HttpRequest request = this.buildHttpRequest(url, requestStr, useKey); String responseString = this.getResponseString(request.send()); this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); @@ -63,6 +54,35 @@ public class WxPayServiceJoddHttpImpl extends WxPayServiceAbstractImpl { } } + private HttpRequest buildHttpRequest(String url, String requestStr, boolean useKey) throws WxPayException { + HttpRequest request = HttpRequest + .post(url) + .timeout(this.getConfig().getHttpTimeout()) + .connectionTimeout(this.getConfig().getHttpConnectionTimeout()) + .bodyText(requestStr); + + if (useKey) { + SSLContext sslContext = this.getConfig().getSslContext(); + if (null == sslContext) { + sslContext = this.getConfig().initSSLContext(); + } + final SSLSocketHttpConnectionProvider provider = new SSLSocketHttpConnectionProvider(sslContext); + request.withConnectionProvider(provider); + } + + if (StringUtils.isNotBlank(this.getConfig().getHttpProxyHost()) && this.getConfig().getHttpProxyPort() > 0) { + ProxyInfo httpProxy = new ProxyInfo(ProxyType.HTTP, this.getConfig().getHttpProxyHost(), this.getConfig().getHttpProxyPort(), + this.getConfig().getHttpProxyUsername(), this.getConfig().getHttpProxyPassword()); + HttpConnectionProvider provider = request.connectionProvider(); + if (null == provider) { + provider = new SocketHttpConnectionProvider(); + } + provider.useProxy(httpProxy); + request.withConnectionProvider(provider); + } + return request; + } + private String getResponseString(HttpResponse response) throws WxPayException { try { this.log.debug("【微信服务器响应头信息】:\n{}", response.toString(false)); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java index efb9d856..10aedfe3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java @@ -1,7 +1,11 @@ package com.github.binarywang.wxpay.util; +import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest; +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.util.BeanUtils; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; @@ -11,11 +15,11 @@ import org.slf4j.LoggerFactory; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.*; /** *
    @@ -33,7 +37,7 @@ public class SignUtils {
        */
       @Deprecated
       public static String createSign(Object xmlBean, String signKey) {
    -    return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
    +    return createSign(xmlBean2Map(xmlBean), signKey);
       }
     
       /**
    @@ -54,7 +58,7 @@ public class SignUtils {
        * @return 签名字符串
        */
       public static String createSign(Object xmlBean, String signType, String signKey, boolean isIgnoreSignType) {
    -    return createSign(BeanUtils.xmlBean2Map(xmlBean), signType, signKey, isIgnoreSignType);
    +    return createSign(xmlBean2Map(xmlBean), signType, signKey, isIgnoreSignType);
       }
     
       /**
    @@ -116,7 +120,7 @@ public class SignUtils {
        * @return true - 签名校验成功,false - 签名校验失败
        */
       public static boolean checkSign(Object xmlBean, String signType, String signKey) {
    -    return checkSign(BeanUtils.xmlBean2Map(xmlBean), signType, signKey);
    +    return checkSign(xmlBean2Map(xmlBean), signType, signKey);
       }
     
       /**
    @@ -131,4 +135,48 @@ public class SignUtils {
         String sign = createSign(params, signType, signKey, false);
         return sign.equals(params.get("sign"));
       }
    +
    +  /**
    +   * 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象
    +   *
    +   * @param bean 包含@XStreamAlias的xml bean对象
    +   * @return map对象
    +   */
    +  public static Map xmlBean2Map(Object bean) {
    +    Map result = Maps.newHashMap();
    +    List fields = new ArrayList<>(Arrays.asList(bean.getClass().getDeclaredFields()));
    +    fields.addAll(Arrays.asList(bean.getClass().getSuperclass().getDeclaredFields()));
    +    if(bean.getClass().getSuperclass().getSuperclass() == BaseWxPayRequest.class){
    +      fields.addAll(Arrays.asList(BaseWxPayRequest.class.getDeclaredFields()));
    +    }
    +
    +    if(bean.getClass().getSuperclass().getSuperclass() == BaseWxPayResult.class){
    +      fields.addAll(Arrays.asList(BaseWxPayResult.class.getDeclaredFields()));
    +    }
    +
    +    for (Field field : fields) {
    +      try {
    +        boolean isAccessible = field.isAccessible();
    +        field.setAccessible(true);
    +        if (field.get(bean) == null) {
    +          field.setAccessible(isAccessible);
    +          continue;
    +        }
    +
    +        if (field.isAnnotationPresent(XStreamAlias.class)) {
    +          result.put(field.getAnnotation(XStreamAlias.class).value(), field.get(bean).toString());
    +        } else if (!Modifier.isStatic(field.getModifiers())) {
    +          //忽略掉静态成员变量
    +          result.put(field.getName(), field.get(bean).toString());
    +        }
    +
    +        field.setAccessible(isAccessible);
    +      } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
    +        log.error(e.getMessage(), e);
    +      }
    +
    +    }
    +
    +    return result;
    +  }
     }
    diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxScanPayNotifyResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxScanPayNotifyResultTest.java
    new file mode 100644
    index 00000000..77316724
    --- /dev/null
    +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxScanPayNotifyResultTest.java
    @@ -0,0 +1,47 @@
    +package com.github.binarywang.wxpay.bean.notify;
    +
    +import org.testng.annotations.*;
    +
    +import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
    +
    +import static org.assertj.core.api.Assertions.assertThat;
    +
    +/**
    + * 
    + *
    + * Created by Binary Wang on 2018/2/2.
    + * 
    + * + * @author Binary Wang + */ +public class WxScanPayNotifyResultTest { + + @Test + public void testToMap() { + } + + @Test + public void testFromXML() { + String xmlString = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + WxScanPayNotifyResult result = BaseWxPayResult.fromXML(xmlString, WxScanPayNotifyResult.class); + + assertThat(result).isNotNull(); + + assertThat(result.getAppid()).isEqualTo("wx8888888888888888"); + assertThat(result.getOpenid()).isEqualTo("o8GeHuLAsgefS_80exEr1cTqekUs"); + assertThat(result.getMchId()).isEqualTo("1900000109"); + assertThat(result.getNonceStr()).isEqualTo("5K8264ILTKCH16CQ2502SI8ZNMTM67VS"); + assertThat(result.getProductId()).isEqualTo("88888"); + assertThat(result.getSign()).isEqualTo("C380BEC2BFD727A4B6845133519F3AD6"); + } + +} diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/BaseWxPayResultTest.java similarity index 98% rename from weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResultTest.java rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/BaseWxPayResultTest.java index d6a1f7b8..10baf017 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResultTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/BaseWxPayResultTest.java @@ -11,7 +11,7 @@ import java.util.Map; * @author binarywang(Binary Wang) *
    */ -public class WxPayBaseResultTest { +public class BaseWxPayResultTest { @Test public void testGetXmlValue() throws Exception { diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResultTest.java index d847a155..1925c80b 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResultTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderQueryResultTest.java @@ -11,8 +11,8 @@ import org.testng.annotations.*; */ public class WxPayOrderQueryResultTest { @Test - public void testComposeCoupons() throws Exception { - /** + public void testComposeCoupons() { + /* * xml样例字符串来自于官方文档,并稍加改造加入了coupon相关的数据便于测试 */ String xmlString = "\n" + diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayRedpackQueryResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayRedpackQueryResultTest.java new file mode 100644 index 00000000..c857fa0d --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayRedpackQueryResultTest.java @@ -0,0 +1,51 @@ +package com.github.binarywang.wxpay.bean.result; + +import org.testng.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + *
    + *
    + * Created by Binary Wang on 2018/1/24.
    + * 
    + * + * @author Binary Wang + */ +public class WxPayRedpackQueryResultTest { + @Test + public void testFromXML() { + String xmlString = "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "1\n" + + "100\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "100\n" + + "\n" + + "\n" + + "\n" + + ""; + + WxPayRedpackQueryResult orderQueryResult = WxPayRedpackQueryResult.fromXML(xmlString, WxPayRedpackQueryResult.class); + System.out.println(orderQueryResult); + assertThat(orderQueryResult).isNotNull(); + + assertThat(orderQueryResult.getRedpackList()).isNotEmpty(); + assertThat(orderQueryResult.getRedpackList().get(0).getAmount()).isEqualTo(100); + assertThat(orderQueryResult.getRedpackList().get(0).getOpenid()).isEqualTo("o3yHF0uHuckI3yE6lwWiFQBQdVDI"); + assertThat(orderQueryResult.getRedpackList().get(0).getReceiveTime()).isEqualTo("2018-01-23 13:45:31"); + } +} diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java similarity index 92% rename from weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImplTest.java rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java index 9c293103..34a7dc68 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImplTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java @@ -8,7 +8,6 @@ import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; -import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.constant.WxPayConstants.BillType; import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType; @@ -26,6 +25,8 @@ import java.nio.file.Path; import java.util.Calendar; import java.util.Date; +import static com.github.binarywang.wxpay.constant.WxPayConstants.TarType; +import static org.assertj.core.api.Assertions.assertThat; import static org.testng.Assert.*; /** @@ -36,7 +37,7 @@ import static org.testng.Assert.*; */ @Test @Guice(modules = ApiTestModule.class) -public class WxPayServiceAbstractImplTest { +public class BaseWxPayServiceImplTest { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Inject @@ -51,7 +52,7 @@ public class WxPayServiceAbstractImplTest { .body("我去") .totalFee(1) .spbillCreateIp("11.1.11.1") - .notifyURL("111111") + .notifyUrl("111111") .tradeType(TradeType.JSAPI) .openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) .outTradeNo("1111112") @@ -74,7 +75,7 @@ public class WxPayServiceAbstractImplTest { .body("我去") .totalFee(1) .spbillCreateIp("11.1.11.1") - .notifyURL("111111") + .notifyUrl("111111") .tradeType(TradeType.JSAPI) .openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) .outTradeNo("1111112") @@ -90,7 +91,7 @@ public class WxPayServiceAbstractImplTest { .body("我去") .totalFee(1) .spbillCreateIp("11.1.11.1") - .notifyURL("111111") + .notifyUrl("111111") .tradeType(TradeType.APP) .outTradeNo("1111112") .build()); @@ -106,7 +107,7 @@ public class WxPayServiceAbstractImplTest { .totalFee(1) .productId("aaa") .spbillCreateIp("11.1.11.1") - .notifyURL("111111") + .notifyUrl("111111") .tradeType(TradeType.NATIVE) .outTradeNo("111111290") .build()); @@ -139,7 +140,13 @@ public class WxPayServiceAbstractImplTest { @DataProvider public Object[][] billingData() { return new Object[][]{ -// {"20170831", BillType.ALL, null, "deviceInfo"}, + {"20170831", BillType.ALL, TarType.GZIP, "deviceInfo"}, + {"20170831", BillType.RECHARGE_REFUND, TarType.GZIP, "deviceInfo"}, + {"20170831", BillType.REFUND, TarType.GZIP, "deviceInfo"}, + {"20170831", BillType.SUCCESS, TarType.GZIP, "deviceInfo"}, + {"20170831", BillType.ALL, null, "deviceInfo"}, + {"20170831", BillType.RECHARGE_REFUND, null, "deviceInfo"}, + {"20170831", BillType.REFUND, null, "deviceInfo"}, {"20170831", BillType.SUCCESS, null, "deviceInfo"} }; } @@ -148,11 +155,11 @@ public class WxPayServiceAbstractImplTest { public void testDownloadBill(String billDate, String billType, String tarType, String deviceInfo) throws Exception { WxPayBillResult billResult = this.payService.downloadBill(billDate, billType, tarType, deviceInfo); - assertNotNull(billResult); + assertThat(billResult).isNotNull(); this.logger.info(billResult.toString()); } - @Test + @Test(expectedExceptions = WxPayException.class) public void testDownloadBill_withNoParams() throws Exception { //必填字段为空时,抛出异常 this.payService.downloadBill("", "", "", null); @@ -237,31 +244,6 @@ public class WxPayServiceAbstractImplTest { this.logger.info(redpackResult.toString()); } - /** - * Test method for {@link WxPayService#entPay(WxEntPayRequest)}. - */ - @Test - public void testEntPay() throws WxPayException { - WxEntPayRequest request = WxEntPayRequest.newBuilder() - .partnerTradeNo("Eb6Aep7uVTdbkJqrP4") - .openid("ojOQA0y9o-Eb6Aep7uVTdbkJqrP4") - .amount(1) - .spbillCreateIp("10.10.10.10") - .checkName(WxPayConstants.CheckNameOption.NO_CHECK) - .description("描述信息") - .build(); - - this.logger.info(this.payService.entPay(request).toString()); - } - - /** - * Test method for {@link WxPayService#queryEntPay(String)}. - */ - @Test - public void testQueryEntPay() throws WxPayException { - this.logger.info(this.payService.queryEntPay("11212121").toString()); - } - @Test public void testCreateScanPayQrcodeMode1() throws Exception { String productId = "abc"; diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImplTest.java new file mode 100644 index 00000000..b0d34a60 --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/EntPayServiceImplTest.java @@ -0,0 +1,72 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.entpay.EntPayBankRequest; +import com.github.binarywang.wxpay.bean.entpay.EntPayBankResult; +import com.github.binarywang.wxpay.bean.entpay.EntPayRequest; +import com.github.binarywang.wxpay.constant.WxPayConstants.CheckNameOption; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.testbase.ApiTestModule; +import com.google.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.*; + +/** + *
    + *  企业付款测试类.
    + *  Created by BinaryWang on 2017/12/19.
    + * 
    + * + * @author Binary Wang + */ +@Test +@Guice(modules = ApiTestModule.class) +public class EntPayServiceImplTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Inject + private WxPayService payService; + + @Test + public void testEntPay() throws WxPayException { + EntPayRequest request = EntPayRequest.newBuilder() + .partnerTradeNo("Eb6Aep7uVTdbkJqrP4") + .openid("ojOQA0y9o-Eb6Aep7uVTdbkJqrP5") + .amount(100) + .spbillCreateIp("10.10.10.10") + .checkName(CheckNameOption.NO_CHECK) + .description("描述信息") + .build(); + + this.logger.info(this.payService.getEntPayService().entPay(request).toString()); + } + + @Test + public void testQueryEntPay() throws WxPayException { + this.logger.info(this.payService.getEntPayService().queryEntPay("11212121").toString()); + } + + @Test + public void testGetPublicKey() throws Exception { + this.logger.info(this.payService.getEntPayService().getPublicKey()); + } + + @Test + public void testPayBank() throws Exception { + EntPayBankResult result = this.payService.getEntPayService().payBank(EntPayBankRequest.builder() + .bankCode("aa") + .amount(1) + .encBankNo("1") + .encTrueName("2") + .partnerTradeNo("3") + .description("11") + .build()); + this.logger.info(result.toString()); + } + + @Test + public void testQueryPayBank() throws Exception { + this.logger.info(this.payService.getEntPayService().queryPayBank("123").toString()); + } +}