├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── application ├── .htaccess ├── api │ ├── controller │ │ ├── BaseController.php │ │ └── v1 │ │ │ ├── Address.php │ │ │ ├── Banner.php │ │ │ ├── Category.php │ │ │ ├── Order.php │ │ │ ├── Pay.php │ │ │ ├── Product.php │ │ │ ├── Theme.php │ │ │ └── Token.php │ ├── model │ │ ├── Banner.php │ │ ├── Category.php │ │ ├── Order.php │ │ ├── OrderProduct.php │ │ ├── Product.php │ │ ├── ProductImage.php │ │ ├── ProductProperty.php │ │ ├── Theme.php │ │ ├── ThirdApp.php │ │ ├── User.php │ │ └── UserAddress.php │ ├── service │ │ ├── AppToken.php │ │ ├── DeliverMessage.php │ │ ├── Order.php │ │ ├── Pay.php │ │ ├── Token.php │ │ ├── UserToken.php │ │ └── WxNotify.php │ └── validate │ │ ├── AddressNew.php │ │ ├── AppTokenGet.php │ │ ├── BaseValidate.php │ │ ├── Count.php │ │ ├── IDMustBePositiveInt.php │ │ ├── IdConnection.php │ │ ├── OrderPlace.php │ │ ├── PagingParamter.php │ │ ├── TestValidate.php │ │ └── TokenGet.php ├── command.php ├── common.php ├── config.php ├── database.php ├── extra │ ├── secure.php │ ├── setting.php │ └── wx.php ├── lib │ ├── enum │ │ ├── OrderStatusEnum.php │ │ └── ScopeEnum.php │ └── exception │ │ ├── BannerMissException.php │ │ ├── BaseException.php │ │ ├── CategoryException.php │ │ ├── ExceptionHandler.php │ │ ├── ForbiddenException.php │ │ ├── OrderException.php │ │ ├── ParameterException.php │ │ ├── ProductException.php │ │ ├── SuccessMessage.php │ │ ├── ThemeException.php │ │ ├── TokenException.php │ │ ├── UserException.php │ │ └── WeChatException.php ├── route.php └── tags.php ├── build.php ├── composer.json ├── error_code.txt ├── extend └── .gitignore ├── public ├── .htaccess ├── favicon.ico ├── index.php ├── info.php ├── robots.txt ├── router.php └── static │ └── .gitignore ├── runtime └── .gitignore ├── think └── vendor └── .gitignore /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | composer.lock 3 | *.log 4 | thinkphp 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | branches: 6 | only: 7 | - stable 8 | 9 | cache: 10 | directories: 11 | - $HOME/.composer/cache 12 | 13 | before_install: 14 | - composer self-update 15 | 16 | install: 17 | - composer install --no-dev --no-interaction --ignore-platform-reqs 18 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip . 19 | - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0" 20 | - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0" 21 | - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0" 22 | - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0" 23 | - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0" 24 | - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0" 25 | - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0" 26 | - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0" 27 | - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0" 28 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip . 29 | 30 | script: 31 | - php think unit 32 | 33 | deploy: 34 | provider: releases 35 | api_key: 36 | secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw= 37 | file: 38 | - ThinkPHP_Core.zip 39 | - ThinkPHP_Full.zip 40 | skip_cleanup: true 41 | on: 42 | tags: true 43 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 3 | 版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) 4 | All rights reserved。 5 | ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 6 | 7 | Apache Licence是著名的非盈利开源组织Apache采用的协议。 8 | 该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, 9 | 允许代码修改,再作为开源或商业软件发布。需要满足 10 | 的条件: 11 | 1. 需要给代码的用户一份Apache Licence ; 12 | 2. 如果你修改了代码,需要在被修改的文件中说明; 13 | 3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 14 | 带有原来代码中的协议,商标,专利声明和其他原来作者规 15 | 定需要包含的说明; 16 | 4. 如果再发布的产品中包含一个Notice文件,则在Notice文 17 | 件中需要带有本协议内容。你可以在Notice中增加自己的 18 | 许可,但不可以表现为对Apache Licence构成更改。 19 | 具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ThinkPHP 5.0 2 | =============== 3 | 4 | [![Total Downloads](https://poser.pugx.org/topthink/think/downloads)](https://packagist.org/packages/topthink/think) 5 | [![Latest Stable Version](https://poser.pugx.org/topthink/think/v/stable)](https://packagist.org/packages/topthink/think) 6 | [![Latest Unstable Version](https://poser.pugx.org/topthink/think/v/unstable)](https://packagist.org/packages/topthink/think) 7 | [![License](https://poser.pugx.org/topthink/think/license)](https://packagist.org/packages/topthink/think) 8 | 9 | ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PHP版本要求提升到5.4,对已有的CBD模式做了更深的强化,优化核心,减少依赖,基于全新的架构思想和命名空间实现,是ThinkPHP突破原有框架思路的颠覆之作,其主要特性包括: 10 | 11 | + 基于命名空间和众多PHP新特性 12 | + 核心功能组件化 13 | + 强化路由功能 14 | + 更灵活的控制器 15 | + 重构的模型和数据库类 16 | + 配置文件可分离 17 | + 重写的自动验证和完成 18 | + 简化扩展机制 19 | + API支持完善 20 | + 改进的Log类 21 | + 命令行访问支持 22 | + REST支持 23 | + 引导文件支持 24 | + 方便的自动生成定义 25 | + 真正惰性加载 26 | + 分布式环境支持 27 | + 更多的社交类库 28 | 29 | > ThinkPHP5的运行环境要求PHP5.4以上。 30 | 31 | 详细开发文档参考 [ThinkPHP5完全开发手册](http://www.kancloud.cn/manual/thinkphp5) 32 | 33 | ## 目录结构 34 | 35 | 初始的目录结构如下: 36 | 37 | ~~~ 38 | www WEB部署目录(或者子目录) 39 | ├─application 应用目录 40 | │ ├─common 公共模块目录(可以更改) 41 | │ ├─module_name 模块目录 42 | │ │ ├─config.php 模块配置文件 43 | │ │ ├─common.php 模块函数文件 44 | │ │ ├─controller 控制器目录 45 | │ │ ├─model 模型目录 46 | │ │ ├─view 视图目录 47 | │ │ └─ ... 更多类库目录 48 | │ │ 49 | │ ├─command.php 命令行工具配置文件 50 | │ ├─common.php 公共函数文件 51 | │ ├─config.php 公共配置文件 52 | │ ├─route.php 路由配置文件 53 | │ ├─tags.php 应用行为扩展定义文件 54 | │ └─database.php 数据库配置文件 55 | │ 56 | ├─public WEB目录(对外访问目录) 57 | │ ├─index.php 入口文件 58 | │ ├─router.php 快速测试文件 59 | │ └─.htaccess 用于apache的重写 60 | │ 61 | ├─thinkphp 框架系统目录 62 | │ ├─lang 语言文件目录 63 | │ ├─library 框架类库目录 64 | │ │ ├─think Think类库包目录 65 | │ │ └─traits 系统Trait目录 66 | │ │ 67 | │ ├─tpl 系统模板目录 68 | │ ├─base.php 基础定义文件 69 | │ ├─console.php 控制台入口文件 70 | │ ├─convention.php 框架惯例配置文件 71 | │ ├─helper.php 助手函数文件 72 | │ ├─phpunit.xml phpunit配置文件 73 | │ └─start.php 框架入口文件 74 | │ 75 | ├─extend 扩展类库目录 76 | ├─runtime 应用的运行时目录(可写,可定制) 77 | ├─vendor 第三方类库目录(Composer依赖库) 78 | ├─build.php 自动生成定义文件(参考) 79 | ├─composer.json composer 定义文件 80 | ├─LICENSE.txt 授权说明文件 81 | ├─README.md README 文件 82 | ├─think 命令行入口文件 83 | ~~~ 84 | 85 | > router.php用于php自带webserver支持,可用于快速测试 86 | > 切换到public目录后,启动命令:php -S localhost:8888 router.php 87 | > 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。 88 | 89 | ## 命名规范 90 | 91 | `ThinkPHP5`遵循PSR-2命名规范和PSR-4自动加载规范,并且注意如下规范: 92 | 93 | ### 目录和文件 94 | 95 | * 目录不强制规范,驼峰和小写+下划线模式均支持; 96 | * 类库、函数文件统一以`.php`为后缀; 97 | * 类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致; 98 | * 类名和类文件名保持一致,统一采用驼峰法命名(首字母大写); 99 | 100 | ### 函数和类、属性命名 101 | * 类的命名采用驼峰法,并且首字母大写,例如 `User`、`UserType`,默认不需要添加后缀,例如`UserController`应该直接命名为`User`; 102 | * 函数的命名使用小写字母和下划线(小写字母开头)的方式,例如 `get_client_ip`; 103 | * 方法的命名使用驼峰法,并且首字母小写,例如 `getUserName`; 104 | * 属性的命名使用驼峰法,并且首字母小写,例如 `tableName`、`instance`; 105 | * 以双下划线“__”打头的函数或方法作为魔法方法,例如 `__call` 和 `__autoload`; 106 | 107 | ### 常量和配置 108 | * 常量以大写字母和下划线命名,例如 `APP_PATH`和 `THINK_PATH`; 109 | * 配置参数以小写字母和下划线命名,例如 `url_route_on` 和`url_convert`; 110 | 111 | ### 数据表和字段 112 | * 数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如 `think_user` 表和 `user_name`字段,不建议使用驼峰和中文作为数据表字段命名。 113 | 114 | ## 参与开发 115 | 请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。 116 | 117 | ## 版权信息 118 | 119 | ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 120 | 121 | 本项目包含的第三方源码和二进制文件之版权信息另行标注。 122 | 123 | 版权所有Copyright © 2006-2017 by ThinkPHP (http://thinkphp.cn) 124 | 125 | All rights reserved。 126 | 127 | ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 128 | 129 | 更多细节参阅 [LICENSE.txt](LICENSE.txt) 130 | -------------------------------------------------------------------------------- /application/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /application/api/controller/BaseController.php: -------------------------------------------------------------------------------- 1 | ['only' => 'createOrUpdateAddress,getUserAddress'] 24 | ]; 25 | 26 | public function createOrUpdateAddress(){ 27 | $validate = new AddressNew(); 28 | $validate->goCheck(); 29 | //根据Token获取用户的uid 30 | //根据uid查找用户数据,判断用户是否存在,如果不存在,抛出异常 31 | //获取用户从客户端提交来的地址信息 32 | $uid = TokenService::getCurrentUID(); 33 | $user = UserModel::get($uid); 34 | if(!$user){ 35 | throw new UserException([ 36 | 'code' => 404, 37 | 'msg' => '用户收货地址不存在', 38 | 'errorCode' => 60001 39 | ]); 40 | } 41 | 42 | $dataArray = $validate->getDataByRule(input('post.')); 43 | 44 | $userAddress = $user->address; 45 | if(!$userAddress){ 46 | $user->address()->save($dataArray); 47 | } 48 | else{ 49 | $user->address->save($dataArray); 50 | } 51 | return new SuccessMessage(); 52 | } 53 | 54 | /** 55 | * 获取用户地址信息 56 | * @return UserAddress 57 | * @throws UserException 58 | */ 59 | public function getUserAddress(){ 60 | $uid = TokenService::getCurrentUid(); 61 | $userAddress = UserAddress::where('user_id', $uid) 62 | ->find(); 63 | if(!$userAddress){ 64 | throw new UserException([ 65 | 'msg' => '用户地址不存在', 66 | 'errorCode' => 60001 67 | ]); 68 | } 69 | return $userAddress; 70 | } 71 | } -------------------------------------------------------------------------------- /application/api/controller/v1/Banner.php: -------------------------------------------------------------------------------- 1 | goCheck(); 28 | //$banner = BannerModule::with(['items', 'items.img'])->find($id); 29 | $banner = BannerModel::getBannerById($id); 30 | if(!$banner){ 31 | //throw new BannerMissException(); 32 | throw new BannerMissException(); 33 | } 34 | $c = config('setting.img_prefix'); 35 | return $banner; 36 | } 37 | 38 | public function showHello(){ 39 | return 'Hello World.'; 40 | } 41 | } -------------------------------------------------------------------------------- /application/api/controller/v1/Category.php: -------------------------------------------------------------------------------- 1 | ['only' => 'getAllCategories'] 20 | // ]; 21 | // 22 | // protected function checkPrimaryScope(){ 23 | // TokenService::needPrimaryScope(); 24 | // } 25 | 26 | public function getAllCategories(){ 27 | $categories = CategoryModel::all([], 'img'); 28 | if(empty($categories)){ 29 | throw new CategoryException(); 30 | } 31 | return $categories; 32 | } 33 | } -------------------------------------------------------------------------------- /application/api/controller/v1/Order.php: -------------------------------------------------------------------------------- 1 | ['only' => 'placeOrder'] 35 | ]; 36 | 37 | public function placeOrder(){ 38 | (new OrderPlace())->goCheck(); 39 | $products = input('post.products/a'); 40 | $uid = TokenService::getCurrentUid(); 41 | 42 | $order = new OrderService(); 43 | $status = $order->place($uid, $products); 44 | return $status; 45 | } 46 | 47 | public function getOrderByUser($page=1, $size=15){ 48 | (new PagingParamter())->goCheck(); 49 | $uid = TokenService::getCurrentUID(); 50 | $pagingOrders = OrderModel::getSummaryByUser($uid, $page, $size); 51 | if($pagingOrders->isEmpty()){ 52 | return [ 53 | 'data' => [], 54 | 'current_page' =>$pagingOrders->getCurrentPage() 55 | ]; 56 | } 57 | $data = $pagingOrders->hidden('snap_items','snap_address','prepay_id') 58 | ->toArray(); 59 | return [ 60 | 'data' => $data, 61 | 'current_page' =>$pagingOrders->getCurrentPage() 62 | ]; 63 | } 64 | 65 | public function getDetail($id){ 66 | (new IDMustBePositiveInt())->goCheck(); 67 | $orderDetail = OrderModel::get($id); 68 | if(!$orderDetail){ 69 | throw new OrderException(); 70 | } 71 | return $orderDetail->hidden('prepay_id'); 72 | } 73 | 74 | /** 75 | * 根据用户id分页获取订单列表(简要信息) 76 | * @param int $page 77 | * @param int $size 78 | * @return array 79 | * @throws \app\lib\exception\ParameterException 80 | */ 81 | public function getSummaryByUser($page = 1, $size = 15) 82 | { 83 | (new PagingParamter())->goCheck(); 84 | $uid = TokenService::getCurrentUid(); 85 | $pagingOrders = OrderModel::getSummaryByUser($uid, $page, $size); 86 | if ($pagingOrders->isEmpty()) 87 | { 88 | return [ 89 | 'current_page' => $pagingOrders->currentPage(), 90 | 'data' => [] 91 | ]; 92 | } 93 | // $collection = collection($pagingOrders->items()); 94 | // $data = $collection->hidden(['snap_items', 'snap_address']) 95 | // ->toArray(); 96 | $data = $pagingOrders->hidden(['snap_items', 'snap_address']) 97 | ->toArray(); 98 | return [ 99 | 'current_page' => $pagingOrders->currentPage(), 100 | 'data' => $data 101 | ]; 102 | 103 | } 104 | 105 | /** 106 | * 获取全部订单简要信息(分页) 107 | * @param int $page 108 | * @param int $size 109 | * @return array 110 | * @throws \app\lib\exception\ParameterException 111 | */ 112 | public function getSummary($page=1, $size = 20){ 113 | (new PagingParamter())->goCheck(); 114 | // $uid = Token::getCurrentUid(); 115 | $pagingOrders = OrderModel::getSummaryByPage($page, $size); 116 | if ($pagingOrders->isEmpty()) 117 | { 118 | return [ 119 | 'current_page' => $pagingOrders->currentPage(), 120 | 'data' => [] 121 | ]; 122 | } 123 | $data = $pagingOrders->hidden(['snap_items', 'snap_address']) 124 | ->toArray(); 125 | return [ 126 | 'current_page' => $pagingOrders->currentPage(), 127 | 'data' => $data 128 | ]; 129 | } 130 | } -------------------------------------------------------------------------------- /application/api/controller/v1/Pay.php: -------------------------------------------------------------------------------- 1 | ['only' => 'getPreOrder'], 21 | 'checkPrimaryScope' => ['only' => 'getDetail,getSummaryByUser'], 22 | 'checkSuperScope' => ['only' => 'delivery,getSummary'] 23 | ]; 24 | 25 | public function getPreOrder($id=''){ 26 | (new IDMustBePositiveInt())->goCheck(); 27 | $pay = new PayService($id); 28 | return $pay->pay(); 29 | } 30 | 31 | public function receiveNotify(){ 32 | //通知频率为15/15/30/180/1000/1000/1000/3600 33 | 34 | //1.检查库存量 35 | //2.更新这个订单的status状态 36 | //3.减库存 37 | //如果成功处理,返回成功的通知,否则返回失败通知 38 | //特点:post 39 | $notify = new WxNotify(); 40 | $notify->Handle(); 41 | // $xmlData = file_get_contents('php://input'); 42 | // $result = curl_post_raw('http://leidong.cn/api/v1/pay/re_notify?'); 43 | } 44 | } -------------------------------------------------------------------------------- /application/api/controller/v1/Product.php: -------------------------------------------------------------------------------- 1 | ['only' => 'createOne,deleteOne'] 21 | ]; 22 | 23 | public function getRecent($count=15){ 24 | (new Count())->goCheck(); 25 | $product = ProductModel::getMostRecent($count); 26 | if(!$product){ 27 | throw new ProductException(); 28 | } 29 | $collection = collection($product); 30 | $product = $collection->hidden(['summary'])->toArray(); 31 | return $product; 32 | } 33 | 34 | public function getAllInCategory($id=-1){ 35 | (new IDMustBePositiveInt())->goCheck(); 36 | $products = ProductModel::getProductsByCcategoryID($id); 37 | if(!$products){ 38 | throw new ProductException(); 39 | } 40 | $data = $products; 41 | // ->hidden(['summary']) 42 | //->toArray(); 43 | return $data; 44 | } 45 | 46 | public function getOne($id){ 47 | (new IDMustBePositiveInt())->goCheck(); 48 | $product = ProductModel::getProductDetail($id); 49 | if(!$product){ 50 | throw new ProductException(); 51 | } 52 | return $product; 53 | } 54 | 55 | public function deleteOne($id){ 56 | ProductModel::destroy($id); 57 | } 58 | } -------------------------------------------------------------------------------- /application/api/controller/v1/Theme.php: -------------------------------------------------------------------------------- 1 | goCheck(); 26 | $ids = explode(',', $ids); 27 | $result = ThemeModel::with('topicImg,headImg') 28 | ->select($ids); 29 | if(!$result){ 30 | throw new ThemeException(); 31 | } 32 | return $result; 33 | } 34 | 35 | /** 36 | * @url /theme/id 37 | */ 38 | public function getComplexOne($id){ 39 | (new IDMustBePositiveInt())->goCheck(); 40 | $theme = ThemeModel::getThemeWithProducts($id); 41 | if(!$theme){ 42 | throw new ThemeException(); 43 | } 44 | return $theme; 45 | } 46 | } -------------------------------------------------------------------------------- /application/api/controller/v1/Token.php: -------------------------------------------------------------------------------- 1 | goCheck(); 22 | $ut = new UserToken($code); 23 | $token = $ut->get(); 24 | return [ 25 | 'token' => $token 26 | ]; 27 | } 28 | 29 | public function verifyToken($token=''){ 30 | if(!$token){ 31 | throw new ParameterException([ 32 | 'Token不允许为空' 33 | ]); 34 | } 35 | $valid = TokenService::verifyToken($token); 36 | return [ 37 | 'isValid' => $valid 38 | ]; 39 | } 40 | 41 | /** 42 | * 第三方应用获取令牌 43 | * @url /app_token? 44 | * @POST ac=:ac se=:secret 45 | */ 46 | public function getAppToken($ac='', $se='') 47 | { 48 | header('Access-Control-Allow-Origin: *'); 49 | header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"); 50 | header('Access-Control-Allow-Methods: GET'); 51 | (new AppTokenGet())->goCheck(); 52 | $app = new AppToken(); 53 | $token = $app->get($ac, $se); 54 | return [ 55 | 'token' => $token 56 | ]; 57 | } 58 | } -------------------------------------------------------------------------------- /application/api/model/Banner.php: -------------------------------------------------------------------------------- 1 | hasMany("BannerItem", 'banner_id', 'id'); 18 | } 19 | 20 | public static function getBannerById($id){ 21 | //TODO:根据Banner的id号获取Banner的信息 22 | // $result = Db::query('select * from banner_item where img_id=?', [3]); 23 | // return $result; 24 | // $result = Db::table('banner_item') 25 | // //->fetchSql() 26 | // ->where(function ($query) use($id){ 27 | // $query->where('banner_id', '=', '$id'); 28 | // }) 29 | // ->select( ); 30 | // return $result; 31 | 32 | $banner = self::with(['items','items.img']) 33 | 34 | ->find($id); 35 | return $banner; 36 | } 37 | } -------------------------------------------------------------------------------- /application/api/model/Category.php: -------------------------------------------------------------------------------- 1 | hasMany('Product', 'category_id', 'id'); 17 | } 18 | 19 | public function img() 20 | { 21 | return $this->belongsTo('Image', 'topic_img_id', 'id'); 22 | } 23 | 24 | public static function getCategories($ids) 25 | { 26 | $categories = self::with('products') 27 | ->with('products.img') 28 | ->select($ids); 29 | return $categories; 30 | } 31 | 32 | public static function getCategory($id) 33 | { 34 | $category = self::with('products') 35 | ->with('products.img') 36 | ->find($id); 37 | return $category; 38 | } 39 | } -------------------------------------------------------------------------------- /application/api/model/Order.php: -------------------------------------------------------------------------------- 1 | order('create_time desc') 38 | ->paginate($size, true, ['page' => $page]); 39 | return $pagingData ; 40 | } 41 | 42 | public static function getSummaryByPage($uid, $page=1, $size=20){ 43 | $pagingData = self::where('user_id','=',$uid) 44 | ->order('create_time desc') 45 | ->paginate($size, true, ['page' => $page]); 46 | return $pagingData ; 47 | } 48 | 49 | public function products() 50 | { 51 | return $this->belongsToMany('Product', 'order_product', 'product_id', 'order_id'); 52 | } 53 | 54 | public function getSnapItemAttr($value){ 55 | if(empty($value)){ 56 | return null; 57 | } 58 | return json_encode($value); 59 | } 60 | } -------------------------------------------------------------------------------- /application/api/model/OrderProduct.php: -------------------------------------------------------------------------------- 1 | order('create_time desc') 21 | ->select(); 22 | return $product; 23 | } 24 | 25 | public static function getProductsByCcategoryID($categoryID){ 26 | $products = self::where('category_id', '=', $categoryID) 27 | ->select(); 28 | return $products; 29 | } 30 | 31 | public static function getProductDetail($id){ 32 | $product = self::with( 33 | [ 34 | 'imgs' => function ($query) 35 | { 36 | $query->with(['imgUrl']) 37 | ->order('order', 'asc'); 38 | }]) 39 | ->with('properties') 40 | ->find($id); 41 | return $product; 42 | } 43 | 44 | public function properties(){ 45 | return $this->hasMany('ProductProperty', 'product_id', 'id'); 46 | } 47 | 48 | public function imgs(){ 49 | return $this->hasMany('ProductImage', 'product_id', 'id'); 50 | } 51 | 52 | public function getMainImgUrlAttr($value, $data) 53 | { 54 | return $this->prefixImgUrl($value, $data); 55 | } 56 | } -------------------------------------------------------------------------------- /application/api/model/ProductImage.php: -------------------------------------------------------------------------------- 1 | belongsTo('Image', 'img_id', 'id'); 18 | } 19 | } -------------------------------------------------------------------------------- /application/api/model/ProductProperty.php: -------------------------------------------------------------------------------- 1 | belongsTo('Image', 'topic_img_id', 'id'); 16 | } 17 | 18 | public function headImg(){ 19 | return $this->belongsTo('Image', 'head_img_id', 'id'); 20 | } 21 | 22 | public function products(){ 23 | return $this->belongsToMany('Product', 'theme_product', 'product_id', 'theme_id'); 24 | } 25 | 26 | public static function getThemeWithProducts($id){ 27 | $theme = self::with('products,topicImg,headImg') 28 | ->find($id); 29 | return $theme; 30 | } 31 | } -------------------------------------------------------------------------------- /application/api/model/ThirdApp.php: -------------------------------------------------------------------------------- 1 | where('app_secret', '=',$se) 17 | ->find(); 18 | return $app; 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /application/api/model/User.php: -------------------------------------------------------------------------------- 1 | hasOne('UserAddress', 'user_id', 'id'); 15 | } 16 | 17 | public function orders() 18 | { 19 | return $this->hasMany('Order', 'user_id', 'id'); 20 | } 21 | 22 | public static function getByOpenID($openid){ 23 | $user = User::where('openid', '=', $openid) 24 | ->find(); 25 | return $user; 26 | } 27 | } -------------------------------------------------------------------------------- /application/api/model/UserAddress.php: -------------------------------------------------------------------------------- 1 | '授权失败', 22 | 'errorCode' => 10004 23 | ]); 24 | } 25 | else{ 26 | $scope = $app->scope; 27 | $uid = $app->id; 28 | $values = [ 29 | 'scope' => $scope, 30 | 'uid' => $uid 31 | ]; 32 | $token = $this->saveToCache($values); 33 | return $token; 34 | } 35 | } 36 | 37 | private function saveToCache($values){ 38 | $token = self::generateToken(); 39 | $expire_in = config('setting.token_expire_in'); 40 | $result = cache($token, json_encode($values), $expire_in); 41 | if(!$result){ 42 | throw new TokenException([ 43 | 'msg' => '服务器缓存异常', 44 | 'errorCode' => 10005 45 | ]); 46 | } 47 | return $token; 48 | } 49 | } -------------------------------------------------------------------------------- /application/api/service/DeliverMessage.php: -------------------------------------------------------------------------------- 1 | tplID = self::DELIVERY_MSG_ID; 29 | $this->formID = $order->prepay_id; 30 | $this->page = $tplJumpPage; 31 | $this->prepareMessageData($order); 32 | $this->emphasisKeyWord='keyword2.DATA'; 33 | return parent::sendMessage($this->getUserOpenID($order->user_id)); 34 | } 35 | 36 | private function prepareMessageData($order) 37 | { 38 | $dt = new \DateTime(); 39 | $data = [ 40 | 'keyword1' => [ 41 | 'value' => '顺风速运', 42 | ], 43 | 'keyword2' => [ 44 | 'value' => $order->snap_name, 45 | 'color' => '#27408B' 46 | ], 47 | 'keyword3' => [ 48 | 'value' => $order->order_no 49 | ], 50 | 'keyword4' => [ 51 | 'value' => $dt->format("Y-m-d H:i") 52 | ] 53 | ]; 54 | $this->data = $data; 55 | } 56 | 57 | private function getUserOpenID($uid) 58 | { 59 | $user = User::get($uid); 60 | if (!$user) { 61 | throw new UserException(); 62 | } 63 | return $user->openid; 64 | } 65 | } -------------------------------------------------------------------------------- /application/api/service/Order.php: -------------------------------------------------------------------------------- 1 | oProducts = $oProducts; 38 | $this->products = $this->getProductsByOrder($oProducts); 39 | $this->uid = $uid; 40 | $status = $this->getOrderStatus(); 41 | if(!$status['pass']){ 42 | $status['order_id'] = -1; 43 | return $status; 44 | } 45 | 46 | //开始创建订单了 47 | $orderSnap = $this->snapOrder($status); 48 | $order = $this->createOrder($orderSnap); 49 | $order['pass'] = true; 50 | return $order; 51 | 52 | } 53 | 54 | /** 55 | * 生成订单快照 56 | */ 57 | private function snapOrder($status){ 58 | // status可以单独定义一个类 59 | $snap = [ 60 | 'orderPrice' => 0, 61 | 'totalCount' => 0, 62 | 'pStatus' => [], 63 | 'snapAddress' => json_encode($this->getUserAddress()), 64 | 'snapName' => $this->products[0]['name'], 65 | 'snapImg' => $this->products[0]['main_img_url'], 66 | ]; 67 | 68 | if (count($this->products) > 1) { 69 | $snap['snapName'] .= '等'; 70 | } 71 | 72 | 73 | for ($i = 0; $i < count($this->products); $i++) { 74 | $product = $this->products[$i]; 75 | $oProduct = $this->oProducts[$i]; 76 | 77 | $pStatus = $this->snapProduct($product, $oProduct['count']); 78 | $snap['orderPrice'] += $pStatus['totalPrice']; 79 | $snap['totalCount'] += $pStatus['count']; 80 | array_push($snap['pStatus'], $pStatus); 81 | } 82 | return $snap; 83 | } 84 | 85 | public function createOrder($snap){ 86 | Db::startTrans(); 87 | try { 88 | $orderNo = $this->makeOrderNo(); 89 | $order = new OrderModel(); 90 | 91 | $order->user_id = $this->uid; 92 | $order->order_no = $orderNo; 93 | $order->total_price = $snap['orderPrice']; 94 | $order->total_count = $snap['totalCount']; 95 | $order->snap_img = $snap['snapImg']; 96 | $order->snap_name = $snap['snapName']; 97 | $order->snap_address = $snap['snapAddress']; 98 | $order->snap_items = json_encode($snap['pStatus']); 99 | 100 | $order->save(); 101 | 102 | $orderID = $order->id; 103 | $create_time = $order->create_time; 104 | 105 | foreach ($this->oProducts as &$p) { 106 | $p['order_id'] = $orderID; 107 | } 108 | $orderProduct = new OrderProduct(); 109 | $orderProduct->saveAll($this->oProducts); 110 | Db::commit(); 111 | return [ 112 | 'order_no' => $orderNo, 113 | 'order_id' => $orderID, 114 | 'create_time' => $create_time 115 | ]; 116 | } catch (Exception $ex) { 117 | throw $ex; 118 | } 119 | } 120 | 121 | public static function makeOrderNo() 122 | { 123 | $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'); 124 | $orderSn = 125 | $yCode[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date( 126 | 'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf( 127 | '%02d', rand(0, 99)); 128 | return $orderSn; 129 | } 130 | 131 | private function snapProduct($product, $oCount) 132 | { 133 | $pStatus = [ 134 | 'id' => null, 135 | 'name' => null, 136 | 'main_img_url'=>null, 137 | 'count' => $oCount, 138 | 'totalPrice' => 0, 139 | 'price' => 0 140 | ]; 141 | 142 | $pStatus['counts'] = $oCount; 143 | // 以服务器价格为准,生成订单 144 | $pStatus['totalPrice'] = $oCount * $product['price']; 145 | $pStatus['name'] = $product['name']; 146 | $pStatus['id'] = $product['id']; 147 | $pStatus['main_img_url'] =$product['main_img_url']; 148 | $pStatus['price'] = $product['price']; 149 | return $pStatus; 150 | } 151 | 152 | private function getUserAddress(){ 153 | $userAddress = UserAddress::where('user_id', '=', $this->uid) 154 | ->find(); 155 | if(!$userAddress){ 156 | throw new UserException([ 157 | 'msg' => '用户收获地址不存在,下单失败', 158 | 'errorCode' => 60001 159 | ]); 160 | } 161 | return $userAddress->toArray(); 162 | } 163 | 164 | //根据订单查收真实的products信息 165 | private function getProductsByOrder($oProducts){ 166 | $oPIDs = []; 167 | foreach ($oProducts as $item) { 168 | array_push($oPIDs, $item['product_id']); 169 | } 170 | $products = Product::all($oPIDs); 171 | //->visible(['id','price','stock','name','main_img_url']) 172 | //->toArray(); 173 | return $products; 174 | } 175 | 176 | public function getOrderStatus(){ 177 | $status = [ 178 | 'pass' => true, 179 | 'totalCount' => 0, 180 | 'orderPrice' => 0, 181 | 'pStatusArray' => [] 182 | ]; 183 | 184 | foreach ($this->oProducts as $oProduct) { 185 | $pStatus = $this->getProductStatus( 186 | $oProduct['product_id'], $oProduct['count'], $this->products 187 | ); 188 | if(!$pStatus['haveStock']){ 189 | $status['pass'] = false; 190 | } 191 | $status['orderPrice'] += $pStatus['totalPrice']; 192 | //$status['totalCount'] += $pStatus['totalCount']; 193 | array_push($status['pStatusArray'], $pStatus); 194 | } 195 | return $status; 196 | } 197 | 198 | private function getProductStatus($oPID, $oCount, $products){ 199 | $pIndex = -1; 200 | 201 | $pStatus = [ 202 | 'id' => null, 203 | 'haveStock' => false, 204 | 'count' => 0, 205 | 'name' => '', 206 | 'price' => 0, 207 | 'totalPrice' => 0 208 | ]; 209 | 210 | for($i = 0; $i < count($products); $i++){ 211 | if($oPID == $products[$i]['id']){ 212 | $pIndex = $i; 213 | } 214 | } 215 | 216 | if($pIndex == -1){ 217 | throw new OrderException([ 218 | 'msg' => 'id为'.$oPID.'的商品不存在,创建订单失败' 219 | ]); 220 | } 221 | else{ 222 | $product = $products[$pIndex]; 223 | $pStatus['id'] = $product['id']; 224 | $pStatus['name'] = $product['name']; 225 | //$pStatus['count'] = $oCount; 226 | $pStatus['counts'] = $oCount; 227 | $pStatus['price'] = $product['price']; 228 | $pStatus['main_img_url'] = $product['main_img_url']; 229 | $pStatus['totalPrice'] = $product['price'] * $oCount; 230 | if($product['stock'] - $oCount >= 0){ 231 | $pStatus['haveStock'] = true; 232 | } 233 | } 234 | return $pStatus; 235 | } 236 | 237 | public function getOrderStock($orderID){ 238 | $oProducts = OrderProduct::where('order_id','=', $orderID) 239 | ->select(); 240 | $this->oProducts = $oProducts; 241 | 242 | $this->products = $this->getProductsByOrder($oProducts); 243 | $status = $this->getOrderStatus(); 244 | return $status; 245 | } 246 | 247 | public function checkOrderStock($orderID) 248 | { 249 | // if (!$orderNo) 250 | // { 251 | // throw new Exception('没有找到订单号'); 252 | // } 253 | 254 | // 一定要从订单商品表中直接查询 255 | // 不能从商品表中查询订单商品 256 | // 这将导致被删除的商品无法查询出订单商品来 257 | $oProducts = OrderProduct::where('order_id', '=', $orderID) 258 | ->select(); 259 | $this->products = $this->getProductsByOrder($oProducts); 260 | $this->oProducts = $oProducts; 261 | $status = $this->getOrderStatus(); 262 | return $status; 263 | } 264 | } -------------------------------------------------------------------------------- /application/api/service/Pay.php: -------------------------------------------------------------------------------- 1 | orderID = $orderID; 33 | } 34 | 35 | public function pay(){ 36 | //客户端传来的参数是不匹配的 37 | //订单号可能根本就不存在 38 | //订单号存在,但是与用户ID不匹配 39 | //订单有可能已经被支付 40 | //进行库存量检测 41 | $this->checkOrderValid(); 42 | $orderService = new OrderService(); 43 | $status = $orderService->checkOrderStock($this->orderID); 44 | 45 | if(!$status['pass']){ 46 | return $status; 47 | } 48 | return $this->makeWxPreOrder($status['orderPrice']); 49 | } 50 | 51 | private function makeWxPreOrder($totalPrice){ 52 | //openid 53 | $openid = Token::getCurrentTokenVar('openid'); 54 | if(!$openid){ 55 | throw new TokenException(); 56 | } 57 | $wxOrderData = new \WxPayUnifiedOrder(); 58 | $wxOrderData->SetOut_trade_no($this->orderNO); 59 | $wxOrderData->SetTrade_type('JSAPI'); 60 | $wxOrderData->SetTotal_fee($totalPrice * 100); 61 | $wxOrderData->SetBody('零食商贩'); 62 | $wxOrderData->SetOpenid($openid); 63 | $wxOrderData->SetNotify_url(config('secure.pay_back_url')); 64 | return $this->getPaySignature($wxOrderData); 65 | } 66 | 67 | private function getPaySignature($wxOrderData){ 68 | $wxOrder = \WxPayApi::unifiedOrder($wxOrderData); 69 | if($wxOrder['return_code'] != 'SUCCESS' 70 | || $wxOrder['result_code'] != 'SUCCESS'){ 71 | 72 | Log::record($wxOrder, 'error'); 73 | Log::record('获取支付订单失败', 'error'); 74 | } 75 | //prepay_id 76 | $this->recordPreOrder($wxOrder); 77 | $signature = $this->sign($wxOrder); 78 | return $signature; 79 | } 80 | 81 | private function recordPreOrder($wxOrder){ 82 | OrderModel::where('id','=',$this->orderID) 83 | ->update(['prepay_id'=>$wxOrder['prepay_id']]); 84 | } 85 | 86 | private function checkOrderValid(){ 87 | $order = OrderModel::where('id', '=', $this->orderID) 88 | ->find(); 89 | 90 | if(!$order){ 91 | throw new OrderException(); 92 | } 93 | if(!Token::isValidOperate($order->user_id)){ 94 | throw new TokenException([ 95 | 'msg' => '订单与用户不匹配', 96 | 'errorCode' => 10003 97 | ]); 98 | } 99 | if($order->status != OrderStatusEnum::UNPAID){ 100 | throw new OrderException([ 101 | 'msg' => '订单状态异常', 102 | 'errorCode' => 80003, 103 | 'code' => 400 104 | ]); 105 | } 106 | $this->orderNO = $order->order_no; 107 | return true; 108 | } 109 | 110 | private function sign($wxOrder){ 111 | $jsApiPayData = new \WxPayJsApiPay(); 112 | $jsApiPayData->SetAppid(config('wx.app_id')); 113 | $jsApiPayData->SetTimeStamp((string)time()); 114 | 115 | $rand = md5(time() . mt_rand(0, 1000)); 116 | $jsApiPayData->SetNonceStr($rand); 117 | 118 | $jsApiPayData->SetPackage('prepay_id='.$wxOrder['prepay_id']); 119 | $jsApiPayData->SetSignType('md5'); 120 | 121 | $sign = $jsApiPayData->MakeSign(); 122 | $rawValues = $jsApiPayData->GetValues(); 123 | $rawValues['paySign'] = $sign; 124 | unset($rawValues['app_id']); 125 | 126 | return $rawValues; 127 | } 128 | } -------------------------------------------------------------------------------- /application/api/service/Token.php: -------------------------------------------------------------------------------- 1 | header('token'); 32 | $vars = Cache::get($token); 33 | if(!$vars){ 34 | throw new TokenException(); 35 | } 36 | else{ 37 | if(!is_array($vars)){ 38 | $vars = json_decode($vars, true); 39 | } 40 | if(array_key_exists($key, $vars)){ 41 | return $vars[$key]; 42 | } 43 | else{ 44 | throw new Exception('尝试获取的Token变量并不存在!'); 45 | } 46 | } 47 | } 48 | 49 | public static function getCurrentUID(){ 50 | $uid = self::getCurrentTokenVar('uid'); 51 | return $uid; 52 | } 53 | 54 | public static function needPrimaryScope(){ 55 | $scope = self::getCurrentTokenVar('scope'); 56 | if ($scope) { 57 | if ($scope >= ScopeEnum::User) { 58 | return true; 59 | }else { 60 | throw new ForbiddenException(); 61 | } 62 | } 63 | else{ 64 | throw new TokenException(); 65 | } 66 | } 67 | 68 | public static function needExclusiveScope() 69 | { 70 | $scope = TokenService::getCurrentTokenVar('scope'); 71 | if ($scope) { 72 | if ($scope == ScopeEnum::User) { 73 | return true; 74 | }else { 75 | throw new ForbiddenException(); 76 | } 77 | } 78 | else{ 79 | throw new TokenException(); 80 | } 81 | } 82 | 83 | public static function isValidOperate($checkedUID){ 84 | if(!$checkedUID){ 85 | throw new Exception('检测UID时必须传入一个被检测UID'); 86 | } 87 | $currentOperateUID = self::getCurrentUID(); 88 | if($currentOperateUID == $checkedUID){ 89 | return true; 90 | } 91 | return false; 92 | } 93 | 94 | public static function verifyToken($token){ 95 | $exist = Cache::get($token); 96 | if($exist){ 97 | return true; 98 | } 99 | else{ 100 | return false; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /application/api/service/UserToken.php: -------------------------------------------------------------------------------- 1 | code = $code; 27 | $this->wxAppID = config('wx.app_id'); 28 | $this->wxAppSecret = config('wx.app_secret'); 29 | $this->wxLoginUrl = sprintf(config('wx.login_url'), $this->wxAppID, $this->wxAppSecret, $this->code); 30 | } 31 | 32 | public function getToken($code=''){ 33 | (new TokenGet())->goCheck(); 34 | $ut = new UserToken(); 35 | $token = $ut->get($code); 36 | return $token; 37 | } 38 | 39 | public function get(){ 40 | $result = curl_get($this->wxLoginUrl); 41 | $wxResult = json_decode($result, true); 42 | if(empty($wxResult)){ 43 | throw new Exception('获取sessionKey及openID时异常,微信内部错误'); 44 | } 45 | else{ 46 | $loginFail = array_key_exists('errorCode', $wxResult); 47 | if($loginFail){ 48 | $this->processLoginError($wxResult); 49 | } 50 | else{ 51 | return $this->grantToken($wxResult); 52 | } 53 | } 54 | } 55 | 56 | /** 57 | * 颁发令牌 58 | * @param $wxResult 59 | */ 60 | private function grantToken($wxResult){ 61 | //拿到openid 62 | //数据库里看一下,这个openid是不是已经存在 63 | //如果存在则不处理,如果不存在新增一条记录 64 | //生成令牌,准备缓存数据,写入缓存 65 | //把令牌返回到客户端去 66 | //key 令牌 67 | //value wxResult uid scope 68 | $openid = $wxResult['openid']; 69 | $user = UserModel::getByOpenID($openid); 70 | if($user){ 71 | $uid = $user->id; 72 | } 73 | else{ 74 | $uid = $this->newUser($openid); 75 | } 76 | $cachedValue = $this->prepareCacheValue($wxResult, $uid); 77 | $token = $this->saveToCache($cachedValue); 78 | return $token; 79 | } 80 | 81 | private function saveToCache($cachedValue){ 82 | $key = self::generateToken(); 83 | $value = json_encode($cachedValue); 84 | $expire_in = config('setting.token_expire_in'); 85 | 86 | $request = cache($key, $value, $expire_in);//缓存 87 | if(!$request){ 88 | throw new TokenException([ 89 | 'msg' => '服务器缓存异常', 90 | 'errorCode' => '10005' 91 | ]); 92 | } 93 | return $key; 94 | } 95 | 96 | private function prepareCacheValue($wxResult, $uid){ 97 | $cachedValue = $wxResult; 98 | $cachedValue['uid'] = $uid; 99 | //16代表客户端用户的权限 100 | //32代表(CMS)管理员的权限 101 | $cachedValue['scope'] = ScopeEnum::User; 102 | return $cachedValue; 103 | } 104 | 105 | private function newUser($openid){ 106 | $user = UserModel::create([ 107 | 'openid' => $openid 108 | ]); 109 | return $user->id; 110 | } 111 | 112 | private function processLoginError($wxResult){ 113 | throw new WeChatException([ 114 | 'msg' => $wxResult['errmsg'], 115 | 'errorCode' => $wxResult['errcode'], 116 | ]); 117 | } 118 | } -------------------------------------------------------------------------------- /application/api/service/WxNotify.php: -------------------------------------------------------------------------------- 1 | lock(true) 34 | ->find(); 35 | if($order->status == 1){ 36 | $orderService = new OrderService(); 37 | $stockStatus = $orderService->checkOrderStock($order->id); 38 | if($stockStatus['pass']){ 39 | $this->updateOrderStatus($order->id, true); 40 | $this->reduceStock($stockStatus); 41 | } 42 | else{ 43 | $this->updateOrderStatus($order->id, false); 44 | } 45 | } 46 | Db::commit(); 47 | return true; 48 | } 49 | catch(Exception $ex){ 50 | Log::error($ex); 51 | return false; 52 | } 53 | } 54 | else{ 55 | return true; 56 | } 57 | } 58 | 59 | private function updateOrderStatus($orderID, $success){ 60 | $status = $success ? OrderStatusEnum::PAID : 61 | OrderStatusEnum::PAID_BUT_OUT_OF; 62 | OrderModel::where('id','=',$orderID) 63 | ->update(['status' => $status]); 64 | } 65 | 66 | private function reduceStock($stockStatus){ 67 | foreach ($stockStatus['pStatusArray'] as $singlePStatus){ 68 | ProductModel::where('id','=',$singlePStatus['id']) 69 | ->setDec('stock',$singlePStatus['count']); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /application/api/validate/AddressNew.php: -------------------------------------------------------------------------------- 1 | 'require|isNotEmpty', 20 | 'mobile' => 'require|isMobile', 21 | 'province' => 'require|isNotEmpty', 22 | 'city' => 'require|isNotEmpty', 23 | 'country' => 'require|isNotEmpty', 24 | 'detail' => 'require|isNotEmpty', 25 | ]; 26 | } -------------------------------------------------------------------------------- /application/api/validate/AppTokenGet.php: -------------------------------------------------------------------------------- 1 | 'require|isNotEmpty', 16 | 'se' => 'require|isNotEmpty' 17 | ]; 18 | } -------------------------------------------------------------------------------- /application/api/validate/BaseValidate.php: -------------------------------------------------------------------------------- 1 | param(); 27 | 28 | $result = $this->batch()->check($params); 29 | if(!$result){ 30 | $e = new ParameterException([ 31 | 'msg' => $this->error, 32 | ]); 33 | throw $e; 34 | } 35 | else{ 36 | return true; 37 | } 38 | } 39 | 40 | protected function isPositiveInteger($value, $rule='', $data=' 41 | ', $field=''){ 42 | if(is_numeric($value) && is_int($value + 0) && ($value + 0) > 0){ 43 | return true; 44 | } 45 | else{ 46 | return false; 47 | //return $field.'必须是正整数'; 48 | } 49 | } 50 | 51 | protected function isNotEmpty($value, $rulr='', $data='', $field=''){ 52 | if(empty($value)){ 53 | return false; 54 | } 55 | else{ 56 | return true; 57 | } 58 | } 59 | 60 | public function getDataByRule($arrays) 61 | { 62 | if (array_key_exists('user_id', $arrays) | array_key_exists('uid', $arrays)) { 63 | // 不允许包含user_id或者uid,防止恶意覆盖user_id外键 64 | throw new ParameterException([ 65 | 'msg' => '参数中包含有非法的参数名user_id或者uid' 66 | ]); 67 | } 68 | $newArray = []; 69 | foreach ($this->rule as $key => $value) { 70 | $newArray[$key] = $arrays[$key]; 71 | } 72 | return $newArray; 73 | } 74 | 75 | //没有使用TP的正则验证,集中在一处方便以后修改 76 | //不推荐使用正则,因为复用性太差 77 | //手机号的验证规则 78 | protected function isMobile($value) 79 | { 80 | $rule = '^1(3|4|5|7|8)[0-9]\d{8}$^'; 81 | $result = preg_match($rule, $value); 82 | if ($result) { 83 | return true; 84 | } else { 85 | return false; 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /application/api/validate/Count.php: -------------------------------------------------------------------------------- 1 | 'isPositiveInteger|between:1,20' 16 | ]; 17 | } -------------------------------------------------------------------------------- /application/api/validate/IDMustBePositiveInt.php: -------------------------------------------------------------------------------- 1 | 'require|isPositiveInteger' 16 | ]; 17 | 18 | protected $message = [ 19 | 'id' => 'id必须是正整数' 20 | ]; 21 | } -------------------------------------------------------------------------------- /application/api/validate/IdConnection.php: -------------------------------------------------------------------------------- 1 | 'require|checkIDs' 16 | ]; 17 | 18 | protected $message = [ 19 | 'ids' => 'ids参数必须是为以都好分割的多个正整数' 20 | ]; 21 | 22 | protected function checkIDs($value){ 23 | $values = explode(',', $value); 24 | if(empty($values)){ 25 | return false; 26 | } 27 | foreach ($values as $id){ 28 | if(!$this->isPositiveInteger($id)){ 29 | return false; 30 | } 31 | } 32 | return true; 33 | } 34 | } -------------------------------------------------------------------------------- /application/api/validate/OrderPlace.php: -------------------------------------------------------------------------------- 1 | 'checkProducts' 18 | ]; 19 | 20 | protected $singleRule = [ 21 | 'product_id' => 'require|isPositiveInteger', 22 | 'count' => 'require|isPositiveInteger' 23 | ]; 24 | 25 | protected function checkProducts($values){ 26 | if(empty($values)){ 27 | throw new ParameterException([ 28 | 'msg' => '商品列表不能为空' 29 | ]); 30 | } 31 | if(!is_array($values)){ 32 | throw new ParameterException([ 33 | 'msg' => '商品列表必须是数组' 34 | ]); 35 | } 36 | 37 | foreach ($values as $value) { 38 | $this->checkProduct($value); 39 | } 40 | return true; 41 | } 42 | 43 | protected function checkProduct($value){ 44 | $validate = new BaseValidate($this->singleRule); 45 | $result = $validate->check($value); 46 | if(!$result){ 47 | throw new ParameterException([ 48 | 'mag' => '商品列表参数错误' 49 | ]); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /application/api/validate/PagingParamter.php: -------------------------------------------------------------------------------- 1 | 'isPositiveInteger', 16 | 'size' => 'isPositiveInteger' 17 | ]; 18 | 19 | protected $message = [ 20 | 'page' => '分页单数必须是正整数', 21 | 'size' => '分页单数必须是正整数' 22 | ]; 23 | } -------------------------------------------------------------------------------- /application/api/validate/TestValidate.php: -------------------------------------------------------------------------------- 1 | 'require|max:10', 16 | 'email' => 'require|email' 17 | ]; 18 | } -------------------------------------------------------------------------------- /application/api/validate/TokenGet.php: -------------------------------------------------------------------------------- 1 | 'require|isNotEmpty' 16 | ]; 17 | 18 | protected $message = [ 19 | 'code' => '没有Code还想获取Token' 20 | ]; 21 | } -------------------------------------------------------------------------------- /application/command.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return []; 13 | -------------------------------------------------------------------------------- /application/common.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // 应用公共文件 13 | 14 | function curl_get($url, $httpCode = 0){ 15 | $ch = curl_init(); 16 | curl_setopt($ch, CURLOPT_URL, $url); 17 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 18 | 19 | //下载证书校验,部署在Linux环境下请改为false 20 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 21 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); 22 | $file_contents = curl_exec($ch); 23 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 24 | curl_close($ch); 25 | return $file_contents; 26 | } 27 | 28 | function getRandChar($length){ 29 | $str = null; 30 | $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 31 | $max = strlen($strPol) - 1; 32 | 33 | for($i = 0; $i < $length; $i++){ 34 | $str .= $strPol[rand(0, $max)]; 35 | } 36 | return $str; 37 | } 38 | -------------------------------------------------------------------------------- /application/config.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | // +---------------------------------------------------------------------- 14 | // | 应用设置 15 | // +---------------------------------------------------------------------- 16 | 17 | // 应用命名空间 18 | 'app_namespace' => 'app', 19 | // 应用调试模式 20 | 'app_debug' => true, 21 | // 应用Trace 22 | 'app_trace' => false, 23 | // 应用模式状态 24 | 'app_status' => '', 25 | // 是否支持多模块 26 | 'app_multi_module' => true, 27 | // 入口自动绑定模块 28 | 'auto_bind_module' => false, 29 | // 注册的根命名空间 30 | 'root_namespace' => [], 31 | // 扩展函数文件 32 | 'extra_file_list' => [THINK_PATH . 'helper' . EXT], 33 | // 默认输出类型 34 | 'default_return_type' => 'json', 35 | // 默认AJAX 数据返回格式,可选json xml ... 36 | 'default_ajax_return' => 'json', 37 | // 默认JSONP格式返回的处理方法 38 | 'default_jsonp_handler' => 'jsonpReturn', 39 | // 默认JSONP处理方法 40 | 'var_jsonp_handler' => 'callback', 41 | // 默认时区 42 | 'default_timezone' => 'PRC', 43 | // 是否开启多语言 44 | 'lang_switch_on' => false, 45 | // 默认全局过滤方法 用逗号分隔多个 46 | 'default_filter' => '', 47 | // 默认语言 48 | 'default_lang' => 'zh-cn', 49 | // 应用类库后缀 50 | 'class_suffix' => false, 51 | // 控制器类后缀 52 | 'controller_suffix' => false, 53 | 54 | // +---------------------------------------------------------------------- 55 | // | 模块设置 56 | // +---------------------------------------------------------------------- 57 | 58 | // 默认模块名 59 | 'default_module' => 'index', 60 | // 禁止访问模块 61 | 'deny_module_list' => ['common'], 62 | // 默认控制器名 63 | 'default_controller' => 'Index', 64 | // 默认操作名 65 | 'default_action' => 'index', 66 | // 默认验证器 67 | 'default_validate' => '', 68 | // 默认的空控制器名 69 | 'empty_controller' => 'Error', 70 | // 操作方法后缀 71 | 'action_suffix' => '', 72 | // 自动搜索控制器 73 | 'controller_auto_search' => false, 74 | 75 | // +---------------------------------------------------------------------- 76 | // | URL设置 77 | // +---------------------------------------------------------------------- 78 | 79 | // PATHINFO变量名 用于兼容模式 80 | 'var_pathinfo' => 's', 81 | // 兼容PATH_INFO获取 82 | 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'], 83 | // pathinfo分隔符 84 | 'pathinfo_depr' => '/', 85 | // URL伪静态后缀 86 | 'url_html_suffix' => 'html', 87 | // URL普通方式参数 用于自动生成 88 | 'url_common_param' => false, 89 | // URL参数方式 0 按名称成对解析 1 按顺序解析 90 | 'url_param_type' => 0, 91 | // 是否开启路由 92 | 'url_route_on' => true, 93 | // 路由使用完整匹配 94 | 'route_complete_match' => true, 95 | // 路由配置文件(支持配置多个) 96 | 'route_config_file' => ['route'], 97 | // 是否强制使用路由 98 | 'url_route_must' => false, 99 | // 域名部署 100 | 'url_domain_deploy' => false, 101 | // 域名根,如thinkphp.cn 102 | 'url_domain_root' => '', 103 | // 是否自动转换URL中的控制器和操作名 104 | 'url_convert' => true, 105 | // 默认的访问控制器层 106 | 'url_controller_layer' => 'controller', 107 | // 表单请求类型伪装变量 108 | 'var_method' => '_method', 109 | // 表单ajax伪装变量 110 | 'var_ajax' => '_ajax', 111 | // 表单pjax伪装变量 112 | 'var_pjax' => '_pjax', 113 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 114 | 'request_cache' => false, 115 | // 请求缓存有效期 116 | 'request_cache_expire' => null, 117 | 118 | // +---------------------------------------------------------------------- 119 | // | 模板设置 120 | // +---------------------------------------------------------------------- 121 | 122 | 'template' => [ 123 | // 模板引擎类型 支持 php think 支持扩展 124 | 'type' => 'Think', 125 | // 模板路径 126 | 'view_path' => '', 127 | // 模板后缀 128 | 'view_suffix' => 'html', 129 | // 模板文件名分隔符 130 | 'view_depr' => DS, 131 | // 模板引擎普通标签开始标记 132 | 'tpl_begin' => '{', 133 | // 模板引擎普通标签结束标记 134 | 'tpl_end' => '}', 135 | // 标签库标签开始标记 136 | 'taglib_begin' => '{', 137 | // 标签库标签结束标记 138 | 'taglib_end' => '}', 139 | ], 140 | 141 | // 视图输出字符串内容替换 142 | 'view_replace_str' => [], 143 | // 默认跳转页面对应的模板文件 144 | 'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', 145 | 'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', 146 | 147 | // +---------------------------------------------------------------------- 148 | // | 异常及错误设置 149 | // +---------------------------------------------------------------------- 150 | 151 | // 异常页面的模板文件 152 | 'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl', 153 | 154 | // 错误显示信息,非调试模式有效 155 | 'error_message' => '页面错误!请稍后再试~', 156 | // 显示错误信息 157 | 'show_error_msg' => false, 158 | // 异常处理handle类 留空使用 \think\exception\Handle 159 | 'exception_handle' => 'app\lib\exception\ExceptionHandler', 160 | 161 | // +---------------------------------------------------------------------- 162 | // | 日志设置 163 | // +---------------------------------------------------------------------- 164 | 165 | 'log' => [ 166 | // 日志记录方式,内置 file socket 支持扩展 167 | 'type' => 'test', 168 | // 日志保存目录 169 | 'path' => LOG_PATH, 170 | // 日志记录级别 171 | 'level' => [], 172 | ], 173 | 174 | // +---------------------------------------------------------------------- 175 | // | Trace设置 开启 app_trace 后 有效 176 | // +---------------------------------------------------------------------- 177 | 'trace' => [ 178 | // 内置Html Console 支持扩展 179 | 'type' => 'Html', 180 | ], 181 | 182 | // +---------------------------------------------------------------------- 183 | // | 缓存设置 184 | // +---------------------------------------------------------------------- 185 | 186 | 'cache' => [ 187 | // 驱动方式 188 | 'type' => 'File', 189 | // 缓存保存目录 190 | 'path' => CACHE_PATH, 191 | // 缓存前缀 192 | 'prefix' => '', 193 | // 缓存有效期 0表示永久缓存 194 | 'expire' => 0, 195 | ], 196 | 197 | // +---------------------------------------------------------------------- 198 | // | 会话设置 199 | // +---------------------------------------------------------------------- 200 | 201 | 'session' => [ 202 | 'id' => '', 203 | // SESSION_ID的提交变量,解决flash上传跨域 204 | 'var_session_id' => '', 205 | // SESSION 前缀 206 | 'prefix' => 'think', 207 | // 驱动方式 支持redis memcache memcached 208 | 'type' => '', 209 | // 是否自动开启 SESSION 210 | 'auto_start' => true, 211 | ], 212 | 213 | // +---------------------------------------------------------------------- 214 | // | Cookie设置 215 | // +---------------------------------------------------------------------- 216 | 'cookie' => [ 217 | // cookie 名称前缀 218 | 'prefix' => '', 219 | // cookie 保存时间 220 | 'expire' => 0, 221 | // cookie 保存路径 222 | 'path' => '/', 223 | // cookie 有效域名 224 | 'domain' => '', 225 | // cookie 启用安全传输 226 | 'secure' => false, 227 | // httponly设置 228 | 'httponly' => '', 229 | // 是否使用 setcookie 230 | 'setcookie' => true, 231 | ], 232 | 233 | //分页配置 234 | 'paginate' => [ 235 | 'type' => 'bootstrap', 236 | 'var_page' => 'page', 237 | 'list_rows' => 15, 238 | ], 239 | ]; 240 | -------------------------------------------------------------------------------- /application/database.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | // 数据库类型 14 | 'type' => 'mysql', 15 | // 服务器地址 16 | 'hostname' => '127.0.0.1', 17 | // 数据库名 18 | 'database' => 'zerg', 19 | // 用户名 20 | 'username' => 'root', 21 | // 密码 22 | 'password' => '', 23 | // 端口 24 | 'hostport' => '3307', 25 | // 连接dsn 26 | 'dsn' => '', 27 | // 数据库连接参数 28 | 'params' => [], 29 | // 数据库编码默认采用utf8 30 | 'charset' => 'utf8', 31 | // 数据库表前缀 32 | 'prefix' => '', 33 | // 数据库调试模式 34 | 'debug' => true, 35 | // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 36 | 'deploy' => 0, 37 | // 数据库读写是否分离 主从式有效 38 | 'rw_separate' => false, 39 | // 读写分离后 主服务器数量 40 | 'master_num' => 1, 41 | // 指定从服务器序号 42 | 'slave_no' => '', 43 | // 是否严格检查字段是否存在 44 | 'fields_strict' => true, 45 | // 数据集返回类型 46 | 'resultset_type' => 'colection', 47 | // 自动写入时间戳字段 48 | 'auto_timestamp' => false, 49 | // 时间字段取出后的默认时间格式 50 | 'datetime_format' => 'Y-m-d H:i:s', 51 | // 是否需要进行SQL性能分析 52 | 'sql_explain' => false, 53 | ]; 54 | -------------------------------------------------------------------------------- /application/extra/secure.php: -------------------------------------------------------------------------------- 1 | 'JKBGJskdbkaGibksd67823d', 11 | 'pay_back_url' => 'http://253ef10a.ngrok.io/zerg/public/index.php/api/v1/pay/notify' 12 | 13 | ]; -------------------------------------------------------------------------------- /application/extra/setting.php: -------------------------------------------------------------------------------- 1 | 'http://leidong.cn/images', 11 | 'token_expire_in' => 7200 12 | ]; -------------------------------------------------------------------------------- /application/extra/wx.php: -------------------------------------------------------------------------------- 1 | 'wx3614e5c4f8da54b3', 11 | 'app_secret' => '9f6295673f8834710b9b151d7ec132a3', 12 | 'login_url' => "https://api.weixin.qq.com/sns/jscode2session?" . 13 | "appid=%s&secret=%s&js_code=%s&grant_type=authorization_code" 14 | 15 | ]; -------------------------------------------------------------------------------- /application/lib/enum/OrderStatusEnum.php: -------------------------------------------------------------------------------- 1 | code = $params['code']; 34 | } 35 | if(array_key_exists('msg', $params)){ 36 | $this->msg = $params['msg']; 37 | } 38 | if(array_key_exists('errorCode', $params)){ 39 | $this->errorCode = $params['errorCode']; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /application/lib/exception/CategoryException.php: -------------------------------------------------------------------------------- 1 | code = $e->code; 30 | $this->msg = $e->msg; 31 | $this->errorCode = $e->errorCode; 32 | } 33 | //如果不是自定义的异常 34 | else{ 35 | if(config('app_debug')){ 36 | return parent::render($e); 37 | } 38 | else{ 39 | $this->code = 500; 40 | $this->msg = '服务器内部错误,不想告诉你'; 41 | $this->errorCode = 999; 42 | $this->recordErrorLog($e); 43 | } 44 | } 45 | $requesu = Request::instance(); 46 | $result = [ 47 | 'msg' => $this->msg, 48 | 'error_code' => $this->errorCode, 49 | 'request_url' => $requesu->url() 50 | ]; 51 | return json($result, $this->code); 52 | } 53 | 54 | /** 55 | * @param Exception $e 56 | */ 57 | private function recordErrorLog(Exception $e){ 58 | Log::init([ 59 | 'type' => 'File', 60 | 'path' => LOG_PATH, 61 | 'level' => ['error'] 62 | ]); 63 | Log::record($e->getMessage(), 'error'); 64 | } 65 | } -------------------------------------------------------------------------------- /application/lib/exception/ForbiddenException.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | //return [ 13 | // '__pattern__' => [ 14 | // 'name' => '\w+', 15 | // ], 16 | // '[hello]' => [ 17 | // ':id' => ['index/hello', ['method' => 'get'], ['id' => '\d+']], 18 | // ':name' => ['index/hello', ['method' => 'post']], 19 | // ], 20 | // 21 | //]; 22 | 23 | use think\Route; 24 | 25 | //Banner 26 | Route::get('api/:version/banner/:id', 'api/:version.Banner/getBanner'); 27 | 28 | //Theme 29 | Route::get('api/:version/theme', 'api/:version.Theme/getSimpleList'); 30 | Route::get('api/:version/theme/:id', 'api/:version.Theme/getComplexOne'); 31 | 32 | //Product(2种写法) 33 | //Route::get('api/:version/product/recent', 'api/:version.Product/getRecent'); 34 | //Route::get('api/:version/product/by_category', 'api/:version.Product/getAllInCategory'); 35 | //Route::get('api/:version/product/:id', 'api/:version.Product/getOne', [], ['id '=> '\d+']); 36 | //Route::group('api/:version/product', function (){ 37 | // Route::get('/by_category', 'api/:version.Product/getAllInCategory'); 38 | // Route::get('/recent', 'api/:version.Product/getRecent'); 39 | // Route::get('/ :id', 'api/:version.Product/getOne', [], ['id '=> '\d+']); 40 | //}); 41 | Route::post('api/:version/product', 'api/:version.Product/createOne'); 42 | Route::delete('api/:version/product/:id', 'api/:version.Product/deleteOne'); 43 | Route::get('api/:version/product/by_category/paginate', 'api/:version.Product/getByCategory'); 44 | Route::get('api/:version/product/by_category', 'api/:version.Product/getAllInCategory'); 45 | Route::get('api/:version/product/:id', 'api/:version.Product/getOne',[],['id'=>'\d+']); 46 | Route::get('api/:version/product/recent', 'api/:version.Product/getRecent'); 47 | 48 | //Category 49 | Route::get('api/:version/category/all', 'api/:version.Category/getAllCategories'); 50 | 51 | //Token 52 | Route::post('api/:version/token/user', 'api/:version.Token/getToken'); 53 | Route::post('api/:version/token/app', 'api/:version.Token/getAppToken'); 54 | Route::post('api/:version/token/verify', 'api/:version.Token/verifyToken'); 55 | 56 | //Address 57 | Route::post('api/:version/address', 'api/:version.Address/createOrUpdateAddress'); 58 | Route::get('api/:version/address', 'api/:version.Address/getUserAddress'); 59 | 60 | //Order 61 | Route::post('api/:version/order', 'api/:version.Order/placeOrder'); 62 | Route::get('api/:version/order/:id', 'api/:version.Order/getDetail',[], ['id'=>'\d+']); 63 | Route::get('api/:version/order/by_user', 'api/:version.Order/getSummaryByUser'); 64 | 65 | //Pay 66 | Route::post('api/:version/pay/pre_order', 'api/:version.Pay/getPreOrder'); 67 | Route::post('api/:version/pay/notify', 'api/:version.Pay/receiveNotify'); 68 | Route::post('api/:version/pay/re_notify', 'api/:version.Pay//receiveNotify'); 69 | 70 | //Test 71 | Route::get('hello/:id', 'api/v1.Banner/showHello'); 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /application/tags.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // 应用行为扩展定义文件 13 | return [ 14 | // 应用初始化 15 | 'app_init' => [], 16 | // 应用开始 17 | 'app_begin' => [], 18 | // 模块初始化 19 | 'module_init' => [], 20 | // 操作开始执行 21 | 'action_begin' => [], 22 | // 视图内容过滤 23 | 'view_filter' => [], 24 | // 日志写入 25 | 'log_write' => [], 26 | // 应用结束 27 | 'app_end' => [], 28 | ]; 29 | -------------------------------------------------------------------------------- /build.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | // 生成应用公共文件 14 | '__file__' => ['common.php', 'config.php', 'database.php'], 15 | 16 | // 定义demo模块的自动生成 (按照实际定义的文件名生成) 17 | 'demo' => [ 18 | '__file__' => ['common.php'], 19 | '__dir__' => ['behavior', 'controller', 'model', 'view'], 20 | 'controller' => ['Index', 'Test', 'UserType'], 21 | 'model' => ['User', 'UserType'], 22 | 'view' => ['index/index'], 23 | ], 24 | // 其他更多的模块定义 25 | ]; 26 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "topthink/think", 3 | "description": "the new thinkphp framework", 4 | "type": "project", 5 | "keywords": [ 6 | "framework", 7 | "thinkphp", 8 | "ORM" 9 | ], 10 | "homepage": "http://thinkphp.cn/", 11 | "license": "Apache-2.0", 12 | "authors": [ 13 | { 14 | "name": "liu21st", 15 | "email": "liu21st@gmail.com" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=5.4.0", 20 | "topthink/framework": "^5.0" 21 | }, 22 | "extra": { 23 | "think-path": "thinkphp" 24 | }, 25 | "config": { 26 | "preferred-install": "dist" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /error_code.txt: -------------------------------------------------------------------------------- 1 | 2 | 999 未知错误或者是不想让用户知道的错误 3 | 4 | 1 通用崔武 5 | 3 主题类的错误 6 | 7 | 10000 通用参数错误 8 | 9 | 30000 请求的主题不存在 -------------------------------------------------------------------------------- /extend/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymlinks -Multiviews 3 | RewriteEngine On 4 | 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 8 | 9 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leidongld/ThinkPHP5/39c100fd7d90e505d8166eac8448e6c650e91920/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // [ 应用入口文件 ] 13 | 14 | // 定义应用目录 15 | define('APP_PATH', __DIR__ . '/../application/'); 16 | define('LOG_PATH', __DIR__ . '/../log/'); 17 | // 加载框架引导文件 18 | require __DIR__ . '/../thinkphp/start.php'; 19 | 20 | \think\Log::init([ 21 | 'type' => 'File', 22 | 'path' => LOG_PATH, 23 | 'level' => ['sql'] 24 | ]); 25 | -------------------------------------------------------------------------------- /public/info.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | // $Id$ 12 | 13 | if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["REQUEST_URI"])) { 14 | return false; 15 | } else { 16 | require __DIR__ . "/index.php"; 17 | } 18 | -------------------------------------------------------------------------------- /public/static/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /think: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 11 | // +---------------------------------------------------------------------- 12 | 13 | // 定义项目路径 14 | define('APP_PATH', __DIR__ . '/application/'); 15 | 16 | // 加载框架引导文件 17 | require './thinkphp/console.php'; -------------------------------------------------------------------------------- /vendor/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore --------------------------------------------------------------------------------