Browse Source

Merge pull request #518 from Wechat-Group/develop

merge Develop
master
Binary Wang 7 years ago
committed by GitHub
parent
commit
9405fa2b6f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
100 changed files with 1727 additions and 931 deletions
  1. +3
    -0
      .gitignore
  2. BIN
      .mvn/wrapper/maven-wrapper.jar
  3. +1
    -0
      .mvn/wrapper/maven-wrapper.properties
  4. +4
    -4
      .travis.yml
  5. +2
    -0
      check-dependency-updates.sh
  6. +2
    -0
      check-plugin-updates.sh
  7. +2
    -0
      check-property-updates.sh
  8. +236
    -0
      mvnw
  9. +146
    -0
      mvnw.cmd
  10. +10
    -14
      pom.xml
  11. +11
    -21
      quality-checks/google_checks.xml
  12. +2
    -2
      weixin-java-common/pom.xml
  13. +3
    -6
      weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java
  14. +8
    -8
      weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java
  15. +15
    -14
      weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java
  16. +0
    -36
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java
  17. +4
    -4
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java
  18. +2
    -2
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java
  19. +12
    -1
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java
  20. +5
    -2
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java
  21. +16
    -12
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java
  22. +0
    -8
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java
  23. +0
    -8
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java
  24. +0
    -8
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java
  25. +11
    -12
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java
  26. +3
    -1
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java
  27. +6
    -4
      weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java
  28. +2
    -2
      weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java
  29. +12
    -2
      weixin-java-cp/pom.xml
  30. +4
    -3
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpDepartmentService.java
  31. +1
    -206
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
  32. +53
    -0
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java
  33. +5
    -5
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java
  34. +1
    -1
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java
  35. +0
    -206
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java
  36. +49
    -0
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java
  37. +8
    -2
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java
  38. +2
    -0
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java
  39. +2
    -0
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java
  40. +2
    -0
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java
  41. +2
    -0
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java
  42. +1
    -1
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java
  43. +2
    -2
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java
  44. +7
    -4
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java
  45. +11
    -5
      weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java
  46. +9
    -9
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java
  47. +15
    -6
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java
  48. +26
    -3
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java
  49. +3
    -3
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java
  50. +1
    -1
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java
  51. +1
    -1
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java
  52. +1
    -1
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java
  53. +1
    -1
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java
  54. +1
    -1
      weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java
  55. +11
    -2
      weixin-java-miniapp/pom.xml
  56. +6
    -9
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java
  57. +30
    -16
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java
  58. +89
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java
  59. +14
    -5
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java
  60. +2
    -1
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java
  61. +45
    -14
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java
  62. +101
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImpl.java
  63. +9
    -16
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java
  64. +4
    -2
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java
  65. +5
    -5
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java
  66. +81
    -16
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java
  67. +7
    -5
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java
  68. +30
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java
  69. +23
    -5
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java
  70. +1
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java
  71. +20
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java
  72. +31
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java
  73. +28
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java
  74. +29
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java
  75. +0
    -27
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java
  76. +30
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java
  77. +53
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java
  78. +47
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java
  79. +0
    -27
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java
  80. +30
    -0
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java
  81. +19
    -11
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java
  82. +4
    -4
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java
  83. +0
    -2
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java
  84. +0
    -46
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java
  85. +8
    -4
      weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java
  86. +9
    -23
      weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java
  87. +70
    -0
      weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImplTest.java
  88. +17
    -6
      weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java
  89. +38
    -21
      weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessageTest.java
  90. +0
    -0
      weixin-java-miniapp/src/test/resources/test-config-sample.xml
  91. +11
    -2
      weixin-java-mp/pom.xml
  92. +2
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java
  93. +10
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java
  94. +11
    -11
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java
  95. +14
    -14
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java
  96. +12
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java
  97. +8
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
  98. +40
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpSubscribeMsgService.java
  99. +1
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java
  100. +1
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java

+ 3
- 0
.gitignore View File

@@ -50,3 +50,6 @@ Temporary Items
.apdisk
/.sonar/
sonar-project.properties

!/.mvn/wrapper/maven-wrapper.jar
*.versionsBackup

BIN
.mvn/wrapper/maven-wrapper.jar View File


+ 1
- 0
.mvn/wrapper/maven-wrapper.properties View File

@@ -0,0 +1 @@
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip

+ 4
- 4
.travis.yml View File

