Przeglądaj źródła

add 用户隐私指引

master
xhxu 3 lat temu
rodzic
commit
5ae5ed841e
63 zmienionych plików z 6505 dodań i 6 usunięć
  1. +2
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxAuthorizerInfo.java
  2. +2
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxWeappBasicSet.java
  3. +1
    -0
      mallinkService/src/main/java/com/iformall/service/WxAuthorizerInfoService.java
  4. +12
    -5
      mallinkService/src/main/java/com/iformall/service/impl/WxAuthorizerInfoServiceImpl.java
  5. +12
    -0
      mallinkService/src/main/resources/mapper/WxAuthorizerInfoMapper.xml
  6. +2
    -1
      mallinkService/src/main/resources/mapper/WxWeappBasicSetMapper.xml
  7. +1
    -0
      mlToutiaoOpen/.gitignore
  8. +179
    -0
      mlToutiaoOpen/pom.xml
  9. +62
    -0
      mlToutiaoOpen/src/main/java/com/iformall/WechatOpenApplication.java
  10. +59
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/AsyncConfig.java
  11. +52
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/AwsProperty.java
  12. +32
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/KaptchaConfig.java
  13. +72
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/RedisConfig.java
  14. +58
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/RestFilter.java
  15. +24
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/RestTemplateConfig.java
  16. +305
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/ShiroConfig.java
  17. +31
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/ShiroLoginFilter.java
  18. +89
    -0
      mlToutiaoOpen/src/main/java/com/iformall/config/WebConfig.java
  19. +124
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/HomeController.java
  20. +106
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WechatAuthController.java
  21. +415
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WechatCalllbackController.java
  22. +133
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WechatMediaController.java
  23. +703
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappCodeController.java
  24. +79
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappDraftTemplateController.java
  25. +175
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappMsgTemplateController.java
  26. +231
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappSetController.java
  27. +63
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WxWeappBasicSetController.java
  28. +138
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WxWeappExtSetController.java
  29. +1047
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/WxWeappInfoController.java
  30. +45
    -0
      mlToutiaoOpen/src/main/java/com/iformall/controller/base/BaseController.java
  31. +76
    -0
      mlToutiaoOpen/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java
  32. +70
    -0
      mlToutiaoOpen/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java
  33. +125
    -0
      mlToutiaoOpen/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java
  34. +17
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/builder/AbstractBuilder.java
  35. +24
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/builder/ImageBuilder.java
  36. +25
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/builder/TextBuilder.java
  37. +114
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMemController.java
  38. +190
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMenuController.java
  39. +152
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMpCallBackController.java
  40. +70
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMpTemplateController.java
  41. +45
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxRedirectController.java
  42. +29
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/error/ErrorController.java
  43. +27
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/error/ErrorPageConfiguration.java
  44. +144
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/manager/WxMpManager.java
  45. +22
    -0
      mlToutiaoOpen/src/main/java/com/iformall/mp/utils/MpUtil.java
  46. +52
    -0
      mlToutiaoOpen/src/main/java/com/iformall/schedule/AppAccessTokenSchedule.java
  47. +18
    -0
      mlToutiaoOpen/src/main/java/com/iformall/schedule/SchedulingConfig.java
  48. +80
    -0
      mlToutiaoOpen/src/main/java/com/iformall/schedule/UserUnionIdSchedule.java
  49. +24
    -0
      mlToutiaoOpen/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java
  50. +90
    -0
      mlToutiaoOpen/src/main/java/com/iformall/shiro/MyShiroRealm.java
  51. +32
    -0
      mlToutiaoOpen/src/main/java/com/iformall/shiro/PasswordHelper.java
  52. +126
    -0
      mlToutiaoOpen/src/main/java/com/iformall/shiro/ShiroService.java
  53. +11
    -0
      mlToutiaoOpen/src/main/java/com/iformall/shiro/UserSession.java
  54. +39
    -0
      mlToutiaoOpen/src/main/java/com/iformall/shiro/UseriFormallToken.java
  55. +61
    -0
      mlToutiaoOpen/src/main/java/com/iformall/utils/ShiroUtils.java
  56. +15
    -0
      mlToutiaoOpen/src/main/java/com/iformall/utils/UrlCheck.java
  57. +125
    -0
      mlToutiaoOpen/src/main/resources/application-dev.yml
  58. +110
    -0
      mlToutiaoOpen/src/main/resources/application-prod.yml
  59. +109
    -0
      mlToutiaoOpen/src/main/resources/application-test.yml
  60. +52
    -0
      mlToutiaoOpen/src/main/resources/application.yml
  61. +100
    -0
      mlToutiaoOpen/src/main/resources/logback-spring.xml
  62. +76
    -0
      mlWechatOpen/src/main/java/com/iformall/controller/WechatWeappSetController.java
  63. +1
    -0
      pom.xml

+ 2
- 0
mallinkService/src/main/java/com/iformall/domain/po/WxAuthorizerInfo.java Wyświetl plik

@@ -54,6 +54,8 @@ public class WxAuthorizerInfo extends BaseEntity {
private Integer templateStatus;
@io.swagger.annotations.ApiModelProperty(value="微信小程序模板设置时间",name="templateTime")
private Date templateTime;
@io.swagger.annotations.ApiModelProperty(value="微信小程序用户隐私指引,0为已设置,1为设置失败",name="privacySettingStatus")
private Integer privacySettingStatus;
@io.swagger.annotations.ApiModelProperty(value="小程序每月审核撤回次数",name="auditBackNum")
private Integer auditBackNum;
@io.swagger.annotations.ApiModelProperty(value="微信小程序审核最后撤回时间",name="auditBackTime")


+ 2
- 0
mallinkService/src/main/java/com/iformall/domain/po/WxWeappBasicSet.java Wyświetl plik

@@ -25,6 +25,8 @@ public class WxWeappBasicSet extends BaseEntity {
private String version;
@io.swagger.annotations.ApiModelProperty(value="模板库信息",name="templateInfo")
private String templateInfo;
@io.swagger.annotations.ApiModelProperty(value="小程序用户隐私保护指引",name="privacySetting")
private String privacySetting;
@io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate")
private Date createDate;
@io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateDate")


+ 1
- 0
mallinkService/src/main/java/com/iformall/service/WxAuthorizerInfoService.java Wyświetl plik

@@ -84,4 +84,5 @@ public interface WxAuthorizerInfoService {

int updateAuthBackInfo(WxAuthorizerInfo record);

int updatePrivacySetting(WxAuthorizerInfo authorizerInfo);
}

+ 12
- 5
mallinkService/src/main/java/com/iformall/service/impl/WxAuthorizerInfoServiceImpl.java Wyświetl plik

@@ -229,9 +229,16 @@ public class WxAuthorizerInfoServiceImpl implements WxAuthorizerInfoService {
}
return 0;
}

@Override
public int updatePrivacySetting(WxAuthorizerInfo record) {
Date curDate = new Date();
WxAuthorizerInfo info = new WxAuthorizerInfo();
info.setId(record.getId());
info.setPrivacySettingStatus(record.getPrivacySettingStatus());
info.setUpdateTime(curDate);
return authorizerInfoMapper.updateById(info);
}


}

+ 12
- 0
mallinkService/src/main/resources/mapper/WxAuthorizerInfoMapper.xml Wyświetl plik

@@ -21,6 +21,8 @@
<result column="webdomain_time" jdbcType="TIMESTAMP" property="webdomainTime"/>
<result column="template_status" jdbcType="INTEGER" property="templateStatus"/>
<result column="template_time" jdbcType="TIMESTAMP" property="templateTime"/>
<result column="privacy_setting_status" jdbcType="INTEGER" property="privacySettingStatus"/>

<result column="current_version" jdbcType="VARCHAR" property="currentVersion"/>
<result column="current_desc" jdbcType="VARCHAR" property="currentDesc"/>
<result column="release_time" jdbcType="TIMESTAMP" property="releaseTime"/>
@@ -34,6 +36,7 @@
<sql id="allColumns">
`id`,`tenant_id`,`type`,`authorizer_appid`,`head_img`,`alias`,`qrcode_url`,`create_time`,`authorization_status`,`auth_time`,
`base_status`, `base_time`, `domain_status`, `domain_time`, `webdomain_status`, `webdomain_time`, `template_status`, `template_time`,
`privacy_setting_status`,
`current_version`,`current_desc`,`release_time`,
`open_appid`,`bind_open_time`,`refresh_token`,
`access_token`,`access_token_expire`
@@ -98,6 +101,9 @@
<if test=" null != templateTime ">
and `template_time` = #{templateTime}
</if>
<if test=" null != privacySettingStatus ">
and `privacy_setting_status` = #{privacySettingStatus}
</if>
<if test=" null != currentVersion ">
and `current_version` = #{currentVersion}
</if>
@@ -201,6 +207,8 @@
<result column="webdomain_time" jdbcType="TIMESTAMP" property="webdomainTime"/>
<result column="template_status" jdbcType="INTEGER" property="templateStatus"/>
<result column="template_time" jdbcType="TIMESTAMP" property="templateTime"/>
<result column="privacy_setting_status" jdbcType="INTEGER" property="privacySettingStatus"/>

<result column="current_version" jdbcType="VARCHAR" property="currentVersion"/>
<result column="current_desc" jdbcType="VARCHAR" property="currentDesc"/>
<result column="release_time" jdbcType="TIMESTAMP" property="releaseTime"/>
@@ -216,6 +224,7 @@
ai.`domain_status`,ai.`domain_time`,
ai.`webdomain_status`,ai.`webdomain_time`,
ai.`template_status`,ai.`template_time`,
ai.`privacy_setting_status`,
ai.`current_version` as `current_version`,ai.`current_desc`,ai.`release_time`,
ai.`open_appid`,ai.`bind_open_time`,
a.`name` as `name`
@@ -268,6 +277,9 @@
<if test=" null != templateTime ">
and ai.`template_time` = #{templateTime}
</if>
<if test=" null != privacySettingStatus ">
and ai.`privacy_setting_status` = #{privacySettingStatus}
</if>
<if test=" null != currentVersion ">
and ai.`current_version` = #{currentVersion}
</if>


+ 2
- 1
mallinkService/src/main/resources/mapper/WxWeappBasicSetMapper.xml Wyświetl plik

@@ -8,12 +8,13 @@
<result column="domain_url" jdbcType="VARCHAR" property="domainUrl"/>
<result column="version" jdbcType="VARCHAR" property="version"/>
<result column="template_info" jdbcType="VARCHAR" property="templateInfo"/>
<result column="privacy_setting" jdbcType="VARCHAR" property="privacySetting"/>
<result column="create_date" jdbcType="TIMESTAMP" property="createDate"/>
<result column="update_date" jdbcType="TIMESTAMP" property="updateDate"/>
</resultMap>

<sql id="allColumns">
`id`,`type`,`domain_url`,`version`,`template_info`,`create_date`,`update_date`
`id`,`type`,`domain_url`,`version`,`template_info`,`privacy_setting`,`create_date`,`update_date`
</sql>

<sql id="dynamicWhereConditions">


+ 1
- 0
mlToutiaoOpen/.gitignore Wyświetl plik

@@ -0,0 +1 @@
/target/

+ 179
- 0
mlToutiaoOpen/pom.xml Wyświetl plik

@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>mallink</artifactId>
<groupId>com.iformall</groupId>
<version>1.0</version>
</parent>

<artifactId>mlToutiaoOpen</artifactId>

<properties>
</properties>

<dependencies>
<dependency>
<groupId>com.iformall</groupId>
<artifactId>mallinkService</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>

<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<layout>ZIP</layout>
<excludeGroupIds>
antlr,
cn.afterturn,
ch.qos.logback,
com.alibaba,
com.amazonaws,
com.baomidou,
com.mchange,
com.fasterxml.jackson.core,
com.fasterxml.jackson.dataformat,
com.fasterxml.jackson.datatype,
com.fasterxml.jackson.module,
com.fasterxml.uuid,
com.fasterxml,
com.github.axet,
com.github.jsqlparser,
com.github.pagehelper,
com.github.ulisesbocchio,
com.github.virtuald,
com.google.code.findbugs,
com.google.code.gson,
com.google.errorprone,
com.google.guava,
com.google.protobuf,
com.google.zxing,
com.jayway.jsonpath,
com.jhlabs,
com.puppycrawl.tools,
com.rabbitmq,
com.squareup.okhttp3,
com.squareup.okio,
com.sun,
com.sun.mail,
com.sun.xml.messaging.saaj,
com.thoughtworks.xstream,
com.zaxxer,
commons-beanutils,
commons-cli,
commons-codec,
commons-collections,
commons-fileupload,
commons-io,
commons-logging,
io.lettuce,
io.netty,
io.projectreactor,
io.springfox,
io.swagger,
io.undertow,
javax.activation,
javax.annotation,
javax.mail,
javax.persistence,
javax.servlet,
javax.validation,
javax.xml.bind,
javax.xml.soap,
javax.xml.ws,
joda-time,
junit,
mysql,
net.bytebuddy,
net.minidev,
net.sf.dozer,
net.sf.saxon,
ognl,
org.antlr,
org.apache.commons,
org.apache.httpcomponents,
org.apache.logging.log4j,
org.apache.poi,
org.apache.poi.wso2,
org.apache.rocketmq,
org.apache.shiro,
org.apache.tomcat.embed,
org.apache.xmlbeans,
org.aspectj,
org.assertj,
org.bouncycastle,
org.checkerframework,
org.codehaus.mojo,
org.crazycake,
org.dom4j,
org.flowable,
org.flywaydb,
org.glassfish,
org.hibernate.validator,
org.jasypt,
org.javassist,
org.jboss.logging,
org.jboss.spec.javax.annotation,
org.jboss.spec.javax.websocket,
org.jboss.xnio,
org.jdom,
org.jodd,
org.jvnet.mimepull,
org.jvnet.staxex,
org.mapstruct,
org.mockito,
org.mybatis,
org.mybatis.generator,
org.mybatis.spring.boot,
org.ow2.asm,
org.projectlombok,
org.quartz-scheduler,
org.reactivestreams,
org.reflections,
org.rocketmq.spring.boot,
org.slf4j,
org.springframework,
org.springframework.amqp,
org.springframework.boot,
org.springframework.data,
org.springframework.retry,
org.springframework.ws,
org.yaml,
redis.clients,
software.amazon.ion,
tk.mybatis,
xmlpull,
xpp3
</excludeGroupIds>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 62
- 0
mlToutiaoOpen/src/main/java/com/iformall/WechatOpenApplication.java Wyświetl plik

@@ -0,0 +1,62 @@
package com.iformall;

import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
* @author stormeye
* @date 2019-01-14
*/
@SpringBootApplication
@MapperScan("com.iformall.mapper")
@EnableSwagger2
@EnableEncryptableProperties
public class WechatOpenApplication {

@Value("${fm.exception}")
private boolean fmException;

@Value("${fm.exception_emails}")
private String fmExceptionEmails;

@Value("${fm.audit_emails}")
private String fmAuditEmails;

@Value("${fm.deploy}")
private Integer fmDeploy;

@Value("${fm.upload_dir}")
private String uploadDir;

@Bean
public boolean isFmException() {
return fmException;
}

@Bean
public String fmExceptionEmails() {
return fmExceptionEmails;
}

@Bean
public String fmAuditEmails() {
return fmAuditEmails;
}

@Bean
public Integer getFmDeploy() { return fmDeploy; }

@Bean
public String fmUploadDir() {
return uploadDir;
}

public static void main(String[] args) {
SpringApplication.run(WechatOpenApplication.class, args);
}
}

+ 59
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/AsyncConfig.java Wyświetl plik

@@ -0,0 +1,59 @@
package com.iformall.config;


import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
private Logger logger = LoggerFactory.getLogger(getClass());

@Value("${thread.pool.corePoolSize:10}")
private int corePoolSize;

@Value("${thread.pool.maxPoolSize:20}")
private int maxPoolSize;

@Value("${thread.pool.keepAliveSeconds:4}")
private int keepAliveSeconds;

@Value("${thread.pool.queueCapacity:512}")
private int queueCapacity;

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setQueueCapacity(queueCapacity);
executor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor exe) -> {
logger.warn("当前任务线程池队列已满.");
});
executor.initialize();
logger.info("限定线程池大小");
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
logger.error("线程池执行任务发生未知异常.", ex);
}
};
}
}

+ 52
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/AwsProperty.java Wyświetl plik

@@ -0,0 +1,52 @@
package com.iformall.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
* @author Stormeye
*/
@Component
@ConfigurationProperties(prefix = "aws")
public class AwsProperty {
// AWS ACCESS KEY
private String access;

private String secret;

private String clientRegion;

private String bucketName;

public String getAccess() {
return access;
}

public void setAccess(String access) {
this.access = access;
}

public String getSecret() {
return secret;
}

public void setSecret(String secret) {
this.secret = secret;
}

public String getClientRegion() {
return clientRegion;
}

public void setClientRegion(String clientRegion) {
this.clientRegion = clientRegion;
}

public String getBucketName() {
return bucketName;
}

public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
}

+ 32
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/KaptchaConfig.java Wyświetl plik

@@ -0,0 +1,32 @@
package com.iformall.config;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;


/**
* 生成验证码配置
*
* @author stormeye.wu
* @email wugq@mippoint.com
* @date 2017-04-20 19:22
*/
@Configuration
public class KaptchaConfig {

@Bean
public DefaultKaptcha producer() {
Properties properties = new Properties();
properties.put("kaptcha.border", "no");
properties.put("kaptcha.textproducer.font.color", "black");
properties.put("kaptcha.textproducer.char.space", "5");
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

+ 72
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/RedisConfig.java Wyświetl plik

@@ -0,0 +1,72 @@
package com.iformall.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;

import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* Created by Stormeye on 2018/10/1.
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

//缓存管理器
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
/*
//user信息缓存配置
RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)).disableCachingNullValues().prefixKeysWith("user");
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
redisCacheConfigurationMap.put("user", userCacheConfiguration);
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
// 设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现
// ClassLoader loader = this.getClass().getClassLoader();
// JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader);
// RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer);
// RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
//设置默认超过期时间是30秒
defaultCacheConfig.entryTtl(Duration.ofSeconds(30));
//初始化RedisCacheManager
RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap);
return cacheManager;
*/
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置
.disableCachingNullValues(); // 不缓存空值

// 设置一个初始化的缓存空间set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("my-redis-cache1");
cacheNames.add("my-redis-cache2");

// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("my-redis-cache1", config);
configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));

RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory) // 使用自定义的缓存配置初始化一个cacheManager
.initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}

}

+ 58
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/RestFilter.java Wyświetl plik

@@ -0,0 +1,58 @@
package com.iformall.config;

import java.io.IOException;
import java.util.Optional;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 前后端分离RESTful接口过滤器
*
* @author xuguoqin
*
*/
public class RestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = null;
if (request instanceof HttpServletRequest) {
req = (HttpServletRequest) request;
}
HttpServletResponse res = null;
if (response instanceof HttpServletResponse) {
res = (HttpServletResponse) response;
}
if (req != null && res != null) {
//设置允许传递的参数
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
//设置允许带上cookie
res.setHeader("Access-Control-Allow-Credentials", "true");
String origin = Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer"));
//设置允许的请求来源
res.setHeader("Access-Control-Allow-Origin", origin);
//设置允许的请求方法
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}

+ 24
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/RestTemplateConfig.java Wyświetl plik

@@ -0,0 +1,24 @@
package com.iformall.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//ms
factory.setConnectTimeout(10000);//ms
return factory;
}
}

+ 305
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/ShiroConfig.java Wyświetl plik

@@ -0,0 +1,305 @@
package com.iformall.config;

import com.iformall.service.MallPermissionService;
import com.iformall.shiro.MyRetryLimitCredentialsMatcher;
import com.iformall.shiro.MyShiroRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;
import java.util.Map;


/**
* Created by yangqj on 2017/4/23.
*/
@Configuration
public class ShiroConfig {
@Autowired(required = false)
private MallPermissionService resourcesService;

@Value("${spring.redis.host}")
private String host;

@Value("${spring.redis.port}")
private int port;

@Value("${spring.redis.timeout}")
private int timeout;

@Value("${spring.redis.expire}")
private int expire;

@Value("${spring.redis.password}")
private String password;

@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}

/**
* ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
* @return
*/
// @Bean
// public ShiroDialect shiroDialect() {
// return new ShiroDialect();
// }

/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
* <p>
* Filter Chain定义说明
* 1、一个URL可以配置多个Filter,使用逗号分隔
* 2、当设置多个过滤器时,全部验证通过,才视为通过
* 3、部分过滤器可指定参数,如perms,roles
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
filters.put("token", new ShiroLoginFilter());
filters.put("corsFilter", new RestFilter());
//filters.put("authc", new MyFormAuthenticationFilter());
shiroFilterFactoryBean.setFilters(filters);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/#/");
// 登录成功后要跳转的链接

shiroFilterFactoryBean.setSuccessUrl("/usersPage");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
//拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了

//filterChainDefinitionMap.put("/ue/**", "anon");
//filterChainDefinitionMap.put("/config.json", "anon");

// 静态文件
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/font-awesome/**", "anon");
//<!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//自定义加载权限资源关系
// Map<String,Object> map = new HashMap<>();
// List<SysPermission> resourcesList = resourcesService.list(map);
// for(SysPermission resources:resourcesList){
//
// if (StringUtil.isNotEmpty(resources.getUrl())) {
// String permission = "perms[" + resources.getUrl()+ "]";
// filterChainDefinitionMap.put(resources.getUrl(),permission);
// }
// }

// 登录
filterChainDefinitionMap.put("/captcha.jpg", "anon");
filterChainDefinitionMap.put("/doLogin/**", "anon");
filterChainDefinitionMap.put("/version", "anon");

/// swagger-ui.html
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");

// 第三方平台
filterChainDefinitionMap.put("/wxOpen/**", "anon");
filterChainDefinitionMap.put("/wx/**", "anon");
filterChainDefinitionMap.put("/wxCardIO/**", "anon");


// filterChainDefinitionMap.put("/role/**", "corsFilter,token");
filterChainDefinitionMap.put("/**", "corsFilter,token,authc");
// filterChainDefinitionMap.put("/**", "anon");


shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}


public static boolean isAjax(ServletRequest request) {
String header = ((HttpServletRequest) request).getHeader("X-Requested-With");
if ("XMLHttpRequest".equalsIgnoreCase(header)) {
System.out.println("当前请求为Ajax请求");
return Boolean.TRUE;
}
System.out.println("当前请求非Ajax请求");
return Boolean.FALSE;
}

@Bean
public SecurityManager securityManager(@Qualifier("retryLimitCredentialsMatcher") MyRetryLimitCredentialsMatcher matcher) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置realm.
securityManager.setRealm(myShiroRealm(matcher));
// 自定义缓存实现 使用redis
//securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager());
return securityManager;
}

@Bean
public MyShiroRealm myShiroRealm(MyRetryLimitCredentialsMatcher matcher) {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(matcher);
return myShiroRealm;
}


/**
* 密码匹配凭证管理器 凭证匹配器
* (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
* 所以我们需要修改下doGetAuthenticationInfo中的代码;
* )
*
* @return
*/
@Bean(name = "retryLimitCredentialsMatcher")
public MyRetryLimitCredentialsMatcher hashedCredentialsMatcher() {
MyRetryLimitCredentialsMatcher hashedCredentialsMatcher = new MyRetryLimitCredentialsMatcher();

hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));

return hashedCredentialsMatcher;
}


/**
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
*
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}

/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
*
* @return
*/
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host);
redisManager.setPort(port);
//redisManager.setExpire(expire);// 配置缓存过期时间
redisManager.setTimeout(timeout);
redisManager.setPassword(password);
return redisManager;
}

/**
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*
* @return
*/
public RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
return redisCacheManager;
}


/**
* RedisSessionDAO shiro sessionDao层的实现 通过redis
* 使用的是shiro-redis开源插件
*/
@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}

/**
* shiro session的管理
*/
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//设置session过期时间为1小时(单位:毫秒),默认为30分钟
sessionManager.setGlobalSessionTimeout(60 * 60 * 1000);
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdUrlRewritingEnabled(false);

sessionManager.setSessionDAO(redisSessionDAO());
sessionManager.setSessionIdCookie(simpleCookie());
return sessionManager;
}

@Bean
public SimpleCookie simpleCookie() {
SimpleCookie simpleCookie = new SimpleCookie("SSID");
simpleCookie.setDomain("");
return simpleCookie;
}

// @Bean
// public SimpleCookie rememberMeCookie(){
// //System.out.println("ShiroConfiguration.rememberMeCookie()");
// //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
// SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
// //<!-- 记住我cookie生效时间30天 ,单位秒;-->
// simpleCookie.setMaxAge(60*30);
// return simpleCookie;
// }

// @Bean
// public CookieRememberMeManager rememberMeManager(){
// //System.out.println("ShiroConfiguration.rememberMeManager()");
// CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
// cookieRememberMeManager.setCookie(rememberMeCookie());
// //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
// cookieRememberMeManager.setCipherKey(Base64.decodeBytes("2AvVhdsgUs0FSA3SDFAdag=="));
// return cookieRememberMeManager;
// }

// @Bean(name = "securityManager")
// public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm realm){
// DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// //设置realm
// securityManager.setRealm(realm);
// //用户授权/认证信息Cache, 采用EhCache缓存
// securityManager.setCacheManager(cacheManager());
// //注入记住我管理器
// securityManager.setRememberMeManager(rememberMeManager());
// return securityManager;
// }

}

+ 31
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/ShiroLoginFilter.java Wyświetl plik

@@ -0,0 +1,31 @@
package com.iformall.config;

import com.alibaba.fastjson.JSON;
import com.iformall.common.ResultData;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class ShiroLoginFilter extends FormAuthenticationFilter {

@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
ResultData resultData = new ResultData(ResultData.UNLOGIN,"用户未登录");
response.getWriter().write(JSON.toJSONString(resultData));
return false;
}
/**
* 判断ajax请求
* @param request
* @return
*/
boolean isAjax(HttpServletRequest request){
return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString()) ) ;
}
}

+ 89
- 0
mlToutiaoOpen/src/main/java/com/iformall/config/WebConfig.java Wyświetl plik

@@ -0,0 +1,89 @@
package com.iformall.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.iformall.interceptor.HttpServletRequestWrapperFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.List;

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
//registry.addResourceHandler("/app/**").addResourceLocations("classpath:/app/");

}

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
//ObjectMapper 是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();

//不显示为null的字段
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

DeserializationConfig dc = objectMapper.getDeserializationConfig();
// 设置反序列化日期格式、忽略不存在get、set的属性
objectMapper.setConfig(
dc.with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
.without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
);

//序列化将Long转String类型
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
SimpleModule bigIntegerModule = new SimpleModule();
//序列化将BigInteger转String类型
bigIntegerModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
SimpleModule bigDecimalModule = new SimpleModule();
//序列化将BigDecimal转String类型
bigDecimalModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
objectMapper.registerModule(bigDecimalModule);
objectMapper.registerModule(bigIntegerModule);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.add(jackson2HttpMessageConverter);
}

@Bean
public FilterRegistrationBean<HttpServletRequestWrapperFilter> Filters() {
FilterRegistrationBean<HttpServletRequestWrapperFilter> registrationBean = new FilterRegistrationBean<HttpServletRequestWrapperFilter>();
registrationBean.setFilter(new HttpServletRequestWrapperFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setName("koalaSignFilter");
return registrationBean;
}
}

+ 124
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/HomeController.java Wyświetl plik

@@ -0,0 +1,124 @@
package com.iformall.controller;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.domain.po.MallUserInfo;
import com.iformall.exception.MallinkException;
import com.iformall.shiro.UserSession;
import com.iformall.utils.ShiroUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;


@RestController
@Api(description = "登录相关接口")
public class HomeController extends BaseController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Value("${version}")
private String version;

@Autowired
private Producer producer;


@GetMapping("/captcha.jpg")
public void captcha(HttpServletResponse response)throws ServletException, IOException {
logger.debug("[" + getIpAddr() + "] HomeController::captcha");
response.setHeader("Cache-Control", "no-store, no-cache");
response.setContentType("image/jpeg");

//生成文字验证码
String text = producer.createText();
//生成图片验证码
BufferedImage image = producer.createImage(text);
//保存到shiro session
ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);

ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpg", out);
IOUtils.closeQuietly(out);
}

@ApiOperation("登录")
@PostMapping("/doLogin")
public ResultData login(@RequestBody MallUserInfo user, HttpServletResponse response) {
logger.debug("[" + getIpAddr() + "] HomeController::login");

try {
String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY);
if(!user.getCaptcha().equalsIgnoreCase(kaptcha)){
return new ResultData(ErrorCode.KAPCHA_NOT_EQUAL);
}
} catch (MallinkException e) {
logger.error("验证码" + e.getMessage());
return new ResultData(ErrorCode.KAPCHA_NOT_VALID.getCode(), e.getMessage());
}


ResultData data = new ResultData();
if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) {
// throw new SystemException(ErrorCode.LOGIN_USER_OR_PWD_ERROR);
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
try {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
subject.login(token);
MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo);
info.setPassword("保密");
info.setBopenId("保密");
if(StringUtils.isNotBlank(info.getWebOpenId())) {
info.setWebOpenId("保密");
}

Cookie unameCookie = new Cookie("uname", info.getUsername());
unameCookie.setMaxAge(60);
response.addCookie(unameCookie);

data.data = info;
} catch (Exception e) {
return new ResultData(ErrorCode.USER_PASSWD_ERR);
}
return data;
}

@ApiOperation("登出")
@GetMapping("/logout")
public ResultData logout() {
logger.debug("[" + getIpAddr() + "] HomeController::logout");
ResultData data = new ResultData();
SecurityUtils.getSubject().logout();
return data;
}

@ApiOperation("获取后端版本号")
@GetMapping("/version")
public ResultData version() {
return new ResultData(version);
}
}

+ 106
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WechatAuthController.java Wyświetl plik

@@ -0,0 +1,106 @@
package com.iformall.controller;

import com.iformall.domain.po.WxAuthorizerInfo;
import com.iformall.enums.EnumWxAuthorizationStatus;
import com.iformall.service.WxAuthorizerInfoService;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
* Stormeye Wu
*/
@Controller
@RequestMapping("/wt_auth")
@Api(description = "微信第三方开放平台授权相关接口")
public class WechatAuthController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private FmOpenService openService;

@Autowired
private WxAuthorizerInfoService authorizerInfoService;

@ApiOperation(value = "获取授权跳转页", notes = "")
@GetMapping("/goto_auth_url_show")
@ResponseBody
public String gotoPreAuthUrlShow() {
return "<html>" +
"<body>" +
"<a href='/O/wt_auth/goto_auth_url'>go</a>" +
"</body>" +
"</html>";
}

@ApiOperation(value = "授权跳转页", notes = "")
@GetMapping("/goto_auth_url")
public void gotoPreAuthUrl(HttpServletRequest request, HttpServletResponse response) {
String host = request.getHeader("host");
String url = "https://" + host + "/O/wt_auth/jump";
try {
url = openService.getWxOpenComponentService().getPreAuthUrl(url);
response.sendRedirect(url);
} catch (WxErrorException | IOException e) {
logger.error("gotoPreAuthUrl", e);
throw new RuntimeException(e);
}
}

@ApiOperation(value = "授权", notes = "")
@GetMapping("/jump")
@ResponseBody
public void jump(@RequestParam("auth_code") String authorizationCode) {
try {
WxOpenQueryAuthResult queryAuthResult = openService.getWxOpenComponentService().getQueryAuth(authorizationCode);
logger.info("getQueryAuth", queryAuthResult);
WxOpenAuthorizerInfoResult openAuthorizerInfoResult = openService.getWxOpenComponentService().getAuthorizerInfo(
queryAuthResult.getAuthorizationInfo().getAuthorizerAppid());
logger.info(openAuthorizerInfoResult.toString());
// save auth info
authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo(){
{
setAuthorizerAppid(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAppid());
setAlias(openAuthorizerInfoResult.getAuthorizerInfo().getAlias());
setHeadImg(openAuthorizerInfoResult.getAuthorizerInfo().getHeadImg());
setQrcodeUrl(openAuthorizerInfoResult.getAuthorizerInfo().getQrcodeUrl());
setRefreshToken(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerRefreshToken());
setAccessToken(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAccessToken());
setAccessTokenExpire(new Date(Long.valueOf(System.currentTimeMillis() + openAuthorizerInfoResult.getAuthorizationInfo().getExpiresIn()*1000)));
setAuthorizationStatus(EnumWxAuthorizationStatus.AUTHORIZED.getCode());
setAuthTime(new Date());
}
});
} catch (WxErrorException e) {
logger.error("gotoPreAuthUrl", e);
throw new RuntimeException(e);
}
}

@ApiOperation(value = "手机跳转链接url", notes = "")
@GetMapping("/getMobilePreAuthUrl")
@ResponseBody
public String getMobilePreAuthUrl(HttpServletRequest request, HttpServletResponse response) {
String host = request.getHeader("host");
String url = "https://" + host + "/O/wt_auth/jump";
try {
url = openService.getWxOpenComponentService().getMobilePreAuthUrl(url);
return url;
} catch (WxErrorException e) {
logger.error("getMobilePreAuthUrl", e);
throw new RuntimeException(e);
}
}
}

+ 415
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WechatCalllbackController.java Wyświetl plik

@@ -0,0 +1,415 @@
package com.iformall.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.domain.po.*;
import com.iformall.enums.*;
import com.iformall.service.*;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.open.bean.WxOpenCreateResult;
import me.chanjar.weixin.open.bean.WxOpenGetResult;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
import me.chanjar.weixin.open.bean.result.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.Map;

@Controller
@RequestMapping("/wxOpen")
@Api(description = "微信第三方开放平台回调相关接口")
public class WechatCalllbackController extends BaseController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
protected FmOpenService openService;

@Autowired
private WxComponentVerifyTicketService componentVerifyTicketService;

@Autowired
private WxAuthorizerInfoService authorizerInfoService;

@PostMapping(value = "/notify")
@ApiOperation("接收ticket回调")
@ResponseBody
public String receiveTicket(HttpServletRequest request) throws IOException {
logger.info("[" + getIpAddr() + "]接收微信回调 /wxOpen/notify");

String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String signature = request.getParameter("signature");
String encType = request.getParameter("encrypt_type");
String msgSignature = request.getParameter("msg_signature");

if (!StringUtils.equalsIgnoreCase("aes", encType)
|| !openService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}

String resultxml = getRequestXML(request);

logger.info("\n接收微信回调:[signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
signature, encType, msgSignature, timestamp, nonce, resultxml);

// aes加密的消息, 解密
WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(resultxml,
openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
this.logger.info("接收微信回调,消息解密后内容为:{} ", inMessage.toString());

// 处理
handleTicket(inMessage);
return "success";
}

/**
* 处理ticket消息
* @param inMessage
* @return
*/
private void handleTicket(WxOpenXmlMessage inMessage) {
try {
String out = openService.getWxOpenComponentService().route(inMessage);
this.logger.info("组装回复信息:{}", out);
} catch (WxErrorException e) {
this.logger.error("notify", e);
}
if (inMessage.getInfoType().equalsIgnoreCase(EnumWxAuthorizationInfoType.COMPONENT_VERIFY_TICKET.getMessage())) {
// 保存component_verify_ticket
componentVerifyTicketService.saveOrUpdate(new WxComponentVerifyTicket() {
{
setComponentVerifyTicket(inMessage.getComponentVerifyTicket());
setCreateTime(new Date(Long.valueOf(inMessage.getCreateTime() * 1000)));
setComponentAppid(inMessage.getAppId());
setDeadline(new Date(Long.valueOf(System.currentTimeMillis() + (60 * 60 * 1000))));
}
});
} else if (inMessage.getInfoType().equalsIgnoreCase(EnumWxAuthorizationInfoType.AUTHORIZED.getMessage()) ||
inMessage.getInfoType().equalsIgnoreCase(EnumWxAuthorizationInfoType.UPDATEAUTHORIZED.getMessage())) {
// 审核通过
handleWeappAuditedMessage(inMessage);
} else if (inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.UNAUTHORIZED.getMessage())) {
// 授权取消
authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo() {
{
setAuthorizerAppid(inMessage.getAuthorizerAppid());
setAuthorizationStatus(EnumWxAuthorizationStatus.UNAUTHORIZED.getCode());
setAuthTime(new Date());
}
});
}
}

