Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master'

wkyy 4 anni fa
parent
commit
d59885222b
39 ha cambiato i file con 1530 aggiunte e 15 eliminazioni
  1. 1 0
      common/src/main/java/com/jpsoft/employment/modules/base/dao/UserAuthenticationApproveDAO.java
  2. 1 0
      common/src/main/java/com/jpsoft/employment/modules/base/service/UserAuthenticationApproveService.java
  3. 5 0
      common/src/main/java/com/jpsoft/employment/modules/base/service/impl/UserAuthenticationApproveServiceImpl.java
  4. 12 0
      common/src/main/java/com/jpsoft/employment/modules/common/dto/MessageResultBuilder.java
  5. 106 0
      common/src/main/java/com/jpsoft/employment/modules/common/utils/MapUtils.java
  6. 1 0
      common/src/main/java/com/jpsoft/employment/modules/job/dao/ResumeDAO.java
  7. 1 0
      common/src/main/java/com/jpsoft/employment/modules/job/dao/ResumeEducationExperienceDAO.java
  8. 3 0
      common/src/main/java/com/jpsoft/employment/modules/job/dao/ResumeWorkExperienceDAO.java
  9. 3 0
      common/src/main/java/com/jpsoft/employment/modules/job/dao/UserBrowseDAO.java
  10. 2 0
      common/src/main/java/com/jpsoft/employment/modules/job/dao/UserCollectionDAO.java
  11. 1 1
      common/src/main/java/com/jpsoft/employment/modules/job/entity/JobUser.java
  12. 3 0
      common/src/main/java/com/jpsoft/employment/modules/job/entity/ResumeDeliver.java
  13. 1 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/ResumeEducationExperienceService.java
  14. 1 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/ResumeService.java
  15. 1 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/ResumeWorkExperienceService.java
  16. 3 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/UserBrowseService.java
  17. 2 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/UserCollectionService.java
  18. 5 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/impl/ResumeEducationExperienceServiceImpl.java
  19. 5 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/impl/ResumeServiceImpl.java
  20. 5 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/impl/ResumeWorkExperienceServiceImpl.java
  21. 11 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/impl/UserBrowseServiceImpl.java
  22. 9 0
      common/src/main/java/com/jpsoft/employment/modules/job/service/impl/UserCollectionServiceImpl.java
  23. 8 3
      common/src/main/resources/mapper/base/UserAuthenticationApprove.xml
  24. 2 2
      common/src/main/resources/mapper/job/JobUser.xml
  25. 7 0
      common/src/main/resources/mapper/job/Resume.xml
  26. 9 2
      common/src/main/resources/mapper/job/ResumeEducationExperience.xml
  27. 11 2
      common/src/main/resources/mapper/job/ResumeWorkExperience.xml
  28. 44 1
      common/src/main/resources/mapper/job/UserBrowse.xml
  29. 15 2
      common/src/main/resources/mapper/job/UserCollection.xml
  30. 1 0
      web/src/main/java/com/jpsoft/employment/config/WebMvcConfig.java
  31. 111 2
      web/src/main/java/com/jpsoft/employment/modules/mobile/controller/JobUserApiController.java
  32. 302 0
      web/src/main/java/com/jpsoft/employment/modules/mobile/controller/ResumeApiController.java
  33. 57 0
      web/src/main/java/com/jpsoft/employment/modules/mobile/controller/UserBrowseApiController.java
  34. 67 0
      web/src/main/java/com/jpsoft/employment/modules/pay/properties/AliPayProperties.java
  35. 68 0
      web/src/main/java/com/jpsoft/employment/modules/pay/properties/ParkAliPayProperties.java
  36. 71 0
      web/src/main/java/com/jpsoft/employment/modules/pay/properties/WxJpsoftProperties.java
  37. 71 0
      web/src/main/java/com/jpsoft/employment/modules/pay/properties/WxPayProperties.java
  38. 85 0
      web/src/main/java/com/jpsoft/employment/modules/wechat/callback/EventCallback.java
  39. 419 0
      web/src/main/java/com/jpsoft/employment/modules/wechat/controller/WxController.java

+ 1 - 0
common/src/main/java/com/jpsoft/employment/modules/base/dao/UserAuthenticationApproveDAO.java

@@ -16,4 +16,5 @@ public interface UserAuthenticationApproveDAO {
 	int delete(String id);
 	List<UserAuthenticationApprove> list();
 	List<UserAuthenticationApprove> search(Map<String, Object> searchParams, List<Sort> sortList);
+	UserAuthenticationApprove findByUserId(String userId);
 }

+ 1 - 0
common/src/main/java/com/jpsoft/employment/modules/base/service/UserAuthenticationApproveService.java

@@ -14,4 +14,5 @@ public interface UserAuthenticationApproveService {
 	int delete(String id);
 	List<UserAuthenticationApprove> list();
 	Page<UserAuthenticationApprove> pageSearch(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList);
+	UserAuthenticationApprove findByUserId(String userId);
 }

+ 5 - 0
common/src/main/java/com/jpsoft/employment/modules/base/service/impl/UserAuthenticationApproveServiceImpl.java

@@ -67,4 +67,9 @@ public class UserAuthenticationApproveServiceImpl implements UserAuthenticationA
         
         return page;
 	}
+
+	@Override
+	public UserAuthenticationApprove findByUserId(String userId){
+		return userAuthenticationApproveDAO.findByUserId(userId);
+	}
 }

+ 12 - 0
common/src/main/java/com/jpsoft/employment/modules/common/dto/MessageResultBuilder.java

@@ -0,0 +1,12 @@
+package com.jpsoft.employment.modules.common.dto;
+
+public class MessageResultBuilder {
+
+    public static <T>  MessageResult<T> ok(T data){
+            return new MessageResult<T>(true,null,data,200);
+    }
+
+    public static <T>  MessageResult<T> error(String msg){
+        return new MessageResult<T>(false,msg,null,500);
+    }
+}

+ 106 - 0
common/src/main/java/com/jpsoft/employment/modules/common/utils/MapUtils.java

@@ -0,0 +1,106 @@
+package com.jpsoft.employment.modules.common.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+
+
+
+public class MapUtils {
+
+	/**
+	 * 为空串的value设置为null
+	 * @param args
+	 */
+	public static void blankValToNull(Map<String,Object> args){
+		for(String key : args.keySet()){
+			if(args.get(key) instanceof String && StringUtils.isEmpty((String)args.get(key))){
+				args.put(key,null);
+			}
+		}
+	}
+	
+	/**
+	 * 为空串的value设置为null,指定的keys有效
+	 * @param args
+	 */
+    public static void blankValToNull(Map<String,Object> args,String... keys){
+		for(String key : keys){
+			if(args.get(key) instanceof String && StringUtils.isEmpty((String)args.get(key))){
+				args.put(key,null);
+			}
+		}
+	}
+    
+    
+    /**
+     * 字符串时间value转换为Date对象值,指定的keys有效
+     * @param args
+     * @param fields
+     */
+    /*public static void strValToDate(Map<String,Object> args,String... keys){
+		for(String key : keys){
+			if(StringUtils.isNotEmpty((String)args.get(key))){
+				args.put(key,DateUtil.parse((String)args.get(key)));
+			}
+		}
+	}*/
+    
+    /**
+     * 提取部分键值对作为新的Map返回,原Map去掉被提取的键值对
+     * @param <V>
+     * @param srcMap
+     * @param keys
+     * @return
+     */
+    public static <V>  Map<String,V>  trackMap(Map<String,V> srcMap,String... keys){
+		Map<String,V> rtnMap=new HashMap<String,V>(keys.length);
+		for(String key : keys){
+			rtnMap.put(key, srcMap.get(key));
+		}
+		for(String key : keys){
+			srcMap.remove(key);
+		}
+		return rtnMap;
+	}
+	
+    /**
+     * 提取部分键值对作为新的Map返回
+     * @param <V>
+     * @param srcMap
+     * @param keys
+     * @return
+     */
+	public static <V> Map<String,V> clone(Map<String,V> srcMap,String... keys){
+		Map<String,V> rtnMap=new HashMap<String,V>(keys.length);
+		for(String key : keys){
+			rtnMap.put(key, srcMap.get(key));
+		}
+		return rtnMap;
+	}
+	
+	public static Map<String,Object> builder(String... keyVal){
+		if(keyVal==null){
+			return null;
+		}
+		Map<String,Object>  rtnMap=new HashMap<String,Object>();
+		for(int i=0,len=keyVal.length;i<len;i++){
+			rtnMap.put(keyVal[i], (i+1)<len?keyVal[i+1]:null);
+			i+=1;
+		}
+		return rtnMap;
+	}
+	
+	public static Map<String,Object> builder(Object... keyVal){
+		if(keyVal==null){
+			return null;
+		}
+		Map<String,Object>  rtnMap=new HashMap<String,Object>();
+		for(int i=0,len=keyVal.length;i<len;i++){
+			rtnMap.put(keyVal[i].toString(), (i+1)<len?keyVal[i+1]:null);
+			i+=1;
+		}
+		return rtnMap;
+	}
+}