@@ -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'


+ 2
- 0
check-dependency-updates.sh View File

@@ -0,0 +1,2 @@
#!/usr/bin/env bash
./mvnw org.codehaus.mojo:versions-maven-plugin:display-dependency-updates

+ 2
- 0
check-plugin-updates.sh View File

@@ -0,0 +1,2 @@
#!/usr/bin/env bash
./mvnw org.codehaus.mojo:versions-maven-plugin:display-plugin-updates

+ 2
- 0
check-property-updates.sh View File

@@ -0,0 +1,2 @@
#!/usr/bin/env bash
./mvnw org.codehaus.mojo:versions-maven-plugin:display-property-updates

+ 236
- 0
mvnw View File

@@ -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 "$@"

+ 146
- 0
mvnw.cmd View File

@@ -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%

+ 10
- 14
pom.xml View File

@@ -6,9 +6,9 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.9.0</version>
<version>2.9.9.BETA</version>
<packaging>pom</packaging>
<name>WeiXin Java Tools - Parent</name>
<name>Weixin Java Tools - Parent</name>
<description>微信公众号、企业号上级POM</description>
<url>https://github.com/wechat-group/weixin-java-tools</url>

@@ -108,8 +108,6 @@
<maven.compiler.target>1.7</maven.compiler.target>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<downloadJavadocs>true</downloadJavadocs>
<downloadSources>true</downloadSources>
<httpclient.version>4.5</httpclient.version>
<jetty.version>9.3.0.RC0</jetty.version>
</properties>
@@ -225,6 +223,13 @@
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-guava</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
@@ -235,7 +240,7 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
@@ -353,15 +358,6 @@
<goals>deploy</goals>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>


+ 11
- 21
quality-checks/google_checks.xml View File

@@ -32,7 +32,7 @@
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format" value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message" value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
<property name="message" value="考虑使用特殊的转义字符,而非八进制值或者Unicode转义值。"/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
@@ -69,9 +69,9 @@
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
value="WhitespaceAround: ''{0}''后面没有空格。Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
value="WhitespaceAround: ''{0}''前面没有加空格。"/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
@@ -100,11 +100,11 @@
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
value="包名 ''{0}'' 必须匹配模式:''{1}''。"/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
value="类型名 ''{0}'' 必须匹配模式:''{1}''。"/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
@@ -114,28 +114,28 @@
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
value="参数名''{0}'' 必须匹配模式:''{1}''。"/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
value="本地变量名 ''{0}'' 必须匹配模式:''{1}''。"/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
value="类的类型名 ''{0}'' 必须匹配模式:''{1}''。"/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
value="方法类型名 ''{0}'' 必须匹配模式:''{1}''。"/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
value="Interface type name ''{0}'' 必须匹配模式:''{1}''。"/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
@@ -148,14 +148,6 @@
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
@@ -186,7 +178,6 @@
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
@@ -207,7 +198,7 @@
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
value="方法名 ''{0}'' 必须匹配模式:''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
@@ -215,6 +206,5 @@
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation"/>
</module>
</module>

+ 2
- 2
weixin-java-common/pom.xml View File

@@ -7,11 +7,11 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.9.0</version>
<version>2.9.9.BETA</version>
</parent>

<artifactId>weixin-java-common</artifactId>
<name>WeiXin Java Tools - Common</name>
<name>Weixin Java Tools - Common</name>
<description>微信公众号、企业号Java SDK Common</description>

<dependencies>


+ 3
- 6
weixin-java-common/src/main/java/me/chanjar/weixin/common/session/Constants.java View File

@@ -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";
}

+ 8
- 8
weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java View File

@@ -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<String, Object> 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<String> getAttributeNames() {
if (!isValidInternal()) {
throw new IllegalStateException(sm.getString("sessionImpl.getAttributeNames.ise"));
throw new IllegalStateException(SM.getString("sessionImpl.getAttributeNames.ise"));
}

Set<String> 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();


+ 15
- 14
weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSessionManager.java View File

@@ -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);

}


+ 0
- 36
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/BeanUtils.java View File

