项目地址:https://mgo.whhtjl.com/coursedetails/4216

我这里后端使用的SpringBoot,Maven项目,代码如下:

<!--公众号(包括订阅号和服务号) -->
<dependency>
	<groupId>com.github.binarywang</groupId>
	<artifactId>weixin-java-mp</artifactId>
	<version>3.9.0</version>
</dependency>

在application.properties中配置相关信息

#微信公众号
wx.mp.appId=xxxxxxxxxxxx
wx.mp.secret=xxxxxxxxxxxxxxxxxxxxxx
wx.mp.subscribeUri=https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzIxMTM3NzcxMw==&scene=%s#wechat_redirect

创建需要的实体类

package com.ltf.entity;

import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;

/**
 * 第三方登录用户实体类
 * @author xhz
 *
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class UserProfile implements Serializable{

	private static final long serialVersionUID = 1L;
	private int id;//主键
	private String nickName;//属性名称如token,昵称
	private int gender;//性别(1:男;2:女)
	private String openId;//第三方key
	private String unionId;//仅供微信使用
	private String accessToken;//仅供QQ使用
	private String profileType;//第三方类型:WXHD(微信海报裂变活动)
	private int userId;//用户id
	private Date profileDate;//添加时间
	private String avatar;//第三方头像
	private String valueTwo;//第三方key辅助
	private boolean subscribe;//是否关注公众号

}
package com.ltf.entity;

import java.io.Serializable;
import java.util.Date;
import lombok.Data;

/**
 * 活动
 * @author ltf
 *
 */
@Data
public class WxTaskDTO implements Serializable{

	private static final long serialVersionUID = 1L;
	private int taskId;
	private int taskCourseId;
	private String taskSubject;
	private Date inittime;
	private Date endtime;
	private String content;
	private String templateactorurl;
	private String templatefinishurl;
	private String templatefinishurl2;
	private String templatefinishurl3;
	private int counts;
	private int counts2;
	private int counts3;
	private String hbinfo;

}
package com.ltf.entity;

import java.io.Serializable;
import java.util.Date;
import lombok.Data;

/**
 * 活动
 * @author ltf
 *
 */
@Data
public class WxTaskProgressDTO implements Serializable{

	private static final long serialVersionUID = 1L;
	private int id;
	private int taskId;
	private int initUserId;
	private int pUserId;
	private Date cctime;

}
package com.ltf.config;

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

/**
 * 文件上传
 * @author xhz
 *
 */
@Data
@Component
@ConfigurationProperties(prefix = "youkego.file")
public class FileConfig {

	private String uploadPath;//上传路径
	private String username;//用户名
	private String password;//密码
	private String rootDirectory;//根目录
	private String  hdImages;//海报裂变路径

}

创建dao层

package com.ltf.dao;

import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.ltf.entity.UserProfile;

/**
 * 用户第三方登录dao层
 * @author xhz
 *
 */
@Mapper
public interface UserProfileDao {

	//表名
	String TABLE_NAME = "edu_user_profile";
	//插入的字段
	String INSERT_FIELDS = " nick_name, gender, open_id, union_id, access_token, profile_type, user_id, profile_date, avatar, value_two,subscribe ";
	//查找的字段
	String SELECT_FIELDS = " id, " + INSERT_FIELDS;

	/**
	 *  修改用户第三方登录信息
	 * @param userProfile
	 */
	public void updateUserProfile(UserProfile userProfile);

	/**
	 * 更新微信openId查询唯一用户
	 * @param openId
	 * @return
	 */
	@Select({"select ",SELECT_FIELDS," from ",TABLE_NAME," where open_id=#{openId}"})
	public UserProfile queryUserProfileByOpenId(String openId);

}
package com.ltf.dao;

import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.ltf.entity.WxTaskDTO;

/**
 * 微信海报裂变活动
 * @author ltf
 *
 */
@Mapper
public interface WxTaskDao {

	//表名
	String TABLE_NAME = "wxtask";
	//插入的字段
	String INSERT_FIELDS = " taskCourseId, taskSubject, inittime, endtime, content, templateactorurl, templatefinishurl, templatefinishurl2, templatefinishurl3, counts, counts2,counts3, hbinfo";
	//查找的字段
	String SELECT_FIELDS = " taskId, " + INSERT_FIELDS;