+ 1 - 0
common/src/main/java/com/jpsoft/employment/modules/job/dao/ResumeDAO.java

@@ -15,4 +15,5 @@ public interface ResumeDAO {
 	int delete(String id);
 	List<Resume> list();
 	List<Resume> search(Map<String,Object> searchParams,List<Sort> sortList);
+	Resume findByUserId(String userId);
 }

+ 1 - 0
common/src/main/java/com/jpsoft/employment/modules/job/dao/ResumeEducationExperienceDAO.java

@@ -15,4 +15,5 @@ public interface ResumeEducationExperienceDAO {
 	int delete(String id);
 	List<ResumeEducationExperience> list();
 	List<ResumeEducationExperience> search(Map<String,Object> searchParams,List<Sort> sortList);
+	List<ResumeEducationExperience> findByResumeId(String resumeId);
 }

+ 3 - 0
common/src/main/java/com/jpsoft/employment/modules/job/dao/ResumeWorkExperienceDAO.java

@@ -1,6 +1,8 @@
 package com.jpsoft.employment.modules.job.dao;
 
 import java.util.List;
+
+import com.jpsoft.employment.modules.job.entity.ResumeEducationExperience;
 import org.springframework.stereotype.Repository;
 import com.jpsoft.employment.modules.job.entity.ResumeWorkExperience;
 import java.util.Map;
@@ -15,4 +17,5 @@ public interface ResumeWorkExperienceDAO {
 	int delete(String id);
 	List<ResumeWorkExperience> list();
 	List<ResumeWorkExperience> search(Map<String,Object> searchParams,List<Sort> sortList);
+	List<ResumeWorkExperience> findByResumeId(String resumeId);
 }

+ 3 - 0
common/src/main/java/com/jpsoft/employment/modules/job/dao/UserBrowseDAO.java

@@ -1,6 +1,8 @@
 package com.jpsoft.employment.modules.job.dao;
 
 import java.util.List;
+
+import com.jpsoft.employment.modules.job.entity.Recruitment;
 import org.springframework.stereotype.Repository;
 import com.jpsoft.employment.modules.job.entity.UserBrowse;
 import java.util.Map;
@@ -15,4 +17,5 @@ public interface UserBrowseDAO {
 	int delete(String id);
 	List<UserBrowse> list();
 	List<UserBrowse> search(Map<String,Object> searchParams,List<Sort> sortList);
+	List<Recruitment> loadUserBrowses(Map<String,Object> searchParams, List<Sort> sortList);
 }

+ 2 - 0
common/src/main/java/com/jpsoft/employment/modules/job/dao/UserCollectionDAO.java

@@ -15,4 +15,6 @@ public interface UserCollectionDAO {
 	int delete(String id);
 	List<UserCollection> list();
 	List<UserCollection> search(Map<String,Object> searchParams,List<Sort> sortList);
+	UserCollection findByUserIdAndRId(String userId,String recruitmentId);
+	List<UserCollection> findByUserId(String userId);
 }

+ 1 - 1
common/src/main/java/com/jpsoft/employment/modules/job/entity/JobUser.java

@@ -71,7 +71,7 @@ public class JobUser {
 	private String headImageUrl;
 
 	@ApiModelProperty(value = "是否认证")
-	private Boolean isAuthentication;
+	private String isAuthentication;
 
 	@ApiModelProperty(value = "身份证号")
 	private String idCard;

+ 3 - 0
common/src/main/java/com/jpsoft/employment/modules/job/entity/ResumeDeliver.java

@@ -48,6 +48,9 @@ public class ResumeDeliver {
 	@ApiModelProperty(value = "招聘ID")
 	private String jobRecruitmentId;
 
+	@ApiModelProperty(value = "投递的招聘信息")
+	private Recruitment jobRecruitment;
+
 	@ApiModelProperty(value = "简历状态(已投递,已查看,邀请面试等)")
 	private String status;
 

+ 1 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/ResumeEducationExperienceService.java

@@ -14,4 +14,5 @@ public interface ResumeEducationExperienceService {
 	int delete(String id);
 	List<ResumeEducationExperience> list();
 	Page<ResumeEducationExperience> pageSearch(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList);
+	List<ResumeEducationExperience> findByResumeId(String resumeId);
 }

+ 1 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/ResumeService.java

@@ -14,4 +14,5 @@ public interface ResumeService {
 	int delete(String id);
 	List<Resume> list();
 	Page<Resume> pageSearch(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList);
+	Resume findByUserId(String userId);
 }

+ 1 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/ResumeWorkExperienceService.java

@@ -14,4 +14,5 @@ public interface ResumeWorkExperienceService {
 	int delete(String id);
 	List<ResumeWorkExperience> list();
 	Page<ResumeWorkExperience> pageSearch(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList);
+	List<ResumeWorkExperience> findByResumeId(String resumeId);
 }

+ 3 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/UserBrowseService.java

@@ -2,6 +2,8 @@ package com.jpsoft.employment.modules.job.service;
 
 import java.util.List;
 import java.util.Map;
+
+import com.jpsoft.employment.modules.job.entity.Recruitment;
 import com.jpsoft.employment.modules.job.entity.UserBrowse;
 import com.github.pagehelper.Page;
 import com.jpsoft.employment.modules.common.dto.Sort;
@@ -14,4 +16,5 @@ public interface UserBrowseService {
 	int delete(String id);
 	List<UserBrowse> list();
 	Page<UserBrowse> pageSearch(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList);
+	Page<Recruitment> loadUserBrowses(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList);
 }

+ 2 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/UserCollectionService.java

@@ -14,4 +14,6 @@ public interface UserCollectionService {
 	int delete(String id);
 	List<UserCollection> list();
 	Page<UserCollection> pageSearch(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList);
+	UserCollection findByUserIdAndRId(String userId,String recruitmentId);
+	List<UserCollection> findByUserId(String userId);
 }

+ 5 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/impl/ResumeEducationExperienceServiceImpl.java

@@ -67,4 +67,9 @@ public class ResumeEducationExperienceServiceImpl implements ResumeEducationExpe
         
         return page;
 	}
+
+	@Override
+	public List<ResumeEducationExperience> findByResumeId(String resumeId){
+		return resumeEducationExperienceDAO.findByResumeId(resumeId);
+	}
 }

+ 5 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/impl/ResumeServiceImpl.java

@@ -58,6 +58,11 @@ public class ResumeServiceImpl implements ResumeService {
 		// TODO Auto-generated method stub
 		return resumeDAO.list();
 	}
+
+	@Override
+	public Resume findByUserId(String userId){
+		return resumeDAO.findByUserId(userId);
+	}
 		
 	@Override
 	public Page<Resume> pageSearch(Map<String, Object> searchParams, int pageNumber, int pageSize,boolean count,List<Sort> sortList) {

+ 5 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/impl/ResumeWorkExperienceServiceImpl.java

@@ -67,4 +67,9 @@ public class ResumeWorkExperienceServiceImpl implements ResumeWorkExperienceServ
         
         return page;
 	}
+
+	@Override
+	public List<ResumeWorkExperience> findByResumeId(String resumeId){
+		return resumeWorkExperienceDAO.findByResumeId(resumeId);
+	}
 }

+ 11 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/impl/UserBrowseServiceImpl.java

@@ -4,6 +4,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import javax.annotation.Resource;
+
+import com.jpsoft.employment.modules.job.entity.Recruitment;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import com.jpsoft.employment.modules.job.dao.UserBrowseDAO;
@@ -67,4 +69,13 @@ public class UserBrowseServiceImpl implements UserBrowseService {
         
         return page;
 	}