@@ -32,7 +32,6 @@ public class BeanUtils {
* 检查bean里标记为@Required的field是否为空,为空则抛异常
*
* @param bean 要检查的bean对象
* @throws WxErrorException
*/
public static void checkRequiredFields(Object bean) throws WxErrorException {
List<String> requiredFields = Lists.newArrayList();
@@ -68,39 +67,4 @@ public class BeanUtils {
}
}

/**
* 将bean按照@XStreamAlias标识的字符串内容生成以之为key的map对象
*
* @param bean 包含@XStreamAlias的xml bean对象
* @return map对象
*/
public static Map<String, String> xmlBean2Map(Object bean) {
Map<String, String> result = Maps.newHashMap();
List<Field> 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;
}
}

+ 4
- 4
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java View File

@@ -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<DocumentBuilder> builderLocal = new ThreadLocal<DocumentBuilder>() {
private static final ThreadLocal<DocumentBuilder> BUILDER_LOCAL = new ThreadLocal<DocumentBuilder>() {
@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);
}


+ 2
- 2
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java View File

@@ -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 文件名


+ 12
- 1
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/HttpType.java View File

@@ -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
}

+ 5
- 2
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/okhttp/OkHttpMediaDownloadRequestExecutor.java View File

@@ -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;
}


+ 16
- 12
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/GsonHelper.java View File

@@ -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<String> 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) {


+ 0
- 8
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxAccessTokenAdapter.java View File

@@ -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.*;


+ 0
- 8
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxErrorAdapter.java View File

@@ -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.*;


+ 0
- 8
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxMediaUploadResultAdapter.java View File

@@ -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.*;


+ 11
- 12
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/res/StringManager.java View File

@@ -46,8 +46,7 @@ import java.util.*;
*/
public class StringManager {

private static final Map<String, Map<Locale, StringManager>> managers =
new Hashtable<>();
private static final Map<String, Map<Locale, StringManager>> 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<Locale, StringManager> map = managers.get(packageName);
Map<Locale, StringManager> 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, StringManager>(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);


+ 3
- 1
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java View File

@@ -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);


+ 6
- 4
weixin-java-common/src/test/java/me/chanjar/weixin/common/api/WxMessageInMemoryDuplicateCheckerTest.java View File

@@ -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);


+ 2
- 2
weixin-java-common/src/test/java/me/chanjar/weixin/common/session/SessionTest.java View File

@@ -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);

}


+ 12
- 2
weixin-java-cp/pom.xml View File

@@ -7,11 +7,11 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.9.0</version>
<version>2.9.9.BETA</version>
</parent>

<artifactId>weixin-java-cp</artifactId>
<name>WeiXin Java Tools - CP</name>
<name>Weixin Java Tools - CP</name>
<description>微信企业号Java SDK</description>

<dependencies>
@@ -69,6 +69,16 @@
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-guava</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>


+ 4
- 3
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpDepartmentService.java View File

