PHP实现微信支付功能开发代码分享

小云云
发布: 2023-03-21 06:46:02
原创
6495 人浏览过

本文主要和大家详细介绍了PHP微信支付开发过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能帮助到大家。

1.开发环境 
Thinkphp 3.2.3 
微信:服务号,已认证 
开发域名:http://test.paywechat.com (自定义的域名,外网不可访问)

2.需要相关文件和权限 
微信支付需申请开通 
微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 
微信支付开发者文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 
微信支付SDK下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

3.开发 
下载好微信支付PHP版本的SDK,文件目录为下图:

这里写图片描述

这里写图片描述 

把微信支付SDK的Cert和Lib目录放入Thinkphp,目录为 

这里写图片描述 

现在介绍微信支付授权目录问题,首先是微信支付开发配置里面的支付授权目录填写, 

这里写图片描述

然后填写js接口安全域。

这里写图片描述

最后设置网页授权 

这里写图片描述

这里写图片描述

这些设置完,基本完成一半,注意设置的目录和我thinkphp里面的目录。 

这里写图片描述

4.微信支付配置

这里写图片描述

把相关配置填写正确。




[php] view plain copy


  1. /** 

  2. * 配置账号信息 

  3. */  

  4.   

  5. class WxPayConfig  

  6. {  

  7.  //=======【基本信息设置】=====================================  

  8.  //  

  9.  /** 

  10.  * TODO: 修改这里配置为您自己申请的商户信息 

  11.  * 微信公众号信息配置 

  12.  *  

  13.  * APPID:绑定支付的APPID(必须配置,开户邮件中可查看) 

  14.  *  

  15.  * MCHID:商户号(必须配置,开户邮件中可查看) 

  16.  *  

  17.  * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置) 

  18.  * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert 

  19.  *  

  20.  * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置), 

  21.  * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN 

  22.  * @var string 

  23.  */  

  24.  const APPID = '';  

  25.  const MCHID = '';  

  26.  const KEY = '';  

  27.  const APPSECRET = '';  

  28.   

  29.  //=======【证书路径设置】=====================================  

  30.  /** 

  31.  * TODO:设置商户证书路径 

  32.  * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载, 

  33.  * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书) 

  34.  * @var path 

  35.  */  

  36.  const SSLCERT_PATH = '../cert/apiclient_cert.pem';  

  37.  const SSLKEY_PATH = '../cert/apiclient_key.pem';  

  38.   

  39.  //=======【curl代理设置】===================================  

  40.  /** 

  41.  * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0 

  42.  * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器, 

  43.  * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置) 

  44.  * @var unknown_type 

  45.  */  

  46.  const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";  

  47.  const CURL_PROXY_PORT = 0;//8080;  

  48.   

  49.  //=======【上报信息配置】===================================  

  50.  /** 

  51.  * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】, 

  52.  * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少 

  53.  * 开启错误上报。 

  54.  * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报 

  55.  * @var int 

  56.  */  

  57.  const REPORT_LEVENL = 1;  

  58. }  

现在开始贴出代码:




[php] view plain copy


  1. namespace Wechat\Controller;  

  2. use Think\Controller;  

  3. /** 

  4.  * 父类控制器,需要继承 

  5.  * @file ParentController.class.php 

  6.  * @author Gary  

  7.  * @date 2015年8月4日 

  8.  * @todu 

  9.  */  

  10. class ParentController extends Controller {   

  11.  protected $options = array (  

  12.  'token' => ''// 填写你设定的key  

  13.  'encodingaeskey' => ''// 填写加密用的EncodingAESKey  

  14.  'appid' => ''// 填写高级调用功能的app id  

  15.  'appsecret' => ''// 填写高级调用功能的密钥  

  16.  'debug' => false,  

  17.  'logcallback' => ''  

  18.  );   

  19.  public $errCode = 40001;   

  20.  public $errMsg = "no access";   

  21.   

  22.  /** 

  23.  * 获取access_token 

  24.  * @return mixed|boolean|unknown 

  25.  */  

  26.  public function getToken(){  

  27.  $cache_token = S('exp_wechat_pay_token');  

  28.  if(!empty($cache_token)){  

  29.  return $cache_token;  

  30.  }  

  31.  $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s';  

  32.  $url = sprintf($url,$this->options['appid'],$this->options['appsecret']);   

  33.  $result = $this->http_get($url);  

  34.  $result = json_decode($result,true);   

  35.  if(empty($result)){  

  36.  return false;  

  37.  }   

  38.  S('exp_wechat_pay_token',$result['access_token'],array('type'=>'file','expire'=>3600));  

  39.  return $result['access_token'];  

  40.  }  

  41.   

  42.  /** 

  43.  * 发送客服消息 

  44.  * @param array $data 消息结构{"touser":"OPENID","msgtype":"news","news":{...}} 

  45.  */  

  46.  public function sendCustomMessage($data){  

  47.  $token = $this->getToken();  

  48.  if (empty($token)) return false;   

  49.  $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s';  

  50.  $url = sprintf($url,$token);  

  51.  $result = $this->http_post($url,self::json_encode($data));  

  52.  if ($result)  

  53.  {  

  54.  $json = json_decode($result,true);  

  55.  if (!$json || !empty($json['errcode'])) {  

  56.  $this->errCode = $json['errcode'];  

  57.  $this->errMsg = $json['errmsg'];  

  58.  return false;  

  59.  }  

  60.  return $json;  

  61.  }  

  62.  return false;  

  63.  }  

  64.   

  65.  /** 

  66.  * 发送模板消息 

  67.  * @param unknown $data 

  68.  * @return boolean|unknown 

  69.  */  

  70.  public function sendTemplateMessage($data){  

  71.  $token = $this->getToken();  

  72.  if (empty($token)) return false;  

  73.  $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";  

  74.  $url = sprintf($url,$token);  

  75.  $result = $this->http_post($url,self::json_encode($data));  

  76.  if ($result)  

  77.  {  

  78.  $json = json_decode($result,true);  

  79.  if (!$json || !empty($json['errcode'])) {  

  80.  $this->errCode = $json['errcode'];  

  81.  $this->errMsg = $json['errmsg'];  

  82.  return false;  

  83.  }  

  84.  return $json;  

  85.  }  

  86.  return false;  

  87.  }  

  88.   

  89.   

  90.  public function getFileCache($name){  

  91.  return S($name);  

  92.  }  

  93.   

  94.  /** 

  95.  * 微信api不支持中文转义的json结构 

  96.  * @param array $arr 

  97.  */  

  98.  static function json_encode($arr) {  

  99.  $parts = array ();  

  100.  $is_list = false;  

  101.  //Find out if the given array is a numerical array  

  102.  $keys = array_keys ( $arr );  

  103.  $max_length = count ( $arr ) - 1;  

  104.  if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //See if the first key is 0 and last key is length - 1  

  105.  $is_list = true;  

  106.  for($i = 0; $i < count ( $keys ); $i ++) { //See if each key correspondes to its position

  107. if ($i != $keys [$i]) { //A key fails at position check.

  108. $is_list = false; //It is an associative array.

  109. break;

  110. }

  111. }

  112. }

  113. foreach ( $arr as $key => $value ) {  

  114.  if (is_array ( $value )) { //Custom handling for arrays  

  115.  if ($is_list)  

  116.   $parts [] = self::json_encode ( $value ); /* :RECURSION: */  

  117.  else  

  118.   $parts [] = '"' . $key . '":' . self::json_encode ( $value ); /* :RECURSION: */  

  119.  } else {  

  120.  $str = '';  

  121.  if (! $is_list)  

  122.   $str = '"' . $key . '":';  

  123.  //Custom handling for multiple data types  

  124.  if (!is_string ( $value ) && is_numeric ( $value ) && $value<2000000000)

  125. $str .= $value; //Numbers

  126. elseif ($value === false)

  127. $str .= 'false'; //The booleans

  128. elseif ($value === true)

  129. $str .= 'true';

  130. else

  131. $str .= '"' . addslashes ( $value ) . '"'; //All other things

  132. // :TODO: Is there any more datatype we should be in the lookout for? (Object?)

  133. $parts [] = $str;

  134. }

  135. }

  136. $json = implode ( ',', $parts );

  137. if ($is_list)

  138. return '[' . $json . ']'; //Return numerical JSON

  139. return '{' . $json . '}'; //Return associative JSON

  140. }

  141. /**

  142. +----------------------------------------------------------

  143. * 生成随机字符串

  144. +----------------------------------------------------------

  145. * @param int $length 要生成的随机字符串长度

  146. * @param string $type 随机码类型:0,数字+大小写字母;1,数字;2,小写字母;3,大写字母;4,特殊字符;-1,数字+大小写字母+特殊字符

  147. +----------------------------------------------------------

  148. * @return string

  149. +----------------------------------------------------------

  150. */

  151. static public function randCode($length = 5, $type = 2){

  152. $arr = array(1 => "0123456789", 2 => "abcdefghijklmnopqrstuvwxyz", 3 => "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 4 => "~@#$%^&*(){}[]|");  

  153.  if ($type == 0) {  

  154.  array_pop($arr);  

  155.  $string = implode(""$arr);  

  156.  } elseif ($type == "-1") {  

  157.  $string = implode(""$arr);  

  158.  } else {  

  159.  $string = $arr[$type];  

  160.  }  

  161.  $count = strlen($string) - 1;  

  162.  $code = '';  

  163.  for ($i = 0; $i < $length; $i++) {

  164. $code .= $string[rand(0, $count)];

  165. }

  166. return $code;

  167. }

  168. /**

  169. * GET 请求

  170. * @param string $url

  171. */

  172. private function http_get($url){

  173. $oCurl = curl_init();

  174. if(stripos($url,"https://")!==FALSE){

  175. curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);

  176. curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);

  177. curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1

  178. }

  179. curl_setopt($oCurl, CURLOPT_URL, $url);

  180. curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );

  181. $sContent = curl_exec($oCurl);

  182. $aStatus = curl_getinfo($oCurl);

  183. curl_close($oCurl);

  184. if(intval($aStatus["http_code"])==200){

  185. return $sContent;

  186. }else{

  187. return false;

  188. }

  189. }

  190. /**

  191. * POST 请求

  192. * @param string $url

  193. * @param array $param

  194. * @param boolean $post_file 是否文件上传

  195. * @return string content

  196. */

  197. private function http_post($url,$param,$post_file=false){

  198. $oCurl = curl_init();

  199. if(stripos($url,"https://")!==FALSE){

  200. curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);

  201. curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);

  202. curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1

  203. }

  204. if (is_string($param) || $post_file) {

  205. $strPOST = $param;

  206. } else {

  207. $aPOST = array();

  208. foreach($param as $key=>$val){  

  209.  $aPOST[] = $key."=".urlencode($val);  

  210.  }  

  211.  $strPOST = join("&"$aPOST);  

  212.  }  

  213.  curl_setopt($oCurl, CURLOPT_URL, $url);  

  214.  curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );  

  215.  curl_setopt($oCurl, CURLOPT_POST,true);  

  216.  curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);  

  217.  $sContent = curl_exec($oCurl);  

  218.  $aStatus = curl_getinfo($oCurl);  

  219.  curl_close($oCurl);  

  220.  if(intval($aStatus["http_code"])==200){  

  221.  return $sContent;  

  222.  }else{  

  223.  return false;  

  224.  }  

  225.  }  

  226. }  