+
+	@Override
+	public Page<Recruitment> loadUserBrowses(Map<String, Object> searchParams, int pageNum, int pageSize, boolean count, List<Sort> sortList) {
+		Page<Recruitment> page = PageHelper.startPage(pageNum, pageSize, count).doSelectPage(() -> {
+			userBrowseDAO.loadUserBrowses(searchParams, sortList);
+		});
+
+		return page;
+	}
 }

+ 9 - 0
common/src/main/java/com/jpsoft/employment/modules/job/service/impl/UserCollectionServiceImpl.java

@@ -67,4 +67,13 @@ public class UserCollectionServiceImpl implements UserCollectionService {
         
         return page;
 	}
+
+	@Override
+	public UserCollection findByUserIdAndRId(String userId,String recruitmentId){
+		return userCollectionDAO.findByUserIdAndRId(userId,recruitmentId);
+	}
+	@Override
+	public List<UserCollection> findByUserId(String userId){
+		return userCollectionDAO.findByUserId(userId);
+	}
 }

+ 8 - 3
common/src/main/resources/mapper/base/UserAuthenticationApprove.xml

@@ -2,7 +2,7 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <!-- namespace必须指向DAO接口 -->
-<mapper namespace="com.jpsoft.employment.dao.UserAuthenticationApproveDAO">
+<mapper namespace="com.jpsoft.employment.modules.base.dao.UserAuthenticationApproveDAO">
 	<resultMap id="UserAuthenticationApproveMap" type="com.jpsoft.employment.modules.base.entity.UserAuthenticationApprove">
 		<id property="id" column="id_" />
 			<result property="createBy" column="create_by" />
@@ -76,8 +76,7 @@
 	where id_=#{id}
 	</update>
 	<select id="get" parameterType="string" resultMap="UserAuthenticationApproveMap">
-		select 
-id_,create_by,create_time,update_by,update_time,del_flag,job_user_id,approve_person_id,approve_time,approval_status		from base_user_authentication_approve where id_=#{0}
+		select * from base_user_authentication_approve where id_=#{0}
 	</select>
 	<select id="exist" parameterType="string" resultType="int">
 		select count(*) from base_user_authentication_approve where id_=#{0}
@@ -98,4 +97,10 @@ id_,create_by,create_time,update_by,update_time,del_flag,job_user_id,approve_per
 	        ${sort.name} ${sort.order}
 	 	</foreach>
 	</select>
+	<select id="findByUserId" parameterType="string" resultMap="UserAuthenticationApproveMap">
+		select * from base_user_authentication_approve
+		where del_flag = 0
+		and job_user_id = #{0}
+		limit 1
+	</select>
 </mapper>

+ 2 - 2
common/src/main/resources/mapper/job/JobUser.xml

@@ -52,7 +52,7 @@
 ,#{address,jdbcType=VARCHAR}
 ,#{firstJobTime,jdbcType= TIMESTAMP }
 ,#{headImageUrl,jdbcType=VARCHAR}
-,#{isAuthentication,jdbcType= NUMERIC }
+,#{isAuthentication,jdbcType= VARCHAR }
 ,#{idCard,jdbcType=VARCHAR}
 ,#{idCardUrl,jdbcType= NUMERIC }
 ,#{jobStatus,jdbcType=VARCHAR}
@@ -111,7 +111,7 @@
 		head_image_url=#{headImageUrl,jdbcType=VARCHAR},
 		</if>
 				<if test="isAuthentication!=null">
-		is_authentication=#{isAuthentication,jdbcType= NUMERIC },
+		is_authentication=#{isAuthentication,jdbcType= VARCHAR },
 		</if>
 				<if test="idCard!=null">
 		id_card=#{idCard,jdbcType=VARCHAR},

+ 7 - 0
common/src/main/resources/mapper/job/Resume.xml

@@ -133,4 +133,11 @@
 	        ${sort.name} ${sort.order}
 	 	</foreach>
 	</select>
+	<select id="findByUserId" parameterType="string" resultMap="ResumeMap">
+		select * from job_resume
+		where
+		job_user_id=#{0}
+		and del_flag = 0
+		limit 1
+	</select>
 </mapper>

+ 9 - 2
common/src/main/resources/mapper/job/ResumeEducationExperience.xml

@@ -91,8 +91,7 @@
 	where id_=#{id}
 	</update>
 	<select id="get" parameterType="string" resultMap="ResumeEducationExperienceMap">
-		select 
-id_,create_by,create_time,update_by,update_time,del_flag,resume_id,sort_no,start_time,end_time,school_name,education_,major_		from job_resume_education_experience where id_=#{0}
+		select * from job_resume_education_experience where id_=#{0}
 	</select>
 	<select id="exist" parameterType="string" resultType="int">
 		select count(*) from job_resume_education_experience where id_=#{0}
@@ -113,4 +112,12 @@ id_,create_by,create_time,update_by,update_time,del_flag,resume_id,sort_no,start
 	        ${sort.name} ${sort.order}
 	 	</foreach>
 	</select>
+	<select id="findByResumeId" parameterType="string" resultMap="ResumeEducationExperienceMap">
+		select
+		*
+		from
+		job_resume_education_experience
+		where del_flag = 0
+		and resume_id = #{resumeId}
+	</select>
 </mapper>

+ 11 - 2
common/src/main/resources/mapper/job/ResumeWorkExperience.xml

@@ -91,8 +91,7 @@
 	where id_=#{id}
 	</update>
 	<select id="get" parameterType="string" resultMap="ResumeWorkExperienceMap">
-		select 
-id_,create_by,create_time,update_by,update_time,del_flag,resume_id,sort_no,start_time,end_time,company_name,job_,content_		from job_resume_work_experience where id_=#{0}
+		select * from job_resume_work_experience where id_=#{0}
 	</select>
 	<select id="exist" parameterType="string" resultType="int">
 		select count(*) from job_resume_work_experience where id_=#{0}
@@ -113,4 +112,14 @@ id_,create_by,create_time,update_by,update_time,del_flag,resume_id,sort_no,start
 	        ${sort.name} ${sort.order}
 	 	</foreach>
 	</select>
+
+	<select id="findByResumeId" parameterType="string" resultMap="ResumeWorkExperienceMap">
+		select
+		*
+		from
+		job_resume_work_experience
+		where del_flag = 0
+		and resume_id = #{resumeId}
+		limit 1
+	</select>
 </mapper>

+ 44 - 1
common/src/main/resources/mapper/job/UserBrowse.xml

@@ -12,7 +12,38 @@
 			<result property="delFlag" column="del_flag" />
 			<result property="jobUserId" column="job_user_id" />
 			<result property="jobRecruitmentId" column="job_recruitment_id" />
-			</resultMap>
+	</resultMap>
+
+	<resultMap id="RecruitmentMap" type="com.jpsoft.employment.modules.job.entity.Recruitment">
+		<id property="id" column="id_" />
+		<result property="companyId" column="company_id" />
+		<result property="title" column="title_" />
+		<result property="area" column="area_" />
+		<result property="address" column="address_" />
+		<result property="position" column="position_" />
+		<result property="positionMessage" column="position_message" />
+		<result property="requirements" column="requirements_" />
+		<result property="positionNumber" column="position_number" />
+		<result property="workYear" column="work_year" />
+		<result property="education" column="education_" />
+		<result property="positionSex" column="position_sex" />
+		<result property="readTimes" column="read_times" />
+		<result property="wageType" column="wage_type" />
+		<result property="isDiscussPersonally" column="is_discuss_personally" />
+		<result property="contactPerson" column="contact_person" />
+		<result property="tel" column="tel_" />
+		<result property="status" column="status_" />
+		<result property="approveStatus" column="approve_status" />
+		<result property="readingTimes" column="reading_times" />
+		<result property="collectionTimes" column="collection_times" />
+		<result property="deliveryTimes" column="delivery_times" />
+		<result property="createBy" column="create_by" />
+		<result property="createTime" column="create_time" />
+		<result property="updateBy" column="update_by" />
+		<result property="updateTime" column="update_time" />
+		<result property="delFlag" column="del_flag" />
+	</resultMap>
+
 	<insert id="insert" parameterType="com.jpsoft.employment.modules.job.entity.UserBrowse">
 	<!--
 	<selectKey resultType="java.lang.String" order="BEFORE" keyProperty="id">