@@ -29,11 +29,12 @@ public interface WxCpDepartmentService {

/**
* <pre>
* 部门管理接口 - 查询所有部门
* 详情请见: 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
* </pre>
* @param id 部门id。获取指定部门及其下的子部门。非必需,可为null
*/
List<WxCpDepart> listAll() throws WxErrorException;
List<WxCpDepart> list(Integer id) throws WxErrorException;

/**
* <pre>


+ 1
- 206
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java View File

@@ -19,9 +19,9 @@ import java.util.List;

/**
* 微信API的Service
* @author chanjaster
*/
public interface WxCpService {

/**
* <pre>
* 验证推送过来的消息的正确性
@@ -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;

/**
* <pre>
* 发送消息
@@ -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<WxCpDepart> 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<WxCpUser> userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException;

/**
* @deprecated 请使用 {@link WxCpUserService#listSimpleByDepartment(Integer, Boolean, Integer)}
*/
@Deprecated
List<WxCpUser> 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<WxCpTag> tagGet() throws WxErrorException;

/**
* @deprecated 请使用 {@link WxCpTagService#listUsersByTagId(String)}
*/
@Deprecated
List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException;

/**
* @deprecated 请使用 {@link WxCpTagService#addUsers2Tag(String, List, List)}
*/
@Deprecated
void tagAddUsers(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException;

/**
* @deprecated 请使用 {@link WxCpTagService#removeUsersFromTag(String, List)}
*/
@Deprecated
void tagRemoveUsers(String tagId, List<String> 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;

/**
* <pre>
* 邀请成员关注
* 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
* </pre>
*
* @param userId 用户的userid
* @param inviteTips 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。
* @return 1:微信邀请 2.邮件邀请
*/
int invite(String userId, String inviteTips) throws WxErrorException;

/**
* <pre>
* 获取微信服务器的ip段


+ 53
- 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java View File

@@ -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;

/**
* <pre>
@@ -80,4 +81,56 @@ public interface WxCpUserService {
* @param userid 用户id
*/
WxCpUser getById(String userid) throws WxErrorException;

/**
* <pre>
* 邀请成员关注
* 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
* </pre>
*
* @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;

/**
* <pre>
* userid转openid.
* 该接口使用场景为微信支付、微信红包和企业转账。
*
* 在使用微信支付的功能时,需要自行将企业微信的userid转成openid。
* 在使用微信红包功能时,需要将应用id和userid转成appid和openid才能使用。
* 注:需要成员使用微信登录企业微信或者关注微信插件才能转成openid
*
* 文档地址:https://work.weixin.qq.com/api/doc#11279
* </pre>
*
* @param userId 企业内的成员id
* @param agentId 非必填,整型,仅用于发红包。其它场景该参数不要填,如微信支付、企业转账、电子发票
* @return map对象,可能包含以下值:
* - openid 企业微信成员userid对应的openid,若有传参agentid,则是针对该agentid的openid。否则是针对企业微信corpid的openid
* - appid 应用的appid,若请求包中不包含agentid则不返回appid。该appid在使用微信红包时会用到
*/
Map<String, String> userId2Openid(String userId, Integer agentId) throws WxErrorException;

/**
* <pre>
* openid转userid
*
* 该接口主要应用于使用微信支付、微信红包和企业转账之后的结果查询。
* 开发者需要知道某个结果事件的openid对应企业微信内成员的信息时,可以通过调用该接口进行转换查询。
* 权限说明:
* 管理组需对openid对应的企业微信成员有查看权限。
*
* 文档地址:https://work.weixin.qq.com/api/doc#11279
* </pre>
*
* @param openid 在使用微信支付、微信红包和企业转账之后,返回结果的openid
* @return userid 该openid在企业微信对应的成员userid
*/
String openid2UserId(String openid) throws WxErrorException;
}

+ 5
- 5
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java View File

@@ -48,13 +48,13 @@ public class WxCpDepartmentServiceImpl implements WxCpDepartmentService {
}

@Override
public List<WxCpDepart> listAll() throws WxErrorException {
public List<WxCpDepart> 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"),


+ 1
- 1
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java View File

@@ -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


+ 0
- 206
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceAbstractImpl.java View File

@@ -138,188 +138,6 @@ public abstract class WxCpServiceAbstractImpl<H, P> 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<WxCpUser> userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException {
return this.getUserService().listByDepartment(departId, fetchChild, status);
}

@Override
@Deprecated
public List<WxCpUser> 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<WxCpTag> tagGet() throws WxErrorException {
return this.getTagService().listAll();
}

@Override
@Deprecated
public List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException {
return this.getTagService().listUsersByTagId(tagId);
}

@Override
@Deprecated
public void tagAddUsers(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException {
this.getTagService().addUsers2Tag(tagId, userIds, partyIds);
}

@Override
@Deprecated
public void tagRemoveUsers(String tagId, List<String> 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<H, P> 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<WxCpDepart> departGet() throws WxErrorException {
return this.getDepartmentService().listAll();
}

@Override
public RequestHttp getRequestHttp() {
return this;


+ 49
- 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java View File

@@ -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;

/**
* <pre>
@@ -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<String, String> 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<String, String> 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();
}
}

+ 8
- 2
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpUser.java View File

@@ -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;


+ 2
- 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessage.java View File

@@ -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;



+ 2
- 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessage.java View File

@@ -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;



+ 2
- 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessage.java View File

@@ -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;



+ 2
- 0
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessage.java View File

@@ -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;



+ 1
- 1
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/outxmlbuilder/BaseBuilder.java View File

@@ -23,7 +23,7 @@ public abstract class BaseBuilder<BuilderType, ValueType> {
public void setCommon(WxCpXmlOutMessage m) {
m.setToUserName(this.toUserName);
m.setFromUserName(this.fromUserName);
m.setCreateTime(System.currentTimeMillis() / 1000l);
m.setCreateTime(System.currentTimeMillis() / 1000L);
}

}

+ 2
- 2
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java View File

@@ -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


+ 7
- 4
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java View File

@@ -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;


+ 11
- 5
weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java View File

@@ -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, XStream> CLASS_2_XSTREAM_INSTANCE = configXStreamInstance();
@@ -38,7 +44,7 @@ public class XStreamTransformer {
}

/**
* pojo -> xml
* pojo -> xml.
*/
public static <T> String toXml(Class<T> clazz, T object) {
return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);


+ 9
- 9
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpMessageRouterTest.java View File

@@ -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);
}
}


+ 15
- 6
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImplTest.java View File

@@ -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<WxCpDepart> departList = this.wxCpService.getDepartmentService().listAll();
assertNotNull(departList);
assertTrue(departList.size() > 0);
List<WxCpDepart> 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();
}
}



+ 26
- 3
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImplTest.java View File

@@ -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;

/**
* <pre>
@@ -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<String, String> 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);
}
}

+ 3
- 3
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlMessageTest.java View File

@@ -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");


+ 1
- 1
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutImageMessageTest.java View File

@@ -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");



+ 1
- 1
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutNewsMessageTest.java View File

@@ -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");



+ 1
- 1
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutTextMessageTest.java View File

@@ -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");



+ 1
- 1
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVideoMessageTest.java View File

@@ -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");



+ 1
- 1
weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/WxCpXmlOutVoiceMessageTest.java View File

@@ -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");



+ 11
- 2
weixin-java-miniapp/pom.xml View File

@@ -7,10 +7,10 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.9.0</version>
<version>2.9.9.BETA</version>
</parent>
<artifactId>weixin-java-miniapp</artifactId>
<name>WeiXin Java Tools - MiniApp</name>
<name>Weixin Java Tools - MiniApp</name>
<description>微信小程序Java SDK</description>

<dependencies>
@@ -61,10 +61,19 @@
<artifactId>joda-time</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-guava</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>

<build>


+ 6
- 9
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaQrcodeService.java View File

@@ -7,7 +7,7 @@ import java.io.File;

/**
* <pre>
* 二维码相关操作接口
* 二维码相关操作接口.
*
* 接口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: 获取小程序页面二维码.
* <pre>
* 获取小程序页面二维码
* 适用于需要的码数量较少的业务场景
* 通过该接口,仅能生成已发布的小程序的二维码。
* 可以在开发者工具预览时生成开发版的带参二维码。
@@ -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
* 获取小程序码(永久有效、数量暂无限制)
* <p>
* 接口B: 获取小程序码(永久有效、数量暂无限制).
* <pre>
* 通过该接口生成的小程序码,永久有效,数量暂无限制。
* 用户扫描该码进入小程序后,将统一打开首页,开发者需在对应页面根据获取的码中 scene 字段的值,再做处理逻辑。
* 使用如下代码可以获取到二维码中的 scene 字段的值。
* 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode
*
* </pre>
* @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
* @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面
* @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调


+ 30
- 16
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java View File

@@ -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;
/**
* <pre>
* 验证消息的确来自微信服务器
* 验证消息的确来自微信服务器.
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
* </pre>
*/
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 {

/**
* <pre>
* 获取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 {

/**
* <pre>
* 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试
* 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试.
* 默认:1000ms
* </pre>
*/
@@ -75,59 +83,65 @@ public interface WxMaService {

/**
* <pre>
* 设置当微信系统响应系统繁忙时,最大重试次数
* 设置当微信系统响应系统繁忙时,最大重试次数.
* 默认:5次
* </pre>
*/
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();



+ 89
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaTemplateService.java View File

@@ -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";

/**
* <pre>
* 获取小程序模板库标题列表
*
* 详情请见: <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1500465446_j4CgR&token=&lang=zh_CN">获取小程序模板库标题列表</a>
* 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list?access_token=ACCESS_TOKEN
* </pre>
* @param offset
* @param count
* @return
*/
WxMaTemplateLibraryListResult findTemplateLibraryList(int offset, int count) throws WxErrorException;

/**
* <pre>
* 获取模板库某个模板标题下关键词库
*
* 详情请见: <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1500465446_j4CgR&token=&lang=zh_CN">获取小程序模板库标题列表</a>
* 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token=ACCESS_TOKEN
* </pre>
* @param id
* @return
*/
WxMaTemplateLibraryGetResult findTemplateLibraryKeywordList(String id) throws WxErrorException;

/**
* <pre>
* 组合模板并添加至帐号下的个人模板库
*
* 详情请见: <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1500465446_j4CgR&token=&lang=zh_CN">获取小程序模板库标题列表</a>
* 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/add?access_token=ACCESS_TOKEN
* </pre>
* @param id
* @param keywordIdList
* @return
*/
WxMaTemplateAddResult addTemplate(String id, List<Integer> keywordIdList) throws WxErrorException;

/**
* <pre>
* 获取帐号下已存在的模板列表
*
* 详情请见: <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1500465446_j4CgR&token=&lang=zh_CN">获取小程序模板库标题列表</a>
* 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=ACCESS_TOKEN
* </pre>
* @param offset
* @param count
* @return
*/
WxMaTemplateListResult findTemplateList(int offset, int count) throws WxErrorException;

/**
* <pre>
* 删除帐号下的某个模板
*
* 详情请见: <a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1500465446_j4CgR&token=&lang=zh_CN">获取小程序模板库标题列表</a>
* 接口url格式: https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=ACCESS_TOKEN
* </pre>
* @param templateId
*/
boolean delTemplate(String templateId) throws WxErrorException;
}

+ 14
- 5
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
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 微信用户基本信息


+ 2
- 1
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java View File

@@ -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);


+ 45
- 14
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpClient, HttpHost> {
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<CloseableHttpCl
private WxMaMediaService materialService = new WxMaMediaServiceImpl(this);
private WxMaUserService userService = new WxMaUserServiceImpl(this);
private WxMaQrcodeService qrCodeService = new WxMaQrcodeServiceImpl(this);
private WxMaTemplateService templateService = new WxMaTemplateServiceImpl(this);

private int retrySleepMillis = 1000;
private int maxRetryTimes = 5;
@@ -120,6 +133,19 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
return this.getWxMaConfig().getAccessToken();
}

@Override
public WxMaJscode2SessionResult jsCode2SessionInfo(String jsCode) throws WxErrorException {
final WxMaConfig config = getWxMaConfig();
Map<String, String> 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<CloseableHttpCl
public WxMaQrcodeService getQrcodeService() {
return this.qrCodeService;
}

@Override
public WxMaTemplateService getTemplateService() {
return this.templateService;
}
}

+ 101
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImpl.java View File

@@ -0,0 +1,101 @@
package cn.binarywang.wx.miniapp.api.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaTemplateService;
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.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class WxMaTemplateServiceImpl implements WxMaTemplateService {

private WxMaService wxMaService;

public WxMaTemplateServiceImpl(WxMaService wxMaService){
this.wxMaService = wxMaService;
}

@Override
public WxMaTemplateLibraryListResult findTemplateLibraryList(int offset, int count) throws WxErrorException {

Map<String, Integer> 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<String, String> 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<Integer> keywordIdList) throws WxErrorException {

Map<String, Object> 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<String, Integer> 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<String, String> 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);
}
}
}

