>위챗 애플릿 >위챗 개발 >WeChat 공개 플랫폼 개발 시리즈

WeChat 공개 플랫폼 개발 시리즈

高洛峰
高洛峰원래의
2018-05-14 15:28:581768검색

WeChat 공개 플랫폼 개발을 시작하려면 먼저 WeChat 플랫폼이 우리에게 무엇을 도울 수 있는지 이해해야 합니까?

공개 계정을 사용하여 http://mp.weixin.qq.com/에 로그인하고 메뉴-고급 기능-개발 모드-문서 보기를 선택하면 개발 가능한 WeChat 공개 플랫폼 기능의 현재 상태.

1. 커뮤니케이션 메커니즘

微信公众平台开发系列

공개 플랫폼의 주요 콘텐츠는

  • 보낸 공개 계정을 수락합니다. 사용자가 당신에게 메시지

  • 사용자에게 메시지에 답장

메시지를 보내고 답장이 사라지는 것은 연속적이라는 점에 유의해야 합니다. 과정은 한 번의 대화로만 가능합니다. 즉, 사용자가 말을 하지 않으면 고객에게 적극적으로 메시지를 보낼 수 없습니다(대량 메시지는 횟수에 제한이 있는 또 다른 상황입니다. 위챗 사용을 위해 유료로 신청할 수도 있습니다). CRM 플랫폼). 보내고 받는 모든 메시지는 WeChat 플랫폼을 통해 전송되어야 합니다.

2. 메시지 유형

다음은 사용자가 보낼 수 있는 메시지 유형, 즉 현재 수신되는 메시지 유형을 소개합니다.

1. 메시지 유형 수락

1.1 문자 메시지:

우리가 일반적으로 가장 많이 접하는 내용은 본문에 언급된 몇 가지 키워드를 기준으로 판단할 수 있습니다. 사용자의 의미를 파악하고 응답합니다.

1.2 사진 메시지:

현재로서는 사용자가 사진을 통해 무엇을 표현하고 싶은지 아직 파악하기 어렵습니다. 따라서 대부분의 공개 계정에서는 사진 정보를 무시하거나 수동으로 처리하는 방식을 선택합니다. 제가 말할 수 있는 것은 사진이 아름답지만 이해할 수 없다는 것뿐입니다.

1.3 위치정보 메시지:

사용자는 자신의 위치를 ​​귀하에게 전송하며 이는 대부분의 공개 계정에 중요한 정보입니다. 주변 호텔을 추천할 수 있는 호텔 예약 공용 계정 등 위치 정보를 기반으로 일부 서비스를 제공할 수 있습니다. 또 다른 추가 기능은 위치 정보를 분석하여 문자 메시지에 사용할 수 있다는 것입니다. 예를 들어, 사용자가 "난징로 보행가"를 입력하면 난징로 보행가의 해당 가맹점을 사용자에게 제공할 수 있다.

1.4 링크 메시지:

개발 모드에서는 아직 특별히 효과적인 사용 방법이 없습니다. 쇼핑이나 상담을 할 때 말하는 사람을 명확히 하기 위해 더 자주 사용될 수 있습니다.

1.5 이벤트 푸시 메시지 :

사용자가 나와 대화에 들어오면 먼저 인사 등을 할 수 있습니다. 이 메시지는 현재 버전 4.5만 지원하며 아직 개발되지 않았습니다. 예를 들어, 사용자가 세션에 들어간 후 이를 흔들면 어떻게 될까요?

2. 답장 메시지 유형

2.1 문자 메시지
사용자의 메시지에 응답하기 위해 일반적으로 가장 많이 보내는 메시지 유형입니다. 사용된 정보입니다. 문자 메시지에는 링크 주소가 포함될 수 있습니다.

微信公众平台开发系列

2.2 그래픽 메시지
그래픽 메시지는 푸시 메시지에서 흔히 볼 수 있는 메시지 형식입니다. 각 콘텐츠 항목을 클릭하면 더 자세한 정보를 볼 수 있습니다. (물론 점프할 수 없도록 링크를 비워둘 수도 있습니다.)

微信公众平台开发系列

2.3 음악뉴스
사용자에게 답장으로 음성 메시지나 음악을 제공하는 것은 많은 사용자가 선호할 것입니다.
공개 플랫폼의 커뮤니케이션 메커니즘과 메시지 유형을 이해한 후 개발 환경을 준비하기 시작했습니다.

1. 개발자 모드로 설정

