找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 68|回复: 0

[扩展开发] Discuz 插件开发【旗舰版】 二次开发 - 在线手册

[复制链接]
发表于 2025-7-2 17:00:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

您需要 登录 才可以下载或查看,没有账号?立即注册

×
验证插件二次开发

本功能由PHP+MYSQL语言开发,无缝对接新秀网络验证系统,采用独立入口文件、类文件、第三方类文件库进行调用开发。所有功能实现及控制均采用api接口操作,数据输出形式为JSON、XML两种常见形式,达到毫秒级数据快速交换功能。

1、插件开发是结合新秀网络验证系统进行的二次开发,不能独立使用;

2、插件开发遵循Discuz、新秀网络验证、PHP语言规范开发;

3、插件开发适用于新秀网络验证系统旗舰版ver1.0版本以后;

4、本功能与新秀网络验证系统、扩展框架系统,代码相互独立,但功能同时执行;

5、插件开发可使用Discuz内置函数、新秀网络验证内置函数、PHP函数。

适用环境:php版本>7.1、Mysql版本>5.7以上、Discuz版本>3.5。

= Discuz资料库  = Discuz插件开发文档  = 开发交流  =  BUG反馈  =  QQ客服:3188639  QQ交流群:281079920


( S5 a3 X! J: ?$ X% j! R4 p
接口开发常用函数

1、DB数据库操作函数    /*常用MYSQL数据库操作命令,增、减、改、查功能函数。*/

2、新秀网络验证数据库对照表    /*新秀网络验证系统内部,所有数据库表及说明*/

3、Discuz官方数据库对照表  /*Discuz官方数据库表,包括discuz、UCente数据库字典。*/

4、Discuz基础框架、类、函数    /*包含Discuz官方基础框架、类、函数、方法使用说明。*/

5、新秀网络基础框架类、函数    /*包含新秀网络验证基础框架、类、函数、方法使用说明。*/

3 O2 v" v! |! x* \
使 用 简 介

1、插件开发演示文件下载(IP地址查询)

ip.zip (8.99 KB, 下载次数: 5)

2、插件开发演示文件目录说明

xinxiuvip_network_plugin \\新秀网络验证应用中心插件主目录

—lib \\自定义类存放目录 (用于开发者存放第三方类、自定义类)

——lib_ip.php \\自定义方法库开发文件 (自定义开发接口方法库)

—function \\自定义方法存放目录 (用于开发者存放自定义开发接口类和方法)

——function_ip.php \\自定义方法类开发文件 (自定义开发接口方法类)

—plugins \\插件数据库代码存放目录 (用于开发者存放插件数据库执行代码)

—ip\\插件名目录

——extend_network.php \\设置插件数据库执行代码文件(数据新增、更新、删除,接口增加、删除功能,插件安装和卸载代码)

template/plugin/admin \\插件前端htm开发存放目录(根据discuz官方插件前台开发代码进行开发

—ip\\插件名目录

——ip.htm \\插件后台设置文件(根据discuz官方插件后台开发代码进行开发,并在插件设计页面自行增加插件设置文件入口)

ip.inc.php \\自定义接口入口开发文件

3、如何安装、开发、调试?

#1、下载演示文件后,上传至新秀网络验证应用中心插件根目录。discuz论坛插件根目录 \source\plugin\xinxiuvip_network_plugin\

#2、使用PHP代码编辑软件,对入口文件 ip.inc.php 和 自定义方法类文件 function_ip.php 等进行开发。

#3、如需新增接口文件,请根据演示文件,修改 “ip” 为您想要的文件名,但不能与新秀框架插件内文件名冲突,且开发的接口方法,不能与新秀框架冲突

#4、如何发布自己开发的插件并获取一定收益,请联系客服QQ:

#5、功能代码开发完成,组装调试接口:


//根据演示文件中组装url接口地址

http://demo35.xinxiuvip.com/plugin.php?id=xinxiuvip_network_plugin:ip&action=ip_cha&key=123456&ip=14.21.97.153


[PHP] 纯文本查看 复制代码
{
        "code": 200,
        "result": "OK",
        "count": 2,
        "data": {
                "ip": "14.21.97.153",
                "dizhi": "- 广东"
        },
        "sqltime": "0.027s",
}

ip.inc.php入口文件代码实例
[PHP] 纯文本查看 复制代码
<?php
#========================================
#以下两行代码,用于开发环境下代码错误提示,可根据提示信息进行代码检查,无误后即可注释掉!
//ini_set("display_errors", "on");
//error_reporting(E_ALL);
#========================================

#========================================
#防止游客直接输入网址进行访问,权限检测,勿动!!!
if (!defined('IN_DISCUZ')) {
    exit('Access Denied');
}
#========================================

#========================================
#引入自定义开发类文件,此文件保存位置 'function/ip' 代表 function/function_ip.php 如需修改请按格式进行!
C::import('function/ip', 'plugin/xinxiuvip_network_plugin', false);//注意这里插件开发和接口二次开发不同!
$api = new function_ip();//实例化function_ip.php类操作,实例化后可用$api->调用function_ip.php中的类方法!
#========================================


#此处为入口文件,根据接口方法,调用对应类方法。
switch ($api->action) { //$api->action 获取入口方法,勿动!!!

    #========================================
    case 'ip_cha': // 判断是否是此方法,如果是则进入下一步!
        $ip =  web_client::safe_check('ip', true); //判断参数传输,params为参数名称,iscore为是否是必填项(true为必填,false为可空)
        $api->ip_cha($ip);//调用function_ip.php实例化后类方法,根据类方法设置传入参数。
        break;
    #此处代码根据接口开发需求,可以无限添加循环。
    #========================================

    #========================================
    #此处代码是判断接口输入是否正确。勿删!!!
    default:
        web_output::json_output(400,'error010');
        break;
    #========================================
}
: I& h  Z% \2 f9 z# l# m
function_ip.php自定义方法类代码实例
[PHP] 纯文本查看 复制代码
<?php
#========================================
#以下两行代码,用于开发环境下代码错误提示,可根据提示信息进行代码检查,无误后即可注释掉!
//ini_set("display_errors", "on");
//error_reporting(E_ALL);
#========================================

#========================================
#防止游客直接输入网址进行访问,权限检测,勿动!!!
if (!defined('IN_DISCUZ')) {
    exit('Access Denied');
}
#========================================

#========================================
#引入核心系统类,勿删!!!
C::import('class/plugin','plugin/xinxiuvip_network_plugin',false);
#========================================


#如何引入自定义系统类?
#1、将自定义核心类、第三方核心类上传至extend文件夹下;
#2、通过 C::import 、 require_once 两种引入形式引入第三方核心类;
#3、在下方方法中使用 lib_ip::convertip_tiny($ip, $ipdatafile); 进行调用,具体功能看lib_ip封装代码;
C::import('lib/ip', 'plugin/xinxiuvip_network_plugin', false);//如果没有自定义类库,请将此处注释掉!
#注释结束


class function_ip extends class_plugin
{
    public $action_all = array('ip_cha');//所有接口必填,用逗号隔开!!!除以下key、adminkey所包含以外,未包含的接口都是通过token令牌进行访问。
    public $function_action_key = array('ip_cha');//使用key密钥访问的接口
    public $function_action_adminkey = array();//使用管理密钥adminkey访问的接口

    /**
     * 构造方法 __construct() 是在实例化对象时被自动调用
     * 用途:可以用于初始化程序(可以给成员属性赋值,也可以调用成员方法)
     */
    public function __construct(){
        $this->plugin_config;//是后台插件设置的数据,可在本页面进行调用。
        parent::__construct();//注意这里和接口二次开发不同
    }

    #========================================
    #此处为标准类方法,可根据DISCUZ、新秀网络验证内置函数进行调用,也可使用PHP官方函数进行操作。
    public function ip_cha($ip){

        #-具体DISCUZ内置函数、新秀网络验证内置函数、PHP函数,论坛相应帖子有专门介绍。
        $tinyipfile = DISCUZ_ROOT.'./data/ipdata/tinyipdata.dat';

        $data = lib_ip::convertip_tiny($ip,$tinyipfile);//调用lib自定义封装类库示例;
       
        $data_array = array(
            'ip'=>$ip,
            'dizhi'=>$data,
        );


        #========================================
        #嵌入插件开发钩子,注意:此扩展方法在应用中心扩展文件中使用‘extend_plugin.php’;
        web_client::class_hook('hook_ip_cha',array('ip'=>$ip));

        /*
         * 下面是插件拓展对应的方法
         * 注意class_hook中的'hook_ip_cha' 就是扩展文件中的方法名!
         *
        public function hook_ip_cha($ip){
            var_dump($ip);
        }
        */
        #========================================



        $data ? web_output::json_output(200,'OK',$data_array): web_output::json_output(400,'请检查IP地址是否正确!');
        #-具体DISCUZ内置函数、新秀网络验证内置函数、PHP函数,论坛相应帖子有专门介绍。
    }
    #========================================

    /**
     * 析构方法 __destruct() 是在对象被销毁时自动调用
     * 用途:可以进行资源的释放操作或文件的关闭操作或信息保存操作
     */
    public function __destruct()
    {
        return parent::__destruct(); // TODO: 析构方法
    }

}

: ]" P, r% h0 |; ^( B! v
lib_ip.php自定义方法类库代码实例
[PHP] 纯文本查看 复制代码
<?php
#以下两行代码,用于开发环境下代码错误提示,可根据提示信息进行代码检查,无误后即可注释掉!
//ini_set("display_errors", "on");
//error_reporting(E_ALL);
#注释结束

#引入验证自带核心系统类,勿删!!!
C::import('class/xinxiu', 'plugin/xinxiuvip_network', false);
#注释结束

class lib_ip
{

    /**
     * 自定义方法类库,用于扩展系统功能!
     * 1、在function_ip.php中引用此类库,直接调用方法即可!
     * 2、引用代码:C::import('lib/ip', 'plugin/xinxiuvip_network_plugin', false);//引用自定义类库!
     * 3、此方法为纯静态方法,无需实例化,可直接调用!
     * 4、调用代码:lib_ip::convertip_tiny($ip,$tinyipfile);//调用lib自定义封装类库示例!
     */
      public static function convertip_tiny($ip, $ipdatafile) {

        static $fp = NULL, $offset = array(), $index = NULL;

        $ipdot = explode('.', $ip);
        $ip    = pack('N', ip2long($ip));

        $ipdot[0] = (int)$ipdot[0];
        $ipdot[1] = (int)$ipdot[1];

        if($fp === NULL && $fp = @fopen($ipdatafile, 'rb')) {
            $offset = @unpack('Nlen', @fread($fp, 4));
            $index  = @fread($fp, $offset['len'] - 4);
        } elseif($fp == FALSE) {
            return  '- Invalid IP data file';
        }

        $length = $offset['len'] - 1028;
        $start  = @unpack('Vlen', $index[$ipdot[0] * 4] . $index[$ipdot[0] * 4 + 1] . $index[$ipdot[0] * 4 + 2] . $index[$ipdot[0] * 4 + 3]);

        for ($start = $start['len'] * 8 + 1024; $start < $length; $start += 8) {

            if ($index[$start] . $index[$start + 1] . $index[$start + 2] . $index[$start + 3] >= $ip) {
                $index_offset = @unpack('Vlen', $index[$start + 4] . $index[$start + 5] . $index[$start + 6] . "\x0");
                $index_length = @unpack('Clen', $index[$start + 7]);
                break;
            }
        }

        @fseek($fp, $offset['len'] + $index_offset['len'] - 1024);
        if($index_length['len']) {
            return '- '.@fread($fp, $index_length['len']);
        } else {
            return '- Unknown';
        }

    }
}

+ j/ D1 K* M2 K, d6 I7 r+ m
ip.htm插件后台设置文件
[HTML] 纯文本查看 复制代码
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>插件设置页面</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="/source/plugin/xinxiuvip_network/template/res/layui/css/layui.css" rel="stylesheet">
    <link href="/source/plugin/xinxiuvip_network/template/res/adminui/dist/css/admin.css" rel="stylesheet">
</head>
<style>
    body {
        background-color: #ffffff;
    }
</style>

<body>

    <div class="layui-fluid">
        <div class="layui-main">
            <blockquote class="layui-elem-quote">
                此页面为插件后台设置页面,请根据具体文档进行设置。
                <a href="http://www.xinxiuvip.com/forum.php?mod=viewthread&tid=649" target="_blank">【插件开发文档】</a>
            </blockquote>
            <div class="layui-form" id="form" lay-filter="form" action="">


                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label">radio开关类</label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <!--{if $plugin_config['status'] == 0}-->
                        <input name="status" type="radio" value="0" checked="" title="正常" lay-skin="primary">
                        <input name="status" type="radio" value="1" title="禁止" lay-skin="primary">
                        <input name="status" type="radio" value="2" title="其他" lay-skin="primary">
                        <!--{elseif $plugin_config['status'] == 1}-->
                        <input name="status" type="radio" value="0" title="正常" lay-skin="primary">
                        <input name="status" type="radio" value="1" checked="" title="禁止" lay-skin="primary">
                        <input name="status" type="radio" value="2" title="其他" lay-skin="primary">
                        <!--{elseif $plugin_config['status'] == 2}-->
                        <input name="status" type="radio" value="0" title="正常" lay-skin="primary">
                        <input name="status" type="radio" value="1" title="禁止" lay-skin="primary">
                        <input name="status" type="radio" value="2" checked="" title="其他" lay-skin="primary">
                        <!--{/if}-->
                    </div>
                    <div class="layui-form-mid layui-word-aux">radio开关类注释</div>
                </div>

                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label">text文本</label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <input type="text" name="text" value="{$plugin_config['text']}" autocomplete="off"
                            class="layui-input" style="width: 99%;">
                    </div>
                    <div class="layui-form-mid layui-word-aux">text文本注释</div>
                </div>

                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label">text文本验证</label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <input type="password" name="password" value="{$plugin_config['password']}" autocomplete="off"
                            class="layui-input" style="width: 99%;">
                    </div>
                    <div class="layui-form-mid layui-word-aux">text文本验证注释</div>
                </div>

                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label">
                        textarea文本
                    </label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <textarea class="layui-textarea" name="textarea" style="width: 99%;">{$plugin_config['textarea']}
                                                </textarea>
                    </div>
                    <div class="layui-form-mid layui-word-aux">
                        textarea文本域注释
                    </div>
                </div>
                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label">select下拉框</label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <select name="select">
                            <option value="">请选择</option>
                            <!--{if $plugin_config['select'] == 1}-->
                            <option value="1" selected>value为1</option>
                            <!--{else}-->
                            <option value="1">value为1</option>
                            <!--{/if}-->
                            <!--{if $plugin_config['select'] == 2}-->
                            <option value="2" selected>value为2</option>
                            <!--{else}-->
                            <option value="2">value为2</option>
                            <!--{/if}-->
                            <!--{if $plugin_config['select'] == 3}-->
                            <option value="3" selected>value为3</option>
                            <!--{else}-->
                            <option value="3">value为3</option>
                            <!--{/if}-->
                        </select>
                    </div>
                    <div class="layui-form-mid layui-word-aux">select下拉框注释</div>
                </div>
                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label">时间选择</label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <input type="text" name="groupline" value="{$plugin_config['groupline']}"
                            id="form-date" placeholder="yyyy-MM-dd HH:mm:ss" autocomplete="off"
                            class="layui-input" style="width: 99%;">
                    </div>
                    <div class="layui-form-mid layui-word-aux">时间选择注释</div>
                </div>

                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label">
                        选择积分
                    </label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <select name="credits">
                            {$plugin_config['credits']}
                        </select>
                    </div>
                    <div class="layui-form-mid layui-word-aux">
                        内置选择积分类型。
                    </div>
                </div>
                <div class="layui-form-item adminj-sort-item" style="width: 100%;">
                    <label class="layui-form-label" style="margin-top: -3px;">
                        选择会员组
                    </label>
                    <div class="layui-input-inline" style="width: 30%;">
                        <select name="groupids" lay-ignore="" class="layui-select-group layui-select-tips"
                            multiple="multiple" data-placeholder="" data-dropdown-css-class="select2-purple"
                            style="width: 99%;height: 200px;">
                            {$plugin_config['groupids']}
                        </select>
                    </div>
                    <div class="layui-form-mid layui-word-aux">
                        内置选择会员组。
                    </div>
                </div>
                <div class="layui-form-item adminj-sort-item">
                    <div class="layui-input-block">
                        <button type="submit" class="layui-btn" lay-submit="" lay-filter="postButton" id="postButton">
                            立即修改
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script src="/source/plugin/xinxiuvip_network/template/res/layui/layui.js?t=1"></script>


    <script>
        layui.use(['form', 'layer', 'jquery'], function () {
            var form = layui.form;
            var layer = layui.layer;
            var $ = layui.jquery;
            var laydate = layui.laydate;

            laydate.render({
                elem: '#form-date',
                type: 'datetime',
                fullPanel: true // 2.8+
            });

            form.on('submit(postButton)', function (data) {
                function getQueryParam(param) {
                    const search = window.location.search || window.location.hash.split('?')[1] || '';
                    const params = new URLSearchParams(search);
                    return params.get(param);
                }
                const dir = getQueryParam('dir');
                $.post('plugin.php?id=xinxiuvip_network_plugin:web_admin&action=api&dir=' + dir, {
                    data: data.field,
                }, function (jsondata, textStatus, jqXHR) {
                    if (jsondata.code === 200) {
                        layer.msg('[ ' + dir + ' ] 插件设置成功!', {
                            icon: 1
                        });
                    } else {
                        layer.msg('[ ' + dir + ' ] 插件设置失败!', {
                            icon: 2
                        });
                    }
                    return false;
                });

            });
        });
    </script>
</body>

</html>

3 e) G3 u% r) l2 ?0 c4 c5 z
extend_network.php插件安装卸载配置实例
[PHP] 纯文本查看 复制代码
<?php