@@ -88,4 +119,16 @@ id_,create_by,create_time,update_by,update_time,del_flag,job_user_id,job_recruit
 	        ${sort.name} ${sort.order}
 	 	</foreach>
 	</select>
+
+	<select id="loadUserBrowses" parameterType="hashmap" resultMap="RecruitmentMap">
+		<![CDATA[
+			select j.* from job_user_browse b inner join job_recruitment j on b.job_recruitment_id=j.id_ and j.del_flag=0
+		]]>
+		<where>
+			and job_user_id = #{searchParams.jobUserId}
+		</where>
+		<foreach item="sort" collection="sortList"  open="order by" separator=",">
+			${sort.name} ${sort.order}
+		</foreach>
+	</select>
 </mapper>

+ 15 - 2
common/src/main/resources/mapper/job/UserCollection.xml

@@ -66,8 +66,7 @@
 	where id_=#{id}
 	</update>
 	<select id="get" parameterType="string" resultMap="UserCollectionMap">
-		select 
-id_,create_by,create_time,update_by,update_time,del_flag,job_user_id,job_recruitment_id		from job_user_collection where id_=#{0}
+		select * from job_user_collection where id_=#{0}
 	</select>
 	<select id="exist" parameterType="string" resultType="int">
 		select count(*) from job_user_collection where id_=#{0}
@@ -88,4 +87,18 @@ id_,create_by,create_time,update_by,update_time,del_flag,job_user_id,job_recruit
 	        ${sort.name} ${sort.order}
 	 	</foreach>
 	</select>
+
+	<select id="findByUserIdAndRId" parameterType="string" resultMap="UserCollectionMap">
+		select * from job_user_collection
+		where del_flag = 0
+		and job_user_id = #{userId}
+		and job_recruitment_id = #{recruitmentId}
+		limit 1
+	</select>
+
+	<select id="findByUserId" parameterType="string" resultMap="UserCollectionMap">
+		select * from job_user_collection
+		where del_flag = 0
+		and job_user_id = #{userId}
+	</select>
 </mapper>

+ 1 - 0
web/src/main/java/com/jpsoft/employment/config/WebMvcConfig.java

@@ -53,6 +53,7 @@ public class WebMvcConfig implements WebMvcConfigurer {
 						"/doc.html",
                         "/v2/**",
                         "/mobileApi/**")
+                .excludePathPatterns("/wechat/**")
 				.excludePathPatterns("/mobile/jobUserApi/findByOpenId")
 				.excludePathPatterns("/mobile/jobUserApi/wechatLogin")
 				.excludePathPatterns("/mobile/jobUserApi/validateCode")

+ 111 - 2
web/src/main/java/com/jpsoft/employment/modules/mobile/controller/JobUserApiController.java

@@ -3,13 +3,21 @@ package com.jpsoft.employment.modules.mobile.controller;
 import com.alibaba.fastjson.JSONObject;
 import com.alipay.api.domain.CompanyInfo;
 import com.jpsoft.employment.config.OSSConfig;
+import com.jpsoft.employment.modules.base.entity.UserAuthenticationApprove;
+import com.jpsoft.employment.modules.base.service.UserAuthenticationApproveService;
 import com.jpsoft.employment.modules.common.dto.MessageResult;
 import com.jpsoft.employment.modules.common.utils.DES3;
 import com.jpsoft.employment.modules.common.utils.JwtUtil;
 import com.jpsoft.employment.modules.common.utils.OSSUtil;
 import com.jpsoft.employment.modules.common.utils.SMSUtil;
 import com.jpsoft.employment.modules.job.entity.JobUser;
+import com.jpsoft.employment.modules.job.entity.Resume;
+import com.jpsoft.employment.modules.job.entity.ResumeDeliver;
+import com.jpsoft.employment.modules.job.entity.UserCollection;
 import com.jpsoft.employment.modules.job.service.JobUserService;
+import com.jpsoft.employment.modules.job.service.ResumeDeliverService;
+import com.jpsoft.employment.modules.job.service.ResumeService;
+import com.jpsoft.employment.modules.job.service.UserCollectionService;
 import com.jpsoft.employment.modules.sys.entity.SysLog;
 import com.jpsoft.employment.modules.sys.service.SysLogService;
 import io.swagger.annotations.ApiImplicitParam;
