songdb 5 lat temu
rodzic
commit
660f82c30a
23 zmienionych plików z 3527 dodań i 19 usunięć
  1. 229 19
      .env.example
  2. 68 0
      app/Http/Controllers/KuaiYingYong/BaseController.php
  3. 70 0
      app/Http/Controllers/KuaiYingYong/Book/BookCategoryController.php
  4. 662 0
      app/Http/Controllers/KuaiYingYong/Book/BookController.php
  5. 668 0
      app/Http/Controllers/KuaiYingYong/Book/ChapterController.php
  6. 45 0
      app/Http/Controllers/KuaiYingYong/Book/Transformers/BookTransformer.php
  7. 22 0
      app/Http/Controllers/KuaiYingYong/Book/Transformers/ChapterListTransformer.php
  8. 24 0
      app/Http/Controllers/KuaiYingYong/Book/Transformers/ChapterTransformer.php
  9. 283 0
      app/Http/Controllers/KuaiYingYong/Oauth/UsersController.php
  10. 719 0
      app/Http/Controllers/KuaiYingYong/Order/OrdersController.php
  11. 17 0
      app/Http/Controllers/KuaiYingYong/Order/Transformers/BookOrderTransformer.php
  12. 19 0
      app/Http/Controllers/KuaiYingYong/Order/Transformers/ChapterOrderTransformer.php
  13. 16 0
      app/Http/Controllers/KuaiYingYong/Order/Transformers/ChargeListTransformer.php
  14. 19 0
      app/Http/Controllers/KuaiYingYong/Order/Transformers/OrderTransformer.php
  15. 189 0
      app/Http/Controllers/KuaiYingYong/User/ReadRecordController.php
  16. 20 0
      app/Http/Controllers/KuaiYingYong/User/Transformers/ReadRecordTransformer.php
  17. 24 0
      app/Http/Controllers/KuaiYingYong/User/Transformers/UserShelfBooksTransformer.php
  18. 96 0
      app/Http/Controllers/KuaiYingYong/User/UserController.php
  19. 225 0
      app/Http/Controllers/KuaiYingYong/User/UserShelfBooksController.php
  20. 15 0
      app/Http/Controllers/KuaiYingYong/apidoc.json
  21. 4 0
      app/Http/Controllers/KuaiYingYong/header.md
  22. 80 0
      app/Http/Routes/KuaiYingYong/KuaiYingYongRoutes.php
  23. 13 0
      app/Providers/RouteServiceProvider.php

+ 229 - 19
.env.example

@@ -1,21 +1,41 @@
 APP_ENV=local
 APP_DEBUG=true
 APP_KEY=base64:IUGnJ8O7ITqPwyOTQn85mFcioQaEqwu4Vn2UXk9VN5c=
-
+APP_LOG=daily
+LOG_MAX_FILES=3
+APP_ALLOW='*'
 DB_CONNECTION=mysql
-DB_HOST=rm-bp1z1dto3n2rdb02f.mysql.rds.aliyuncs.com
+#DB_HOST=rm-bp1z1dto3n2rdb02f.mysql.rds.aliyuncs.com
+DB_READ_HOST=rm-bp1z1dto3n2rdb02f.mysql.rds.aliyuncs.com
+DB_WRITE_HOST=rm-bp1z1dto3n2rdb02f.mysql.rds.aliyuncs.com
 DB_PORT=3306
-DB_DATABASE=yueduyun
+DB_DATABASE=otest_yueduyun
 DB_USERNAME=yueduyun
 DB_PASSWORD=yueduyun2017#Ydy
 
+CHAPTER_DB_HOST=rm-bp1z1dto3n2rdb02f.mysql.rds.aliyuncs.com
+CHAPTER_DB_PORT=3306
+CHAPTER_DB_DATABASE=otest_zsy_sub
+CHAPTER_DB_USERNAME=yueduyun
+CHAPTER_DB_PASSWORD=yueduyun2017#Ydy
+
+NEW_YUNQI_DB_HOST=rm-bp1hr7s22jozojrap.mysql.rds.aliyuncs.com
+NEW_YUNQI_DB_PORT=3306
+NEW_YUNQI_DB_DATABASE=xinyunxi
+NEW_YUNQI_DB_USERNAME=xinyunxi
+NEW_YUNQI_DB_PASSWORD=NewYunxi!zwkj2066
+
 CACHE_DRIVER=file
 SESSION_DRIVER=file
 QUEUE_DRIVER=sync
 
 REDIS_HOST=127.0.0.1
-REDIS_PASSWORD=null
+REDIS_PASSWORD=bd_zsy_online_test
 REDIS_PORT=6379
+REDIS_HOST_CHAPTER=127.0.0.1
+REDIS_PORT_CHAPTER=6379
+REDIS_PASSWORD_CHAPTER=bd_zsy_online_test
+REDIS_PASSWORD_ORDER=bd_zsy_online_test
 
 MAIL_DRIVER=smtp
 MAIL_HOST=mailtrap.io
@@ -24,39 +44,229 @@ MAIL_USERNAME=null
 MAIL_PASSWORD=null
 MAIL_ENCRYPTION=null
 
-
 QUEUE_DRIVER=rabbitmq
 
-RABBITMQ_HOST=172.16.157.148
+#RABBITMQ_HOST=116.62.153.249
+RABBITMQ_HOST=172.16.114.111
 RABBITMQ_PORT=5672
 RABBITMQ_VHOST=/
-RABBITMQ_LOGIN=test
-RABBITMQ_PASSWORD=6acbQWE13
+RABBITMQ_LOGIN=online_test
+RABBITMQ_PASSWORD='online_test_123#123'
 RABBITMQ_QUEUE=queue_name
 
+YCSD_CALL_PAY_MERCHANT_ID=44
 
-
-CHANNEL_MAIN_DOMAIN=fx.readcloud.com
+CHANNEL_MAIN_DOMAIN=pre.aizhuishu.com
 CHANNEL_SITE_PREFIX=site
-PROTOCOL=http
 IAMGE_SERVER_DOMAIN=//images.wangluogudu.com
 OFFICIAL_ACCOUNT_HOST=http://oauth.yueloo.com.cn
 OFFICIAL_ACCOUNT_AUTH_URL=http://oauth.yueloo.com.cn/oauth/oauth_platform
 OFFICIAL_ACCOUNT_AUTH_REDIRECT_URL=/service/new
 
-LOWEST_WITHDRAW_MONEY=100
+LOWEST_WITHDRAW_MONEY=1
+
+PROTOCOL=http
+H5_SCHEME=http
+CUSTOM_HOST=pre.aizhuishu
+WECHAT_CUSTOM_HOST=zhuishuyun
+GROUP_NICK=zhuishuyun
+MEDIA_API_BASE_URI=http://preauth.aizhuishu.com/api/
 
 SECRET_KEY=zhuishuyun#_2017
 
-CHANNEL_DOMAIN=
-WAP_DOMAIN=
-MANAGE_DOMAIN=
-WECHAT_DOMAIN=
+CHANNEL_DOMAIN=channel.pre.aizhuishu.com
+WAP_DOMAIN=site{i}.pre.{j}.com
+WAP_BROWER_DOMAIN=bsite{i}.pre.{j}.com
+PAY_WAP_DOMAIN=prepay.aizhuishu.com
+MANAGE_DOMAIN=manage.pre.aizhuishu.com
+WECHAT_DOMAIN=172.16.114.111
+CP_DOMAIN=cp.pre.aizhuishu.com
+FRIEND_LINK_DOMAIN=site{i}.pre.{j}.com
+
+OFFICIAL_AUTH_FOMAIN=preauth.aizhuishu.com
+
+HELP_DOMAIN=help
+OFFICIAL_FINANCE='116.62.153.249'
+
+
+OSS_ACCESS_ID=VM2vq1ZtF0LT4hUx
+OSS_ACCESS_KEY=eqllJuthP21t5A6tln7dSE3g9N00Ad
+OSS_END_POINT__=oss-cn-hangzhou.internal.aliyuncs.com
+OSS_END_POINT=oss-cn-hangzhou.aliyuncs.com
+OSS_BUCKET=yueduyun
+
+SMS_AccessKeyId=LTAIGE5kkq4PGUjv
+SMS_AccessKeySecret=q2HsOLhOqQtvkc2PHlR6uROdZ1zQFg
+SMS_SIGN=追书云
+
+OAUTH_KEY=zhuishuyun#_2017
+U_COOKIE_EXPIRE=2592000
+COOKIE_AUTH_WEB_WECHAT=web_user_auth
+BOOK_MALE_LOOP=1,2,3,4,5,6
+BOOK_MALE_HOT=76,757,4,73,642,780
+BOOK_MALE_ZHIBO=635,623,88
+BOOK_MALE_RECOM=72,85,639
+BOOK_MALE_NEW_RECOM=673,67,668
+
+BOOK_FEMALE_LOOP=6,535,521,135,47,46
+BOOK_FEMALE_HOT=7,5,464,126,60,52
+BOOK_FEMALE_ZHIBO=159,354,151,31,12,517
+BOOK_FEMALE_RECOM=46,51,45,242,124,165
+BOOK_FEMALE_NEW_RECOM=442,355,115,56,479,20
+
+
+OFFICIAL_PAY_CALL_BACK_URL='https://prepay.aizhuishu.com/pay/wcback_official'
+ALLINPAY_PAY_NOFITY_URL='https://prepay.aizhuishu.com/pay/wcback_allinpay'
+PALMPAY_NOFITY_URL='https://prepay.aizhuishu.com/pay/wcback_palmpay'
+ORIGINBANK_NOFITY_URL='https://prepay.aizhuishu.com/pay/wcback_originbank'
+LIANLIAN_PAY_CALL_BACK_URL='https://prepay.aizhuishu.com/pay/wcback_lianlianpay'
+UNIONPAY_NOFITY_URL='https://prepay.aizhuishu.com/pay/wcback_union'
+AUTH_CALLBACK_URL=https://zsynewauth.aizhuishu.com/wxAuthCallBack/
+AUTH_CALLBACK_URL_V2=https://preauth.aizhuishu.com/wxAuthCallBackv2/
+AUTH_CALLBACK_URL_V2_2=https://preauth.aizhuishu.com/wxAuthCallBack2v2/
+#WECHAT_AUTH_APPID=wxdbc486f1b4f6a8c3
+WECHAT_AUTH_APPID=wxebcb86ec4b80eaca
+WECHAT_SUB_APPID=wxdbc486f1b4f6a8c3
+
+XIYUE_HOST='https://xiyue.aizhuishu.com'
 
+AUTH_URL_='https://preauth.aizhuishu.com/user_oauth_v2'
+AUTH_URL__='https://zsyauth.aizhuishu.com/user_oauth'
+AUTH_URL='https://zsynewauth.aizhuishu.com/user_oauth'
+CREATE_PAY_URL='https://prepay.aizhuishu.com/goToPay'
+
+
+MONTH_ORDER_APPID=Aekgrv87yo5785l715
+MONTH_ORDER_APP_SECRET=57gwsnd158ib2sn7wluq57167858fzm
+MONTH_ORDER_KEY=sn7wluq5716brp8fzm
+MONTH_ORDER_PLAN_ID=127955
+MONTH_WEEK_ORDER_PLAN_ID=128349
+MONTH_QUARTER_ORDER_PLAN_ID=129440
+MONTH_PAY_SIGN_NOTIFY_URLV2='https://prepay.aizhuishu.com/monthpay/signcallbackv2'
+MONTH_PAY_CALLBACK_URLV2='https://prepay.aizhuishu.com/monthpay/ordercallbackv2'
+
+
+TEST_UID=10008,20213,167642,7530358,7530367,7530394,7530399,7530436,7530362,7530397,109861757,109861817,109861821,109861826,109861820,109861819,109861830,109861819
 
-#自动打款开关
 PAYMENT_AUTO_PAY_ON=false
 
 