+ 9
- 16
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
@@ -25,15 +22,7 @@ public class WxMaUserServiceImpl implements WxMaUserService {

@Override
public WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException {
final WxMaConfig config = service.getWxMaConfig();
Map<String, String> 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);
}



+ 4
- 2
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/AbstractWxMaQrcodeWrapper.java View File

@@ -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();
}

}

+ 5
- 5
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java View File

@@ -8,8 +8,11 @@ import lombok.EqualsAndHashCode;
import java.io.Serializable;

/**
* {"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","expires_in":2592000,"openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"}
*
* <pre>
* code换取session_key接口的响应
* 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject
* 微信返回报文:{"session_key":"nzoqhc3OnwHzeTxJs+inbQ==","openid":"oVBkZ0aYgDMDIywRdgPW8-joxXc4"}
* </pre>
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@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;



+ 81
- 16
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessage.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
@@ -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);
}

}

+ 7
- 5
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java View File

@@ -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 配置存储器对象


+ 30
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaPhoneNumberInfo.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
@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;
}
}

+ 23
- 5
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaTemplateMessage.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class WxMaTemplateMessage implements Serializable {
private static final long serialVersionUID = 5063374783759519418L;

/**
* 接收者(用户)的 openid.
* <pre>
* 参数:touser
* 是否必填: 是
@@ -28,6 +32,7 @@ public class WxMaTemplateMessage implements Serializable {
private String toUser;

/**
* 所需下发的模板消息的id.
* <pre>
* 参数:template_id
* 是否必填: 是
@@ -37,6 +42,7 @@ public class WxMaTemplateMessage implements Serializable {
private String templateId;

/**
* 点击模板卡片后的跳转页面,仅限本小程序内的页面.
* <pre>
* 参数:page
* 是否必填: 否
@@ -46,6 +52,7 @@ public class WxMaTemplateMessage implements Serializable {
private String page;

/**
* 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id.
* <pre>
* 参数:form_id
* 是否必填: 是
@@ -55,16 +62,17 @@ public class WxMaTemplateMessage implements Serializable {
private String formId;

/**
* 模板内容,不填则下发空模板.
* <pre>
* 参数:data
* 是否必填: 是
* 描述: 模板内容,不填则下发空模板
* </pre>
*/
@Builder.Default
private final List<Data> data = new ArrayList<>();
private List<Data> data;