@@ -54,6 +62,18 @@ public class JobUserApiController {
     @Autowired
     private SysLogService sysLogService;
 
+    @Autowired
+    private UserAuthenticationApproveService userAuthenticationApproveService;
+
+    @Autowired
+    private UserCollectionService userCollectionService;
+
+    @Autowired
+    private ResumeDeliverService resumeDeliverService;
+
+    @Autowired
+    private ResumeService resumeService;
+
     @PostMapping("findByOpenId")
     @ApiOperation(value = "通过openId查询人员(公开接口)")
     @ApiImplicitParams({
@@ -115,7 +135,7 @@ public class JobUserApiController {
                 jobUser.setCreateTime(new Date());
                 jobUser.setDelFlag(false);
                 jobUser.setHeadImageUrl("http://xpgj.oss-cn-shanghai.aliyuncs.com/xpgj/test/default_avatar.jpg");
-                jobUser.setIsAuthentication(false);
+                jobUser.setIsAuthentication("0");
                 jobUser.setOpenId(openId);
 
                 jobUserService.insert(jobUser);
@@ -217,7 +237,7 @@ public class JobUserApiController {
                     jobUser.setCreateTime(new Date());
                     jobUser.setDelFlag(false);
                     jobUser.setHeadImageUrl("http://xpgj.oss-cn-shanghai.aliyuncs.com/xpgj/test/default_avatar.jpg");
-                    jobUser.setIsAuthentication(false);
+                    jobUser.setIsAuthentication("0");
                     jobUser.setOpenId(openId);
 
                     jobUserService.insert(jobUser);
@@ -425,4 +445,93 @@ public class JobUserApiController {
         return messageResult;
     }
 
+    @PostMapping("authenticationStatus")
+    @ApiOperation(value = "用户认证状态")
+    public MessageResult<String> authenticationStatus(String token, @RequestAttribute  String subject) {
+        MessageResult<String> messageResult = new MessageResult<>();
+
+        try {
+            JobUser jobUser = jobUserService.get(subject);
+            String returnIs = "";
+            if(jobUser != null){
+                returnIs = jobUser.getIsAuthentication();
+            }
+
+            messageResult.setData(returnIs);
+            messageResult.setResult(true);
+            messageResult.setCode(200);
+        } catch (Exception ex) {
+            logger.error(ex.getMessage(), ex);
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+        }
+        return messageResult;
+    }
+
+
+    @PostMapping("submitAuthentication")
+    @ApiOperation(value = "提交认证信息")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "name", value = "姓名", required = true, paramType = "form"),
+            @ApiImplicitParam(name = "idCard", value = "身份证", required = true,paramType = "form"),
+            @ApiImplicitParam(name = "positiveUrl", value = "身份证正面地址", required = true,paramType = "form"),
+            @ApiImplicitParam(name = "reverseUrl", value = "身份证反面地址", required = true,paramType = "form"),
+    })
+    public MessageResult<String> submitAuthentication(
+            String name,
+            String idCard,
+            String positiveUrl,
+            String reverseUrl,
+            String token,
+            @RequestAttribute  String subject) {
+        MessageResult<String> messageResult = new MessageResult<>();
+
+        try {
+            JobUser jobUser = jobUserService.get(subject);
+
+            if (jobUser == null) {
+                throw new Exception("未登录!");
+            }
+
+            jobUser.setUpdateTime(new Date());
+            jobUser.setUpdateBy(subject);
+
+            jobUser.setIdCard(idCard);
+            jobUser.setHeadImageUrl(positiveUrl+","+reverseUrl);
+            jobUser.setRealName(name);
+            jobUser.setIsAuthentication("2");//待审核
+
+            jobUserService.update(jobUser);
+
+            UserAuthenticationApprove uaa = userAuthenticationApproveService.findByUserId(jobUser.getId());
+            if(uaa == null) {
+                //保存认证信息到审批表
+                uaa = new UserAuthenticationApprove();
+                uaa.setId(UUID.randomUUID().toString());
+                uaa.setCreateTime(new Date());
+                uaa.setCreateBy(subject);
+                uaa.setDelFlag(false);
+                uaa.setJobUserId(jobUser.getId());
+
+                userAuthenticationApproveService.insert(uaa);
+            }else{
+                uaa.setUpdateTime(new Date());
+                uaa.setUpdateBy(subject);
+                uaa.setJobUserId(jobUser.getId());
+                userAuthenticationApproveService.update(uaa);
+            }
+
+            messageResult.setData("提交成功,请等待审核!");
+            messageResult.setResult(true);
+            messageResult.setCode(200);
+        } catch (Exception ex) {
+            log.error(ex.getMessage());
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+        }
+
+        return messageResult;
+    }
+
+
 }

+ 302 - 0
web/src/main/java/com/jpsoft/employment/modules/mobile/controller/ResumeApiController.java

@@ -0,0 +1,302 @@
+package com.jpsoft.employment.modules.mobile.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.github.pagehelper.Page;
+import com.jpsoft.employment.config.OSSConfig;
+import com.jpsoft.employment.modules.common.dto.MessageResult;
+import com.jpsoft.employment.modules.common.dto.Sort;
+import com.jpsoft.employment.modules.common.utils.*;
+import com.jpsoft.employment.modules.job.entity.*;
+import com.jpsoft.employment.modules.job.service.*;
+import com.jpsoft.employment.modules.sys.entity.SysLog;
+import com.jpsoft.employment.modules.sys.service.DataDictionaryService;
+import com.jpsoft.employment.modules.sys.service.SysLogService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+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.data.redis.core.ValueOperations;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import sun.misc.BASE64Decoder;
+
+import java.io.ByteArrayInputStream;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@RestController
+@RequestMapping("/mobile/resumeApi")
+@Api(description = "简历接口")
+@Slf4j
+public class ResumeApiController {
+    @Value("${jwt.secret}")
+    private String jwtSecret;
+
+    @Autowired
+    private JobUserService jobUserService;
+
+    @Autowired
+    private ResumeService resumeService;
+
+    @Autowired
+    private RecruitmentService recruitmentService;
+
+    @Autowired
+    private DataDictionaryService dataDictionaryService;
+
+    @Autowired
+    private UserCollectionService userCollectionService;
+
+    @Autowired
+    private ResumeDeliverService resumeDeliverService;
+
+    @Autowired
+    private ResumeEducationExperienceService resumeEducationExperienceService;
+
+    @Autowired
+    private ResumeWorkExperienceService resumeWorkExperienceService;
+
+    @Autowired
+    private ResumeDeliverRecordService resumeDeliverRecordService;
+
+
+    private Logger logger = LoggerFactory.getLogger(getClass());
+
+    @PostMapping("resumeStatus")
+    @ApiOperation(value = "简历状态")
+    public MessageResult<String> resumeStatus(String token, @RequestAttribute  String subject) {
+        MessageResult<String> messageResult = new MessageResult<>();
+
+        try {
+            //JobUser jobUser = jobUserService.get(subject);
+            Resume resume = resumeService.findByUserId(subject);
+            String returnStr = "未创建";
+            if(resume != null){
+                returnStr = dataDictionaryService.findNameByCatalogNameAndValue("简历审批状态",resume.getApproveStatus());
+            }
+
+            messageResult.setData(returnStr);
+            messageResult.setResult(true);
+            messageResult.setCode(200);
+        } catch (Exception ex) {
+            logger.error(ex.getMessage(), ex);
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+        }
+        return messageResult;
+    }
+
+    @PostMapping("collectResume")
+    @ApiOperation(value = "收藏简历")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "recruitmentId", value = "岗位ID", required = true, paramType = "form"),
+            @ApiImplicitParam(name = "status", value = "状态(收藏1,取消0),默认1收藏",  paramType = "form"),
+    })
+    public MessageResult<String> collectResume(
+            String recruitmentId,
+            @RequestParam(value="status",defaultValue="1") String status,
+            @RequestAttribute  String subject) {
+        MessageResult<String> messageResult = new MessageResult<>();
+
+        try {
+            UserCollection uc = userCollectionService.findByUserIdAndRId(subject,recruitmentId);
+            if("1".equals(status)){
+                if(uc == null){
+                    uc = new UserCollection();
+                    uc.setId(UUID.randomUUID().toString());
+                    uc.setCreateBy(subject);
+                    uc.setCreateTime(new Date());
+                    uc.setJobRecruitmentId(recruitmentId);
+                    uc.setJobUserId(subject);
+                    uc.setDelFlag(false);
+
+                    userCollectionService.insert(uc);
+                }else{
+                    uc.setUpdateBy(subject);
+                    uc.setUpdateTime(new Date());
+                    uc.setDelFlag(false);
+
+                    userCollectionService.update(uc);
+                }
+            }else{
+                if(uc != null){
+                    uc.setUpdateBy(subject);
+                    uc.setUpdateTime(new Date());
+                    uc.setDelFlag(true);
+
+                    userCollectionService.update(uc);
+                }
+            }
+
+
+            messageResult.setData("操作成功");
+            messageResult.setResult(true);
+            messageResult.setCode(200);
+        } catch (Exception ex) {
+            log.error(ex.getMessage());
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+        }
+
+        return messageResult;
+    }
+
+    @PostMapping("deliverResume")
+    @ApiOperation(value = "投递简历")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "recruitmentId", value = "岗位ID", required = true, paramType = "form"),
+            @ApiImplicitParam(name = "resumeId", value = "简历ID,不传则默认查当前简历", paramType = "form"),
+    })
+    public MessageResult<String> deliverResume(
+            String recruitmentId,
+            @RequestParam(value="resumeId",defaultValue="") String resumeId,
+            @RequestAttribute  String subject) {
+        MessageResult<String> messageResult = new MessageResult<>();
+
+        try {
+            //JobUser jobUser = jobUserService.get(subject);
+            Resume resume = null;
+            if(StringUtils.isNotEmpty(resumeId)) {
+                resume = resumeService.get(resumeId);
+            }else{
+                resume = resumeService.findByUserId(subject);
+            }
+            if(resume == null){
+                messageResult.setMessage("未创建简历");
+                messageResult.setResult(false);
+                messageResult.setCode(400);
+                return messageResult;
+            }else{
+                if(!"0".equals(resume.getStatus())){
+                    messageResult.setMessage("当前简历未开启");
+                    messageResult.setResult(false);
+                    messageResult.setCode(400);
+                    return messageResult;
+                }
+
+                if(!"2".equals(resume.getApproveStatus())){
+                    messageResult.setMessage("当前简历未审批");
+                    messageResult.setResult(false);
+                    messageResult.setCode(400);
+                    return messageResult;
+                }
+            }
+
+            ResumeDeliver rd = new ResumeDeliver();
+            rd.setId(UUID.randomUUID().toString());
+            rd.setCreateBy(subject);
+            rd.setCreateTime(new Date());
+            rd.setDelFlag(false);
+            rd.setJobRecruitmentId(recruitmentId);
+            rd.setJobUserId(subject);
+            rd.setStatus("0");
+
+            int inCount = resumeDeliverService.insert(rd);
+            if(inCount > 0) {
+                messageResult.setMessage("投递成功");
+                messageResult.setResult(true);
+                messageResult.setCode(200);
+            }else{
+                messageResult.setMessage("投递失败");
+                messageResult.setResult(false);
+                messageResult.setCode(400);
+                return messageResult;
+            }
+        } catch (Exception ex) {
+            log.error(ex.getMessage());
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+        }
+
+        return messageResult;
+    }
+
+    @PostMapping("myResumeDetail")
+    @ApiOperation(value = "我的简历-详情")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "resumeId", value = "简历ID,不传则默认查当前简历", paramType = "form"),
+    })
+    public MessageResult<Map> myResumeDetail(
+            @RequestParam(value="resumeId",defaultValue="") String resumeId,
+            @RequestAttribute  String subject) {
+        MessageResult<Map> messageResult = new MessageResult<>();
+
+        try {
+            //JobUser jobUser = jobUserService.get(subject);
+            Resume resume = null;
+            if(StringUtils.isNotEmpty(resumeId)) {
+                resume = resumeService.get(resumeId);
+            }else{
+                resume = resumeService.findByUserId(subject);
+            }
+
+            if(resume == null){
+                messageResult.setMessage("未创建简历");
+                messageResult.setResult(false);
+                messageResult.setCode(400);
+                return messageResult;
+            }
+
+            List<ResumeEducationExperience> rexList = resumeEducationExperienceService.findByResumeId(resume.getId());
+            List<ResumeWorkExperience> rweList = resumeWorkExperienceService.findByResumeId(resume.getId());
+
+
+            Map<String, Object> dataMap = new HashMap<String, Object>();
+
+            dataMap.put("resume", resume);
+            dataMap.put("educationExperienceList", rexList);
+            dataMap.put("workExpList", rweList);
+
+            messageResult.setData(dataMap);
+            messageResult.setResult(true);
+            messageResult.setCode(200);
+            return messageResult;
+        } catch (Exception ex) {
+            log.error(ex.getMessage());
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+        }
+
+        return messageResult;
+    }
+
+
+    @PostMapping("deliveryRecord")
+    @ApiOperation(value = "投递记录")
+    public MessageResult<Map> deliveryRecord(
+            @RequestParam(value="pageIndex",defaultValue="1") int pageIndex,
+            @RequestParam(value="pageSize",defaultValue="10") int pageSize,
+            @RequestAttribute  String subject) {
+        MessageResult<Map> messageResult = new MessageResult<>();
+
+        try {
+            //JobUser jobUser = jobUserService.get(subject);
+            Map<String,Object> searchParams = new HashMap<>();
+
+            List<Sort> sortList = new ArrayList<>();
+            sortList.add(new Sort("a.create_time","desc"));
+
+            Page<ResumeDeliver> page = resumeDeliverService.pageSearch(searchParams,pageIndex,pageSize,true,sortList);
+            for(ResumeDeliver rd : page.getResult()){
+                Recruitment recruitment = recruitmentService.get(rd.getJobRecruitmentId());
+                rd.setJobRecruitment(recruitment);
+            }
+
+            messageResult.setResult(true);
+            messageResult.setData(PojoUtils.pageWrapper(page));
+        } catch (Exception ex) {
+            log.error(ex.getMessage());
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+        }
+
+        return messageResult;
+    }
+}