로그인합니다. WeChat Work 플랫폼에서 고급 기능을 선택하고 개발 모드로 들어가서 개발자가 되세요. 아래와 같이 구성해야 합니다. URL 구성 정보는 WeChat의 백엔드 서버가 처리를 위해 사용자 메시지를 URL로 보내는 것을 의미합니다. 토큰은 귀하와 WeChat 사이의 비밀번호입니다. 메시지가 WeChat 서비스에서 전송되었는지, 귀하의 시스템을 공격하는 다른 사람에게서 전송되었는지 확인하는 데 사용됩니다.

아직 설정할 수 없습니다. 설정하는 동안 WeChat은 설정한 URL에 대해 GET 요청을 하고 인터페이스를 사용할 수 있는지 확인합니다. GET 메소드가 준비된 후에만 이를 설정할 수 있습니다.

微信公众平台开发系列

2. GET 메소드 구현

문서에서 알 수 있듯이 POST 및 GET 메소드를 구현해야 합니다. GET 방식은 WeChat 인증과 통신 인증에 사용되고, POST는 메시지 처리에 사용됩니다.

새 서블릿 HelloWeChat을 생성하고 먼저 GET 메소드를 구현합니다

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
        // TODO 为了简单起见,先不对消息来源进行校验
        response.setContentType("text/html;charset=UTF-8"); 
        PrintWriter pw = response.getWriter(); 
        String echo = request.getParameter("echostr"); 
        echo = new String(echo.getBytes("ISO-8859-1"),"UTF-8"); 
        pw.println(echo); 
    }

로컬에서는 http://localhost:8080/QiyadengWeb/HelloWeChat?echostr=hello 중국어를 사용해 볼 수 있습니다. 문제가 없으면 먼저 서버에 배포한 후 위챗에서 설정하면 됩니다. 공개 플랫폼.

3. POST 메서드 구현

POST 메서드는 먼저 WeChat 공개 플랫폼에서 보낸 XML을 수신하고 메시지 보낸 사람과 메시지 내용을 추출합니다. 더 많은 메시지 전송 콘텐츠를 위해 자체 처리 로직을 추가하고 마지막으로 이를 응답 메시지 XML로 조합하여 WeChat 공개 플랫폼에 반환할 수 있습니다.

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
        response.setContentType("text/html;charset=UTF-8"); 
        PrintWriter pw = response.getWriter(); 
        String wxMsgXml = IOUtils.toString(request.getInputStream(),"utf-8"); 
        WeChatTextMessage textMsg = null; 
        try { 
            textMsg = getWeChatTextMessage(wxMsgXml); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        StringBuffer replyMsg = new StringBuffer(); 
        if(textMsg != null){ 
            //增加你所需要的处理逻辑,这里只是简单重复消息
            replyMsg.append("您给我的消息是:"); 
            replyMsg.append(textMsg.getContent()); 
        } 
        else{ 
            replyMsg.append(":)不是文本的消息,我暂时看不懂"); 
        } 
        String returnXml = getReplyTextMessage(replyMsg.toString(), textMsg.getFromUserName()); 
        pw.println(returnXml); 
    }

디버깅과 관련하여 Fiddler가 권장하는 도구는 다음과 같습니다. 매번 디버깅을 위해 서버에 배포할 필요 없이 로컬 영역에 WeChat POST 메시지를 시뮬레이션할 수 있습니다. Fiddler의 POST 데이터를 활용하는 방법은 아래 그림에 표시된 내용을 참고하시면 됩니다.

微信公众平台开发系列

4. 배포 및 테스트

첫 번째 단계를 완료하고 공개 계정과 대화를 나누세요. 질문이 있으시면 축하드립니다 .

微信公众平台开发系列

5. 종속성 라이브러리

maven을 사용하는 학생의 경우 다음 종속성을 추가하면 됩니다. Maven이 아닌 사용자의 경우 이러한 라이브러리를 찾아 빌더 경로에 추가하면 됩니다.

<dependency> 
    <groupId>joda-time</groupId> 
    <artifactId>joda-time</artifactId> 
    <version>2.2</version> 
</dependency> 
<dependency> 
    <groupId>org.apache.commons</groupId> 
    <artifactId>commons-io</artifactId> 
    <version>1.3.2</version> 
</dependency> 
<dependency> 
    <groupId>com.thoughtworks.xstream</groupId> 
    <artifactId>xstream</artifactId> 
    <version>1.4.3</version> 
</dependency>

6. 전체 코드