	/**
	 * 根据taskId查找
	 * @param id
	 * @return
	 */
	@Select({"select", SELECT_FIELDS, " from ", TABLE_NAME, " where taskId=#{taskId}"})
	WxTaskDTO getWxTaskInfoByTaskId(int taskId);
	
	@Select({"select", SELECT_FIELDS, " from ", TABLE_NAME, " where endtime>now()"})
	List<WxTaskDTO> getWxTaskInfoActivty();

}
package com.ltf.dao;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import com.ltf.entity.WxTaskProgressDTO;

/**
 * 微信海报裂变活动
 * @author ltf
 *
 */
@Mapper
public interface WxTaskProgressDao {

	//表名
	String TABLE_NAME = "wxtaskprogress";
	//插入的字段
	String INSERT_FIELDS = " taskId, initUserId, pUserId, cctime";
	//查找的字段
	String SELECT_FIELDS = " id, " + INSERT_FIELDS;

	/**
	 * 根据taskId查找
	 * @param id
	 * @return
	 */
	@Select({"select "+SELECT_FIELDS+" from wxtaskprogress where id=#{id}"})
	WxTaskProgressDTO getWxTaskInfoProcessByTaskId(int id);
	
	@Select({"select "+SELECT_FIELDS+" from wxtaskprogress where taskId=#{taskId} and pUserId=#{pUserId}"})
	WxTaskProgressDTO getWxTaskInfoProcessByTPID(int taskId,int pUserId);
	
	/**
	 * 插入一条记录
	 * @return
	 */
	@Insert(value = { "insert into "+TABLE_NAME+"("+INSERT_FIELDS+") values(#{taskId},#{initUserId},#{pUserId},NOW())"})
	@Options(useGeneratedKeys=true, keyColumn="id", keyProperty="id")
	void insertWxTaskProcess(WxTaskProgressDTO dto);
	
	/**
	 * 查询完成数量
	 * @param taskId
	 * @param initUserId
	 * @return
	 */
	@Select({"select count(1) as fcounts from wxtaskprogress where taskId=#{taskId} and initUserId=#{initUserId}"})
	int selectFinshCounts(int taskId,int initUserId);
	
}

创建service类

package com.ltf.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.ltf.common.CacheConstans;
import com.ltf.common.CommonConstants;
import com.ltf.dao.UserProfileDao;
import com.ltf.entity.UserProfile;
import com.ltf.utils.DateUtils;
import com.ltf.utils.MD5;
import com.ltf.utils.ObjectUtils;
import com.ltf.utils.StringUtils;

/**
 * 用户第三方登录service层
 * @author xhz
 *
 */
@Service
public class UserProfileService {

	private static final Logger logger = LoggerFactory
			.getLogger(UserProfileService.class);

	@Autowired
	private UserProfileDao userProfileDao;
	
	/**
	 * 活动海报,不形成上下级绑定关系
	 * @param userProfile
	 * @return
	 */
	public Map<String,Object> autoRegisterByWxHd(UserProfile userProfile) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			UserProfile queryUserProfile = userProfileDao.queryUserProfileByOpenId(userProfile.getOpenId());
			if (ObjectUtils.isNotNull(queryUserProfile)
					&& ObjectUtils.isNotNull(queryUserProfile.getUserId())
					&& queryUserProfile.getUserId()> 0) {
				if (StringUtils.isNotEmpty(userProfile.getValueTwo())
						&& StringUtils.isEmpty(queryUserProfile.getValueTwo())) {
					queryUserProfile.setValueTwo(userProfile.getValueTwo());
				}
			}
			userProfile.setProfileDate(new Date());
			// 下载图片
			userProfile.setAvatar(StringUtils.isNotEmpty(userProfile.getAvatar())?userProfile.getAvatar():"https://xxxxxxxxx/xxxxxx/htjl.jpg");
			// 如果已经有数据
			if (ObjectUtils.isNotNull(queryUserProfile)&&queryUserProfile.getUserId() == 0) {
				// 未绑定用户 更新库中 userProfile
				userProfile.setId(queryUserProfile.getId());
				userProfile.setUserId(queryUserProfile.getUserId());
				//System.out.println("更新用户"+queryUserProfile);
				userProfileDao.updateUserProfile(userProfile);
				return map;
			} else {
				//System.out.println("老用户无需添加或者更新");
			}
		} catch (Exception e) {
			logger.error("UserProfileService.autoRegisterByWxHd()----error", e);
		}
		return map;
	}
	
}