+ 57 - 0
web/src/main/java/com/jpsoft/employment/modules/mobile/controller/UserBrowseApiController.java

@@ -0,0 +1,57 @@
+package com.jpsoft.employment.modules.mobile.controller;
+
+import com.github.pagehelper.Page;
+import com.jpsoft.employment.modules.common.dto.MessageResult;
+import com.jpsoft.employment.modules.common.dto.MessageResultBuilder;
+import com.jpsoft.employment.modules.common.dto.Sort;
+import com.jpsoft.employment.modules.common.utils.MapUtils;
+import com.jpsoft.employment.modules.common.utils.PojoUtils;
+import com.jpsoft.employment.modules.job.entity.Recruitment;
+import com.jpsoft.employment.modules.job.entity.UserBrowse;
+import com.jpsoft.employment.modules.job.service.UserBrowseService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+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.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/mobile/userBrowseApi")
+@Api(tags = "移动端接口:求职人职位浏览记录")
+@Slf4j
+public class UserBrowseApiController {
+
+
+    private Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Autowired
+    private UserBrowseService userBrowseService;
+
+
+    @PostMapping("pagedLoad")
+    @ApiOperation(value = "分页加载职位浏览记录(按浏览时间倒序)")
+    public MessageResult<Map> pagedLoad( @RequestParam(value="pageIndex",defaultValue="1") int pageIndex,
+                                         @RequestParam(value="pageSize",defaultValue="20") int pageSize,
+                                         @RequestAttribute String subject){
+        try{
+            List<Sort> sortList = new ArrayList<>();
+            sortList.add(new Sort("update_time","desc"));
+            Page<Recruitment> page = userBrowseService.loadUserBrowses(MapUtils.builder("jobUserId",subject),pageIndex,pageSize,true,sortList);
+            return MessageResultBuilder.ok(PojoUtils.pageWrapper(page));
+        }
+        catch(Exception ex){
+            log.error(ex.getMessage());
+            return MessageResultBuilder.error(ex.getMessage());
+        }
+
+    }
+}

+ 67 - 0
web/src/main/java/com/jpsoft/employment/modules/pay/properties/AliPayProperties.java

@@ -0,0 +1,67 @@
+package com.jpsoft.employment.modules.pay.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author 墨鱼_mo
+ * @date 2019-11-26 9:37
+ */
+
+@Data
+@ConfigurationProperties(prefix = "alipay")
+@Component
+public class AliPayProperties {
+
+
+    /**
+     * 支付宝网关
+     */
+    private String serviceUrl;
+
+    /**
+     * 应用appid
+     */
+    private String appId;
+
+    /**
+     * 应用私钥
+     */
+    private String privateKey;
+
+    /**
+     * 支付宝公钥
+     */
+    private String zfbPublicKey;
+
+    /**
+     * 编码
+     */
+    private String inputCharset;
+
+    /**
+     * 服务商id
+     */
+    private String mchId;
+
+    /**
+     * 授权token
+     */
+    private String appAuthToken;
+
+    /**
+     * 加密方式
+     */
+    private String signType;
+
+    /**
+     * 支付回调地址
+     */
+    private String notifyUrl;
+
+    /**
+     * 商品描述
+     */
+    private String body;
+}

+ 68 - 0
web/src/main/java/com/jpsoft/employment/modules/pay/properties/ParkAliPayProperties.java

@@ -0,0 +1,68 @@
+package com.jpsoft.employment.modules.pay.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author 墨鱼_mo
+ * @date 2020-4-16 15:05
+ */
+@Data
+@ConfigurationProperties(prefix = "parkalipay")
+@Component
+public class ParkAliPayProperties {
+
+    /**
+     * 支付宝网关
+     */
+    private String serviceUrl;
+
+    /**
+     * 应用appid
+     */
+    private String appId;
+
+    /**
+     * 应用私钥
+     */
+    private String privateKey;
+
+    /**
+     * 支付宝公钥
+     */
+    private String zfbPublicKey;
+
+    /**
+     * 编码
+     */
+    private String inputCharset;
+
+    /**
+     * 服务商id
+     */
+    private String mchId;
+
+    /**
+     * 授权token
+     */
+    private String appAuthToken;
+
+    /**
+     * 加密方式
+     */
+    private String signType;
+
+    /**
+     * 支付回调地址
+     */
+    private String notifyUrl;
+
+    /**
+     * 商品描述
+     */
+    private String body;
+
+    private String format;
+
+}

+ 71 - 0
web/src/main/java/com/jpsoft/employment/modules/pay/properties/WxJpsoftProperties.java

@@ -0,0 +1,71 @@
+package com.jpsoft.employment.modules.pay.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author 墨鱼_mo
+ * @date 2019-11-26 9:35
+ */
+
+@Data
+@ConfigurationProperties(prefix = "wx.jpsoft")
+@Component
+public class WxJpsoftProperties {
+
+    /**
+     * 设置微信公众号或者小程序等的appid
+     */
+    private String appId;
+
+    /**
+     * 设置微信公众号或者小程序等的appSecret
+     */
+    private String appSecret;
+
+    /**
+     * 微信支付商户号
+     */
+    private String mchId;
+
+    /**
+     * 微信支付商户密钥
+     */
+    private String mchKey;
+
+    /**
+     * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
+     */
+    private String subAppId;
+
+    /**
+     * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
+     */
+    private String subMchId;
+
+    /**
+     * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
+     */
+    private String keyPath;
+
+    /**
+     * 回调地址
+     */
+    private String notifyUrl;
+
+    /**
+     * 发起ip
+     */
+    private String ip;
+
+    /**
+     * 商品描述
+     */
+    private String body;
+
+    /**
+     * 页面跳转标识
+     */
+    private String urlKey;
+}

+ 71 - 0
web/src/main/java/com/jpsoft/employment/modules/pay/properties/WxPayProperties.java