-#结算过滤
-not_in_pay_merchant_id=13
+WEB_READER_BACKGROUND=3
+WEB_READER_FONT_SIZE=19
+WEB_READER_PAGE_STYLE=vertical
+
+SEND_ORDER_EXPORT_SPECIAL_CHANNEL=123,14,691,691,695,2
+
+SIGN_MALE_RECOMF=758,642
+SIGN_FEMALE_RECOMF=857,917
+
+ACTIVITY_ID=16
+ACTIVITY_TITLE='[五一书币欢乐送,领取6000书币]'
+OFF_SHELF_DOMAIN='iycdm.com'
+CHANNEL_INNER_ROLE=5,14,123,2
+QRCODE_AUTH_URL='https://zsyauth.aizhuishu.com/user_oauth'
+LONG_ACTIVITY_PRODUCT_ID=916,917
+
+
+SIGN_CALL_BACK_ACTIVITY_ID=16
+SIGN_CALL_BACK_ACTIVITY_TITLE=¥¥五一书币欢乐送·充28送32
+
+
+YEAR_ACTIVITY_CHANNEL=5,8,123,266,14,2
+YEAR_MALE_BID=2346,2434,1108,2408,1599,642,2115
+YEAR_FEMALE_BID=2346,2434,1108,2408,1599,642,2115
+YEAR_MALE_SITE=5
+YEAR_ACTIVITY_ID=10816
+YEAR_OLD_ACTIVITY_ID=17
+internal_shelf_text_mode_book_white_list=1
+
+READR_BOTTOM_ACTIVITY_IMG='https://yueduyun.oss-cn-hangzhou.aliyuncs.com/h5/2018042605.jpg'
+READR_BOTTOM_ACTIVITY_IMG_YEAR='https://yueduyun.oss-cn-hangzhou.aliyuncs.com/h5/2018042702.jpg'
+
+not_in_pay_merchant_id=13,14,15,16,17,18,19,20,21,22,23,24,25,26,27
+
+CHANNEL_RECOMMEND_IMPORTANT_BIDS=1460,1005,936,48,1347,1576,917,1021,532,10,1154,1257,1304,1475,1389,490,857,324
+CHANNEL_RECOMMEND_BIDS=1460,1005,936,48,1347,917,1021,532,10,1257,1304,1475,1389,490,857,324
+
+HIDDEN_READER_MENUS=69434,123
+no_participate_activity=168
+
+FILL_SEND_ORDER_ID=67
+
+NOT_ALLOW_ACCESS_SITE=1
+
+
+HIDE_BOOKS=1850,1347
+
+SHOW_NEW_BOOK_PAGE=
+
+SHOW_CHAPTER_PRICE_CHANNEL=all
+
+OPEN_WELFARE_CHANNEL=12,14
+
+IS_OPEN_DB_RECORD=false
+
+IS_OPEN_PAGE_RECORD=true
+
+SHOW_CUSTOM_ACTIVITY_CHANNEL=2
+
+HIDDEN_READ_BOOTSTRAP=22
+
+OSS_INTERNAL_DOMAIN=http://yueduyun.oss-cn-hangzhou-internal.aliyuncs.com
+
+NATIONAL_DAY_ACTIVITY_IDS=2322,2323,2324
+
+NOT_ALLOW_PAID_USER_CHANNEL_ID=2,1
+
+FOREVER_ACTIVITY_ID=930
+
+FOREVER_ACTIVITY_BID=1,2,3
+
+HELP_PAY_PAGE_CHANNEL_ID=2
+
+JUMP_AGENT_URL=t.leyuee.com
+
+SHOPPING_DAY_ACTIVITY_IDS=2990,2991,2992
+
+CAN_ACCESS_SITE=2,1
+
+FISSION_SEND_ORDER_ID=1
+
+RECORD_FIRST_VISIT_PAY_PAGE_TIME=1542088800
+
+NEW_SUB_PAGE=2
+
+DATA_ANALYSIS_SELECT_USERS_SUBSCRIBE_TIME=1542088800
+
+SPECIAL_USER_LOG=7530391
+
+JS_AppId=wx1037462ad78bf1f2
+JS_AppSecret=d6bda51bfdb4cf6eb504c622fd72c210
+AGENT_DOMAIN=agent.pre.aizhuishu.com
+
+SHARE_DOMAIN=pre.aizhuishu.com
+
+WECHAT_OP_APPID=wxceb2aacdce248393
+
+SHORT_PUSH_SHORT_START_TIME=1545705063
+
+TEMPLATE_COMPARE_START_TIME=147804996
+
+NEW_AUTH_CHANNEL_ID=2
+
+OTHER_ACTIVITY_ID=2631
+OTHER_ACTIVITY_CHANNEL=14
+
+ADS_OPEN_SITE=2
+
+OUTSTANDING_YEAR_ORDER_SITE=3,4,5,6
+
+SHOW_CUSTOM_NEW_USER_ACTIVITY_CHANNEL=21
+
+share_domain_url=http://sitejump.pre.aizhuishu.com/share/show
+
+share_domain=sitejump.pre.aizhuishu.com
+SHARE_OPEN_SITE=2
+
+TEST_CPC_UID=167655,109861757,7530367,109861732,7530398
+CREATE_PAY_URL=https://prepay.aizhuishu.com/goToPay

+ 68 - 0
app/Http/Controllers/KuaiYingYong/BaseController.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong;
+use Illuminate\Routing\Controller;
+use App\Modules\User\Models\Xcxuser;
+use JWTAuth;
+class BaseController extends Controller
+{
+
+    /**
+     * 公众号接口签名密钥
+     * @var string
+     */
+    protected $secret_key = 'Uv%vkPI5K8Opqoww';
+
+
+    protected function checkUid(){
+        if(!$this->getAuthenticatedUser()) return false;
+        return true;
+    }
+
+    public function __get($name)
+    {
+        static $user =null;
+        if(is_null($user)) $user =  $this->getAuthenticatedUser();
+
+        if($name == '_user_info'){
+            return $user;
+        }
+        if($name == 'uid'){
+            return $user->id;
+        }
+        if($name == 'distribution_channel_id'){
+            return $user->distribution_channel_id;
+        }
+        if($name == 'openid'){
+            $xcx_user = Xcxuser::where('uid',$user->id)->select('openid')->first();
+            return $xcx_user->openid;
+        }
+        return null;
+    }
+
+    public function getAuthenticatedUser(){
+        try {
+            if (! $user = JWTAuth::parseToken()->authenticate()) {
+                return false;
+            }
+        } catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
+            return false;
+            //return response()->json(['token_expired'], $e->getStatusCode());
+        } catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
+            return false;
+            //return response()->json(['token_invalid'], $e->getStatusCode());
+        } catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
+            return false;
+            //return response()->json(['token_absent'], $e->getStatusCode());
+        }
+
+        return $user;
+    }
+
+    public function checkSign($param){
+        if(!isset($param['sign'])) return false;
+        if(empty($param['sign'])) return false;
+
+        return $param['sigin'] == _sign($param,$this->secret_key);
+    }
+}

+ 70 - 0
app/Http/Controllers/KuaiYingYong/Book/BookCategoryController.php

@@ -0,0 +1,70 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Book;
+
+use Illuminate\Http\Request;
+use App\Http\Controllers\Controller;
+use App\Modules\Book\Services\BookCategoryService;
+class BookCategoryController extends Controller
+{
+    /**
+     * @apiDefine Book 图书
+     */
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 获取分类
+     * @api {get} books/getCategory  获取分类
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Book
+     * @apiName getCategory
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:  [
+     *                   {
+     *                   id: 1,
+     *                   name: "男频",
+     *                   children: [
+     *                           {
+     *                               id: 7,
+     *                               name: "灵异鬼怪"
+     *                           },
+     *                           {
+     *                               id: 8,
+     *                               name: "历史穿越"
+     *                           },
+     *                           {
+     *                               id: 30,
+     *                               name: "青春爱情"
+     *                           }
+     *                       ]
+     *                   },
+     *                   {
+     *                   id: 2,
+     *                   name: "女频",
+     *                   children: [
+     *                           {
+     *                               id: 26,
+     *                               name: "豪门总裁"
+     *                           },
+     *                           {
+     *                               id: 35,
+     *                               name: "民国爱情"
+     *                           }
+     *                       ]
+     *                   }
+     *               ]
+     *       }
+     */
+    public function getCategory(Request $request){
+        $res = BookCategoryService::getCategory(true);
+        return response()->success($res);
+    }
+}

Plik diff jest za duży
+ 662 - 0
app/Http/Controllers/KuaiYingYong/Book/BookController.php


+ 668 - 0
app/Http/Controllers/KuaiYingYong/Book/ChapterController.php