/**
* 模板内容字体的颜色,不填默认黑色.
* <pre>
* 参数:color
* 是否必填: 否
@@ -74,6 +82,7 @@ public class WxMaTemplateMessage implements Serializable {
private String color;

/**
* 模板需要放大的关键词,不填则默认无放大.
* <pre>
* 参数: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);
}


+ 1
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java View File

@@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode;
import java.io.Serializable;

/**
* 小程序码接口B.
*
* @author Element
* @date 2017/7/27


+ 20
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateAddResult.java View File

@@ -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);
}
}

+ 31
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryGetResult.java View File

@@ -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<KeywordInfo> 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);
}
}

+ 28
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateLibraryListResult.java View File

@@ -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<TemplateItem> 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;
}
}

+ 29
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/template/WxMaTemplateListResult.java View File

@@ -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<TemplateInfo> 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;
}
}

+ 0
- 27
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public final class ImageBuilder extends BaseBuilder<ImageBuilder> {
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;
}
}

+ 30
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageMessageBuilder.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public final class ImageMessageBuilder extends BaseBuilder<ImageMessageBuilder> {
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;
}
}

+ 53
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/LinkMessageBuilder.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class LinkMessageBuilder extends BaseBuilder<LinkMessageBuilder> {
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;
}
}

+ 47
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/MaPageMessageBuilder.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class MaPageMessageBuilder extends BaseBuilder<MaPageMessageBuilder> {
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;
}
}

+ 0
- 27
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextBuilder.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public final class TextBuilder extends BaseBuilder<TextBuilder> {
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;
}
}

+ 30
- 0
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/TextMessageBuilder.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public final class TextMessageBuilder extends BaseBuilder<TextMessageBuilder> {
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;
}
}

+ 19
- 11
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java View File

@@ -2,29 +2,29 @@ package cn.binarywang.wx.miniapp.constant;

/**
* <pre>
* 小程序常量
* 小程序常量.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
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;
}


+ 4
- 4
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java View File

@@ -37,17 +37,17 @@ public class QrCodeRequestExecutor implements RequestExecutor<File, AbstractWxMa
HttpPost httpPost = new HttpPost(uri);
if (requestHttp.getRequestHttpProxy() != null) {
httpPost.setConfig(
RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build()
RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build()
);
}
httpPost.setEntity(new StringEntity(ticket.toString()));
httpPost.setEntity(new StringEntity(ticket.toJson()));

try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost);
InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) {
Header[] contentTypeHeader = response.getHeaders("Content-Type");
if (contentTypeHeader != null && contentTypeHeader.length > 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));
}


+ 0
- 2
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaGsonBuilder.java View File

@@ -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());
}



+ 0
- 46
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxMaKefuMessageGsonAdapter implements JsonSerializer<WxMaKefuMessage> {

@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;
}

}

+ 8
- 4
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
@@ -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);
}



+ 9
- 23
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
*/
@@ -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超链接:<a href=\"http://www.baidu.com\">Hello World</a>");
TestConfig config = (TestConfig) this.wxService.getWxMaConfig();
WxMaKefuMessage message = WxMaKefuMessage.newTextBuilder()
.toUser(config.getOpenid())
.content("欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>")
.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);
}