/**
* 处理小程序审核消息
* @param inMessage
* @return
*/
private boolean handleWeappAuditedMessage(WxOpenXmlMessage inMessage) {
// 审核通过
try {
WxOpenQueryAuthResult queryAuthResult = openService.getWxOpenComponentService().getQueryAuth(inMessage.getAuthorizationCode());
logger.info("getQueryAuth", queryAuthResult);

WxOpenAuthorizerInfoResult openAuthorizerInfoResult = openService.getWxOpenComponentService().getAuthorizerInfo(
queryAuthResult.getAuthorizationInfo().getAuthorizerAppid());
logger.info(openAuthorizerInfoResult.toString());
// save auth info
authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo() {
{
setAuthorizerAppid(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAppid());
setAlias(openAuthorizerInfoResult.getAuthorizerInfo().getAlias());
setHeadImg(openAuthorizerInfoResult.getAuthorizerInfo().getHeadImg());
setQrcodeUrl(openAuthorizerInfoResult.getAuthorizerInfo().getQrcodeUrl());
setRefreshToken(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerRefreshToken());
setAccessToken(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAccessToken());
setAccessTokenExpire(new Date(Long.valueOf(System.currentTimeMillis() + openAuthorizerInfoResult.getAuthorizationInfo().getExpiresIn()*1000)));
setAuthorizationStatus(EnumWxAuthorizationStatus.AUTHORIZED.getCode());
setAuthTime(new Date());
}
});
return true;
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
return false;
}

@RequestMapping(value = "/{appId}/callback")
@ApiOperation("消息回调")
public void callback(@PathVariable("appId") String appId, HttpServletRequest request, HttpServletResponse response) throws IOException {
logger.info("[" + getIpAddr() + "]接收微信APP回调 /{appId}/callback");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String signature = request.getParameter("signature");
String encType = request.getParameter("encrypt_type");
String openid = request.getParameter("openid");
String msgSignature = request.getParameter("msg_signature");

// 第三方平台一定接收的是加密的消息
if (!StringUtils.equalsIgnoreCase("aes", encType)
|| !openService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}

String resultxml = getRequestXML(request);

logger.info("接收微信APP回调:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
appId, openid, signature, encType, msgSignature, timestamp, nonce, resultxml);


String out = "";
// aes加密的消息, 解密
WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(resultxml,
openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
logger.info("接收微信APP回调,消息解密后内容为:\n{}", inMessage.toString());

// 全网发布测试用例
if (StringUtils.equalsAnyIgnoreCase(appId, "wx570bc396a51b8ff8", "wxd101a85aa106f53e")) {
handleWechatTest(appId, response, inMessage);
PrintWriter printWriter = response.getWriter();
wechatWriteSuccess(printWriter);
return;
}

// 实际 消息 处理
//handleCallbackMessage(appId, response, inMessage);
WxMpXmlOutMessage outMessage = openService.getWxOpenMessageRouter().route(inMessage, appId);
if(outMessage == null) {
PrintWriter printWriter = response.getWriter();
wechatWriteSuccess(printWriter);
}
PrintWriter printWriter = response.getWriter();
wechatWriteSuccess(printWriter);
}

private void wechatWriteSuccess(PrintWriter printWriter) {
printWriter.print("success");
printWriter.flush();
printWriter.close();
}

/**
* 测试账号特殊处理
* @param appId
* @param response
* @param inMessage
* @throws IOException
*/
private void handleWechatTest(@PathVariable("appId") String appId, HttpServletResponse response, WxMpXmlMessage inMessage) throws IOException {
String out;
try {
if (StringUtils.equals(inMessage.getMsgType(), "text")) {
if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) {
out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(
WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback")
.fromUser(inMessage.getToUser())
.toUser(inMessage.getFromUser())
.build(),
openService.getWxOpenConfigStorage()
);
} else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) {
String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build();
openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
}
} else if (StringUtils.equals(inMessage.getMsgType(), "event")) {
WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(inMessage.getEvent() + "from_callback").toUser(inMessage.getFromUser()).build();
openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
}
} catch (WxErrorException e) {
logger.error("callback", e);
}
}

private String getRequestXML(HttpServletRequest request) throws IOException {
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String resultxml = new String(outSteam.toByteArray(), Charset.forName("UTF-8"));
logger.info(resultxml);

outSteam.close();
inStream.close();
return resultxml;
}

private void getThreadCount( int i) {
ThreadGroup group = Thread.currentThread().getThreadGroup();
ThreadGroup topGroup = group;
// 遍历线程组树,获取根线程组
while (group != null) {
topGroup = group;
group = group.getParent();
}
// 激活的线程数加倍
int activeCount = topGroup.activeCount();
// copy into a list that is the exact size
logger.info("Thread list size == " + i + " : " + activeCount);

}


@GetMapping(value = "/createOpenPlatform")
@ApiOperation("创建微信开放平台")
public ResultData createOpenPlatform(@RequestParam(value = "appId") String appId) {
Gson gson = new GsonBuilder().create();
try {
WxOpenCreateResult ret = openService.getWxOpenComponentService().createOpenAccount(appId);
logger.info(ret.toString());
if (ret.isSuccess()) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if (authorizerInfo != null) {
authorizerInfo.setId(authorizerInfo.getId());
authorizerInfo.setOpenAppid(ret.getOpenAppid());
authorizerInfoService.updateOpenAppid(authorizerInfo);
}
}
return new ResultData(ret.toString());
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@GetMapping(value = "/bindOpenPlatform")
@ApiOperation("绑定微信开放平台")
public ResultData bindOpenPlatform(@RequestParam(value = "appId") String appId, @RequestParam(value = "openAppId") String openAppId) {
Gson gson = new GsonBuilder().create();
try {
Boolean ret = openService.getWxOpenComponentService().bindOpenAccount(appId, openAppId);
if (ret) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if (authorizerInfo != null) {
authorizerInfo.setId(authorizerInfo.getId());
authorizerInfo.setOpenAppid(openAppId);
authorizerInfoService.updateOpenAppid(authorizerInfo);
}
return new ResultData();
}
return new ResultData(Result.ERROR, ret.toString());
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@GetMapping(value = "/unbindOpenPlatform")
@ApiOperation("解绑微信开放平台")
public ResultData unbindOpenPlatform(@RequestParam(value = "appId") String appId, @RequestParam(value = "openAppId") String openAppId) {
Gson gson = new GsonBuilder().create();
try {
Boolean ret = openService.getWxOpenComponentService().unbindOpenAccount(appId, openAppId);
if (ret) {
WxAuthorizerInfo authorizerInfo = new WxAuthorizerInfo();
authorizerInfo.setAuthorizerAppid(appId);
authorizerInfoService.removeOpenAppid(authorizerInfo);
return new ResultData();
}
return new ResultData(Result.ERROR, ret.toString());
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@GetMapping(value = "/getOpenPlatform")
@ApiOperation("获取微信开放平台appId")
public ResultData getOpenPlatform(@RequestParam(value = "appId") String appId) {
Gson gson = new GsonBuilder().create();
try {
WxOpenGetResult ret = openService.getWxOpenComponentService().getOpenAccount(appId);
logger.info(ret.toString());
if (ret.isSuccess()) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if (authorizerInfo != null) {
if(StringUtils.isBlank(authorizerInfo.getOpenAppid()) && StringUtils.isNotBlank(ret.getOpenAppid())) {
authorizerInfo.setId(authorizerInfo.getId());
authorizerInfo.setOpenAppid(ret.getOpenAppid());
authorizerInfoService.updateOpenAppid(authorizerInfo);
}
}
return new ResultData(ret.getOpenAppid());
}
return new ResultData(Result.ERROR, ret.toString());
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@GetMapping(value = "/clearQuota")
@ApiOperation("代公众号清零quota,每个公众号每个月有10次清零机会,包括在微信公众平台上的清零以及调用API进行清零")
public ResultData clearQuota(@RequestParam(value = "appId") String appId) {
try {
openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).clearQuota(appId);
return new ResultData();
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@GetMapping(value = "/getAuthorizerList")
@ApiOperation("拉取当前所有已授权的帐号基本信息")
public ResultData getAuthorizerList() {
try {
WxOpenAuthorizerListResult authorizerListResult = openService.getWxOpenComponentService().getAuthorizerList(0, 100);
logger.info("getAuthorizerList: " + authorizerListResult);
if(authorizerListResult.getTotalCount() > 0) {
for (Map<String, String> data : authorizerListResult.getList()) {
String appId = data.get("authorizer_appid");
String refreshToken = data.get("refresh_token");
Long authTime = Long.valueOf(data.get("auth_time"));
Date authDate = new Date(authTime*1000);

if(StringUtils.isBlank(refreshToken)) {
continue;
}

WxAuthorizerInfo authorizerInfo = new WxAuthorizerInfo();
authorizerInfo.setAuthorizerAppid(appId);
authorizerInfo.setRefreshToken(refreshToken);
authorizerInfo.setAuthTime(authDate);
authorizerInfoService.updateAuthAppidInfo(authorizerInfo);

openService.getWxOpenComponentService().getWxOpenConfigStorage().setAuthorizerRefreshToken(appId, refreshToken);
}
}
return new ResultData(authorizerListResult.toString());
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}
}

+ 133
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WechatMediaController.java Wyświetl plik

@@ -0,0 +1,133 @@
package com.iformall.controller;

import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.service.WxAuthorizerInfoService;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
* Stormeye Wu
*/
@Controller
@RequestMapping("/material")
@Api(description = "微信第三方开放平台素材文件")
public class WechatMediaController extends BaseController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private String fmUploadDir;
@Autowired
private FmOpenService openService;

@Autowired
private WxAuthorizerInfoService authorizerInfoService;

@ApiOperation(value = "获取永久素材", notes = "")
@GetMapping("/getMedia")
@ApiImplicitParams({
@ApiImplicitParam(name = "appId", value = "appId", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "mediaId", value = "mediaId", dataType = "String", paramType = "query", required = true)})
public void getMediaInfo(String appId, String mediaId, HttpServletRequest req, HttpServletResponse response) {
InputStream inputStream = null;
String filename = mediaId;
try {
WxMpService mpService = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId);
inputStream = mpService.getMaterialService().materialImageOrVoiceDownload(mediaId);
} catch (WxErrorException e) {
logger.error("获取永久素材失败", e);
throw new RuntimeException(e);
}

try {
response.reset();
response.setContentType("application/octet-stream");
String agent = req.getHeader("user-agent");
if (agent.contains("Firefox")) {
response.setHeader("Content-disposition",
"attachment; filename="
+ new String(filename.getBytes("GB2312"), "ISO-8859-1"));
} else {
response.setHeader("Content-disposition",
"attachment; filename="
+ java.net.URLEncoder.encode(filename, "UTF-8"));
}
// 循环取出流中的数据
byte[] b = new byte[1024];
int len;
while ((len = inputStream.read(b)) > 0)
response.getOutputStream().write(b, 0, len);
inputStream.close();
} catch (Exception e) {
logger.error(e.getMessage());
}
}

/**
* 图片上传
*
* @param multiReq
* @return
* @throws Exception
*/
@PostMapping(value = "/imgUpload/{appId}", consumes = "multipart/*", headers = "content-type=multipart/form-data")
@ApiOperation("上传图片")
public ResultData imgUpload(
@PathVariable("appId") String appId,
@RequestParam("file") MultipartFile multiReq) throws Exception {
logger.info("[" + getIpAddr() + "] WechatMediaController::imgUpload");

String fileName = multiReq.getOriginalFilename();
System.out.println(fileName);

// 本地保存
FileOutputStream fos = null;
String localImgFileName = fmUploadDir + fileName;
BufferedInputStream fs = null;
File localFile = new File(localImgFileName);
fos = new FileOutputStream(localFile);
fs = (BufferedInputStream) multiReq.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fs.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.close();
fs.close();

// 上传 微信
try {
WxMpService mpService = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId);
WxMediaImgUploadResult openResult = mpService.getMaterialService().mediaImgUpload(localFile);
if(openResult != null) {
return new ResultData(openResult.getUrl());
}
} catch (WxErrorException e) {
logger.error("获取永久素材失败", e);
throw new RuntimeException(e);
}

// 删除本地缓存
localFile.delete();

return new ResultData();
}
}

+ 703
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappCodeController.java Wyświetl plik

@@ -0,0 +1,703 @@
package com.iformall.controller;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.domain.dto.WxWeappCodeAuditDto;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxWeappCodeStatusVo;
import com.iformall.enums.*;
import com.iformall.service.*;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.open.api.WxOpenMaService;
import me.chanjar.weixin.open.bean.ma.WxMaOpenCommitExtInfo;
import me.chanjar.weixin.open.bean.message.WxOpenMaSubmitAuditMessage;
import me.chanjar.weixin.open.bean.result.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* Stormeye Wu
*/
@RestController
@RequestMapping("/weappCode")
@Api(description = "微信第三方开发平台-小程序-代码管理")
public class WechatWeappCodeController extends BaseController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private FmOpenService openService;

@Autowired
private WxWeappCodeStatusService weappCodeStatusService;

@Autowired
private WxWeappAuditStatusService weappAuditStatusService;

@Autowired
private WxWeappReleaseStatusService weappReleaseStatusService;

@Autowired
private WxAppinfoService appinfoService;

@Autowired
private WxAuthorizerInfoService authorizerInfoService;

@Autowired
private WxWeappExtSetService weappExtSetService;


@ApiOperation(value = "为授权的小程序帐号上传小程序代码", notes = "extInfo参考https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html")
@PostMapping("/codeCommit")
public ResultData codeCommit(Long templateId, String userVersion, String userDesc, String extInfoStr) {
Gson gson = new GsonBuilder().create();
WxMaOpenCommitExtInfo extInfo = gson.fromJson(extInfoStr, new TypeToken<WxMaOpenCommitExtInfo>() {}.getType());
String appId = extInfo.getExtAppid();

// 检查appId是否已授权
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if(authorizerInfo == null) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(!authorizerInfo.getAuthorizationStatus().equals(EnumWxAuthorizationStatus.AUTHORIZED.getCode())) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}

WxWeappCodeStatus codeStatus = weappCodeStatusService.getByAppId(appId);

WxAppinfo appinfo = appinfoService.getByAppId(appId);

int iAppType = 0;
String appTypeStr = userVersion.substring(0, 1);
if(appTypeStr.equalsIgnoreCase("C"))
iAppType = EnumAppType.C.getCode();
else if(appTypeStr.equalsIgnoreCase("B"))
iAppType = EnumAppType.B.getCode();

try {
// code提交
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
logger.info(extInfo.toString());
WxOpenResult openRet = openMaService.codeCommit(templateId, userVersion, userDesc, extInfo);
logger.info(openRet.toString());
boolean codeCommitStatus = false;
if (openRet.isSuccess()) {
codeCommitStatus = true;
}
if (codeStatus == null) {
codeStatus = new WxWeappCodeStatus();
codeStatus.setAppId(appId);
if (appinfo != null) {
codeStatus.setTenantId(appinfo.getTenantId());
codeStatus.setType(appinfo.getType());
}
codeStatus.setUserVersion(userVersion);
codeStatus.setVersionDesc(userDesc);
if(codeCommitStatus) {
codeStatus.setCodeStatus(EnumWeappCodeCommitStatus.SUCCESS.getCode());
} else {
codeStatus.setCodeStatus(EnumWeappCodeCommitStatus.FAIL.getCode());
codeStatus.setCodeErrCode(gson.toJson(openRet));
}
codeStatus.setCodeTime(new Date());
weappCodeStatusService.saveStatus(codeStatus);
} else {
codeStatus.setUserVersion(userVersion);
codeStatus.setVersionDesc(userDesc);
if(codeCommitStatus) {
codeStatus.setCodeStatus(EnumWeappCodeCommitStatus.SUCCESS.getCode());
} else {
codeStatus.setCodeStatus(EnumWeappCodeCommitStatus.FAIL.getCode());
codeStatus.setCodeErrCode(gson.toJson(openRet));
}
codeStatus.setCodeTime(new Date());
weappCodeStatusService.updateStatus(codeStatus);
}
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
if (codeStatus == null) {
codeStatus = new WxWeappCodeStatus();
codeStatus.setAppId(appId);
if (appinfo != null) {
codeStatus.setTenantId(appinfo.getTenantId());
codeStatus.setType(appinfo.getType());
}
codeStatus.setUserVersion(userVersion);
codeStatus.setVersionDesc(userDesc);
codeStatus.setCodeStatus(EnumWeappCodeCommitStatus.FAIL.getCode());
codeStatus.setCodeErrCode(e.getMessage());
codeStatus.setCodeTime(new Date());
weappCodeStatusService.saveStatus(codeStatus);
} else {
codeStatus.setUserVersion(userVersion);
codeStatus.setVersionDesc(userDesc);
codeStatus.setCodeStatus(EnumWeappCodeCommitStatus.FAIL.getCode());
codeStatus.setCodeErrCode(e.getMessage());
codeStatus.setCodeTime(new Date());
weappCodeStatusService.updateStatus(codeStatus);
}
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation("获取体验小程序的体验二维码")
@GetMapping("/getQrcode")
public void getQrcode(@RequestParam(value = "appId") String appId, @RequestParam(value = "pagePath") String pagePath,
@RequestParam(value = "params", required = false) Map<String, String> params,
HttpServletResponse response, HttpServletRequest req) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
File file = openMaService.getTestQrcode(pagePath, params);
ServletOutputStream out = response.getOutputStream();

response.reset();
response.setContentType("image/jpeg");
String agent = req.getHeader("user-agent");
String filename = "QRCode.jpg";
if (agent.contains("Firefox")) {
response.setHeader("Content-disposition",
"attachment; filename=" + new String(filename.getBytes("GB2312"),"ISO-8859-1"));
} else {
response.setHeader("Content-disposition",
"attachment; filename=" + URLEncoder.encode(filename,"UTF-8"));
}
// 循环取出流中的数据
byte[] b = new byte[1024];
int len;
InputStream inStream = new FileInputStream(file);
while ((len = inStream.read(b)) > 0)
response.getOutputStream().write(b, 0, len);
inStream.close();
} catch (WxErrorException e) {
logger.error(e.getMessage());
} catch (IOException e) {
logger.error(e.getMessage());
}
}

@ApiOperation("获取授权小程序帐号已设置的类目")
@GetMapping("/getCategory")
public ResultData getCategory(String appId) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenMaCategoryListResult openRet = openMaService.getCategoryList();
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation("获取小程序的第三方提交代码的页面配置")
@GetMapping("/getPage")
public ResultData getPage(String appId) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenMaPageListResult openRet = openMaService.getPageList();
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation("将第三方提交的代码包提交审核 -- 即将废弃")
@GetMapping("/submitAudit")
@ApiImplicitParams({
@ApiImplicitParam(name = "appId", value = "appId", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "version", value = "version", dataType = "String", paramType = "query")})
public ResultData submitAudit(String appId, String version) {
Gson gson = new GsonBuilder().create();
WxWeappExtSet extSetQ = new WxWeappExtSet();
extSetQ.setAppId(appId);
WxWeappExtSet extSet = weappExtSetService.getByObj(extSetQ);
if(StringUtils.isBlank(extSet.getReleaseJson())) {
logger.error("Release JSON is null");
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}

WxWeappCodeStatusVo codeQ = new WxWeappCodeStatusVo();
codeQ.setAppId(appId);
if(StringUtils.isNotBlank(version)) {
codeQ.setUserVersion(version);
}
List<WxWeappCodeStatusVo> codeStatusList = weappCodeStatusService.getList(codeQ);
if(codeStatusList.size() == 1) {
WxWeappCodeStatusVo codeStatus = codeStatusList.get(0);
WxOpenMaSubmitAuditMessage subMessage = gson.fromJson(extSet.getReleaseJson(), new TypeToken<WxOpenMaSubmitAuditMessage>() {}.getType());
if(codeStatus != null && codeStatus.getCodeStatus().equals(EnumWeappCodeCommitStatus.SUCCESS.getCode())) {
WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(appId);
boolean submitStatus = false;
String codeErrCode = "";
Long auditId = null;
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenMaSubmitAuditResult openRet = openMaService.submitAudit(subMessage);
logger.info(openRet.toString());
if(openRet.isSuccess()) {
submitStatus = true;
codeErrCode = gson.toJson(openRet);
auditId = openRet.getAuditId();
} else {
submitStatus = false;
codeErrCode = gson.toJson(openRet);
}
} catch (WxErrorException e) {
logger.error(e.getMessage());
submitStatus = false;
codeErrCode = e.getMessage();
}

if (auditStatus == null) {
auditStatus = new WxWeappAuditStatus();
auditStatus.setId(codeStatus.getId());
auditStatus.setTenantId(codeStatus.getTenantId());
auditStatus.setAppId(codeStatus.getAppId());
auditStatus.setType(codeStatus.getType());
auditStatus.setUserVersion(codeStatus.getUserVersion());
auditStatus.setVersionDesc(codeStatus.getVersionDesc());
if(submitStatus) {
auditStatus.setAuditStatus(EnumWeappAuditStatus.AUDITING.getCode());
} else {
auditStatus.setAuditStatus(EnumWeappAuditStatus.FAIL.getCode());
}
auditStatus.setAuditErrCode(codeErrCode);
auditStatus.setAuditTime(new Date());
weappAuditStatusService.saveStatus(auditStatus);
} else {
if(!submitStatus) {
if(!auditStatus.getUserVersion().equals(codeStatus.getUserVersion())
&& auditStatus.getAuditStatus().equals(EnumWeappAuditStatus.AUDITING.getCode())) {
// 提交审核失败不替换当前审核中的数据
return new ResultData(ErrorCode.WEAPP_HAD_AUDITING);
}
codeStatus.setCodeStatus(EnumWeappAuditStatus.FAIL.getCode());
codeStatus.setCodeErrCode(codeErrCode);
} else {
codeStatus.setCodeStatus(EnumWeappAuditStatus.AUDITING.getCode());
}
auditStatus.setUserVersion(codeStatus.getUserVersion());
auditStatus.setVersionDesc(codeStatus.getVersionDesc());
auditStatus.setAuditTime(new Date());
weappAuditStatusService.updateStatus(auditStatus);
}
if(submitStatus) {
return new ResultData(codeErrCode);
} else {
return new ResultData(ErrorCode.WEAPP_AUDIT_ERR);
}
} else {
logger.error(ErrorCode.WEAPP_CODE_COMMIT_ERR.getMessage());
return new ResultData(ErrorCode.WEAPP_CODE_COMMIT_ERR);
}
}
return new ResultData(ErrorCode.WEAPP_CODE_COMMIT_ERR);
}

@ApiOperation("查询服务商的当月提审限额(quota)和加急次数")
@GetMapping("/queryQuota")
@ApiImplicitParams({
@ApiImplicitParam(name = "appId", value = "appId", dataType = "String", paramType = "query", required = true)})
public ResultData queryQuota(String appId) {
logger.debug("[" + getIpAddr() + "] WechatWeappCodeController::queryQuota");
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenMaQueryQuotaResult openRet = openMaService.queryQuota();
logger.info(openRet.toString());
return new ResultData(openRet.toString());
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(e.getMessage());
}
}