@@ -0,0 +1,668 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Book;
+
+use Illuminate\Http\Request;
+use App\Http\Controllers\KuaiYingYong\BaseController;
+use Redis;
+use App\Modules\Book\Services\ChapterService;
+use App\Modules\User\Services\ReadRecordService;
+use App\Http\Controllers\KuaiYingYong\Book\Transformers\ChapterTransformer;
+use App\Modules\Book\Services\BookConfigService;
+use App\Http\Controllers\KuaiYingYong\Book\Transformers\ChapterListTransformer;
+use App\Modules\Subscribe\Services\BookOrderService;
+use App\Modules\Subscribe\Services\ChapterOrderService;
+use App\Modules\Subscribe\Services\YearOrderService;
+use App\Modules\OfficialAccount\Services\ForceSubscribeService;
+use App\Modules\Subscribe\Services\ChapterReminderService;
+use App\Modules\OfficialAccount\Services\OfficialAccountService;
+use Hashids;
+use GuzzleHttp\Client;
+use Log;
+use DB;
+use App\Modules\User\Services\UserSignService;
+use App\Modules\User\Services\UserDeepReadTagService;
+class ChapterController extends BaseController
+{
+
+    /**
+     * @apiDefine Chapter 章节
+     */
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 章节列表不分页
+     * @api {get} books/{bid}/allcatalog 章节列表不分页
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Chapter
+     * @apiName getCatalog
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Array}       data.list 分页结果集
+     * @apiSuccess {Int}         data.list.bid   bid
+     * @apiSuccess {Int}         data.list.chapter_id   章节id
+     * @apiSuccess {String}      data.list.chapter_name   章节名称
+     * @apiSuccess {Int}         data.list.chapter_sequence   序号
+     * @apiSuccess {Int}         data.list.chapter_is_vip   是否vip
+     * @apiSuccess {Int}         data.list.chapter_size   章节大小
+     * @apiSuccess {Int}         data.list.prev_cid   上一章节id
+     * @apiSuccess {Int}         data.list.next_cid   下一章节
+     * @apiSuccess {String}      data.list.recent_update_at   更新时间
+     * @apiSuccess {String}      data.list.is_need_subscirbe   是否强制关注
+     * @apiSuccess {object}      data.meta   分页信息
+     * @apiSuccess {Int}         data.meta.total  总条数
+     * @apiSuccess {Int}         data.meta.per_page  每页条数
+     * @apiSuccess {Int}         data.meta.current_page 当前页
+     * @apiSuccess {Int}         data.meta.last_page  最后页
+     * @apiSuccess {String}      data.meta.next_page_url  下一页
+     * @apiSuccess {String}      data.meta.prev_page_url  上一页
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:
+     *            [
+     *             {
+     *               bid: 5,
+     *               chapter_id: 5,
+     *               chapter_name: "第1240章 不是我",
+     *               chapter_sequence: 1239,
+     *               chapter_is_vip: 1,
+     *               chapter_size: 2422,
+     *               prev_cid: 0,
+     *               next_cid: 0,
+     *               recent_update_at: 2017-11-20 15:01:56,
+     *               is_need_subscirbe: 1,
+     *            },
+     *             {
+     *               bid: 5,
+     *               chapter_id: 5,
+     *               chapter_name: "第1240章 不是我",
+     *               chapter_sequence: 1239,
+     *               chapter_is_vip: 1,
+     *               chapter_size: 2422,
+     *               prev_cid: 0,
+     *               next_cid: 0,
+     *               recent_update_at: 2017-11-20 15:01:56,
+     *               is_need_subscirbe: 1,
+     *            },
+     *          ]
+     *       }
+     */
+    public function getCatalog(Request $request,$bid){
+        $bid = Hashids::decode($bid)[0];
+        $lists = ChapterService::getChapterLists($bid);
+        return response()->collection(new ChapterListTransformer,$lists);
+    }
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 章节列表分页
+     * @api {get} books/{bid}/catalog 章节列表分页
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Chapter
+     * @apiName getCatalogPerPage
+     * @apiParam   {Int}         page_size  分页大小(默认15)
+     * @apiParam   {Int}         page  页码(默认1)
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Array}       data.list 分页结果集
+     * @apiSuccess {Int}         data.list.bid   bid
+     * @apiSuccess {Int}         data.list.chapter_id   章节id
+     * @apiSuccess {String}      data.list.chapter_name   章节名称
+     * @apiSuccess {Int}         data.list.chapter_sequence   序号
+     * @apiSuccess {Int}         data.list.chapter_is_vip   是否vip
+     * @apiSuccess {Int}         data.list.chapter_size   章节大小
+     * @apiSuccess {Int}         data.list.prev_cid   上一章节id
+     * @apiSuccess {Int}         data.list.next_cid   下一章节
+     * @apiSuccess {String}      data.list.recent_update_at   更新时间
+     * @apiSuccess {String}      data.list.is_need_subscirbe   是否强制关注
+     * @apiSuccess {object}      data.meta   分页信息
+     * @apiSuccess {Int}         data.meta.total  总条数
+     * @apiSuccess {Int}         data.meta.per_page  每页条数
+     * @apiSuccess {Int}         data.meta.current_page 当前页
+     * @apiSuccess {Int}         data.meta.last_page  最后页
+     * @apiSuccess {String}      data.meta.next_page_url  下一页
+     * @apiSuccess {String}      data.meta.prev_page_url  上一页
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:
+     *            list:[
+     *             {
+     *               bid: 5,
+     *               chapter_id: 5,
+     *               chapter_name: "第1240章 不是我",
+     *               chapter_sequence: 1239,
+     *               chapter_is_vip: 1,
+     *               chapter_size: 2422,
+     *               prev_cid: 0,
+     *               next_cid: 0,
+     *               recent_update_at: 2017-11-20 15:01:56,
+     *               is_need_subscirbe: 1,
+     *            },
+     *             {
+     *               bid: 5,
+     *               chapter_id: 5,
+     *               chapter_name: "第1240章 不是我",
+     *               chapter_sequence: 1239,
+     *               chapter_is_vip: 1,
+     *               chapter_size: 2422,
+     *               prev_cid: 0,
+     *               next_cid: 0,
+     *               recent_update_at: 2017-11-20 15:01:56,
+     *               is_need_subscirbe: 1,
+     *            },
+     *          ]
+     *          meta:{
+     *              total: 1253,
+     *              per_page: 15,
+     *              current_page: 1,
+     *              last_page: 84,
+     *              next_page_url: "http://myapi.cn/api/books/1/chapter?page=2",
+     *              prev_page_url: ""
+     *         }
+     *       }
+     */
+    public function getCatalogPerPage(Request $request,$bid){
+        $bid = Hashids::decode($bid)[0];
+        $page_size = $request->input('page_size',15);
+        $res = ChapterService::getChapterListsPage($bid,$page_size);
+        return response()->pagination(new ChapterListTransformer,$res);
+    }
+
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 章节内容
+     * @api {get} books/{bid}/chapters/{chapter_id} 章节内容
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Chapter
+     * @apiName index
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Int}         data.chapter_id   章节id
+     * @apiSuccess {String}      data.chapter_name   章节名称
+     * @apiSuccess {Int}         data.chapter_sequence   序号
+     * @apiSuccess {Int}         data.chapter_is_vip   是否vip
+     * @apiSuccess {Int}         data.chapter_size   章节大小
+     * @apiSuccess {Int}         data.prev_cid   上一章节id
+     * @apiSuccess {Int}         data.next_cid   下一章节
+     * @apiSuccess {String}      data.recent_update_at   更新时间
+     * @apiSuccess {String}      data.chapter_content  章节内容
+     * @apiSuccess {Int}         data.is_need_subscirbe  是否强制关注(删除)
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {
+     *               chapter_id: 5,
+     *               chapter_name: "第1240章 不是我",
+     *               chapter_sequence: 1239,
+     *               chapter_is_vip: 1,
+     *               chapter_size: 2422,
+     *               prev_cid: 0,
+     *               next_cid: 0,
+     *               recent_update_at: 2017-11-20 15:01:56,
+     *               chapter_content: "叶妩被司行霈的阴阳怪气一吓,思路偏得太远了。 她张口结舌,忘记了自己要说什么。",
+     *            }
+     *       }
+     */
+    public function index(Request $request,$bid,$cid){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $oldbid = $bid;
+        $bid = Hashids::decode($bid)[0];
+        //获取图书信息
+        $book_info  = BookConfigService::getBookById($bid);
+
+
+        if(empty($book_info)) return response()->error('XCX_SYS_ERROR');
+
+        if($book_info->is_on_shelf == 0 || $book_info->is_on_shelf == 3){
+            //return response()->error('XCX_OFF_SHELF');
+        }
+        //获取章节信息
+        $chapter = ChapterService::getChapterNameById($cid,$bid);
+        if(!$chapter){
+            return response()->error('XCX_SYS_ERROR');
+        }
+
+        if($chapter->is_vip == 0){
+            ReadRecordService::addReadRecord(['uid'=>$this->uid,'bid'=>$bid,'book_name'=>$book_info->book_name,
+                'cid'=>$cid,'chapter_name'=>$chapter->name ]);
+            //用户标签
+            if($chapter->sequence >= 20){
+                $this->addTag($book_info);
+            }
+            return response()->item(new ChapterTransformer,$this->getChapter($bid,$cid,$chapter));
+        }
+
+        //已经付费
+        if($this->getOrderRecord($bid,$cid)){
+            ReadRecordService::addReadRecord(['uid'=>$this->uid,'bid'=>$bid,'book_name'=>$book_info->book_name,
+                'cid'=>$cid,'chapter_name'=>$chapter->name ]);
+            //用户标签
+            if($chapter->sequence >= 20){
+                $this->addTag($book_info);
+            }
+            return response()->item(new ChapterTransformer,$this->getChapter($bid,$cid,$chapter));
+        }
+
+        //未付费 要提醒
+        $user_info = $this->_user_info;
+        //未付费 余额不足
+        $fee = $this->getPrice($book_info,$chapter->size);
+        $data = [
+            'book_id'=>$oldbid,
+            'book_name'=>$book_info->book_name,
+            'chapter_name'=>$chapter->name,
+            'chapter_id'=>$cid,
+            'pay_type'=>$book_info->charge_type,
+            'fee'=>$fee,
+            'user_balance'=>$user_info->balance,
+            'product_id'=>$book_info->product_id,
+            'uid'=>$this->uid,
+            'distribution_channel_id'=>$this->distribution_channel_id,
+            'is_discount'=>0,
+            'discount_fee' => '',
+            'discount'=>''
+
+        ];
+
+        if($user_info['balance'] < $fee){
+            //需要提箱
+            if($this->isOrderRemind($bid)){
+
+                if($book_info->charge_type == 'BOOK'){
+                    return response()->error('XCX_BOOK_BALANCE_PAY',$data);
+                }else
+                    if($book_info->charge_type == 'CHAPTER'){
+                        return response()->error('XCX_CHAPTER_INSUFFICIENT_BALANCE',$data);
+                    }else{
+                        return response()->error('XCX_SYS_ERROR');
+                    }
+            }else{
+                //不需要提醒
+                if($book_info->charge_type == 'BOOK'){
+                    return response()->error('XCX_BOOK_SECOND_BALANCE_PAY',$data);
+                }elseif($book_info->charge_type == 'CHAPTER'){
+                    return response()->error('XCX_CHAPTER_SECOND_BALANCE_PAY',$data);
+                }else{
+                    return response()->error('XCX_SYS_ERROR');
+                }
+            }
+        }
+
+        if($this->isOrderRemind($bid)){
+            //return response()->error('INSUFFICIENT_BALANCE',$data);
+            if($book_info->charge_type  == 'BOOK'){
+                return response()->error('XCX_BOOK_BUY',$data);
+            }else
+                if($book_info->charge_type == 'CHAPTER'){
+                    return response()->error('XCX_CHAPTER_BUY',$data);
+                }else{
+                    return response()->error('XCX_SYS_ERROR');
+                }
+        }
+        //付费 不提醒
+        if($this->balancePay($book_info,$cid,$chapter->size,$chapter->name,0)){
+
+            ReadRecordService::addReadRecord(['uid'=>$this->uid,'bid'=>$bid,'book_name'=>$book_info->book_name,
+                'cid'=>$cid,'chapter_name'=>$chapter->name ]);
+            //用户标签
+            if($chapter->sequence >= 20){
+                $this->addTag($book_info);
+            }
+            return response()->item(new ChapterTransformer,$this->getChapter($bid,$cid,$chapter));
+        }else{
+
+            //不需要提醒
+            if($book_info->charge_type == 'BOOK'){
+                return response()->error('XCX_BOOK_SECOND_BALANCE_PAY',$data);
+            }elseif($book_info->charge_type == 'CHAPTER'){
+                return response()->error('XCX_CHAPTER_SECOND_BALANCE_PAY',$data);
+            }else{
+                return response()->error('XCX_SYS_ERROR');
+            }
+        }
+    }
+
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 余额支付
+     * @api {get} books/{bid}/balance/chapterOrders/{cid} 余额支付
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Chapter
+     * @apiName pay
+     * @apiParam   (Int)         remind 提醒
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Int}         data.chapter_id   章节id
+     * @apiSuccess {String}      data.chapter_name   章节名称
+     * @apiSuccess {Int}         data.chapter_sequence   序号
+     * @apiSuccess {Int}         data.chapter_is_vip   是否vip
+     * @apiSuccess {Int}         data.chapter_size   章节大小
+     * @apiSuccess {Int}         data.prev_cid   上一章节id
+     * @apiSuccess {Int}         data.next_cid   下一章节
+     * @apiSuccess {String}      data.recent_update_at   更新时间
+     * @apiSuccess {String}      data.chapter_content  章节内容
+     * @apiSuccess {Int}         data.is_need_subscirbe  是否强制关注(删除)
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {
+     *               chapter_id: 5,
+     *               chapter_name: "第1240章 不是我",
+     *               chapter_sequence: 1239,
+     *               chapter_is_vip: 1,
+     *               chapter_size: 2422,
+     *               prev_cid: 0,
+     *               next_cid: 0,
+     *               recent_update_at: 2017-11-20 15:01:56,
+     *               chapter_content: "叶妩被司行霈的阴阳怪气一吓,思路偏得太远了。 她张口结舌,忘记了自己要说什么。",
+     *            }
+     *       }
+     */
+    public function pay(Request $request,$bid,$cid){
+
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $remind = (int)$request->input('remind');
+        $oldbid = $bid;
+        $bid = Hashids::decode($bid)[0];
+        $book_info = BookConfigService::getBookById($bid);;
+        if(empty($book_info)) response()->error('XCX_SYS_ERROR');
+
+        if($book_info->is_on_shelf == 0 || $book_info->is_on_shelf == 3){
+            if(!$this->isBookOrdered($bid)){
+                response()->error('XCX_OFF_SHELF');
+            } 
+        }
+        //获取章节
+        $chapter = ChapterService::getChapterNameById($cid,$bid);
+        if(!$chapter){
+            return response()->error('XCX_SYS_ERROR');
+        }
+
+
+        if($this->balancePay($book_info,$cid,$chapter->size,$chapter->name,$remind)){
+            ReadRecordService::addReadRecord(['uid'=>$this->uid,'bid'=>$bid,'book_name'=>$book_info->book_name,
+                'cid'=>$cid,'chapter_name'=>$chapter->name ]);
+            //用户标签
+            if($chapter->sequence >= 20){
+                $this->addTag($book_info);
+            }
+            return response()->item(new ChapterTransformer,$this->getChapter($bid,$cid,$chapter));
+        }else{
+            $fee = $this->getPrice($book_info,$chapter->size);
+
+            $data = [
+                'book_id'=>$oldbid,
+                'book_name'=>$book_info->book_name,
+                'chapter_name'=>$chapter->name,
+                'chapter_id'=>$cid,
+                'pay_type'=>$book_info->charge_type,
+                'fee'=>$fee,
+                'user_balance'=>$this->_user_info['balance'],
+                'product_id'=>$book_info->product_id,
+                'uid'=>$this->uid,
+                'distribution_channel_id'=>$this->distribution_channel_id,
+                'is_discount'=>0,
+                'discount_fee' => '',
+                'discount'=>''
+            ];
+            //不需要提醒
+            if($book_info->charge_type == 'BOOK'){
+                return response()->error('XCX_BOOK_SECOND_BALANCE_PAY',$data);
+            }elseif($book_info->charge_type == 'CHAPTER'){
+                return response()->error('XCX_CHAPTER_SECOND_BALANCE_PAY',$data);
+            }else{
+                return response()->error('XCX_SYS_ERROR');
+            }
+        }
+    }
+
+
+
+    /**
+     * 余额支付
+     * @param $book_info
+     * @param $chapter_id
+     * @param $chapter_size
+     * @return bool
+     */
+    protected function balancePay($book_info,$chapter_id,$chapter_size,$chapter_name,$is_remind){
+        $fee = $this->getPrice($book_info,$chapter_size);
+        if((int)$this->_user_info['balance'] >= $fee){
+            if($this->bookOrderOrChapterOrder($book_info,$chapter_id,$fee,$chapter_name,$is_remind)){
+                return true;
+            }
+            return false;
+        }else{
+            return false;
+        }
+
+    }
+
+
+    /**
+     * 获取章节内容
+     * @param $bid
+     * @param $cid
+     * @return bool|mixed
+     */
+    protected function getChapter($bid,$cid,$chapter){
+        $chapter_content = ChapterService::getChapter($bid,$cid);
+        if(!$chapter_content) return false;
+        //$chapter->content = $chapter_content->content;
+        $chapter->content = trim(str_replace($chapter_content->name, '', $chapter_content->content));
+        //统计点击率
+        $key = 'book_click_num_bid_'.$bid;
+        $field = date('Y-m-d');
+        $old = Redis::hget($key,$field);
+        if(!$old)  $old = 0;
+        Redis::hset($key,$field,$old+1);
+        //签到奖励
+        /*
+        $sign_key = 'sign-'.date('Y-m-d');
+        $sign_status = 0;
+        if(!Redis::hexists($sign_key,$this->uid)){
+            Redis::hset($sign_key,$this->uid,time());
+            $sign_status = 1;
+        }*/
+        $sign_status = $this->userSign($this->uid);
+        $chapter->sign_status = $sign_status;
+        return $chapter;
+    }
+
+    /**
+     * 签到
+     * @param $uid
+     * @return int
+     */
+    protected function userSign($uid){
+
+        if($this->distribution_channel_id != 5){
+            return 0;
+        }
+
+        $day = date('Y-m-d');
+        if(UserSignService::isSign($uid,$day)){
+            return 0;
+        }
+        if(UserSignService::sign($uid,$day)){
+            return 1;
+        }
+        return 0;
+
+    }
+    /**
+     * 添加订购记录
+     * @param $book_info
+     * @param $chapter_id
+     * @param $fee
+     * @return bool
+     */
+    protected function bookOrderOrChapterOrder($book_info,$chapter_id,$fee,$chapter_name,$is_remind){
+        $send_order_id = 0;
+        if($book_info['charge_type'] == 'BOOK'){
+            $data = [
+                'uid'=>$this->uid,
+                'fee'=>$fee,
+                'u'=>$send_order_id,
+                'distribution_channel_id'=>$this->distribution_channel_id,
+                'bid'=>$book_info->bid,
+                'book_name'=>$book_info->book_name,
+                'send_order_id'=>$send_order_id,
+            ];
+            return BookOrderService::addOrderRecodeAndDecrUserBalance($data,$this->uid);
+        }
+        else{
+            $data = [
+                'uid'=>$this->uid,
+                'fee'=>$fee,
+                'cid'=>$chapter_id,
+                'bid'=>$book_info->bid,
+                'distribution_channel_id'=>$this->distribution_channel_id,
+                'book_name'=>$book_info->book_name,
+                'chapter_name'=>$chapter_name,
+                'send_order_id'=>$send_order_id,
+                'is_remind'=>$is_remind
+            ];
+            //print_r($data);
+            if($is_remind){
+                $this->addOrderRemind($book_info->bid);
+            }
+            return ChapterOrderService::addOrderAndDecrUserBalance($data,$this->uid);
+        }
+    }
+
+
+    protected  function  addOrderRemind($bid){
+        if(ChapterReminderService::checkIsNoReminder($this->uid,$bid)){
+            return true;
+        }else{
+            ChapterReminderService::add($this->uid,$bid);
+            return true;
+        }
+    }
+    /**
+     * 是否订购提醒
+     * @param $chapter_id
+     * @return bool
+     */
+    protected function isOrderRemind($bid){
+        $is_no_reminder = ChapterReminderService::checkIsNoReminder($this->uid,$bid) ? 1 : 0;
+        return $is_no_reminder == 0;
+    }
+
+    /**
+     * 用户是否关注
+     * @param $uid
+     * @return bool
+     */
+    protected  function getSubscribe(){
+        $res = ForceSubscribeService::forceSubscribeUsersByUid(['uid'=>$this->uid]);
+        if($res) return true;
+        return false;
+    }
+
+
+    /**
+     * 获取订购记录
+     * @param $book_info
+     * @param $chapter_id
+     * @return bool
+     */
+    protected function getOrderRecord($bid,$chapter_id){
+        //包年记录
+        $uid = $this->uid;
+        $res = YearOrderService::getRecord($uid);
+        if($res) return true;
+        $res = null;
+
+        //单本订购记录
+        $res = BookOrderService::getRecordByuidBid($uid,$bid);
+        if($res) return true;
+        $res = null;
+
+        //章节订购记录
+        $chapterOrder = new ChapterOrderService();
+
+        if($chapterOrder->checkIsOrdered($uid,$bid,$chapter_id))  return true;
+
+        return false;
+    }
+
+
+    /**
+     * 计算价格
+     * @param $book_info
+     * @param $chapter_size
+     * @return float
+     */
+    protected function getPrice($book_info,$chapter_size){
+        if($book_info->charge_type == 'BOOK')
+            return $book_info->price*100;
+        return   ceil($chapter_size/100);
+    }
+
+
+
+
+    /**
+     * 用户添加标签
+     * @param $book_info
+     */
+    protected function addTag($book_info){
+        $send_order_id = 0;
+        if(!UserDeepReadTagService::isAddTag($this->uid,$book_info->bid)){
+            try{
+                UserDeepReadTagService::addTag([
+                    'uid'=>$this->uid,
+                    'bid'=>$book_info->bid,
+                    'book_name'=>$book_info->book_name,
+                    'category_id'=>$book_info->category_id,
+                    'category_name'=>$book_info->category_name,
+                    'sex_preference'=>$book_info->channel_name?$book_info->channel_name:'',
+                    'distribution_channel_id'=>$this->distribution_channel_id?$this->distribution_channel_id:'0',
+                    'send_order_id'=>$send_order_id,
+                ]);
+            }catch (\Exception  $e){
+
+            }
+
+        }    
+    }
+
+
+    protected function isBookOrdered($bid){
+
+        $chapter_order = ChapterOrderService::checkBookIsOrdered($this->uid,$bid);
+        if($chapter_order) return true;
+
+        $res = BookOrderService::getRecordByuidBid($this->uid,$bid);
+        if($res) return true;
+        return false;
+    }
+}