@@ -0,0 +1,71 @@
+package com.jpsoft.employment.modules.pay.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author 墨鱼_mo
+ * @date 2019-11-26 9:35
+ */
+
+@Data
+@ConfigurationProperties(prefix = "wx.pay")
+@Component
+public class WxPayProperties {
+
+    /**
+     * 设置微信公众号或者小程序等的appid
+     */
+    private String appId;
+
+    /**
+     * 设置微信公众号或者小程序等的appSecret
+     */
+    private String appSecret;
+
+    /**
+     * 微信支付商户号
+     */
+    private String mchId;
+
+    /**
+     * 微信支付商户密钥
+     */
+    private String mchKey;
+
+    /**
+     * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
+     */
+    private String subAppId;
+
+    /**
+     * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
+     */
+    private String subMchId;
+
+    /**
+     * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
+     */
+    private String keyPath;
+
+    /**
+     * 回调地址
+     */
+    private String notifyUrl;
+
+    /**
+     * 发起ip
+     */
+    private String ip;
+
+    /**
+     * 商品描述
+     */
+    private String body;
+
+    /**
+     * 前端页面url
+     */
+    private String portalUrl;
+}

+ 85 - 0
web/src/main/java/com/jpsoft/employment/modules/wechat/callback/EventCallback.java

@@ -0,0 +1,85 @@
+package com.jpsoft.employment.modules.wechat.callback;
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Data
+public class EventCallback {
+    private String code;
+    private String callbackUrl;
+    private String message;
+
+    public EventCallback(){
+
+    }
+
+    public EventCallback(String code, String callbackUrl){
+        this.code = code;
+        this.callbackUrl = callbackUrl;
+//        this.message = message;
+    }
+
+    public boolean process(String wechatId, String openId, String eventKey){
+        boolean result = false;
+
+        try {
+            StringBuilder urlBuilder = new StringBuilder();
+
+            urlBuilder.append(this.callbackUrl);
+
+            HttpPost httpPost = new HttpPost(urlBuilder.toString());
+
+            RequestConfig requestConfig = RequestConfig.custom()
+                    .setSocketTimeout(5000)
+                    .setConnectTimeout(5000)
+                    .setConnectionRequestTimeout(5000)
+                    .build();
+
+            CloseableHttpClient httpClient = HttpClientBuilder.create()
+                    .setDefaultRequestConfig(requestConfig)
+                    .build();
+
+            List<NameValuePair> list = new ArrayList<NameValuePair>();
+            list.add(new BasicNameValuePair("eventKey", eventKey));
+            list.add(new BasicNameValuePair("wechatId", wechatId));
+            list.add(new BasicNameValuePair("openId", openId));
+
+            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
+            httpPost.setEntity(entity);
+
+            HttpResponse res = httpClient.execute(httpPost);
+
+            if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+                String content = EntityUtils.toString(res.getEntity());
+                this.setMessage(content);
+
+                result = true;
+            }
+            else{
+                this.setMessage("发送请求到业务平台失败!");
+            }
+        }
+        catch (Exception ex){
+            log.error(ex.getMessage(),ex);
+
+            result = false;
+            this.setMessage(ex.getMessage());
+        }
+
+        return result;
+    }
+}

+ 419 - 0
web/src/main/java/com/jpsoft/employment/modules/wechat/controller/WxController.java