[php] view plain copy


  1. namespace Wechat\Controller;  

  2. use Wechat\Controller\ParentController;  

  3. /** 

  4.  * 微信支付测试控制器 

  5.  * @file TestController.class.php 

  6.  * @author Gary  

  7.  * @date 2015年8月4日 

  8.  * @todu 

  9.  */  

  10. class TestController extends ParentController {  

  11.  private $_order_body = 'xxx';  

  12.  private $_order_goods_tag = 'xxx';  

  13.  public function __construct(){  

  14.  parent::__construct();  

  15.  require_once ROOT_PATH."Api/lib/WxPay.Api.php";  

  16.  require_once ROOT_PATH."Api/lib/WxPay.JsApiPay.php";  

  17.  }  

  18.   

  19.  public function index(){  

  20.  //①、获取用户openid  

  21.  $tools = new \JsApiPay();  

  22.  $openId = $tools->GetOpenid();   

  23.  //②、统一下单  

  24.  $input = new \WxPayUnifiedOrder();   

  25.  //商品描述  

  26.  $input->SetBody($this->_order_body);  

  27.  //附加数据,可以添加自己需要的数据,微信回异步回调时会附加这个数据  

  28.  $input->SetAttach('xxx');  

  29.  //商户订单号  

  30.  $out_trade_no = \WxPayConfig::MCHID.date("YmdHis");  

  31.  $input->SetOut_trade_no($out_trade_no);  

  32.  //总金额,订单总金额,只能为整数,单位为分   

  33.  $input->SetTotal_fee(1);  

  34.  //交易起始时间  

  35.  $input->SetTime_start(date("YmdHis"));  

  36.  //交易结束时间  

  37.  $input->SetTime_expire(date("YmdHis", time() + 600));  

  38.  //商品标记  

  39.  $input->SetGoods_tag($this->_order_goods_tag);  

  40.  //通知地址,接收微信支付异步通知回调地址 SITE_URL=http://test.paywechat.com/Charge  

  41.  $notify_url = SITE_URL.'/index.php/Test/notify.html';  

  42.  $input->SetNotify_url($notify_url);  

  43.  //交易类型  

  44.  $input->SetTrade_type("JSAPI");  

  45.  $input->SetOpenid($openId);  

  46.  $order = \WxPayApi::unifiedOrder($input);  

  47.  $jsApiParameters = $tools->GetJsApiParameters($order);  

  48.  //获取共享收货地址js函数参数  

  49.  $editAddress = $tools->GetEditAddressParameters();  

  50.   

  51.  $this->assign('openId',$openId);  

  52.  $this->assign('jsApiParameters',$jsApiParameters);  

  53.  $this->assign('editAddress',$editAddress);  

  54.  $this->display();   

  55.  }  

  56.   

  57.  /** 

  58.  * 异步通知回调方法 

  59.  */  

  60.  public function notify(){  

  61.  require_once ROOT_PATH."Api/lib/notify.php";  

  62.  $notify = new \PayNotifyCallBack();  

  63.  $notify->Handle(false);  

  64.  //这里的IsSuccess是我自定义的一个方法,后面我会贴出这个文件的代码,供参考。  

  65.  $is_success = $notify->IsSuccess();   

  66.  $bdata = $is_success['data'];   

  67.  //支付成功  

  68.  if($is_success['code'] == 1){   

  69.  $news = array(  

  70.   'touser' => $bdata['openid'],  

  71.   'msgtype' => 'news',  

  72.   'news' => array (  

  73.   'articles'=> array (  

  74.    array(  

  75.    'title' => '订单支付成功',  

  76.    'description' => "支付金额:{$bdata['total_fee']}\n".  

  77.    "微信订单号:{$bdata['transaction_id']}\n"  

  78.    'picurl' => '',  

  79.    'url' => ''   

  80.    )  

  81.   

  82.   )  

  83.   )  

  84.  );  

  85.  //发送微信支付通知  

  86.  $this->sendCustomMessage($news);   

  87.  }else{//支付失败  

  88.   

  89.  }  

  90.  }  

  91.   

  92.  /** 

  93.  * 支付成功页面 

  94.  * 不可靠的回调 

  95.  */  

  96.  public function ajax_PaySuccess(){  

  97.  //订单号  

  98.  $out_trade_no = I('post.out_trade_no');  

  99.  //支付金额  

  100.  $total_fee = I('post.total_fee');  

  101.  /*相关逻辑处理*/  

  102.   

  103.  }  

贴上模板HTML




[xhtml] view plain copy


  1. <html>  

  2. <head>  

  3.  <meta http-equiv="content-type" content="text/html;charset=utf-8"/>  

  4.  <meta name="viewport" content="width=device-width, initial-scale=1"/>   

  5.  <title>微信支付样例-支付title>  

  6.  <script type="text/javascript">  

  7.  //调用微信JS api 支付  

  8.  function jsApiCall()  

  9.  {  

  10.  WeixinJSBridge.invoke(  

  11.  'getBrandWCPayRequest',  

  12.  {$jsApiParameters},  

  13.  function(res){  

  14.  WeixinJSBridge.log(res.err_msg);  

  15.  //取消支付  

  16.  if(res.err_msg == 'get_brand_wcpay_request:cancel'){  

  17.  //处理取消支付的事件逻辑  

  18.  }else if(res.err_msg == "get_brand_wcpay_request:ok"){  

  19.  /*使用以上方式判断前端返回,微信团队郑重提示:  

  20.  res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。  

  21.  这里可以使用Ajax提交到后台,处理一些日志,如Test控制器里面的ajax_PaySuccess方法。  

  22.  */  

  23.  }  

  24.  alert(res.err_code+res.err_desc+res.err_msg);  

  25.  }  

  26.  );  

  27.  }  

  28.   

  29.  function callpay()  

  30.  {  

  31.  if (typeof WeixinJSBridge == "undefined"){  

  32.  if( document.addEventListener ){  

  33.  document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);  

  34.  }else if (document.attachEvent){  

  35.  document.attachEvent('WeixinJSBridgeReady', jsApiCall);   

  36.  document.attachEvent('onWeixinJSBridgeReady', jsApiCall);  

  37.  }  

  38.  }else{  

  39.  jsApiCall();  

  40.  }  

  41.  }  

  42.  //获取共享地址  

  43.  function editAddress()  

  44.  {  

  45.  WeixinJSBridge.invoke(  

  46.  'editAddress',  

  47.  {$editAddress},  

  48.  function(res){  

  49.  var value1 = res.proviceFirstStageName;  

  50.  var value2 = res.addressCitySecondStageName;  

  51.  var value3 = res.addressCountiesThirdStageName;  

  52.  var value4 = res.addressDetailInfo;  

  53.  var tel = res.telNumber;   

  54.  alert(value1 + value2 + value3 + value4 + ":" + tel);  

  55.  }  

  56.  );  

  57.  }  

  58.   

  59.  window.onload = function(){  

  60.  if (typeof WeixinJSBridge == "undefined"){  

  61.  if( document.addEventListener ){  

  62.  document.addEventListener('WeixinJSBridgeReady', editAddress, false);  

  63.  }else if (document.attachEvent){  

  64.  document.attachEvent('WeixinJSBridgeReady', editAddress);   

  65.  document.attachEvent('onWeixinJSBridgeReady', editAddress);  

  66.  }  

  67.  }else{  

  68.  editAddress();  

  69.  }  

  70.  };  

  71.   

  72.  script>  

  73. head>  

  74. <body>  

  75.  <br/>  

  76.  <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分span>b>font><br/><br/>  

  77.  <p align="center">  

  78.  <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()" >立即支付button>  

  79.  p>  

  80. body>  

  81. html>  

