package com.yc.sdk.weixinmp.action; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.DocumentException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Controller; import com.yc.entity.DataSourceEntity; import com.yc.factory.FactoryBean; import com.yc.multiData.MultiDataSource; import com.yc.multiData.SpObserver; import com.yc.sdk.shopping.entity.SettingEntity; import com.yc.sdk.shopping.service.SettingIfc; import com.yc.sdk.shopping.util.SettingKey; import com.yc.sdk.weixincp.entity.DocumentItemEntity; import com.yc.sdk.weixincp.item.AllItemEntity; import com.yc.sdk.weixincp.item.FileItem; import com.yc.sdk.weixincp.item.ImageItem; import com.yc.sdk.weixincp.item.MpNewsItem; import com.yc.sdk.weixincp.item.NewsItem; import com.yc.sdk.weixincp.item.TextItem; import com.yc.sdk.weixincp.item.VideoItem; import com.yc.sdk.weixincp.item.VoiceItem; import com.yc.sdk.weixincp.util.DocumentItem; import com.yc.sdk.weixincp.util.HttpTookitThread; import com.yc.sdk.weixinmp.entity.MpCorpMsgEntity; import com.yc.sdk.weixinmp.entity.MpUnidEntity; import com.yc.sdk.weixinmp.entity.MyWxMpKfInfo; import com.yc.sdk.weixinmp.entity.MyWxMpKfMsgRecord; import com.yc.sdk.weixinmp.entity.MyWxMpUser; import com.yc.sdk.weixinmp.service.AuthAppIdBy3rdIfc; import com.yc.sdk.weixinmp.service.MpKfAccountIfc; import com.yc.sdk.weixinmp.service.MpMessagesIfc; import com.yc.sdk.weixinmp.service.MpTemplateIfc; import com.yc.sdk.weixinmp.service.MpToDoMsgDataIfc; import com.yc.sdk.weixinmp.service.MpUserIfc; import com.yc.sdk.weixinopen.entity.OpenComponentAppSetting; import com.yc.service.demo.DemoIfc; import com.yc.utils.SessionKey; 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.WxMpService; import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfInfo; import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTransferKefuMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutVideoMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutVoiceMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage.Item; import me.chanjar.weixin.mp.bean.result.WxMpUser; import me.chanjar.weixin.mp.builder.outxml.NewsBuilder; import me.chanjar.weixin.open.api.WxOpenMaService; import me.chanjar.weixin.open.api.WxOpenService; import redis.clients.jedis.JedisPool; @Controller public class MpMessageHandler { @Autowired DemoIfc demo = (DemoIfc)FactoryBean.getBean("demo"); //@Autowired MpMessagesIfc messagesIfc = (MpMessagesIfc)FactoryBean.getBean("MpMessagesImpl"); //@Autowired //MpToDoMsgDataIfc toDoMsgData ; MpToDoMsgDataIfc toDoMsgData = (MpToDoMsgDataIfc)FactoryBean.getBean("MpToDoMsgData"); //@Autowired MpUserIfc mpUserIfc = (MpUserIfc)FactoryBean.getBean("MpUserImpl"); //@Autowired MpKfAccountIfc kfAccountIfc = (MpKfAccountIfc)FactoryBean.getBean("MpKfAccountImpl"); //@Autowired MpTemplateIfc mpTemplateIfc = (MpTemplateIfc)FactoryBean.getBean("MpTemplateImpl"); //@Autowired SettingIfc settingIfc = (SettingIfc)FactoryBean.getBean("SettingImpl"); //@Autowired JedisPool jedisPool = (JedisPool)FactoryBean.getBean("jedisPool"); AuthAppIdBy3rdIfc authAppIdBy3rdIfc = (AuthAppIdBy3rdIfc)FactoryBean.getBean("AuthAppIdBy3rdImpl"); protected DataSourceEntity corpEntity ; protected HttpServletRequest request; public MpMessageHandler(final HttpServletRequest request) { this.request = request; } public WxMpMessageHandler handler = new WxMpMessageHandler() { @Override public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException{ String lang = "zh_CN"; //语言 String msg=""; String msgType = wxMessage.getMsgType(); String event = wxMessage.getEvent(); String fromUser = wxMessage.getFromUser(); String content = null ; List itemList = new ArrayList() ; AllItemEntity allItemEntity = null ; if (wxMpService == null ) return null; //System.out.println("msgType=" + msgType+" EventKey=" + wxMessage.getEventKey() + " Content="+wxMessage.getContent()); corpEntity = MultiDataSource.getDataSourceMapByMpAppId(wxMpService.getWxMpConfigStorage().getAppId()) ; //键盘录入 if ("text".equalsIgnoreCase(msgType)) { allItemEntity = toDoMsgData.getToDoMsgData(wxMessage.getMsgType(),wxMessage.getEventKey(), wxMessage.getContent(),wxMessage.getFromUser(),corpEntity,1); //将客户发过来的信息保存到数据库中 MyWxMpKfMsgRecord chatRecord = new MyWxMpKfMsgRecord() ; chatRecord.setWorker(""); chatRecord.setOpenid(fromUser); chatRecord.setText(wxMessage.getContent()); chatRecord.setTime(wxMessage.getCreateTime()); chatRecord.setOperateCode(2001); // 2001 : 公众号收到消息 chatRecord.setMsgType(msgType); Integer mpMsgSeq = kfAccountIfc.saveChatRecords(chatRecord) ; //保存到数据库 if (allItemEntity != null) { WxMpXmlOutMessage m = sendAll (wxMessage.getToUser(),wxMessage.getFromUser(),allItemEntity,msgType); if (m!=null) return m ; } else { try { //转发给客服处理 String kfAccount = getKfAccount(wxMessage,"",mpMsgSeq,request,wxMpService) ; if (kfAccount==null||"".equals(kfAccount)) { WxMpXmlOutTextMessage m = WxMpXmlOutMessage .TEXT() .content("你的信息已收到,我们会尽快回复你!") .fromUser(wxMessage.getToUser()) .toUser(wxMessage.getFromUser()) .build(); return m ; }else { return transferCustomerService(wxMessage.getToUser(),fromUser,kfAccount); } }catch(DataAccessException e ) { e.printStackTrace(); WxMpXmlOutTextMessage m = WxMpXmlOutMessage .TEXT() .content("你的信息已收到,我们会尽快回复你!") .fromUser(wxMessage.getToUser()) .toUser(wxMessage.getFromUser()) .build(); return m ; }catch(Exception e) { e.printStackTrace(); WxMpXmlOutTextMessage m = WxMpXmlOutMessage .TEXT() .content("你的信息已收到,我们会尽快回复你!") .fromUser(wxMessage.getToUser()) .toUser(wxMessage.getFromUser()) .build(); return m ; }finally{ } } } if ("event".equalsIgnoreCase(msgType)) { //6、获取小程序审核结果 //当小程序有审核结果后,第三方平台将可以通过开放平台上填写的回调地址,获得审核结果通知。 if ("weapp_audit_success".equalsIgnoreCase(event)||"weapp_audit_fail".equalsIgnoreCase(event)) { try { DataSourceEntity dataSourceEntity = MultiDataSource.getDataSourceMapByMaOrgId(wxMessage.getToUser()) ; if (dataSourceEntity!=null&&!"".equals(dataSourceEntity.getMiniAppOrgId())) { String releaseAuthorizationAppid = dataSourceEntity.getMiniAppId(); OpenComponentAppSetting openComponentAppSetting = OpenComponentAppSetting.defaultSettings(); Date auditSuccessTime = null,auditFailTime = null ; if (wxMessage.getSuccessTime()!=null) { auditSuccessTime = new Date(wxMessage.getSuccessTime() * 1000L) ; } if (wxMessage.getFailTime()!=null) { auditFailTime = new Date(wxMessage.getFailTime() * 1000L) ; } try { SpObserver.setDBtoInstance("_"+openComponentAppSetting.getOpenDbId());//切换数据源 authAppIdBy3rdIfc.saveAuditState(openComponentAppSetting.getOpenAppId(),dataSourceEntity.getMiniAppId(), event,wxMessage.getFailReason(),auditSuccessTime,auditFailTime) ; //自动发布已经审核通过的小程序 WxOpenService wxOpenService = MpServiceInit.getWxOpenService(); WxOpenMaService wxOpenMaService = wxOpenService.getWxOpenComponentService().getWxMaServiceByAppid(releaseAuthorizationAppid) ; wxOpenMaService.getCodeService().release(); authAppIdBy3rdIfc.saveReleaseAudited(wxOpenService.getWxOpenConfigStorage().getComponentAppId(), releaseAuthorizationAppid) ; }catch(WxErrorException e) { e.printStackTrace(); }catch (Exception e) { e.printStackTrace(); }finally { SpObserver.setDBtoInstance(); } } }catch (IOException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); }catch(Exception e) { throw e ; } return null ; } //空白定位,丢弃 if ( "LOCATION".equalsIgnoreCase(event)) { messagesIfc.saveAutoPushLocation( wxMessage, corpEntity); return null; } // //当成员进入应用时,会将该事件上报给企业 // if ("enter_agent".equalsIgnoreCase(event)) { // Item item = new Item() ; // //item.setTitle("欢迎回来!"); // item.setTitle(""); // itemList.add(item); // } //菜单事件 ,与 text调用相同事件 if ("click".equalsIgnoreCase(event)) { allItemEntity = toDoMsgData.getToDoMsgData(wxMessage.getMsgType(),wxMessage.getEventKey(), wxMessage.getContent(),wxMessage.getFromUser(),corpEntity,1); if (allItemEntity != null) { WxMpXmlOutMessage m = sendAll (wxMessage.getToUser(),wxMessage.getFromUser(),allItemEntity,msgType); if (m!=null) return m ; } Item item = new Item() ; item.setTitle("没有内容!"); itemList.add(item); } //扫码事件,提示等待 ,与 text调用相同事件 if ("scancode_waitmsg".equalsIgnoreCase(event)||"scancode_push".equalsIgnoreCase(event)) { //如果是扫码,则必须先赋值,因为在 getCallBackMsgsData 方法中调用扫码的字符串 corpEntity.setScanCode(wxMessage.getScanCodeInfo().getScanResult()); if (corpEntity.getScanCode() != null && corpEntity.getScanCode().trim().startsWith("http") && !corpEntity.getScanCode().trim().startsWith("http://weixin.qq.com/q/")) { return sendHttpUrl (wxMessage.getToUser(),wxMessage.getFromUser(), wxMessage.getScanCodeInfo().getScanResult()); } else { allItemEntity = toDoMsgData.getToDoMsgData(wxMessage.getMsgType(),wxMessage.getEventKey(), wxMessage.getContent(),wxMessage.getFromUser(),corpEntity,1); if (allItemEntity != null) { WxMpXmlOutMessage m = sendAll (wxMessage.getToUser(),wxMessage.getFromUser(),allItemEntity,msgType); if (m!=null) return m ; } } } //跳转 URL if ("VIEW".equalsIgnoreCase(event)) return null ; if ("SCAN".equalsIgnoreCase(event)) { Item item = new Item() ; item.setTitle("您已经成功关注本公众号!"); itemList.add(item); } //关注 subscribe if ("subscribe".equalsIgnoreCase(event)) { WxMpUser wxMpUser = null ; String userName = null ; MyWxMpUser myWxMpUser = new MyWxMpUser() ; try { wxMpUser = wxMpService.getUserService().userInfo(fromUser, lang); myWxMpUser.setSubscribe(wxMpUser.getSubscribe()); myWxMpUser.setOpenId(wxMpUser.getOpenId()); userName = wxMpUser.getNickname(); myWxMpUser.setNickname(userName); myWxMpUser.setSex(wxMpUser.getSex()); myWxMpUser.setLanguage(wxMpUser.getLanguage()); myWxMpUser.setCity(wxMpUser.getCity()); myWxMpUser.setProvince(wxMpUser.getProvince()); myWxMpUser.setCountry(wxMpUser.getCountry()); myWxMpUser.setHeadImgUrl(wxMpUser.getHeadImgUrl()); myWxMpUser.setSubscribeTime(wxMpUser.getSubscribeTime()); myWxMpUser.setUnionId(wxMpUser.getUnionId()); myWxMpUser.setSex(wxMpUser.getSex()); myWxMpUser.setRemark(wxMpUser.getRemark()); myWxMpUser.setGroupId(wxMpUser.getGroupId()); myWxMpUser.setTagIds(wxMpUser.getTagIds()); //介绍人 ,格式: qrscene_abcdefg String eventKey = wxMessage.getEventKey() ; if (eventKey != null && ! "".equals(eventKey)) { String qrscene = eventKey.replace("qrscene_", "") ; if (qrscene!=null&&!"".equals(qrscene)) { String qrscenes[] = qrscene.split(SettingKey.QrCodeSplitChar) ; if (qrscene != null && qrscenes.length > 0) { myWxMpUser.setReferralsCode(qrscenes[0]); } if (qrscene != null && qrscenes.length > 1) { myWxMpUser.setFromWx(qrscenes[1]); } } } Item item = null ; if (wxMpUser != null ) { mpUserIfc.saveUser(myWxMpUser, false); //保存所关注的用户信息 //读取 “关注”时需要回复的信息 allItemEntity = null ; allItemEntity = toDoMsgData.getToDoMsgData(wxMessage.getMsgType(), event, // wxMessage.getEventKey(), wxMessage.getContent(),wxMessage.getFromUser(),corpEntity,1); if (allItemEntity != null) { WxMpXmlOutMessage m = sendAll (wxMessage.getToUser(),wxMessage.getFromUser(),allItemEntity,msgType); if (m!=null) { sendTemplateMsg(myWxMpUser) ; //发送模板消息 return m ; } } else { item = new Item() ; item.setTitle("欢迎【"+ userName +"】关注本公众号!"); } sendTemplateMsg(myWxMpUser) ; //发送模板消息 } if (item != null) { itemList.add(item); } } catch (Exception e) { e.printStackTrace(); } //return itemList ; } //取消关注 unsubscribe if ("unsubscribe".equalsIgnoreCase(event)) { Date unSubscribeTime = new Date(wxMessage.getCreateTime()*1000); Integer in = messagesIfc.saveUnsubscribeEvent(wxMessage.getFromUser(),unSubscribeTime) ; Item item = new Item() ; if (in != null && in.intValue() <= 0) { content = "在ERP系统中未找到你的用户账号"; }else { content = "谢谢使用本公众号!"; } itemList.add(item); // return itemList; } //发送模板消息状态 if ("TEMPLATESENDJOBFINISH".equalsIgnoreCase(event)) { mpTemplateIfc.updateTemplateStatus(String.valueOf(wxMessage.getMsgId()), wxMessage.getStatus()) ; content = "模板消息发送状态:消息ID"+ wxMessage.getMsgId() +",发送状态:"+wxMessage.getStatus() ; itemList.add(new Item()); } } //图片,视频,语音,小视频 if ("image".equalsIgnoreCase(msgType) ||"voice".equalsIgnoreCase(msgType) ||"video".equalsIgnoreCase(msgType) ||"shortvideo".equalsIgnoreCase(msgType)) { Item item = new Item() ; //将附件保存到数据库 MpUnidEntity mpUnidEntity = messagesIfc.saveImgFile(wxMpService,wxMessage,corpEntity); item.setTitle( "收到,谢谢!") ; itemList.add(item); //转发给客服处理 String kfAccount = getKfAccount(wxMessage,mpUnidEntity.getUnid(),mpUnidEntity.getMpMsgSeq(),request,wxMpService) ; return transferCustomerService(wxMessage.getToUser(),fromUser,kfAccount); } //定位 if ("location".equalsIgnoreCase(msgType)) { content = wxMessage.getLabel(); MpUnidEntity mpUnid = messagesIfc.saveUserClickLocation( wxMessage, corpEntity); if (mpUnid != null ) { Item item = new Item() ; item.setTitle( content) ; itemList.add(item); // return itemList; } //将客户发过来的信息保存到数据库中 MyWxMpKfMsgRecord chatRecord = new MyWxMpKfMsgRecord() ; chatRecord.setWorker(""); chatRecord.setOpenid(fromUser); chatRecord.setText(content); chatRecord.setTime(wxMessage.getCreateTime()); chatRecord.setOperateCode(2001); // 2001 : 公众号收到消息 chatRecord.setMsgType(msgType); chatRecord.setAttachmentUNID(mpUnid != null ? mpUnid.getUnid():""); chatRecord.setLocationSeq(mpUnid != null?mpUnid.getMpMsgSeq():null); // Integer mpMsgSeq = kfAccountIfc.saveChatRecords(chatRecord) ; //保存到数据库 wxMessage.setPicUrl(mpUnid!=null?mpUnid.getPicUrl():""); //设置PicUrl //设置地图定位 wxMessage.setUrl(mpUnid!=null?mpUnid.getUrl():"") ; //转发给客服处理 String kfAccount = getKfAccount(wxMessage,mpUnid!=null?mpUnid.getUnid():"" ,mpMsgSeq,request,wxMpService) ; return transferCustomerService(wxMessage.getToUser(),fromUser,kfAccount); } //链接 link if ("link".equalsIgnoreCase(msgType)) { Item item = new Item() ; item.setTitle( "收到,谢谢!") ; itemList.add(item); //将客户发过来的信息保存到数据库中 MyWxMpKfMsgRecord chatRecord = new MyWxMpKfMsgRecord() ; chatRecord.setWorker(""); chatRecord.setOpenid(fromUser); chatRecord.setText("点击查看"); chatRecord.setTime(wxMessage.getCreateTime()); chatRecord.setOperateCode(2001); // 2001 : 公众号收到消息 chatRecord.setMsgType(msgType); Integer mpMsgSeq = kfAccountIfc.saveChatRecords(chatRecord) ; //保存到数据库 //转发给客服处理 String kfAccount = getKfAccount(wxMessage,"",mpMsgSeq,request,wxMpService) ; return transferCustomerService(wxMessage.getToUser(),fromUser,kfAccount); } if (itemList == null || itemList.size() == 0) { msg = ("帮助".equals(wxMessage.getContent()) ||"?".equals(wxMessage.getContent()) ||"?".equals(wxMessage.getContent()) //中文符号 ||"help".equalsIgnoreCase(wxMessage.getContent()) ||"sos".equalsIgnoreCase(wxMessage.getContent()) ? "请尝试录入:\n\n":"请求不理解,请尝试录入:\n\n"); Item helpItem = new Item() ; helpItem.setTitle(msg); itemList.add(helpItem); List KeyIDlist = messagesIfc.getMsgsKeyIds(); if (KeyIDlist != null) { for( String m:KeyIDlist){ //msg += m + "\n\n"; Item keyIdItem = new Item() ; keyIdItem.setTitle(m); itemList.add(keyIdItem); } } } NewsBuilder nb = WxMpXmlOutNewsMessage.NEWS().toUser(wxMessage.getFromUser()) .fromUser(wxMessage.getToUser()) ; for (int i = 0 ; itemList != null && i < itemList.size();i++) { nb.addArticle(itemList.get(i)); } WxMpXmlOutNewsMessage m = nb.build(); return m; // WxMpXmlOutTextMessage m // = WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUser()) // .toUser(wxMessage.getFromUser()).build(); // return m; } }; /** * 取出以前服务过的客服(或在线客服择优录取,录取条件:按空闲%确定,空闲%越大,则选中机率越高) * @return */ private String getKfAccount(WxMpXmlMessage wxMessage,String unid,Integer mpMsgSeq,HttpServletRequest request,WxMpService wxMpService) { String openId = wxMessage.getFromUser() ; //.getFromUser() ; String msgType = wxMessage.getMsgType() ; String lang = "zh_CN"; //语言 String fromUserName = "" ; MyWxMpUser myWxMpUser = mpUserIfc.getUser(openId) ; WxMpUser wxMpUser = null ; if (wxMpUser == null) { try { wxMpUser = wxMpService.getUserService().userInfo(openId, lang) ; myWxMpUser.setSubscribe(wxMpUser.getSubscribe()); myWxMpUser.setOpenId(wxMpUser.getOpenId()); myWxMpUser.setNickname(wxMpUser.getNickname()); myWxMpUser.setSex(wxMpUser.getSex()); myWxMpUser.setLanguage(wxMpUser.getLanguage()); myWxMpUser.setCity(wxMpUser.getCity()); myWxMpUser.setProvince(wxMpUser.getProvince()); myWxMpUser.setCountry(wxMpUser.getCountry()); myWxMpUser.setHeadImgUrl(wxMpUser.getHeadImgUrl()); myWxMpUser.setSubscribeTime(wxMpUser.getSubscribeTime()); myWxMpUser.setUnionId(wxMpUser.getUnionId()); myWxMpUser.setSex(wxMpUser.getSex()); myWxMpUser.setRemark(wxMpUser.getRemark()); myWxMpUser.setGroupId(wxMpUser.getGroupId()); myWxMpUser.setTagIds(wxMpUser.getTagIds()); mpUserIfc.saveUser(myWxMpUser,false); //更新用户表 t720102 } catch (WxErrorException e) { System.out.println("获取微信用户时【"+openId+"】出错,错误代码:" + e.getError().getErrorCode()+ ",错误信息:" + e.getError().getErrorMsg()+ "\n"); e.printStackTrace(); }catch(Exception e) { e.printStackTrace(); } } if (wxMpUser != null) { fromUserName = (wxMpUser.getRemark()!=null&&!"".equals(wxMpUser.getRemark()) ?wxMpUser.getRemark(): wxMpUser.getNickname()); } String kfAccountId = messagesIfc.getKfAccountByOpenId(openId) ; //List kfOnlineList= null ; WxMpKfOnlineList wxMpKfOnlineList = null ; try { wxMpKfOnlineList = wxMpService.getKefuService().kfOnlineList() ; //获取在线客服 } catch (WxErrorException e) { e.printStackTrace(); } if (! isOnline(wxMpKfOnlineList, kfAccountId)) kfAccountId = null ; //如果不在线,则设置为空值 if (kfAccountId != null && !"".equals(kfAccountId)) { // try { // wxMpService.kfSessionCreate(kfAccountId+"@"+corpEntity.getMpOrgId() ,openId,"客服代表【"+kfAccountId+"】为您提供服务") ; // } catch (WxErrorException e) { // System.out.println("创建客户【"+fromUserName + "】与客服代表【"+kfAccountId+"】会话时出错,错误代码:" // + e.getError().getErrorCode()+ ",错误信息:" + e.getError().getErrorMsg()+ "\n"); // e.printStackTrace(); // } return kfAccountId ; //如果找到了,则直接返回 } String lastKfAccountId = null ; int lastAcceptedCase = 0 ; //把最空闲的人取出来 if (wxMpKfOnlineList != null) { List kfOnlineList = wxMpKfOnlineList.getKfOnlineList(); for (int i = 0 ;kfOnlineList != null && i < kfOnlineList.size(); i ++) { kfAccountId = kfOnlineList.get(i).getAccount() ; //.getKfAccountId() ; Integer acceptedCase = kfOnlineList.get(i).getAcceptedCase() ; if (lastAcceptedCase == 0 || acceptedCase != null && lastAcceptedCase > acceptedCase.intValue()) { lastKfAccountId = kfAccountId ; } } if (lastKfAccountId != null && !"".equals(lastKfAccountId)) { // try { // wxMpService.kfSessionCreate(kfAccountId+"@"+corpEntity.getMpOrgId() ,openId,"客服代表【"+kfAccountId+"】为您提供服务") ; // } catch (WxErrorException e) { // System.out.println("创建客户【"+fromUserName + "】与客服代表【"+kfAccountId+"】会话时出错,错误代码:" // + e.getError().getErrorCode()+ ",错误信息:" + e.getError().getErrorMsg()+ "\n"); // e.printStackTrace(); // } return lastKfAccountId ; //如果找到了,则直接返回 } } String msgName = "" ; if ("text".equalsIgnoreCase(msgType)) msgName = "消息"; if ("image".equalsIgnoreCase(msgType)) msgName = "图片"; if ("voice".equalsIgnoreCase(msgType)) msgName = "语音"; if ("video".equalsIgnoreCase(msgType)) msgName = "视频"; if ("shortvideo".equalsIgnoreCase(msgType)) msgName = "短视频"; if ("link".equalsIgnoreCase(msgType)) msgName = "链接"; if ("location".equalsIgnoreCase(msgType)) msgName = "位置"; //将接收到的消息发送给所有客服代表所对应的企业号 List kfAccountList = kfAccountIfc.getKfAccount(corpEntity.getMpOrgId()); for (int i = 0 ;kfAccountList != null && i < kfAccountList.size();i++) { MyWxMpKfInfo kfAccount = kfAccountList.get(i) ; if (kfAccount.getUserId() == null || kfAccount.getUserId().equals("") ) continue ; if ("image".equalsIgnoreCase(msgType)) { MpCorpMsgEntity corpMsg = new MpCorpMsgEntity() ; corpMsg.setMsgFrom(2) ; corpMsg.setAgentId(0); corpMsg.setMsgType("news") ; corpMsg.setTitle("【"+fromUserName+"】从公众号发来的"+msgName ); corpMsg.setDescription("点击查看原图"); corpMsg.setUrl(wxMessage.getPicUrl()); corpMsg.setPicUrl(wxMessage.getPicUrl()); corpMsg.setMatId(""); corpMsg.setMatIdAttachmentUID(unid); //因为视频文件只有 mediaid , 没有url , 因此在异步发送时,再上传临时素材解决 corpMsg.setMediaId(wxMessage.getMediaId()); corpMsg.setAuthor(wxMessage.getFromUser()); corpMsg.setContentSourceUrl(""); corpMsg.setContent(wxMessage.getContent()); corpMsg.setDigest(""); corpMsg.setShowCoverPic(1); corpMsg.setToUser(kfAccount.getUserId()); corpMsg.setToParty(""); corpMsg.setToTag(""); corpMsg.setSafe(1); corpMsg.setReportUID(""); corpMsg.setRemainTimes(1); corpMsg.setMsgId(0); corpMsg.setOrgUrl("") ; corpMsg.setMpMsgSeq(mpMsgSeq); //发送企业号消息 messagesIfc.pushCorpMsgByKfAccount(corpMsg) ; } else //如果是语音,短视频等,把它转换为 news 类型发送给企业号,因为这些 文件在 企业号 中有权限限制,不处理的话,导致接收不到 if ("video".equalsIgnoreCase(msgType)||"shortvideo".equalsIgnoreCase(msgType)) { MpCorpMsgEntity corpMsg = new MpCorpMsgEntity() ; corpMsg.setMsgFrom(2) ; corpMsg.setAgentId(0); corpMsg.setMsgType("shortvideo".equalsIgnoreCase(msgType)?"video":msgType) ; corpMsg.setTitle("【"+fromUserName+"】从公众号发来的"+msgName ); corpMsg.setDescription("点击查看原"+msgName); corpMsg.setUrl(wxMessage.getPicUrl()); corpMsg.setPicUrl(wxMessage.getPicUrl()); corpMsg.setMatId(""); corpMsg.setMatIdAttachmentUID(unid); //因为视频文件只有 mediaid , 没有url , 因此在异步发送时,再上传临时素材解决 corpMsg.setMediaId(""); corpMsg.setAuthor("【"+fromUserName+"】"); corpMsg.setContentSourceUrl(""); corpMsg.setContent(wxMessage.getContent()); corpMsg.setDigest("【"+fromUserName+"】从公众号发来的"+msgName); corpMsg.setShowCoverPic(1); corpMsg.setToUser(kfAccount.getUserId()); corpMsg.setToParty(""); corpMsg.setToTag(""); corpMsg.setSafe(1); corpMsg.setReportUID(""); corpMsg.setRemainTimes(1); corpMsg.setMsgId(0); corpMsg.setOrgUrl("") ; corpMsg.setMpMsgSeq(mpMsgSeq); //发送企业号消息 messagesIfc.pushCorpMsgByKfAccount(corpMsg) ; }else //由于语音和短视频没有 title ,无法指出是谁发的,因此在接收前,先发一条 news 信息告诉接收者是谁发的。 if ("voice".equalsIgnoreCase(msgType)) { MpCorpMsgEntity corpMsgTxt = new MpCorpMsgEntity() ; corpMsgTxt.setMsgFrom(2) ; corpMsgTxt.setAgentId(0); corpMsgTxt.setMsgType("news"); //如果是文本,则转换为 news 输出 corpMsgTxt.setTitle("【"+fromUserName+"】从公众号发来的"+msgName+":" ); corpMsgTxt.setDescription(wxMessage.getContent()); corpMsgTxt.setUrl(""); corpMsgTxt.setPicUrl(wxMessage.getPicUrl()); corpMsgTxt.setMatId(""); corpMsgTxt.setMatIdAttachmentUID(""); corpMsgTxt.setMediaId(""); corpMsgTxt.setAuthor("【"+fromUserName+"】"); corpMsgTxt.setContentSourceUrl(""); corpMsgTxt.setContent("【"+msgName + "】请看下一条信息" ); corpMsgTxt.setDigest(""); corpMsgTxt.setShowCoverPic(1); corpMsgTxt.setToUser(kfAccount.getUserId()); corpMsgTxt.setToParty(""); corpMsgTxt.setToTag(""); corpMsgTxt.setSafe(1); corpMsgTxt.setReportUID(""); corpMsgTxt.setRemainTimes(1); corpMsgTxt.setMsgId(0); corpMsgTxt.setOrgUrl("") ; corpMsgTxt.setMpMsgSeq(null); //发送企业号消息 messagesIfc.pushCorpMsgByKfAccount(corpMsgTxt) ; MpCorpMsgEntity corpMsg = new MpCorpMsgEntity() ; corpMsg.setMsgFrom(2) ; corpMsg.setAgentId(0); corpMsg.setMsgType(msgType) ; corpMsg.setTitle("【"+fromUserName+"】从公众号发来的"+msgName ); corpMsg.setDescription("点击查看原"+msgName); corpMsg.setUrl(wxMessage.getPicUrl()); corpMsg.setPicUrl(wxMessage.getPicUrl()); corpMsg.setMatId(""); corpMsg.setMatIdAttachmentUID(unid); //因为视频文件只有 mediaid , 没有url , 因此在异步发送时,再上传临时素材解决 corpMsg.setMediaId(""); corpMsg.setAuthor("【"+fromUserName+"】"); corpMsg.setContentSourceUrl(""); corpMsg.setContent(wxMessage.getContent()); corpMsg.setDigest("【"+fromUserName+"】从公众号发来的"+msgName); corpMsg.setShowCoverPic(1); corpMsg.setToUser(kfAccount.getUserId()); corpMsg.setToParty(""); corpMsg.setToTag(""); corpMsg.setSafe(1); corpMsg.setReportUID(""); corpMsg.setRemainTimes(1); corpMsg.setMsgId(0); corpMsg.setOrgUrl("") ; corpMsg.setMpMsgSeq(mpMsgSeq); //发送企业号消息 messagesIfc.pushCorpMsgByKfAccount(corpMsg) ; } else if ("text".equalsIgnoreCase(msgType)) { // text MpCorpMsgEntity corpMsg = new MpCorpMsgEntity() ; corpMsg.setMsgFrom(2) ; corpMsg.setAgentId(0); corpMsg.setMsgType("text"); //如果是文本,则转换为 news 输出 corpMsg.setTitle("【"+fromUserName+"】从公众号发来的"+msgName+":" ); corpMsg.setDescription(wxMessage.getContent()); corpMsg.setUrl(""); corpMsg.setPicUrl(wxMessage.getPicUrl()); corpMsg.setMatId(""); corpMsg.setMatIdAttachmentUID(""); corpMsg.setMediaId(wxMessage.getMediaId()); corpMsg.setAuthor("【"+fromUserName+"】"); corpMsg.setContentSourceUrl(""); corpMsg.setContent("【"+fromUserName+"】从公众号发来的"+msgName+":" +"\r\n"+ wxMessage.getContent()); corpMsg.setDigest(""); corpMsg.setShowCoverPic(1); corpMsg.setToUser(kfAccount.getUserId()); corpMsg.setToParty(""); corpMsg.setToTag(""); corpMsg.setSafe(1); corpMsg.setReportUID(""); corpMsg.setRemainTimes(1); corpMsg.setMsgId(0); corpMsg.setOrgUrl("") ; corpMsg.setMpMsgSeq(mpMsgSeq); //发送企业号消息 messagesIfc.pushCorpMsgByKfAccount(corpMsg) ; } else if ("link".equalsIgnoreCase(msgType)) { // link //如果扫到了 网址 时,把网址的 title 和最大的图片 url 返回,以保证发送的 微信 news 显示有图有真相 DocumentItemEntity doc = null; try { doc = DocumentItem.getDocumentItem(wxMessage.getUrl()) ; }catch(IllegalArgumentException e ) { System.out.println("DocumentItem.getDocumentItem 提取url信息时出错:" + wxMessage.getUrl()); }catch(Exception e) { System.out.println("DocumentItem.getDocumentItem 提取url信息时出错:" + wxMessage.getUrl()); } MpCorpMsgEntity corpMsg = new MpCorpMsgEntity() ; corpMsg.setMsgFrom(2) ; corpMsg.setAgentId(0); corpMsg.setMsgType("news"); //如果是文本,则转换为 news 输出 corpMsg.setTitle("【"+fromUserName+"】从公众号发来的"+msgName+":" ); corpMsg.setDescription(doc != null&&doc.getTitle()!=null?doc.getTitle():""); corpMsg.setUrl(wxMessage.getUrl()); corpMsg.setPicUrl(doc != null&&doc.getPicUrl()!=null?doc.getPicUrl():""); corpMsg.setMatId(""); corpMsg.setMatIdAttachmentUID(""); corpMsg.setMediaId(wxMessage.getMediaId()); corpMsg.setAuthor("【"+fromUserName+"】"); corpMsg.setContentSourceUrl(""); corpMsg.setContent(doc != null&&doc.getTitle()!=null?doc.getTitle():""); corpMsg.setDigest(""); corpMsg.setShowCoverPic(1); corpMsg.setToUser(kfAccount.getUserId()); corpMsg.setToParty(""); corpMsg.setToTag(""); corpMsg.setSafe(1); corpMsg.setReportUID(""); corpMsg.setRemainTimes(1); corpMsg.setMsgId(0); corpMsg.setOrgUrl("") ; corpMsg.setMpMsgSeq(mpMsgSeq); //发送企业号消息 messagesIfc.pushCorpMsgByKfAccount(corpMsg) ; } else if ("location".equalsIgnoreCase(msgType)) { // link MpCorpMsgEntity corpMsg = new MpCorpMsgEntity() ; corpMsg.setMsgFrom(2) ; corpMsg.setAgentId(0); corpMsg.setMsgType("news"); //如果是文本,则转换为 news 输出 corpMsg.setTitle("【"+fromUserName+"】从公众号发来的"+msgName+":" ); corpMsg.setDescription(wxMessage.getLabel()); corpMsg.setUrl(wxMessage.getUrl()); corpMsg.setPicUrl(wxMessage.getPicUrl()); corpMsg.setMatId(""); corpMsg.setMatIdAttachmentUID(unid); corpMsg.setMediaId(wxMessage.getMediaId()); corpMsg.setAuthor("【"+fromUserName+"】"); corpMsg.setContentSourceUrl(""); corpMsg.setContent(wxMessage.getLabel()); corpMsg.setDigest(""); corpMsg.setShowCoverPic(1); corpMsg.setToUser(kfAccount.getUserId()); corpMsg.setToParty(""); corpMsg.setToTag(""); corpMsg.setSafe(1); corpMsg.setReportUID(""); corpMsg.setRemainTimes(1); corpMsg.setMsgId(0); corpMsg.setOrgUrl("") ; corpMsg.setMpMsgSeq(mpMsgSeq); //发送企业号消息 messagesIfc.pushCorpMsgByKfAccount(corpMsg) ; } } return null ; } /** * 判断当前客服是否在线 * @param wxMpKfOnlineList * @param kfAccountId * @return */ private boolean isOnline(WxMpKfOnlineList wxMpKfOnlineList ,String kfAccountId) { if (wxMpKfOnlineList == null || kfAccountId == null) return false ; List kfOnlineList = wxMpKfOnlineList.getKfOnlineList(); for (int i = 0 ;kfOnlineList != null && i < kfOnlineList.size();i++){ if (kfOnlineList.get(i).getAccount() != null && !"".equals(kfOnlineList.get(i).getAccount())) { String worker = kfOnlineList.get(i) .getAccount(); //.getKfAccountId() ; if (worker!= null && !"".equals(worker) && worker.equals(kfAccountId)) return true ; } } return false ; } /** * 异步执行消息发送 * @param corpEntity * @param toUser */ public void callAsync(DataSourceEntity corpEntity,String mediaid) { String asyncUrl = (corpEntity.getCorpURL() == null ? "" : corpEntity.getCorpURL()) + "/wx/MpDownloadAttachment.do" ; String queryString = SessionKey.WEIXIN_CORPID+"=" + corpEntity.getMpAppId() + "&mediaid=" + mediaid ; //HttpTookit.doGet(asyncUrl, queryString) ; //异步调用:执行,此方法会把最后面结果先输出,导致用户收到的消息顺序是乱的。 Thread t = new HttpTookitThread(asyncUrl, queryString) ; //异步调用:执行,用线程保证用户收到消息的先后顺序,方便阅读 t.start(); //启动线程 } /** * 处理扫码时,如果扫到了 网址 时,把网址的 title 和最大的图片 url 返回,以保证发送的 微信 news 显示有图有真相 * @param toUser * @param fromUser * @param url * @return */ private WxMpXmlOutMessage sendHttpUrl (String toUser,String fromUser,String url) { WxMpXmlOutMessage m = null ; DocumentItemEntity docItem = DocumentItem.getDocumentItem(url); Item item = new Item() ; item.setTitle(docItem.getTitle()); item.setDescription(null); item.setUrl(docItem.getUrl()); item.setPicUrl(docItem.getPicUrl()); m = WxMpXmlOutNewsMessage.NEWS().toUser(fromUser) .fromUser(toUser).addArticle(item).build(); return m ; } /** * 发送所有消息的主程序,包括发送文本 text, image , voice ,vedio ,file, news , mpnews * @param toUser * @param fromUser * @param allItemEntity * @return */ private WxMpXmlOutMessage sendAll (String toUser,String fromUser,AllItemEntity allItemEntity,String msgType) { WxMpXmlOutMessage m = null ; int isFound = 0 ; //微信错误: errcode=48002, errmsg=api forbidden if (allItemEntity.getText() != null && allItemEntity.getText().size() > 0) { m = sendText( toUser,fromUser,allItemEntity.getText(),msgType) ; //text isFound = 1 ; } if (isFound == 0 && allItemEntity.getImage() != null && allItemEntity.getImage().size() > 0) { m = sendImage(toUser,fromUser,allItemEntity.getImage()); //image isFound = 1 ; } if (isFound == 0 && allItemEntity.getVoice() != null && allItemEntity.getVoice().size() > 0) { m = sendVoice(toUser,fromUser,allItemEntity.getVoice()); //voice isFound = 1 ; } if (isFound == 0 && allItemEntity.getVideo() != null && allItemEntity.getVideo().size() > 0) { m = sendVideo(toUser,fromUser,allItemEntity.getVideo()) ; //video isFound = 1 ; } // 被动响应消息 不支持文件 File ,因此注释掉 ,改为异步发送文件 if (isFound == 0 && allItemEntity.getFile() != null && allItemEntity.getFile().size() > 0) { m = sendFile( toUser,fromUser,allItemEntity.getFile()); //file } if (isFound == 0 && allItemEntity.getNews() != null && allItemEntity.getNews().size() > 0) { m = sendNews( toUser,fromUser,allItemEntity.getNews()); isFound = 1 ; } if (isFound == 0 && allItemEntity.getMpNews() != null && allItemEntity.getMpNews().size() > 0) { m = sendMpNews( toUser,fromUser,allItemEntity.getMpNews()); isFound = 1 ; } toDoMsgData.saveToDoMsgData(corpEntity.getDbId(), allItemEntity); //保存到数据库 return m ; } /** * 设置为客服人员应答 * @param toUser * @param fromUser * @param textList * @return */ private WxMpXmlOutMessage transferCustomerService(String toUser,String fromUser,String kfAccount) { WxMpXmlOutTransferKefuMessage m = null ; if (kfAccount != null && ! "".equals(kfAccount)) { m = WxMpXmlOutMessage .TRANSFER_CUSTOMER_SERVICE() .kfAccount(kfAccount) .fromUser(toUser) .toUser(fromUser) .build(); } else { m = WxMpXmlOutMessage .TRANSFER_CUSTOMER_SERVICE() .fromUser(toUser) .toUser(fromUser) .build(); } return m; } /** * 发送文本消息 * @param wxMessage * @param textList * @return */ private WxMpXmlOutMessage sendText(String toUser,String fromUser,List textList,String msgType) { String content = "" ; WxMpXmlOutTextMessage m = null ; for (int i = 0;textList != null && textList.size()>0 && i imageItems) { WxMpXmlOutImageMessage m = null ; //只能发送一个图片文件, i < 1 for(int i = 0; imageItems != null && imageItems.size()>0 && i voiceItems) { WxMpXmlOutVoiceMessage m = null ; //只能发送一个图片文件, i < 1 for(int i = 0; voiceItems != null && voiceItems.size()>0 && i videoItems) { WxMpXmlOutVideoMessage m = null ; //只能发送一个图片文件, i < 1 for(int i = 0; videoItems != null && videoItems.size()>0 && i fileList) { WxMpXmlOutTextMessage m = null; m = WxMpXmlOutMessage .TEXT() .content("") //因为被动响应消息不支持 file ,所以返回空串,然后使用异步推送过去 .fromUser(toUser) .toUser(fromUser) .build(); return m ; } /** * 发送 news 消息 * @param toUser * @param fromUser * @param newsList * @return */ private WxMpXmlOutMessage sendNews(String toUser,String fromUser,List newsList) { List itemList = new ArrayList() ; WxMpXmlOutNewsMessage m = null; //只能发送8条,多余的条数异步发送,(由于微信公众号不能主动发送消息给用户,实际超过8条的记录用户永远也收不到) for(int i = 0; newsList != null && newsList.size()>0 && i 0) { NewsBuilder nb = WxMpXmlOutNewsMessage.NEWS().toUser(fromUser) .fromUser(toUser) ; for (int i = 0 ;itemList != null && i < itemList.size();i++) { nb.addArticle(itemList.get(i)); } m = nb.build(); } return m ; } /** * 发送 mpnews 消息 * @param toUser * @param fromUser * @param mpNewsList * @return */ private WxMpXmlOutMessage sendMpNews(String toUser,String fromUser,List mpNewsList) { WxMpXmlOutTextMessage m = null; m = WxMpXmlOutMessage .TEXT() .content("") //因为被动响应消息不支持 mpnews ,所以返回空串,然后使用异步推送过去 .fromUser(toUser) .toUser(fromUser) .build(); return m ; } /** * 发送模板消息 added by Johns Wang, 2018-06-10 * @param myWxMpUser */ private void sendTemplateMsg(MyWxMpUser myWxMpUser) { SettingEntity settingEntity = settingIfc.getSettingEntity(request) ; if (settingEntity.getSubscriptionNotificationTemplateId()!= null && !"".equals(settingEntity.getSubscriptionNotificationTemplateId())) { //发送给关注者本人 mpUserIfc.doSendTemplateMsg(myWxMpUser.getOpenId(), settingEntity.getSubscriptionNotificationTemplateId(), myWxMpUser.getOpenId(), new Date(), 720102, 3, myWxMpUser.getOpenId(), myWxMpUser.getNickname(), "提交", 5, null, null, "OpenId", null,myWxMpUser.getOpenId()); } if (myWxMpUser.getReferralsCode() != null && !"".equals(myWxMpUser.getReferralsCode()) && settingEntity.getSubscriptionReminderTemplateId()!= null && !"".equals(settingEntity.getSubscriptionReminderTemplateId())) { //发送给介绍人 mpUserIfc.doSendTemplateMsg(myWxMpUser.getReferralsCode(), settingEntity.getSubscriptionReminderTemplateId(), myWxMpUser.getOpenId(), new Date(), 720102, 3, myWxMpUser.getOpenId(), myWxMpUser.getNickname(), "提交", 5, null, null, "OpenId", null,myWxMpUser.getOpenId()); } } }