+ 45 - 0
app/Http/Controllers/KuaiYingYong/Book/Transformers/BookTransformer.php

@@ -0,0 +1,45 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * Date: 2017/3/31
+ * Time: 14:02
+ */
+
+namespace App\Http\Controllers\KuaiYingYong\Book\Transformers;
+use Hashids;
+class BookTransformer
+{
+    public function transform($book){
+        return [
+            'book_id'=>Hashids::encode($book->bid),
+            //'book_id_no_hash'=>$book->bid,
+            'book_name'=>$book->book_name,
+            'book_summary'=>$book->intro,
+            'book_author'=>$book->author,
+            'cover_url'=>$book->cover,
+            'book_word_count'=>$book->size,
+            'book_chapter_total'=>$book->chapter_count,
+            'book_category_id'=>$book->category_id,
+            'book_category'=>$book->category_name,
+            'book_end_status'=>$book->status,
+            'book_published_time'=>is_null($book->updated_at)?'':$book->updated_at,
+            'copyright'=>is_null($book->copyright)? '':$book->copyright,
+            'charge_type'=>is_null($book->charge_type)?'':$book->charge_type,
+            'force_subscribe_chapter_id'=>$book->force_subscribe_chapter_seq,
+            'update_time'=>$book->updated_at,
+            'is_on_shelf'=>$book->is_on_shelf,
+            'book_price'=>is_null($book->price)?0:$book->price,
+            'keyword'=>$book->keyword,
+            'recommend_index'=> $book->recommend_index,
+            'is_show_index_content'=>$book->is_show_index_content,
+            'click_count'=>$book->click_count,
+            'product_id'=>$book->product_id,
+            'sex_preference'=>$book->channel_name,
+            'last_cid'=>$book->last_cid,
+            'last_chapter'=>$book->last_chapter,
+            'first_cid'=>$book->first_cid,
+            'is_on_user_shelf'=>$book->is_on_user_shelf,
+            'last_chapter_is_vip'=>$book->last_chapter_is_vip
+        ];
+    }
+}

+ 22 - 0
app/Http/Controllers/KuaiYingYong/Book/Transformers/ChapterListTransformer.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Book\Transformers;
+use Hashids;
+class ChapterListTransformer
+{
+
+    public function transform($chapter){
+        return [
+            'bid'       =>  Hashids::encode($chapter->bid),
+            //'bid_no_hash'       =>  ($chapter->bid),
+            'chapter_id'       =>  $chapter->id,
+            'chapter_name'   =>  $chapter->name,
+            'chapter_sequence'   =>  $chapter->sequence,
+            'chapter_is_vip'   =>  $chapter->is_vip,
+            'chapter_size'   =>  $chapter->size,
+            'prev_cid'   =>  $chapter->prev_cid,
+            'next_cid'   =>  $chapter->next_cid,
+            'recent_update_at'   =>  $chapter->recent_update_at,
+        ];
+    }
+}

+ 24 - 0
app/Http/Controllers/KuaiYingYong/Book/Transformers/ChapterTransformer.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Book\Transformers;
+use Hashids;
+class ChapterTransformer
+{
+    public function transform($chapter){
+        return [
+            'bid'       =>  Hashids::encode($chapter->bid),
+            //'bid_no_hash'       =>  $chapter->bid,
+            'chapter_id'       =>  $chapter->id,
+            'chapter_name'   =>  $chapter->name,
+            'chapter_sequence'   =>  $chapter->sequence,
+            'chapter_is_vip'   =>  $chapter->is_vip,
+            'chapter_size'   =>  $chapter->size,
+            'prev_cid'   =>  $chapter->prev_cid,
+            'next_cid'   =>  $chapter->next_cid,
+            'recent_update_at'   =>  $chapter->recent_update_at,
+            'chapter_content'   =>  $chapter->content,
+            'sign_status'   =>  $chapter->sign_status,
+            //'is_need_subscirbe'   =>  $chapter->is_need_subscirbe,
+        ];
+    }
+}

+ 283 - 0
app/Http/Controllers/KuaiYingYong/Oauth/UsersController.php