notify.php文件代码,这里有在官方文件里新添加的一个自定义方法。




[php] view plain copy


  1. require_once ROOT_PATH."Api/lib/WxPay.Api.php";  

  2. require_once ROOT_PATH.'Api/lib/WxPay.Notify.php';  

  3. require_once ROOT_PATH.'Api/lib/log.php';  

  4.   

  5. //初始化日志  

  6. $logHandlernew \CLogFileHandler(ROOT_PATH."/logs/".date('Y-m-d').'.log');  

  7. $log = \Log::Init($logHandler, 15);  

  8.   

  9. class PayNotifyCallBack extends WxPayNotify  

  10. {  

  11.  protected $para = array('code'=>0,'data'=>'');  

  12.  //查询订单  

  13.  public function Queryorder($transaction_id)  

  14.  {  

  15.  $input = new \WxPayOrderQuery();  

  16.  $input->SetTransaction_id($transaction_id);  

  17.  $result = \WxPayApi::orderQuery($input);  

  18.  \Log::DEBUG("query:" . json_encode($result));  

  19.  if(array_key_exists("return_code"$result)  

  20.  && array_key_exists("result_code"$result)  

  21.  && $result["return_code"] == "SUCCESS"  

  22.  && $result["result_code"] == "SUCCESS")  

  23.  {  

  24.  return true;  

  25.  }  

  26.  $this->para['code'] = 0;  

  27.  $this->para['data'] = '';  

  28.  return false;  

  29.  }  

  30.   

  31.  //重写回调处理函数  

  32.  public function NotifyProcess($data, &$msg)  

  33.  {  

  34.  \Log::DEBUG("call back:" . json_encode($data));  

  35.  $notfiyOutput = array();  

  36.   

  37.  if(!array_key_exists("transaction_id"$data)){  

  38.  $msg = "输入参数不正确";  

  39.  $this->para['code'] = 0;  

  40.  $this->para['data'] = '';  

  41.  return false;  

  42.  }  

  43.  //查询订单,判断订单真实性  

  44.  if(!$this->Queryorder($data["transaction_id"])){  

  45.  $msg = "订单查询失败";  

  46.  $this->para['code'] = 0;  

  47.  $this->para['data'] = '';  

  48.  return false;  

  49.  }  

  50.   

  51.  $this->para['code'] = 1;  

  52.  $this->para['data'] = $data;  

  53.  return true;  

  54.  }  

  55.   

  56.  /** 

  57.  * 自定义方法 检测微信端是否回调成功方法 

  58.  * @return multitype:number string 

  59.  */  

  60.  public function IsSuccess(){  

  61.  return $this->para;  

  62.  }  

  63. }  

到这里基本上完成,可以在微信端打开http://test.paywechat.com/Charge/index.php/Test/index/
相关推荐:

nodejs实现微信支付功能实例详解

Thinkphp整合微信支付功能

怎么给PC端网站添加这种微信支付功能

以上是PHP实现微信支付功能开发代码分享的详细内容。更多信息请关注PHP中文网其他相关文章!

相关标签:
来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!