创建海报裂变控制层

package com.ltf.controller;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ltf.config.FileConfig;
import com.ltf.dao.IWxPushKfMessage;
import com.ltf.dao.SysWxOpencofigDao;
import com.ltf.dao.UserDao;
import com.ltf.dao.WxAuthinfoDao;
import com.ltf.dao.WxTaskDao;
import com.ltf.dao.WxTaskProgressDao;
import com.ltf.entity.User;
import com.ltf.entity.UserProfile;
import com.ltf.entity.WxAuthinfoDTO;
import com.ltf.entity.WxTaskDTO;
import com.ltf.entity.WxTaskProgressDTO;
import com.ltf.service.UserProfileService;
import com.ltf.utils.StringUtils;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
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 me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.open.api.WxOpenService;
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;

@Controller
@RequestMapping("/xwyz")
public class WxOpenController {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private static final Map<String, WxMpMessageRouter> wxOpenMpMessageRouterMap = new Hashtable<String, WxMpMessageRouter>();
	private static final Map<String, String> auth_refresh_tocken_Map = new Hashtable<String, String>();
	@Autowired
	private IWxPushKfMessage iWxPushKfMessage;
	@Autowired
	private WxOpenService wxOpenService;
	@Autowired
	private WxAuthinfoDao wxAuthinfo;
	@Autowired
	private SysWxOpencofigDao sysWxOpencofigDao;
	@Autowired
	private UserProfileService userProfileService;
	@Autowired
	private WxTaskDao wxTaskDao;
	@Autowired
	private WxTaskProgressDao wxTaskProgressDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private WxMpService jsWxMpService;
	@Autowired
	private FileConfig fileConfig;

