Yii2.0实现微信公众号后台开发
2019獨角獸企業重金招聘Python工程師標準>>>
研讀 微信公眾平臺開發者文檔 ,然后再閱讀本文,效果更佳!
接入微信
Yii2后臺配置
1.在app/config/params.php中配置token參數
| return [ ????//微信接入 ????'wechat' =>[ ????????'token' => 'your token', ????], ]; |
2.在app/config/main.php中配置路由
因為接口模塊使用的RESTful API,所以需要定義路由規則。
| 'urlManager' => [ ????'enablePrettyUrl' => true, ????'enableStrictParsing' => true, ????'showScriptName' => false, ????'rules' => [ ????????[ ????????????'class' => 'yii\rest\UrlRule', ????????????'controller' => 'wechat', ????????????'extraPatterns' => [ ????????????????'GET valid' => 'valid', ????????????], ????????], ????], ], |
3.在app/controllers中新建WechatController
| <?php ? namespace api\controllers; ? use Yii; use yii\rest\ActiveController; ? class WechatController extends ActiveController { ? ????public $modelClass = ''; ? ????public function actionValid() ????{ ????????$echoStr = $_GET["echostr"]; ????????$signature = $_GET["signature"]; ????????$timestamp = $_GET["timestamp"]; ????????$nonce = $_GET["nonce"]; ????????//valid signature , option ????????if($this->checkSignature($signature,$timestamp,$nonce)){ ????????????echo $echoStr; ????????} ????} ? ????private function checkSignature($signature,$timestamp,$nonce) ????{ ????????// you must define TOKEN by yourself ????????$token = Yii::$app->params['wechat']['token']; ????????if (!$token) { ????????????echo 'TOKEN is not defined!'; ????????} else { ????????????$tmpArr = array($token, $timestamp, $nonce); ????????????// use SORT_STRING rule ????????????sort($tmpArr, SORT_STRING); ????????????$tmpStr = implode( $tmpArr ); ????????????$tmpStr = sha1( $tmpStr ); ? ????????????if( $tmpStr == $signature ){ ????????????????return true; ????????????}else{ ????????????????return false; ????????????} ????????} ????} ? } |
微信公眾號后臺配置
在微信公眾號后臺配置URL和Token,然后提交驗證即可。
| URL:<a rel="nofollow" href="http://app.demo.com/wechats/valid" target="_blank">http://app.demo.com/wechats/valid</a> Token:your token |
獲取用戶信息
用戶表設計
| CREATE TABLE `wechat_user` ( ??`id` int(11) NOT NULL, ??`openid` varchar(255) COLLATE utf8_unicode_ci NOT NULL, ??`nickname` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT '微信昵稱', ??`sex` tinyint(4) NOT NULL COMMENT '性別', ??`headimgurl` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '頭像', ??`country` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT '國家', ??`province` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT '省份', ??`city` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT '城市', ??`access_token` varchar(255) COLLATE utf8_unicode_ci NOT NULL, ??`refresh_token` varchar(255) COLLATE utf8_unicode_ci NOT NULL, ??`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; ? ALTER TABLE `wechat_user` ??ADD PRIMARY KEY (`id`); |
獲取用戶信息的相關接口
1.用戶授權接口:獲取access_token、openid等;獲取并保存用戶資料到數據庫
| public function actionAccesstoken() { ????$code = $_GET["code"]; ????$state = $_GET["state"]; ????$appid = Yii::$app->params['wechat']['appid']; ????$appsecret = Yii::$app->params['wechat']['appsecret']; ????$request_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$appid.'&secret='.$appsecret.'&code='.$code.'&grant_type=authorization_code'; ? ????//初始化一個curl會話 ????$ch = curl_init(); ????curl_setopt($ch, CURLOPT_URL, $request_url); ????curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); ????$result = curl_exec($ch); ????curl_close($ch); ????$result = $this->response($result); ? ????//獲取token和openid成功,數據解析 ????$access_token = $result['access_token']; ????$refresh_token = $result['refresh_token']; ????$openid = $result['openid']; ? ????//請求微信接口,獲取用戶信息 ????$userInfo = $this->getUserInfo($access_token,$openid); ????$user_check = WechatUser::find()->where(['openid'=>$openid])->one(); ????if ($user_check) { ????????//更新用戶資料 ????} else { ????????//保存用戶資料 ????} ? ????//前端網頁的重定向 ????if ($openid) { ????????return $this->redirect($state.$openid); ????} else { ????????return $this->redirect($state); ????} } |
2.從微信獲取用戶資料
| public function getUserInfo($access_token,$openid) { ????$request_url = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$access_token.'&openid='.$openid.'&lang=zh_CN'; ????//初始化一個curl會話 ????$ch = curl_init(); ????curl_setopt($ch, CURLOPT_URL, $request_url); ????curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); ????$result = curl_exec($ch); ????curl_close($ch); ????$result = $this->response($result); ????return $result; } |
3.獲取用戶資料接口
| public function actionUserinfo() { ????if(isset($_REQUEST["openid"])){ ????????$openid = $_REQUEST["openid"]; ????????$user = WechatUser::find()->where(['openid'=>$openid])->one(); ????????if ($user) { ????????????$result['error'] = 0; ????????????$result['msg'] = '獲取成功'; ????????????$result['user'] = $user; ????????} else { ????????????$result['error'] = 1; ????????????$result['msg'] = '沒有該用戶'; ????????} ????} else { ????????$result['error'] = 1; ????????$result['msg'] = 'openid為空'; ????} ????return $result; } |
微信支付
1.微信支付接口:打包支付數據
| public function actionPay(){ ????if(isset($_REQUEST["uid"])&&isset($_REQUEST["oid"])&&isset($_REQUEST["totalFee"])){ ????????//uid、oid、totalFee ????????$uid = $_REQUEST["uid"]; ????????$oid = $_REQUEST["oid"]; ????????$totalFee = $_REQUEST["totalFee"]; ????????$timestamp = time(); ? ????????//微信支付參數 ????????$appid = Yii::$app->params['wechat']['appid']; ????????$mchid = Yii::$app->params['wechat']['mchid']; ????????$key = Yii::$app->params['wechat']['key']; ????????$notifyUrl = Yii::$app->params['wechat']['notifyUrl']; ? ????????//支付打包 ????????$wx_pay = new WechatPay($mchid, $appid, $key); ????????$package = $wx_pay->createJsBizPackage($uid, $totalFee, $oid, $notifyUrl, $timestamp); ????????$result['error'] = 0; ????????$result['msg'] = '支付打包成功'; ????????$result['package'] = $package; ????????return $result; ????}else{ ????????$result['error'] = 1; ????????$result['msg'] = '請求參數錯誤'; ????} ????return $result; } |
2.接收微信發送的異步支付結果通知
| public function actionNotify(){ ????$postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; ????$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); ????// ????if ($postObj === false) { ????????die('parse xml error'); ????} ????if ($postObj->return_code != 'SUCCESS') { ????????die($postObj->return_msg); ????} ????if ($postObj->result_code != 'SUCCESS') { ????????die($postObj->err_code); ????} ? ????//微信支付參數 ????$appid = Yii::$app->params['wechat']['appid']; ????$mchid = Yii::$app->params['wechat']['mchid']; ????$key = Yii::$app->params['wechat']['key']; ????$wx_pay = new WechatPay($mchid, $appid, $key); ? ????//驗證簽名 ????$arr = (array)$postObj; ????unset($arr['sign']); ????if ($wx_pay->getSign($arr, $key) != $postObj->sign) { ????????die("簽名錯誤"); ????} ? ????//支付處理正確-判斷是否已處理過支付狀態 ????$orders = Order::find()->where(['uid'=>$postObj->openid, 'oid'=>$postObj->out_trade_no, 'status' => 0])->all(); ? ????if(count($orders) > 0){ ????????//更新訂單狀態 ????????foreach ($orders as $order) { ????????????//更新訂單 ????????????$order['status'] = 1; ????????????$order->update(); ????????} ????????return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; ????} else { ????????//訂單狀態已更新,直接返回 ????????return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; ????} } |
3.微信支付類 WechatPay.php
| <?php ? namespace api\sdk; ? use Yii; ? class WechatPay { ????protected $mchid; ????protected $appid; ????protected $key; ? ????public function construct($mchid, $appid, $key){ ????????$this->mchid = $mchid; ????????$this->appid = $appid; ????????$this->key = $key; ????} ? ????public function createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp){ ????????$config = array( ????????????'mch_id' => $this->mchid, ????????????'appid' => $this->appid, ????????????'key' => $this->key, ????????); ????????$unified = array( ????????????'appid' => $config['appid'], ????????????'attach' => '支付', ????????????'body' => $orderName, ????????????'mch_id' => $config['mch_id'], ????????????'nonce_str' => self::createNonceStr(), ????????????'notify_url' => $notifyUrl, ????????????'openid' => $openid, ????????????'out_trade_no' => $outTradeNo, ????????????'spbill_create_ip' => '127.0.0.1', ????????????'total_fee' => intval($totalFee * 100), ????????????'trade_type' => 'JSAPI', ????????); ????????$unified['sign'] = self::getSign($unified, $config['key']); ????????$responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified)); ????????$unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA); ????????if ($unifiedOrder === false) { ????????????die('parse xml error'); ????????} ????????if ($unifiedOrder->return_code != 'SUCCESS') { ????????????die($unifiedOrder->return_msg); ????????} ????????if ($unifiedOrder->result_code != 'SUCCESS') { ????????????die($unifiedOrder->err_code); ????????} ????????$arr = array( ????????????"appId" => $config['appid'], ????????????"timeStamp" => $timestamp, ????????????"nonceStr" => self::createNonceStr(), ????????????"package" => "prepay_id=" . $unifiedOrder->prepay_id, ????????????"signType" => 'MD5', ????????); ????????$arr['paySign'] = self::getSign($arr, $config['key']); ????????return $arr; ????} ? ????public static function curlGet($url = '', $options = array()){ ????????$ch = curl_init($url); ????????curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); ????????curl_setopt($ch, CURLOPT_TIMEOUT, 30); ????????if (!empty($options)) { ????????????curl_setopt_array($ch, $options); ????????} ????????//https請求 不驗證證書和host ????????curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); ????????curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); ????????$data = curl_exec($ch); ????????curl_close($ch); ????????return $data; ????} ? ? ????public static function curlPost($url = '', $postData = '', $options = array()){ ????????if (is_array($postData)) { ????????????$postData = http_build_query($postData); ????????} ????????$ch = curl_init(); ????????curl_setopt($ch, CURLOPT_URL, $url); ????????curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); ????????curl_setopt($ch, CURLOPT_POST, 1); ????????curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); ????????curl_setopt($ch, CURLOPT_TIMEOUT, 30); //設置cURL允許執行的最長秒數 ????????if (!empty($options)) { ????????????curl_setopt_array($ch, $options); ????????} ????????//https請求 不驗證證書和host ????????curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); ????????curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); ????????$data = curl_exec($ch); ????????curl_close($ch); ????????return $data; ????} ? ????public static function createNonceStr($length = 16){ ????????$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; ????????$str = ''; ????????for ($i = 0; $i<$length; $i++){ ????????????$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); ????????} ????????return $str; ????} ? ????public static function arrayToXml($arr){ ????????$xml = "<xml>"; ????????foreach ($arr as $key => $val){ ????????????if (is_numeric($val)) { ????????????????$xml .= "<" . $key . ">" . $val . "</" . $key . ">"; ????????????} else { ????????????????$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; ????????????} ????????} ????????$xml .= "</xml>"; ????????return $xml; ????} ? ????public static function getSign($params, $key){ ????????ksort($params, SORT_STRING); ????????$unSignParaString = self::formatQueryParaMap($params, false); ????????$signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); ????????return $signStr; ????} ? ????protected static function formatQueryParaMap($paraMap, $urlEncode = false){ ????????$buff = ""; ????????ksort($paraMap); ????????foreach ($paraMap as $k => $v){ ????????????if (null != $v && "null" != $v) { ????????????????if ($urlEncode) { ????????????????????$v = urlencode($v); ????????????????} ????????????????$buff .= $k . "=" . $v . "&"; ????????????} ????????} ????????$reqPar = ''; ????????if (strlen($buff)>0) { ????????????$reqPar = substr($buff, 0, strlen($buff) - 1); ????????} ????????return $reqPar; ????} ? } |
獲取JS-SDK的config參數
根據微信公眾平臺開發者文檔:
所有需要使用JS-SDK的頁面必須先注入配置信息,否則將無法調用(同一個url僅需調用一次,對于變化url的SPA的web app可在每次url變化時進行調用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來實現web app的頁面會導致簽名失敗,此問題會在Android6.2中修復)。
即:
| wx.config({ ????debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。 ????appId: '', // 必填,公眾號的唯一標識 ????timestamp: , // 必填,生成簽名的時間戳 ????nonceStr: '', // 必填,生成簽名的隨機串 ????signature: '',// 必填,簽名,見附錄1 ????jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2 }); |
1.微信支付類 WechatPay.php
| <?php ? namespace api\sdk; ? use Yii; ? class WechatPay { ? ????public function getSignPackage($url) { ????????$jsapiTicket = self::getJsApiTicket(); ? ????????$timestamp = time(); ????????$nonceStr = self::createNonceStr(); ? ????????// 這里參數的順序要按照 key 值 ASCII 碼升序排序 ????????$string = "jsapi_ticket=".$jsapiTicket."&noncestr=".$nonceStr."×tamp=".$timestamp."&url=".$url; ? ????????$signature = sha1($string); ? ????????$signPackage = array( ????????????"appId"???? => $this->appid, ????????????"nonceStr"? => $nonceStr, ????????????"timestamp" => $timestamp, ????????????"url"?????? => $url, ????????????"signature" => $signature, ????????????"rawString" => $string ????????); ????????return $signPackage; ????} ? ????public static function getJsApiTicket() { ????????//使用Redis緩存 jsapi_ticket ????????$redis = Yii::$app->redis; ????????$redis_ticket = $redis->get('wechat:jsapi_ticket'); ????????if ($redis_ticket) { ????????????$ticket = $redis_ticket; ????????} else { ????????????$accessToken = self::getAccessToken(); ????????????$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$accessToken; ????????????$res = json_decode(self::curlGet($url)); ????????????$ticket = $res->ticket; ????????????if ($ticket) { ????????????????$redis->set('wechat:jsapi_ticket', $ticket); ????????????????$redis->expire('wechat:jsapi_ticket', 7000); ????????????} ????????} ????????return $ticket; ????} ? ????public static function getAccessToken() { ????????//使用Redis緩存 access_token ????????$redis = Yii::$app->redis; ????????$redis_token = $redis->get('wechat:access_token'); ????????if ($redis_token) { ????????????$access_token = $redis_token; ????????} else { ????????????$appid = Yii::$app->params['wechat']['appid']; ????????????$appsecret = Yii::$app->params['wechat']['appsecret']; ????????????$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret; ????????????$res = json_decode(self::curlGet($url)); ????????????$access_token = $res->access_token; ????????????if ($access_token) { ????????????????$redis->set('wechat:access_token', $access_token); ????????????????$redis->expire('wechat:access_token', 7000); ????????????} ????????} ????????return $access_token; ????} ? ????public static function curlGet($url = '', $options = array()){ ????????$ch = curl_init($url); ????????curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); ????????curl_setopt($ch, CURLOPT_TIMEOUT, 30); ????????if (!empty($options)) { ????????????curl_setopt_array($ch, $options); ????????} ????????//https請求 不驗證證書和host ????????curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); ????????curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); ????????$data = curl_exec($ch); ????????curl_close($ch); ????????return $data; ????} ? ????public static function curlPost($url = '', $postData = '', $options = array()){ ????????if (is_array($postData)) { ????????????$postData = http_build_query($postData); ????????} ????????$ch = curl_init(); ????????curl_setopt($ch, CURLOPT_URL, $url); ????????curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); ????????curl_setopt($ch, CURLOPT_POST, 1); ????????curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); ????????curl_setopt($ch, CURLOPT_TIMEOUT, 30); //設置cURL允許執行的最長秒數 ????????if (!empty($options)) { ????????????curl_setopt_array($ch, $options); ????????} ????????//https請求 不驗證證書和host ????????curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); ????????curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); ????????$data = curl_exec($ch); ????????curl_close($ch); ????????return $data; ????} ? ????public static function createNonceStr($length = 16){ ????????$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; ????????$str = ''; ????????for ($i = 0; $i<$length; $i++){ ????????????$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); ????????} ????????return $str; ????} ? } |
2.獲取config參數接口
| public function actionConfig(){ ????if (isset($_REQUEST['url'])) { ????????$url = $_REQUEST['url']; ????????//微信支付參數 ????????$appid = Yii::$app->params['wechat']['appid']; ????????$mchid = Yii::$app->params['wechat']['mchid']; ????????$key = Yii::$app->params['wechat']['key']; ????????$wx_pay = new WechatPay($mchid, $appid, $key); ????????$package = $wx_pay->getSignPackage($url); ????????$result['error'] = 0; ????????$result['msg'] = '獲取成功'; ????????$result['config'] = $package; ????} else { ????????$result['error'] = 1; ????????$result['msg'] = '參數錯誤'; ????} ????return $result; } |
以上就是Yii2.0實現微信公眾號后臺開發的詳細內容
?
?
?
G
M
T
?
?
| ? | Detect languageAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu | ? | AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu | ? | ? | ? ? | ? | ? |
?
?
?
Text-to-speech function is limited to 200 characters
?
| ? | ? | Options : History : Feedback : Donate | Close |
| Detect languageAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu | AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu |
| Options : History : Feedback : Donate | Close |
轉載于:https://my.oschina.net/botkenni/blog/1819322
總結
以上是生活随笔為你收集整理的Yii2.0实现微信公众号后台开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ 3489: A simple
- 下一篇: tensorflow省钱方案-ml-en