+ 70
- 0
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaTemplateServiceImplTest.java View File

@@ -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<Integer> 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<Integer> 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());
}
}

+ 17
- 6
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImplTest.java View File

@@ -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());
}
}

+ 38
- 21
weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaKefuMessageTest.java View File

@@ -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 <a href="https://github.com/binarywang">Binary Wang</a>
@@ -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\"}}");
}




weixin-java-miniapp/src/test/resources/test-config.sample.xml → weixin-java-miniapp/src/test/resources/test-config-sample.xml View File


+ 11
- 2
weixin-java-mp/pom.xml View File

@@ -7,10 +7,10 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId>
<version>2.9.0</version>
<version>2.9.9.BETA</version>
</parent>
<artifactId>weixin-java-mp</artifactId>
<name>WeiXin Java Tools - MP</name>
<name>Weixin Java Tools - MP</name>
<description>微信公众号Java SDK</description>

<dependencies>
@@ -65,6 +65,15 @@
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-guava</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>

<build>


+ 2
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java View File

@@ -85,6 +85,8 @@ public interface WxMpConfigStorage {

String getAesKey();

String getTemplateId();

long getExpiresTime();

String getOauth2redirectUri();


+ 10
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java View File

@@ -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;


+ 11
- 11
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java View File

@@ -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);
}
}
}