if (!defined('IN_DISCUZ')) {
    exit('Access Denied');
}

C::import('class/plugin', 'plugin/xinxiuvip_network_plugin', false); //引入系统核心类

class extend_network extends class_plugin
{

    public function __construct() //构造方法
    {
        parent::__construct(false);
    }
    /**
     * ##创建插件的安装代码
     * 1、此处代码以创建数据库表为主,提前创建插件需要的数据库表及字段!
     * 2、在这里也可以添加一些插件自定义php代码,系统自动执行!
     * 3、如果不需要执行代码,直接返回true即可,实例:return true;
     */
    public function hook_plugin_install() //插件安装代码
    {
        $sql = <<<EOF
        CREATE TABLE IF NOT EXISTS `pre_xinxiuvip_plugin_ip` (
          `id` BIGINT(16) unsigned NOT NULL AUTO_INCREMENT,
          `text1` longtext NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ;
EOF;
        $sql ? web_mysql::xinxiuvip_plugin_run_sql($sql) : ''; //执行上面的多行SQL代码;
        return true; //创建结束
    }
    /**
     * ##更新插件的更新代码
     * 1、此处代码以更新数据库表为主,对安装的数据库表和字段进行更新!
     * 2、在这里也可以添加一些插件自定义php代码,系统自动执行!
     * 3、如果不需要执行代码,直接返回true即可,实例:return true;
     */
    public function hook_plugin_upgrade() //插件更新代码
    {
        $sql = <<<EOF
        CREATE TABLE IF NOT EXISTS `pre_xinxiuvip_plugin_ip` (
          `id` BIGINT(16) unsigned NOT NULL AUTO_INCREMENT,
          `text1` longtext NOT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ;
EOF;
        $sql ? web_mysql::xinxiuvip_plugin_run_sql($sql) : ''; //执行上面的多行SQL代码;
        return true; //更新结束
    }
    /**
     * ##卸载插件的卸载代码
     * 1、此处代码以卸载数据库表为主,对安装的数据库表和字段进行卸载!
     * 2、在这里也可以添加一些插件自定义php代码,系统自动执行!
     * 3、如果不需要执行代码,直接返回true即可,实例:return true;
     */
    public function hook_plugin_uninstall() //插件卸载代码
    {
        $sql = <<<EOF
        DROP TABLE IF EXISTS `pre_xinxiuvip_plugin_ip`;
EOF;
        $sql ? web_mysql::xinxiuvip_plugin_run_sql($sql) : ''; //执行上面的多行SQL代码;
        return true; //更新结束
    }
    /**
     * ##安装插件的接口代码
     * 1、此处代码以添加插件接口为主,对插件封装的接口,添加到数据库!
     * 2、如果不需要添加任何接口信息,直接返回false即可,实例:return false;
     */
    public function hook_plugin_actions_install() //插件安装接口代码
    {
        $actions_array = array(
            array(
                'type' => 'ip模块',//插件模块
                'name' => '查询ip地址',//接口名称
                'actions' => 'ip_cha',//接口方法
                'url' => 'http://www.xinxiuvip.com/thread-556-1-1.html',//接口文档
            ),
            array(
                'type' => 'ip模块1',//插件模块
                'name' => '查询ip地址1',//接口名称
                'actions' => 'ip_cha1',//接口方法
                'url' => 'http://www.xinxiuvip.com/thread-556-1-1.html',//接口文档
            ),
        );
        return $actions_array;
    }
    /**
     * ##更新插件的接口代码
     * 1、此处代码以更新插件接口为主,对插件封装的接口,更新到数据库!
     * 2、如果不需要更新任何接口信息,直接返回false即可,实例:return false;
     */
    public function hook_plugin_actions_upgrade() //插件接口更新代码
    {
        $actions_array = array(
            array(
                'type' => 'ip模块2',//插件模块
                'name' => '查询ip地址2',//接口名称
                'actions' => 'ip_cha2',//接口方法
                'url' => 'http://www.xinxiuvip.com/thread-556-1-1.html',//接口文档
            ),
        );
        return $actions_array;
    }
}

6 K# r  c3 J. X4 g, S3 O/ M) `3 z
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|新秀网络验证系统API[软著登字第13061951号] ( 豫ICP备2021033257号-1 )

GMT+8, 2025-7-27 12:35 , Processed in 0.203074 second(s), 41 queries , Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表