package com.qiyadeng.wechat; 
import java.io.IOException; 
import java.io.PrintWriter; 
import java.util.Date; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.apache.commons.io.IOUtils; 
import com.thoughtworks.xstream.XStream; 
import com.thoughtworks.xstream.io.xml.DomDriver; 
/**
 * Servlet implementation class HelloWeChat
 */
public class HelloWeChat extends HttpServlet { 
    private static final long serialVersionUID = 1L; 
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloWeChat() { 
        super(); 
    } 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
        // TODO 为了简单起见,先不对消息来源进行校验
        response.setContentType("text/html;charset=UTF-8"); 
        PrintWriter pw = response.getWriter(); 
        String echo = request.getParameter("echostr"); 
        echo = new String(echo.getBytes("ISO-8859-1"),"UTF-8"); 
        pw.println(echo); 
    } 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
        response.setContentType("text/html;charset=UTF-8"); 
        PrintWriter pw = response.getWriter(); 
        String wxMsgXml = IOUtils.toString(request.getInputStream(),"utf-8"); 
        WeChatTextMessage textMsg = null; 
        try { 
            textMsg = getWeChatTextMessage(wxMsgXml); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        StringBuffer replyMsg = new StringBuffer(); 
        if(textMsg != null){ 
            //增加你所需要的处理逻辑,这里只是简单重复消息
            replyMsg.append("您给我的消息是:"); 
            replyMsg.append(textMsg.getContent()); 
        } 
        else{ 
            replyMsg.append(":)不是文本的消息,我暂时看不懂"); 
        } 
        String returnXml = getReplyTextMessage(replyMsg.toString(), textMsg.getFromUserName()); 
        pw.println(returnXml); 
    } 
    private WeChatTextMessage getWeChatTextMessage(String xml){ 
        XStream xstream = new XStream(new DomDriver()); 
        xstream.alias("xml", WeChatTextMessage.class); 
        xstream.aliasField("ToUserName", WeChatTextMessage.class, "toUserName"); 
        xstream.aliasField("FromUserName", WeChatTextMessage.class, "fromUserName"); 
        xstream.aliasField("CreateTime", WeChatTextMessage.class, "createTime"); 
        xstream.aliasField("MsgType", WeChatTextMessage.class, "messageType"); 
        xstream.aliasField("Content", WeChatTextMessage.class, "content"); 
        xstream.aliasField("MsgId", WeChatTextMessage.class, "msgId"); 
        WeChatTextMessage wechatTextMessage = (WeChatTextMessage)xstream.fromXML(xml);  
        return wechatTextMessage; 
    } 
    private String getReplyTextMessage(String content, String weChatUser){ 
        WeChatReplyTextMessage we = new WeChatReplyTextMessage(); 
        we.setMessageType("text"); 
        we.setFuncFlag("0"); 
        we.setCreateTime(new Long(new Date().getTime()).toString()); 
        we.setContent(content); 
        we.setToUserName(weChatUser); 
        we.setFromUserName("shanghaiweather");//TODO 你的公众帐号微信号
        XStream xstream = new XStream(new DomDriver());  
        xstream.alias("xml", WeChatReplyTextMessage.class); 
        xstream.aliasField("ToUserName", WeChatReplyTextMessage.class, "toUserName"); 
        xstream.aliasField("FromUserName", WeChatReplyTextMessage.class, "fromUserName"); 
        xstream.aliasField("CreateTime", WeChatReplyTextMessage.class, "createTime"); 
        xstream.aliasField("MsgType", WeChatReplyTextMessage.class, "messageType"); 
        xstream.aliasField("Content", WeChatReplyTextMessage.class, "content"); 
        xstream.aliasField("FuncFlag", WeChatReplyTextMessage.class, "funcFlag"); 
        String xml =xstream.toXML(we); 
        return xml; 
    } 
}

위치 식별은 실제 응용 프로그램, 특히 많은 가맹점에서 자주 사용되는 메시지로 사용자에게 위치 정보를 이해하여 위치. 쇼핑몰의 제품이나 추천. 사용자는 두 가지 유형의 메시지를 보낼 수 있습니다:

1. WeChat 지리적 위치 정보

2. 도로 이름, 랜드마크 건물 또는 쇼핑몰 이름

1. WeChat 지리 위치 메시지

WeChat 위치 메시지에는 어떤 정보가 포함되어 있는지 알아봅시다