@ApiOperation("将第三方提交的代码包提交审核")
@PostMapping("/submitAuditWithFeedBack")
public ResultData submitAudit(@RequestBody WxWeappCodeAuditDto codeAuditDto) {
Gson gson = new GsonBuilder().create();
WxWeappExtSet extSetQ = new WxWeappExtSet();
extSetQ.setAppId(codeAuditDto.getAppId());
WxWeappExtSet extSet = weappExtSetService.getByObj(extSetQ);
if(StringUtils.isBlank(extSet.getReleaseJson())) {
logger.error("Release JSON is null");
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}

WxWeappCodeStatusVo codeQ = new WxWeappCodeStatusVo();
codeQ.setAppId(codeAuditDto.getAppId());
if(StringUtils.isNotBlank(codeAuditDto.getVersion())) {
codeQ.setUserVersion(codeAuditDto.getVersion());
}
List<WxWeappCodeStatusVo> codeStatusList = weappCodeStatusService.getList(codeQ);
if(codeStatusList.size() == 1) {
WxWeappCodeStatusVo codeStatus = codeStatusList.get(0);
WxOpenMaSubmitAuditMessage subMessage = gson.fromJson(extSet.getReleaseJson(), new TypeToken<WxOpenMaSubmitAuditMessage>() {}.getType());
if(StringUtils.isNotBlank(codeAuditDto.getFeedbackInfo())) {
subMessage.setFeedbackInfo(codeAuditDto.getFeedbackInfo());
}
if(StringUtils.isNotBlank(codeAuditDto.getFeedbackStuff())) {
subMessage.setFeedbackStuff(codeAuditDto.getFeedbackStuff());
}
if(codeStatus != null && codeStatus.getCodeStatus().equals(EnumWeappCodeCommitStatus.SUCCESS.getCode())) {
WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(codeAuditDto.getAppId());
boolean submitStatus = false;
String codeErrCode = "";
Long auditId = null;
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(codeAuditDto.getAppId());
WxOpenMaSubmitAuditResult openRet = openMaService.submitAudit(subMessage);
logger.info(openRet.toString());
if(openRet.isSuccess()) {
submitStatus = true;
codeErrCode = gson.toJson(openRet);
auditId = openRet.getAuditId();
} else {
submitStatus = false;
codeErrCode = gson.toJson(openRet);
}
} catch (WxErrorException e) {
logger.error(e.getMessage());
submitStatus = false;
codeErrCode = e.getMessage();
}

if (auditStatus == null) {
auditStatus = new WxWeappAuditStatus();
auditStatus.setId(codeStatus.getId());
auditStatus.setTenantId(codeStatus.getTenantId());
auditStatus.setAppId(codeStatus.getAppId());
auditStatus.setType(codeStatus.getType());
auditStatus.setUserVersion(codeStatus.getUserVersion());
auditStatus.setVersionDesc(codeStatus.getVersionDesc());
auditStatus.setAuditid(auditId);
if(submitStatus) {
auditStatus.setAuditStatus(EnumWeappAuditStatus.AUDITING.getCode());
} else {
auditStatus.setAuditStatus(EnumWeappAuditStatus.FAIL.getCode());
}
auditStatus.setAuditErrCode(codeErrCode);
auditStatus.setAuditTime(new Date());
weappAuditStatusService.saveStatus(auditStatus);
} else {
if(!submitStatus) {
if(!auditStatus.getUserVersion().equals(codeStatus.getUserVersion())
&& auditStatus.getAuditStatus().equals(EnumWeappAuditStatus.AUDITING.getCode())) {
// 提交审核失败不替换当前审核中的数据
return new ResultData(ErrorCode.WEAPP_HAD_AUDITING);
}
codeStatus.setCodeStatus(EnumWeappAuditStatus.FAIL.getCode());
codeStatus.setCodeErrCode(codeErrCode);
} else {
codeStatus.setCodeStatus(EnumWeappAuditStatus.AUDITING.getCode());
}
auditStatus.setUserVersion(codeStatus.getUserVersion());
auditStatus.setVersionDesc(codeStatus.getVersionDesc());
auditStatus.setAuditid(auditId);
auditStatus.setAuditTime(new Date());
weappAuditStatusService.updateStatus(auditStatus);
}
if(submitStatus) {
return new ResultData(codeErrCode);
} else {
return new ResultData(ErrorCode.WEAPP_AUDIT_ERR);
}
} else {
logger.error(ErrorCode.WEAPP_CODE_COMMIT_ERR.getMessage());
return new ResultData(ErrorCode.WEAPP_CODE_COMMIT_ERR);
}
}
return new ResultData(ErrorCode.WEAPP_CODE_COMMIT_ERR);
}

@ApiOperation("加速某个指定版本的审核状态")
@GetMapping("/speedAudit")
@ApiImplicitParams({
@ApiImplicitParam(name = "appId", value = "appId", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "auditid", value = "auditid", dataType = "Long", paramType = "query", required = true)})
public ResultData speedAudit(String appId, Long auditid) {
logger.debug("[" + getIpAddr() + "] WechatWeappCodeController::speedAudit");
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
Boolean ret = openMaService.speedAudit(Long.valueOf(auditid));
return new ResultData(ret.toString());
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(e.getMessage());
}
}

@ApiOperation("查询某个指定版本的审核状态")
@PostMapping("/getAuditstatus")
public ResultData getAuditstatus(String appId, String auditidStr) {
Gson gson = new GsonBuilder().create();
Long auditId = Long.valueOf(auditidStr);
WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(appId);
if(auditStatus != null && auditStatus.getAuditid().equals(auditId)) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenMaQueryAuditResult openRet = openMaService.getAuditStatus(auditId);
logger.info(openRet.toString());
if (openRet.isSuccess()) {
auditStatus.setAuditid(openRet.getAuditId());
// 审核状态,其中0为审核成功,1为审核失败,2为审核中,3已撤回
switch (openRet.getStatus().intValue()) {
case 0:
auditStatus.setAuditStatus(EnumWeappAuditStatus.SUCCESS.getCode());
break;
case 1:
auditStatus.setAuditStatus(EnumWeappAuditStatus.FAIL.getCode());
break;
case 2:
auditStatus.setAuditStatus(EnumWeappAuditStatus.AUDITING.getCode());
break;
case 3:
auditStatus.setAuditStatus(EnumWeappAuditStatus.UNDO.getCode());
break;
default:
auditStatus.setAuditStatus(EnumWeappAuditStatus.AUDITING.getCode());
break;
}
auditStatus.setAuditErrCode(gson.toJson(openRet));
auditStatus.setAuditTime(new Date());
weappAuditStatusService.updateStatus(auditStatus);
}
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}
return new ResultData(Result.ERROR, "auditid不对应");
}

@ApiOperation("查询最新一次提交的审核状态")
@GetMapping("/getLatestAuditstatus")
public ResultData get_latest_auditstatus(String appId) {
Gson gson = new GsonBuilder().create();
WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(appId);
if(auditStatus != null
&& auditStatus.getAuditStatus().equals(EnumWeappAuditStatus.AUDITING.getCode())) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenMaQueryAuditResult openRet = openMaService.getLatestAuditStatus();
logger.info(openRet.toString());
if (openRet.isSuccess()) {
auditStatus.setAuditid(openRet.getAuditId());
// 审核状态,其中0为审核成功,1为审核失败,2为审核中,3已撤回
switch (openRet.getStatus().intValue()) {
case 0:
auditStatus.setAuditStatus(EnumWeappAuditStatus.SUCCESS.getCode());
break;
case 1:
auditStatus.setAuditStatus(EnumWeappAuditStatus.FAIL.getCode());
break;
case 2:
auditStatus.setAuditStatus(EnumWeappAuditStatus.AUDITING.getCode());
break;
case 3:
auditStatus.setAuditStatus(EnumWeappAuditStatus.UNDO.getCode());
break;
default:
auditStatus.setAuditStatus(EnumWeappAuditStatus.AUDITING.getCode());
break;
}
auditStatus.setAuditErrCode(gson.toJson(openRet));
auditStatus.setAuditTime(new Date());
weappAuditStatusService.updateStatus(auditStatus);
}
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
} else {
return new ResultData(Result.ERROR, "审核状态不是审核中");
}
}

@ApiOperation("发布已通过审核的小程序")
@GetMapping("/releaseAudited")
public ResultData releaesAudited(String appId) {
if(StringUtils.isBlank(appId)) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
Gson gson = new GsonBuilder().create();
WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(appId);
if(auditStatus.getAuditStatus().equals(EnumWeappAuditStatus.SUCCESS.getCode())) {
boolean isUpdate = false;
WxWeappReleaseStatus releaseStatus = weappReleaseStatusService.getByAppId(appId);
if(releaseStatus != null) {
// 版本已发布成功,跳过
if(releaseStatus.getUserVersion().equals(auditStatus.getUserVersion())
&& releaseStatus.getReleaseStatus().equals(EnumWeappReleaseStatus.SUCCESS.getCode())) {
return new ResultData(ErrorCode.WEAPP_APP_RELEASEED);
}
releaseStatus.setUserVersion(auditStatus.getUserVersion());
releaseStatus.setVersionDesc(auditStatus.getVersionDesc());
isUpdate = true;
} else {
releaseStatus = new WxWeappReleaseStatus();
releaseStatus.setId(auditStatus.getId());
releaseStatus.setTenantId(auditStatus.getTenantId());
releaseStatus.setAppId(auditStatus.getAppId());
releaseStatus.setType(auditStatus.getType());
releaseStatus.setUserVersion(auditStatus.getUserVersion());
releaseStatus.setVersionDesc(auditStatus.getVersionDesc());
}
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenResult openRet = openMaService.releaesAudited();
logger.info(openRet.toString());
boolean releaseSuccess = false;
if(openRet.isSuccess()) {
releaseSuccess = true;
}
if(releaseSuccess) {
releaseStatus.setReleaseStatus(EnumWeappReleaseStatus.SUCCESS.getCode());
} else {
if(openRet.getErrcode().equals("85052")) { // app is already released
releaseStatus.setReleaseStatus(EnumWeappReleaseStatus.SUCCESS.getCode());
} else {
releaseStatus.setReleaseStatus(EnumWeappReleaseStatus.FAIL.getCode());
}
}
releaseStatus.setReleaseErrCode(gson.toJson(openRet));
releaseStatus.setReleaseTime(new Date());
if(isUpdate) {
weappReleaseStatusService.updateStatus(releaseStatus);
} else {
weappReleaseStatusService.saveStatus(releaseStatus);
}
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
if(e.getError().getErrorCode() == 85052) {
releaseStatus.setReleaseStatus(EnumWeappReleaseStatus.SUCCESS.getCode());
} else {
releaseStatus.setReleaseStatus(EnumWeappReleaseStatus.FAIL.getCode());
}
releaseStatus.setReleaseErrCode(e.getMessage());
releaseStatus.setReleaseTime(new Date());
if(isUpdate) {
weappReleaseStatusService.updateStatus(releaseStatus);
} else {
weappReleaseStatusService.saveStatus(releaseStatus);
}
return new ResultData(Result.ERROR, e.getMessage());
}
} else {
return new ResultData(ErrorCode.WEAPP_NOT_AUDITED);
}
}

@ApiOperation("小程序版本回退")
@GetMapping("/revertCodeRelease")
public ResultData revertCodeRelease(String appId) {
Gson gson = new GsonBuilder().create();
WxWeappReleaseStatus releaseStatus = weappReleaseStatusService.getByAppId(appId);
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenResult openRet = openMaService.revertCodeReleaes();
logger.info(openRet.toString());
if(openRet.isSuccess()) {
if(releaseStatus != null) {
releaseStatus.setReleaseStatus(EnumWeappReleaseStatus.BACK.getCode());
releaseStatus.setReleaseErrCode(gson.toJson(openRet));
releaseStatus.setReleaseTime(new Date());
weappReleaseStatusService.updateStatus(releaseStatus);
}
return new ResultData();
}
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation("查询当前设置的最低基础库版本及各版本用户占比")
@GetMapping("/getSupportVersion")
public ResultData getSupportVersion(String appId) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
String openRet = openMaService.getSupportVersion();
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation("设置最低基础库版本")
@GetMapping("/setSupportVersion")
public ResultData setSupportVersion(String appId, String version) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
String openRet = openMaService.setSupportVersion(version);
logger.info(openRet);
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation(value = "小程序审核撤回", notes = "单个帐号每天审核撤回次数最多不超过1次,一个月不超过10次。")
@GetMapping("/undoCodeAudit")
public ResultData undoCodeAudit(String appId) {
Gson gson = new GsonBuilder().create();
WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(appId);
if(auditStatus != null) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenResult openResult = openMaService.undoCodeAudit();
Date curDate = new Date();
if(openResult.isSuccess()) {
// 审核状态
auditStatus.setAuditStatus(EnumWeappAuditStatus.UNDO.getCode());
auditStatus.setAuditErrCode(gson.toJson(openResult));
auditStatus.setAuditTime(curDate);
weappAuditStatusService.updateStatus(auditStatus);
// 审核次数记入wx_authorizer_info
WxAuthorizerInfo authorizerInfo = new WxAuthorizerInfo();
authorizerInfo.setAuthorizerAppid(appId);
authorizerInfo.setAuditBackTime(curDate);
authorizerInfoService.updateAuthBackInfo(authorizerInfo);
return new ResultData("审核撤回成功");
}
return new ResultData(Result.ERROR, "审核撤回失败");
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}
return new ResultData(Result.ERROR, "没有审核记录,不能撤回");
}
}