	@RequestMapping("{appId}/callback")
	public void callback(@RequestBody(required = false) String requestBody, @PathVariable("appId") String appId,
			@RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp,
			@RequestParam("nonce") String nonce, @RequestParam("openid") String openid,
			@RequestParam("encrypt_type") String encType, @RequestParam("msg_signature") String msgSignature,
			HttpServletResponse response) {
		this.logger.info(
				"\n接收微信请求:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
						+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
						appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
		if (!StringUtils.equalsIgnoreCase("aes", encType)
				|| !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
			throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
		}
		// aes加密的消息
		WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody,
				wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
		if (StringUtils.isEmpty(wxOpenService.getWxOpenConfigStorage().getAuthorizerRefreshToken(appId))) {
			String appId_token = getWxMpAuthRefreshTockenByAppid(appId);
			wxOpenService.getWxOpenConfigStorage().setAuthorizerRefreshToken(appId, appId_token);
		}
		WxMpXmlOutMessage outMessage = getWxMpMessageRouterByAppid(appId).route(inMessage);
		if (outMessage != null) {
			try {
				response.getWriter().write(
						outMessage.toEncryptedXml(wxOpenService.getWxOpenConfigStorage().getWxMpConfigStorage(appId)));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private String getWxMpAuthRefreshTockenByAppid(String appId) {
		String token = auth_refresh_tocken_Map.get(appId);
		if (StringUtils.isEmpty(token)) {
			token = wxAuthinfo.selectWxAuthinfo(appId);
			auth_refresh_tocken_Map.put(appId, token);
		}
		return token;
	}

	public WxMpMessageRouter getWxMpMessageRouterByAppid(String appId) {
		WxMpMessageRouter wxMpMessageRouter = wxOpenMpMessageRouterMap.get(appId);
		if (wxMpMessageRouter == null) {
			synchronized (wxOpenMpMessageRouterMap) {
				wxMpMessageRouter = wxOpenMpMessageRouterMap.get(appId);
				if (wxMpMessageRouter == null) {
					wxMpMessageRouter = new WxMpMessageRouter(
							wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId));
					wxOpenMpMessageRouterMap.put(appId, wxMpMessageRouter);
					addTxtMsgRouter(appId, wxMpMessageRouter);
					addEventRouter(appId, wxMpMessageRouter);
				}
			}
		}
		return wxMpMessageRouter;
	}

	private void addEventRouter(final String appId, WxMpMessageRouter wxMpMessageRouter) {
		WxMpMessageHandler handler = new WxMpMessageHandler() {
			public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
					WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
				WxMpXmlOutTextMessage m = null;
				// 订阅事件
				if (wxMessage.getEvent().equals(WxConsts.EventType.SUBSCRIBE)) {
					if (wxMessage.getEventKey().startsWith("qrscene_") && wxMessage.getTicket() != null) {
						System.out.println("用户未关注时,进行关注后的事件推送 扫描推送");
						actorService(wxMpService, wxMessage, true);
					}
				} else if (wxMessage.getEvent().equals(WxConsts.EventType.SCAN)) {
					// 扫码 用户已关注时的事件推送
					if (wxMessage.getEventKey() != null || wxMessage.getTicket() != null) {
						actorService(wxMpService, wxMessage, true);
					}
				} else if (wxMessage.getEvent().equals(WxConsts.EventType.CLICK)) {// 自定义菜单点击事件
					if (wxMessage.getEventKey() != null && !wxMessage.getEventKey().equals("")) {
						System.out.println("事件KEY值,与自定义菜单接口中KEY值对应");
					}
				} else if (wxMessage.getEvent().equals(WxConsts.EventType.VIEW)) {
					System.out.println("点击菜单跳转链接时的事件推送");
				}
				return m;
			}
		};
		wxMpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).handler(handler).end();
	}

	private void addTxtMsgRouter(final String appId, WxMpMessageRouter wxMpMessageRouter) {
		WxMpMessageHandler handler = new WxMpMessageHandler() {
			public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
					WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
				WxMpXmlOutTextMessage m = null;
				String keys = wxMessage.getContent();
				if (keys.startsWith("xxxxx")&& wxMessage.getFromUser().equals("DSFGDFNMHJJHJ")) {
					actorService(wxMpService, wxMessage, false);
				}
				return m;
			}
		};
		wxMpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).handler(handler).end();
	}

	/**
	 * 注意 这里的代码 是非常的不规范,目前没有精力管这些,后续有必要在调整
	 * 
	 * @param authorizationCode
	 * @return
	 */
	@RequestMapping("/oauthInfo")
	public void oauthInfo(@RequestParam("auth_code") String authorizationCode, HttpServletRequest request,
			HttpServletResponse response) {
		try {
			WxOpenQueryAuthResult queryAuthResult = wxOpenService.getWxOpenComponentService()
					.getQueryAuth(authorizationCode);
			String appId = queryAuthResult.getAuthorizationInfo().getAuthorizerAppid();
			WxOpenAuthorizerInfoResult info = wxOpenService.getWxOpenComponentService().getAuthorizerInfo(appId);
			WxAuthinfoDTO dto = new WxAuthinfoDTO();
			String func_info = "";
			List<Integer> list = info.getAuthorizationInfo().getFuncInfo();
			for (Integer integer : list) {
				func_info += integer + ",";
			}
			func_info = func_info.substring(0, func_info.length() - 1);
			dto.setWxappid(info.getAuthorizationInfo().getAuthorizerAppid());
			dto.setFuncInfo(func_info);
			dto.setNickName(info.getAuthorizerInfo().getNickName());
			dto.setHeadImg(info.getAuthorizerInfo().getHeadImg());
			dto.setServiceTypeInfo(info.getAuthorizerInfo().getServiceTypeInfo());
			dto.setVerifyTypeInfo(info.getAuthorizerInfo().getVerifyTypeInfo());
			dto.setUserName(info.getAuthorizerInfo().getUserName());
			dto.setPrincipalName(info.getAuthorizerInfo().getPrincipalName());
			dto.setOpenStore(info.getAuthorizerInfo().getBusinessInfo().get("open_store"));
			dto.setOpenScan(info.getAuthorizerInfo().getBusinessInfo().get("open_scan"));
			dto.setOpenCard(info.getAuthorizerInfo().getBusinessInfo().get("open_card"));
			dto.setOpenPay(info.getAuthorizerInfo().getBusinessInfo().get("open_pay"));
			dto.setOpenShake(info.getAuthorizerInfo().getBusinessInfo().get("open_shake"));
			dto.setAlias(info.getAuthorizerInfo().getAlias());
			dto.setQrcodeUrl(info.getAuthorizerInfo().getQrcodeUrl());
			dto.setAuthorizerRefreshToken(info.getAuthorizationInfo().getAuthorizerRefreshToken());
			wxAuthinfo.insertAuthinfo(dto);
		} catch (WxErrorException e) {
			e.printStackTrace();
		}
		try {
			response.setContentType("text/html;charset=UTF-8");
			response.sendRedirect("https://xxxxxxxxxxx.com/");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void actorService(WxMpService wxMpService, WxMpXmlMessage wxMessage, boolean isdefault) {
		try {
			WxMpUser userInfo = wxMpService.getUserService().userInfo(wxMessage.getFromUser());
			String keys = wxMessage.getContent();
			if (!isdefault&&keys.startsWith("xxxxxxxxx")) {
				keys =keys.substring(8);
			} else {
				if (wxMessage.getEventKey().startsWith("qrscene_") && wxMessage.getTicket() != null) {
					keys = wxMessage.getEventKey().substring(8);
				} else {
					keys = wxMessage.getEventKey();
				}
			}
			UserProfile userProfile = new UserProfile();
			userProfile.setNickName(StringUtils.filterEmoji(userInfo.getNickname()));
			userProfile.setGender(userInfo.getSex());
			userProfile.setAvatar(userInfo.getHeadImgUrl());
			userProfile.setOpenId(userInfo.getOpenId());
			userProfile.setUnionId(userInfo.getUnionId());
			userProfile.setProfileType("WXHD");
			userProfile.setSubscribe(true);
			userProfileService.autoRegisterByWxHd(userProfile);
			if (StringUtils.isNotEmpty(keys) && keys.contains("&")) {
				String[] array = keys.split("&");
				int taskId = Integer.parseInt(array[0]);
				int initUserId = Integer.parseInt(array[1]);
				WxTaskDTO wxTask = wxTaskDao.getWxTaskInfoByTaskId(taskId);
				// 活动时间过期了
				Date curTime = new Date();
				String nickName=StringUtils.filterEmoji(userInfo.getNickname());
				if(nickName==null||"".equals(nickName.trim())) nickName="❤";
				if (wxTask.getEndtime().getTime() < curTime.getTime()) {
					String content = "亲,{nickname},该活动已结束,请添加客服whhtjl,咨询最新活动~~";
					sendActorMessage(wxMpService, userInfo.getOpenId(), nickName, content);
					return;
				}
				User user = userDao.selectUserByWxOpendId(userInfo.getOpenId());
				if (user != null) {
					int pUserId = user.getId();// 理论上 user 是一定存在的 自动注册了
					if (pUserId == initUserId && isdefault) {// 测试流程所以注释了
						String content = "亲,自己不能助力自己哦~~,快去邀请好友吧~";
						sendActorMessage(wxMpService, userInfo.getOpenId(), userProfile.getNickName(), content);
						return;
					}
					WxTaskProgressDTO wxProgress = wxTaskProgressDao.getWxTaskInfoProcessByTPID(taskId, pUserId);
					if (wxProgress != null) {
						// 已经助力过了 同一个活动只能给1个用户助力
						String content = "亲,{nickname},您已经给其他人助力过了! 同一个活动只能给1个用户助力哦!";
						sendActorMessage(wxMpService, userInfo.getOpenId(), userProfile.getNickName(), content);
					} else {
						// 助力+1
						WxTaskProgressDTO dto=new WxTaskProgressDTO();
						dto.setTaskId(taskId);
						dto.setInitUserId(initUserId);
						dto.setPUserId(pUserId);
						dto.setCctime(new Date());
						wxTaskProgressDao.insertWxTaskProcess(dto);
						// 判断是否达成目标,并给予消息提示
						User init_user = userDao.getUserById(initUserId);
						System.out.println("被识别者:"+init_user.getUserName()+"="+init_user.getOpenId());
						int fcounts = wxTaskProgressDao.selectFinshCounts(taskId, initUserId);
						if (fcounts < wxTask.getCounts()) {
							String content = nickName+"已成功为您助力!\n\n再邀请"+(wxTask.getCounts()-fcounts)+"人助力即可成功领取!加油鸭~~";
							sendActorMessage(wxMpService, init_user.getOpenId(), init_user.getUserName(), content);
						} else {
							String content = nickName+"已成功为您助力!\n\n";
							content += "恭喜您已成功完成任务\n\n ☞<a href=\"" + wxTask.getTemplateactorurl() + "\">点击领取课程礼包</a>";
							sendActorMessage(wxMpService, init_user.getOpenId(), init_user.getUserName(), content);
						}
						String content = wxTask.getContent();
						content=content.replaceAll("nickName",  nickName);
						content=content.replaceAll("initName",  init_user.getUserName());
						content=content.replaceAll("totalCount",  wxTask.getCounts()+"");
						content=content.replaceAll("<br>", "\n");
						sendActorMessage(wxMpService, userInfo.getOpenId(), nickName, content);
					}
				}
				String scene_id=taskId+"&"+user.getId();
				// 自己的海报
				autoWxTaskHb(wxMpService, scene_id, taskId, wxTask, userInfo);
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
		}
	}

	private void sendActorMessage(WxMpService wxMpService, String actor, String initnickName, String actorcontent) {
		WxMpKefuMessage messageInfo = new WxMpKefuMessage();
		messageInfo.setToUser(actor);
		messageInfo.setMsgType(WxConsts.KefuMsgType.TEXT);
		String content = actorcontent.replace("{nickname}", initnickName);
		messageInfo.setContent(content);
		try {
			wxMpService.getKefuService().sendKefuMessage(messageInfo);
		} catch (WxErrorException e) {
			e.printStackTrace();
		}
	}

	private void autoWxTaskHb(WxMpService wxMpService, String scene_id, int taskId, WxTaskDTO wxTask,
			WxMpUser userInfo) {
		try {
			String webPath = fileConfig.getHdImages();
			String posInfo = wxTask.getHbinfo();
			JSONObject hbInfo = JSON.parseObject(posInfo);
			String url = hbInfo.getString("url");
			String hz=url.substring(url.lastIndexOf("."));
			String outFilePathName = webPath + "/" + taskId + "/" + scene_id + hz;
			String dirPath = webPath + "/" + taskId + "/";
			File upload = new File(webPath, "/" + taskId + "/");
			if (!upload.exists())
				upload.mkdirs();
			WxMpQrCodeTicket ticker = wxMpService.getQrcodeService().qrCodeCreateLastTicket(scene_id);
			File coderFile = wxMpService.getQrcodeService().qrCodePicture(ticker);
			// 裁剪版 尽量简化
			FileOutputStream out = new FileOutputStream(outFilePathName);
			String backFileName="template"+hz;
			String backFilePathName=dirPath+backFileName;
			File backImageFile=new File(backFilePathName);
			if(!backImageFile.exists()) {
				download(url, backFileName,dirPath);
				backImageFile=new File(backFilePathName);
			}
			BufferedImage backImage = ImageIO.read(backImageFile);
			BufferedImage outImage = new BufferedImage(backImage.getWidth(), backImage.getHeight(),
					backImage.getType());
			Graphics dec = outImage.getGraphics();
			// 输出背景
			dec.drawImage(backImage, 0, 0, backImage.getWidth(), backImage.getHeight(), null);
			// 输出二维码
			BufferedImage tickImage = ImageIO.read(coderFile);
			dec.drawImage(tickImage, hbInfo.getJSONObject("qr_pos").getIntValue("x"),
					hbInfo.getJSONObject("qr_pos").getIntValue("y"), hbInfo.getJSONObject("qr_pos").getIntValue("w"),
					hbInfo.getJSONObject("qr_pos").getIntValue("h"), null);
			dec.dispose();
			// 输出整个图片
			ImageIO.write(outImage, hz.substring(1), out);
			outImage.flush();
			out.close();
			File file = new File(outFilePathName);
			WxMediaUploadResult wxResult = wxMpService.getMaterialService().mediaUpload(WxConsts.MaterialType.IMAGE,
					file);
			// 生成海报
			WxMpKefuMessage message = new WxMpKefuMessage();
			message.setToUser(userInfo.getOpenId());
			message.setMsgType(wxResult.getType());
			message.setMediaId(wxResult.getMediaId());
			wxMpService.getKefuService().sendKefuMessage(message);

		} catch (WxErrorException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取远程网络图片信息
	 * 
	 * @param imageURL
	 * @return
	 */
	private void download(String urlString, String filename, String savePath) throws Exception {
		URL url = new URL(urlString);
		URLConnection con = url.openConnection();
		con.setConnectTimeout(5 * 1000);
		InputStream is = con.getInputStream();
		byte[] bs = new byte[1024];
		int len;
		File sf = new File(savePath);
		if (!sf.exists()) {
			sf.mkdirs();
		}
		OutputStream os = new FileOutputStream(sf.getPath() + "/" + filename);
		// 开始读取
		while ((len = is.read(bs)) != -1) {
			os.write(bs, 0, len);
		}
		// 完毕,关闭所有链接
		os.close();
		is.close();
	}

}