<xml> 
<ToUserName><![CDATA[toUser]]></ToUserName> 
<FromUserName><![CDATA[fromUser]]></FromUserName> 
<CreateTime>1351776360</CreateTime> 
<MsgType><![CDATA[location]]></MsgType> 
<Location_X>23.134521</Location_X> 
<Location_Y>113.358803</Location_Y> 
<Scale>20</Scale> 
<Label><![CDATA[位置信息]]></Label> 
<MsgId>1234567890123456</MsgId> 
</xml>

포함되는 주요 정보는 경도, 위도 및 라벨 위치입니다. 라벨에 기재된 위치 정보를 기반으로 사용자에게 해당 서비스를 제공할 수 있습니다. 사용자의 경도, 위도 정보를 바탕으로 최신 제품이나 지역별 제품을 제공할 수도 있습니다.

微信公众平台开发系列

먼저 WeChat의 지리적 위치 정보를 기반으로 WeChatLocationMessage 클래스를 정의하고 Xml을 WeChatLocationMessage 객체로 변환합니다.

public class WeChatLocationMessage { 
    private String toUserName; 
    private String fromUserName; 
    private String createTime; 
    private String msgType; 
    private String locationx; 
    private String localtiony; 
    private String scale; 
    private String label; 
    private String msgId; 
    public static WeChatLocationMessage getWeChatLocationMessage(String xml){ 
        XStream xstream = new XStream(new DomDriver()); 
        WeChatLocationMessage  message = null; 
        xstream.alias("xml", WeChatLocationMessage.class); 
        xstream.aliasField("ToUserName", WeChatLocationMessage.class, "toUserName"); 
        xstream.aliasField("FromUserName", WeChatLocationMessage.class, "fromUserName"); 
        xstream.aliasField("CreateTime", WeChatLocationMessage.class, "createTime"); 
        xstream.aliasField("MsgType", WeChatLocationMessage.class, "msgType"); 
        xstream.aliasField("Location_X", WeChatLocationMessage.class, "locationx"); 
        xstream.aliasField("Location_Y", WeChatLocationMessage.class, "localtiony"); 
        xstream.aliasField("Scale", WeChatLocationMessage.class, "scale"); 
        xstream.aliasField("Label", WeChatLocationMessage.class, "label"); 
        xstream.aliasField("MsgId", WeChatLocationMessage.class, "msgId"); 
        message = (WeChatLocationMessage)xstream.fromXML(xml); 
        return message; 
    } 
//getter and setter
}

이 글에서는 Baidu의 지도 API를 사용하여 위치를 찾습니다. 가장 가까운 은행을 예로 들어보겠습니다.

public String getPalace(String query,String lat,String lng) throws ClientProtocolException, IOException{ 
    HttpClient httpClient = new DefaultHttpClient(); 
    String url = palceRequestUrl(query,lat,lng); 
    logger.log(Level.INFO, url); 
    HttpGet httpget = new HttpGet(url); 
    ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
    String responseBody = httpClient.execute(httpget, responseHandler); 
    logger.log(Level.INFO,"baidu response:"+responseBody); 
    return responseBody; 
} 

public String palceRequestUrl(String query,String lat,String lng) throws UnsupportedEncodingException { 
    String url = WeChatConstant.BASEURL + "place/search?query=" + URLEncoder.encode(query,"UTF-8") + "&key="
            + WeChatConstant.MAPKEY +"&location="+lat+","+lng +"&radius=2000"+"&output=" + WeChatConstant.OUTPUTFORMAT; 
    return url; 
}

출력 결과

<PlaceSearchResponse> 
    <status>OK</status> 
    <results> 
        <result> 
            <name>中国工商银行东长安街支行</name> 
            <location> 
                <lat>39.915891</lat> 
                <lng>116.41867</lng> 
            </location> 
            <address>东城区东长安街1号东方广场西三办公楼1楼</address> 
            <uid>a025683c73033c35a21de987</uid> 
            <detail_url>http://api.map.baidu.com/place/detail?uid=a025683c73033c35a21de987&amp;amp;output=html&amp;amp;source=placeapi
            </detail_url> 
            <tag>银行,王府井/东单</tag> 
        </result> 
      </results> 
</PlaceSearchResponse>