+ 79
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappDraftTemplateController.java Wyświetl plik

@@ -0,0 +1,79 @@
package com.iformall.controller;

import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.open.bean.WxOpenMaCodeTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* Stormeye Wu
*/
@RestController
@RequestMapping("/weappDraftTemplate")
@Api(description = "微信第三方开发平台-小程序-代码模版库管理")
public class WechatWeappDraftTemplateController {
private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private FmOpenService openService;


@GetMapping("/tempDraftList")
public ResultData getTempDraftList() {
try {
List<WxOpenMaCodeTemplate> list = openService.getWxOpenComponentService().getTemplateDraftList();
return new ResultData(list);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}

}

@GetMapping("/tempList")
public ResultData getTempList() {
try {
List<WxOpenMaCodeTemplate> list = openService.getWxOpenComponentService().getTemplateList();
return new ResultData(list);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@PostMapping("/addToTemplate")
public ResultData addToTemplate(@RequestBody WxOpenMaCodeTemplate template) {
if(template == null || template.getDraftId() == null) {
return new ResultData(Result.ERROR, "draftId is null");
}
try {
openService.getWxOpenComponentService().addToTemplate(template.getDraftId());
return new ResultData();
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@PostMapping("/deleteTemplate")
public ResultData deleteTemplate(@RequestBody WxOpenMaCodeTemplate template) {
if(template == null || template.getTemplateId() == null) {
return new ResultData(Result.ERROR, "templateId is null");
}
try {
openService.getWxOpenComponentService().deleteTemplate(template.getTemplateId());
return new ResultData();
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}
}

+ 175
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappMsgTemplateController.java Wyświetl plik

@@ -0,0 +1,175 @@
package com.iformall.controller;

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 com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.domain.po.WxAuthorizerInfo;
import com.iformall.domain.po.WxTemplateMsg;
import com.iformall.enums.EnumWxAuthorizationStatus;
import com.iformall.service.WxAppinfoService;
import com.iformall.service.WxAuthorizerInfoService;
import com.iformall.service.WxTemplateMsgService;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* Stormeye Wu
*/
@RestController
@RequestMapping("/weappMsgTemplate")
@Api(description = "微信第三方开发平台-小程序-消息模板设置")
public class WechatWeappMsgTemplateController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private FmOpenService openService;

@Autowired
private WxAuthorizerInfoService authorizerInfoService;

@Autowired
private WxAppinfoService appinfoService;

@Autowired
private WxTemplateMsgService templateMsgService;

@ApiOperation("获取小程序模板库标题列表")
@GetMapping("getTmpLibList")
@ApiImplicitParams({
@ApiImplicitParam(name = "appId", value = "appId", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
@ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
public ResultData getTmpLibList(String appId, Integer pageNum, Integer pageSize) {
try {
WxMaService maService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxMaTemplateLibraryListResult ret = maService.getTemplateService().findTemplateLibraryList(pageNum, pageSize);
return new ResultData(ret);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation("获取模板库某个模板标题下关键词库")
@GetMapping("getTemplateLibraryKeywordList")
@ApiImplicitParams({
@ApiImplicitParam(name = "appId", value = "appId", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "id", value = "模板标题id", dataType = "String", paramType = "query", required = true)})
public ResultData findTemplateLibraryKeywordList(String appId, String id) {
try {
WxMaService maService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxMaTemplateLibraryGetResult ret = maService.getTemplateService().findTemplateLibraryKeywordList(id);
return new ResultData(ret);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}

}

@ApiOperation("组合模板并添加至帐号下的个人模板库")
@PostMapping("addTemplate")
public ResultData addTemplate(String appId, String id, List<Integer> keywordIdList) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if(authorizerInfo == null) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(!authorizerInfo.getAuthorizationStatus().equals(EnumWxAuthorizationStatus.AUTHORIZED.getCode())) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
try {
WxMaService maService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxMaTemplateAddResult ret = maService.getTemplateService().addTemplate(id, keywordIdList);
authorizerInfo.setTemplateStatus(0);
authorizerInfo.setTemplateTime(new Date());
authorizerInfo.setUpdateTime(new Date());
authorizerInfoService.updateTemplate(authorizerInfo);
return new ResultData(ret);
} catch (WxErrorException e) {
logger.error(e.getMessage());
authorizerInfo.setTemplateStatus(1);
authorizerInfo.setTemplateTime(new Date());
authorizerInfo.setUpdateTime(new Date());
authorizerInfoService.updateTemplate(authorizerInfo);
return new ResultData(Result.ERROR, e.getMessage());
}

}

@ApiOperation("获取帐号下已存在的模板列表")
@GetMapping("getTemplateList")
@ApiImplicitParams({
@ApiImplicitParam(name = "appId", value = "appId", dataType = "String", paramType = "query", required = true),
@ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
@ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
public ResultData findTemplateList(String appId, Integer pageNum, Integer pageSize) {
try {
WxMaService maService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
if(pageNum > 0) {
pageNum = pageNum - 1;
}
WxMaTemplateListResult ret = maService.getTemplateService().findTemplateList(pageNum, pageSize);
logger.info(ret.toString());
return new ResultData(ret);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}

}

@ApiOperation("删除帐号下的某个模板")
@PostMapping("delTemplate")
public ResultData delTemplate(@RequestBody Map<String, String> params) {
String appId = params.get("appId");
String templateId = params.get("templateId");
if(StringUtils.isBlank(appId)) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
if(StringUtils.isBlank(templateId)) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
// check app
WxAppinfo appinfo = appinfoService.getByAppId(appId);
if(appinfo == null) {
String msg = "此appId未纳入管理,请联系管理员";
logger.error(msg);
return new ResultData(Result.ERROR, msg);
}
WxTemplateMsg msgQ = new WxTemplateMsg();
msgQ.setTemplateId(templateId);
msgQ.setTenantId(appinfo.getTenantId());
WxTemplateMsg msg = templateMsgService.getByObj(msgQ);
if(msg != null) {
String msgStr = "此模板正被使用,请不要删除";
logger.error(msgStr);
return new ResultData(Result.ERROR, msgStr);
}
try {
WxMaService maService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
maService.getTemplateService().delTemplate(templateId);
return new ResultData();
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}
}

+ 231
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WechatWeappSetController.java Wyświetl plik

@@ -0,0 +1,231 @@
package com.iformall.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxAuthorizerInfo;
import com.iformall.enums.EnumEnableType;
import com.iformall.enums.EnumWxAuthorizationStatus;
import com.iformall.service.WxAuthorizerInfoService;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.open.api.WxOpenMaService;
import me.chanjar.weixin.open.bean.result.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* Stormeye Wu
*/
@RestController
@RequestMapping("/weappSet")
@Api(description = "微信第三方开发平台-小程序设置")
public class WechatWeappSetController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private FmOpenService openService;

@Autowired
private WxAuthorizerInfoService authorizerInfoService;

@ApiOperation("获取小程序的信息")
@GetMapping("/getInfo")
public ResultData getAccountBasicInfo(String appId) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
String openRet = openMaService.getAccountBasicInfo();
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
return new ResultData(Result.ERROR);
}

@ApiOperation("获取小程序服务器域名")
@GetMapping("/getDomain")
public ResultData getDomain(String appId) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenResult openRet = openMaService.getDomain();
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}

}

@ApiOperation("获取小程序服务器域名")
@GetMapping("/getWebDomain")
public ResultData getWebDomain(String appId) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
String openRet = openMaService.getWebViewDomain();
logger.info(openRet);
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(Result.ERROR, e.getMessage());
}
}

@ApiOperation(value = "设置小程序服务器域名", notes = "{\n" +
" \"action\":\"add/set/delete/get\",\n" +
" \"requestdomain\":[\"https://www.qq.com\",\"https://www.qq.com\"],\n" +
" \"wsrequestdomain\":[\"wss://www.qq.com\",\"wss://www.qq.com\"],\n" +
" \"uploaddomain\":[\"https://www.qq.com\",\"https://www.qq.com\"],\n" +
" \"downloaddomain\":[\"https://www.qq.com\",\"https://www.qq.com\"],\n" +
" }")
@PostMapping("/modifyDomain")
public ResultData modifyDomain(String appId, String action,
List<String> requestDomain, List<String> wsrequestdomain,
List<String> uploaddomain, List<String> downloaddomain) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if(authorizerInfo == null) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(!authorizerInfo.getAuthorizationStatus().equals(EnumWxAuthorizationStatus.AUTHORIZED.getCode())) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenMaDomainResult openRet = openMaService.modifyDomain(action,
requestDomain, wsrequestdomain,
uploaddomain, downloaddomain);
logger.info(openRet.toString());
if(openRet.isSuccess()) {
logger.info("设置服务器域名成功");
authorizerInfo.setDomainStatus(EnumEnableType.SUCC.getCode());
authorizerInfo.setDomainTime(new Date());
authorizerInfo.setUpdateTime(new Date());

} else {
logger.info("设置服务器域名成功");
authorizerInfo.setDomainStatus(EnumEnableType.FAIL.getCode());
authorizerInfo.setDomainTime(new Date());
authorizerInfo.setUpdateTime(new Date());
}
authorizerInfoService.updateDomainUrl(authorizerInfo);
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
return new ResultData(Result.ERROR);
}

@ApiOperation(value = "设置小程序业务域名", notes = "{\n" +
" \"action\":\"add/set/delete/get\",\n" +
" \"webviewdomain\":[\"https://www.qq.com\",\"https://m.qq.com\"]\n" +
" }")
@PostMapping("/modifyWebViewDomain")
public ResultData modifyWebViewDomain(String appId, String action,
List<String> urlList) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if(authorizerInfo == null) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(!authorizerInfo.getAuthorizationStatus().equals(EnumWxAuthorizationStatus.AUTHORIZED.getCode())) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
String openRet = openMaService.setWebViewDomain(action, urlList);
logger.info(openRet);
JSONObject webRetObj = JSON.parseObject(openRet);
if(webRetObj.getInteger("errcode").equals(0)) {
logger.info("设置服务器业务域名成功");
authorizerInfo.setWebdomainStatus(EnumEnableType.SUCC.getCode());
authorizerInfo.setWebdomainTime(new Date());
authorizerInfo.setUpdateTime(new Date());
} else {
logger.info("设置服务器业务域名失败");
authorizerInfo.setWebdomainStatus(EnumEnableType.FAIL.getCode());
authorizerInfo.setWebdomainTime(new Date());
authorizerInfo.setUpdateTime(new Date());
}
authorizerInfoService.updateWebDomainUrl(authorizerInfo);
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
return new ResultData(Result.ERROR);
}

@ApiOperation(value = "绑定微信用户为小程序体验者", notes = "{\"appId\":\"string\", \"wechatId\":\"string\"}")
@PostMapping("/bindTester")
public ResultData bindTester(@RequestBody Map<String, String> params) {
String appId = params.get("appId");
String wechatId = params.get("wechatId");
if(StringUtils.isBlank(appId)) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "appId不能为空");
}
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if(authorizerInfo == null) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(!authorizerInfo.getAuthorizationStatus().equals(EnumWxAuthorizationStatus.AUTHORIZED.getCode())) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(StringUtils.isBlank(wechatId)) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "wechatId不能为空");
}
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenResult openRet = openMaService.bindTester(wechatId);
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(e.getMessage());
}
}

@ApiOperation(value = "解除绑定小程序的体验者", notes = "")
@PostMapping("/unbindTester")
public ResultData unbindTester(@RequestBody Map<String, String> params) {
String appId = params.get("appId");
String wechatId = params.get("wechatId");
if(StringUtils.isBlank(appId)) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "appId不能为空");
}
if(StringUtils.isBlank(wechatId)) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "wechatId不能为空");
}
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenResult openRet = openMaService.unbindTester(wechatId);
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
return new ResultData(e.getMessage());
}
}

@ApiOperation(value = "获取体验者列表", notes = "")
@GetMapping("/getTesterList")
public ResultData getTesterList(@RequestParam(value = "appId") String appId) {
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
WxOpenResult openRet = openMaService.getTesterList();
logger.info(openRet.toString());
return new ResultData(openRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
return new ResultData(Result.ERROR);
}
}

+ 63
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WxWeappBasicSetController.java Wyświetl plik

@@ -0,0 +1,63 @@
package com.iformall.controller;

import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.domain.po.WxWeappBasicSet;
import com.iformall.service.WxWeappBasicSetService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

/**
* Stormeye Wu
*/
@Controller
@RequestMapping("/weappBasicSet")
@Api(description = "小程序基础设置接口")
public class WxWeappBasicSetController extends BaseController {
private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private Integer getFmDeploy;

@Autowired
private WxWeappBasicSetService weappBasicSetService;

@ApiOperation("分页列表接口")
@GetMapping("list")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
@ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
public ResultData list(@ModelAttribute WxWeappBasicSet weappBasicSet, Integer pageNum, Integer pageSize) {
logger.debug("[" + getIpAddr() + "] WxWeappBasicSetController::list");
if (null == weappBasicSet) weappBasicSet = new WxWeappBasicSet();
weappBasicSet.setDeploy(getFmDeploy);
final PageInfo<WxWeappBasicSet> page = weappBasicSetService.listAsPage(weappBasicSet, pageNum, pageSize);
return new ResultData(page);
}

@PostMapping("add")
public ResultData add(WxWeappBasicSet weappBasicSet) {
logger.debug("[" + getIpAddr() + "] WxWeappBasicSetController::add");
if (null == weappBasicSet) return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
weappBasicSetService.saveOrUpdate(weappBasicSet);
return new ResultData();
}

@PostMapping("update")
public ResultData update(WxWeappBasicSet weappBasicSet) {
logger.debug("[" + getIpAddr() + "] WxWeappBasicSetController::update");
if (null == weappBasicSet) return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
weappBasicSetService.saveOrUpdate(weappBasicSet);
return new ResultData();
}

}

+ 138
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WxWeappExtSetController.java Wyświetl plik

@@ -0,0 +1,138 @@
package com.iformall.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.domain.po.WxWeappExtSet;
import com.iformall.enums.EnumAppType;
import com.iformall.service.WxAppinfoService;
import com.iformall.service.WxWeappExtSetService;
import com.iformall.utils.OpenConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* Stormeye Wu
*/
@Controller
@RequestMapping("/weappExtSet")
@Api(description = "小程序扩展设置接口")
public class WxWeappExtSetController extends BaseController {
private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private WxAppinfoService appinfoService;

@Autowired
private WxWeappExtSetService weappExtSetService;

@ApiOperation("分页列表接口")
@GetMapping("list")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
@ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
public ResultData list(@ModelAttribute WxWeappExtSet weappExtSet, Integer pageNum, Integer pageSize) {
logger.debug("[" + getIpAddr() + "] WxWeappExtSetController::list");
if (null == weappExtSet) weappExtSet = new WxWeappExtSet();
final PageInfo<WxWeappExtSet> page = weappExtSetService.listAsPage(weappExtSet, pageNum, pageSize);
return new ResultData(page);
}

@PostMapping("add")
public ResultData add(@RequestBody WxWeappExtSet weappExtSet) {
logger.debug("[" + getIpAddr() + "] WxWeappExtSetController::add");
if (null == weappExtSet) return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
weappExtSetService.saveOrUpdate(weappExtSet);
return new ResultData();
}

@PostMapping("update")
public ResultData update(@RequestBody WxWeappExtSet weappExtSet) {
logger.debug("[" + getIpAddr() + "] WxWeappBasicSetController::update");
if (null == weappExtSet) return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
if (StringUtils.isBlank(weappExtSet.getExtJson())) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
if (StringUtils.isBlank(weappExtSet.getReleaseJson())) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
weappExtSetService.saveOrUpdate(weappExtSet);
return new ResultData();
}

@ApiOperation("扩展模板-批量模板更新")
@PostMapping("batchUpdate")
public ResultData batchAdd(@RequestBody WxWeappExtSet weappExtSet) {
logger.debug("[" + getIpAddr() + "] WxWeappExtSetController::batchUpdate");
if (null == weappExtSet) return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
if(StringUtils.isBlank(weappExtSet.getExtJson())) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
if(weappExtSet.getType() == null) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
String extJson = weappExtSet.getExtJson();
JSONObject obj = JSON.parseObject(extJson);
if(obj == null) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
JSONObject extObj = obj.getJSONObject(OpenConstant.EXT);
if(extObj == null) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
JSONObject attrObj = extObj.getJSONObject(OpenConstant.ATTR);
if(attrObj == null) {
return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
}
WxWeappExtSet extSetQ = new WxWeappExtSet();
extSetQ.setType(weappExtSet.getType());
List<WxWeappExtSet> weappExtSetList = weappExtSetService.getList(extSetQ);
for(WxWeappExtSet info: weappExtSetList) {
WxAppinfo appinfo = appinfoService.getByAppId(info.getAppId());
if(appinfo == null) {
continue;
}
obj.put(OpenConstant.EXT_APPID, info.getAppId());
if(weappExtSet.getType().equals(EnumAppType.C.getCode())) {
if (attrObj != null) {
attrObj.put(OpenConstant.IF_HAVE_CAR_MODULE, String.valueOf(info.getCarSupport()));
attrObj.put(OpenConstant.IF_STORE_APP, String.valueOf(info.getStoreApp()));
}
}
if(extObj != null) {
extObj.put(OpenConstant.WE_APPID, info.getAppId());
extObj.put(OpenConstant.NAME, appinfo.getName());
if(weappExtSet.getType().equals(EnumAppType.C.getCode())) {
extObj.put(OpenConstant.ATTR, attrObj);
}
obj.put(OpenConstant.EXT, extObj);
}

WxWeappExtSet newInfo = new WxWeappExtSet();
newInfo.setExtJson(JSON.toJSONString(obj));
newInfo.setId(info.getId());

try {
weappExtSetService.saveOrUpdate(newInfo);
} catch (Exception e) {
logger.error("APPID " + info.getAppId() + ", 保存失败 " + e.getMessage());
}
}
return new ResultData();
}

}

+ 1047
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/WxWeappInfoController.java
Plik diff jest za duży
Wyświetl plik


+ 45
- 0
mlToutiaoOpen/src/main/java/com/iformall/controller/base/BaseController.java Wyświetl plik

