Force.com は、単純なテキスト メッセージの返信に加えて、写真やテキストでメッセージに返信したり、音楽やビデオに返信したり、ユーザーが送信した音声を認識したり、ユーザーの地理的位置情報を収集したり、対応するコンテンツやサービスを提供したりすることもできます。この記事では、これらのスキルを 1 つずつ説明します。その前に、すべてのサービス アカウント インターフェイス機能を備えたテスト アカウントを申請する方法を紹介する必要があります (ただし、これはグラフィック メッセージに返信する場合には必要ありません)。
テスト アカウントを申請する
個人の開発者は、サブスクリプション アカウントを申請できます。サブスクリプション アカウントでは、ユーザー メッセージの受信、ユーザーへの返信、イベントの受け入れなどの基本的なインターフェイスのみが開きます (イベント プッシュには次のものが含まれます)。またはフォロー解除、スキャン パラメーターを使用して QR コードをプッシュするための 3 つのインターフェイス (このような QR コードの生成には高度なインターフェイスが必要です)、地理的位置のレポート (通常のサブスクリプション アカウントではサポートされていません)、カスタム メニュー (通常のサブスクリプション アカウントではサポートされていません)、クリック)、ただし、カスタム メニュー、音声認識、カスタマー サービス インターフェイス、OAuth2.0 Web ページ認証、ユーザーの地理的位置情報の取得などの高度な機能はすべて、サポートするサービス アカウントが必要です。その中で、認定されたサブスクリプション アカウントはカスタム メニューをサポートします。他のプラットフォーム企業と同様に、開発者が Tencent のこれらのインターフェイスを理解し、学習できるようにするために、Tencent は昨年末、ついにテスト アカウント用のアプリケーションをオープンしました。 WeChat サブスクリプション アカウントを持っている人なら誰でも応募できます (サービス アカウントも応募できるはずですが、サービス アカウントのバックエンドがどのようなものかをまだ見ていないのでコメントしません)。
申請方法はシンプルで直接的です。WeChatバックエンド(https://mp.weixin.qq.com)に入ると、最新バージョンのバックエンドの左下に「開発者センター」があります。 2014年7月6日)」リンクをクリックすると、「クリックしてインターフェーステスト申請システムに入る」リンクが表示されます。クリックして入ると、テンセントの考えに従って申請できます。ここでは詳細は説明しません。
ログインに成功した後のアプリケーションの外観は次のとおりです。ページをスクロールすると、この QR コードが表示されます。最大 20 人のテスト ユーザーをサポートします。フォローアップが成功すると、WeChat の「サブスクリプション アカウント」フォルダーに「WeChat パブリック プラットフォーム テスト アカウント」という追加のアカウントが作成されます。 、すべてのサービス アカウントがあります。 関数:
機能
次のジョブで作業するために、ここでは最初に、その後の追加機能を容易にするために、いくつかの主要なクラスと対応する処理フレームワークをセットアップします。サポート。 IncomingMsg: さまざまなキーフィールド情報を含む、ユーザーによって送信されたメッセージクラス。WeChatNews: 写真やテキストでニュースに返信するときのニュースクラス。IncomingMsg クラスのコードは次のとおりで、絶対的な詳細を含みます。さまざまなメッセージタイプのほとんどのフィールド情報:public class IncomingMsg{ public String toUserName; public String fromUserName; public String msgType; public String picURL; public String mediaID; public String locationX; public String locationY; public String URL; public String content; public String event; public String eventKey; public String recognition; public IncomingMsg(){} public IncomingMsg(String tUN, String fUN, String mT, String pU, String mI, String lX, String lY, String u, String c, String e, String eK, String r){ this.toUserName = tUN; this.fromUserName = fUN; this.msgType = mT; this.picURL = pU; this.mediaID = mI; this.locationX = lX; this.locationY = lY; this.URL = u; this.content = c; this.event = e; this.eventKey = eK; this.recognition = r; } }
public class WeChatNews{ public String title; public String description; public String picUrl; public String url; public WeChatNews(){} public WeChatNews(String t, String d, String p, String u){ this.title = t; this.description = d; this.picUrl = p; this.url = u; } }
global static void doPost(){ //Receive message from user; RestRequest req = RestContext.request; RestResponse res = RestContext.response; string strMsg = req.requestBody.toString(); System.debug('Request Contents' + strMsg); XmlStreamReader reader = new XmlStreamReader(strMsg); String toUserName = ''; String fromUserName = ''; String msgType = ''; String picURL = ''; String mediaID = ''; String locationX = ''; String locationY = ''; String URL = ''; String content = ''; String msgID = ''; String event = ''; String eventKey = ''; String recognition = ''; while(reader.hasNext()){ if(reader.getLocalName() == 'ToUserName'){ reader.next(); if(String.isNotBlank(reader.getText())){ toUserName = reader.getText(); } } else if(reader.getLocalName() == 'FromUserName'){ reader.next(); if(String.isNotBlank(reader.getText())){ fromUserName = reader.getText(); } } else if(reader.getLocalName() == 'MsgType'){ reader.next(); if(String.isNotBlank(reader.getText())){ msgType = reader.getText(); } } else if(reader.getLocalName() == 'PicURL'){ reader.next(); if(String.isNotBlank(reader.getText())){ picURL = reader.getText(); } } else if(reader.getLocalName() == 'MediaId'){ reader.next(); if(String.isNotBlank(reader.getText())){ mediaID = reader.getText(); } } else if(reader.getLocalName() == 'Location_X'){ reader.next(); if(String.isNotBlank(reader.getText())){ locationX = reader.getText(); } } else if(reader.getLocalName() == 'Location_Y'){ reader.next(); if(String.isNotBlank(reader.getText())){ locationY = reader.getText(); } } else if(reader.getLocalName() == 'Url'){ reader.next(); if(String.isNotBlank(reader.getText())){ URL = reader.getText(); } } else if(reader.getLocalName() == 'MsgId'){ reader.next(); if(String.isNotBlank(reader.getText())){ msgID = reader.getText(); } } else if(reader.getLocalName() == 'Content'){ reader.next(); if(String.isNotBlank(reader.getText())){ content = reader.getText(); } } else if(reader.getLocalName() == 'Event'){ reader.next(); if(String.isNotBlank(reader.getText())){ event = reader.getText(); } } else if(reader.getLocalName() == 'EventKey'){ reader.next(); if(String.isNotBlank(reader.getText())){ eventKey = reader.getText(); } } else if(reader.getLocalName() == 'Recognition'){ reader.next(); if(String.isNotBlank(reader.getText())){ recognition = reader.getText(); } } reader.next(); } IncomingMsg inMsg = new IncomingMsg(toUserName, fromUserName, msgType, picURL, mediaID, locationX, locationY, URL, content, event, eventKey, recognition ); }
String rtnMsg = ''; //回复消息 if(msgType.equals('text')){ rtnMsg = handleText(inMsg); } RestContext.response.addHeader('Content-Type', 'text/plain'); RestContext.response.responseBody = Blob.valueOf(rtnMsg);
private static String handleText(IncomingMsg msg){ String keyword = msg.content; String strReply; String strResult; if(keyword.equals('文本')){ strReply = '这是个文本消息'; strResult = composeTextReply(msg, strReply); } else if(keyword.equals('图文') || keyword.equals('单图文')){ WeChatNews news = new WeChatNews('苹果WWDC2014召开在即', '2014 年似乎将成为又一个“苹果之年”,热爱和不那么热爱苹果的人都对它的一举一动保持着关注和揣测——以下是苹果 WWDC 2014 的13大看点:', 'http://a.36krcnd.com/photo/2014/4e3ae0dac4884bb91934a689b72f8f8b.png', 'http://www.36kr.com/p/212479.html'); List<wechatnews> newsList = new List<wechatnews>(); newsList.add(news); strResult = composeNewsReply(msg, newsList); } else if(keyword.equals('多图文')){ WeChatNews news1 = new WeChatNews('苹果WWDC2014召开在即', '2014年似乎将成为又一个苹果之年,热爱和不那么热爱苹果的人都对它的一举一动保持着关注和揣测——以下是苹果 WWDC 2014 的13大看点:', 'http://a.36krcnd.com/photo/2014/4e3ae0dac4884bb91934a689b72f8f8b.png', 'http://www.36kr.com/p/212479.html'); WeChatNews news2 = new WeChatNews('Facebook CEO 马克·扎克伯格再做慈善,为湾区学校捐赠 1.2 亿美元', '据 re/code消息,Facebook CEO 马克·扎克伯格与妻子Priscilla Cha (中文名陈慧娴) 计划向湾区学校捐赠 1.2 亿美元。', 'http://a.36krcnd.com/photo/2014/e64d647389bfda39131e12fa9d606bb6.jpg', 'http://www.36kr.com/p/212476.html'); WeChatNews news3 = new WeChatNews('Nokia收购Siri的同门师弟Desti,为自家地图业务HERE融入更多人工智能', 'Nokia最近收购了一家地图公司Desti,来补强自家的地图业务HERE。', 'http://a.36krcnd.com/photo/2014/25490e2b8e63ced9586f0a432eebb972.jpg', 'http://www.36kr.com/p/212484.html'); List<wechatnews> newsList = new List<wechatnews>(); newsList.add(news1); newsList.add(news2); newsList.add(news3); strResult = composeNewsReply(msg, newsList); } else if(keyword.equals('音乐')){ Map<string> music = new Map<string>(); music.put('title', '爱你的宿命'); music.put('description', '张信哲'); music.put('musicUrl', 'http://zhangmenshiting.baidu.com/data2/music/119826740/1197655931401552061128.mp3?xcode=80587c819993d49621a8dce05e5bb8c9e36664380262dc7e&song_id=119765593'); music.put('musicHQUrl', 'http://zhangmenshiting.baidu.com/data2/music/119826740/1197655931401552061128.mp3?xcode=80587c819993d49621a8dce05e5bb8c9e36664380262dc7e&song_id=119765593'); strResult = composeMusicReply(msg, music); } return strResult; }</string></string></wechatnews></wechatnews></wechatnews></wechatnews>
代码的思路应该来说比较直接,从第4行的if开始判断用户发送过来的文本是什么,根据不同的关键字来确定不同的返回内容,第一个if里将返回给用户单图文信息,这里先构造了一个WeChatNews数组,当然数组里只有一个WeChatNews对象,将这个数组交给composeNewsReply来完成最终的XML文构建;第一个else if也很类似,只不过这里的WeChatNews数组里有三条新闻,关于composeNewsReply方法的细节我们稍后介绍;最后一个else if里展示了如何回复音乐,这里我们构建了一个Map对象存储音乐的详情,并调用composeMusicReply方法来完成最终的XML文构建,同样该方法的细节稍后就会介绍到。
上面的思路应该来说还是比较清楚的,接下来介绍composeNewsReply方法的全部代码:
private static String composeNewsReply(IncomingMsg msg, List<wechatnews> newsList){ String strNews = ''; String newsTpl = '<item><title></title> <description></description><picurl></picurl><url></url></item>'; for(WeChatNews news : newsList){ String[] arguments = new String[]{news.title, news.description, news.picUrl, news.url}; strNews += String.format(newsTpl, arguments); } String strTmp = '<xml><tousername></tousername><fromusername></fromusername><createtime>1234567890</createtime><msgtype></msgtype><articlecount></articlecount><articles>' + strNews + '</articles></xml>'; String[] arguments = new String[]{msg.fromUserName, msg.toUserName, String.valueOf(newsList.size())}; String results = String.format(strTmp, arguments); return results; }</wechatnews>
了解该方法代码前先要了解回复图文信息的XML格式,关于此点可以参照腾讯公司链接:回复图文消息 ,与前文介绍到的普通文本消息大同小异,可以留意到里面有个ArticleCount字段用来指定回复的消息里能有几条图文新闻,最大是10,超过10则会无法响应;另外Article节点下方每一个item均是一条图文消息。为此,上述代码的第3行先构造一个每条新闻的模板,接着从第4行开始轮询新闻列表里的每一条新闻,并构造相应的XML文。从第8行开始构造整个图文回复的字符串模板,并在第9、10行通过相应参数将模板转换为最终的XML字符串。
再接下来介绍composeMusicReply,该方法的全部代码如下:
private static String composeMusicReply(IncomingMsg msg, Map<string> music){ String strTitle = music.get('title'); String strDesc = music.get('description'); String strURL = music.get('musicUrl'); String strHQURL = music.get('musicHQUrl'); String musicTpl = '<xml><tousername></tousername><fromusername></fromusername><createtime>12345678</createtime><msgtype></msgtype><music><title></title> <description></description><musicurl></musicurl><hqmusicurl></hqmusicurl></music></xml>'; String[] arguments = new String[]{msg.fromUserName, msg.toUserName, strTitle, strDesc, strURL, strHQURL}; String results = String.format(musicTpl, arguments); return results; }</string>
同样了解该方法要首先了解回复音乐信息的XML格式,可以参照腾讯公司链接:回复音乐消息,上面代码与前面方法比较类似,就不再赘述。(这里的Map对象也许有点多余,可以考虑是否可以和回复视频的方法整合到一起,否则不需要额外的Map对象开销,直接将标题、描述、链接等信息传给composeMusicReply方法即可)。
运行效果
完成后直接保存代码便可立即生效,回复图文、多图文、音乐的运行效果分别如下:
更多Force.com WeChat 開発シリーズはテスト アカウントに適用され、グラフィック メッセージに応答します相关文章请关注PHP中文网!