JAVA 는 springMVC 방식 의 위 챗 접속 을 실현 하고 메시지 자동 답장 인 스 턴 스 를 실현 합 니 다.
1.사고방식
위 챗 접속:사용자 메시지 와 개발 자가 필요 로 하 는 이벤트 푸 시 는 위 챗 서버 를 통 해 요청 을 합 니 다.공공 플랫폼 에 설 치 된 서버 url 주 소 를 전달 합 니 다.위 챗 측은 signature,timestamp,nonce,echostr 네 개의 매개 변 수 를 가 져 옵 니 다.저 희 는 공공 플랫폼 에 설 치 된 token 과 전 달 된 timestamp 를 연결 합 니 다.nonce 는 SHA 1 암호 화 를 한 후 signature 와 일치 하 며,ture 설명 을 되 돌려 접속 에 성 공 했 습 니 다.
메시지 답장:사용자 가 공중 번호 로 메 시 지 를 보 낼 때 위 챗 서버 는 사용자 메 시 지 를 xml 형식 으로 POST 를 통 해 우리 가 설정 한 서버 에 대응 하 는 인터페이스 에 요청 합 니 다.우리 가 해 야 할 일 은 메시지 유형 등에 따라 해당 하 는 논리 적 처 리 를 하고 마지막 반환 결 과 를 xml 형식 으로 위 챗 서버 에 반환 하 는 것 입 니 다.위 챗 측 이 사용자 에 게 전달 하 는 이러한 과정.
1.퍼 블 릭 플랫폼 설정
2.Controller
@Controller
@RequestMapping("/wechat")
publicclass WechatController {
@Value("${DNBX_TOKEN}")
private String DNBX_TOKEN;
private static final Logger LOGGER = LoggerFactory.getLogger(WechatController.class);
@Resource
WechatService wechatService;
/**
*
* @param wc
* @return
* @throws IOException
*/
@RequestMapping(value="/connect",method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
publicvoid connectWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException{
// 、 UTF-8( )
request.setCharacterEncoding("UTF-8"); // POST UTF-8 , , ;
response.setCharacterEncoding("UTF-8"); // ( ) , UTF-8, ;boolean isGet = request.getMethod().toLowerCase().equals("get");
PrintWriter out = response.getWriter();
try {
if (isGet) {
String signature = request.getParameter("signature");//
String timestamp = request.getParameter("timestamp");//
String nonce = request.getParameter("nonce");//
String echostr = request.getParameter("echostr");//
// signature , echostr, , if (SignUtil.checkSignature(DNBX_TOKEN, signature, timestamp, nonce)) {
LOGGER.info("Connect the weixin server is successful.");
response.getWriter().write(echostr);
} else {
LOGGER.error("Failed to verify the signature!");
}
}else{
String respMessage = " !";
try {
respMessage = wechatService.weixinPost(request);
out.write(respMessage);
LOGGER.info("The request completed successfully");
LOGGER.info("to weixin server "+respMessage);
} catch (Exception e) {
LOGGER.error("Failed to convert the message from weixin!");
}
}
} catch (Exception e) {
LOGGER.error("Connect the weixin server is error.");
}finally{
out.close();
}
}
}
3.서명 검증 검사 서명위의 contrller 에서 볼 수 있 듯 이 저 는 도구 류 SignUtil 을 봉 하여 안에 있 는 checkSignature 라 는 이름 으로 네 개의 값 을 전 달 했 습 니 다.DNBXTOKEN, signature, timestamp, nonce。이 과정 은 매우 중요 하 다.사실 우 리 는 위 챗 이 보 내 온 값 을 복호화 하 는 과정 으로 이해 할 수 있다.많은 대형 프로젝트 의 모든 인 터 페 이 스 는 안전성 을 확보 하기 위해 이런 검증 과정 이 있 을 것 이다.DNBX_TOKEN 저희 가 위 챗 공식 플랫폼 에 설정 한 token 문자열 입 니 다.비밀 로 하 겠 습 니 다!다른 세 가 지 는 모두 위 챗 서버 에서 get 요청 을 보 내 온 매개 변수 입 니 다.저 희 는 sha 1 암호 화 를 진행 합 니 다.
public class SignUtil {
/**
*
*
* @param token token, env.properties
* @param signature sha1
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String token,String signature, String timestamp, String nonce) {
String[] arr = new String[] { token, timestamp, nonce };
// token、timestamp、nonce
Arrays.sort(arr);
// sha1
String tmpStr = SHA1.encode(arr[0] + arr[1] + arr[2]);
// sha1 signature ,
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
}
SHA1:
/**
* (JAVA) SDK
*
* SHA1
*
* @author helijun 2016/06/15 19:49
*/
public final class SHA1 {
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
* Takes the raw bytes from the digest and formats them correct.
*
* @param bytes the raw bytes from the digest.
* @return the formatted bytes.
*/
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
//
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
public static String encode(String str) {
if (str == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(str.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
공공 플랫폼 에 저장 을 제출 하고 녹색 힌트 인'접속 성공'을 본 후에 위 챗 접속 을 완료 한 것 을 축하합니다.이 과정 은 암호 화 알고리즘 의 대소 문 자 를 주의해 야 합 니 다.만약 에 접속 이 성공 하지 못 하면 대부분 암호 화 알고리즘 문제 이 므 로 검 사 를 많이 해 야 합 니 다.4.메시지 자동 답장 서비스 구현
/**
*
*
* @param request
* @return
*/
public String weixinPost(HttpServletRequest request) {
String respMessage = null;
try {
// xml
Map<String, String> requestMap = MessageUtil.xmlToMap(request);
// (open_id)
String fromUserName = requestMap.get("FromUserName");
//
String toUserName = requestMap.get("ToUserName");
//
String msgType = requestMap.get("MsgType");
//
String content = requestMap.get("Content");
LOGGER.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType);
//
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
// , ,
if(content.equals("xxx")){
}
//
TextMessage text = new TextMessage();
text.setContent("the text is" + content);
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setCreateTime(new Date().getTime() + "");
text.setMsgType(msgType);
respMessage = MessageUtil.textMessageToXml(text);
} /*else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {//
String eventType = requestMap.get("Event");//
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {//
respContent = " xxx !";
return MessageResponse.getTextMessage(fromUserName , toUserName , respContent);
} else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {//
String eventKey = requestMap.get("EventKey");// KEY , KEY
logger.info("eventKey is:" +eventKey);
return xxx;
}
}
// 2015-3-30
else if(msgType.equals("voice"))
{
String recvMessage = requestMap.get("Recognition");
//respContent = " :"+recvMessage;
if(recvMessage!=null){
respContent = TulingApiProcess.getTulingResult(recvMessage);
}else{
respContent = " , ?";
}
return MessageResponse.getTextMessage(fromUserName , toUserName , respContent);
}
//
else if(msgType.equals("pic_sysphoto"))
{
}
else
{
return MessageResponse.getTextMessage(fromUserName , toUserName , " ");
}*/
//
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
String eventType = requestMap.get("Event");//
//
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
TextMessage text = new TextMessage();
text.setContent(" ,xxx");
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setCreateTime(new Date().getTime() + "");
text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
respMessage = MessageUtil.textMessageToXml(text);
}
// TODO ,
else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {//
}
//
else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
String eventKey = requestMap.get("EventKey");// KEY , KEY
if (eventKey.equals("customer_telephone")) {
TextMessage text = new TextMessage();
text.setContent("0755-86671980");
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setCreateTime(new Date().getTime() + "");
text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
respMessage = MessageUtil.textMessageToXml(text);
}
}
}
}
catch (Exception e) {
Logger.error("error......")
}
return respMessage;
}
먼저 코드 를 붙 이 고 위 와 같이 대부분 주석 이 있 으 며 기본 적 인 의 미 를 한 번 읽 어도 더 설명 할 필요 가 없다.특히 주의해 야 할 점 이 있 습 니 다.
위 에 빨간색 으로 표 시 된 from User Name 과 toUser Name 은 정반 대 입 니 다.이것 도 구덩이 중 하나 입 니 다.제 가 오랫동안 조정 한 것 을 기억 합 니 다.문제 가 없 으 면서 도 통 하지 않 았 습 니 다.마지막 에 이 두 개 를 바 꾸 면 소식 을 받 았 습 니 다!사실 뒤 돌아 보 니 맞 는 것 같 아 요.위 챗 서버 에 되 돌아 갈 때 그 자체 의 캐릭터 가 바 뀌 었 기 때문에 발송 과 수신 자 도 반대 일 거 예요.
5.MessageUtil
public class MessageUtil {
/**
* :
*/
public static final String RESP_MESSAGE_TYPE_TEXT = "text";
/**
* :
*/
public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
/**
* :
*/
public static final String RESP_MESSAGE_TYPE_NEWS = "news";
/**
* :
*/
public static final String REQ_MESSAGE_TYPE_TEXT = "text";
/**
* :
*/
public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
/**
* :
*/
public static final String REQ_MESSAGE_TYPE_LINK = "link";
/**
* :
*/
public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
/**
* :
*/
public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
/**
* :
*/
public static final String REQ_MESSAGE_TYPE_EVENT = "event";
/**
* :subscribe( )
*/
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
/**
* :unsubscribe( )
*/
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
/**
* :CLICK( )
*/
public static final String EVENT_TYPE_CLICK = "CLICK";
}
여 기 는 프로그램의 가 독성,확장 성 을 위해 서 저 는 패 키 지 를 만 들 었 습 니 다.몇 개의 상수 와 위 챗 에서 보 내 온 일부 매개 변 수 를 자바 bean 의 지속 적 인 대상 으로 포장 하고 핵심 코드 는 위 와 같 습 니 다.xml 와 map 사이 의 전환 에 중점 을 두 었 습 니 다.
사실 이 문 제 는 위 챗 이 xml 로 통신 한 탓 으로 돌 릴 수 있 습 니 다.우 리 는 평소에 json 을 사용 하기 때문에 짧 은 시간 안에 적응 하지 못 할 수도 있 습 니 다.
1.jar 패키지 도입
<!-- xml -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
2.xml 전 맵 집합 대상
/**
* xml map
* @param request
* @return
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException{
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
InputStream ins = null;
try {
ins = request.getInputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
Document doc = null;
try {
doc = reader.read(ins);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
return map;
} catch (DocumentException e1) {
e1.printStackTrace();
}finally{
ins.close();
}
return null;
}
3.텍스트 메시지 대상 을 xml 로 변환
/**
* xml
*
* @param textMessage
* @return xml
*/
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
지금까지 큰 성 과 를 거 두 었 습 니 다.이 럴 때 공중 번호 에서'테스트'를 보 내 보 세 요.당신 은 위 챗 으로 답장 하 는'the text is 테스트'를 받 을 수 있 습 니 다.이것 도 위 코드 에서 한 답장 처리 입 니 다.물론 당신 의 상상 을 발휘 하여 그 로 하여 금 당신 이 하고 싶 은 모든 일 을 할 수 있 습 니 다.예 를 들 어 날 씨 를 확인 하고 규정 을 위반 하 는 등..이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
springmvc application/octet-stream problemmistake: Source code: Solution: Summarize: application/octet-stream is the original binary stream method. If the convers...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.