@@ -0,0 +1,45 @@
package com.iformall.controller.base;

import com.iformall.utils.IPUtil;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@RestController
public class BaseController {
@InitBinder
public void InitBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
public void setAsText(String value) {
try {
setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value));
} catch(ParseException e) {
try {
setValue(new SimpleDateFormat("yyyy-MM-dd ").parse(value));
} catch (ParseException e1) {
setValue(null);
}
}
}

public String getAsText() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue());
}

});
}

public String getIpAddr() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ipaddress = IPUtil.getIpAddr(request);
return ipaddress;
}
}

+ 76
- 0
mlToutiaoOpen/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java Wyświetl plik

@@ -0,0 +1,76 @@
package com.iformall.interceptor;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;

public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper {
private final String body;

public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuffer stringBuilder = new StringBuffer();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
char[] charBuffer = new char[1024];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}

@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream =
new ByteArrayInputStream(body.getBytes("utf-8"));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}

@Override
public boolean isReady() {
return false;
}

@Override
public void setReadListener(ReadListener readListener) {

}

@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}

@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}

public String getBody() {
return this.body;
}
}

+ 70
- 0
mlToutiaoOpen/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java Wyświetl plik

@@ -0,0 +1,70 @@
package com.iformall.interceptor;

import com.iformall.utils.UrlCheck;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class HttpServletRequestWrapperFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestWrapperFilter.class);
// 多个跨域域名设置
// public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"};

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {

ServletRequest requestWrapper = null;
/* // 跨域访问
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String originHeader = req.getHeader("Origin");

if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) {
//通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。
res.setHeader("Access-Control-Allow-Origin", originHeader);
//通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie
//设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域
res.setHeader("Access-Control-Allow-Credentials", "true");
//请求方式
res.setHeader("Access-Control-Allow-Methods", "*");
//(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久
res.setHeader("Access-Control-Max-Age", "86400");
//首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段
//res.setHeader("Access-Control-Allow-Headers", "*");
res.setHeader("Access-Control-Allow-Headers",
"Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers");
}
*/

//sql,xss过滤
XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request);

if (request instanceof HttpServletRequest) {
String url = ((HttpServletRequest) request).getRequestURI();
if (!UrlCheck.checkUrl(url)) {
requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
}
}
if (null == requestWrapper) {
chain.doFilter(xssHttpServletRequestWrapper, response);
} else {
chain.doFilter(requestWrapper, response);
}

}


@Override
public void destroy() {

}
}

+ 125
- 0
mlToutiaoOpen/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java Wyświetl plik

@@ -0,0 +1,125 @@
package com.iformall.interceptor;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* 防止sql注入,xss攻击
* 前端可以对输入信息做预处理,后端也可以做处理。
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final Logger log = LoggerFactory.getLogger(getClass());
private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+";
private static Set<String> notAllowedKeyWords = new HashSet<String>(0);
private static String replacedString="INVALID";
static {
String keyStr[] = key.split("\\|");
for (String str : keyStr) {
notAllowedKeyWords.add(str);
}
}

private String currentUrl;

public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
currentUrl = servletRequest.getRequestURI();
}


/**覆盖getParameter方法,将参数名和参数值都做xss过滤。
* 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
* getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
*/
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return cleanXSS(value);
}
@Override
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = cleanXSS(values[i]);
}
return encodedValues;
}
@Override
public Map<String, String[]> getParameterMap(){
Map<String, String[]> values=super.getParameterMap();
if (values == null) {
return null;
}
Map<String, String[]> result=new HashMap<>();
for(String key:values.keySet()){
String encodedKey=cleanXSS(key);
int count=values.get(key).length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++){
encodedValues[i]=cleanXSS(values.get(key)[i]);
}
result.put(encodedKey,encodedValues);
}
return result;
}
/**
* 覆盖getHeader方法,将参数名和参数值都做xss过滤。
* 如果需要获得原始的值,则通过super.getHeaders(name)来获取
* getHeaderNames 也可能需要覆盖
*/
@Override
public String getHeader(String name) {
if(name.equalsIgnoreCase("user-agent")) {
return super.getHeader(name);
}
String value = super.getHeader(name);
if (value == null) {
return null;
}
return cleanXSS(value);
}

private String cleanXSS(String valueP) {
// You'll need to remove the spaces from the html entities below
String value = valueP.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
value = value.replaceAll("'", "& #39;");
value = value.replaceAll("eval\\((.*)\\)", "");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
value = value.replaceAll("script", "");
value = cleanSqlKeyWords(value);
return value;
}

private String cleanSqlKeyWords(String value) {
String paramValue = value;
for (String keyword : notAllowedKeyWords) {
if (paramValue.length() > keyword.length() + 4
&& (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) {
paramValue = StringUtils.replace(paramValue, keyword, replacedString);
log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword
+ ")"+";参数:"+value+";过滤后的参数:"+paramValue);
}
}
return paramValue;
}

}

+ 17
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/builder/AbstractBuilder.java Wyświetl plik

@@ -0,0 +1,17 @@
package com.iformall.mp.builder;

import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Stormeye
*/
public abstract class AbstractBuilder {
protected final Logger logger = LoggerFactory.getLogger(getClass());

public abstract WxMpXmlOutMessage build(String content,
WxMpXmlMessage wxMessage, WxMpService service);
}

+ 24
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/builder/ImageBuilder.java Wyświetl plik

@@ -0,0 +1,24 @@
package com.iformall.mp.builder;

import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;

/**
* @author Binary Wang(https://github.com/binarywang)
*/
public class ImageBuilder extends AbstractBuilder {

@Override
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
WxMpService service) {

WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();

return m;
}

}

+ 25
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/builder/TextBuilder.java Wyświetl plik

@@ -0,0 +1,25 @@
package com.iformall.mp.builder;

import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Binary Wang(https://github.com/binarywang)
*/
public class TextBuilder extends AbstractBuilder {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
WxMpService service) {
WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
.build();
return m;
}

}

+ 114
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMemController.java Wyświetl plik

@@ -0,0 +1,114 @@
package com.iformall.mp.controller;

import com.iformall.common.ResultData;
import com.iformall.domain.po.WxAuthorizerInfo;
import com.iformall.mapper.WxAuthorizerInfoMapper;
import com.iformall.mp.manager.WxMpManager;
import com.iformall.service.WxCUserService;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
* @author Stormeye
*/
@RestController
@RequestMapping("/wx/{appId}/mem")
public class WxMemController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxMpManager wxMpManager;

@Autowired
private WxAuthorizerInfoMapper wxAuthorizerInfoMapper;

@Autowired
private WxCUserService userService;

@GetMapping("/syncAccountFansList")
public ResultData syncAccountFansList(@PathVariable String appId) {
final WxMpService wxService = wxMpManager.getMpService(appId);

WxAuthorizerInfo authQ = new WxAuthorizerInfo();
authQ.setAuthorizerAppid(appId);
WxAuthorizerInfo authorizerInfo = wxAuthorizerInfoMapper.findWeChatMp(authQ);

String nextOpenId = null;

while (true) {
WxMpUserList mpUserList;
try {
mpUserList = wxService.getUserService().userList(nextOpenId);
} catch (WxErrorException e) {
logger.error("获取粉丝openIds出错: " + e.getMessage());
break;
}
logger.info(mpUserList.toString());
getBatchUserInfos(wxService, mpUserList, authorizerInfo);
nextOpenId = mpUserList.getNextOpenid();
if(StringUtils.isBlank(nextOpenId)) {
break;
}
}
return new ResultData();
}

private void getBatchUserInfos(WxMpService wxService, WxMpUserList mpUserList, WxAuthorizerInfo authorizerInfo) {
List<String> openIds = mpUserList.getOpenids();

if(openIds.size() > 100) {
int index = 0;
int index_end = index + 100;
while(true) {
if(openIds.size()-1 > index_end) {
getBatchUserInfo(wxService, openIds.subList(index, index_end), authorizerInfo);
} else if(openIds.size()-1 > index) {
getBatchUserInfo(wxService, openIds.subList(index, openIds.size()-1), authorizerInfo);
} else {
break;
}
index += 100;
index_end = index + 100;
}
} else {
getBatchUserInfo(wxService, openIds, authorizerInfo);
}
}

private void getBatchUserInfo(WxMpService wxService, List<String> openIds, WxAuthorizerInfo authorizerInfo) {
if(openIds.size() <= 0) {
return;
}
List<WxMpUser> userList = null;
try{
userList = wxService.getUserService().userInfoList(openIds);
} catch (WxErrorException e) {
logger.error("batchget userinfo list error: " + e.getMessage());
return;
}
if(userList != null) {
logger.info(userList.toString());
for(WxMpUser mpUser: userList) {
if(StringUtils.isNotBlank(mpUser.getUnionId())) {
try {
userService.saveOrUpdateMpUser(mpUser, authorizerInfo);
} catch (Exception e) {
logger.error("保存用户出错: " + e.getMessage());
}
}
}
}
}
}

+ 190
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMenuController.java Wyświetl plik

@@ -0,0 +1,190 @@
package com.iformall.mp.controller;

import com.iformall.mp.manager.WxMpManager;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
import me.chanjar.weixin.mp.bean.menu.WxMpMenu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.net.MalformedURLException;
import java.net.URL;

import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType;

/**
* @author Stormeye
*/
@RestController
@RequestMapping("/wx/menu/{appId}")
public class WxMenuController {

@Autowired
private WxMpManager wxMpManager;

/**
* <pre>
* 自定义菜单创建接口
* 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
* 如果要创建个性化菜单,请设置matchrule属性
* 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
* </pre>
*
* @return 如果是个性化菜单,则返回menuid,否则返回null
*/
@PostMapping("/create")
public String menuCreate(@PathVariable String appId, @RequestBody WxMenu menu) throws WxErrorException {
return wxMpManager.getMpService(appId).getMenuService().menuCreate(menu);
}

@GetMapping("/create")
public String menuCreateSample(@PathVariable String appId) throws WxErrorException, MalformedURLException {
WxMenu menu = new WxMenu();
WxMenuButton button1 = new WxMenuButton();
button1.setType(MenuButtonType.CLICK);
button1.setName("今日歌曲");
button1.setKey("V1001_TODAY_MUSIC");

// WxMenuButton button2 = new WxMenuButton();
// button2.setType(WxConsts.BUTTON_MINIPROGRAM);
// button2.setName("小程序");
// button2.setAppId("wx286b93c14bbf93aa");
// button2.setPagePath("pages/lunar/index.html");
// button2.setUrl("http://mp.weixin.qq.com");

WxMenuButton button3 = new WxMenuButton();
button3.setName("菜单");

menu.getButtons().add(button1);
// menu.getButtons().add(button2);
menu.getButtons().add(button3);

WxMenuButton button31 = new WxMenuButton();
button31.setType(MenuButtonType.VIEW);
button31.setName("搜索");
button31.setUrl("http://www.soso.com/");

WxMenuButton button32 = new WxMenuButton();
button32.setType(MenuButtonType.VIEW);
button32.setName("视频");
button32.setUrl("http://v.qq.com/");

WxMenuButton button33 = new WxMenuButton();
button33.setType(MenuButtonType.CLICK);
button33.setName("赞一下我们");
button33.setKey("V1001_GOOD");

WxMenuButton button34 = new WxMenuButton();
button34.setType(MenuButtonType.VIEW);
button34.setName("获取用户信息");

ServletRequestAttributes servletRequestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (servletRequestAttributes != null) {
HttpServletRequest request = servletRequestAttributes.getRequest();
URL requestURL = new URL(request.getRequestURL().toString());
String url = wxMpManager.getMpService(appId)
.oauth2buildAuthorizationUrl(
String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), appId),
WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
button34.setUrl(url);
}

button3.getSubButtons().add(button31);
button3.getSubButtons().add(button32);
button3.getSubButtons().add(button33);
button3.getSubButtons().add(button34);

return wxMpManager.getMpService(appId).getMenuService().menuCreate(menu);
}

/**
* <pre>
* 自定义菜单创建接口
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
* 如果要创建个性化菜单,请设置matchrule属性
* 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
* </pre>
*
* @param json
* @return 如果是个性化菜单,则返回menuid,否则返回null
*/
@PostMapping("/createByJson")
public String menuCreate(@PathVariable String appId, @RequestBody String json) throws WxErrorException {
return wxMpManager.getMpService(appId).getMenuService().menuCreate(json);
}

/**
* <pre>
* 自定义菜单删除接口
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN
* </pre>
*/
@GetMapping("/delete")
public void menuDelete(@PathVariable String appId) throws WxErrorException {
wxMpManager.getMpService(appId).getMenuService().menuDelete();
}

/**
* <pre>
* 删除个性化菜单接口
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
* </pre>
*
* @param menuId 个性化菜单的menuid
*/
@GetMapping("/delete/{menuId}")
public void menuDelete(@PathVariable String appId, @PathVariable String menuId) throws WxErrorException {
wxMpManager.getMpService(appId).getMenuService().menuDelete(menuId);
}

/**
* <pre>
* 自定义菜单查询接口
* 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN
* </pre>
*/
@GetMapping("/get")
public WxMpMenu menuGet(@PathVariable String appId) throws WxErrorException {
return wxMpManager.getMpService(appId).getMenuService().menuGet();
}

/**
* <pre>
* 测试个性化菜单匹配结果
* 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
* </pre>
*
* @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。
*/
@GetMapping("/menuTryMatch/{userid}")
public WxMenu menuTryMatch(@PathVariable String appId, @PathVariable String userid) throws WxErrorException {
return wxMpManager.getMpService(appId).getMenuService().menuTryMatch(userid);
}

/**
* <pre>
* 获取自定义菜单配置接口
* 本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过API调用设置的菜单,则返回菜单的开发配置,而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。
* 请注意:
* 1、第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自定义菜单配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。
* 2、本接口与自定义菜单查询接口的不同之处在于,本接口无论公众号的接口是如何设置的,都能查询到接口,而自定义菜单查询接口则仅能查询到使用API设置的菜单配置。
* 3、认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。
* 4、从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。
* 5、本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理-获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理-获取永久素材接口来获取这些素材)。
* 接口调用请求说明:
* http请求方式: GET(请使用https协议)
* https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
* </pre>
*/
@GetMapping("/getSelfMenuInfo")
public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String appId) throws WxErrorException {
return wxMpManager.getMpService(appId).getMenuService().getSelfMenuInfo();
}
}

+ 152
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMpCallBackController.java Wyświetl plik

@@ -0,0 +1,152 @@
package com.iformall.mp.controller;

import com.iformall.mp.manager.WxMpManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;

/**
* @author Stormeye
*/
@Controller
@RequestMapping("/wx")
public class WxMpCallBackController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxMpManager wxMpManager;

/**
* GET请求:进行URL、Tocken 认证;
* 1. 将token、timestamp、nonce三个参数进行字典序排序
* 2. 将三个参数字符串拼接成一个字符串进行sha1加密
* 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
*/
@GetMapping(value = "/{account}/message")
@ResponseBody
public void authGet(@PathVariable String account, HttpServletRequest request, HttpServletResponse response) throws IOException {
String signature = request.getParameter("signature");// 微信加密签名
String timestamp = request.getParameter("timestamp");// 时间戳
String nonce = request.getParameter("nonce");// 随机数
String echostr = request.getParameter("echostr");// 随机字符串

if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
throw new IllegalArgumentException("请求参数非法,请核实!");
}

logger.info("接收到来自微信服务器的认证消息:[{}, {}, {}, {}]",
signature, timestamp, nonce, echostr);

// 数据库 ->
final WxMpService wxService = wxMpManager.getMpService(account);
if (wxService == null) {
throw new IllegalArgumentException(String.format("未找到对应account=[%s]的配置,请核实!", account));
}

if (wxService.checkSignature(timestamp, nonce, signature)) {
logger.info("微信服务验证成功");
PrintWriter out = response.getWriter();
out.print(echostr);
out.close();
}
}

/**
* POST 请求:进行消息处理;
*/
@PostMapping(value = "/{account}/message")
@ResponseBody
public String post(@PathVariable String account, HttpServletRequest request) throws IOException {
// 处理用户和微信公众账号交互消息
String signature = request.getParameter("signature");// 微信加密签名
String timestamp = request.getParameter("timestamp");// 时间戳
String nonce = request.getParameter("nonce");// 随机数
String openid = request.getParameter("openid");
String encType = request.getParameter("encrypt_type");
String msgSignature = request.getParameter("msg_signature");

if (StringUtils.isAnyBlank(signature, timestamp, nonce)) {
throw new IllegalArgumentException("请求参数非法,请核实!");
}

final WxMpService wxService = wxMpManager.getMpService(account);

if (!wxService.checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}

InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String requestBody = new String(outSteam.toByteArray(), Charset.forName("UTF-8"));
logger.info(requestBody);

outSteam.close();
inStream.close();

logger.info("\n接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
openid, signature, encType, msgSignature, timestamp, nonce, requestBody);

String out = null;
if (encType == null) {
// 明文传输的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);

WxMpXmlOutMessage outMessage = this.route(inMessage, wxService);
if (outMessage == null) {
logger.info("1 return: success");
return "success";
}

out = outMessage.toXml();
logger.info(out);
} else if ("aes".equalsIgnoreCase(encType)) {
// aes加密的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
timestamp, nonce, msgSignature);
this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
WxMpXmlOutMessage outMessage = this.route(inMessage, wxService);
if (outMessage == null) {
logger.info("2 return: success");
return "success";
}
logger.info("out: " + outMessage.toXml());

out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
}
this.logger.info("\n组装回复信息:{}", out);
return out;
}

private WxMpXmlOutMessage route(WxMpXmlMessage message, WxMpService wxService) {
String appId = wxService.getWxMpConfigStorage().getAppId();
logger.info("route appId: " + appId);
try {
return wxMpManager.getRouter(appId).route(message);
} catch (Exception e) {
this.logger.error("路由消息时出现异常!", e);
}

return null;
}

}

+ 70
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxMpTemplateController.java Wyświetl plik

@@ -0,0 +1,70 @@
package com.iformall.mp.controller;

import com.google.common.collect.Lists;
import com.iformall.common.ResultData;
import com.iformall.mp.manager.WxMpManager;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* @author Stormeye
*/
@RestController
@RequestMapping("/wx/{appId}/template")
public class WxMpTemplateController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxMpManager wxMpManager;