+ 14
- 14
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java View File

@@ -7,7 +7,7 @@ import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;

/**
* <pre>
* 群发消息服务类
* 群发消息服务类.
* Created by Binary Wang on 2017-8-16.
* </pre>
*
@@ -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";

/**
* <pre>
* 上传群发用的图文消息,上传后才能群发图文消息
* 上传群发用的图文消息,上传后才能群发图文消息.
*
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
* </pre>
@@ -53,7 +53,7 @@ public interface WxMpMassMessageService {

/**
* <pre>
* 上传群发用的视频,上传后才能群发视频消息
* 上传群发用的视频,上传后才能群发视频消息.
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN
* </pre>
*
@@ -64,7 +64,7 @@ public interface WxMpMassMessageService {

/**
* <pre>
* 分组群发消息
* 分组群发消息.
* 如果发送图文消息,必须先使用 {@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 {

/**
* <pre>
* 按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 {

/**
* <pre>
* 群发消息预览接口
* 群发消息预览接口.
* 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版。为了满足第三方平台开发者的需求,在保留对openID预览能力的同时,增加了对指定微信号发送预览的能力,但该能力每日调用次数有限制(100次),请勿滥用。
* 接口调用请求说明
* http请求方式: POST
@@ -98,7 +98,7 @@ public interface WxMpMassMessageService {

/**
* <pre>
* 删除群发
* 删除群发.
* 群发之后,随时可以通过该接口删除群发。
* 请注意:
* 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;

}

+ 12
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java View File

@@ -130,6 +130,16 @@ public class WxMpMessageRouter {
* 处理微信消息
*/
public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage, final Map<String, Object> context) {
return route(wxMessage, context, null);
}
/**
* 处理微信消息
*/
public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage, final Map<String, Object> 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);


+ 8
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java View File

@@ -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();

/**
* 返回硬件平台相关接口方法的实现类对象,以方便调用其各个接口
*


+ 40
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpSubscribeMsgService.java View File

@@ -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;

/**
* <pre>
* 一次性订阅消息接口
* https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1500374289_66bvB
* </pre>
*
* @author Mklaus
* @date 2018-01-22 上午11:07
*/
public interface WxMpSubscribeMsgService {

/**
* <pre>
* 构造用户订阅一条模板消息授权的url连接
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1500374289_66bvB
* </pre>
*
* @param redirectURI 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode
* @param scene 重定向后会带上scene参数,开发者可以填0-10000的整形值,用来标识订阅场景值
* @param reserved 用于保持请求和回调的状态,授权请后原样带回给第三方 (最多128字节,要求做urlencode)
* @return url
*/
String subscribeMsgAuthorizationUrl(String redirectURI, int scene, String reserved);

/**
* <pre>
* 发送一次性订阅消息
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1500374289_66bvB
* </pre>
*
* @return 消息Id
*/
boolean sendSubscribeMessage(WxMpSubscribeMessage message) throws WxErrorException;

}

+ 1
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpCardServiceImpl.java View File

@@ -213,7 +213,7 @@ public class WxMpCardServiceImpl implements WxMpCardService {
WxMpCardResult cardResult = WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement,
new TypeToken<WxMpCardResult>() {
}.getType());
if (!cardResult.getErrorCode().equals("0")) {
if (!"0".equals(cardResult.getErrorCode())) {
this.log.warn("朋友的券mark失败:{}", cardResult.getErrorMsg());
}
}


+ 1
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java View File

@@ -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);


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save