@@ -0,0 +1,419 @@
+package com.jpsoft.employment.modules.wechat.controller;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.alipay.api.domain.CompanyInfo;
+import com.jpsoft.employment.config.WxConfig;
+import com.jpsoft.employment.modules.common.dto.MessageResult;
+import com.jpsoft.employment.modules.common.service.impl.RedisServiceImpl;
+import com.jpsoft.employment.modules.common.utils.Generator.CaptchaUtilA;
+import com.jpsoft.employment.modules.common.utils.Generator.CircleCaptchaA;
+import com.jpsoft.employment.modules.common.utils.SMSUtil;
+import com.jpsoft.employment.modules.common.utils.Sign;
+import com.jpsoft.employment.modules.common.utils.WeixinUtil;
+import com.jpsoft.employment.modules.job.entity.JobUser;
+import com.jpsoft.employment.modules.job.service.JobUserService;
+import com.jpsoft.employment.modules.pay.properties.WxPayProperties;
+import com.jpsoft.employment.modules.sys.entity.User;
+import com.jpsoft.employment.modules.sys.service.UserService;
+import com.jpsoft.employment.modules.wechat.callback.EventCallback;
+import com.jpsoft.employment.modules.wechat.entity.AccessToken;
+import com.jpsoft.employment.modules.wechat.vo.UserInfo;
+import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @author 墨鱼_mo
+ * @date 2019-12-3 15:08
+ */
+
+@Slf4j
+@RequestMapping("/wechat")
+@RestController
+public class WxController {
+
+
+    @Autowired
+    private WxConfig wxConfig;
+
+
+    @Autowired
+    private ValueOperations<String, Object> valueOperations;
+
+    @Autowired
+    private RedisServiceImpl redisService;
+
+    @Autowired
+    private WxPayProperties wxPayProperties;
+
+    @Autowired
+    private JobUserService jobUserService;
+
+    @Autowired
+    private UserService userService;
+
+    @ApiOperation(value = "获取微信配置")
+    @GetMapping(value = "/getConfig")
+    public MessageResult getConfig(String url) {
+
+        int code = 200;
+        String message = "获取成功";
+        Object data = "";
+        boolean result = true;
+
+        try {
+            AccessToken token = WeixinUtil.getAccessToken(wxPayProperties.getAppId(), wxPayProperties.getAppSecret());
+
+            Map<String, String> wxMap = Sign.sign(WeixinUtil.getJsAPI(token.getToken()), url);
+
+            wxMap.put("appId", wxPayProperties.getAppId());
+
+            log.warn(JSONObject.toJSONString(wxMap));
+
+            HashMap<String, Object> dataMap = new HashMap<String, Object>();
+
+            dataMap.put("wxConfig", wxMap);
+
+            data = dataMap;
+        } catch (Exception ex) {
+            log.error(ex.getMessage(),ex);
+
+            code = 500;
+            result = false;
+            message = "系统错误";
+        }
+
+        return new MessageResult(result, message, data, code);
+    }
+
+    @ApiOperation(value = "获取微信code")
+    @PostMapping(value = "findWechatUrl")
+    public MessageResult findWechatUrl(@RequestBody String url) {
+
+        String newpath = WeixinUtil.getCodeRequest(wxPayProperties.getAppId(), url, "snsapi_userinfo");
+
+        HashMap<String, Object> dataMap = new HashMap<String, Object>();
+
+        dataMap.put("wechatUrl", newpath);
+
+        return new MessageResult(true, "获取成功", dataMap, 200);
+    }
+
+    @ApiOperation(value = "获取公众号用户信息")
+    @GetMapping(value = "findUserInfo/{code}")
+    public MessageResult findUserInfo(@PathVariable String code) {
+        try {
+            log.warn("code=" + code);
+            log.warn("appId=" + wxPayProperties.getAppId());
+            log.warn("appSecret=" + wxPayProperties.getAppSecret());
+
+            AccessToken at = WeixinUtil.getAccessToken(wxPayProperties.getAppId(), wxPayProperties.getAppSecret(), code);
+
+
+            if (at != null && StringUtils.isNotBlank(at.getOpenid())) {
+                String openId = at.getOpenid();
+                System.out.println("openId:" + openId);
+
+                UserInfo userInfo = WeixinUtil.getUserInfo(openId, at.getToken());
+
+                HashMap<String, Object> dataMap = new HashMap<String, Object>();
+
+                dataMap.put("userInfo", userInfo);
+
+                return new MessageResult(true, "获取微信信息成功", userInfo, 200);
+
+            } else {
+                return new MessageResult(false, "获取微信信息失败", "", 400);
+            }
+
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            return new MessageResult(false, "系统错误", "", 500);
+        }
+    }
+
+    @GetMapping(value = "getAppId/{id}")
+    @ResponseBody
+    public MessageResult getAppId(@PathVariable("id") String id) {
+
+        int code = 200;
+        String message = "获取成功";
+        Object data = "";
+        boolean result = true;
+
+        try {
+
+            HashMap<String, Object> wxMap = new HashMap<>();
+
+            wxMap.put("appId", wxPayProperties.getAppId());
+
+            HashMap<String, Object> dataMap = new HashMap<String, Object>();
+
+            dataMap.put("wxConfig", wxMap);
+
+            data = dataMap;
+
+        } catch (Exception ex) {
+            code = 500;
+            message = "系统错误";
+            result = false;
+        }
+
+        return new MessageResult(result, message, data, code);
+    }
+
+    @ApiOperation(value = "获取图片验证码信息")
+    @GetMapping("/getVerifyPic")
+    public MessageResult getVerifyPic(String openId, HttpServletResponse response) {
+        int code = 200;
+        String message = "获取验证码成功";
+        Object data = "";
+        boolean result = true;
+
+        try {
+
+            if (StringUtils.isBlank(openId)) {
+                throw new Exception("openId为空");
+            }
+
+            CircleCaptchaA captcha = CaptchaUtilA.createCircleCaptcha(200, 100, 4, 0);
+            captcha.write(response.getOutputStream());
+            String verifyPic = captcha.getCode();
+            redisService.put("code", openId, verifyPic, 120);
+
+
+            response.getOutputStream().close();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            code = 500;
+            message = e.getMessage();
+            result = false;
+        }
+
+        return new MessageResult(result, message, data, code);
+    }
+
+
+    @ApiOperation(value = "管理员绑定微信openid")
+    @PostMapping(value = "/bindWechat")
+    public MessageResult<String> bindWechat(String eventKey,String openId){
+        MessageResult<String> messageResult = new MessageResult<>();
+
+        try{
+            String[] arr = eventKey.split(",");
+
+            String userId = arr[1];
+            User user = userService.get(userId);
+
+            if (user!=null) {
+                user.setOpenId(openId);
+                user.setUpdateTime(new Date());
+                user.setUpdateBy(userId);
+                userService.update(user);
+            }
+            else{
+                throw new Exception("用户不存在!");
+            }
+
+            messageResult.setMessage(user.getUserName() + "绑定微信成功!");
+            messageResult.setResult(true);
+        }
+        catch (Exception ex){
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+
+            log.error(ex.getMessage(),ex);
+        }
+
+        return messageResult;
+    }
+
+    @ApiOperation(value = "用户绑定微信openid")
+    @PostMapping(value = "/bindPersonWechat")
+    public MessageResult<String> bindPersonWechat(String eventKey,String openId){
+        MessageResult<String> messageResult = new MessageResult<>();
+
+        try{
+            String[] arr = eventKey.split(",");
+
+            String userId = arr[1];
+            String phone = arr[2];
+
+            JobUser jobUser = jobUserService.get(userId);
+
+            //多传一个电话号码避免,测试环境和正式环境混淆
+            if (jobUser!=null) {
+                if(jobUser.getTel().equals(phone)) {
+                    jobUser.setOpenId(openId);
+                    jobUser.setUpdateTime(new Date());
+                    jobUser.setUpdateBy(userId);
+                    jobUserService.update(jobUser);
+                }
+                else{
+                    throw new Exception("用户手机号错误!");
+                }
+            }
+            else{
+                throw new Exception("用户不存在!");
+            }
+
+            messageResult.setMessage(jobUser.getRealName() + "绑定微信成功!");
+            messageResult.setResult(true);
+        }
+        catch (Exception ex){
+            messageResult.setResult(false);
+            messageResult.setMessage(ex.getMessage());
+
+            log.error(ex.getMessage(),ex);
+        }
+
+        return messageResult;
+    }
+
+    @ApiOperation(value = "验证服务器地址的有效性")
+    @GetMapping("/get")
+    @ResponseBody
+    public String index(@RequestParam(defaultValue = "") String signature,
+                        @RequestParam(defaultValue = "") String timestamp,
+                        @RequestParam(defaultValue = "") String nonce,
+                        @RequestParam(defaultValue = "") String echostr) {
+        log.warn("signature=" + signature);
+        log.warn("timestamp=" + timestamp);
+        log.warn("nonce=" + nonce);
+        log.warn("echostr=" + echostr);
+
+        if (WeixinUtil.checkSignature(wxConfig.getToken(), signature, timestamp, nonce)) {
+            return echostr;
+        } else {
+            return "index";
+        }
+    }
+
+
+    @ResponseBody
+    @ApiOperation(value = "创建二维码")
+    @PostMapping("/qrcode/create")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "expire_seconds", paramType = "query", required = true, value = "该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。"),
+            @ApiImplicitParam(name = "action_name", paramType = "query", required = true, value = "二维码类型,QR_SCENE为临时的整型参数值,QR_STR_SCENE为临时的字符串参数值,QR_LIMIT_SCENE为永久的整型参数值,QR_LIMIT_STR_SCENE为永久的字符串参数值"),
+            @ApiImplicitParam(name = "scene_id", paramType = "query", value = "场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)"),
+            @ApiImplicitParam(name = "scene_str", paramType = "query", value = "场景值ID(字符串形式的ID),字符串类型,长度限制为1到64")
+    })
+    public cn.hutool.json.JSONObject createQrcode(@RequestParam(name = "expire_seconds", defaultValue = "300") long expireSeconds,
+                                                  @RequestParam(name = "action_name", defaultValue = "QR_STR_SCENE") String actionName,
+                                                  @RequestParam(name = "scene_id", required = false) String sceneId,
+                                                  @RequestParam(name = "scene_str", required = false) String sceneStr) {
+        cn.hutool.json.JSONObject resultObj = new cn.hutool.json.JSONObject();
+
+        try {
+            StringBuilder urlBuilder = new StringBuilder();
+            AccessToken accessToken = WeixinUtil.getAccessToken(wxConfig.getAppId(), wxConfig.getAppSecret());
+
+            urlBuilder.append(wxConfig.getCreateQrCodeUrl())
+                    .append("?access_token=")
+                    .append(URLEncoder.encode(accessToken.getToken(), "UTF-8"));
+
+            cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject();
+            jsonObject.put("expire_seconds", expireSeconds);
+            jsonObject.put("action_name", actionName);
+
+            cn.hutool.json.JSONObject actionInfo = new cn.hutool.json.JSONObject();
+            cn.hutool.json.JSONObject scene = new cn.hutool.json.JSONObject();
+
+            StringBuilder keyBuilder = new StringBuilder();
+
+            keyBuilder.append(accessToken);
+
+            if (StringUtils.isNotEmpty(sceneId)) {
+                scene.put("scene_id", sceneId);
+                keyBuilder.append(sceneId);
+            }
+
+            if (StringUtils.isNotEmpty(sceneStr)) {
+                scene.put("scene_str", sceneStr);
+                keyBuilder.append(sceneStr);
+            }
+
+            String qrcodeUrl = (String) valueOperations.get("QRCODE_" + keyBuilder.toString());
+
+            if (StringUtils.isNotEmpty(qrcodeUrl)) {
+                resultObj.put("data", qrcodeUrl);
+                resultObj.put("result", true);
+            } else {
+                actionInfo.put("scene", scene);
+
+                jsonObject.put("action_info", actionInfo);
+
+                StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
+
+                entity.setContentType("application/json");//发送json数据需要设置contentType
+
+                HttpPost httpPost = new HttpPost(urlBuilder.toString());
+                CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+
+                httpPost.setEntity(entity);
+
+                HttpResponse res = httpClient.execute(httpPost);
+
+                if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+                    String content = EntityUtils.toString(res.getEntity());// 返回json格式:
+                    cn.hutool.json.JSONObject ret = new cn.hutool.json.JSONObject(content);
+
+                    if (ret.containsKey("errcode")) {
+                        resultObj.put("result", false);
+                        resultObj.put("message", ret.getStr("errmsg"));
+                        resultObj.put("code", ret.getInt("errcode"));
+                    } else {
+                        String ticket = ret.getStr("ticket");
+                        long expire_seconds = ret.getLong("expire_seconds");
+
+                        qrcodeUrl = wxConfig.getShowQrCodeUrl() + "?ticket=" + URLEncoder.encode(ticket, "UTF-8");
+
+                        valueOperations.set("QRCODE_" + keyBuilder, qrcodeUrl, expire_seconds - 5, TimeUnit.SECONDS);
+
+                        resultObj.put("data", qrcodeUrl);
+                        resultObj.put("result", true);
+                    }
+                } else {
+                    resultObj.put("result", false);
+                    resultObj.put("message", "weixin服务器未正常返回!");
+                }
+            }
+        } catch (Exception ex) {
+            log.error(ex.getMessage(), ex);
+
+            resultObj.put("message", ex.getMessage());
+            resultObj.put("result", false);
+        }
+
+        return resultObj;
+    }
+}