@GetMapping("/send")
public ResultData syncAccountFansList(@PathVariable String appId) throws WxErrorException {
final WxMpService wxService = wxMpManager.getMpService(appId);

// 审核结果通知 SxhGTL6AlcYtbc4nEYxcS4zoGRzTiUr9KEscvpEItQw
// {{first.DATA}}
// 审核状态:{{keyword1.DATA}}
// 活动名称:{{keyword2.DATA}}
// 活动时间:{{keyword3.DATA}}
// 活动地点:{{keyword4.DATA}}
// {{remark.DATA}}

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

String templateId = "SxhGTL6AlcYtbc4nEYxcS4zoGRzTiUr9KEscvpEItQw";

WxMpTemplateMessage.MiniProgram miniprogram = new WxMpTemplateMessage.MiniProgram();
miniprogram.setAppid("wxea71200db93d756b");
miniprogram.setPagePath("pages/index/index");
miniprogram.setUsePath(true);

WxMpTemplateMessage msg = WxMpTemplateMessage.builder()
.toUser("o8iB81ZUK0SOR0ZOp6t9Q1GCMYuM")
.templateId(templateId)
.miniProgram(miniprogram)
.data(Lists.newArrayList(
new WxMpTemplateData("first", "恭喜您,您的小程序\"富茂客官开发\"审核已通过", "#173177"),
new WxMpTemplateData("keyword1", "审核已通过", "#173177"),
new WxMpTemplateData("keyword2", "提交审核已通过", "#173177"),
new WxMpTemplateData("keyword3", dateFormat.format(new Date()), "#173177"),
new WxMpTemplateData("keyword4", "地点", "#173177"),
new WxMpTemplateData("remark", "test", "#173177")
))
.build();
String rest = wxService.getTemplateMsgService().sendTemplateMsg(msg);
logger.info(rest);
return new ResultData();
}
}

+ 45
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/controller/WxRedirectController.java Wyświetl plik

@@ -0,0 +1,45 @@
package com.iformall.mp.controller;

import com.iformall.mp.manager.WxMpManager;
import com.iformall.mp.utils.MpUtil;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
* @author Stormeye
*/
@Controller
@RequestMapping("/wx/redirect/{appId}")
public class WxRedirectController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxMpManager wxMpManager;


@RequestMapping("/greet")
public String greetUser(@PathVariable String appId, @RequestParam String code, ModelMap map) {

WxMpService mpService = wxMpManager.getMpService(appId);

try {
WxMpOAuth2AccessToken accessToken = mpService.oauth2getAccessToken(code);
WxMpUser user = mpService.oauth2getUserInfo(accessToken, null);
map.put("user", user);
} catch (WxErrorException e) {
e.printStackTrace();
}

return "greet_user";
}
}

+ 29
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/error/ErrorController.java Wyświetl plik

@@ -0,0 +1,29 @@
package com.iformall.mp.error;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* <pre>
* 出错页面控制器
* Created by Binary Wang on 2018/8/25.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Controller
@RequestMapping("/error")
public class ErrorController {

@GetMapping(value = "/404")
public String error404() {
return "error";
}

@GetMapping(value = "/500")
public String error500() {
return "error";
}

}

+ 27
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/error/ErrorPageConfiguration.java Wyświetl plik

@@ -0,0 +1,27 @@
package com.iformall.mp.error;

import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

/**
* <pre>
* 配置错误状态与对应访问路径
* Created by Binary Wang on 2018/8/25.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Component
public class ErrorPageConfiguration implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
errorPageRegistry.addErrorPages(
new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"),
new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500")
);
}

}

+ 144
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/manager/WxMpManager.java Wyświetl plik

@@ -0,0 +1,144 @@
package com.iformall.mp.manager;

import com.iformall.service.wechat.FmOpenService;
import com.iformall.service.wechat.handler.*;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.constant.WxMpEventConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static me.chanjar.weixin.common.api.WxConsts.*;

/**
* wechat mp configuration
*
* @author Stormeye
*/
@Service
public class WxMpManager {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

private static Map<String, WxMpMessageRouter> myRouterMap = new ConcurrentHashMap<String, WxMpMessageRouter>();


@Autowired
protected FmOpenService openService;

@Autowired
protected LogHandler logHandler;
@Autowired
protected NullHandler nullHandler;
@Autowired
protected KfSessionHandler kfSessionHandler;
@Autowired
protected StoreCheckNotifyHandler storeCheckNotifyHandler;
@Autowired
protected LocationHandler locationHandler;
@Autowired
protected MenuHandler menuHandler;
@Autowired
protected MsgHandler msgHandler;
@Autowired
protected UnsubscribeHandler unsubscribeHandler;
@Autowired
protected SubscribeHandler subscribeHandler;

public WxMpService getMpService(String appId) {
return openService.getWxOpenComponentService().getWxMpServiceByAppid(appId);
}

public WxMpMessageRouter getRouter(String appId) {
if (myRouterMap.containsKey(appId)) {
logger.info("found appId : " + appId);
return myRouterMap.get(appId);
} else {
WxMpService wxMpService = openService.getWxOpenComponentService().getWxMpServiceByAppid(appId);
WxMpMessageRouter newRouter = newRouter(wxMpService);
myRouterMap.put(appId, newRouter);
logger.info("found new appId : " + appId);
return newRouter;
}
}

private WxMpMessageRouter newRouter(WxMpService wxMpService) {
final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);

// 记录所有事件的日志 (异步执行)
newRouter.rule().handler(this.logHandler).next();


// 接收客服会话管理事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
.handler(this.kfSessionHandler).end();
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
.handler(this.kfSessionHandler).end();
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
.handler(this.kfSessionHandler).end();

// 门店审核事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(WxMpEventConstants.POI_CHECK_NOTIFY)
.handler(this.storeCheckNotifyHandler).end();

// 自定义菜单事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(MenuButtonType.CLICK)
.handler(this.menuHandler).end();

// 点击菜单连接事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(MenuButtonType.VIEW)
.handler(this.nullHandler).end();

// 关注事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(EventType.SUBSCRIBE)
.handler(this.subscribeHandler).end();

// 取消关注事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(EventType.UNSUBSCRIBE)
.handler(this.unsubscribeHandler).end();

// 上报地理位置事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(EventType.LOCATION)
.handler(this.locationHandler).end();

// 接收地理位置消息
newRouter.rule().async(false)
.msgType(XmlMsgType.LOCATION)
.handler(this.locationHandler).end();

// 扫码事件
newRouter.rule().async(false)
.msgType(XmlMsgType.EVENT)
.event(EventType.SCAN)
.handler(this.nullHandler).end();

// 默认
newRouter.rule().async(false).handler(this.msgHandler).end();

return newRouter;
}

}

+ 22
- 0
mlToutiaoOpen/src/main/java/com/iformall/mp/utils/MpUtil.java Wyświetl plik

@@ -0,0 +1,22 @@
package com.iformall.mp.utils;

import com.iformall.domain.po.WxAppinfo;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;

/**
* @author Stormeye
*/
public class MpUtil {
static public WxMpService getMpService(WxAppinfo appinfo) {
WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
configStorage.setAppId(appinfo.getAppId());
configStorage.setSecret(appinfo.getSecret());
configStorage.setToken(appinfo.getToken());
configStorage.setAesKey(appinfo.getAesKey());
WxMpService service = new WxMpServiceImpl();
service.setWxMpConfigStorage(configStorage);
return service;
}
}

+ 52
- 0
mlToutiaoOpen/src/main/java/com/iformall/schedule/AppAccessTokenSchedule.java Wyświetl plik

@@ -0,0 +1,52 @@
package com.iformall.schedule;

import com.iformall.domain.vo.WxWeappInfo;
import com.iformall.mapper.WxAuthorizerInfoMapper;
import com.iformall.service.wechat.FmOpenService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class AppAccessTokenSchedule {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private WxAuthorizerInfoMapper authorizerInfoMapper;

@Autowired
private FmOpenService openService;

// @Scheduled(cron = "0 40 */1 * * *?") // 每小时更新一次
//@Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次
public void updateAppAccessToken() {
// 暂不启用定时token设置
/*
// 微信小程序
List<WxWeappInfo> weappList = authorizerInfoMapper.findWeappList();
weappList.stream().forEach(weappInfo -> {
try {
openService.getWxOpenComponentService().getAuthorizerAccessToken(weappInfo.getAuthorizerAppid(), true);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
});

// 微信公众号
List<WxWeappInfo> wxmpList = authorizerInfoMapper.findWxMpList();
wxmpList.stream().forEach(weappInfo -> {
try {
openService.getWxOpenComponentService().getAuthorizerAccessToken(weappInfo.getAuthorizerAppid(), true);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
});
*/

}
}

+ 18
- 0
mlToutiaoOpen/src/main/java/com/iformall/schedule/SchedulingConfig.java Wyświetl plik

@@ -0,0 +1,18 @@
package com.iformall.schedule;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@Configuration
@EnableScheduling
public class SchedulingConfig implements SchedulingConfigurer {

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {


}

}

+ 80
- 0
mlToutiaoOpen/src/main/java/com/iformall/schedule/UserUnionIdSchedule.java Wyświetl plik

@@ -0,0 +1,80 @@
package com.iformall.schedule;

import com.iformall.domain.po.WxPayAccount;
import com.iformall.domain.vo.WxPayOrderVo;
import com.iformall.mapper.WxPayAccountMapper;
import com.iformall.mapper.WxPayOrderMapper;
import com.iformall.service.WxAppinfoService;
import com.iformall.service.wechat.FmOpenService;
import me.chanjar.weixin.open.api.WxOpenMaService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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

@Component
public class UserUnionIdSchedule {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

private final int TIME_OUT_VALUE = 4 * 60 * 1000; //4分钟

@Autowired
WxPayOrderMapper payOrderMapper;

@Autowired
private FmOpenService openService;

@Autowired
private WxPayAccountMapper payAccountMapper;

@Autowired
WxAppinfoService wxAppinfoService;

//@Scheduled(cron = "0 */4 * * * *?") // 每4分钟检查一次
//@Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次
public void payOrderGetUnionIdSchedule() {
Map dateMap = new HashMap();
Date curDate = new Date();
Date expireDate = new Date(curDate.getTime() - TIME_OUT_VALUE );

// 券相关订单
dateMap.put("startDate", expireDate);
List<WxPayOrderVo> paidList = payOrderMapper.findListOfPaidOrderByDate(dateMap);
paidList.parallelStream().forEach( payOrderVo -> {
getUnionId(payOrderVo);
});
}

/**
* 根据payOrder信息获取UnionId
* @param payOrderVo
*/
public void getUnionId(WxPayOrderVo payOrderVo) {
if(StringUtils.isBlank(payOrderVo.getOpenId())) {
return;
}
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(payOrderVo.getAppId());
if(StringUtils.isNotBlank(payOrderVo.getTransactionId())) {
String openRet = openMaService.getPaidUnionId(payOrderVo.getOpenId(), payOrderVo.getTransactionId(), null, null);
logger.info(openRet);
} else {
WxPayAccount payAccount = payAccountMapper.selectById(payOrderVo.getPayId());
if(payAccount != null) {
String openRet = openMaService.getPaidUnionId(payOrderVo.getOpenId(), null, payAccount.getMchId(), payOrderVo.getPayOrderNo());
logger.info(openRet);
}
}
}catch (Exception e) {
logger.error(e.getMessage());
}

}
}

+ 24
- 0
mlToutiaoOpen/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java Wyświetl plik

@@ -0,0 +1,24 @@
package com.iformall.shiro;

import com.iformall.enums.EnumLoginType;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyRetryLimitCredentialsMatcher extends HashedCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
if(authcToken instanceof UseriFormallToken) {
UseriFormallToken tk = (UseriFormallToken) authcToken;
if(tk.getType().equals(EnumLoginType.NOPASSWD)){
return true;
}
boolean matches = super.doCredentialsMatch(authcToken, info);
return matches;
}
boolean matches =super.doCredentialsMatch(authcToken, info);
return matches;
}
}

+ 90
- 0
mlToutiaoOpen/src/main/java/com/iformall/shiro/MyShiroRealm.java Wyświetl plik

@@ -0,0 +1,90 @@
package com.iformall.shiro;

import com.iformall.domain.po.MallUserInfo;
import com.iformall.enums.EnumMallUserStatus;
import com.iformall.service.MallPermissionService;
import com.iformall.service.MallUserInfoService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import javax.annotation.Resource;

/**
* Created by yangqj on 2017/4/21.
*/
public class MyShiroRealm extends AuthorizingRealm {

@Resource
private MallUserInfoService userService;

@Resource
private MallPermissionService resourcesService;

//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
MallUserInfo user= (MallUserInfo) SecurityUtils.getSubject().getPrincipal();//User{id=1, username='admin', password='3ef7164d1f6167cb9f2658c07d3c2f0a', enable=1}
// Map<String,Object> map = new HashMap<String,Object>();
// map.put("userid",user.getId());
// List<SysPermission> resourcesList = resourcesService.list(map);
// 权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// for(SysPermission resources: resourcesList){
// info.addStringPermission(resources.getUrl());
// }
return info;
}

//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户的输入的账号.
String username = (String)token.getPrincipal();
MallUserInfo user = userService.getByUsername(username);
if(user == null) {
throw new UnknownAccountException("用户名不存在");
}
// if (0==user.getEnable()) {
// throw new LockedAccountException(); // 帐号锁定
// }
//用户被禁用
if(user.getStatus()==null ||
!EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) {
throw new DisabledAccountException("用户被禁用");
}
if(!user.getTenantId().equals("1")) {
// 只支持租户为1的用户
throw new UnknownAccountException("用户名不支持");
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user, //用户
user.getPassword(), //密码
ByteSource.Util.bytes(username),
getName() //realm name
);
// 当验证都通过后,把用户信息放在session里
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute(UserSession.userInfo, user);
session.setAttribute(UserSession.userId, user.getId());
session.setAttribute(UserSession.tenantId, user.getTenantId());
return authenticationInfo;
}


/**
* 指定principalCollection 清除
*/
/* public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) {

SimplePrincipalCollection principals = new SimplePrincipalCollection(
principalCollection, getName());
super.clearCachedAuthorizationInfo(principals);
}
*/
}

+ 32
- 0
mlToutiaoOpen/src/main/java/com/iformall/shiro/PasswordHelper.java Wyświetl plik

@@ -0,0 +1,32 @@
package com.iformall.shiro;


import com.iformall.domain.po.MallUserInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;


public class PasswordHelper {
//private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
private String algorithmName = "md5";
private int hashIterations = 2;

public void encryptPassword(MallUserInfo user) {
//String salt=randomNumberGenerator.nextBytes().toHex();
String newPassword = new SimpleHash(algorithmName, user.getPassword(), ByteSource.Util.bytes(user.getUsername()), hashIterations).toHex();
//String newPassword = new SimpleHash(algorithmName, user.getPassword()).toHex();
user.setPassword(newPassword);

}

public static void main(String[] args) {
MallUserInfo user = new MallUserInfo();
user.setUsername("fmadmin");
user.setPassword("fm2020open");
PasswordHelper passwordHelper = new PasswordHelper();
passwordHelper.encryptPassword(user);
System.out.println(user);
System.out.println(user.getPassword());
}
}

+ 126
- 0
mlToutiaoOpen/src/main/java/com/iformall/shiro/ShiroService.java Wyświetl plik

@@ -0,0 +1,126 @@
package com.iformall.shiro;

import com.iformall.service.MallPermissionService;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.LinkedHashMap;
import java.util.Map;

