ホームページ >WeChat アプレット >WeChatの開発 >WeChat 開発ノート - カスタム共有インターフェイスを呼び出す
はじめに:
私たちは仕事でマイクロサイトと呼ばれるWeChat Webサイトを開発しています。マイクロサイトの共有コンテンツはシステムによって自動的に選択された現在の URL であるため、顧客は共有コンテンツを変更する必要があります。つまり、画面の右上隅にある共有ボタンをクリックし、[友達に送信] または [モーメントに送信] を選択します。コンテンツと写真はカスタマイズする必要があります。そこで、ドキュメント WeChat JS-SDK Documentation と Web サイト上の多くの専門家の経験を調べて、呼び出しの手順は大体わかりましたが、正常に呼び出す方法がわかりません。いくつかの実験の後、Send to Friends と Send to Moments の 2 つのインターフェイスが最終的に正常に呼び出されました。その呼び出しの具体的なプロセスがここに記録されています。
ステップ 1: js ファイルを参照します。
JS インターフェースを呼び出す必要があるページに次の JS ファイルを導入します (https をサポート): http://res.wx.qq.com/open/js/jweixin-1.0.0.js
ステップ2: パス 設定インターフェイスは権限検証設定を挿入します
wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 });
インターネット上の多くのネチズンもこれを書いていますが、具体的な設定についてはほとんど話されていません。次に、この記事でそれを呼び出す方法を紹介します。 。
Debug と appId は言うまでもなく、非常に簡単です。
timespan は署名付きタイムスタンプを生成します:
/// 631fb227578dfffda61e1fa4d04b7d25 /// 生成时间戳 /// 从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间,且最终需要转换为字符串形式 /// 039f3e95db2a684c7b74365531eb6044 /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public string getTimestamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); }
nonceStr は署名付きランダム文字列を生成します:
/// 631fb227578dfffda61e1fa4d04b7d25 /// 生成随机字符串 /// 039f3e95db2a684c7b74365531eb6044 /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public string getNoncestr() { Random random = new Random(); return MD5Util.GetMD5(random.Next(1000).ToString(), "GBK"); }
/// 631fb227578dfffda61e1fa4d04b7d25 /// MD5Util 的摘要说明。 /// 039f3e95db2a684c7b74365531eb6044 public class MD5Util { public MD5Util() { // // TODO: 在此处添加构造函数逻辑 // } /** 获取大写的MD5签名结果 */ public static string GetMD5(string encypStr, string charset) { string retStr; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //创建md5对象 byte[] inputBye; byte[] outputBye; //使用GB2312编码方式把字符串转化为字节数组. try { inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr); } catch (Exception ex) { inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr); } outputBye = m5.ComputeHash(inputBye); retStr = System.BitConverter.ToString(outputBye); retStr = retStr.Replace("-", "").ToUpper(); return retStr; } }
コードを見る
/// <summary> /// MD5Util 的摘要说明。 /// </summary> public class MD5Util { public MD5Util() { // // TODO: 在此处添加构造函数逻辑 // } /** 获取大写的MD5签名结果 */ public static string GetMD5(string encypStr, string charset) { string retStr; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //创建md5对象 byte[] inputBye; byte[] outputBye; //使用GB2312编码方式把字符串转化为字节数组. try { inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr); } catch (Exception ex) { inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr); } outputBye = m5.ComputeHash(inputBye); retStr = System.BitConverter.ToString(outputBye); retStr = retStr.Replace("-", "").ToUpper(); return retStr; } }
署名の生成はさらに面倒です。
最初に access_token を生成して取得します (有効期間は 7200 秒、開発者は access_token を独自のサービスでグローバルにキャッシュする必要があります)
public string Getaccesstoken() { string appid = System.Configuration.ConfigurationManager.AppSettings["WXZjAppID"].ToString(); string secret = System.Configuration.ConfigurationManager.AppSettings["WXZjAppSecret"].ToString(); string urljson = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret; string strjson = ""; UTF8Encoding encoding = new UTF8Encoding(); HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(urljson); myRequest.Method = "GET"; myRequest.ContentType = "application/x-www-form-urlencoded"; HttpWebResponse response; Stream responseStream; StreamReader reader; string srcString; response = myRequest.GetResponse() as HttpWebResponse; responseStream = response.GetResponseStream(); reader = new System.IO.StreamReader(responseStream, Encoding.UTF8); srcString = reader.ReadToEnd(); reader.Close(); if (srcString.Contains("access_token")) { //CommonJsonModel model = new CommonJsonModel(srcString); HP.CPS.BLL.WeiXin.CommonJsonModel model = new BLL.WeiXin.CommonJsonModel(srcString); strjson = model.GetValue("access_token"); Session["access_tokenzj"] = strjson; } return strjson; }
public class CommonJsonModelAnalyzer { protected string _GetKey(string rawjson) { if (string.IsNullOrEmpty(rawjson)) return rawjson; rawjson = rawjson.Trim(); string[] jsons = rawjson.Split(new char[] { ':' }); if (jsons.Length a1553b849066844e5dd92b24025343bd 0) builder.Remove(builder.Length - 1, 1); string value = builder.ToString(); if (value.StartsWith("\"")) value = value.Substring(1); if (value.EndsWith("\"")) value = value.Substring(0, value.Length - 1); return value; } protected List98c455a79ddfebb79781bff588e7b37e _GetCollection(string rawjson) { //[{},{}] List98c455a79ddfebb79781bff588e7b37e list = new List98c455a79ddfebb79781bff588e7b37e(); if (string.IsNullOrEmpty(rawjson)) return list; rawjson = rawjson.Trim(); StringBuilder builder = new StringBuilder(); int nestlevel = -1; int mnestlevel = -1; for (int i = 0; i 26a485ceddac2a4986e7745b4f11808b 0) list.Add(builder.ToString()); return list; } } public class CommonJsonModel : CommonJsonModelAnalyzer { private string rawjson; private bool isValue = false; private bool isModel = false; private bool isCollection = false; public CommonJsonModel(string rawjson) { this.rawjson = rawjson; if (string.IsNullOrEmpty(rawjson)) throw new Exception("missing rawjson"); rawjson = rawjson.Trim(); if (rawjson.StartsWith("{")) { isModel = true; } else if (rawjson.StartsWith("[")) { isCollection = true; } else { isValue = true; } } public string Rawjson { get { return rawjson; } } public bool IsValue() { return isValue; } public bool IsValue(string key) { if (!isModel) return false; if (string.IsNullOrEmpty(key)) return false; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); return submodel.IsValue(); } } return false; } public bool IsModel() { return isModel; } public bool IsModel(string key) { if (!isModel) return false; if (string.IsNullOrEmpty(key)) return false; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); return submodel.IsModel(); } } return false; } public bool IsCollection() { return isCollection; } public bool IsCollection(string key) { if (!isModel) return false; if (string.IsNullOrEmpty(key)) return false; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); return submodel.IsCollection(); } } return false; } /// 631fb227578dfffda61e1fa4d04b7d25 /// 当模型是对象,返回拥有的key /// 039f3e95db2a684c7b74365531eb6044 /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public List98c455a79ddfebb79781bff588e7b37e GetKeys() { if (!isModel) return null; List98c455a79ddfebb79781bff588e7b37e list = new List98c455a79ddfebb79781bff588e7b37e(); foreach (string subjson in base._GetCollection(this.rawjson)) { string key = new CommonJsonModel(subjson).Key; if (!string.IsNullOrEmpty(key)) list.Add(key); } return list; } /// 631fb227578dfffda61e1fa4d04b7d25 /// 当模型是对象,key对应是值,则返回key对应的值 /// 039f3e95db2a684c7b74365531eb6044 /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2 /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public string GetValue(string key) { if (!isModel) return null; if (string.IsNullOrEmpty(key)) return null; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) return model.Value; } return null; } /// 631fb227578dfffda61e1fa4d04b7d25 /// 模型是对象,key对应是对象,返回key对应的对象 /// 039f3e95db2a684c7b74365531eb6044 /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2 /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public CommonJsonModel GetModel(string key) { if (!isModel) return null; if (string.IsNullOrEmpty(key)) return null; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); if (!submodel.IsModel()) return null; else return submodel; } } return null; } /// 631fb227578dfffda61e1fa4d04b7d25 /// 模型是对象,key对应是集合,返回集合 /// 039f3e95db2a684c7b74365531eb6044 /// 4b9508bee1b4e18a78c442a485ff2a938bb7487ae6a16a43571bc14c7fcf93c2 /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public CommonJsonModel GetCollection(string key) { if (!isModel) return null; if (string.IsNullOrEmpty(key)) return null; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); if (!submodel.IsCollection()) return null; else return submodel; } } return null; } /// 631fb227578dfffda61e1fa4d04b7d25 /// 模型是集合,返回自身 /// 039f3e95db2a684c7b74365531eb6044 /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public Listd4f06880a8bb972f429fc35193731b86 GetCollection() { Listd4f06880a8bb972f429fc35193731b86 list = new Listd4f06880a8bb972f429fc35193731b86(); if (IsValue()) return list; foreach (string subjson in base._GetCollection(rawjson)) { list.Add(new CommonJsonModel(subjson)); } return list; } /// 631fb227578dfffda61e1fa4d04b7d25 /// 当模型是值对象,返回key /// 039f3e95db2a684c7b74365531eb6044 private string Key { get { if (IsValue()) return base._GetKey(rawjson); return null; } } /// 631fb227578dfffda61e1fa4d04b7d25 /// 当模型是值对象,返回value /// 039f3e95db2a684c7b74365531eb6044 private string Value { get { if (!IsValue()) return null; return base._GetValue(rawjson); } } }
コードを表示
public class CommonJsonModelAnalyzer { protected string _GetKey(string rawjson) { if (string.IsNullOrEmpty(rawjson)) return rawjson; rawjson = rawjson.Trim(); string[] jsons = rawjson.Split(new char[] { ':' }); if (jsons.Length < 2) return rawjson; return jsons[0].Replace("\"", "").Trim(); } protected string _GetValue(string rawjson) { if (string.IsNullOrEmpty(rawjson)) return rawjson; rawjson = rawjson.Trim(); string[] jsons = rawjson.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (jsons.Length < 2) return rawjson; StringBuilder builder = new StringBuilder(); for (int i = 1; i < jsons.Length; i++) { builder.Append(jsons[i]); builder.Append(":"); } if (builder.Length > 0) builder.Remove(builder.Length - 1, 1); string value = builder.ToString(); if (value.StartsWith("\"")) value = value.Substring(1); if (value.EndsWith("\"")) value = value.Substring(0, value.Length - 1); return value; } protected List<string> _GetCollection(string rawjson) { //[{},{}] List<string> list = new List<string>(); if (string.IsNullOrEmpty(rawjson)) return list; rawjson = rawjson.Trim(); StringBuilder builder = new StringBuilder(); int nestlevel = -1; int mnestlevel = -1; for (int i = 0; i < rawjson.Length; i++) { if (i == 0) continue; else if (i == rawjson.Length - 1) continue; char jsonchar = rawjson[i]; if (jsonchar == '{') { nestlevel++; } if (jsonchar == '}') { nestlevel--; } if (jsonchar == '[') { mnestlevel++; } if (jsonchar == ']') { mnestlevel--; } if (jsonchar == ',' && nestlevel == -1 && mnestlevel == -1) { list.Add(builder.ToString()); builder = new StringBuilder(); } else { builder.Append(jsonchar); } } if (builder.Length > 0) list.Add(builder.ToString()); return list; } } public class CommonJsonModel : CommonJsonModelAnalyzer { private string rawjson; private bool isValue = false; private bool isModel = false; private bool isCollection = false; public CommonJsonModel(string rawjson) { this.rawjson = rawjson; if (string.IsNullOrEmpty(rawjson)) throw new Exception("missing rawjson"); rawjson = rawjson.Trim(); if (rawjson.StartsWith("{")) { isModel = true; } else if (rawjson.StartsWith("[")) { isCollection = true; } else { isValue = true; } } public string Rawjson { get { return rawjson; } } public bool IsValue() { return isValue; } public bool IsValue(string key) { if (!isModel) return false; if (string.IsNullOrEmpty(key)) return false; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); return submodel.IsValue(); } } return false; } public bool IsModel() { return isModel; } public bool IsModel(string key) { if (!isModel) return false; if (string.IsNullOrEmpty(key)) return false; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); return submodel.IsModel(); } } return false; } public bool IsCollection() { return isCollection; } public bool IsCollection(string key) { if (!isModel) return false; if (string.IsNullOrEmpty(key)) return false; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); return submodel.IsCollection(); } } return false; } /// <summary> /// 当模型是对象,返回拥有的key /// </summary> /// <returns></returns> public List<string> GetKeys() { if (!isModel) return null; List<string> list = new List<string>(); foreach (string subjson in base._GetCollection(this.rawjson)) { string key = new CommonJsonModel(subjson).Key; if (!string.IsNullOrEmpty(key)) list.Add(key); } return list; } /// <summary> /// 当模型是对象,key对应是值,则返回key对应的值 /// </summary> /// <param name="key"></param> /// <returns></returns> public string GetValue(string key) { if (!isModel) return null; if (string.IsNullOrEmpty(key)) return null; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) return model.Value; } return null; } /// <summary> /// 模型是对象,key对应是对象,返回key对应的对象 /// </summary> /// <param name="key"></param> /// <returns></returns> public CommonJsonModel GetModel(string key) { if (!isModel) return null; if (string.IsNullOrEmpty(key)) return null; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); if (!submodel.IsModel()) return null; else return submodel; } } return null; } /// <summary> /// 模型是对象,key对应是集合,返回集合 /// </summary> /// <param name="key"></param> /// <returns></returns> public CommonJsonModel GetCollection(string key) { if (!isModel) return null; if (string.IsNullOrEmpty(key)) return null; foreach (string subjson in base._GetCollection(this.rawjson)) { CommonJsonModel model = new CommonJsonModel(subjson); if (!model.IsValue()) continue; if (model.Key == key) { CommonJsonModel submodel = new CommonJsonModel(model.Value); if (!submodel.IsCollection()) return null; else return submodel; } } return null; } /// <summary> /// 模型是集合,返回自身 /// </summary> /// <returns></returns> public List<CommonJsonModel> GetCollection() { List<CommonJsonModel> list = new List<CommonJsonModel>(); if (IsValue()) return list; foreach (string subjson in base._GetCollection(rawjson)) { list.Add(new CommonJsonModel(subjson)); } return list; } /// <summary> /// 当模型是值对象,返回key /// </summary> private string Key { get { if (IsValue()) return base._GetKey(rawjson); return null; } } /// <summary> /// 当模型是值对象,返回value /// </summary> private string Value { get { if (!IsValue()) return null; return base._GetValue(rawjson); } } }
次に jsapi_ticket を取得します:
最初のステップで取得した access_token を使用して、http GET メソッドを使用して jsapi_ticket をリクエストします (有効期間は 7200 秒、開発者は jsapi_ticket を独自のサービスでグローバルにキャッシュする必要があります)
public string Getjsapi_ticket() { string accesstoken = (string)Session["access_tokenzj"]; string urljson = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accesstoken + "&type=jsapi"; string strjson = ""; UTF8Encoding encoding = new UTF8Encoding(); HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(urljson); myRequest.Method = "GET"; myRequest.ContentType = "application/x-www-form-urlencoded"; HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse; Stream responseStream = response.GetResponseStream(); StreamReader reader = new System.IO.StreamReader(responseStream, Encoding.UTF8); string srcString = reader.ReadToEnd(); reader.Close(); if (srcString.Contains("ticket")) { HP.CPS.BLL.WeiXin.CommonJsonModel model = new BLL.WeiXin.CommonJsonModel(srcString); strjson = model.GetValue("ticket"); Session["ticketzj"] = strjson; } return strjson; }
最終的に生成された署名:
public string Getsignature(string nonceStr, string timespanstr) { if (Session["access_tokenzj"] == null) { Getaccesstoken(); } if (Session["ticketzj"] == null) { Getjsapi_ticket(); } string url = Request.Url.ToString(); string str = "jsapi_ticket=" + (string)Session["ticketzj"] + "&noncestr=" + nonceStr + "×tamp=" + timespanstr + "&url=" + url;// +"&wxref=mp.weixin.qq.com"; string singature = SHA1Util.getSha1(str); string ss = singature; return ss; }
class SHA1Util { public static String getSha1(String str) { //建立SHA1对象 SHA1 sha = new SHA1CryptoServiceProvider(); //将mystr转换成byte[] ASCIIEncoding enc = new ASCIIEncoding(); byte[] dataToHash = enc.GetBytes(str); //Hash运算 byte[] dataHashed = sha.ComputeHash(dataToHash); //将运算结果转换成string string hash = BitConverter.ToString(dataHashed).Replace("-", ""); return hash; } }
class SHA1Util { public static String getSha1(String str) { //建立SHA1对象 SHA1 sha = new SHA1CryptoServiceProvider(); //将mystr转换成byte[] ASCIIEncoding enc = new ASCIIEncoding(); byte[] dataToHash = enc.GetBytes(str); //Hash运算 byte[] dataHashed = sha.ComputeHash(dataToHash); //将运算结果转换成string string hash = BitConverter.ToString(dataHashed).Replace("-", ""); return hash; } }
View Code
この記事の呼び出し例:
8019067d09615e43c7904885b5246f0a wx.config({ debug: false, appId: '8b714b3c2c6d4a77d9fafb62fc5c6527', timestamp: d338d8cc12e391b6077114439755f24c, nonceStr: 'b0a30cd4be74010f57ebf0728129f0b5', signature: '5f680811c4a8b50943bd0e6592e3a9c3', jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] }); 2cacc6d41bbb37262a98f745aa00fbf0
ステップ 3 : インターフェイスを呼び出します
2 番目のステップを呼び出した後、ステップ 3 は非常に簡単になります。
wx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。});
この記事の呼び出し例は次のとおりです:
<script type="text/javascript" > wx.ready(function () { wx.onMenuShareAppMessage({ title: '<%=shareTitle %>', desc: '<%=shareContent %>', link: '<%=currentUrl %>', imgUrl: '<%=shareImageUrl %>' }); wx.onMenuShareTimeline({ title: '<%=shareContent %>', link: '<%=currentUrl %>', imgUrl: '<%=shareImageUrl %>' }); }) </script>
ea1aab715d1b735c8b112b6fff119ca8 wx.ready(function () { wx.onMenuShareAppMessage({ title: '80e0a7013b745db2823b130323b41331', desc: '152f3453142071ccbd67e476c57fed3e', link: '5d9d8eaa1edde12e5f5cd9082c708a3e', imgUrl: '490b6150690e3af5006b483eb68141cc' }); wx.onMenuShareTimeline({ title: '152f3453142071ccbd67e476c57fed3e', link: '5d9d8eaa1edde12e5f5cd9082c708a3e', imgUrl: '490b6150690e3af5006b483eb68141cc' }); }) 2cacc6d41bbb37262a98f745aa00fbf0
この記事は基本的にここにまとめられています。
起こりやすい問題:
1. バックエンドが設定されているかどうかを確認します: 右上隅の公式アカウント名 - 機能設定 - JS インターフェースのセキュリティドメイン名
2. コード内の appid が一致しているかどうかを確認します。公式アカウントのバックエンドのID
3. 画像の呼び出しアドレスは絶対パスです(相対パスは機能しないようです)。
WeChat 開発ノートの詳細 - カスタム共有インターフェイスの呼び出しに関する関連記事については、PHP 中国語 Web サイトに注目してください。