国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Rumah applet WeChat pembangunan WeChat 利用Yii2微信后臺(tái)開(kāi)發(fā)的詳細(xì)介紹

利用Yii2微信后臺(tái)開(kāi)發(fā)的詳細(xì)介紹

Mar 19, 2017 pm 06:07 PM

Yii2是一個(gè)高性能,基于組件的 PHP 框架,這篇文章詳細(xì)的給大家介紹了利用Yii2開(kāi)發(fā)微信后臺(tái)。我們一起來(lái)看看。

網(wǎng)上有很多關(guān)于YII2.0微信開(kāi)發(fā)教程,但是太過(guò)復(fù)雜凌亂,所以今天在這里給大家整理總結(jié)利用Yii2微信后臺(tái)開(kāi)發(fā)的系列了,給需要的小伙伴們參考。

一:接入微信

Yii2后臺(tái)配置

1.在app/config/params.php中配置token參數(shù)

return [
 //微信接入
 'wechat' =>[
 'token' => 'your token',
 ],
];

2.在app/config/main.php中配置路由

因?yàn)榻涌谀K使用的RESTful API,所以需要定義路由規(guī)則。

'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 = &#39;&#39;;

 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[&#39;wechat&#39;][&#39;token&#39;];
 if (!$token) {
  echo &#39;TOKEN is not defined!&#39;;
 } 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;
  }
 }
 }

}

微信公眾號(hào)后臺(tái)配置

在微信公眾號(hào)后臺(tái)配置URL和Token,然后提交驗(yàn)證即可。

URL:http://app.demo.com/wechats/valid
Token:your token

二:獲取用戶信息

用戶表設(shè)計(jì)

代碼如下:

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 &#39;微信昵稱&#39;,
  `sex` tinyint(4) NOT NULL COMMENT &#39;性別&#39;,
  `headimgurl` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT &#39;頭像&#39;,
  `country` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT &#39;國(guó)家&#39;,
  `province` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT &#39;省份&#39;,
  `city` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT &#39;城市&#39;,
  `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`);

獲取用戶信息的相關(guān)接口

1.用戶授權(quán)接口:獲取access_token、openId等;獲取并保存用戶資料到數(shù)據(jù)庫(kù)

代碼如下:

public function actionAccesstoken()
{
    $code = $_GET["code"];
    $state = $_GET["state"];
    $appid = Yii::$app->params[&#39;wechat&#39;][&#39;appid&#39;];
    $appsecret = Yii::$app->params[&#39;wechat&#39;][&#39;appsecret&#39;];
    $request_url = &#39;https://api.weixin.qq.com/sns/oauth2/access_token?appid=&#39;.$appid.&#39;&secret=&#39;.$appsecret.&#39;&code=&#39;.$code.&#39;&grant_type=authorization_code&#39;;
    //初始化一個(gè)curl會(huì)話
    $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成功,數(shù)據(jù)解析
    $access_token = $result[&#39;access_token&#39;];
    $refresh_token = $result[&#39;refresh_token&#39;];
    $openid = $result[&#39;openid&#39;];
    //請(qǐng)求微信接口,獲取用戶信息
    $userInfo = $this->getUserInfo($access_token,$openid);
    $user_check = WechatUser::find()->where([&#39;openid&#39;=>$openid])->one();
    if ($user_check) {
        //更新用戶資料
    } else {
        //保存用戶資料
    }
    //前端網(wǎng)頁(yè)的重定向
    if ($openid) {
        return $this->redirect($state.$openid);
    } else {
        return $this->redirect($state);
    }
}

2.從微信獲取用戶資料

代碼如下:

public function getUserInfo($access_token,$openid)
{
    $request_url = &#39;https://api.weixin.qq.com/sns/userinfo?access_token=&#39;.$access_token.&#39;&openid=&#39;.$openid.&#39;&lang=zh_CN&#39;;
    //初始化一個(gè)curl會(huì)話
    $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([&#39;openid&#39;=>$openid])->one();
  if ($user) {
   $result[&#39;error&#39;] = 0;
   $result[&#39;msg&#39;] = &#39;獲取成功&#39;;
   $result[&#39;user&#39;] = $user;
  } else {
   $result[&#39;error&#39;] = 1;
   $result[&#39;msg&#39;] = &#39;沒(méi)有該用戶&#39;;
  }
 } else {
  $result[&#39;error&#39;] = 1;
  $result[&#39;msg&#39;] = &#39;openid為空&#39;;
 }
 return $result;
}

三:微信支付

1.微信支付接口:打包支付數(shù)據(jù)

代碼如下:

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();
        //微信支付參數(shù)
        $appid = Yii::$app->params[&#39;wechat&#39;][&#39;appid&#39;];
        $mchid = Yii::$app->params[&#39;wechat&#39;][&#39;mchid&#39;];
        $key = Yii::$app->params[&#39;wechat&#39;][&#39;key&#39;];
        $notifyUrl = Yii::$app->params[&#39;wechat&#39;][&#39;notifyUrl&#39;];
        //支付打包
        $wx_pay = new WechatPay($mchid, $appid, $key);
        $package = $wx_pay->createJsBizPackage($uid, $totalFee, $oid, $notifyUrl, $timestamp);
        $result[&#39;error&#39;] = 0;
        $result[&#39;msg&#39;] = &#39;支付打包成功&#39;;
        $result[&#39;package&#39;] = $package;
        return $result;
    }else{
        $result[&#39;error&#39;] = 1;
        $result[&#39;msg&#39;] = &#39;請(qǐng)求參數(shù)錯(cuò)誤&#39;;
    }
    return $result;
}

2.接收微信發(fā)送的異步支付結(jié)果通知

代碼如下:

public function actionNotify(){
    $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
    $postObj = simplexml_load_string($postStr, &#39;SimpleXMLElement&#39;, LIBXML_NOCDATA);
    //
    if ($postObj === false) {
        die(&#39;parse xml error&#39;);
    }
    if ($postObj->return_code != &#39;SUCCESS&#39;) {
        die($postObj->return_msg);
    }
    if ($postObj->result_code != &#39;SUCCESS&#39;) {
        die($postObj->err_code);
    }
    //微信支付參數(shù)
    $appid = Yii::$app->params[&#39;wechat&#39;][&#39;appid&#39;];
    $mchid = Yii::$app->params[&#39;wechat&#39;][&#39;mchid&#39;];
    $key = Yii::$app->params[&#39;wechat&#39;][&#39;key&#39;];
    $wx_pay = new WechatPay($mchid, $appid, $key);
    //驗(yàn)證簽名
    $arr = (array)$postObj;
    unset($arr[&#39;sign&#39;]);
    if ($wx_pay->getSign($arr, $key) != $postObj->sign) {
        die("簽名錯(cuò)誤");
    }
    //支付處理正確-判斷是否已處理過(guò)支付狀態(tài)
    $orders = Order::find()->where([&#39;uid&#39;=>$postObj->openid, &#39;oid&#39;=>$postObj->out_trade_no, &#39;status&#39; => 0])->all();
    if(count($orders) > 0){
        //更新訂單狀態(tài)
        foreach ($orders as $order) {
            //更新訂單
            $order[&#39;status&#39;] = 1;
            $order->update();
        }
        return &#39;<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>&#39;;
    } else {
        //訂單狀態(tài)已更新,直接返回
        return &#39;<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>&#39;;
    }
}

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(
            &#39;mch_id&#39; => $this->mchid,
            &#39;appid&#39; => $this->appid,
            &#39;key&#39; => $this->key,
        );
        $unified = array(
            &#39;appid&#39; => $config[&#39;appid&#39;],
            &#39;attach&#39; => &#39;支付&#39;,
            &#39;body&#39; => $orderName,
            &#39;mch_id&#39; => $config[&#39;mch_id&#39;],
            &#39;nonce_str&#39; => self::createNonceStr(),
            &#39;notify_url&#39; => $notifyUrl,
            &#39;openid&#39; => $openid,
            &#39;out_trade_no&#39; => $outTradeNo,
            &#39;spbill_create_ip&#39; => &#39;127.0.0.1&#39;,
            &#39;total_fee&#39; => intval($totalFee * 100),
            &#39;trade_type&#39; => &#39;JSAPI&#39;,
        );
        $unified[&#39;sign&#39;] = self::getSign($unified, $config[&#39;key&#39;]);
        $responseXml = self::curlPost(&#39;https://api.mch.weixin.qq.com/pay/unifiedorder&#39;, self::arrayToXml($unified));
        $unifiedOrder = simplexml_load_string($responseXml, &#39;SimpleXMLElement&#39;, LIBXML_NOCDATA);
        if ($unifiedOrder === false) {
            die(&#39;parse xml error&#39;);
        }
        if ($unifiedOrder->return_code != &#39;SUCCESS&#39;) {
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != &#39;SUCCESS&#39;) {
            die($unifiedOrder->err_code);
        }
        $arr = array(
            "appId" => $config[&#39;appid&#39;],
            "timeStamp" => $timestamp,
            "nonceStr" => self::createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => &#39;MD5&#39;,
        );
        $arr[&#39;paySign&#39;] = self::getSign($arr, $config[&#39;key&#39;]);
        return $arr;
    }
    public static function curlGet($url = &#39;&#39;, $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請(qǐng)求 不驗(yàn)證證書(shū)和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 = &#39;&#39;, $postData = &#39;&#39;, $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); //設(shè)置cURL允許執(zhí)行的最長(zhǎng)秒數(shù)
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https請(qǐng)求 不驗(yàn)證證書(shū)和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 = &#39;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&#39;;
        $str = &#39;&#39;;
        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 = &#39;&#39;;
        if (strlen($buff)>0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
}

四:獲取JS-SDK的config參數(shù)

根據(jù)微信公眾平臺(tái)開(kāi)發(fā)者文檔:

所有需要使用JS-SDK的頁(yè)面必須先注入配置信息,否則將無(wú)法調(diào)用(同一個(gè)url僅需調(diào)用一次,對(duì)于變化url的SPA的web app可在每次url變化時(shí)進(jìn)行調(diào)用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來(lái)實(shí)現(xiàn)web app的頁(yè)面會(huì)導(dǎo)致簽名失敗,此問(wèn)題會(huì)在Android6.2中修復(fù))。

即:

代碼如下:

wx.config({
    debug: true, // 開(kāi)啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái),若要查看傳入的參數(shù),可以在pc端打開(kāi),參數(shù)信息會(huì)通過(guò)log打出,僅在pc端時(shí)才會(huì)打印。
    appId: &#39;&#39;, // 必填,公眾號(hào)的唯一標(biāo)識(shí)
    timestamp: , // 必填,生成簽名的時(shí)間戳
    nonceStr: &#39;&#39;, // 必填,生成簽名的隨機(jī)串
    signature: &#39;&#39;,// 必填,簽名,見(jiàn)附錄1
    jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表見(jiàn)附錄2
});

1.微信支付類 WechatPay.php

代碼如下:

<?php
namespace api\sdk;
use Yii;
class WechatPay
{
    public function getSignPackage($url) {
        $jsapiTicket = self::getJsApiTicket();
        $timestamp = time();
        $nonceStr = self::createNonceStr();
        // 這里參數(shù)的順序要按照 key 值 ASCII 碼升序排序
        $string = "jsapi_ticket=".$jsapiTicket."&noncestr=".$nonceStr."&timestamp=".$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(&#39;wechat:jsapi_ticket&#39;);
        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(&#39;wechat:jsapi_ticket&#39;, $ticket);
                $redis->expire(&#39;wechat:jsapi_ticket&#39;, 7000);
            }
        }
        return $ticket;
    }
    public static function getAccessToken() {
        //使用Redis緩存 access_token
        $redis = Yii::$app->redis;
        $redis_token = $redis->get(&#39;wechat:access_token&#39;);
        if ($redis_token) {
            $access_token = $redis_token;
        } else {
            $appid = Yii::$app->params[&#39;wechat&#39;][&#39;appid&#39;];
            $appsecret = Yii::$app->params[&#39;wechat&#39;][&#39;appsecret&#39;];
            $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(&#39;wechat:access_token&#39;, $access_token);
                $redis->expire(&#39;wechat:access_token&#39;, 7000);
            }
        }
        return $access_token;
    }
    public static function curlGet($url = &#39;&#39;, $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請(qǐng)求 不驗(yàn)證證書(shū)和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 = &#39;&#39;, $postData = &#39;&#39;, $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); //設(shè)置cURL允許執(zhí)行的最長(zhǎng)秒數(shù)
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https請(qǐng)求 不驗(yàn)證證書(shū)和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 = &#39;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&#39;;
        $str = &#39;&#39;;
        for ($i = 0; $i<$length; $i++){
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
}

2.獲取config參數(shù)接口

public function actionConfig(){
 if (isset($_REQUEST[&#39;url&#39;])) {
 $url = $_REQUEST[&#39;url&#39;];
 //微信支付參數(shù)
 $appid = Yii::$app->params[&#39;wechat&#39;][&#39;appid&#39;];
 $mchid = Yii::$app->params[&#39;wechat&#39;][&#39;mchid&#39;];
 $key = Yii::$app->params[&#39;wechat&#39;][&#39;key&#39;];
 $wx_pay = new WechatPay($mchid, $appid, $key);
 $package = $wx_pay->getSignPackage($url);
 $result[&#39;error&#39;] = 0;
 $result[&#39;msg&#39;] = &#39;獲取成功&#39;;
 $result[&#39;config&#39;] = $package;
 } else {
 $result[&#39;error&#39;] = 1;
 $result[&#39;msg&#39;] = &#39;參數(shù)錯(cuò)誤&#39;;
 }
 return $result;
}

Atas ialah kandungan terperinci 利用Yii2微信后臺(tái)開(kāi)發(fā)的詳細(xì)介紹. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial PHP
1502
276