@@ -0,0 +1,283 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Oauth;
+
+use App\Modules\User\Services\UserService;
+use App\Modules\Xcx\Services\XcxSendOrderService;
+use Illuminate\Http\Request;
+use App\Http\Controllers\Controller;
+use App\Modules\User\Models\User;
+use App\Modules\User\Models\Xcxuser;
+use Log;
+use JWTAuth;
+use GuzzleHttp\Client;
+
+class UsersController extends Controller
+{
+
+
+    /**
+     * @apiDefine Login 登录
+     */
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 登录
+     * @api {post} login 登录
+     * @apiParam  {String}  js_code js_code
+     * @apiParam  {Int}     distribution_channel_id distribution_channel_id
+     * @apiParam  {String}  sign    签名
+     * @apiGroup Login
+     * @apiName index
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {String}      data.token token
+     * @apiSuccess {Int}         data.time 过期时间
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:  {
+     *            token:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
+     *            time:123455
+     *           }
+     *       }
+     */
+    public function index(Request $request)
+    {
+        Log::info($request->all());
+        //$distribution_channel_id = $request->input('distribution_channel_id', '');
+        //海报推广的参数
+        $scene = $request->input('scene', '');
+        $js_code = $request->input('js_code');
+        $sign = $request->input('sign');
+        $encryptedData = $request->input('encryptedData');
+        $iv = $request->input('iv');
+        //参数推广的参数
+        $channel_key = $request->input('channel_key',0);
+        $sign = 1;
+        if (empty($js_code)  || empty($sign)) {
+            return response()->error('PARAM_ERROR');
+        }
+        $distribution_channel_id = 14;
+        $uid = 0;
+        $u = 0;
+        //解析海报推广的参数
+        if($scene){
+            $scene_arr = explode('_',$scene);
+            $distribution_channel_id = (int)$scene_arr[0];
+            $uid = $scene_arr[1];
+            $u = $scene_arr[2];
+        }
+        //解析参数推广的参数
+        if($channel_key){
+            $channel_key =(int)$channel_key;
+            $channel_info = XcxSendOrderService::getChannelIdBySendOrderId($channel_key);
+            if($channel_info){
+                $distribution_channel_id = $channel_info->distribution_channel_id;
+                $u = $channel_key;
+            }
+        }
+        if ($sign !== _sign(compact('openid', 'distribution_channel_id', 'unionid'), 'Uv%vkPI5K8Opqoww')) {
+            //return response()->error('PARAM_ERROR');
+        }
+        $login_info = $this->getUserWeixinInfo($js_code);
+        $appid = 'wxa0c8331eba3b34d5';
+        $status = $this->decryptData($appid,$login_info['session_key'],$encryptedData,$iv,$user_info);
+
+        if($status != ErrorCode::$OK){
+            return response()->error('PARAM_ERROR');
+        }
+
+        if (!$user_info) response()->error('PARAM_ERROR');
+        $user_info = json_decode($user_info,1);
+        if (!isset($user_info['openId']) || !isset($user_info['unionId'])) {
+            return response()->error('PARAM_ERROR');
+        }
+        $openid = $user_info['openId'];
+        $unionid = $user_info['unionId'];
+        $user = $this->createUser(compact('openid', 'distribution_channel_id', 'unionid','uid','u'),$user_info);
+        if ($user) {
+            $uid = $user->id;
+            $time = time() + 7200;
+            $token = JWTAuth::fromUser($user);
+            return response()->success(compact('token', 'time','uid'));
+        } else {
+            return response()->error('PARAM_ERROR');
+        }
+    }
+
+    /**
+     * 授权用户信息
+     * @param $data
+     * @return bool
+     */
+    protected function createUser($data,$user_info)
+    {
+        //compact('openid', 'distribution_channel_id', 'unionid','uid','u')
+        //用户已经是小程序用户了
+        $xcx_user = Xcxuser::where('unionid',$data['unionid'])
+            ->where('distribution_channel_id',$data['distribution_channel_id'])
+            ->select('uid')
+            ->first();
+        if($xcx_user){
+            return User::find($xcx_user->uid);
+        }
+        $info = [];
+        if(isset($user_info['city']) && !empty($user_info['city'])) {$info['city'] = $user_info['city'];}
+        if(isset($user_info['province']) && !empty($user_info['province'])){ $info['province'] = $user_info['province'];}
+        if(isset($user_info['country']) && !empty($user_info['country'])){ $info['country'] = $user_info['country'];}
+        if(isset($user_info['gender']) && !empty($user_info['gender'])) {$info['sex'] = $user_info['gender'];}
+        if(isset($user_info['nickName']) && !empty($user_info['nickName'])) {$info['nickname'] = $user_info['nickName'];}
+        if(isset($user_info['avatarUrl']) && !empty($user_info['avatarUrl'])) {$info['head_img'] = $user_info['avatarUrl'];}
+        //从推广进来的一般会有uid
+        if($data['uid']){
+            Xcxuser::create([
+                'uid'=>$data['uid'],
+                'openid'=>$data['openid'],
+                'unionid'=>$data['unionid'],
+                'distribution_channel_id'=>$data['distribution_channel_id'],
+                'u'=>$data['u']
+            ]);
+
+            if($info){
+                UserService::updateInfo($data['uid'],$info);
+            }
+            return User::find($data['uid']);
+        }else{
+            //直接进入的
+            $info['openid'] =$data['openid'];
+            $info['unionid'] =$data['openid'];
+            $info['distribution_channel_id'] =$data['distribution_channel_id'];
+            $info['send_order_id'] =$data['u'];
+            $user =  User::addUser($info);
+
+            Xcxuser::create([
+                'uid'=>$user->id,
+                'openid'=>$data['openid'],
+                'unionid'=>$data['unionid'],
+                'distribution_channel_id'=>$user->distribution_channel_id,
+                'u'=>$data['u']
+            ]);
+            return $user;
+        }
+    }
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 刷新token
+     * @api {get} RefreshToken 刷新token
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Login
+     * @apiName RefreshToken
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {String}      data.token token
+     * @apiSuccess {Int}         data.time 过期时间
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:  {
+     *            token:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
+     *            time:123455
+     *           }
+     *       }
+     */
+    public function RefreshToken()
+    {
+        try{
+            $old_token = JWTAuth::getToken();
+            $token = JWTAuth::refresh($old_token);
+            $time = time() + 7200;
+            return response()->success(compact('token', 'time'));
+        }catch (\Exception $e){
+
+        }
+        return response()->error('XCX_NOT_LOGIN');
+    }
+
+
+    private function getUserWeixinInfo($js_code)
+    {
+        if (empty($js_code)) {
+            return false;
+        }
+        $url = 'https://api.weixin.qq.com/sns/jscode2session?';
+        $client = new Client([
+            'timeout' => 2.0,
+        ]);
+        $appid = 'wxa0c8331eba3b34d5';
+        $secret = '17c01c26dd7873e557710601436774c7';
+        $grant_type = 'authorization_code';
+        try {
+            $res = $client->get($url . http_build_query(compact('js_code', 'appid', 'secret', 'grant_type')))->getBody()->getContents();
+            Log::info('code 换取 session_key is :');
+            Log::info($res);
+            $res = json_decode($res, true);
+            if (isset($res['errcode'])) {
+                return false;
+            }
+            return $res;
+        } catch (\Exception $e) {
+            Log::info($e);
+            return false;
+        }
+    }
+
+
+    /**
+     * 检验数据的真实性,并且获取解密后的明文.
+     * @param $encryptedData string 加密的用户数据
+     * @param $iv string 与用户数据一同返回的初始向量
+     * @param $data string 解密后的原文
+     *
+     * @return int 成功0,失败返回对应的错误码
+     */
+    private function decryptData($appid, $sessionKey,$encryptedData, $iv, &$data )
+    {
+        if (strlen($sessionKey) != 24) {
+            return ErrorCode::$IllegalAesKey;
+        }
+        $aesKey=base64_decode($sessionKey);
+
+
+        if (strlen($iv) != 24) {
+            return ErrorCode::$IllegalIv;
+        }
+        $aesIV=base64_decode($iv);
+
+        $aesCipher=base64_decode($encryptedData);
+
+        $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
+
+        $dataObj=json_decode( $result );
+        if( $dataObj  == NULL )
+        {
+            return ErrorCode::$IllegalBuffer;
+        }
+        if( $dataObj->watermark->appid !=$appid )
+        {
+            return ErrorCode::$IllegalBuffer;
+        }
+        $data = $result;
+        return ErrorCode::$OK;
+    }
+
+
+
+}
+class ErrorCode
+{
+    public static $OK = 0;
+    public static $IllegalAesKey = -41001;
+    public static $IllegalIv = -41002;
+    public static $IllegalBuffer = -41003;
+    public static $DecodeBase64Error = -41004;
+}

+ 719 - 0
app/Http/Controllers/KuaiYingYong/Order/OrdersController.php

