ホームページ > 記事 > WeChat アプレット > WeChat の開発受動的応答とファイルのアップロードとダウンロード
第 5 章では、ユーザーから送信されたメッセージの処理方法について説明しました。この章では、ユーザーのリクエストに応答する方法について説明します。初心者はこのタイトルを見て混乱するでしょう。WeChat のインターフェースは次のようなものです。写真、音楽、音声などに返信する前に、メディア ファイルを WeChat サーバーにアップロードする必要があります。使用できます。このアプローチでどのような考慮事項があるのかわかりません。また、ユーザーへのメッセージに返信するときに、カスタマー サービス インターフェイスとグループ送信インターフェイスによって送信されるメッセージ本文の形式は実際には異なります。これらのインターフェースは同じ人によって書かれたものではないと推定されており、コードは統一されていませんでした。私たち負け組の開発者は文句を言うしかありません。
アップロードとダウンロードのインターフェイスについて説明する前に、まず access_token の取得方法について説明する必要があります。 WeChat インターフェースの開発プロセスでは、公式アカウントのグローバルに固有のチケットである access_token が重要です。公式アカウントは各インターフェースを呼び出すときに access_token を使用する必要があります。開発者はそれを適切に保存する必要があります。 access_token ストレージ用に少なくとも 512 文字のスペースを予約する必要があります。 access_token の有効期間は現在 2 時間であり、定期的に取得を繰り返すと最後の access_token が無効になります。公式アカウントに対して同時に有効な access_token は 1 つだけであるため、開発者は access_token の有効期限が切れる前に access_token を更新する必要があることに注意してください。更新プロセス中、パブリック プラットフォーム バックエンドは、更新の短い時間内に古いアクセス トークンと新しいアクセス トークンの両方が利用可能になることを保証し、これによりサードパーティ サービスのスムーズな移行が保証されます。
パブリック アカウントは、AppID と AppSecret を使用してこのインターフェイスを呼び出し、access_token を取得できます。 AppID と AppSecret は、WeChat パブリック プラットフォームの公式 Web サイトの開発者センター ページから取得できます (開発者になっていて、アカウントに異常なステータスがないことが必要です)。以下に示すように:
access_token を取得するためのインターフェイス アドレスは次のとおりです:
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
将appid和secret替换成你自己的。
このアドレスに get リクエストを送信すると、返されるデータは次のとおりです:
{"access_token":"eEd6dhp0s24JfWwDyGBbrvJxnhqHTSYZ8MKdQ7MuCGBKxAjHv-tEIwhFZzn102lGvIWxnjZZreT6C1NCT9fpS7NREOkEX42yojVnqKVaicg","expires_in":7200}
我们只需解析这个json,即可获取到我们所需的access_token.代码如下:
AccessToken实体类:
public class AccessToken { public string token { get; set; } public DateTime expirestime { get; set; } }
アクセス トークンを取得します
/// <summary> /// 获取access token /// </summary> /// <param name="appid">第三方用户唯一凭证</param> /// <param name="secret">第三方用户唯一凭证密钥,即appsecret</param> /// <returns>AccessToken对象,expirestime是过期时间</returns> public static AccessToken GetAccessToken(string appid, string secret) { try { string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, secret); string retdata = Utils.HttpGet(url); if (retdata.Contains("access_token")) { JObject obj = (JObject)JsonConvert.DeserializeObject(retdata); string token = obj.Value<string>("access_token"); int expirestime = obj.Value<int>("expires_in"); return new AccessToken { token = token, expirestime = DateTime.Now.AddSeconds(expirestime) }; } else { WriteBug(retdata);//写错误日志 } return null; } catch (Exception e) { WriteBug(e.ToString());//写错误日志 return null; } }
access_token が正常に取得された後取得したら、マルチメディア ファイルのアップロードとダウンロードについて話しましょう。公式アカウントがインターフェースを使用する際、マルチメディアファイルやマルチメディアメッセージの取得や呼び出しなどの操作がmedia_idを通じて行われると公式が言っていました(読み取りについてはあまり詳しくないので、なぜURLが使えないのか分かりませんが、ただし、送信する前にサーバーにアップロードする必要はありません。)このインターフェイスを通じて、公開アカウントはマルチメディア ファイルをアップロードまたはダウンロードできます。ただし、サーバー リソースを節約するために、各マルチメディア ファイル (media_id) は、アップロードされて WeChat サーバーに送信されてから 3 日後に自動的に 削除 されることに注意してください。
マルチメディアをアップロードするためのインターフェイス アドレスは次のとおりです:
file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
ここで、access_token は呼び出し側インターフェイスの資格情報、type は画像、音声、video (ビデオ) および thumbnail (親指) を含むメディア ファイルのタイプです
注:
アップロードされるマルチメディア ファイルには、次のような形式とサイズの制限があります:
写真 (画像): 1M、JPG 形式をサポート
音声 (音声): 2M、再生長さ 60 秒以下、サポートAMRMP3形式
Video (ビデオ): 10MB、MP4形式をサポート
Thumb (サム): 64KB、JPG形式をサポート
メディアファイルはバックグラウンドで3日間保存されます、つまりmedia_id 3日後に期限切れになります。
呼び出しの便宜上、メディア ファイルのタイプを列挙として定義します。コードは次のとおりです:
public enum MediaType { /// <summary> /// 图片(WeChat の開発受動的応答とファイルのアップロードとダウンロード): 1M,支持JPG格式 /// </summary> WeChat の開発受動的応答とファイルのアップロードとダウンロード, /// <summary> /// 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式 /// </summary> voice, /// <summary> /// 视频(video):10MB,支持MP4格式 /// </summary> video, /// <summary> /// 缩略图(thumb):64KB,支持JPG格式 /// </summary> thumb }
次に、戻り値のタイプを定義します:
public class UpLoadInfo { /// <summary> /// 媒体文件类型,分别有图片(WeChat の開発受動的応答とファイルのアップロードとダウンロード)、语音(voice)、视频(video)和缩略图(thumb,主要用于视频与音乐格式的缩略图) /// </summary> public string type { get; set; } /// <summary> /// 媒体文件上传后,获取时的唯一标识 /// </summary> public string media_id { get; set; } /// <summary> /// 媒体文件上传时间戳 /// </summary> public string created_at { get; set; } }
最後に、WebClient クラスを使用してファイルをアップロードします
/// <summary> /// 微信上传多媒体文件 /// </summary> /// <param name="filepath">文件绝对路径</param> public static ReceiveModel.UpLoadInfo WxUpLoad(string filepath, string token, MediaType mt) { using (WebClient client = new WebClient()) { byte[] b = client.UploadFile(string.Format("http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}", token, mt.ToString()), filepath);//调用接口上传文件 string retdata = Encoding.Default.GetString(b);//获取返回值 if (retdata.Contains("media_id"))//判断返回值是否包含media_id,包含则说明上传成功,然后将返回的json字符串转换成json { return JsonConvert.DeserializeObject<UpLoadInfo>(retdata); } else {//否则,写错误日志 WriteBug(retdata);//写错误日志 return null; } } }
この時点で、メッセージへの返信について話す前に、2 つの基本的なサポート インターフェイスが挿入されています。あなたの整理と要約の能力はひどいので、ご容赦ください。ご質問がございましたら、メッセージを残して私にご連絡ください。 メッセージへの返信について正式に話し始めましょう。以下の内容を読む際には、第4章、第5章と合わせてお読みください。
前の 2 つの章では、ユーザーから送信されたメッセージの受信と処理について説明し、受信したメッセージの種類に関係なく、ユーザーのリクエストに応答するメソッドを呼び出すことができる必要があります。 、ユーザーは、要求されたメソッドを基本クラスにカプセル化する必要があると応答します。公開アカウントが返信できるメッセージの種類とメッセージの形式を簡単に見てみましょう。
注:
次の状況が発生すると、WeChat は公式アカウント セッションでユーザーに「この公式アカウントは一時的にサービスを提供できません。後でもう一度お試しください」というシステム プロンプトを発行します:
1、开发者在5秒内未回复任何内容 2、开发者回复了异常数据,比如JSON数据等
<xml><ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName><FromUserName><![CDATA[开发者微信号]]></FromUserName><CreateTime>消息创建时间 (整型)</CreateTime><MsgType><![CDATA[WeChat の開発受動的応答とファイルのアップロードとダウンロード]]></MsgType><Content><![CDATA[回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)]]></Content></xml>
<xml><ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName><FromUserName><![CDATA[开发者微信号]]></FromUserName><CreateTime>消息创建时间 (整型)</CreateTime><MsgType><![CDATA[WeChat の開発受動的応答とファイルのアップロードとダウンロード]]></MsgType><Image><MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId></Image></xml>
<xml><ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName><FromUserName><![CDATA[开发者微信号]]></FromUserName><CreateTime>消息创建时间 (整型)</CreateTime><MsgType><![CDATA[voice]]></MsgType><Voice><MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId></Voice></xml>
<xml><ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName><FromUserName><![CDATA[开发者微信号]]></FromUserName><CreateTime>消息创建时间 (整型)</CreateTime><MsgType><![CDATA[video]]></MsgType><Video><MediaId><![CDATA[通过上传多媒体文件,得到的id。]]></MediaId><Title><![CDATA[视频消息的标题]]></Title> <Description><![CDATA[视频消息的描述]]></Description> </Video></xml>
<xml><ToUserName><![CDATA[接收方帐号(收到的OpenID)]]></ToUserName><FromUserName><![CDATA[开发者微信号]]></FromUserName><CreateTime>消息创建时间 (整型)</CreateTime><MsgType><![CDATA[music]]></MsgType><Music><ThumbMediaId><![CDATA[缩略图的媒体id,通过上传多媒体文件,得到的id。]]></ThumbMediaId><Title><![CDATA[视频消息的标题]]></Title> <Description><![CDATA[视频消息的描述]]></Description> <MusicURL><![CDATA[音乐链接]]></MusicURL> <HQMusicUrl><![CDATA[高质量音乐链接,WIFI环境优先使用该链接播放音乐]]></HQMusicUrl> </Music></xml>
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>2</ArticleCount><Articles><item><Title><![CDATA[title1]]></Title> <Description><![CDATA[description1]]></Description><PicUrl><![CDATA[picurl]]></PicUrl><Url><![CDATA[url]]></Url></item><item><Title><![CDATA[title]]></Title><Description><![CDATA[description]]></Description><PicUrl><![CDATA[picurl]]></PicUrl><Url><![CDATA[url]]></Url></item></Articles></xml>
回复图文中,item是一个项,一个item代码一个图文。在响应的时候,我们只需根据数据格式,替换掉对应的属性,然后Response.Write(s)即可。结合前两章的讲解,BaseMessage的最终代码如下:
/// <summary> /// 消息体基类 /// </summary> public abstract class BaseMessage { /// <summary> /// 开发者微信号 /// </summary> public string ToUserName { get; set; } /// <summary> /// 发送方帐号(一个OpenID) /// </summary> public string FromUserName { get; set; } /// <summary> /// 消息创建时间 (整型) /// </summary> public string CreateTime { get; set; } /// <summary> /// 消息类型 /// </summary> public MsgType MsgType { get; set; } public virtual void ResponseNull() { Utils.ResponseWrite(""); } public virtual void ResText(EnterParam param, string content) { StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>", FromUserName, ToUserName, Utils.ConvertDateTimeInt(DateTime.Now))); resxml.AppendFormat("<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{0}]]></Content><FuncFlag>0</FuncFlag></xml>", content); Response(param, resxml.ToString()); } /// <summary> /// 回复消息(音乐) /// </summary> public void ResMusic(EnterParam param, Music mu) { StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now))); resxml.Append(" <MsgType><![CDATA[music]]></MsgType>"); resxml.AppendFormat("<Music><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description>", mu.Title, mu.Description); resxml.AppendFormat("<MusicUrl><![CDATA[http://{0}{1}]]></MusicUrl><HQMusicUrl><![CDATA[http://{2}{3}]]></HQMusicUrl></Music><FuncFlag>0</FuncFlag></xml>", VqiRequest.GetCurrentFullHost(), mu.MusicUrl, VqiRequest.GetCurrentFullHost(), mu.HQMusicUrl); Response(param, resxml.ToString()); } public void ResVideo(EnterParam param, Video v) { StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now))); resxml.Append(" <MsgType><![CDATA[video]]></MsgType>"); resxml.AppendFormat("<Video><MediaId><![CDATA[{0}]]></MediaId>", v.media_id); resxml.AppendFormat("<Title><![CDATA[{0}]]></Title>", v.title); resxml.AppendFormat("<Description><![CDATA[{0}]]></Description></Video></xml>", v.description); Response(param, resxml.ToString()); } /// <summary> /// 回复消息(图片) /// </summary> public void ResPicture(EnterParam param, Picture pic, string domain) { StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now))); resxml.Append(" <MsgType><![CDATA[WeChat の開発受動的応答とファイルのアップロードとダウンロード]]></MsgType>"); resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl></xml>", domain + pic.PictureUrl); Response(param, resxml.ToString()); } /// <summary> /// 回复消息(图文列表) /// </summary> /// <param name="param"></param> /// <param name="art"></param> public void ResArticles(EnterParam param, List<Articles> art) { StringBuilder resxml = new StringBuilder(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime>",FromUserName,ToUserName, Utils.ConvertDateTimeInt(DateTime.Now))); resxml.AppendFormat("<MsgType><![CDATA[news]]></MsgType><ArticleCount>{0}</ArticleCount><Articles>", art.Count); for (int i = 0; i < art.Count; i++) { resxml.AppendFormat("<item><Title><![CDATA[{0}]]></Title> <Description><![CDATA[{1}]]></Description>", art[i].Title, art[i].Description); resxml.AppendFormat("<PicUrl><![CDATA[{0}]]></PicUrl><Url><![CDATA[{1}]]></Url></item>", art[i].PicUrl.Contains("http://") ? art[i].PicUrl : "http://" + VqiRequest.GetCurrentFullHost() + art[i].PicUrl, art[i].Url.Contains("http://") ? art[i].Url : "http://" + VqiRequest.GetCurrentFullHost() + art[i].Url); } resxml.Append("</Articles><FuncFlag>0</FuncFlag></xml>"); Response(param, resxml.ToString()); } /// <summary> /// 多客服转发 /// </summary> /// <param name="param"></param> public void ResDKF(EnterParam param) { StringBuilder resxml = new StringBuilder(); resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName); resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime); resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType></xml>"); Response(param, resxml.ToString()); } /// <summary> /// 多客服转发如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满),该用户会一直等待指定客服有接入能力后才会被接入,而不会被其他客服接待。建议在指定客服时,先查询客服的接入能力指定到有能力接入的客服,保证客户能够及时得到服务。 /// </summary> /// <param name="param">用户发送的消息体</param> /// <param name="KfAccount">多客服账号</param> public void ResDKF(EnterParam param, string KfAccount) { StringBuilder resxml = new StringBuilder(); resxml.AppendFormat("<xml><ToUserName><![CDATA[{0}]]></ToUserName>",FromUserName); resxml.AppendFormat("<FromUserName><![CDATA[{0}]]></FromUserName><CreateTime>{1}</CreateTime>",ToUserName,CreateTime); resxml.AppendFormat("<MsgType><![CDATA[transfer_customer_service]]></MsgType><TransInfo><KfAccount>{0}</KfAccount></TransInfo></xml>", KfAccount); Response(param, resxml.ToString()); } private void Response(EnterParam param, string data) { if (param.IsAes) { var wxcpt = new MsgCrypt(param.token, param.EncodingAESKey, param.appid); wxcpt.EncryptMsg(data, Utils.ConvertDateTimeInt(DateTime.Now).ToString(), Utils.GetRamCode(), ref data); } Utils.ResponseWrite(data); } }
上面的代码中,public void ResDKF(EnterParam param),public void ResDKF(EnterParam param, string KfAccount)两个方法时多客服中,用户转发用户发送的消息的,多客服将在后期的博文中进行更新,敬请期待。
public void ResMusic(EnterParam param, Music mu)方法中的Music类的定义如下:
public class Music { #region 属性 /// <summary> /// 音乐链接 /// </summary> public string MusicUrl { get; set; } /// <summary> /// 高质量音乐链接,WIFI环境优先使用该链接播放音乐 /// </summary> public string HQMusicUrl { get; set; } /// <summary> /// 标题 /// </summary> public string Title { get; set; } /// <summary> /// 描述 /// </summary> public string Description { get; set; } #endregion }
public void ResVideo(EnterParam param, Video v)方法中的Video类的定义如下:
public class Video { public string title { get; set; } public string media_id { get; set; } public string description { get; set; } }
public void ResArticles(EnterParam param, List
public class Articles { #region 属性 /// <summary> /// 图文消息标题 /// </summary> public string Title { get; set; } /// <summary> /// 图文消息描述 /// </summary> public string Description { get; set; } /// <summary> /// 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80。 /// </summary> public string PicUrl { get; set; } /// <summary> /// 点击图文消息跳转链接 /// </summary> public string Url { get; set; } #endregion }
【相关推荐】
2.微信投票源码
以上がWeChat の開発受動的応答とファイルのアップロードとダウンロードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。