다음으로 바이두 지도에 반영된 최근 위치 정보가 위챗 사용자에게 그래픽 메시지

    public static String getWeChatReplyNewsMessageByBaiduPlace(List<BaiduPlaceResponse> placeList, double lat, double lng,String userName, int size){ 
        WeChatReplyNewsMessage newsMessage = new WeChatReplyNewsMessage(); 
        List<Item> items = new ArrayList<Item>(); 
        StringBuffer strBuf = new StringBuffer(); 
        logger.log(Level.INFO,"placeList count="+placeList.size()); 
        newsMessage.setItems(items); 
        if(placeList.size()>size){ 
            newsMessage.setArticleCount(size); 
        } 
        else{ 
            newsMessage.setArticleCount(placeList.size()); 
        } 
        logger.log(Level.INFO,"article count="+newsMessage.getArticleCount()); 
        newsMessage.setCreateTime(new Date().getTime()+""); 
        newsMessage.setMsgType("news"); 
        newsMessage.setFuncFlag("0"); 
        newsMessage.setToUserName(userName); 
        newsMessage.setFromUserName(WeChatConstant.FROMUSERNAME); 
        for(int i = 0;i <newsMessage.getArticleCount();i++){ 
            BaiduPlaceResponse place = placeList.get(i); 
            Double distance = GeoUtil.DistanceOfTwoPoints(Double.valueOf(place.getLng()), Double.valueOf(place.getLat()), lng, lat, GaussSphere.Beijing54); 
            Item item = new Item(); 
            item.setTitle(place.getName()+"["+distance+"米]"+"\n"+place.getAddress()+"\n"+place.getTelephone()); 
            item.setPicUrl(""); 
            item.setUrl(place.getDetailUrl()); 
            item.setDescription(""); 
            items.add(item); 
        } 
logger.log(Level.INFO,"newMessage="+newsMessage.toString()); 
        strBuf = strBuf.append(getWeChatNewsMessage(newsMessage)); 
        return strBuf.toString(); 
    } 
    public static String getWeChatNewsMessage(WeChatReplyNewsMessage newsMessage){ 
        XStream xstream = new XStream(new DomDriver()); 
        xstream.alias("xml", WeChatReplyNewsMessage.class); 
        xstream.aliasField("ToUserName", WeChatReplyNewsMessage.class, "toUserName"); 
        xstream.aliasField("FromUserName", WeChatReplyNewsMessage.class, "fromUserName"); 
        xstream.aliasField("CreateTime", WeChatReplyNewsMessage.class, "createTime"); 
        xstream.aliasField("MsgType", WeChatReplyNewsMessage.class, "msgType"); 
        xstream.aliasField("ArticleCount", WeChatReplyNewsMessage.class, "articleCount"); 
        xstream.aliasField("Content", WeChatReplyNewsMessage.class, "content"); 
        xstream.aliasField("FuncFlag", WeChatReplyNewsMessage.class, "funcFlag"); 
        xstream.aliasField("Articles", WeChatReplyNewsMessage.class, "items"); 
        xstream.alias("item", Item.class); 
        xstream.aliasField("Title", Item.class, "title"); 
        xstream.aliasField("Description", Item.class, "description"); 
        xstream.aliasField("PicUrl", Item.class, "picUrl"); 
        xstream.aliasField("Url", Item.class, "url"); 
        return xstream.toXML(newsMessage); 
    }

형식으로 표시됩니다. 2. 도로명, 랜드마크 건물이나 쇼핑몰 이름

도로명, 랜드마크 건물 등의 정보는 제3자 지도정보를 통해 입력된 위치정보의 경도와 위도를 파악하는 방식입니다.

이 기사에서는 Baidu Map API를 사용하여 찾고 있는 위치의 경도와 위도를 결정합니다.

경도와 위도를 판단한 후 문제는 첫 번째 메시지 유형과 동일해지며, 경도와 위도에 따라 해당 처리가 이루어집니다.

微信公众平台开发系列

public String getGeoCode(String query) throws ClientProtocolException, IOException{ 
        HttpClient httpClient = new DefaultHttpClient(); 
        String url = geoCodeRequestUrl(query); 
        logger.log(Level.INFO, url); 
        HttpGet httpget = new HttpGet(url); 
        ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
        String responseBody = httpClient.execute(httpget, responseHandler); 
        logger.log(Level.INFO,"baidu response:"+responseBody); 
        return responseBody; 
    } 
    public String geoCodeRequestUrl(String query) throws UnsupportedEncodingException{ 
        String url = WeChatConstant.BASEURL + "geocoder?address=" + URLEncoder.encode(query,"UTF-8") + "&key="
                + WeChatConstant.MAPKEY + "&output=" + WeChatConstant.OUTPUTFORMAT; 
        return url; 
    }

WeChat 공개 플랫폼 개발 시리즈 관련 기사를 더 보려면 PHP 중국어 웹사이트를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.