@@ -0,0 +1,719 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Order;
+
+use App\Http\Controllers\KuaiYingYong\BaseController;
+use Illuminate\Http\Request;
+use App\Modules\Subscribe\Services\BookOrderService;
+use App\Modules\Subscribe\Services\ChapterOrderService;
+use App\Modules\Xcx\Services\XcxOrderService as OrderService;
+use App\Http\Controllers\KuaiYingYong\Order\Transformers\BookOrderTransformer;
+use App\Http\Controllers\KuaiYingYong\Order\Transformers\ChapterOrderTransformer;
+use App\Http\Controllers\KuaiYingYong\Order\Transformers\ChargeListTransformer;
+use App\Modules\Subscribe\Services\YearOrderService;
+use App\Modules\User\Services\UserService;
+use DB;
+use Redis;
+use Hashids;
+use EasyWeChat\Foundation\Application;
+use EasyWeChat\Payment\Order as Wxorder;
+use App\Modules\Product\Services\ProductService;
+use App\Modules\Book\Services\BookConfigService;
+use Log;
+
+class OrdersController extends BaseController
+{
+    /**
+     * @apiDefine Order 订单
+     */
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 充值列表
+     * @api {get} order/chargeList 充值列表
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Order
+     * @apiName chargeList
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: [
+     *               {
+     *                   product_id: 1,
+     *                   price: "30.00元",
+     *                   vip: 0,
+     *                   intro: [
+     *                       {
+     *                           label: 3000,
+     *                           important: false
+     *                       },
+     *                       {
+     *                           label: "书币",
+     *                           important: true
+     *                       }
+     *                   ]
+     *               },
+     *               {
+     *                   product_id: 2,
+     *                   price: "50.00元",
+     *                   vip: 1,
+     *                   intro: [
+     *                       {
+     *                           label: 5000,
+     *                           important: false
+     *                       },
+     *                       {
+     *                           label: "1000+",
+     *                           important: true
+     *                       },
+     *                       {
+     *                           label: "书币",
+     *                           important: false
+     *                       }
+     *                       ]
+     *               },
+     *               {
+     *                   product_id: 5,
+     *                   price: "365.00元",
+     *                   vip: 0,
+     *                   intro: [
+     *                       {
+     *                       label: "年费VIP会员",
+     *                       important: true
+     *                       }
+     *                   ]
+     *               }
+     *               ]
+     *       }
+     */
+    public function chargeList(Request $request)
+    {
+        if (!$this->checkUid()) {
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        
+        $device = $request->has('device')?$request->get('device'):'';
+        
+        // 苹果先不展示充值
+        if($device == 'iPhone'){
+        	return response()->success();
+        }
+        
+        $res = ProductService::getChargeProduct();
+        if (!$res->isEmpty()) {
+            $data = [];
+            foreach ($res as $v) {
+                $intro = [];
+                if ($v->given > 0 && $v->type == 'TICKET_RECHARGE') {
+                    $intro = [
+                        [
+                            'label' => ($v->price * 100) . "+",
+                            'important' => false,
+                        ],
+                        [
+                            'label' => $v->given,
+                            'important' => true,
+                        ],
+                        [
+                            'label' => '书币',
+                            'important' => false,
+                        ]
+
+                    ];
+                    $intro2 = [
+                        ['label' => '多送', 'important' => false],
+                        ['label' => (int)($v->given / 100), 'important' => true],
+                        ['label' => '元', 'important' => false],
+                    ];
+                    $v->vip = 0;
+                }
+                if ($v->given == 0 && $v->type == 'TICKET_RECHARGE') {
+                    $intro = [
+                        [
+                            'label' => $v->price * 100,
+                            'important' => false,
+                        ],
+                        [
+                            'label' => '书币',
+                            'important' => false,
+                        ]
+                    ];
+                    $v->vip = 0;
+                    $intro2 = [];
+                }
+                if ($v->given == 0 && $v->type == 'YEAR_ORDER') {
+                    $intro = [
+                        [
+                            'label' => '年费VIP会员',
+                            'important' => true,
+                        ]
+                    ];
+                    $v->vip = 1;
+                    $intro2 = [
+                        ['label' => '每天1元,全年免费看', 'important' => false],
+                    ];
+                }
+                $data[] = [
+                    'product_id' => $v->id,
+                    'price' => (int)$v->price . '元',
+                    'vip' => $v->vip,
+                    'intro' => $intro,
+                    'intro2' => $intro2,
+                    'is_default' => $v->is_default,
+                ];
+            }
+            return response()->success($data);
+        } else {
+            return response()->error('XCX_SYS_ERROR');
+        }
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 单本消费记录
+     * @api {get} order/bookOrderList 单本消费记录
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Order
+     * @apiName bookOrderList
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Int}         uid uid
+     * @apiSuccess {Int}         bid bid
+     * @apiSuccess {Int}         book_name 书名
+     * @apiSuccess {Int}         fee 钱
+     * @apiSuccess {String}      created_at 时间
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: list:[
+     *               {
+     *                   uid: 4,
+     *                   bid: 1,
+     *                   book_name: "dfsedfertrwet",
+     *                   fee: 100,
+     *                   created_at: "2017-12-02 16:24:54"
+     *                   }
+     *               ]
+     *            meta: {
+     *                       total: 1,
+     *                       per_page: 15,
+     *                       current_page: 1,
+     *                       last_page: 1,
+     *                       next_page_url: "",
+     *                       prev_page_url: ""
+     *               }
+     *       }
+     */
+    public function bookOrderList(Request $request)
+    {
+        if (!$this->checkUid()) {
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $page_size = $request->input('page_size', 15);
+        $book_order = BookOrderService::getRecord($this->uid, $page_size);
+        //$book_order = BookOrder::where('uid', $this->uid)->select('bid', 'uid', 'book_name', 'created_at', 'fee')->paginate($page_size);
+
+        return response()->pagination(new BookOrderTransformer(), $book_order);
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 章节消费记录
+     * @api {get} order/chapterOrderList 章节消费记录
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Order
+     * @apiName chapterOrderList
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Int}         uid uid
+     * @apiSuccess {Int}         bid bid
+     * @apiSuccess {Int}         cid cid
+     * @apiSuccess {Int}         chapter_name 章节名
+     * @apiSuccess {Int}         book_name 书名
+     * @apiSuccess {Int}         fee 钱
+     * @apiSuccess {String}      created_at 时间
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: list:[
+     *               {
+     *                   uid: 4,
+     *                   bid: 1,
+     *                   cid: 1,
+     *                   chapter_name: "sdfsd",
+     *                   book_name: "dfsedfertrwet",
+     *                   fee: 100,
+     *                   created_at: "2017-12-02 16:24:54"
+     *                   }
+     *               ]
+     *            meta: {
+     *                       total: 1,
+     *                       per_page: 15,
+     *                       current_page: 1,
+     *                       last_page: 1,
+     *                       next_page_url: "",
+     *                       prev_page_url: ""
+     *               }
+     *       }
+     */
+    public function chapterOrderList(Request $request)
+    {
+        if (!$this->checkUid()) {
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $chapter_model = new ChapterOrderService();
+        $page_size = $request->input('page_size', 15);
+        $chapter_order = $chapter_model->getByUid($this->uid, $page_size);
+        return response()->pagination(new ChapterOrderTransformer(), $chapter_order);
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 充值记录
+     * @api {get} order/chargeRecordLists 充值记录
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup Order
+     * @apiName chargeRecordLists
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {String}      data.price       价格
+     * @apiSuccess {String}      data.status      状态
+     * @apiSuccess {String}      data.trade_no    订单号
+     * @apiSuccess {String}      data.created_at  时间
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *    {
+     *       code: 0,
+     *       msg: "",
+     *           data: {
+     *               list: [
+     *               {
+     *                    id: 134,
+     *                    price: "1.00",
+     *                    status: "PAID",
+     *                    trade_no: "201712021915481585670623626232",
+     *                    created_at: "2017-12-02 19:15:56"
+     *           }
+     *       ],
+     *           meta: {
+     *               total: 1,
+     *               per_page: 15,
+     *               current_page: 1,
+     *               last_page: 1,
+     *               next_page_url: "",
+     *               prev_page_url: ""
+     *           }
+     *       }
+     *    }
+     */
+    public function chargeRecordLists(Request $request)
+    {
+        if (!$this->checkUid()) {
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $page_size = $request->input('page_size', 15);
+        $res = OrderService::getOrderList($this->uid, $page_size);
+        return response()->pagination(new ChargeListTransformer(), $res);
+    }
+
+    //订单是否成功
+    public function isSuccess(Request $request)
+    {
+        $order = $request->input('order');
+        $order_info = OrderService::getByTradeNo($order);
+        if ($order_info && $order_info->status == 'PAID') {
+            return response()->success();
+        }
+        return response()->error('XCX_SYS_ERROR');
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 支付
+     * @api {get} goToPay 支付
+     * @apiGroup pay
+     * @apiName wxindex
+     * @apiParam {Int}  product_id   product_id
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiParam {String}  bid   bid
+     * @apiParam {String}  sign   签名
+     * @apiSuccess {int}   code 状态码
+     * @apiSuccess {String}  msg 信息
+     * @apiSuccess {Object}  data 信息
+     * @apiSuccess {Object}  data.appId 唤起支付的appId
+     * @apiSuccess {Object}  data.package 唤起支付的package
+     * @apiSuccess {Object}  data.nonceStr 唤起支付的nonceStr
+     * @apiSuccess {Object}  data.timeStamp 唤起支付的timeStamp
+     * @apiSuccess {Object}  data.signType 唤起支付的signType
+     * @apiSuccess {Object}  data.paySign 唤起支付sign
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {
+     *
+     *       }
+     */
+    function wxindex(Request $request)
+    {
+        Log::info($request->all());
+        $product_id = $request->has('product_id') ? $request->get('product_id') : '';
+        $sign = $request->has('sign') ? $request->get('sign') : '';
+        $send_order_id = $request->has('send_order_id') ? $request->get('send_order_id') : 0;
+
+        if (!$this->checkUid()) {
+            return response()->error('XCX_NOT_LOGIN');
+        }
+
+        if (empty($product_id) || empty($sign)) {
+            return response()->error('XCX_PARAM_ERROR');
+        }
+
+        if (!$this->checkSign($request->all('_url'))) {
+            //return response()->error('XCX_PARAM_ERROR');
+        }
+        $bid = $request->has('bid') ? $request->get('bid') : 0;
+        $openid = $this->openid;
+        //$openid = 'o0bsX0b3-kgWIb4JBdTAk7HVtnrk';
+        //根据分校id获取支付配置id
+
+        $trade_no = date("YmdHis") . hexdec(uniqid());
+        $product_info = ProductService::getProductSingle($product_id);
+        $uid = $this->uid;
+        $distribution_channel_id = $this->distribution_channel_id;
+        $price = $product_info->price * 100;
+        if ($uid < 32) {
+            //$price = 1;
+        }
+
+        if (in_array($uid, explode(',', env('TEST_UID')))) {
+            $price = 1;
+        }
+        if ($bid) {
+            try {
+                $bid = Hashids::decode($bid)[0];
+            } catch (\Exception $e) {
+                $bid = 0;
+            }
+
+        }
+        //$price = 1;
+        if ($product_info->type == 'YEAR_ORDER') {
+            $order_type = 'YEAR';
+        } elseif ($product_info->type == 'BOOK_ORDER') {
+            $order_type = 'BOOK';
+        } elseif ($product_info->type == 'TICKET_RECHARGE') {
+            $order_type = 'RECHARGE';
+        } else {
+            $order_type = '';
+        }
+
+        $res = $this->createUnPayOrder([
+            'distribution_channel_id' => $distribution_channel_id,
+            'uid' => $uid,
+            'product_id' => $product_id,
+            'price' => $price / 100,
+            'pay_type' => 1,
+            'trade_no' => $trade_no,
+            'pay_merchant_source' => 'XIAOCHENGXU',
+            'pay_merchant_id' => 0,
+            'create_ip' => $request->getClientIp(),
+            'send_order_id' => $send_order_id,
+            'order_type' => $order_type,
+            'from_bid' => $bid,
+            'from_type' => 'KuaiYingYong',
+            'activity_id'=>0
+        ]);
+        Log::info('order is');
+        Log::info($res);
+        //微信下单
+        $options = [
+            'app_id' => 'wxa0c8331eba3b34d5',
+            'payment' => [
+                'merchant_id' => 1501944981,
+                'key' => 'ee245088b93ba88008279d95f6d30413',
+            ]
+        ];
+        $app = new Application($options);
+        $payment = $app->payment;
+        $attributes = [
+            'trade_type' => 'JSAPI',
+            'body' => 'novel read',
+            'detail' => 'novel read',
+            'out_trade_no' => $trade_no,
+            'total_fee' => $price,
+            'notify_url' => env('XCX_PAY_CALL_BACK_URL'),
+            'openid' => $openid,
+            'spbill_create_ip' => $request->getClientIp(),
+        ];
+
+        $order = new Wxorder($attributes);
+        Log::info('wexin order--------');
+        Log::info($order);
+        $result = $payment->prepare($order);
+        Log::info('wexin order--xcx--result-----');
+        Log::info($result);
+        if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') {
+            Log::info('wechat success in');
+            $data = [
+                'appId' => $result->appid,
+                'package' => 'prepay_id=' . $result->prepay_id,
+                'nonceStr' => $result->nonce_str,
+                'timeStamp' => (string)time(),
+                'signType' => 'MD5',
+            ];
+            $data['paySign'] = $this->MakeSign($data);
+            unset($data['appId']);
+            $data['order'] = $trade_no;
+            $data = [
+                'code' => 0,
+                'msg' => '',
+                'data' => $data
+            ];
+            return response()->json(($data));
+        }
+        return null;
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 订单查询
+     * @api {get} checkOrder 订单查询
+     * @apiGroup pay
+     * @apiName checkOrder
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiParam {String}  order   order
+     * @apiSuccess {int}   code 状态码
+     * @apiSuccess {String}  msg 信息
+     * @apiSuccess {Object}  data 信息
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {
+     *
+     *       }
+     */
+    public function checkOrder(Request $request){
+        $order = $request->input('order','');
+        $i = 0;
+        $uid = $this->uid;
+        while ($i <= 10){
+            $order_info = OrderService::getByTradeNo($order);
+            if(!$order_info){
+                return response()->error('XCX_SYS_ERROR');
+                break;
+            }
+            if (isset($order_info->status) && $order_info->status == 'PAID') {
+                $data['balance'] = 0;
+                $user = UserService::getById($uid);
+                if($user){
+                    $data['balance'] = $user->balance;
+                }
+                return response()->success($data);
+            }
+            sleep(1);
+            $i++;
+        }
+        return response()->error('XCX_SYS_ERROR');
+
+    }
+    protected function MakeSign($value)
+    {
+        $data = $value;
+        //签名步骤一:按字典序排序参数
+        ksort($data);
+        $buff = "";
+        foreach ($data as $k => $v) {
+            if ($k != "sign" && $v != "" && !is_array($v)) {
+                $buff .= $k . "=" . $v . "&";
+            }
+        }
+        $buff = trim($buff, "&");
+        //签名步骤二:在string后加入KEY
+        $string = $buff . "&key=" . 'ee245088b93ba88008279d95f6d30413';
+        //签名步骤三:MD5加密
+        $string = md5($string);
+        //签名步骤四:所有字符转为大写
+        $result = strtoupper($string);
+        return $result;
+    }
+
+    /**
+     * 官方微信回调
+     * @param Request $request
+     * @return
+     */
+    function wxback_xcx(Request $request)
+    {
+        Log::info('-------------en----------------');
+        $options = [
+            'app_id' => 'wxa0c8331eba3b34d5',
+            'payment' => [
+                'merchant_id' => 1501944981,
+                'key' => 'ee245088b93ba88008279d95f6d30413',
+            ]
+        ];
+        $app = new Application($options);
+        $response = $app->payment->handleNotify(function ($notify, $successful) {
+            if (!$successful) return 'fail';
+            $trade_no = $notify->out_trade_no;
+            $order = OrderService::getByTradeNo($trade_no);
+            if (!$order) {
+                return 'fail';
+            }
+
+            if (isset($order->status) && $order->status == 'PAID') {
+                Log::info('has_pay:' . $trade_no);
+                return true;
+            }
+            DB::beginTransaction();
+            try {
+                $transaction_id = $notify->transaction_id;
+                $uid = $order->uid;
+                $distribution_channel_id = $order->distribution_channel_id;
+                $product_id = $order->product_id;
+                $product = ProductService::getProductSingle($product_id);
+                $send_order_id = 0;
+                $price = $product->price;
+
+                //$this->updateOrderTotal($trade_no,$transaction_id);
+                // 更新其他定制Order表
+                if ($product->type == 'YEAR_ORDER') {
+                    Log::info('YEAR_ORDERYEAR_ORDERYEAR_ORDERYEAR_ORDERYEAR_ORDERYEAR_ORDERYEAR_ORDERYEAR_ORDER');
+                    $order_type = 'YEAR';
+                    $this->yearOrder($uid, $distribution_channel_id, $price, $send_order_id);
+                    $order->order_type = $order_type;
+                    $order->status = 'PAID';
+                    $order->pay_end_at = date('Y-m-d H:i:s');
+                    $order->transaction_id = $transaction_id;
+                    $order->save();
+
+                } elseif ($product->type == 'BOOK_ORDER') {
+                    Log::info('BOOK_ORDERBOOK_ORDERBOOK_ORDERBOOK_ORDERBOOK_ORDERBOOK_ORDERBOOK_ORDERBOOK_ORDER');
+                    $order_type = 'BOOK';
+                    $this->bookOrder($product_id, $uid, $send_order_id, $price, $distribution_channel_id);
+                    $order->order_type = $order_type;
+                    $order->status = 'PAID';
+                    $order->pay_end_at = date('Y-m-d H:i:s');
+                    $order->transaction_id = $transaction_id;
+                    $order->save();
+
+                } elseif ($product->type == 'TICKET_RECHARGE') {
+                    Log::info('TICKET_RECHARGETICKET_RECHARGETICKET_RECHARGETICKET_RECHARGETICKET_RECHARGE');
+                    $order_type = 'RECHARGE';
+                    $this->userCharge($product, $uid);
+                    $order->order_type = $order_type;
+                    $order->status = 'PAID';
+                    $order->pay_end_at = date('Y-m-d H:i:s');
+                    $order->transaction_id = $transaction_id;
+                    $order->save();
+
+                } else {
+                    DB::rollback();
+                    return 'Order not exist.';
+                }
+                DB::commit();
+                return true;
+            } catch (\Exception $e) {
+                DB::rollback();
+                return 'fail';
+            }
+        });
+        return $response;
+    }
+
+    /**
+     * 单本充值会掉
+     * @param $product_id
+     * @param $uid
+     * @param $send_order_id
+     * @param $fee
+     */
+    private function bookOrder($product_id, $uid, $send_order_id, $fee, $distribution_channel_id)
+    {
+        $book_conf = BookConfigService::getBookByProduct($product_id);
+        $insert_data['bid'] = isset($book_conf->bid) ? $book_conf->bid : '';
+        $insert_data['book_name'] = isset($book_conf->book_name) ? $book_conf->book_name : '';
+        $insert_data['uid'] = $uid;
+        $insert_data['distribution_channel_id'] = $distribution_channel_id;
+        $insert_data['fee'] = $fee;
+        $insert_data['send_order_id'] = $send_order_id;
+        $insert_data['charge_balance'] = 0;
+        $insert_data['reward_balance'] = 0;
+        Log::info('start_save_book_order');
+        Log::info($insert_data);
+        return BookOrderService::save_book_order($insert_data);
+    }
+
+    /**
+     * 包年
+     * @param $uid
+     * @param $distribution_channel_id
+     * @param $fee
+     * @param $send_order_id
+     * @return mixed
+     */
+    private function yearOrder($uid, $distribution_channel_id, $fee, $send_order_id)
+    {
+        Log::info('start_save_year_order');
+        $insert_data['uid'] = $uid;
+        $insert_data['distribution_channel_id'] = $distribution_channel_id;
+        $insert_data['fee'] = $fee;
+        $insert_data['send_order_id'] = $send_order_id;
+        Log::info($insert_data);
+        return YearOrderService::save_year_order($insert_data);
+    }
+
+    /**
+     * 用户充值
+     * @param $product
+     * @param $uid\
+     */
+    private function userCharge($product, $uid)
+    {
+        $total = $product->price * 100 + $product->given;
+        UserService::addBalance($uid, $total, $product->price * 100, $product->given);
+        Log::info('update_user_balance_end:' . $uid . ' balance_add:' . $total);
+    }
+
+    /**
+     * 添加位置付订单
+     * @param $data
+     * @return mixed
+     */
+    private function createUnPayOrder($data)
+    {
+        $data['status'] = 'UNPAID';
+        $data['transaction_id'] = '';
+        $data['pay_end_at'] = '0000-00-00 00:00:00';
+        return OrderService::save_order($data);
+    }
+
+}

+ 17 - 0
app/Http/Controllers/KuaiYingYong/Order/Transformers/BookOrderTransformer.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Order\Transformers;
+use Hashids;
+class BookOrderTransformer
+{
+    public function transform($res){
+        return [
+            //'bid_no_hash'          =>  $res->uid,
+            'bid'          =>  Hashids::encode($res->bid),
+            'book_name'    =>  $res->book_name,
+            'uid'            =>  $res->uid,
+            'created_at'      => date("Y-m-d H:i:s",strtotime($res->created_at)),
+            'fee'            =>  $res->fee,
+        ];
+    }
+}

+ 19 - 0
app/Http/Controllers/KuaiYingYong/Order/Transformers/ChapterOrderTransformer.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Order\Transformers;
+use Hashids;
+class ChapterOrderTransformer
+{
+    public function transform($res){
+        return [
+            'uid'          		=>  $res->uid,
+            //'bid_no_hash'       =>  $res->bid,
+            'bid'            	=>  Hashids::encode($res->bid),
+            'cid'   		    =>  $res->cid,
+            'book_name'         =>  $res->book_name,
+            'chapter_name'      =>  $res->chapter_name,
+            'fee'               =>  $res->fee,
+            'created_at'        =>  date("Y-m-d H:i:s",strtotime($res->created_at)),
+        ];
+    }
+}

+ 16 - 0
app/Http/Controllers/KuaiYingYong/Order/Transformers/ChargeListTransformer.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Order\Transformers;
+class ChargeListTransformer
+{
+
+    public function transform($res){
+        return [
+            'id'       =>  $res->id,
+            'price'       =>  $res->price,
+            'status'   =>  $res->status,
+            'trade_no'=>$res->trade_no,
+            'created_at'   =>  date("Y-m-d H:i:s",strtotime($res->created_at))
+        ];
+    }
+}

+ 19 - 0
app/Http/Controllers/KuaiYingYong/Order/Transformers/OrderTransformer.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\Order\Transformers;
+
+class OrderTransformer
+{
+    public function transform($order){
+        return [
+            'merchant_order_id'       =>  $order->merchant_order_id,
+            'user_id'       =>  $order->user_id,
+            'user_nickname'       =>  $order->user_nickname,
+            'pay_money'       =>  (int)$order->pay_money/100,
+            'pay_flag'   =>  $order->pay_flag,
+            'pay_time'   =>  $order->pay_time ? date('Y-m-d H:i:s',$order->pay_time) : '',
+            'send_order_id' => isset($order->send_order_id) ? $order->send_order_id : 0,
+            'send_order_name' => isset($order->send_order_name) ? $order->send_order_name : ''
+        ];
+    }
+}

+ 189 - 0
app/Http/Controllers/KuaiYingYong/User/ReadRecordController.php

@@ -0,0 +1,189 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\User;
+
+use Illuminate\Http\Request;
+use App\Http\Controllers\KuaiYingYong\BaseController;
+use App\Modules\Book\Services\BookConfigService;
+use App\Modules\Book\Services\UserShelfBooksService;
+use App\Http\Controllers\KuaiYingYong\User\Transformers\ReadRecordTransformer;
+use App\Modules\User\Services\ReadRecordService;
+use Hashids;
+use Redis;
+use Log;
+class ReadRecordController extends BaseController
+{
+
+    /**
+     * @apiDefine ReadRecord 阅读记录
+     */
+
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 获取阅读记录
+     * @api {get} readrecord 获取阅读记录
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup ReadRecord
+     * @apiName index
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Int}         data.book_name    书名
+     * @apiSuccess {String}      data.chapter_name  章节名
+     * @apiSuccess {Int}         data.bid   bid
+     * @apiSuccess {Int}         data.time   时间
+     * @apiSuccess {Int}         data.cid    章节id
+     * @apiSuccess {Int}         data.chapter_name    章节名
+     * @apiSuccess {Int}         data.cover    封面
+     * @apiSuccess {Int}         data.last_chapter    最后一张
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:[
+     *           {
+     *               book_name: "我来好好爱你",
+     *               bid: 2,
+     *               cid: 10402,
+     *               time: 1511783120,
+     *               chapter_name: "你言重了"
+     *           },
+     *           {
+     *               book_name: "京华烟云",
+     *               bid: 1,
+     *               cid: 4,
+     *               time: 1511783068,
+     *               chapter_name: "背水一战"
+     *           }
+     *           ]
+     */
+    public function index(Request $request){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+
+        $res = ReadRecordService::getReadRecord($this->uid);
+        if($res){
+            $id_arr = [];
+            foreach ($res as $key => $value) {
+                $id_arr[] = $value['bid'];
+            }
+
+            $book = BookConfigService::getBooksByIds($id_arr);
+            foreach ($res as $key => &$value) {
+                foreach ($book as  $val) {
+                    if($value['bid'] == $val->bid){
+                        $value['cover'] = $val->cover;
+                        $value['last_chapter'] = $val->last_chapter;
+                        break;
+                    }
+                }
+            }
+
+            $shelf = UserShelfBooksService::getUserShelfBooksListByUid($this->uid);
+            foreach ($res as &$v){
+                $v['is_on_user_shelf'] = 0;
+                foreach ($shelf as $val){
+                    if($v['bid'] == $val->bid){
+                        $v['is_on_user_shelf'] = 1;
+                        break;
+                    }
+                }
+            }
+        }
+        usort($res,function($a,$b){
+            if($a['time'] >= $b['time']) return -1;
+            return 1;
+
+        });
+        $res = json_encode($res);
+        $res = json_decode($res);
+        return response()->collection(new ReadRecordTransformer(),$res);
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 添加阅读记录
+     * @api {post} readrecord 添加阅读记录
+     * @apiGroup ReadRecord
+     * @apiName addReadRecord
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiParam   {Int}         book_name    书名
+     * @apiParam   {String}      chapter_name  章节名
+     * @apiParam   {Int}         bid     bid
+     * @apiParam   {Int}         cid    章节id
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:{}
+     *
+     */
+    public function addReadRecord(Request $request){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $param = $request->except('_url');
+        if(checkParam($param,['bid','cid','chapter_name'])){
+            return response()->error('LACK_PARAM');
+        }
+        //Redis::hset('book_read:' . $uid, $bid, "{$cid}_{$book_name}_{$chapter_name}_" . time());
+
+        $param['uid'] = $this->uid;
+        $param['bid'] = Hashids::decode($param['bid'])[0];
+        $record_info = Redis::hget('book_read:'.$this->uid,$param['bid']);
+        $param['book_name'] = 'unknown';
+        if($record_info){
+            $param['book_name'] = explode('_',$record_info)[1];
+        }
+
+        ReadRecordService::addReadRecord($param);
+        return response()->success();
+
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 删除阅读记录
+     * @api {get} readrecord/delete 删除阅读记录
+     * @apiGroup ReadRecord
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiName delReadRecord
+     * @apiParam   {Int}         bid     bid
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data:{}
+     *
+     */
+    public function delReadRecord(Request $request){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $param = $request->except('_url');
+        if(checkParam($param,['bid'])){
+            return response()->error('LACK_PARAM');
+        }
+        $param['bid'] = Hashids::decode($param['bid'])[0];
+        ReadRecordService::delReadRecord($this->uid,$param['bid']);
+        return response()->success();
+    }
+
+}

+ 20 - 0
app/Http/Controllers/KuaiYingYong/User/Transformers/ReadRecordTransformer.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\User\Transformers;
+use Hashids;
+class ReadRecordTransformer
+{
+    public function transform($res)
+    {
+        return [
+            'bid' => Hashids::encode($res->bid),
+            'cid' => $res->cid,
+            'book_name' => $res->book_name,
+            'chapter_name' => $res->chapter_name,
+            'time' => $res->time,
+            'cover' => $res->cover,
+            'last_chapter' => $res->last_chapter,
+            'is_on_user_shelf'=>$res->is_on_user_shelf
+        ];
+    }
+}

+ 24 - 0
app/Http/Controllers/KuaiYingYong/User/Transformers/UserShelfBooksTransformer.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\User\Transformers;
+
+use Hashids;
+
+class UserShelfBooksTransformer
+{
+    public function transform($userShelfBook)
+    {
+        return [
+            'id' => $userShelfBook->id,
+            'uid' => $userShelfBook->uid,
+            'distribution_channel_id' => $userShelfBook->distribution_channel_id,
+            //'bid_no_hash' => $userShelfBook->bid,
+            'bid' => Hashids::encode($userShelfBook->bid),
+            'book_name' => $userShelfBook->book_name,
+            'cover' => $userShelfBook->cover,
+            'updated_at' => strtotime($userShelfBook->updated_at),
+            'first_cid' => $userShelfBook->first_cid,
+            'last_cid' => $userShelfBook->last_cid,
+        ];
+    }
+}

+ 96 - 0
app/Http/Controllers/KuaiYingYong/User/UserController.php

@@ -0,0 +1,96 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\User;
+
+
+use App\Http\Controllers\KuaiYingYong\BaseController;
+use App\Modules\Subscribe\Services\YearOrderService;
+use App\Modules\User\Transformers\YearOrderTransformer;
+use App\Modules\User\Services\UserService;
+use Log;
+use Redis;
+use Cookie;
+class UserController extends BaseController
+{
+    /**
+     * @apiDefine User 用户
+     */
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 获取用户信息
+     * @api {GET} userinfo 获取用户信息
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup User
+     * @apiName index
+     * @apiSuccess {Number}  id 用户ID.
+     * @apiSuccess {String}  openid 微信openid.
+     * @apiSuccess {String}  unionid 微信unionid.
+     * @apiSuccess {Number}  distribution_channel_id 分销渠道ID.
+     * @apiSuccess {String}  province 省份.
+     * @apiSuccess {String}  city 城市.
+     * @apiSuccess {String}  country 国家.
+     * @apiSuccess {String}  headimgurl 头像地址.
+     * @apiSuccess {Number}  send_order_id 派单ID.
+     * @apiSuccess {Number=0,1}  sex 性别.
+     * @apiSuccess {String}  balance 书币余额.
+     * @apiSuccess {Int}     is_vip 是否vip
+     * @apiSuccess {String}  vip_days 364天.
+     * @apiSuccessExample {json} Success-Response:
+     *
+     *     {
+     *         "code": 0,
+     *         "msg": "",
+     *         "data": {
+     *             "id": 56,
+     *             "openid": "sdfs34ssdfdsf",
+     *             "unionid": "SDFSD3343S",
+     *             "distribution_channel_id": 1212,
+     *             "province": "浙江省",
+     *             "city": "杭州",
+     *             "country": "中国",
+     *             "headimgurl": "http://.."
+     *             "send_order_id": 323
+     *             "balance": 8956
+     *             "register_time": "2017-12-12 12:12:12"
+     *         }
+     *     }
+     */
+    public function index(){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+
+        $data = UserService::getById($this->uid);
+        if(!$data->head_img){
+            $data->head_img = 'https://yueduyun.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/img/defaulthead.png';
+        }
+        $data['is_vip'] = 0;
+        $data['vip_days'] = 0;
+        $year_record = YearOrderService::getRecord($this->uid);
+        if($year_record){
+            $data['is_vip'] = 1;
+            
+            $time = strtotime($year_record['end_time'])-time();
+            if($time>=86400){
+                  $data['vip_days'] = floor($time/86400).'天';  
+            }elseif ($time>3600) {
+                 $data['vip_days'] = floor($time/3600).'小时';  
+            }elseif ($time>60) {
+                 $data['vip_days'] = floor($time/60).'分钟';  
+            }else{
+                $data['vip_days'] = $time.'秒';  
+            }
+        }
+        return response()->success($data);
+    }
+
+    function logout()
+    {
+        setcookie(env('COOKIE_AUTH_WEB_WECHAT'), '', -1);
+        setcookie('u', '', -1);
+        return response('logout');
+    }
+}

+ 225 - 0
app/Http/Controllers/KuaiYingYong/User/UserShelfBooksController.php

@@ -0,0 +1,225 @@
+<?php
+
+namespace App\Http\Controllers\KuaiYingYong\User;
+
+use Illuminate\Http\Request;
+use App\Http\Controllers\KuaiYingYong\BaseController;
+use Redis;
+use App\Modules\Book\Services\UserShelfBooksService;
+use App\Http\Controllers\KuaiYingYong\User\Transformers\UserShelfBooksTransformer;
+use App\Modules\User\Services\ReadRecordService;
+use Hashids;
+use Log;
+class UserShelfBooksController extends BaseController
+{
+
+    /**
+     * @apiDefine UserShelfBooks 书架
+     */
+
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 获取书架
+     * @api {get} userShelfBooks 获取书架
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup UserShelfBooks
+     * @apiName getChapter
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Int}         data.id   编号
+     * @apiSuccess {String}      data.distribution_channel_id   分销
+     * @apiSuccess {Int}         data.uid   uid
+     * @apiSuccess {Int}         data.bid   bid
+     * @apiSuccess {Int}         data.book_name   书名
+     * @apiSuccess {Int}         data.cover   封面
+     * @apiSuccess {Int}         data.last_cid   章节id
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {
+     *          [
+     *               {
+     *                   id: 6,
+     *                   uid: 4,
+     *                   distribution_channel_id: 1,
+     *                   bid: 1,
+     *                   book_name: "京华烟云",
+     *                   cover: "https://leyue-bucket.oss-cn-hangzhou.aliyuncs.com/ycsd_cover/covermiddle/0/1.jpg",
+     *                   updated_at: 1511783068,
+     *                   last_cid: 4
+     *               },
+     *               {
+     *                   id: 7,
+     *                   uid: 4,
+     *                   distribution_channel_id: 1,
+     *                   bid: 1,
+     *                   book_name: "我来好好爱你",
+     *                   cover: "https://leyue-bucket.oss-cn-hangzhou.aliyuncs.com/ycsd_cover/covermiddle/0/11.jpg",
+     *                   updated_at: 1511783068,
+     *                   last_cid: 4
+     *               }
+     *           ]
+     *       }
+     */
+    public function index(Request $request){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+
+        $res = UserShelfBooksService::getUserShelfBooksListByUid($this->uid);
+
+        if($res->isEmpty()){
+            return response()->success();
+        }
+
+        $record = ReadRecordService::getReadRecord($this->uid);
+
+        //if(empty($record))   return response()->success($res);
+
+        foreach ($res as &$v){
+            $v['last_cid'] = $v['first_cid'];
+            foreach ($record as $val){
+                if($v['bid'] == $val['bid']){
+                    $v['updated_at'] = $val['time'];
+                    $v['last_cid'] = $val['cid'];
+                    break;
+                }
+            }
+        }
+
+        /*
+        usort($res,function($a,$b){
+            if($a['updated_at'] >= $b['updated_at']) return -1;
+            return 1;
+
+        });*/
+        return response()->collection(new UserShelfBooksTransformer(),$res);
+    }
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 添加书架
+     * @api {post} userShelfBooks 添加书架
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup UserShelfBooks
+     * @apiName addShelf
+     * @apiParam   {int}         bid bid
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {}
+     */
+    public function addShelf(Request $request){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $param = $request->except('_url');
+        if(checkParam($param,['bid'])){
+            return response()->error('LACK_PARAM');
+        }
+
+        $param['uid'] = $this->uid;
+        $param['bid'] = Hashids::decode($param['bid'])[0];
+        $param['distribution_channel_id'] = $this->distribution_channel_id;
+        $res = null;
+        try{
+            $res = UserShelfBooksService::create($param);
+        }catch (\Exception $e){
+            return response()->error('XCX_PARAM_ERROR');
+        }
+
+        if($res){
+            return response()->success($res);
+        }
+        return response()->error('XCX_SYS_ERROR');
+    }
+
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 删除书架
+     * @api {get} userShelfBooks/delete 删除书架
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup UserShelfBooks
+     * @apiName delShelf
+     * @apiParam   {int}         bid bid
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {}
+     */
+    public function delShelf(Request $request){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $bid = $request->input('bid');
+        if(empty($bid)) return response()->error('LACK_PARAM');
+        $param['uid'] = $this->uid;
+        $param['bid'] = Hashids::decode($bid)[0];
+        $res = UserShelfBooksService::del($this->uid,$param['bid']);
+        if($res){
+            return response()->success();
+        }
+        return response()->error('XCX_SYS_ERROR');
+    }
+    
+
+    /**
+     * @apiVersion 1.0.0
+     * @apiDescription 是否在书架上
+     * @api {get} userShelfBooks/isonshelf 是否在书架上
+     * @apiParam {String}  [token]  token
+     * @apiHeader {String} [Authorization]  token 两个token任选其一
+     * @apiGroup UserShelfBooks
+     * @apiName isOnshelf
+     * @apiParam   {int}         bid bid
+     * @apiSuccess {int}         code 状态码
+     * @apiSuccess {String}      msg  信息
+     * @apiSuccess {object}      data 结果集
+     * @apiSuccess {Int}         data.is_on 是否在书架上(0|1)
+     * @apiSuccessExample {json} Success-Response:
+     *     HTTP/1.1 200 OK
+     *     {
+     *       code: 0,
+     *       msg: "",
+     *       data: {
+     *               is_on:0
+     *           }
+     */
+    public function  isOnshelf(Request $request){
+        if(!$this->checkUid()){
+            return response()->error('XCX_NOT_LOGIN');
+        }
+        $bid = $request->input('bid');
+        if(!$bid) return response()->error('LACK_PARAM');
+        $bid = Hashids::decode($bid)[0];
+        //$param['uid'] = $this->uid;
+        //$res = $this->apiClient->get($this->joinUrl('Read/isonshelf'),$param);
+        $res = UserShelfBooksService::getUserShelfBooksListByUidAndBid($this->uid,$bid);
+        if($res){
+            $data['is_on'] = 1;
+        }else{
+            $data['is_on'] = 0;
+        }
+        return response()->success($data);
+    }
+
+}

+ 15 - 0
app/Http/Controllers/KuaiYingYong/apidoc.json

@@ -0,0 +1,15 @@
+{
+"name": "追书云快应用平台接口",
+"version": "1.0.0",
+"description": "追书云快应用平台接口,除了登录的所有接口都需要传token或者在header头里面加上Authorization,如(Authorization:Bearer eyJ0eXAiOiJKV1QiLCJ****),所有返回的接口都在返回头中都有Authorization,BearerZz之后的内容就是token,即下一次请求时的token",
+"title": "追书云快应用平台接口",
+"url": "http://kyy.zhuishuyun.com/api/",
+"template": {
+"withCompare": true,
+"withGenerator": true
+},
+"header": {
+    "title": "概述",
+    "filename": "header.md"
+  }
+}

+ 4 - 0
app/Http/Controllers/KuaiYingYong/header.md

@@ -0,0 +1,4 @@
+状态码:<br>
+
+	0:     正常
+    

+ 80 - 0
app/Http/Routes/KuaiYingYong/KuaiYingYongRoutes.php

@@ -0,0 +1,80 @@
+<?php
+
+Route::group(['domain'=>env('KUANYINGYONG_DOMAIN'),'namespace'=>'App\Http\Controllers\KuaiYingYong'],function(){
+    //支付
+    Route::any('pay/wcback_xchengxu','Order\OrdersController@wcback_official');
+    Route::any('help','Web\RedirectController@help');
+    Route::post('api/login','Oauth\UsersController@index');
+    Route::get('api/RefreshToken','Oauth\UsersController@RefreshToken');
+
+    //支付回调
+    Route::any('pay/wcback','Order\OrdersController@wxback_xcx');
+    Route::group(['prefix'=>'api'],function (){
+        //首页
+        Route::get('books/{sex}/index','Book\BookController@getBookLists');
+        //书库
+        Route::get('books/library','Book\BookController@library');
+        //相似推荐
+        Route::get('books/similar','Book\BookController@similarRecom');
+        //阅读完后的推荐
+        Route::get('books/readOverRecommend','Book\BookController@readOverRecommend');
+        //排行榜
+        Route::get('books/rank','Book\BookController@rank');
+        //分类列表
+        Route::get('books/getCategory','Book\BookCategoryController@getCategory');
+    });
+    //web 接口  jwttoken
+    Route::group(['prefix'=>'api','middleware'=>'jwttoken'],function () {
+
+        //图书详情
+        Route::get('book/{bid}','Book\BookController@index');
+
+        //目录不分页
+        Route::get('books/{bid}/allcatalog','Book\ChapterController@getCatalog');
+
+        //Route::get('books/{bid}/allcatalog/{aa}',function ($tt,$bid,$aa){return $bid.'---'.$aa;});
+        //目录分页
+        Route::get('books/{bid}/catalog','Book\ChapterController@getCatalogPerPage');
+        //章节详情
+        Route::get('books/{bid}/chapters/{cid}','Book\ChapterController@index')->where('cid','\d+');
+        //余额订购
+        Route::get('books/{bid}/balance/chapterOrders/{cid}','Book\ChapterController@pay');
+
+        //Route::get('books/search','Book\BookController@bookSearch');
+
+        //充值列表
+        Route::get('order/chargeList','Order\OrdersController@chargeList');
+        //章节订购列表
+        Route::get('order/chapterOrderList','Order\OrdersController@chapterOrderList');
+        //单本订购列表
+        Route::get('order/bookOrderList','Order\OrdersController@bookOrderList');
+        //充值记录
+        Route::get('order/chargeRecordLists','Order\OrdersController@chargeRecordLists');
+
+        Route::get('order/issuccess','Order\OrdersController@isSuccess');
+        Route::get('userinfo','User\UserController@index');
+
+
+        //书架
+        Route::get('userShelfBooks','User\UserShelfBooksController@index');
+        //添加书架
+        Route::post('userShelfBooks','User\UserShelfBooksController@addShelf');
+        //删除书架
+        Route::get('userShelfBooks/delete','User\UserShelfBooksController@delShelf');
+
+        Route::get('userShelfBooks/isonshelf','User\UserShelfBooksController@isOnshelf');
+
+        //阅读记录
+        Route::get('readrecord','User\ReadRecordController@index');
+        //添加阅读记录
+        Route::post('readrecord','User\ReadRecordController@addReadRecord');
+        //删除阅读记录
+        Route::get('readrecord/delete','User\ReadRecordController@delReadRecord');
+
+        //支付
+        Route::get('goToPay','Order\OrdersController@wxindex');
+
+        Route::get('checkOrder','Order\OrdersController@checkOrder');
+    });
+
+});

+ 13 - 0
app/Providers/RouteServiceProvider.php

@@ -39,6 +39,7 @@ class RouteServiceProvider extends ServiceProvider
         $this->mapWapRoutes($router);
         $this->mapWebRoutes($router);
         $this->mapXchengyuRoutes($router);
+        $this->mapKuaiYingYongRoutes($router);
     }
 
 
@@ -95,5 +96,17 @@ class RouteServiceProvider extends ServiceProvider
         });
     }
 
+    /**
+     * 快应用
+     */
+    protected function mapKuaiYingYongRoutes(Router $router)
+    {
+        $router->group([
+            'middleware' => 'web',
+        ], function ($router) {
+            require app_path('Http/Routes/KuaiYingYong/KuaiYingYongRoutes.php');
+        });
+    }
+
 
 }