/**
* Created by yangqj on 2017/4/30.
*/
//@Service
public class ShiroService {
@Autowired
private ShiroFilterFactoryBean shiroFilterFactoryBean;
@Autowired
private MallPermissionService resourcesService;
@Autowired
private RedisSessionDAO redisSessionDAO;
/**
* 初始化权限
*/
public Map<String, String> loadFilterChainDefinitions() {
// 权限控制map.从数据库获取
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/css/**","anon");
filterChainDefinitionMap.put("/js/**","anon");
filterChainDefinitionMap.put("/img/**","anon");
filterChainDefinitionMap.put("/user/**","anon");
filterChainDefinitionMap.put("/font-awesome/**","anon");
// Map<String,Object> map = new HashMap<>();
// List<SysPermission> resourcesList = resourcesService.list(map);
// for(SysPermission resources:resourcesList){
//
// if (StringUtil.isNotEmpty(resources.getUrl())) {
// String permission = "perms[" + resources.getUrl()+ "]";
// filterChainDefinitionMap.put(resources.getUrl(),permission);
// }
// }
filterChainDefinitionMap.put("/**", "authc");
return filterChainDefinitionMap;
}

/**
* 重新加载权限
*/
public void updatePermission() {

synchronized (shiroFilterFactoryBean) {

AbstractShiroFilter shiroFilter = null;
try {
shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean
.getObject();
} catch (Exception e) {
throw new RuntimeException(
"get ShiroFilter from shiroFilterFactoryBean error!");
}

PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
.getFilterChainResolver();
DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
.getFilterChainManager();

// 清空老的权限控制
manager.getFilterChains().clear();

shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
shiroFilterFactoryBean
.setFilterChainDefinitionMap(loadFilterChainDefinitions());
// 重新构建生成
Map<String, String> chains = shiroFilterFactoryBean
.getFilterChainDefinitionMap();
for (Map.Entry<String, String> entry : chains.entrySet()) {
String url = entry.getKey();
String chainDefinition = entry.getValue().trim()
.replace(" ", "");
manager.createChain(url, chainDefinition);
}

System.out.println("更新权限成功!!");
}
}

/**
* 根据userId 清除当前session存在的用户的权限缓存
* @param userIds 已经修改了权限的userId
*/
/* public void clearUserAuthByUserId(List<Integer> userIds){
if(null == userIds || userIds.size() == 0) return ;
//获取所有session
Collection<Session> sessions = redisSessionDAO.getActiveSessions();
//定义返回
List<SimplePrincipalCollection> list = new ArrayList<SimplePrincipalCollection>();
for (Session session:sessions){
//获取session登录信息。
Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if(null != obj && obj instanceof SimplePrincipalCollection){
//强转
SimplePrincipalCollection spc = (SimplePrincipalCollection)obj;
//判断用户,匹配用户ID。
obj = spc.getPrimaryPrincipal();
if(null != obj && obj instanceof User){
User user = (User) obj;
System.out.println("user:"+user);
//比较用户ID,符合即加入集合
if(null != user && userIds.contains(user.getId())){
list.add(spc);
}
}
}
}
RealmSecurityManager securityManager =
(RealmSecurityManager) SecurityUtils.getSecurityManager();
MyShiroRealm realm = (MyShiroRealm)securityManager.getRealms().iterator().next();
for (SimplePrincipalCollection simplePrincipalCollection : list) {
realm.clearCachedAuthorizationInfo(simplePrincipalCollection);
}
}*/
}

+ 11
- 0
mlToutiaoOpen/src/main/java/com/iformall/shiro/UserSession.java Wyświetl plik

@@ -0,0 +1,11 @@
package com.iformall.shiro;

public class UserSession {
public static String userInfo="userSession";
public static String userId ="userSessionId";

public static String tenantId ="TENANT_ID";

}

+ 39
- 0
mlToutiaoOpen/src/main/java/com/iformall/shiro/UseriFormallToken.java Wyświetl plik

@@ -0,0 +1,39 @@
package com.iformall.shiro;

import com.iformall.enums.EnumLoginType;
import org.apache.shiro.authc.UsernamePasswordToken;

public class UseriFormallToken extends UsernamePasswordToken {
private static final long serialVersionUID = -2564928913725078138L;

private EnumLoginType type;

public UseriFormallToken() {
super();
}

public UseriFormallToken(String username, String password, EnumLoginType type, boolean rememberMe, String host) {
super(username, password, rememberMe, host);
this.type = type;
}

/** 免密登录 */
public UseriFormallToken(String username) {
super(username, "", false, null);
this.type = EnumLoginType.NOPASSWD;
}
/** 账号密码登录 */
public UseriFormallToken(String username, String pwd) {
super(username, pwd, false, null);
this.type = EnumLoginType.PASSWORD;
}

public EnumLoginType getType() {
return type;
}


public void setType(EnumLoginType type) {
this.type = type;
}
}

+ 61
- 0
mlToutiaoOpen/src/main/java/com/iformall/utils/ShiroUtils.java Wyświetl plik

@@ -0,0 +1,61 @@
package com.iformall.utils;

import com.iformall.common.ErrorCode;
import com.iformall.domain.po.MallUserInfo;
import com.iformall.exception.MallinkException;
import com.iformall.shiro.UserSession;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

/**
* Shiro工具类
*
* @author stormeye.wu
* @email wugq@mippoint.com
* @date 2016年11月12日 上午9:49:19
*/
public class ShiroUtils {

public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}

public static Subject getSubject() {
return SecurityUtils.getSubject();
}

public static MallUserInfo getUserInfo() {
return (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo);
}

public static Long getUserId() {
return getUserInfo().getId();
}

public static void setSessionAttribute(Object key, Object value) {
getSession().setAttribute(key, value);
}

public static Object getSessionAttribute(Object key) {
return getSession().getAttribute(key);
}

public static boolean isLogin() {
return SecurityUtils.getSubject().getPrincipal() != null;
}

public static void logout() {
SecurityUtils.getSubject().logout();
}

public static String getKaptcha(String key) {
Object kaptcha = getSessionAttribute(key);
if (kaptcha == null) {
throw new MallinkException(ErrorCode.KAPCHA_NOT_VALID);
}
getSession().removeAttribute(key);
return kaptcha.toString();
}

}

+ 15
- 0
mlToutiaoOpen/src/main/java/com/iformall/utils/UrlCheck.java Wyświetl plik

@@ -0,0 +1,15 @@
package com.iformall.utils;

/**
* @author gongbiao
*/
public class UrlCheck {

public static boolean checkUrl(String url) {
return url.contains("awsFileUpload")
|| url.contains("awsFilesUpload")
|| url.contains("wxMsgCallback")
|| url.contains("notify");
}

}

+ 125
- 0
mlToutiaoOpen/src/main/resources/application-dev.yml Wyświetl plik

@@ -0,0 +1,125 @@
spring:
profiles:
include: rabbitMQ
# JDBC
datasource:
url: jdbc:mysql://101.200.130.134:3306/mallink?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false&useAffectedRows=true
username: root
password: fm2020test
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 28000
minEvictableIdleTimeMillis: 28000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000"
#jackson:
#date-format: yyyy-MM-dd HH:mm:ss

# REDIS
redis:
host: 101.200.130.134
port: 6379
password: iF0rm@2l2ol9
timeout: 3600
expire: 1800 #30分钟
database: 1
defaultExpiration: 2592000 # 默认生命周期30天
jedis:
pool:
max-active: 50
max-idle: 50
max-wait: -1
min-idle: 10
# EMAIL
mail:
host: smtp.exmail.qq.com
username: zhengfangyuan@iformall.com
password: xnydCeUzofB2h8qp # 授权密码
properties:
mail:
smtp:
auth: true
starttls:
enable: true
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
aws:
clientRegion: cn-northwest-1
bucketName: iformall-net
access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=)
secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=)

#wechat:
# open:
# componentAppId: "wxdfc8fb4e62d6b52b"
# componentSecret: "98daa62b316dd6feabaad708327ce233"
# componentToken: "formall2018"
# componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN"
# redis:
# host: 101.201.103.81
# port: 6379
# password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk)
# timeout: 3600
# expire: 1800 #30分钟
# database: 2
# defaultExpiration: 2592000 # 默认生命周期30天
# jedis:
# pool:
# max-active: 100
# max-idle: 500
# max-wait: -1
# min-idle: 10

wechat:
web:
appId: "wx091907dd0bfd3f6b"
secret: "2a2ca10738998b9ef92c1fe8a4d366a6"
url: "https://admintest.malls.iformall.com"
open:
componentAppId: wxdfc8fb4e62d6b52b
componentSecret: 98daa62b316dd6feabaad708327ce233
componentToken: formall2018
componentAesKey: htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN
redis:
host: 101.200.130.134
port: 6379
password: iF0rm@2l2ol9
timeout: 3600
expire: 1800 #30分钟
database: 2
defaultExpiration: 2592000 # 默认生命周期30天
jedis:
pool:
max-active: 100
max-idle: 100
max-wait: -1
min-idle: 10

jasypt:
encryptor:
password: oRqdnDbK5pj3eMmB

fm:
exception: false
exception_emails: houtaikaifa@iformall.com
audit_emails: xiaochengxufabu@iformall.com
deploy: 1
upload_dir: /home/test/server/uploads/

logging:
level:
tk.mybatis: debug
com.iformall.mapper: debug
me.chanjar.weixin: debug
path: ./logs/o

+ 110
- 0
mlToutiaoOpen/src/main/resources/application-prod.yml Wyświetl plik

@@ -0,0 +1,110 @@
spring:
profiles:
include: aliyunRocketMQ
# JDBC
datasource:
url: jdbc:mysql://zc349w82qvn56ftl5e64-rw4rm.rwlb.rds.aliyuncs.com:3306/mallink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true
username: ENC(nUefcxWYlMS/1cDxikIKwA==)
password: ENC(neToS+hzeFjgSFB/7UEl5qYnW2rUjrPq)
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 28000
minEvictableIdleTimeMillis: 28000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000"
# REDIS
redis:
host: r-2zeaglwf13qqmnllj5.redis.rds.aliyuncs.com
port: 6379
password: mallone:iF0rm@2l2ol9
timeout: 3600
expire: 1800 #30分钟
database: 1
defaultExpiration: 2592000 # 默认生命周期30天
jedis:
pool:
max-active: 8
max-idle: 8
max-wait: -1
min-idle: 0
# SMS
aliyun:
sms:
accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V
accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry
product: Dysmsapi
domain: dysmsapi.aliyuncs.com
regionId: cn-hangzhou
dateFormat: yyyyMMdd
endpointName: cn-hangzhou
oss:
endpoint: oss-cn-beijing.aliyuncs.com
keyid: LTAI4G7ixY4AhvM35F8o3W3V
keysecret: VfWqGb83qIQrS9us45utskl8itd7ry
bucketname: formall
filehost: malinkadmin
filedomain: http://formall.oss-accelerate.aliyuncs.com
# EMAIL
mail:
host: smtp.exmail.qq.com
username: sysadministor@iformall.com
password: SWqPekCEmhUYuYCd # 授权密码
properties:
mail:
smtp:
auth: true
starttls:
enable: true
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory

aws:
clientRegion: cn-northwest-1
bucketName: iformall-net
access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=)
secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=)

wechat:
open:
componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=)
componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb)
componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC)
componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=)
redis:
host: r-2zeaglwf13qqmnllj5.redis.rds.aliyuncs.com
port: 6379
password: mallone:iF0rm@2l2ol9
timeout: 3600
expire: 1800 #30分钟
database: 2
defaultExpiration: 2592000 # 默认生命周期30天
jedis:
pool:
max-active: 100
max-idle: 100
max-wait: -1
min-idle: 10

fm:
exception: true
exception_emails: houtaikaifa@iformall.com
audit_emails: xiaochengxufabu@iformall.com
deploy: 3
upload_dir: /root/uploads/

logging:
level:
tk.mybatis: debug
com.iformall: debug
path: ./logs/o

+ 109
- 0
mlToutiaoOpen/src/main/resources/application-test.yml Wyświetl plik

@@ -0,0 +1,109 @@
spring:
profiles:
include: rabbitMQ
# JDBC
datasource:
url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true
username: ENC(Uc0AjgkytxHHCwZrmDASWg==)
password: ENC(nV4Mi3bEbBx0Fj7uUyYH55eTaqsFMjKvmNzagicH4pc=)
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 28000
minEvictableIdleTimeMillis: 28000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000"
# REDIS
redis:
host: 127.0.0.1
port: 6379
password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=)
timeout: 3600
expire: 1800 #30分钟
database: 1
defaultExpiration: 2592000 # 默认生命周期30天
jedis:
pool:
max-active: 100
max-idle: 20
max-wait: -1
min-idle: 0
# EMAIL
mail:
host: smtp.exmail.qq.com
username: ENC(TtJQE2C4cWo8CpVGMMl5hiy5eykepd96J5XjsW3Kj5fgP+6+5ctDNQ==)
password: ENC(Zh6A6kRtA2ABtH6nzdvsqQSO1/8p3mparJr8neI2BLU=) # 授权密码
properties:
mail:
smtp:
auth: true
starttls:
enable: true
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
# RABBITMQ
rabbitmq:
host: 127.0.0.1
port: 5672
username: ENC(aSRr6mnSryEqzHHz1hJf1g==)
password: ENC(GnjF/mdqKdvmDYC0tIIso7+20/jBALPw39tiWCYJ4iw=)
publisher-confirms: true
virtual-host: /
flyway:
enabled: true

aws:
clientRegion: cn-northwest-1
bucketName: iformall-net
access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=)
secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=)

wechat:
open:
componentAppId: ENC(hnH31XdNzArfMfikKgBFpqQuJUl6rVOPFFcAVyb595o=)
componentSecret: ENC(t/GUVX5L+U7LCwSvZ5WmxAnmTMrc/Uy1nljsrokuzzsBL2j6BEVnrS/n7DCdGc/G)
componentToken: ENC(gUF1m0YgCCI2IY54fX6sGLZVlCswA8tG)
componentAesKey: ENC(TYHcrIkICtfrCfGq4HW6s1b/pHf7OD2uyPN11SzJNB0acqJ/4JVX1nuljo/cAtgMG4O05TImLQc=)
redis:
host: 127.0.0.1
port: 6379
password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=)
timeout: 3600
expire: 1800 #30分钟
database: 2
defaultExpiration: 2592000 # 默认生命周期30天
jedis:
pool:
max-active: 100
max-idle: 100
max-wait: -1
min-idle: 10

fm:
exception: true
exception_emails: houtaikaifa@iformall.com
audit_emails: xiaochengxufabu@iformall.com
deploy: 2
upload_dir: /home/ec2-user/server/uploads/

ueditor:
config: config.json
unified: true
upload-path: ./upload/
url-prefix: ""

logging:
level:
tk.mybatis: debug
com.iformall: debug
path: ./logs/admin

+ 52
- 0
mlToutiaoOpen/src/main/resources/application.yml Wyświetl plik

@@ -0,0 +1,52 @@
server:
port: 6070
servlet:
context-path: /

spring:
application:
name: mallink
profiles:
active: dev
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
servlet:
multipart:
max-file-size: 2MB
max-request-size: 2MB
cache:
type: REDIS
cache-names: redis_cache #缓存的名字(可以不指定)
redis:
time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒)

#PageHelper
pagehelper:
helperDialect: mysql
reasonable: false
supportMethodsArguments: true
params: count=countSql
offset-as-page-num: true
page-size-zero: true
row-bounds-with-count: true

mapper:
mappers:
- com.iformall.common.CommonMapper

mybatis-plus:
mapper-locations: classpath:mapper/*Mapper.xml
global-config:
db-config:
id-type: id_worker
field-strategy: not_null
db-type: mysql
configuration:
jdbc-type-for-null: 'null'
cache-enabled: false
call-setters-on-nulls: true
type-aliases-package: com.iformall.domain.po

version: @project.version@

+ 100
- 0
mlToutiaoOpen/src/main/resources/logback-spring.xml Wyświetl plik

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<!-- 外部指定路径 -->
<springProperty scop="context" name="logPath" source="logging.path" />

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}][%thread][%-5level] --%mdc{client}%msg%n</Pattern>
</encoder>
</appender>

<appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/trace.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/trace.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}][%thread][%-5level][%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
</appender>

<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/info.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}][%thread][%-5level][%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/debug.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}][%thread][%-5level][%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>


<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/warn.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}][%thread][%-5level][%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>



<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/error.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}][%thread][%-5level][%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<root level="TRACE">
<appender-ref ref="TRACE_FILE" />
<appender-ref ref="INFO_FILE" />
<!-- <appender-ref ref="DEBUG_FILE" /> -->
<!-- <appender-ref ref="WARN_FILE" /> -->
<appender-ref ref="ERROR_FILE" />
</root>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

+ 76
- 0
mlWechatOpen/src/main/java/com/iformall/controller/WechatWeappSetController.java Wyświetl plik

@@ -6,14 +6,19 @@ import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxAuthorizerInfo;
import com.iformall.domain.po.WxWeappBasicSet;
import com.iformall.enums.EnumEnableType;
import com.iformall.enums.EnumWxAuthorizationStatus;
import com.iformall.service.WxAuthorizerInfoService;
import com.iformall.service.WxWeappBasicSetService;
import com.iformall.service.wechat.FmOpenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.open.api.WxOpenMaService;
import me.chanjar.weixin.open.bean.ma.privacy.GetPrivacySettingResult;
import me.chanjar.weixin.open.bean.ma.privacy.PrivacyOwnerSetting;
import me.chanjar.weixin.open.bean.ma.privacy.SetPrivacySetting;
import me.chanjar.weixin.open.bean.result.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -21,6 +26,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -33,12 +39,19 @@ import java.util.Map;
@Api(description = "微信第三方开发平台-小程序设置")
public class WechatWeappSetController {
private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private Integer getFmDeploy;

@Autowired
private FmOpenService openService;

@Autowired
private WxAuthorizerInfoService authorizerInfoService;

@Autowired
private WxWeappBasicSetService weappBasicSetService;

@ApiOperation("获取小程序的信息")
@GetMapping("/getInfo")
public ResultData getAccountBasicInfo(String appId) {
@@ -228,4 +241,67 @@ public class WechatWeappSetController {
}
return new ResultData(Result.ERROR);
}


@ApiOperation(value = "配置小程序用户隐私保护指引", notes = "{\n" +
" }")
@PostMapping("/setprivacysetting")
public ResultData setprivacysetting(String appId) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if(authorizerInfo == null) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(!authorizerInfo.getAuthorizationStatus().equals(EnumWxAuthorizationStatus.AUTHORIZED.getCode())) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
WxWeappBasicSet weappBasicSetQ = new WxWeappBasicSet();
weappBasicSetQ.setType(authorizerInfo.getType());
weappBasicSetQ.setDeploy(getFmDeploy);
WxWeappBasicSet weappBasicSet = weappBasicSetService.getByTypeAndDeploy(weappBasicSetQ);
if(weappBasicSet == null || StringUtils.isBlank(weappBasicSet.getPrivacySetting())) {
logger.error("未找到相关的基础设置参数");
return new ResultData(ErrorCode.WEAPP_BASIC_SET_ERR);
}
try {
SetPrivacySetting setting = JSON.parseObject(weappBasicSet.getPrivacySetting(),SetPrivacySetting.class);
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
String setRet = openMaService.getPrivacyService().setPrivacySetting(setting);
logger.info(setRet);
JSONObject webRetObj = JSON.parseObject(setRet);
if(webRetObj.getInteger("errcode").equals(0)) {
logger.info("配置小程序用户隐私保护指引成功");
authorizerInfo.setPrivacySettingStatus(EnumEnableType.SUCC.getCode());
} else {
logger.info("配置小程序用户隐私保护指引失败");
authorizerInfo.setPrivacySettingStatus(EnumEnableType.FAIL.getCode());
}
authorizerInfoService.updatePrivacySetting(authorizerInfo);
return new ResultData(setRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
return new ResultData(Result.ERROR);
}

@ApiOperation(value = "查询小程序用户隐私保护指引", notes = "{\n" +
" }")
@GetMapping("/getPrivacySetting")
public ResultData setprivacysetting(String appId,Integer privacyVer) {
WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
if(authorizerInfo == null) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
if(!authorizerInfo.getAuthorizationStatus().equals(EnumWxAuthorizationStatus.AUTHORIZED.getCode())) {
return new ResultData(ErrorCode.WEAPP_APPID_NOT_AUTH);
}
try {
WxOpenMaService openMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
GetPrivacySettingResult getRet = openMaService.getPrivacyService().getPrivacySetting(privacyVer);
return new ResultData(getRet);
} catch (WxErrorException e) {
logger.error(e.getMessage());
}
return new ResultData(Result.ERROR);
}

}

+ 1
- 0
pom.xml Wyświetl plik

@@ -12,6 +12,7 @@

<modules>
<module>mallinkService</module>
<module>mlToutiaoOpen</module>
<module>mlWechatOpen</module>
</modules>



Ładowanie…
Anuluj
Zapisz