liaofei 6 лет назад
Родитель
Сommit
16a199312b
43 измененных файлов с 4645 добавлено и 0 удалено
  1. 103 0
      application/core/behavior/ApiAuthBehavior.php
  2. 23 0
      application/core/behavior/ApiPermissionBehavior.php
  3. 19 0
      application/core/behavior/BuildResponseBehavior.php
  4. 211 0
      application/core/behavior/GoodsBehavior.php
  5. 220 0
      application/core/behavior/OrderBehavior.php
  6. 135 0
      application/core/behavior/PaymentBehavior.php
  7. 61 0
      application/core/behavior/RequestFilterBehavior.php
  8. 78 0
      application/core/behavior/UserBehavior.php
  9. 20 0
      application/core/implement/BehaviorIntterface.php
  10. 22 0
      application/core/implement/ProviderInterface.php
  11. 21 0
      application/core/implement/TemplateInterface.php
  12. 23 0
      application/core/lib/BaseException.php
  13. 32 0
      application/core/logic/Login.php
  14. 30 0
      application/core/logic/Pay.php
  15. 34 0
      application/core/logic/Qrcode.php
  16. 13 0
      application/core/logic/Template.php
  17. 22 0
      application/core/logic/routine/RoutineLogin.php
  18. 6 0
      application/core/logic/routine/oder.php
  19. 37 0
      application/core/model/ApiMenus.php
  20. 88 0
      application/core/model/routine/RoutineCode.php
  21. 60 0
      application/core/model/routine/RoutineFormId.php
  22. 92 0
      application/core/model/routine/RoutineQrcode.php
  23. 133 0
      application/core/model/routine/RoutineTemplate.php
  24. 38 0
      application/core/model/routine/Token.php
  25. 150 0
      application/core/model/system/SystemUserLevel.php
  26. 412 0
      application/core/model/system/SystemUserTask.php
  27. 19 0
      application/core/model/user/User.php
  28. 247 0
      application/core/model/user/UserBill.php
  29. 177 0
      application/core/model/user/UserLevel.php
  30. 143 0
      application/core/model/user/UserSign.php
  31. 1 0
      application/core/model/user/UserTaskFinish.php
  32. 131 0
      application/core/traits/LogicTrait.php
  33. 110 0
      application/core/util/ApiLogs.php
  34. 67 0
      application/core/util/GroupDataService.php
  35. 314 0
      application/core/util/MiniProgramService.php
  36. 202 0
      application/core/util/ProgramTemplateService.php
  37. 36 0
      application/core/util/QrcodeService.php
  38. 41 0
      application/core/util/ReturnCode.php
  39. 64 0
      application/core/util/SystemConfigService.php
  40. 25 0
      application/core/util/Template.php
  41. 237 0
      application/core/util/TokenService.php
  42. 559 0
      application/core/util/WechatService.php
  43. 189 0
      application/core/util/WechatTemplateService.php

+ 103 - 0
application/core/behavior/ApiAuthBehavior.php

@@ -0,0 +1,103 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/12 11:20
+ */
+
+namespace app\core\behavior;
+
+use app\core\model\ApiMenus;
+use app\core\model\user\User;
+use app\core\util\ApiLogs;
+use app\core\util\ReturnCode;
+use app\core\util\TokenService;
+use service\JsonService;
+use service\UtilService;
+use think\Cache;
+use think\Config;
+use think\Request;
+use app\core\implement\BehaviorIntterface;
+
+class ApiAuthBehavior implements BehaviorIntterface
+{
+    //Request实例化对象
+     protected $request=null;
+
+    public function run(){
+        $this->request=Request::instance();
+        //开启路由
+        $hash = $this->request->routeInfo();
+        if(Config::get('url_route_on') && isset($hash['rule'][1])){
+            $hash=$hash['rule'][1];
+        }else{
+           //未开启路由或者开启路由并没有使用路由
+            $hash=UtilService::getCurrentController($this->request);
+        }
+        //检测访问接口是否存在,并读取接口详细信息
+        if(Cache::has(ApiLogs::AB_API_INFO . $hash)){
+            $apiInfo=Cache::get(ApiLogs::AB_API_INFO.$hash);
+        }else {
+            $apiInfo = ApiMenus::getHash(['hash' => $hash]);
+            if (!$apiInfo) return JsonService::returnData(ReturnCode::DB_READ_ERROR, '获取接口配置数据失败!');
+            Cache::set(ApiLogs::AB_API_INFO.$hash,$apiInfo,ApiLogs::EXPIRE);
+        }
+        //是否验证accessToken 是测试则不验证
+        if ($apiInfo['access_token'] && !$apiInfo['is_test']) if($accessRes = $this->checkAccessToken()) return $accessRes;
+        //是否为测试模式
+        if (!$apiInfo['is_test']) if($versionRes = $this->checkVersion()) return $versionRes;
+        //验证用户token信息
+        $loginRes = $this->checkLogin($apiInfo['need_login']);
+        if ($loginRes) return $loginRes;
+    }
+
+    /*
+     * 验证access_token不存在则返回错误信息
+     * @return array || boolean
+     * */
+    public function checkAccessToken()
+    {
+        if($this->request===null) $this->request=Request::instance();
+        $access_token = $this->request->header(ApiLogs::ACCESS_TOKEN,'');
+        if($access_token==='') return JsonService::returnData(ReturnCode::ACCESS_TOKEN_TIMEOUT, '缺少参数access-token!');
+        if(!Cache::has(ApiLogs::ACCESS_TOKEN_PREFIX.$access_token)) return JsonService::returnData(ReturnCode::ACCESS_TOKEN_TIMEOUT,'access-token已失效!');
+        //执行更多验证信息
+
+        return false;
+    }
+
+    /*
+     * 验证Api参数版本检测
+     * @return array || boolean
+     * */
+    public function checkVersion()
+    {
+        if($this->request===null) $this->request=Request::instance();
+        $version = $this->request->header(ApiLogs::API_VERSION,'');
+        if($version==='') return JsonService::returnData(ReturnCode::EMPTY_PARAMS,'缺少API版本号!');
+        if($version != Config::get('ebApi.API_VERSION')) return JsonService::returnData(ReturnCode::VERSION_INVALID,'API版本号与系统版本号不匹配');
+        return false;
+    }
+
+    /*
+     * 验证用户token信息
+     *  @param number $needLogin 是否验证用户token
+     * */
+    public function checkLogin($needLogin)
+    {
+        if($this->request===null) $this->request=Request::instance();
+        $userToken = $this->request->header(ApiLogs::USER_TOKEN, '');
+        if(!$userToken && !$needLogin) return JsonService::returnData(ReturnCode::ERROR,'请传入token验证您的身份信息');
+        //验证token
+        $Tokencheck=TokenService::checkToken($userToken,$needLogin);
+        if($Tokencheck===true){
+            return ['uid'=>0];
+        }else if(is_array($Tokencheck)){
+            list($uid)=$Tokencheck;
+            $userInfo = User::get($uid);
+        }else return JsonService::returnData(ReturnCode::USER_TOKEN_ERROR,'没有获取到用户信息,请传入token验证您的身份信息');
+        if((!$userInfo || !isset($userInfo)) && !$needLogin) return JsonService::returnData(ReturnCode::ERROR,'用户信息获取失败,没有这样的用户!');
+        if(isset($userInfo->status) && !$userInfo->status) return JsonService::returnData(ReturnCode::USER_STATUS_ERROR,'您已被禁止登录');
+    }
+
+}

+ 23 - 0
application/core/behavior/ApiPermissionBehavior.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/12 11:21
+ */
+
+namespace app\core\behavior;
+
+use app\core\implement\BehaviorIntterface;
+
+/*
+ * Api权限处理
+ * class ApiPermissionBehavior
+ * */
+class ApiPermissionBehavior implements BehaviorIntterface
+{
+    public function run()
+    {
+
+    }
+
+}

+ 19 - 0
application/core/behavior/BuildResponseBehavior.php

@@ -0,0 +1,19 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/12 11:22
+ */
+
+namespace app\core\behavior;
+
+use app\core\implement\BehaviorIntterface;
+
+class BuildResponseBehavior implements BehaviorIntterface
+{
+    public function run()
+    {
+
+    }
+
+}

+ 211 - 0
application/core/behavior/GoodsBehavior.php

@@ -0,0 +1,211 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 5:41 PM
+ */
+
+namespace app\core\behavior;
+
+use app\ebapi\model\store\StoreOrder;
+use app\ebapi\model\user\User;
+use app\ebapi\model\user\WechatUser;
+use app\ebapi\model\user\UserAddress;
+use app\admin\model\order\StoreOrder as StoreOrderAdminModel;
+use app\core\util\SystemConfigService;
+use app\core\util\WechatTemplateService;
+
+class GoodsBehavior
+{
+    /**
+     * 取消点赞产品后
+     * @param $productId
+     * @param $uid
+     */
+    public static function storeProductUnLikeAfter($productId, $uid)
+    {
+
+    }
+
+    /**
+     * 点赞产品后
+     * @param $product
+     * @param $uid
+     */
+    public static function storeProductLikeAfter($product, $uid)
+    {
+
+    }
+    /**
+     * 用户确认收货
+     * @param $order
+     * @param $uid
+     */
+    public static function storeProductOrderUserTakeDelivery($order, $uid)
+    {
+        $res1 = StoreOrder::gainUserIntegral($order);
+        $res2 = User::backOrderBrokerage($order);
+        StoreOrder::orderTakeAfter($order);
+        $giveCouponMinPrice = SystemConfigService::get('store_give_con_min_price');
+        if($order['total_price'] >= $giveCouponMinPrice) WechatUser::userTakeOrderGiveCoupon($uid);
+        $res = $res1 && $res2;
+        if(!$res) exception('收货失败!');
+    }
+    /**
+     * 订单创建成功后
+     * @param $oid
+     */
+    public static function storeProductOrderCreate($order,$group)
+    {
+        UserAddress::be(['is_default'=>1,'uid'=>$order['uid']]) || UserAddress::setDefaultAddress($group['addressId'],$order['uid']);
+    }
+
+    /**
+     * 修改发货状态  为送货
+     * @param $data
+     *  $data array  送货方式 送货人姓名  送货人电话
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+//    public static function storeProductOrderDeliveryAfter($data,$oid){
+//        StoreOrder::orderPostageAfter($data,$oid);
+//    }
+
+    /**
+     * 修改发货状态  为发货
+     * @param $data
+     *  $data array  发货方式 送货人姓名  送货人电话
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+//    public static function storeProductOrderDeliveryGoodsAfter($data,$oid){
+//        StoreOrder::orderPostageAfter($data,$oid);
+//        RoutineTemplate::sendOrderGoods($oid,$data);
+//    }
+
+    /**
+     * 修改状态 为已收货
+     * @param $data
+     *  $data array status  状态为  已收货
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderTakeDeliveryAfter($order,$oid)
+    {
+        $res1 = StoreOrder::gainUserIntegral($order);
+        $res2 = User::backOrderBrokerage($order);
+        StoreOrder::orderTakeAfter($order);
+        if(!($res1 && $res2)) exception('收货失败!');
+    }
+
+    /**
+     * 线下付款
+     * @param $id
+     * $id 订单id
+     */
+    public static function storeProductOrderOffline($id){
+
+    }
+
+    /**
+     * 修改状态为  已退款
+     * @param $data
+     *  $data array type 1 直接退款  2 退款后返回原状态  refund_price  退款金额
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderRefundYAfter($data,$oid){
+        StoreOrderAdminModel::refundTemplate($data,$oid);
+    }
+
+    /**
+     * 修改状态为  不退款
+     * @param $data
+     *  $data string  退款原因
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderRefundNAfter($data,$oid){
+
+    }
+
+
+    /**
+     * 修改订单状态
+     * @param $data
+     *  data  total_price 商品总价   pay_price 实际支付
+     * @param $oid
+     * oid 订单id
+     */
+    public static function storeProductOrderEditAfter($data,$oid){
+
+    }
+    /**
+     * 修改送货信息
+     * @param $data
+     *  $data array  送货人姓名/快递公司   送货人电话/快递单号
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderDistributionAfter($data,$oid){
+
+    }
+
+    /**
+     * 用户申请退款
+     * @param $oid
+     * @param $uid
+     */
+    public static function storeProductOrderApplyRefundAfter($oid, $uid)
+    {
+        $order = StoreOrder::where('id',$oid)->find();
+        WechatTemplateService::sendAdminNoticeTemplate([
+            'first'=>"亲,您有一个订单申请退款 \n订单号:{$order['order_id']}",
+            'keyword1'=>'申请退款',
+            'keyword2'=>'待处理',
+            'keyword3'=>date('Y/m/d H:i',time()),
+            'remark'=>'请及时处理'
+        ]);
+    }
+
+
+    /**
+     * 评价产品
+     * @param $replyInfo
+     * @param $cartInfo
+     */
+    public static function storeProductOrderReply($replyInfo, $cartInfo)
+    {
+        StoreOrder::checkOrderOver($cartInfo['oid']);
+    }
+
+    /**
+     * 订单全部产品评价完
+     * @param $oid
+     */
+    public static function storeProductOrderOver($oid)
+    {
+
+    }
+
+    /**
+     * 退积分
+     * @param $product
+     * $product 商品信息
+     * @param $back_integral
+     * $back_integral 退多少积分
+     */
+    public static function storeOrderIntegralBack($product,$back_integral){
+
+    }
+
+    /**
+     * 加入购物车成功之后
+     * @param array $cartInfo 购物车信息
+     * @param array $userInfo 用户信息
+     */
+    public static function storeProductSetCartAfterAfter($cartInfo, $userInfo)
+    {
+
+    }
+}

+ 220 - 0
application/core/behavior/OrderBehavior.php

@@ -0,0 +1,220 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 5:41 PM
+ */
+
+namespace app\core\behavior;
+
+use app\ebapi\model\store\StoreOrder;
+use app\ebapi\model\user\User;
+use app\ebapi\model\user\WechatUser;
+use app\ebapi\model\user\UserAddress;
+use app\admin\model\order\StoreOrder as StoreOrderAdminModel;
+use app\core\util\SystemConfigService;
+use app\core\logic\Template;
+
+class OrderBehavior
+{
+    /**
+     * 用户确认收货
+     * @param $order
+     * @param $uid
+     */
+    public static function storeProductOrderUserTakeDelivery($order, $uid)
+    {
+        $res1 = StoreOrder::gainUserIntegral($order);
+        $res2 = User::backOrderBrokerage($order);
+        StoreOrder::orderTakeAfter($order);
+        $giveCouponMinPrice = SystemConfigService::get('store_give_con_min_price');
+        if($order['total_price'] >= $giveCouponMinPrice) WechatUser::userTakeOrderGiveCoupon($uid);
+        if(!($res1 && $res2)) exception('收货失败!');
+    }
+    /**
+     * 订单创建成功后
+     * @param $oid
+     */
+    public static function storeProductOrderCreate($order,$group)
+    {
+        UserAddress::be(['is_default'=>1,'uid'=>$order['uid']]) || UserAddress::setDefaultAddress($group['addressId'],$order['uid']);
+    }
+
+    /**
+     * 修改发货状态  为送货
+     * @param $data
+     *  $data array  送货方式 送货人姓名  送货人电话
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+//    public static function storeProductOrderDeliveryAfter($data,$oid){
+//        StoreOrder::orderPostageAfter($data,$oid);
+//    }
+
+    /**
+     * 修改发货状态  为发货
+     * @param $data
+     *  $data array  发货方式 送货人姓名  送货人电话
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+//    public static function storeProductOrderDeliveryGoodsAfter($data,$oid){
+//        StoreOrder::orderPostageAfter($data,$oid);
+//        RoutineTemplate::sendOrderGoods($oid,$data);
+//    }
+
+    /**
+     * 修改状态 为已收货
+     * @param $data
+     *  $data array status  状态为  已收货
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderTakeDeliveryAfter($order,$oid)
+    {
+        $res1 = StoreOrder::gainUserIntegral($order);
+        $res2 = User::backOrderBrokerage($order);
+        StoreOrder::orderTakeAfter($order);
+        if(!($res1 && $res2)) exception('收货失败!');
+    }
+
+    /**
+     * 线下付款
+     * @param $id
+     * $id 订单id
+     */
+    public static function storeProductOrderOffline($id){
+
+    }
+
+    /**
+     * 修改状态为  已退款
+     * @param $data
+     *  $data array type 1 直接退款  2 退款后返回原状态  refund_price  退款金额
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderRefundYAfter($data,$oid){
+        StoreOrderAdminModel::refundTemplate($data,$oid);
+    }
+
+    /**
+     * 修改状态为  不退款
+     * @param $data
+     *  $data string  退款原因
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderRefundNAfter($data,$oid){
+
+    }
+
+
+    /**
+     * 修改订单状态
+     * @param $data
+     *  data  total_price 商品总价   pay_price 实际支付
+     * @param $oid
+     * oid 订单id
+     */
+    public static function storeProductOrderEditAfter($data,$oid){
+
+    }
+    /**
+     * 修改送货信息
+     * @param $data
+     *  $data array  送货人姓名/快递公司   送货人电话/快递单号
+     * @param $oid
+     * $oid  string store_order表中的id
+     */
+    public static function storeProductOrderDistributionAfter($data,$oid){
+
+    }
+
+    /**
+     * 用户申请退款
+     * @param $oid
+     * @param $uid
+     */
+    public static function storeProductOrderApplyRefundAfter($oid, $uid)
+    {
+        //待完善
+        $order = StoreOrder::where('id',$oid)->find();
+//        Template::sendAdminNoticeTemplate([
+//            'first'=>"亲,您有一个订单申请退款 \n订单号:{$order['order_id']}",
+//            'keyword1'=>'申请退款',
+//            'keyword2'=>'待处理',
+//            'keyword3'=>date('Y/m/d H:i',time()),
+//            'remark'=>'请及时处理'
+//        ]);
+    }
+
+
+    /**
+     * 评价产品
+     * @param $replyInfo
+     * @param $cartInfo
+     */
+    public static function storeProductOrderReply($replyInfo, $cartInfo)
+    {
+        StoreOrder::checkOrderOver($cartInfo['oid']);
+    }
+
+    /**
+     * 订单全部产品评价完
+     * @param $oid
+     */
+    public static function storeProductOrderOver($oid)
+    {
+
+    }
+
+    /**
+     * 退积分
+     * @param array $order
+     *
+     */
+    public static function storeOrderRegressionIntegralAfter($order)
+    {
+        return StoreOrder::RegressionIntegral($order);
+    }
+
+    /**
+     * 退销量
+     * @param array $order
+     *
+     */
+    public static function storeOrderRegressionStockAfter($order)
+    {
+        return StoreOrder::RegressionStock($order);
+    }
+
+    /**
+     * 退优惠券
+     * @param array $order
+     *
+     */
+    public static function storeOrderRegressionCouponAfter($order)
+    {
+        return StoreOrder::RegressionCoupon($order);
+    }
+
+    /*
+     * 回退所有
+     * @param array $order
+     * */
+    public  static function storeOrderRegressionAllAfter($order)
+    {
+        return StoreOrder::RegressionStock($order) && StoreOrder::RegressionIntegral($order) && StoreOrder::RegressionCoupon($order);
+    }
+
+    /**
+     * 加入购物车成功之后
+     * @param array $cartInfo 购物车信息
+     * @param array $userInfo 用户信息
+     */
+    public static function storeProductSetCartAfterAfter($cartInfo, $userInfo)
+    {
+
+    }
+}

+ 135 - 0
application/core/behavior/PaymentBehavior.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ *
+ * @author: xaboy<365615158@qq.com>
+ * @day: 2017/12/26
+ */
+
+namespace app\core\behavior;
+
+use app\ebapi\model\store\StoreOrder as StoreOrderRoutineModel;
+use app\ebapi\model\store\StoreOrder as StoreOrderWapModel; //待完善
+use app\ebapi\model\user\UserRecharge;
+use service\HookService;
+use app\core\util\MiniProgramService;
+use app\core\util\WechatService;
+
+//待完善
+class PaymentBehavior
+{
+
+    /**
+     * 下单成功之后
+     * @param $order
+     * @param $prepay_id
+     */
+    public static function wechatPaymentPrepare($order, $prepay_id)
+    {
+
+    }
+
+    /**
+     * 支付成功后
+     * @param $notify
+     * @return bool|mixed
+     */
+    public static function wechatPaySuccess($notify)
+    {
+        if(isset($notify->attach) && $notify->attach){
+            return HookService::listen('wechat_pay_success_'.strtolower($notify->attach),$notify->out_trade_no,$notify,true,self::class);
+        }
+        return false;
+    }
+
+    /**
+     * 商品订单支付成功后  微信公众号
+     * @param $orderId
+     * @param $notify
+     * @return bool
+     */
+    public static function wechatPaySuccessProduct($orderId, $notify)
+    {
+        try{
+            if(StoreOrderWapModel::be(['order_id'=>$orderId,'paid'=>1])) return true;
+            return StoreOrderWapModel::paySuccess($orderId);
+        }catch (\Exception $e){
+            return false;
+        }
+    }
+
+
+    /**
+     * 商品订单支付成功后  小程序
+     * @param $orderId
+     * @param $notify
+     * @return bool
+     */
+    public static function wechatPaySuccessProductr($orderId, $notify)
+    {
+        try{
+            if(StoreOrderRoutineModel::be(['order_id'=>$orderId,'paid'=>1])) return true;
+            return StoreOrderRoutineModel::paySuccess($orderId);
+        }catch (\Exception $e){
+            return false;
+        }
+    }
+
+    /**
+     * 用户充值成功后
+     * @param $orderId
+     * @param $notify
+     * @return bool
+     */
+    public static function wechatPaySuccessUserRecharge($orderId, $notify)
+    {
+        try{
+            if(UserRecharge::be(['order_id'=>$orderId,'paid'=>1])) return true;
+            return UserRecharge::rechargeSuccess($orderId);
+        }catch (\Exception $e){
+            return false;
+        }
+    }
+
+    /**
+     * 使用余额支付订单时
+     * @param $userInfo
+     * @param $orderInfo
+     */
+    public static function yuePayProduct($userInfo, $orderInfo)
+    {
+
+
+    }
+
+
+    /**
+     * 微信支付订单退款
+     * @param $orderNo
+     * @param array $opt
+     */
+    public static function wechatPayOrderRefund($orderNo, array $opt)
+    {
+        WechatService::payOrderRefund($orderNo,$opt);
+    }
+
+    /**
+     * 小程序支付订单退款
+     * @param $orderNo
+     * @param array $opt
+     */
+    public static function routinePayOrderRefund($orderNo, array $opt)
+    {
+        MiniProgramService::payOrderRefund($orderNo,$opt);
+    }
+
+    /**
+     * 微信支付充值退款
+     * @param $orderNo
+     * @param array $opt
+     */
+
+    public static function userRechargeRefund($orderNo, array $opt)
+    {
+        WechatService::payOrderRefund($orderNo,$opt);
+    }
+}

+ 61 - 0
application/core/behavior/RequestFilterBehavior.php

@@ -0,0 +1,61 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/12 9:33
+ */
+
+namespace app\core\behavior;
+
+use think\Cache;
+use think\Config;
+use think\Request;
+use think\Validate;
+use app\core\implement\BehaviorIntterface;
+
+/*
+ * 请求数据验证
+ * class RequestFilter
+ *
+ * */
+class RequestFilterBehavior implements BehaviorIntterface
+{
+    /*
+     * 请求数据验证默认行为
+     * @retun
+     * */
+    public function run()
+    {
+        $request = Request::instance();
+        $method = strtoupper($request->method());
+        switch ($method) {
+            case 'GET':
+                $data = $request->get();
+                break;
+            case 'POST':
+                $data = $request->post();
+                break;
+            case 'DELETE':
+                $data = $request->delete();
+                break;
+            case 'PUT':
+                $data = $request->put();
+                break;
+            default :
+                $data = [];
+                break;
+        }
+        //开启路由
+        $hash = $request->routeInfo();
+        if(Config::get('url_route_on') && isset($hash['rule'][1])){
+
+        }else{
+            $module=$request->module();
+            $controller=$request->controller();
+            $action=$request->action();
+
+        }
+    }
+
+
+}

+ 78 - 0
application/core/behavior/UserBehavior.php

@@ -0,0 +1,78 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 5:41 PM
+ */
+
+namespace app\core\behavior;
+
+use app\core\model\user\UserLevel;
+use service\HookService;
+use app\core\model\user\User;
+use think\Request;
+
+class UserBehavior
+{
+    /** 用户访问记录
+     * @param $userinfo
+     */
+    public static function init($userinfo)
+    {
+        $request=Request::instance();
+        User::edit(['last_time'=>time(),'last_ip'=>$request->ip()],$userinfo->uid,'uid');
+    }
+    /**
+     * 管理员后台给用户添加金额
+     * @param $user
+     * $user 用户信息
+     * @param $money
+     * $money 添加的金额
+     */
+    public static function adminAddMoneyAfter($user,$money){
+
+    }
+
+    /**
+     * 管理员后台给用户减少金额
+     * @param $user
+     * $user 用户信息
+     * @param $money
+     * $money 减少的金额
+     */
+    public static function adminSubMoneyAfter($user,$money){
+
+    }
+
+    /**
+     * 管理员后台给用户增加的积分
+     * @param $user
+     * $user 用户信息
+     * @param $integral
+     * $integral 增加的积分
+     */
+    public static function adminAddIntegralAfter($user,$integral){
+
+    }
+
+    /**
+     * 管理员后台给用户减少的积分
+     * @param $user
+     * $user 用户信息
+     * @param $integral
+     * $integral 减少的积分
+     */
+    public static function adminSubIntegralAfter($user,$integral){
+
+    }
+
+    /*
+     * 用是否可成为Vip
+     * @param object $user 用户信息
+     * */
+    public static function userLevelAfter($user,$number)
+    {
+        return UserLevel::setLevelComplete($user['uid'],$number);
+    }
+
+}

+ 20 - 0
application/core/implement/BehaviorIntterface.php

@@ -0,0 +1,20 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/12 11:23
+ */
+
+namespace app\core\implement;
+
+/*
+ * 监听行为默认运行方法接口
+ *
+ * */
+
+interface BehaviorIntterface
+{
+
+
+    public function run();
+}

+ 22 - 0
application/core/implement/ProviderInterface.php

@@ -0,0 +1,22 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/9
+ * Time: 14:18
+ */
+
+namespace app\core\implement;
+
+/*
+ * 工厂模式服务注册接口类
+ *
+ * */
+
+interface ProviderInterface
+{
+
+    public function register($config);
+
+}
+

+ 21 - 0
application/core/implement/TemplateInterface.php

@@ -0,0 +1,21 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/9 17:43
+ */
+
+namespace app\core\implement;
+
+
+/*
+ * 模板消息接口类
+ *
+ * */
+
+interface TemplateInterface
+{
+    public static function sendTemplate($openId,$tempCode,$dataKey,$formId=null,$link=null,$defaultColor=null);
+
+    public static function getConstants($key=null);
+}

+ 23 - 0
application/core/lib/BaseException.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/16 9:18
+ */
+
+namespace app\core\lib;
+
+/*
+ * 错误处理基类
+ * */
+class BaseException
+{
+    //错误提示
+    public $msg='系统错误';
+    //HTTP状态码
+    public $code=500;
+    //自定义错误代码
+    public $errorCode=400;
+
+
+}

+ 32 - 0
application/core/logic/Login.php

@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 7:29 PM
+ */
+
+namespace app\core\logic;
+
+use app\core\traits\LogicTrait;
+use service\JsonService;
+
+class Login
+{
+    use LogicTrait;
+
+    protected  $providers=[
+        \app\core\logic\routine\RoutineLogin::class,
+    ];
+
+    public static function login_ing($action)
+    {
+        if($action instanceof Login){
+            return self::instance()->$action->login();
+        }else{
+            return JsonService::fail('访问的方法不存在!');
+        }
+
+    }
+
+}

+ 30 - 0
application/core/logic/Pay.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace app\core\logic;
+
+use app\core\util\MiniProgramService;
+use think\Request;
+
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 5:48 PM
+ */
+class Pay
+{
+    public static function notify(){
+        $request=Request::instance();
+        switch (strtolower($request->param('notify_type','wenxin'))){
+            case 'wenxin':
+                break;
+            case 'routine': //小程序支付回调
+                MiniProgramService::handleNotify();
+                break;
+            case 'alipay':
+                break;
+            default:
+                echo 121;
+                break;
+        }
+    }
+}

+ 34 - 0
application/core/logic/Qrcode.php

@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 7:30 PM
+ */
+use app\admin\model\wechat\WechatQrcode as QrcodeModel;//待完善
+
+class Qrcode
+{
+    /**
+     * 获取临时二维码  单个
+     * */
+    public static function getTemporaryQrcode($type,$id){
+        return QrcodeModel::getTemporaryQrcode($type,$id)->toArray();
+    }
+    /**
+     * 获取永久二维码  单个
+     * */
+    public static function getForeverQrcode($type,$id){
+        return QrcodeModel::getForeverQrcode($type,$id)->toArray();
+    }
+
+    public static function getQrcode($id,$type = 'id')
+    {
+        return QrcodeModel::getQrcode($id,$type);
+    }
+
+    public static function scanQrcode($id,$type = 'id')
+    {
+        return QrcodeModel::scanQrcode($id,$type);
+    }
+}

+ 13 - 0
application/core/logic/Template.php

@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 5:48 PM
+ */
+namespace app\core\logic;
+
+class Template
+{
+
+}

+ 22 - 0
application/core/logic/routine/RoutineLogin.php

@@ -0,0 +1,22 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/11 9:47
+ */
+
+namespace app\core\logic\routine;
+
+use app\core\implement\ProviderInterface;
+
+class RoutineLogin implements ProviderInterface
+{
+    public function register($config)
+    {
+        return ['routine_login',new self()];
+    }
+
+
+
+
+}

+ 6 - 0
application/core/logic/routine/oder.php

@@ -0,0 +1,6 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: xurongyao <763569752@qq.com>
+ * Date: 2019/4/8 5:45 PM
+ */

+ 37 - 0
application/core/model/ApiMenus.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/12 17:00
+ */
+
+namespace app\core\model;
+
+use traits\ModelTrait;
+use basic\ModelBasic;
+
+/*
+ * Api接口列表
+ * class ApiMenus
+ * */
+class ApiMenus extends ModelBasic
+{
+    use ModelTrait;
+
+    /*
+     * 接口列表配置
+     *
+     * */
+    protected $hash=[
+
+    ];
+
+    /*
+     * 获取
+     * */
+    public static function getHash($name)
+    {
+
+    }
+
+}

+ 88 - 0
application/core/model/routine/RoutineCode.php

@@ -0,0 +1,88 @@
+<?php
+namespace  app\core\model\routine;
+
+
+use app\core\util\MiniProgramService;
+
+class RoutineCode{
+
+    /**
+     * TODO 获取小程序二维码
+     * @param $thirdId
+     * @param $thirdType
+     * @param $page
+     * @param $imgUrl
+     * @return bool
+     */
+    public static function getShareCode($thirdId, $thirdType, $page, $imgUrl){
+        $res = RoutineQrcode::routineQrCodeForever($thirdId,$thirdType,$page,$imgUrl);
+        $resCode = MiniProgramService::qrcodeService()->appCodeUnlimit($res->id,$page,280);
+        if($resCode){
+            $dataQrcode['status'] = 1;
+            $dataQrcode['url_time'] = time();
+            $res = RoutineQrcode::setRoutineQrcodeFind($res->id,$dataQrcode);
+            if($res) return $resCode;
+            else return false;
+        }else return false;
+    }
+    /**
+     * TODO 获取小程序页面带参数二维码不保存数据库
+     * @param $thirdId
+     * @param $thirdType
+     * @param $page
+     * @param $imgUrl
+     * @return bool
+     */
+    public static function getPageCode($page = '', $pramam = "?uid=1&product=1",$width = 280){
+        return MiniProgramService::qrcodeService()->appCodeUnlimit($pramam,$page,$width);
+    }
+
+
+    /**
+     * 获取分销二维码
+     * @param int $uid  yonghuID
+     * @param array $color 二维码线条颜色
+     * @return mixed
+     */
+    public static function getCode($uid = 0,$imgUrl = '',$color = array(),$page = '',$thirdType = 'spread'){
+        $accessToken = RoutineServer::get_access_token();
+        $res = RoutineQrcode::setRoutineQrcodeForever($uid,$thirdType,$page,$imgUrl);
+        if($res){
+            $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".$accessToken;
+            if($uid) $data['scene'] = $res->id;
+            else $data['scene'] = 0;
+            if(empty($color)){
+                $color['r'] = 0;
+                $color['g'] = 0;
+                $color['b'] = 0;
+            }
+            $data['page'] = $page;
+            $data['width'] = 430;
+            $data['auto_color'] = false;
+            $data['line_color'] = $color;
+            $data['is_hyaline'] = false;
+            $resCode = RoutineServer::curlPost($url,json_encode($data));
+            if($resCode){
+                $dataQrcode['status'] = 1;
+                $dataQrcode['url_time'] = time();
+                $res = RoutineQrcode::setRoutineQrcodeFind($res->id,$dataQrcode);
+                if($res) return $resCode;
+                else return false;
+            }else return false;
+        }else return false;
+    }
+
+    /**
+     * 获取小程序内访问页面的二维码
+     * @param string $path
+     * @param int $width
+     * @return mixed
+     */
+    public static function getPages($path = '',$width = 430){
+        $accessToken = RoutineServer::get_access_token();
+        $url = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=".$accessToken;
+        $data['path'] = $path;
+        $data['width'] = $width;
+        return RoutineServer::curlPost($url,json_encode($data));
+    }
+}

+ 60 - 0
application/core/model/routine/RoutineFormId.php

@@ -0,0 +1,60 @@
+<?php
+namespace  app\core\model\routine;
+
+use basic\ModelBasic;
+use traits\ModelTrait;
+
+/**
+ * 表单ID表
+ * Class RoutineFormId
+ * @package app\core\model\routine
+ */
+class RoutineFormId extends ModelBasic {
+
+    use ModelTrait;
+
+    /**
+     * 删除已失效的formID
+     * @return int
+     */
+    public static function delStatusInvalid(){
+        return self::where('status',2)->where('stop_time','LT',time())->delete();
+    }
+
+    /**
+     * 获取一个可以使用的formId
+     * @return bool|mixed
+     */
+    public static function getFormIdOne($uid = 0,$isArray=false){
+        $formId = self::where('status',1)->where('stop_time','GT',time())->where('uid',$uid)->order('id asc')->find();
+        if($isArray) return $formId;
+        if($formId) return $formId['form_id'];
+        else return false;
+    }
+
+    /**
+     * 修改一个FormID为已使用
+     * @param string $formId
+     * @return $this|bool
+     */
+    public static function delFormIdOne($formId = ''){
+        if($formId == '') return true;
+        return self::where('form_id',$formId)->update(['status'=>2]);
+    }
+
+    /*
+     * 创建formid
+     * @param string $formId
+     * @param int $uid
+     * @return array
+     * */
+    public static function SetFormId($formId,$uid)
+    {
+        if(!strlen(trim($formId)) || $formId == 'the formId is a mock one') return false;
+        $data['form_id'] = $formId;
+        $data['uid'] = $uid;
+        $data['status'] = 1;
+        $data['stop_time'] = bcadd(time(),bcmul(6,86400,0),0);
+        return self::set($data);
+    }
+}

+ 92 - 0
application/core/model/routine/RoutineQrcode.php

@@ -0,0 +1,92 @@
+<?php
+namespace  app\core\model\routine;
+
+
+use basic\ModelBasic;
+use traits\ModelTrait;
+
+/**
+ * 小程序二维码Model
+ * Class RoutineQrcode
+ * @package app\core\model\routine
+ */
+class RoutineQrcode extends ModelBasic {
+
+    use ModelTrait;
+
+    /**
+     * TODO 添加二维码  存在直接获取
+     * @param int $thirdId
+     * @param string $thirdType
+     * @param string $page
+     * @param string $qrCodeLink
+     * @return array|false|object|\PDOStatement|string|\think\Model
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function routineQrCodeForever($thirdId = 0,$thirdType = 'spread',$page = '',$qrCodeLink = ''){
+       $count = self::where('third_id',$thirdId)->where('third_type',$thirdType)->count();
+       if($count) return self::where('third_id',$thirdId)->where('third_type',$thirdType)->field('id')->find();
+       return self::setRoutineQrcodeForever($thirdId,$thirdType,$page,$qrCodeLink);
+    }
+
+    /**
+     * 添加二维码记录
+     * @param string $thirdType
+     * @param int $thirdId
+     * @return object
+     */
+    public static function setRoutineQrcodeForever($thirdId = 0,$thirdType = 'spread',$page = '',$qrCodeLink = ''){
+       $data['third_type'] = $thirdType;
+       $data['third_id'] = $thirdId;
+       $data['status'] = 0;
+       $data['add_time'] = time();
+       $data['page'] = $page;
+       $data['url_time'] = '';
+       $data['qrcode_url'] = $qrCodeLink;
+       return self::set($data);
+    }
+
+    /**
+     * 修改二维码地址
+     * @param int $id
+     * @param array $data
+     * @return bool
+     */
+    public static function setRoutineQrcodeFind($id = 0,$data = array()){
+        if(!$id) return false;
+        $count = self::getRoutineQrcodeFind($id);
+        if(!$count) return false;
+        return self::edit($data,$id,'id');
+    }
+
+    /**
+     * 获取二维码是否存在
+     * @param int $id
+     * @return int|string
+     */
+    public static function getRoutineQrcodeFind($id = 0){
+        if(!$id) return 0;
+        return self::where('id',$id)->count();
+    }
+
+    /**
+     * 获取小程序二维码信息
+     * @param int $id
+     * @param string $field
+     * @return array|bool|false|\PDOStatement|string|\think\Model
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function getRoutineQrcodeFindType($id = 0,$field = 'third_type,third_id,page'){
+        if(!$id) return false;
+        $count = self::getRoutineQrcodeFind($id);
+        if(!$count) return false;
+        return self::where('id',$id)->where('status',1)->field($field)->find();
+    }
+
+
+}

+ 133 - 0
application/core/model/routine/RoutineTemplate.php

@@ -0,0 +1,133 @@
+<?php
+namespace  app\core\model\routine;
+
+use app\core\util\Template;
+use app\ebapi\model\store\StoreOrder;
+use app\ebapi\model\user\WechatUser;
+
+
+/**
+ * 小程序模板消息
+ * Class RoutineTemplate
+ * @package app\core\model\routine
+ */
+class RoutineTemplate
+{
+
+    /*
+     *
+     * */
+    public static function sendOrderTakeOver()
+    {
+
+    }
+    /*
+     * 送货和发货
+     * */
+    public static function sendOrderPostage($order,$isGive=0)
+    {
+        if($isGive){
+            $data['keyword1'] =  $order['order_id'];
+            $data['keyword2'] =  $order['delivery_name'];
+            $data['keyword3'] =  $order['delivery_id'];
+            $data['keyword4'] =  date('Y-m-d H:i:s',time());
+            $data['keyword5'] =  '您的商品已经发货请注意查收';
+            return self::sendOut('ORDER_POSTAGE_SUCCESS',$order['uid'],$data);
+        }else{
+            $data['keyword1'] =  $order['order_id'];
+            $data['keyword2'] =  $order['delivery_name'];
+            $data['keyword3'] =  $order['delivery_id'];
+            $data['keyword4'] =  date('Y-m-d H:i:s',time());
+            $data['keyword5'] =  '您的商品已经发货请注意查收';
+            return self::sendOut('ORDER_DELIVER_SUCCESS',$order['uid'],$data);
+        }
+    }
+    /**
+     * 退款成功发送消息
+     * @param array $order
+     */
+    public static function sendOrderRefundSuccess($order = array())
+    {
+        if(!$order) return false;
+        $data['keyword1'] =  $order['order_id'];
+        $data['keyword2'] =  date('Y-m-d H:i:s',time());
+        $data['keyword3'] =  $order['pay_price'];
+        if($order['pay_type'] == 'yue') $data['keyword4'] =  '余额支付';
+        else if($order['pay_type'] == 'weixin') $data['keyword4'] =  '微信支付';
+        else if($order['pay_type'] == 'offline') $data['keyword4'] =  '线下支付';
+        $data['keyword5']['value'] = '已成功退款';
+        return self::sendOut('ORDER_REFUND_SUCCESS',$order['uid'],$data);
+    }
+    /**
+     * 用户申请退款给管理员发送消息
+     * @param array $order
+     * @param string $refundReasonWap
+     * @param array $adminList
+     */
+    public static function sendOrderRefundStatus($order = array(),$refundReasonWap = '',$adminList = array()){
+        $data['keyword1'] =  $order['order_id'];
+        $data['keyword2'] =  $refundReasonWap;
+        $data['keyword3'] =  date('Y-m-d H:i:s',time());
+        $data['keyword4'] =  $order['pay_price'];
+        $data['keyword5'] =  '原路返回';
+        foreach ($adminList as $uid){
+            self::sendOut('ORDER_REFUND_STATUS',$uid,$data);
+        }
+    }
+    /**
+     * 砍价成功通知
+     * @param array $bargain
+     * @param array $bargainUser
+     * @param int $bargainUserId
+     */
+    public static function sendBargainSuccess($bargain = array(),$bargainUser  = array(),$bargainUserId = 0){
+        $data['keyword1'] =  $bargain['title'];
+        $data['keyword2'] =  $bargainUser['bargain_price'];
+        $data['keyword3'] =  $bargainUser['bargain_price_min'];
+        $data['keyword4'] =  $bargainUser['price'];
+        $data['keyword5'] =  $bargainUser['bargain_price_min'];
+        $data['keyword6'] =  '恭喜您,已经砍到最低价了';
+        return self::sendOut('BARGAIN_SUCCESS',$bargainUser['uid'],$data);
+    }
+    /**
+     * 订单支付成功发送模板消息
+     * @param string $formId
+     * @param string $orderId
+     */
+    public static function sendOrderSuccess($formId = '',$orderId = ''){
+        if($orderId == '') return ;
+        $order = StoreOrder::where('order_id',$orderId)->find();
+        $data['keyword1'] =  $orderId;
+        $data['keyword2'] =  date('Y-m-d H:i:s',time());
+        $data['keyword3'] =  '已支付';
+        $data['keyword4'] =  $order['pay_price'];
+        if($order['pay_type'] == 'yue') $data['keyword5'] =  '余额支付';
+        else if($order['pay_type'] == 'weixin') $data['keyword5'] =  '微信支付';
+        return self::sendOut('ORDER_PAY_SUCCESS',$order['uid'],$data,$formId,'/pages/order_details/index?order_id='.$orderId);
+    }
+
+    /*
+     * 发送模板消息
+     * @param string  $TempCode 模板消息常量名称
+     * @param int $uid 用户uid
+     * @param array $data 模板内容
+     * @param string $formId formId
+     * @param string $link 跳转链接
+     * */
+    public static function sendOut($TempCode,$uid=null,$data=null,$formId = '',$link='')
+    {
+        try{
+            $openid=WechatUser::uidToOpenid($uid);
+            if(!$formId){
+                $form= RoutineFormId::getFormIdOne($uid,true);
+                if(!$form) return false;
+                if(isset($form['id'])) RoutineFormId::where('id',$form['id'])->delete();
+            }else{
+                $form['form_id']=$formId;
+            }
+            return Template::instance()->routine_two->sendTemplate($TempCode,$openid,$data,$form['form_id'],$link);
+        }catch (\Exception $e){
+            return false;
+        }
+    }
+}

+ 38 - 0
application/core/model/routine/Token.php

@@ -0,0 +1,38 @@
+<?php
+namespace  app\core\model\routine;
+
+
+use basic\ModelBasic;
+use traits\ModelTrait;
+/**
+ * 小程序token辅助验证表
+ * Class Token
+ * @package app\core\model\routine
+ */
+class Token extends ModelBasic
+{
+    use ModelTrait;
+
+    /*
+     * 保存随机字符串 当前用户有token则删除 保存最新token
+     * @param int $uid 用户uid
+     * @param string $randstring 随机字符串
+     * @return array
+     * */
+    public static function SetRandString($uid,$randstring)
+    {
+        if(self::be(['uid'=>$uid])) self::where('uid',$uid)->delete();
+        return self::set(['uid'=>$uid,'rand_string'=>$randstring,'add_time'=>time()]);
+    }
+
+    /*
+     * 验证当前token是否被篡改
+     * @param int $uid 用户uid
+     * @param string $randstring 随机字符串
+     * @return Boolean
+     * */
+    public static function checkRandString($uid,$randstring)
+    {
+        return self::where('uid',$uid)->value('rand_string') === $randstring;
+    }
+}

+ 150 - 0
application/core/model/system/SystemUserLevel.php

@@ -0,0 +1,150 @@
+<?php
+
+
+namespace app\core\model\system;
+
+use app\core\model\user\UserLevel;
+use think\Cache;
+use traits\ModelTrait;
+use basic\ModelBasic;
+
+/**
+ * 设置会员vip model
+ * Class SystemVip
+ * @package app\core\model\system
+ */
+class SystemUserLevel extends ModelBasic
+{
+    use ModelTrait;
+
+    public static function getAddTimeAttr($value)
+    {
+        return date('Y-m-d H:i:s',$value);
+    }
+    public static function getDiscountAttr($value)
+    {
+        return (int)$value;
+    }
+    /*
+     * 获取查询条件
+     * @param string $alert 别名
+     * @param object $model 模型
+     * @return object
+     * */
+    public static function setWhere($alert='',$model=null)
+    {
+        $model=$model===null ? new self() : $model;
+        if($alert) $model=$model->alias($alert);
+        $alert=$alert ? $alert.'.': '';
+        return $model->where("{$alert}is_show",1)->where("{$alert}is_del",0);
+    }
+
+    /*
+     * 获取某个等级的折扣
+     * */
+    public static function getLevelDiscount($id=0)
+    {
+        $model=self::setWhere();
+        if($id) $model=$model->where('id',$id);
+        else $model=$model->order('grade asc');
+        return $model->value('discount');
+    }
+
+    /*
+     * 获取用户等级和当前等级
+     * @param int $uid 用户uid
+     * @param Boolean $isArray 是否查找任务列表
+     * @return array
+     * */
+    public static function getLevelInfo($uid,$isArray=false){
+        $level=['id'=>0];$task=[];
+        $id=UserLevel::getUserLevel($uid);
+        if($id!==false) $level=UserLevel::getUserLevelInfo($id);
+        $list=self::getLevelListAndGrade($level['id'],$isArray);
+        if(isset($list[0]) && $isArray) $task=SystemUserTask::getTashList($list[0]['id'],$uid,$level);
+        if($isArray) return [$list,$task];
+        else return $level['id'] && $id !== false ? $level : false;
+    }
+
+    /*
+     * 获取会员等级级别
+     * @param int $leval_id 等级id
+     * @return Array
+     * */
+    public static function getLevelGrade($leval_id)
+    {
+        return self::setWhere()->where('id',$leval_id)->value('grade');
+    }
+    /*
+     * 获取会员等级列表
+     * @param int $levael_id 用户等级
+     * @param Boolean $isArray 是否查找任务列表
+     * @return Array
+     * */
+    public static function getLevelListAndGrade($leval_id,$isArray,$expire=1400)
+    {
+        if($isArray && Cache::has('LevelListArrayTask')){
+            return Cache::get('LevelListArrayTask');
+        }else if(Cache::has('LevelListArray')){
+            return Cache::get('LevelListArray');
+        }
+        $grade=0;
+        $list=self::setWhere()->field(['name','discount','image','icon','explain','id','grade'])->order('grade asc')->select();
+        $list=count($list) ? $list->toArray() : [];
+        foreach ($list as &$item){
+            if($item['id']==$leval_id) $grade=$item['grade'];
+            if($isArray) $item['task_list']=SystemUserTask::getTashList($item['id']);
+        }
+        foreach ($list as &$item){
+            if($grade < $item['grade']) $item['is_clear']=true;
+            else $item['is_clear']=false;
+        }
+        if($isArray)
+            Cache::set('LevelListArrayTask',$list,$expire);
+        else
+            Cache::set('LevelListArray',$list,$expire);
+        return $list;
+    }
+
+    public static function getClear($leval_id,$list=null)
+    {
+        $list=$list===null ?  self::getLevelListAndGrade($leval_id,false) : $list;
+        foreach ($list as $item){
+            if($item['id']==$leval_id) return $item['is_clear'];
+        }
+        return false;
+    }
+
+    /*
+     * 获取当前vipid 的下一个会员id
+     * @param int $leval_id 当前用户的会员id
+     * @return int
+     * */
+    public static function getNextLevelId($leval_id)
+    {
+        $list=self::getLevelListAndGrade($leval_id,false);
+        $grade=0;
+        $leveal=[];
+        foreach ($list as $item){
+            if($item['id']==$leval_id) $grade=$item['grade'];
+        }
+        foreach ($list as $item){
+            if($grade < $item['grade']) array_push($leveal,$item['id']);
+        }
+        return isset($leveal[0]) ? $leveal[0] : 0;
+    }
+
+    /*
+     * 获取会员等级列表
+     * @parma int $uid 用户uid
+     * @return Array
+     * */
+    public static function getLevelList($uid){
+        list($list,$task)=self::getLevelInfo($uid,true);
+        return ['list'=>$list,'task'=>$task];
+    }
+
+
+
+
+}

+ 412 - 0
application/core/model/system/SystemUserTask.php

@@ -0,0 +1,412 @@
+<?php
+namespace app\core\model\system;
+
+use app\core\model\user\User;
+use app\core\model\user\UserBill;
+use app\core\model\user\UserLevel;
+use app\core\model\user\UserTaskFinish;
+use think\Cache;
+use traits\ModelTrait;
+use basic\ModelBasic;
+
+/**
+ * 设置等级任务 model
+ * Class SystemVipTask
+ * @package app\core\model\system
+ */
+class SystemUserTask extends ModelBasic
+{
+    use ModelTrait;
+
+    /*
+     * 任务类型
+     * type 记录在数据库中用来区分任务
+     * name 任务名 (任务名中的{$num}会自动替换成设置的数字 + 单位)
+     * max_number 最大设定数值 0为不限定
+     * min_number 最小设定数值
+     * unit 单位
+     * */
+    protected static $TaskType=[
+        [
+            'type'=>'SatisfactionIntegral',
+            'name'=>'满足积分{$num}',
+            'real_name'=>'积分数',
+            'max_number'=>0,
+            'min_number'=>0,
+            'unit'=>'分'
+        ],
+        [
+            'type'=>'ConsumptionAmount',
+            'name'=>'消费满{$num}',
+            'real_name'=>'消费金额',
+            'max_number'=>0,
+            'min_number'=>0,
+            'unit'=>'元'
+        ],
+        [
+            'type'=>'ConsumptionFrequency',
+            'name'=>'消费{$num}',
+            'real_name'=>'消费次数',
+            'max_number'=>0,
+            'min_number'=>0,
+            'unit'=>'次'
+        ],
+        [
+            'type'=>'CumulativeAttendance',
+            'name'=>'累计签到{$num}',
+            'real_name'=>'累计签到',
+            'max_number'=>365,
+            'min_number'=>1,
+            'unit'=>'天'
+        ],
+        [
+            'type'=>'SharingTimes',
+            'name'=>'分享给朋友{$num}',
+            'real_name'=>'分享给朋友',
+            'max_number'=>1000,
+            'min_number'=>1,
+            'unit'=>'次'
+        ],
+        [
+            'type'=>'InviteGoodFriends',
+            'name'=>'邀请好友{$num}成为下线',
+            'real_name'=>'邀请好友成为下线',
+            'max_number'=>1000,
+            'min_number'=>1,
+            'unit'=>'人'
+        ],
+        [
+            'type'=>'InviteGoodFriendsLevel',
+            'name'=>'邀请好友{$num}成为会员',
+            'real_name'=>'邀请好友成为会员',
+            'max_number'=>1000,
+            'min_number'=>1,
+            'unit'=>'人'
+        ],
+    ];
+
+    public function profile()
+    {
+        return $this->hasOne('SystemUserLevel','level_id','id')->field('name');
+    }
+
+    public static function getTaskTypeAll()
+    {
+        return self::$TaskType;
+    }
+
+    /*
+     * 获取某个任务
+     * @param string $type 任务类型
+     * @return array
+     * */
+    public static function getTaskType($type)
+    {
+        foreach (self::$TaskType as $item){
+            if($item['type']==$type) return $item;
+        }
+    }
+
+    /*
+     * 设置任务名
+     * @param string $type 任务类型
+     * @param int $num 预设值
+     * @return string
+     * */
+    public static function setTaskName($type,$num)
+    {
+        $systemType=self::getTaskType($type);
+        return str_replace('{$num}',$num.$systemType['unit'],$systemType['name']);
+    }
+
+    /*
+     * 累计消费金额
+     * @param int $task_id 任务id
+     * @param int $uid 用户id
+     * @param int $start_time 开始时间
+     * @param int $number 限定时间
+     * @return boolean
+     * */
+    public static function ConsumptionAmount($task_id,$uid=0,$start_time=0,$number=0)
+    {
+        $isComplete=false;
+        $SumPayPrice=self::getDb('store_order')->where('paid',1)->where('refund_status',0)->where('is_del',0)->where('uid',$uid)->sum('pay_price');
+        if($SumPayPrice >= $number) $isComplete=UserTaskFinish::setFinish($uid,$task_id) ? true : false;
+        return ['还需消费{$num}元',$SumPayPrice,$isComplete];
+    }
+
+    /*
+     * 累计消费次数
+     * @param int $task_id 任务id
+     * @param int $uid 用户id
+     * @param int $start_time 开始时间
+     * @param int $number 限定时间
+     * @return boolean
+     * */
+    public static function ConsumptionFrequency($task_id,$uid=0,$start_time=0,$number=0)
+    {
+        $isComplete=false;
+        $countPay=self::getDb('store_order')->where('paid',1)->where('refund_status',0)->where('is_del',0)->where('uid',$uid)->count();
+        if($countPay >= $number) $isComplete=UserTaskFinish::setFinish($uid,$task_id) ? true : false;
+        return ['还需消费{$num}次',$countPay,$isComplete];
+    }
+
+    /*
+     * 邀请好友成为会员
+     * @param int $task_id 任务id
+     * @param int $uid 用户id
+     * @param int $start_time 开始时间
+     * @param int $number 限定时间
+     * @return boolean
+     * */
+    public static function InviteGoodFriendsLevel($task_id,$uid=0,$start_time=0,$number=0)
+    {
+        $isComplete=false;
+        $uids=User::where('spread_uid',$uid)->where('spread_time','>',$start_time)->column('uid');
+        $levelCount=count($uids) ? UserLevel::setUserLevelCount($uids) : 0;
+        if($levelCount >= $number) $isComplete=serTaskFinish::setFinish($uid,$task_id) ? true : false;
+        return ['还需邀请{$num}人成为会员',$levelCount,$isComplete];
+    }
+
+    /*
+     * 邀请好友成为下线
+     * @param int $task_id 任务id
+     * @param int $uid 用户id
+     * @param int $start_time 查询开始时间
+     * @param int $number 限定数量
+     * */
+    public static function InviteGoodFriends($task_id,$uid=0,$start_time=0,$number=0)
+    {
+        $isComplete=false;
+        $spreadCount=User::where('spread_uid',$uid)->where('spread_time','>',$start_time)->count();
+        if($spreadCount >= $number) $isComplete=UserTaskFinish::setFinish($uid,$task_id) ? true : false;
+        return ['还需邀请{$num}人成为下线',$spreadCount,$isComplete];
+    }
+
+    /*
+     * 满足积分
+     * @param int $task_id 任务id
+     * @param int $uid 用户id
+     * @param int $start_time 查询开始时间
+     * @param int $number 限定数量
+     * @return Boolean
+     * */
+    public static function SatisfactionIntegral($task_id,$uid=0,$start_time=0,$number=0)
+    {
+        $isComplete=false;
+        $sumNumber=UserBill::where(['uid'=>$uid,'category'=>'integral','pm'=>1])->where('type','in',['system_add','sign'])->sum('number');
+        if($sumNumber >= $number) $isComplete=UserTaskFinish::setFinish($uid,$task_id) ? true : false;
+        return ['还需要{$num}经验',$sumNumber,$isComplete];
+    }
+
+    /*
+     * 分享给朋友次数完成情况
+     * @param int $task_id 任务id
+     * @param int $uid 用户id
+     * @param int $start_time 查询开始时间
+     * @param int $number 限定数量
+     * @return Boolean
+     * */
+    public static function SharingTimes($task_id,$uid=0,$start_time=0,$number=0)
+    {
+        $isComplete=false;
+        $sumCount=UserBill::where(['uid'=>$uid,'category'=>'share','pm'=>1])->where('add_time','>',$start_time)->where('type','in',['share'])->count();
+        if($sumCount >= $number) $isComplete=UserTaskFinish::setFinish($uid,$task_id) ? true :false;
+        return ['还需分享{$num}次',$sumCount,$isComplete];
+    }
+
+    /*
+     * 累计签到
+     * @param int $task_id 任务id
+     * @param int $uid 用户id
+     * @param int $start_time 查询开始时间
+     * @param int $number 限定数量
+     * @return Boolean
+     * */
+    public static function CumulativeAttendance($task_id,$uid=0,$start_time=0,$number=0)
+    {
+        $isComplete=false;
+        $sumCount=UserBill::where(['uid'=>$uid,'category'=>'integral','pm'=>1])->where('type','in',['sign'])->count();
+        if($sumCount >= $number) $isComplete=UserTaskFinish::setFinish($uid,$task_id) ? true : false;
+        return ['还需签到{$num}天',$sumCount,$isComplete];
+    }
+
+    /*
+     * 设置任务完成情况
+     * @param int $task_id 任务id
+     * @param int $uid 用户uid
+     * @param int $start_time 查询开始时间
+     * @return Boolean
+     * */
+    public static function setTaskFinish($task_id=0,$uid=0,$start_time=0)
+    {
+        if(!$task_id) return self::setErrorInfo('缺少任务id参数');
+        if(!$uid) return self::setErrorInfo('缺少用户uid');
+        $task=self::where('id',$task_id)->where('is_show',1)->find();
+        if(!$task) return self::setErrorInfo('任务不存在');
+        $task_type=$task->task_type;
+        if($task_type && method_exists(self::class,$task_type)){
+            try{
+                return self::$task_type($task_id,$uid,$start_time,$task->number);
+            }catch (\Exception $e){
+                return self::setErrorInfo($e->getMessage());
+            }
+        }
+        return self::setErrorInfo('没有此任务');
+    }
+
+    /*
+     * 设置任务显示条件
+     * @param string $alert 表别名
+     * @param object $model 模型实例
+     * @return object
+     * */
+    public static function visibleWhere($alert='',$model=null)
+    {
+        $model=$model===null ? new self() : $model;
+        if($alert) $model=$model->alias($alert);
+        $alert=$alert ? $alert.'.': '';
+        return $model->where("{$alert}is_show",1);
+    }
+    /*
+     * 获取等级会员任务列表
+     * @param int $level_id 会员等级id
+     * @param int $uid 用户id
+     * @return array
+     * */
+    public static function getTashList($level_id,$uid=0,$level=null,$expire=1400)
+    {
+        $level_id=is_string($level_id) ? (int)$level_id : $level_id;
+        if(Cache::has('Tash_list_common_'.$level_id))
+            $list=Cache::get('Tash_list_common_'.$level_id);
+        else{
+            $list=self::visibleWhere()->where('level_id',$level_id)->field(['name','real_name','task_type','illustrate','number','id'])->order('sort desc')->select();
+            $list=count($list) ? $list->toArray() : [];
+            Cache::set('Tash_list_common_'.$level_id,$list,$expire);
+        }
+       if($uid==0) return $list;
+       if($level===null) $level=SystemUserLevel::getLevelInfo($uid);
+       $add_time=self::getDb('user')->where('uid',$uid)->value('add_time');
+       if($level===false) $startTime=$add_time;
+       else $startTime=isset($level['add_time']) ? $level['add_time'] : $add_time;
+       $LeveId=SystemUserLevel::getNextLevelId($level['id']);
+       $is_clear=SystemUserLevel::getClear($level['id']);
+       if($is_clear==false && $LeveId==$level_id) $is_clear=true;
+       $reach_count=self::getTaskComplete($level_id,$uid,true);
+       return ['reach_count'=>$reach_count,'task'=>self::tidyTask($list,$uid,$is_clear,$startTime)];
+    }
+
+    /*
+     * 获取未完成任务的详细值
+     * @param array $item 任务
+     * @param int $uid 用户id
+     * @param int $startTime 开始时间
+     * @return array
+     * */
+    protected static function set_task_type($item,$uid,$startTime=0){
+        $task=['task_type_title'=>'','new_number'=>0,'speed'=>0,'finish'=>0];
+        $task_type=$item['task_type'];
+        switch ($task_type) {
+            case 'SatisfactionIntegral':
+            case 'ConsumptionAmount':
+            case 'ConsumptionFrequency':
+            case 'CumulativeAttendance':
+            case 'SharingTimes':
+            case 'InviteGoodFriends':
+            case 'InviteGoodFriendsLevel':
+                try{
+                    list($task_type_title,$num,$isComplete)=self::$task_type($item['id'],$uid,$startTime,$item['number']);
+                    if($isComplete){
+                        $task['finish']=1;
+                        $task['speed']=100;
+                        $task['speed']=$item['number'];
+                        $task['new_number']=$item['number'];
+                    }else{
+                        $numdata=bcsub($item['number'],$num,0);
+                        $task['task_type_title']=str_replace('{$num}',$numdata,$task_type_title);
+                        $task['speed']=bcdiv($num,$item['number'],2);
+                        $task['speed']=bcmul($task['speed'],100,0);
+                        $task['new_number']=$num;
+                    }
+                }catch (\Exception $e){}
+                break;
+        }
+        return [$task['new_number'],$task['speed'],$task['task_type_title'],$task['finish']];
+    }
+
+
+    /*
+     * 设置任务完成状态,已被使用
+     * @param int $level_id 会员id
+     * @param int $uid 用户id
+     * @return Boolean
+     * */
+    public static function setTarkStatus($level_id,$uid)
+    {
+        $taskIds=self::visibleWhere()->where('level_id',$level_id)->column('id');
+        if(!count($taskIds)) return true;
+        return self::getDb('user_task_finish')->where('uid',$uid)->where('task_id','in',$taskIds)->update(['status'=>1]);
+    }
+    /*
+     * 检查当前等级是否完成全部任务
+     * @param int $level_id 会员id
+     * @param int $uid 用户uid
+     * @return boolean
+     * */
+    public static function getTaskComplete($level_id,$uid,$isCount=false)
+    {
+        $taskIds=self::visibleWhere()->where('level_id',$level_id)->column('id');
+        $taskIdsCount=count($taskIds);
+        //如果当前会员没有任务默认为直接升级为下一等级
+        if($taskIdsCount){
+            if($isCount){
+                return self::getDb('user_task_finish')->group('task_id')->where('uid',$uid)->where('task_id','in',$taskIds)->count();
+            }else{
+                $finishCount=self::getDb('user_task_finish')->group('task_id')->where('status',$isCount ? 1 : 0)->where('uid',$uid)->where('task_id','in',$taskIds)->count();
+            }
+            //如果当前任务有完成其一的,查询当前完成的任务数量,如果有任务完成则达成当前vip
+            if(self::visibleWhere()->where('id','in',$taskIds)->where('is_must',0)->count() && $finishCount){
+                return true;
+            }
+            return  $finishCount >= $taskIdsCount;
+        }
+        if($isCount) return 0;
+        //如果没有设置任务当前等级无需购买则返回false
+        if(SystemUserLevel::be(['id'=>$level_id,'is_pay'=>0])) return false;
+        return true;
+    }
+    /*
+     * 设置任务内容完成情况
+     * @param array $task 任务列表
+     * @param int $uid 用户id
+     * @热图图呢 array
+     * */
+    public static function tidyTask($task,$uid,$is_clear,$startTime){
+        if(!is_array($task)) return $task;
+        foreach ($task as &$item){
+            //如果已完成该任务进度直接为100
+            if(self::getDb('user_task_finish')->where('uid',$uid)->where('task_id',$item['id'])->count()){
+                $item['new_number']=$item['number'];
+                $item['speed']=100;
+                $item['finish']=1;
+                $item['task_type_title']='';
+            }else{
+                if($is_clear){
+                    list($new_number, $speed, $task_type_title, $finish) = self::set_task_type($item, $uid, $startTime);
+                    $item['new_number'] = $new_number;
+                    $item['speed'] = $speed;
+                    $item['task_type_title'] = $task_type_title;
+                    $item['finish'] = $finish;
+                }else {
+                    list($new_number, $speed, $task_type_title, $finish) = self::set_task_type($item,-1,time()+86400);
+                    $item['new_number'] = $new_number;
+                    $item['speed'] = $speed;
+                    $item['task_type_title'] = $task_type_title;
+                    $item['finish'] = $finish;
+                }
+            }
+        }
+        return $task;
+    }
+
+}

+ 19 - 0
application/core/model/user/User.php

@@ -0,0 +1,19 @@
+<?php
+/**
+ * Created by CRMEB.
+ * Copyright (c) 2017~2019 http://www.crmeb.com All rights reserved.
+ * Author: liaofei <136327134@qq.com>
+ * Date: 2019/4/3 9:13
+ */
+
+
+namespace app\core\model\user;
+
+use traits\ModelTrait;
+use basic\ModelBasic;
+
+class User extends ModelBasic
+{
+    use ModelTrait;
+
+}

+ 247 - 0
application/core/model/user/UserBill.php

@@ -0,0 +1,247 @@
+<?php
+/**
+ * Created by CRMEB.
+ * Copyright (c) 2017~2019 http://www.crmeb.com All rights reserved.
+ * Author: liaofei <136327134@qq.com>
+ * Date: 2019/3/27 21:44
+ */
+namespace app\core\model\user;
+
+use behavior\user\UserBehavior;
+use service\HookService;
+use think\Cache;
+use traits\ModelTrait;
+use basic\ModelBasic;
+/**
+ * 用户消费新增金额明细 model
+ * Class User
+ * @package app\core\model\user
+ */
+
+class UserBill extends ModelBasic
+{
+    use ModelTrait;
+
+    protected $insert = ['add_time'];
+
+    protected function setAddTimeAttr()
+    {
+        return time();
+    }
+
+    public static function income($title,$uid,$category,$type,$number,$link_id = 0,$balance = 0,$mark = '',$status = 1)
+    {
+        $pm = 1;
+        return self::set(compact('title','uid','link_id','category','type','number','balance','mark','status','pm'));
+    }
+
+    public static function expend($title,$uid,$category,$type,$number,$link_id = 0,$balance = 0,$mark = '',$status = 1)
+    {
+        $pm = 0;
+        return self::set(compact('title','uid','link_id','category','type','number','balance','mark','status','pm'));
+    }
+    /**
+     * 积分使用记录
+     * @param int $uid
+     * @param int $page
+     * @param int $limit
+     * @return \think\response\Json
+     */
+    public static function userBillList($uid,$page,$limit,$category='integral')
+    {
+        $list=self::where('uid',$uid)->where('category',$category)
+            ->field('mark,pm,number,add_time')
+            ->where('status',1)->order('add_time DESC')->page((int)$page,(int)$limit)->select();
+        $list=count($list) ? $list->toArray() : [];
+        foreach ($list as &$v){
+            $v['add_time'] = date('Y/m/d H:i',$v['add_time']);
+            $v['number'] = floatval($v['number']);
+        }
+        return $list;
+    }
+    /*
+     * 获取昨日佣金
+     * @param int $uid 用户uid
+     * */
+    public static function yesterdayCommissionSum($uid)
+    {
+        return self::where('uid',$uid)->where('category','now_money')->where('type','brokerage')->where('pm',1)
+            ->where('status',1)->whereTime('add_time', 'yesterday')->sum('number');
+    }
+
+    /*
+     * 获取总佣金
+     * */
+    public static function getBrokerage($uid)
+    {
+        return self::where('uid',$uid)->where('category','now_money')->where('type','brokerage')->where('pm',1)
+            ->where('status',1)->sum('number');
+    }
+
+
+    /*
+     * 累计充值
+     * */
+    public static function getRecharge($uid)
+    {
+        return self::where(['uid'=>$uid,'category'=>'now_money','type'=>'recharge','pm'=>1,'status'=>1])->sum('number');
+    }
+
+    /*
+     * 获取用户账单明细
+     * @param int $uid 用户uid
+     * @param int $page 页码
+     * @param int $limit 展示多少条
+     * @param int $type 展示类型
+     * @return array
+     * */
+    public static function getUserBillList($uid,$page,$limit,$type)
+    {
+        $model=self::where('uid',$uid)->where('category','now_money')->order('add_time desc')
+            ->field(['FROM_UNIXTIME(add_time,"%Y-%m") as time','group_concat(id SEPARATOR ",") ids'])->group('time');
+        switch ((int)$type){
+            case 0:
+                $model=$model->where('type','in',['recharge','brokerage','pay_product','system_add','pay_product_refund','system_sub']);
+                break;
+            case 1:
+                $model=$model->where('type','pay_product');
+                break;
+            case 2:
+                $model=$model->where('type','recharge');
+                break;
+            case 3:
+                $model=$model->where('type','brokerage');
+                break;
+            case 4:
+                $model=$model->where('type','extract');
+                break;
+        }
+        $list=($list=$model->page((int)$page,(int)$limit)->select()) ? $list->toArray() : [];
+        $data=[];
+        foreach ($list as $item){
+            $value['money']=$item['time'];
+            $value['list']=self::where('id','in',$item['ids'])->field(['FROM_UNIXTIME(add_time,"%Y-%m-%d %H:%i") as add_time','title','number','pm'])->order('add_time DESC')->select();
+            array_push($data,$value);
+        }
+        return $data;
+    }
+
+    /**
+     * TODO 获取用户记录 按月查找
+     * @param $uid $uid  用户编号
+     * @param int $first $first 起始值
+     * @param int $limit $limit 查询条数
+     * @param string $category $category 记录类型
+     * @param string $type $type 记录分类
+     * @return mixed
+     */
+    public static function getRecordList($uid,$first = 0,$limit = 8,$category = 'now_money',$type = ''){
+        $model = new self;
+        $model = $model->field("FROM_UNIXTIME(add_time, '%Y-%m') as time");
+        $model = $model->where('uid','IN',$uid);
+        $model = $model->where('category',$category);
+        if(strlen(trim($type))) $model = $model->where('type','in',$type);
+        $model = $model->group("FROM_UNIXTIME(add_time, '%Y-%m')");
+        $model = $model->limit($first,$limit);
+        $model = $model->order('time desc');
+        $list = $model->select();
+        if($list) return $list->toArray();
+        else [];
+    }
+
+    /**
+     * TODO  按月份查找用户记录
+     * @param $uid $uid  用户编号
+     * @param int $addTime $addTime 月份
+     * @param string $category $category 记录类型
+     * @param string $type $type 记录分类
+     * @return mixed
+     */
+    public static function getRecordListDraw($uid, $addTime = 0,$category = 'now_money',$type = ''){
+        if(!$uid) [];
+        $model = new self;
+        $model = $model->field("title,FROM_UNIXTIME(add_time, '%Y-%m-%d %H:%i') as time,number,pm");
+        $model = $model->where('uid',$uid);
+        $model = $model->where("FROM_UNIXTIME(add_time, '%Y-%m')= '{$addTime}'");
+        $model = $model->where('category',$category);
+        if(strlen(trim($type))) $model = $model->where('type','in',$type);
+        $model = $model->order('add_time desc');
+        $list = $model->select();
+        if($list) return $list->toArray();
+        else [];
+    }
+
+    /**
+     * TODO 获取订单返佣记录
+     * @param $uid
+     * @param int $addTime
+     * @param string $category
+     * @param string $type
+     * @return mixed
+     */
+    public static function getRecordOrderListDraw($uid, $addTime = 0,$category = 'now_money',$type = 'brokerage'){
+        if(!strlen(trim($uid))) [];
+        $model = new self;
+        $model = $model->field("o.order_id,FROM_UNIXTIME(o.add_time, '%Y-%m-%d %H:%i') as time,b.number,u.avatar,u.nickname");
+        $model = $model->alias('b');
+        $model = $model->join('StoreOrder o','o.id=b.link_id');
+        $model = $model->join('User u','u.uid=o.uid','right');
+        $model = $model->where('b.uid','IN',$uid);
+        $model = $model->where("FROM_UNIXTIME(b.add_time, '%Y-%m')= '{$addTime}'");
+        $model = $model->where('b.category',$category);
+        $model = $model->where('b.type','in',$type);
+        $model = $model->order('time desc');
+        $list = $model->select();
+        if($list) return $list->toArray();
+        else [];
+    }
+
+    /**
+     * TODO 获取用户记录总和
+     * @param $uid
+     * @param string $category
+     * @param string $type
+     * @return mixed
+     */
+    public static function getRecordCount($uid, $category = 'now_money', $type = '',$time=''){
+        $model = new self;
+        $model = $model->where('uid','IN',$uid);
+        $model = $model->where('category',$category);
+        if(strlen(trim($type))) $model = $model->where('type','in',$type);
+        if($time) $model=$model->whereTime('add_time',$time);
+        return $model->sum('number');
+    }
+
+    /**
+     * TODO 获取订单返佣记录总数
+     * @param $uid
+     * @param string $category
+     * @param string $type
+     * @return mixed
+     */
+    public static function getRecordOrderCount($uid, $category = 'now_money', $type = 'brokerage'){
+        $model = new self;
+        $model = $model->where('uid','IN',$uid);
+        $model = $model->where('category',$category);
+        if(strlen(trim($type))) $model = $model->where('type','in',$type);
+        return $model->count();
+    }
+
+    /*
+     * 记录分享次数
+     * @param int $uid 用户uid
+     * @param int $cd 冷却时间
+     * @return Boolean
+     * */
+    public static function setUserShare($uid,$cd=300){
+        $user=User::where('uid',$uid)->find();
+        if(!$user) return self::setErrorInfo('用户不存在!');
+        $cachename='Share_'.$uid;
+        if(Cache::has($cachename)) return false;
+        $res=self::income('用户分享记录',$uid,'share',1,0,0,date('Y-m-d H:i:s',time()).':用户分享');
+        Cache::set($cachename,1,$cd);
+        HookService::afterListen('user_leve',$user,false,UserBehavior::class);
+        return true;
+    }
+
+}

+ 177 - 0
application/core/model/user/UserLevel.php

@@ -0,0 +1,177 @@
+<?php
+namespace app\core\model\user;
+
+use app\core\model\system\SystemUserLevel;
+use app\core\model\system\SystemUserTask;
+use basic\ModelBasic;
+use traits\ModelTrait;
+
+class UserLevel extends ModelBasic
+{
+    use ModelTrait;
+
+    /*
+    * 获取用户等级人数
+    * */
+    public static function setUserLevelCount($uids)
+    {
+        $model=new self();
+        if(is_array($uids)) $model=$model->where('uid','in',$uids);
+        else $model=$model->where('uid',$uids);
+        return $model->count();
+    }
+
+    /*
+     * 设置查询初始化条件
+     * @param string $alias 表别名
+     * @param object $model 模型实例化对象
+     * @return object
+     * */
+    public static function valiWhere($alias='',$model=null)
+    {
+        $model=is_null($model) ? new self() : $model;
+        if($alias){
+            $model=$model->alias($alias);
+            $alias.='.';
+        }
+        return $model->where(["{$alias}status"=>1,"{$alias}is_del"=>0]);
+    }
+    /*
+     * 设置会员等级
+     * @param int $uid 用户uid
+     * @param int $level_id 等级id
+     * @return boolean | array
+     * */
+    public static function setUserLevel($uid,$level_id){
+        $vipinfo=SystemUserLevel::get($level_id);
+        if(!$vipinfo) return false;
+        $userinfo=self::getDb('user')->find($uid);
+        if(!$userinfo) return false;
+        $add_valid_time=(int)$vipinfo->valid_date*86400;
+        $uservipinfo=self::valiWhere()->where(['uid'=>$uid,'level_id'=>$level_id])->find();
+        //检查是否购买过
+        if($uservipinfo){
+            $stay=0;
+            //剩余时间
+            if(time() < $uservipinfo->valid_time) $stay=$uservipinfo->valid_time-time();
+            //如果购买过当前等级的会员过期了.从当前时间开始计算
+            //过期时效: 剩余时间+当前会员等级时间+当前time
+            $add_valid_time=$stay+$add_valid_time+time();
+            $data['is_forever']=$vipinfo->is_forever;
+            $data['valid_time']=$add_valid_time;
+            return self::where(['uid'=>$uid,'level_id'=>$level_id])->update($data);
+        }else{
+            $data=[
+                'is_forever'=>$vipinfo->is_forever,
+                'status'=>1,
+                'is_del'=>0,
+                'grade'=>$vipinfo->grade,
+                'uid'=>$uid,
+                'add_time'=>time(),
+                'level_id'=>$level_id,
+                'discount'=>$vipinfo->discount,
+            ];
+            if($data['is_forever'])
+                $data['valid_time']=0;
+            else
+                $data['valid_time']=$add_valid_time;
+            $data['mark']='尊敬的用户'.$userinfo['nickname'].'在'.date('Y-m-d H:i:s',time()).'成为了'.$vipinfo['name'];
+            return self::set($data);
+        }
+    }
+
+    /*
+     * 获取当前用户会员等级返回当前用户等级id
+     * @param int $uid 用户uid
+     * @return int 会员id
+     * */
+    public static function getUserLevel($uid,$grade=0)
+    {
+        $model = self::valiWhere();
+        if ($grade) $model = $model->where('grade', '<', $grade);
+        $level = $model->where('uid', $uid)->order('grade desc')->field('level_id,is_forever,valid_time,id')->find();
+        if (!$level) return false;
+        if ($level->is_forever) return $level->id;
+        //会员已经过期
+        if (time() < $level->valid_time){
+            if($level->status==1){
+                $level->status=0;
+                $level->save();
+            }
+            return self::getUserLevel($uid, $level->grade);
+        }else
+            //会员没有过期
+            return $level->id;
+    }
+
+    /*
+     * 获取会员详细信息
+     * @param int $id 会员记录id
+     * @param string $keyName 字段名
+     * @return array
+     * */
+    public static function getUserLevelInfo($id,$keyName=''){
+        $vipinfo=self::valiWhere('a')->where('a.id',$id)->field('l.id,a.add_time,a.discount,a.level_id,l.name,l.money,l.icon,l.is_pay')
+            ->join('__SYSTEM_USER_LEVEL__ l','l.id=a.level_id')->find();
+        if($keyName) if(isset($vipinfo[$keyName])) return $vipinfo[$keyName]; else return '';
+        return $vipinfo;
+    }
+
+    /*
+     * 获取当前用户已成为的vip id
+     * @param int $uid 用户id
+     * @return array
+     * */
+    public static function getUserLevelIds($uid)
+    {
+       return self::valiWhere()->group('level_id')->where('uid',$uid)->order('grade asc')->column('level_id');
+    }
+
+    /*
+     * 检查是否能成为会员
+     * @param int $uid 用户
+     * */
+    public static function setLevelComplete($uid,$leveNowId=false)
+    {
+        $user=User::where('uid',$uid)->find();
+        if(!$user) return self::setErrorInfo('没有此用户,无法检测升级会员');
+        $level=self::getUserLevel($uid);
+        if($level===false)
+            $level_id=0;
+        else
+            $level_id=self::getUserLevelInfo($level,'level_id');
+        $leveNowId=SystemUserLevel::getNextLevelId($level_id);
+        if($leveNowId===0) return self::setErrorInfo('暂无可升会员');
+        //查找当前需要升级的会员任务
+        $taskAll=SystemUserTask::visibleWhere()->where('level_id',$leveNowId)->column('id');
+        self::startTrans();
+        $res2=true;
+        try{
+            if($level===false){
+                //没有成为会员的从用户添加的时间开始算起
+                $add_time=$user['add_time'];
+            }else{
+                $add_time=self::getUserLevelInfo($level,'add_time');
+            }
+            //查询并记录任务
+            foreach ($taskAll as $id){
+                $res=SystemUserTask::setTaskFinish($id,$uid,$add_time);
+                if(!$res) return self::setErrorInfo(SystemUserTask::getErrorInfo(),true);
+            }
+            //获取需要成为会员的任务完成度
+            if(SystemUserTask::getTaskComplete($leveNowId,$uid)){
+                //设置任务已使用
+                $res=SystemUserTask::setTarkStatus($leveNowId,$uid);
+                if(!$res) return self::setErrorInfo('设置任务状态失败',true);
+                //记录会员
+                $res2=self::setUserLevel($uid,$leveNowId);
+            }
+            self::commitTrans();
+            return $res2;
+        }catch (\Exception $e){
+            self::rollbackTrans();
+            return self::setErrorInfo($e->getMessage());
+        }
+    }
+
+}

+ 143 - 0
application/core/model/user/UserSign.php

@@ -0,0 +1,143 @@
+<?php
+namespace app\core\model\user;
+
+use basic\ModelBasic;
+use app\core\behavior\UserBehavior;
+use service\HookService;
+use traits\ModelTrait;
+
+
+/*
+ * 用户签到模型
+ *
+ * */
+class UserSign extends ModelBasic
+{
+    use ModelTrait;
+    /*
+     * 设置签到数据
+     * @param int $uid 用户uid
+     * @param string $title 签到说明
+     * @param int $number 签到获得积分
+     * @param int $balance 签到前剩余积分
+     * @return object
+     * */
+    public static function setSignData($uid,$title='',$number=0,$balance=0)
+    {
+        $add_time=time();
+        return self::set(compact('uid','title','number','balance','add_time')) && UserBill::income($title,$uid,'integral','sign',$number,0,$balance,$title);
+    }
+
+    /*
+     * 分页获取用户签到数据
+     * @param int $uid 用户uid
+     * @param int $page 页码
+     * @param int $limit 显示多少条
+     * @return array
+     * */
+    public static function getSignList($uid,$page,$limit)
+    {
+        return UserBill::where(['a.category'=>'integral','a.type'=>'sign','a.status'=>1,'a.uid'=>$uid])
+            ->alias('a')->join("__USER__ u",'u.uid=a.uid')->order('a.add_time desc')
+            ->field(['FROM_UNIXTIME(a.add_time,"%Y-%m-%d") as add_time','a.title','a.number'])
+            ->page((int)$page,(int)$limit)->select();
+    }
+
+    /*
+     * 获取用户累计签到次数
+     * @Parma int $uid 用户id
+     * @return int
+     * */
+    public static function getSignSumDay($uid)
+    {
+        return self::where(['uid'=>$uid])->count();
+    }
+
+    /*
+     * 获取用户今天是否签到
+     * @param int $uid
+     * */
+    public static function getToDayIsSign($uid)
+    {
+        return self::where(['uid'=>$uid])->whereTime('add_time','today')->count() ? true : false;
+    }
+
+    /*
+     * 获取用户昨天是否签到
+     * @param int $uid
+     * */
+    public static function getYesterDayIsSign($uid)
+    {
+        return self::where(['uid'=>$uid])->whereTime('add_time','yesterday')->count() ? true : false;
+    }
+
+    /*
+     * 获取签到配置
+     * @param string
+     * */
+    public static function getSignSystemList($key='sign_day_num')
+    {
+        return \app\core\util\GroupDataService::getData($key) ? : [];
+    }
+
+    /*
+     * 用户签到
+     * @param int $uid 用户uid
+     * @return boolean
+     * */
+    public static function sign($uid)
+    {
+        $sign_list=self::getSignSystemList();
+        if(!count($sign_list)) return self::setErrorInfo('请先配置签到天数');
+        $user=User::where('uid',$uid)->find();
+        $sign_num=0;
+        //检测昨天是否签到
+        if(self::getYesterDayIsSign($uid)){
+            if($user->sign_num > (count($sign_list) -1)) $user->sign_num=0;
+        }else{
+            //如果昨天没签到,回退到第一天
+            $user->sign_num=0;
+        }
+        foreach ($sign_list as $key=>$item){
+            if($key==$user->sign_num){
+                $sign_num=$item['sign_num'];
+                break;
+            }
+        }
+        $user->sign_num+=1;
+        if($user->sign_num == count($sign_list))
+            $res1 = self::setSignData($uid,'连续签到奖励',$sign_num,$user->integral);
+        else
+            $res1 = self::setSignData($uid,'用户累计签到第'.(self::getSignSumDay($uid)+1).'天',$sign_num,$user->integral);
+        $res2= User::bcInc($uid,'integral',$sign_num,'uid');
+        $res3=$user->save();
+        $res = $res1 && $res2 && $res3!==false;
+        ModelBasic::checkTrans($res);
+        HookService::afterListen('user_level',$user,false,UserBehavior::class);
+        if($res)
+            return $sign_num;
+        else
+            return false;
+    }
+
+    /*
+     * 获取签到列表按月加载
+     * @param int $uid 用户uid
+     * @param int $page 页码
+     * @param int $limit 显示多少条
+     * @return array
+     * */
+    public static function getSignMonthList($uid,$page=1,$limit=8)
+    {
+        $list=UserBill::where(['uid'=>$uid,'category'=>'integral','type'=>'sign'])->field(['FROM_UNIXTIME(add_time,"%Y-%m") as time','group_concat(id SEPARATOR ",") ids'])
+            ->group('time')->order('time asc')->page((int)$page,(int)$limit)->select();
+        $data=[];
+        foreach ($list as $item){
+            $value['month']=$item['time'];
+            $value['list']=UserBill::where('id','in',$item['ids'])->field(['FROM_UNIXTIME(add_time,"%Y-%m-%d") as add_time','title','number'])->select();
+            array_push($data,$value);
+        }
+        $page++;
+        return compact('data','page');
+    }
+}

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
application/core/model/user/UserTaskFinish.php


+ 131 - 0
application/core/traits/LogicTrait.php

@@ -0,0 +1,131 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/9 16:50
+ */
+
+namespace app\core\traits;
+
+trait LogicTrait
+{
+
+    protected $items = [];
+
+    /*
+     * 魔术方法 对不可访问或不存在的属性调用
+     *
+     * */
+    public function __isset($name)
+    {
+
+    }
+
+    /*
+     * 魔术方法 对不可访问或不存在的属性进行unset时被调用
+     * */
+    public function __unset($name)
+    {
+
+    }
+
+    /*
+     * 静态方法调用
+     * @param  string $method 调用方法
+     * @param  mixed  $args   参数
+     * */
+    public static function __callStatic($method,$args)
+    {
+
+    }
+
+    /*
+     * 执行本类的方法
+     * @param string $carryoutname 方法名
+     * @return boolean
+     * */
+    public static function CarryOut($carryoutname)
+    {
+        $methords = get_class_methods(self::class);
+        if(!in_array($carryoutname,$methords)) return false;
+        try{
+            return (new self)->$carryoutname();
+        }catch (\Exception $e){
+            return false;
+        }
+    }
+
+    /*
+     * 配置参数
+     *
+     * */
+    protected function setConfig(array $config=[])
+    {
+        foreach ($config as $key => $value) {
+            $this->set($this->items,$key, $value);
+        }
+    }
+
+    /*
+     * 设置参数
+     * @param array $array
+     * @param string $key
+     * @param string $value
+     * */
+    protected function set(&$array, $key, $value)
+    {
+        if (is_null($key)) return $array = $value;
+        $keys = explode('.', $key);
+        while (count($keys) > 1) {
+            $key = array_shift($keys);
+            if (!isset($array[$key]) || !is_array($array[$key])) {
+                $array[$key] = [];
+            }
+            $array = &$array[$key];
+        }
+        $array[array_shift($keys)] = $value;
+        return $array;
+    }
+
+    /*
+     * 实例化类
+     *
+     * */
+    protected function registerProviders()
+    {
+        foreach ($this->providers as $key=>$provider)
+        {
+            $this->register(new $provider(),$key);
+        }
+    }
+
+    /*
+     * 获取类内配置信息
+     * @param object $pimple
+     * @return this
+     * */
+    protected function register($pimple,$key)
+    {
+        $response=$pimple->register($this->items);
+        if(is_array($response)) {
+            list($key,$provider)=$response;
+            $this->$key= $provider;
+        }else if(is_string($key)){
+            $this->$key= $pimple;
+        }
+        return $this;
+    }
+
+    /*
+     * 实例化本类
+     * @param array $config
+     * @return this
+     * */
+    public static function instance($config=[])
+    {
+        $that=new self();
+        $that->setConfig($config);
+        $that->registerProviders();
+        return $that;
+    }
+}

+ 110 - 0
application/core/util/ApiLogs.php

@@ -0,0 +1,110 @@
+<?php
+/**
+ * Created by CRMEB.
+ * User: 136327134@qq.com
+ * Date: 2019/4/12 11:19
+ */
+
+namespace app\core\util;
+
+/*
+ * Api 日志和系统字段整合
+ * class ApiLogs
+ * */
+
+use think\Exception;
+use think\Log;
+
+class ApiLogs
+{
+    // +----------------------------------------------------------------------
+    // | 缓存前缀配置区域
+    // +----------------------------------------------------------------------
+    //ACCESS_TOKEN缓存前缀
+    const ACCESS_TOKEN_PREFIX='AccessToken:';
+    //api info 缓存前缀
+    const AB_API_INFO='eb_ApiInfo:';
+
+    // +----------------------------------------------------------------------
+    // | 缓存时间配置区域
+    // +----------------------------------------------------------------------
+    //缓存时间
+    const  EXPIRE=86400;
+
+    // +----------------------------------------------------------------------
+    // | 系统预设字段明配置区域
+    // +----------------------------------------------------------------------
+    //access-token验证字段
+    const ACCESS_TOKEN="access-token";
+    //Api版本字段
+    const API_VERSION='version';
+    //用户token验证字段
+    const USER_TOKEN='user-token';
+    //系统预设日志
+    protected static $logInfo=null;
+    /*
+     * 获取本类所有常量配置
+     * @param string $code 常量名
+     * @return array | string
+     * */
+    public static function getConstants($code='') {
+        $oClass = new \ReflectionClass(__CLASS__);
+        $stants=$oClass->getConstants();
+        if($code) return isset($stants[$code]) ? $stants[$code] : '';
+        else return $stants;
+    }
+
+    /*
+     * 错误日志记录
+     *
+     * */
+    public static function recodeErrorLog(Exception $exception)
+    {
+        $data=[
+            'code'=>$exception->getCode(),
+            'msg'=>$exception->getMessage(),
+            'file'=>$exception->getFile(),
+            'line'=>$exception->getLine(),
+        ];
+        $log="[{$data['code']}] {$data['msg']} [{$data['file']} : {$data['line']}]";
+        self::writeLog($log,'e');
+    }
+    /*
+     * 记录日志
+     * $param string $contentlog 日志内容
+     * $param string $typeLog 日志类型
+     * $param string $dirLog 日志目录
+     * */
+    public static function writeLog($contentlog='',$typeLog='',$dirLog='ebapi')
+    {
+        Log::init([
+            'type'   => 'File',
+            'path'   => LOG_PATH.($dirLog ? $dirLog.'/' : '')
+        ]);
+        if($contentlog==='') $contentlog=self::$logInfo;
+        if($contentlog===null) return false;
+        if(is_array($contentlog)) $contentlog=var_export($contentlog,true);
+        if(is_object($contentlog)) $contentlog=var_export($contentlog,true);
+        switch (strtoupper($typeLog)){
+            case 'SQL':case 'S':
+                Log::sql($contentlog);
+                break;
+            case 'ERROR':case 'E':
+                Log::error($contentlog);
+                break;
+            case 'INFO':case 'I':
+                Log::info($contentlog);
+                break;
+            case 'NOTICE':case 'N':
+                Log::notice($contentlog);
+                break;
+            case 'ALERT':case 'A':
+                Log::alert($contentlog);
+                break;
+            case 'LOG':case 'L':
+                Log::log($contentlog);
+                break;
+        }
+    }
+
+}

+ 67 - 0
application/core/util/GroupDataService.php

@@ -0,0 +1,67 @@
+<?php
+/**
+ *
+ * @author: xaboy<365615158@qq.com>
+ * @day: 2018/01/15
+ */
+
+namespace app\core\util;
+
+
+use app\admin\model\system\SystemGroupData;
+use think\Cache;
+
+class GroupDataService
+{
+    protected static $isCaChe=true;
+    /**获取单个组数据
+     * @param $config_name
+     * @param int $limit
+     * @return array|bool|false|\PDOStatement|string|\think\Model
+     */
+    public static function getGroupData($config_name,$limit = 0)
+    {
+        $cacheName=$limit ? $config_name.'_'.$limit : $config_name;
+        if(Cache::has($cacheName)){
+            return Cache::get($cacheName);
+        }else {
+            $data=SystemGroupData::getGroupData($config_name, $limit);
+            if(self::$isCaChe) Cache::set($cacheName,$data);
+            return $data;
+        }
+    }
+
+    /**获取单个值
+     * @param $config_name
+     * @param int $limit
+     * @return mixed
+     */
+    public static function getData($config_name,$limit = 0)
+    {
+        $cacheName=$limit ? $config_name.'_'.$limit : $config_name;
+        if(Cache::has($cacheName)){
+            return Cache::get($cacheName);
+        }else{
+            $data=SystemGroupData::getAllValue($config_name,$limit);
+            if(self::$isCaChe) Cache::set($cacheName,$data);
+            return $data;
+        }
+    }
+
+    /**
+     * TODO 获取单个值 根据id
+     * @param $id
+     * @return mixed
+     */
+    public static function getDataNumber($id,$cacheA='eb_data_')
+    {
+        $cacheName=$cacheA.$id;
+        if(Cache::has($cacheName)){
+            return Cache::get($cacheName);
+        }else {
+            $data=SystemGroupData::getDateValue($id);
+            if(self::$isCaChe) Cache::set($cacheName,$data);
+            return $data;
+        }
+    }
+}

+ 314 - 0
application/core/util/MiniProgramService.php

@@ -0,0 +1,314 @@
+<?php
+/**
+ *
+ * @author: xaboy<365615158@qq.com>
+ * @day: 2017/11/23
+ */
+
+namespace app\core\util;
+
+use app\core\behavior\PaymentBehavior;
+use EasyWeChat\Foundation\Application;
+use EasyWeChat\Payment\Order;
+use think\Url;
+use service\HookService;
+use app\core\implement\ProviderInterface;
+
+/**微信小程序接口
+ * Class WechatMinService
+ * @package service
+ */
+class MiniProgramService implements ProviderInterface
+{
+    private static $instance = null;
+
+    public function register($config)
+    {
+        return ['mini_program',new self()];
+    }
+
+    public static function options()
+    {
+        $wechat = SystemConfigService::more(['site_url','routine_appId','routine_appsecret']);
+        $payment = SystemConfigService::more(['pay_routine_mchid','pay_routine_key','pay_routine_client_cert','pay_routine_client_key','pay_weixin_open']);
+        $config = [];
+        $config['mini_program'] = [
+            'app_id'=>isset($wechat['routine_appId']) ? $wechat['routine_appId']:'',
+            'secret'=>isset($wechat['routine_appsecret']) ? $wechat['routine_appsecret']:'',
+            'token'=>isset($wechat['wechat_token']) ? $wechat['wechat_token']:'',
+            'aes_key'=> isset($wechat['wechat_encodingaeskey']) ? $wechat['wechat_encodingaeskey']:''
+        ];
+        if(isset($payment['pay_weixin_open']) && $payment['pay_weixin_open'] == 1){
+            $config['payment'] = [
+                'app_id'=>isset($wechat['routine_appId']) ? $wechat['routine_appId']:'',
+                'merchant_id'=>$payment['pay_routine_mchid'],
+                'key'=>$payment['pay_routine_key'],
+                'cert_path'=>realpath('.'.$payment['pay_routine_client_cert']),
+                'key_path'=>realpath('.'.$payment['pay_routine_client_key']),
+                'notify_url'=>$wechat['site_url'].Url::build('/ebapi/notify/notify',['notify_type'=>'routine'])
+            ];
+        }
+        return $config;
+    }
+    public static function application($cache = false)
+    {
+        (self::$instance === null || $cache === true) && (self::$instance = new Application(self::options()));
+        return self::$instance;
+    }
+    /**
+     * 小程序接口
+     * @return \EasyWeChat\MiniProgram\MiniProgram
+     */
+    public static function miniprogram()
+    {
+        return self::application()->mini_program;
+    }
+
+    /**
+     * 获得用户信息 根据code 获取session_key
+     * @param array|string $openid
+     * @return $userInfo
+     */
+    public static function getUserInfo($code)
+    {
+        $userInfo = self::miniprogram()->sns->getSessionKey($code);
+        return $userInfo;
+    }
+
+    /**
+     * 加密数据解密
+     * @param $sessionKey
+     * @param $iv
+     * @param $encryptData
+     * @return $userInfo
+     */
+    public static function encryptor($sessionKey, $iv, $encryptData){
+        return self::miniprogram()->encryptor->decryptData($sessionKey, $iv, $encryptData);
+    }
+
+    /**
+     * 上传临时素材接口
+     * @return \EasyWeChat\Material\Temporary
+     */
+    public static function materialTemporaryService()
+    {
+        return self::miniprogram()->material_temporary;
+    }
+
+    /**
+     * 客服消息接口
+     * @param null $to
+     * @param null $message
+     */
+    public static function staffService()
+    {
+        return self::miniprogram()->staff;
+    }
+
+    /**
+     * 微信小程序二维码生成接口
+     * @return \EasyWeChat\QRCode\QRCode
+     */
+    public static function qrcodeService()
+    {
+        return self::miniprogram()->qrcode;
+    }
+
+    /**微信小程序二维码生成接口不限量永久
+     * @param $scene
+     * @param null $page
+     * @param null $width
+     * @param null $autoColor
+     * @param array $lineColor
+     * @return \Psr\Http\Message\StreamInterface
+     */
+    public static function appCodeUnlimitService($scene, $page = null, $width = 430, $autoColor = false, $lineColor = ['r' => 0, 'g' => 0, 'b' => 0])
+    {
+        return self::qrcodeService()->appCodeUnlimit($scene,$page,$width,$autoColor,$lineColor);
+    }
+
+
+    /**
+     * 模板消息接口
+     * @return \EasyWeChat\Notice\Notice
+     */
+    public static function noticeService()
+    {
+        return self::miniprogram()->notice;
+    }
+
+    /**发送小程序模版消息
+     * @param $openid
+     * @param $templateId
+     * @param array $data
+     * @param null $url
+     * @param null $defaultColor
+     * @return mixed
+     */
+    public static function sendTemplate($openid,$templateId,array $data,$form_id,$link = null,$defaultColor = null)
+    {
+        $notice = self::noticeService()->to($openid)->template($templateId)->formId($form_id)->andData($data);
+        $message = [];
+        if($link !== null) $message = ['page'=>$link];
+        if($defaultColor !== null) $notice->defaultColor($defaultColor);
+        return $notice->send($message);
+    }
+
+
+    /**
+     * 支付
+     * @return \EasyWeChat\Payment\Payment
+     */
+    public static function paymentService()
+    {
+        return self::application()->payment;
+    }
+
+    /**
+     * 生成支付订单对象
+     * @param $openid
+     * @param $out_trade_no
+     * @param $total_fee
+     * @param $attach
+     * @param $body
+     * @param string $detail
+     * @param string $trade_type
+     * @param array $options
+     * @return Order
+     */
+    protected static function paymentOrder($openid,$out_trade_no,$total_fee,$attach,$body,$detail='',$trade_type='JSAPI',$options = [])
+    {
+        $total_fee = bcmul($total_fee,100,0);
+        $order = array_merge(compact('openid','out_trade_no','total_fee','attach','body','detail','trade_type'),$options);
+        if($order['detail'] == '') unset($order['detail']);
+        return new Order($order);
+    }
+
+    /**
+     * 获得下单ID
+     * @param $openid
+     * @param $out_trade_no
+     * @param $total_fee
+     * @param $attach
+     * @param $body
+     * @param string $detail
+     * @param string $trade_type
+     * @param array $options
+     * @return mixed
+     */
+    public static function paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail='', $trade_type='JSAPI', $options = [])
+    {
+        $order = self::paymentOrder($openid,$out_trade_no,$total_fee,$attach,$body,$detail,$trade_type,$options);
+        $result = self::paymentService()->prepare($order);
+        if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
+            try{
+                HookService::listen('wechat_payment_prepare_program',$order,$result->prepay_id,false,PaymentBehavior::class);
+            }catch (\Exception $e){}
+            return $result->prepay_id;
+        }else{
+            if($result->return_code == 'FAIL'){
+                exception('微信支付错误返回:'.$result->return_msg);
+            }else if(isset($result->err_code)){
+                exception('微信支付错误返回:'.$result->err_code_des);
+            }else{
+                exception('没有获取微信支付的预支付ID,请重新发起支付!');
+            }
+            exit;
+        }
+
+    }
+
+    /**
+     * 获得jsSdk支付参数
+     * @param $openid
+     * @param $out_trade_no
+     * @param $total_fee
+     * @param $attach
+     * @param $body
+     * @param string $detail
+     * @param string $trade_type
+     * @param array $options
+     * @return array|string
+     */
+    public static function jsPay($openid, $out_trade_no, $total_fee, $attach, $body, $detail='', $trade_type='JSAPI', $options = [])
+    {
+        return self::paymentService()->configForJSSDKPayment(self::paymentPrepare($openid,$out_trade_no,$total_fee,$attach,$body,$detail,$trade_type,$options));
+    }
+
+    /**
+     * 使用商户订单号退款
+     * @param $orderNo
+     * @param $refundNo
+     * @param $totalFee
+     * @param null $refundFee
+     * @param null $opUserId
+     * @param string $refundReason
+     * @param string $type
+     * @param string $refundAccount
+     */
+    public static function refund($orderNo, $refundNo, $totalFee, $refundFee = null, $opUserId = null, $refundReason = '' , $type = 'out_trade_no', $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS')
+    {
+        $totalFee = floatval($totalFee);
+        $refundFee = floatval($refundFee);
+        return self::paymentService()->refund($orderNo,$refundNo,$totalFee,$refundFee,$opUserId,$type,$refundAccount,$refundReason);
+    }
+
+    /** 根据订单号退款
+     * @param $orderNo
+     * @param array $opt
+     * @return bool
+     */
+    public static function payOrderRefund($orderNo, array $opt)
+    {
+        if(!isset($opt['pay_price'])) exception('缺少pay_price');
+        $totalFee = floatval(bcmul($opt['pay_price'],100,0));
+        $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'],100,0)) : null;
+        $refundReason = isset($opt['desc']) ? $opt['desc'] : '';
+        $refundNo = isset($opt['refund_id']) ? $opt['refund_id'] : $orderNo;
+        $opUserId = isset($opt['op_user_id']) ? $opt['op_user_id'] : null;
+        $type = isset($opt['type']) ? $opt['type'] : 'out_trade_no';
+        /*仅针对老资金流商户使用
+        REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款)
+        REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款*/
+        $refundAccount = isset($opt['refund_account']) ? $opt['refund_account'] : 'REFUND_SOURCE_UNSETTLED_FUNDS';
+        try{
+            $res = (self::refund($orderNo,$refundNo,$totalFee,$refundFee,$opUserId,$refundReason,$type,$refundAccount));
+            if($res->return_code == 'FAIL') exception('退款失败:'.$res->return_msg);
+            if(isset($res->err_code)) exception('退款失败:'.$res->err_code_des);
+        }catch (\Exception $e){
+            exception($e->getMessage());
+        }
+        return true;
+    }
+
+    /**
+     * 微信支付成功回调接口
+     */
+    public static function handleNotify()
+    {
+        self::paymentService()->handleNotify(function($notify, $successful){
+            if($successful && isset($notify->out_trade_no)){
+                return HookService::listen('wechat_pay_success',$notify,null,true,PaymentBehavior::class);
+            }
+        });
+    }
+
+    /**
+     * 作为客服消息发送
+     * @param $to
+     * @param $message
+     * @return bool
+     */
+    public static function staffTo($to, $message)
+    {
+        $staff = self::staffService();
+        $staff = is_callable($message) ? $staff->message($message()) : $staff->message($message);
+        $res = $staff->to($to)->send();
+        HookService::afterListen('wechat_staff_to',compact('to','message'),$res);
+        return $res;
+    }
+
+
+
+
+}

+ 202 - 0
application/core/util/ProgramTemplateService.php

@@ -0,0 +1,202 @@
+<?php
+namespace app\core\util;
+
+use app\admin\model\wechat\WechatUser;
+use app\admin\model\wechat\StoreService as ServiceModel;
+use app\core\implement\ProviderInterface;
+
+/**
+ * 小程序模板消息
+ * Class RoutineTemplate
+ * @package app\routine\model\routine
+ */
+class ProgramTemplateService implements ProviderInterface
+{
+    //订单支付成功
+    const ORDER_PAY_SUCCESS = 'AT0009';
+    //砍价成功
+    const BARGAIN_SUCCESS = 'AT1173';
+    //申请退款通知
+    const ORDER_REFUND_STATUS = 'AT0036';
+    //退款成功
+    const ORDER_REFUND_SUCCESS = 'AT0787';
+    //退款失败
+    const ORDER_REFUND_FILE = 'AT0329';
+    //订单发货提醒(快递)
+    const ORDER_POSTAGE_SUCCESS = 'AT0007';
+    //订单发货提醒(送货)
+    const ORDER_DELIVER_SUCCESS = 'AT0177';
+    //拼团取消通知
+    const PINK_REMOVE='AT2430';
+    //拼团失败
+    const PINK_Fill='AT0310';
+    //拼团成功
+    const PINK_TRUE='AT0051';
+    //开团成功
+    const OPEN_PINK_SUCCESS='AT0541';
+    //确认收货通知
+    const OREDER_TAKEVER='AT0241';
+
+    public static function getConstants($code='')
+    {
+        $oClass = new \ReflectionClass(__CLASS__);
+        $stants=$oClass->getConstants();
+        if($code) return isset($stants[$code]) ? $stants[$code] : '';
+        else return $stants;
+    }
+
+    public function register($config)
+    {
+
+    }
+
+    /**
+     * 根据模板编号获取模板ID
+     * @param string $tempKey
+     * @return mixed|string
+     */
+    public static function setTemplateId($tempKey = ''){
+        if($tempKey == '') return '';
+        return \think\Db::name('RoutineTemplate')->where('tempkey',$tempKey)->where('status',1)->value('tempid');
+    }
+
+    /**
+     * 发送模板消息
+     * @param string $tempCode 所需下发的模板编号
+     * @param string $openId   接收者(用户)的 openid
+     * @param array $dataKey 模板内容,不填则下发空模板
+     * @param string $formId 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id
+     * @param string $link 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
+     * @param string $emphasisKeyword 模板需要放大的关键词,不填则默认无放大
+     * @return bool|mixed
+     */
+    public static function sendTemplate($tempCode = '',$openId = '',$dataKey = array(),$formId = '',$link = '',$defaultColor=null)
+    {
+
+        if($openId == '' || $tempCode == '' || $formId == '') return false;
+        try{
+            return MiniProgramService::sendTemplate($openId,trim(self::setTemplateId(self::getConstants($tempCode))),$dataKey,$formId,$link,$defaultColor);
+        }catch (\Exception $e){
+           return false;
+        }
+
+    }
+
+    /**服务进度通知
+     * @param array $data
+     * @param null $url
+     * @param string $defaultColor
+     * @return bool
+     */
+    public static function sendAdminNoticeTemplate(array $data,$url = null,$defaultColor = '')
+    {
+        $adminIds = explode(',',trim(SystemConfigService::get('site_store_admin_uids')));
+        $kefuIds = ServiceModel::where('notify',1)->column('uid');
+        if(empty($adminIds[0])){
+            $adminList = array_unique($kefuIds);
+        }else{
+            $adminList = array_unique(array_merge($adminIds,$kefuIds));
+        }
+        if(!is_array($adminList) || empty($adminList)) return false;
+        foreach ($adminList as $uid){
+            try{
+                $openid = WechatUser::uidToRoutineOpenid($uid);
+            }catch (\Exception $e){
+                continue;
+            }
+//            self::sendTemplate($openid,self::ADMIN_NOTICE,$data,$url,$defaultColor);
+        }
+    }
+
+    /**
+     * 返回所有支持的行业列表
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function getIndustry()
+    {
+        return MiniProgramService::noticeService()->getIndustry();
+    }
+
+    /**
+     * 修改账号所属行业
+     * 主行业	副行业	代码
+     * IT科技	互联网/电子商务	1
+     * IT科技	IT软件与服务	2
+     * IT科技	IT硬件与设备	3
+     * IT科技	电子技术	4
+     * IT科技	通信与运营商	5
+     * IT科技	网络游戏	6
+     * 金融业	银行	7
+     * 金融业	基金|理财|信托	8
+     * 金融业	保险	9
+     * 餐饮	餐饮	10
+     * 酒店旅游	酒店	11
+     * 酒店旅游	旅游	12
+     * 运输与仓储	快递	13
+     * 运输与仓储	物流	14
+     * 运输与仓储	仓储	15
+     * 教育	培训	16
+     * 教育	院校	17
+     * 政府与公共事业	学术科研	18
+     * 政府与公共事业	交警	19
+     * 政府与公共事业	博物馆	20
+     * 政府与公共事业	公共事业|非盈利机构	21
+     * 医药护理	医药医疗	22
+     * 医药护理	护理美容	23
+     * 医药护理	保健与卫生	24
+     * 交通工具	汽车相关	25
+     * 交通工具	摩托车相关	26
+     * 交通工具	火车相关	27
+     * 交通工具	飞机相关	28
+     * 房地产	建筑	29
+     * 房地产	物业	30
+     * 消费品	消费品	31
+     * 商业服务	法律	32
+     * 商业服务	会展	33
+     * 商业服务	中介服务	34
+     * 商业服务	认证	35
+     * 商业服务	审计	36
+     * 文体娱乐	传媒	37
+     * 文体娱乐	体育	38
+     * 文体娱乐	娱乐休闲	39
+     * 印刷	印刷	40
+     * 其它	其它	41
+     * @param $industryId1
+     * @param $industryId2
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function setIndustry($industryId1, $industryId2)
+    {
+        return MiniProgramService::noticeService()->setIndustry($industryId1, $industryId2);
+    }
+
+    /**
+     * 获取所有模板列表
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function getPrivateTemplates()
+    {
+        return MiniProgramService::noticeService()->getPrivateTemplates();
+    }
+
+    /**
+     * 删除指定ID的模板
+     * @param $templateId
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function deletePrivateTemplate($templateId)
+    {
+        return MiniProgramService::noticeService()->deletePrivateTemplate($templateId);
+    }
+
+
+    /**
+     * 添加模板并获取模板ID
+     * @param $shortId
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function addTemplate($shortId)
+    {
+        return MiniProgramService::noticeService()->addTemplate($shortId);
+    }
+}

+ 36 - 0
application/core/util/QrcodeService.php

@@ -0,0 +1,36 @@
+<?php
+/**
+ *
+ * @author: xaboy<365615158@qq.com>
+ * @day: 2017/10/24
+ */
+
+namespace app\core\util;
+
+
+use app\admin\model\wechat\WechatQrcode as QrcodeModel;
+
+class QrcodeService
+{
+    /**
+     * 获取临时二维码  单个
+     * */
+     public static function getTemporaryQrcode($type,$id){
+         return QrcodeModel::getTemporaryQrcode($type,$id)->toArray();
+     }/**
+     * 获取永久二维码  单个
+     * */
+     public static function getForeverQrcode($type,$id){
+         return QrcodeModel::getForeverQrcode($type,$id)->toArray();
+     }
+
+     public static function getQrcode($id,$type = 'id')
+     {
+        return QrcodeModel::getQrcode($id,$type);
+     }
+
+     public static function scanQrcode($id,$type = 'id')
+     {
+         return QrcodeModel::scanQrcode($id,$type);
+     }
+}

+ 41 - 0
application/core/util/ReturnCode.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * Created by CRMEB.
+ * Copyright (c) 2017~2019 http://www.crmeb.com All rights reserved.
+ * Author: liaofei <136327134@qq.com>
+ * Date: 2019/4/3 16:36
+ */
+
+namespace app\core\util;
+
+class ReturnCode
+{
+    //操作成功
+    const SUCCESS = 200;
+    //普通错误
+    const ERROR = 400;
+    //系统错误
+    const SYSTEM_ERROR=405;
+    //用户token验证成功,用户信息获取失败
+    const USER_TOKEN_ERROR=402;
+    //用户被禁止登录
+    const USER_STATUS_ERROR=402;
+    //access_token验证失效
+    const ACCESS_TOKEN_TIMEOUT=-100;
+    //数据库保存失败
+    const DB_SAVE_ERROR = -1;
+    //数据库查询失败
+    const DB_READ_ERROR = -2;
+    //api版本号不存在
+    const EMPTY_PARAMS = -3;
+    //api版本号不匹配
+    const VERSION_INVALID = -4;
+
+    public static function getConstants($code='') {
+        $oClass = new \ReflectionClass(__CLASS__);
+        $stants=$oClass->getConstants();
+        if($code) return isset($stants[$code]) ? $stants[$code] : '';
+        else return $stants;
+    }
+
+}

+ 64 - 0
application/core/util/SystemConfigService.php

@@ -0,0 +1,64 @@
+<?php
+/**
+ *
+ * @author: xaboy<365615158@qq.com>
+ * @day: 2017/11/23
+ */
+
+namespace app\core\util;
+
+
+use app\admin\model\system\SystemConfig;
+
+/** 获取系统配置服务类
+ * Class SystemConfigService
+ * @package service
+ */
+class SystemConfigService
+{
+    protected static $configList = null;
+
+    public static $ProtectedKey=[
+        'wechat_appid','wechat_appsecret','wechat_token','wechat_encodingaeskey','wechat_encode',
+        'pay_weixin_mchid','pay_weixin_client_cert','pay_weixin_client_key','pay_weixin_key','pay_weixin_open',
+        'routine_appId','routine_appsecret',
+        'pay_routine_mchid','pay_routine_key','pay_routine_client_cert','pay_routine_client_key','pay_weixin_open'
+    ];
+
+    /**获取系统配置
+     * @param $key
+     * @return mixed|null
+     */
+    public static function config($key)
+    {
+        if(self::$configList === null) self::$configList = self::getAll();
+        return isset(self::$configList[$key]) ? self::$configList[$key] : null;
+    }
+
+    /**获取单个配置效率更高
+     * @param $key
+     * @return bool|mixed
+     */
+    public static function get($key)
+    {
+        return SystemConfig::getValue($key);
+    }
+
+    /** 获取多个配置
+     * @param $keys ',' 隔开
+     * @return array
+     */
+    public static function more($keys)
+    {
+        return SystemConfig::getMore($keys);
+    }
+
+    /**获取全部配置
+     * @return array
+     */
+    public static function getAll()
+    {
+        return SystemConfig::getAllConfig()?:[];
+    }
+
+}

+ 25 - 0
application/core/util/Template.php

@@ -0,0 +1,25 @@
+<?php
+/**
+ * Created by CRMEB.
+ * Copyright (c) 2017~2019 http://www.crmeb.com All rights reserved.
+ * Author: liaofei <136327134@qq.com>
+ * Date: 2019/4/3 16:36
+ */
+
+namespace app\core\util;
+
+use app\core\traits\LogicTrait;
+
+/** 模版消息类
+ * Class Template
+ * @package app\core\util
+ */
+class Template
+{
+    use LogicTrait;
+
+    protected  $providers=[
+        'routine_two'=>ProgramTemplateService::class,
+    ];
+
+}

+ 237 - 0
application/core/util/TokenService.php

@@ -0,0 +1,237 @@
+<?php
+namespace app\core\util;
+
+use app\core\model\routine\Token;
+use service\CacheService;
+
+class TokenService
+{
+    //加密分割key
+    private static $KEY='fb';
+    //10位加密key
+    private static $sKey='crmeb12345';
+    //相隔付
+    private static $seperater = "{&&}";
+    //是否开启辅助验证
+    private static $isAuxiliary=false;
+    //加密方式 为空为普通加密
+    private static $encryptType='DES';
+    //实例化类
+    private static $instance=null;
+    //构造单例模式
+    private function __construct()
+    {
+
+    }
+    /*
+     * 初始化类
+     * @return object
+     * */
+    public static function instance()
+    {
+        if(is_null(self::$instance)) self::$instance=new self();
+        return self::$instance;
+    }
+
+    /*
+     * 设置加密方式
+     * @param $encryptType 加密类型
+     * */
+    public function setEncryptType($encryptType='DES')
+    {
+        self::$encryptType=$encryptType;
+    }
+    /*
+     * 验证token
+     * @param string $token token
+     * @param boolean $isSkip 是否跳过验证
+     * @return Boolean | array
+     * */
+    public static function checkToken($token,$isSkip=false)
+    {
+        self::InitSkey();
+        //跳过验证
+        if($isSkip && !$token) return true;
+        //解密token
+        if(strtolower(self::$encryptType)==='des'){
+            $data=explode(self::$seperater,self::DesDecrypt($token));
+        }else{
+            $data=explode(self::$seperater,self::deCode($token));
+        }
+        //验证是否为数组 数组length为6
+        if(is_array($data) && count($data) == 7){
+            //第一位不能为空
+            if(empty($data[0])) return false;
+            //验证公钥是否被篡改
+            if($data[3]!=self::$sKey) return false;
+            //验证token是否过期
+            if((int)$data[5]<time()) return false;
+            //验证当前用户加密的随机字符串
+            if(self::$isAuxiliary===true) if(!Token::checkRandString($data[0],$data[2])) return false;
+            //返回第一位和二位数据
+            return [$data[0],$data[1]];
+        }
+        return false;
+    }
+
+    /*
+      * 获取token
+      * @param string $string 加密字符串
+      * @param string $openid 加密openid
+      * @param int $valid_peroid token过期时间默认5天 259200
+      * @param string $randstring 随机字符串提供辅助验证token
+      * @return token
+      * */
+    public static function getToken($string=1,$openid='0',$randstring='0',$valid_peroid=259200)
+    {
+        self::InitSkey();
+        if(self::$isAuxiliary===true) {
+            $randstring = self::createNonceStr();
+            $res = Token::SetRandString($string, $randstring);
+            if (!$res) return false;
+        }
+        return self::enToken($string,$openid,$randstring,$valid_peroid);
+    }
+
+    /*
+     * 获取token公钥并缓存
+     * @param boolean $debuy 是否为调试模式
+     * @param int $default 默认缓存时效
+     * */
+    private static function InitSkey($debuy=true,$default=3600)
+    {
+        if($token_skey=CacheService::get('token_skey'))
+            self::$sKey=$token_skey;
+        else{
+            $token_skey=SystemConfigService::get('token_skey');
+            if(!$token_skey && $debuy===false) exception('请先配置小程序访问TO_kEN [token_skey] 公钥');
+            if($token_skey){
+                CacheService::set('token_skey',$token_skey,$default);
+                self::$sKey=$token_skey;
+            }
+        }
+    }
+
+    /*
+     * 加密token字符串
+     * @param string $string 加密字符串
+     * @param string $openid 加密openid
+     * @param int $valid_peroid token过期时间默认5天
+     * @return token
+     * */
+    private static function enToken($string,$openid='0',$randString='',$valid_peroid=259200)
+    {
+        //加密字符串 + 相隔付 + openid + 相隔付 + 随机字符串 + 相隔付 +  加密字符串 + 相隔付 + 当前时间 + 相隔付 + token过期时间 + 相隔付
+        $to_ken=$string.self::$seperater.
+            $openid.self::$seperater.
+            $randString.self::$seperater.
+            self::$sKey.self::$seperater.
+            time().self::$seperater.
+            (time()+$valid_peroid).self::$seperater;
+        if(strtolower(self::$encryptType)==='des'){
+            $token=self::DesNncrypt($to_ken);
+        }else {
+            $token = self::enCode($to_ken);
+        }
+        return $token;
+    }
+
+    /**
+     * 通用加密
+     * @param String $string 需要加密的字串
+     * @return String
+     */
+    private static function enCode($string) {
+        $skey = array_reverse(str_split(self::$KEY));
+        $strArr = str_split(base64_encode($string));
+        $strCount = count($strArr);
+        foreach ($skey as $key => $value) {
+            $key < $strCount && $strArr[$key].=$value;
+        }
+        return str_replace('=', 'O0O0O', join('', $strArr));
+    }
+
+    /**
+     * 通用解密
+     * @param String $string 需要解密的字串
+     * @param String $skey 解密KEY
+     * @return String
+     */
+    private static function deCode($string) {
+        $skey = array_reverse(str_split(self::$KEY));
+        $strArr = str_split(str_replace('O0O0O', '=', $string), 2);
+        $strCount = count($strArr);
+        foreach ($skey as $key => $value) {
+            $key < $strCount && $strArr[$key] = rtrim($strArr[$key], $value);
+        }
+        return base64_decode(join('', $strArr));
+    }
+
+    /*
+     *  DES 加密
+     *  @param string $data 待加密明文
+     *  @param string $deskey 加密秘钥
+     *  @return string
+     **/
+    private static function DesNncrypt($data, $key='')
+    {
+        $deskey=$key=='' ? self::$sKey : $key;
+        if(strlen($deskey) > 8) $deskey=substr($deskey,0,8);//php加密秘钥只能为8位
+        if(function_exists('openssl_encrypt')){
+            $data = openssl_encrypt($data, 'AES-128-ECB', $deskey, OPENSSL_RAW_DATA);
+            $data = strtolower(bin2hex($data));
+            return $data;
+        }else{
+            $blocksize = mcrypt_get_block_size(MCRYPT_DES,MCRYPT_MODE_ECB);
+            $pad = $blocksize - (strlen($data) % $blocksize);
+            $data1 = $data. str_repeat(chr($pad),$pad);
+            $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_ECB),MCRYPT_RAND); //初始化向量
+            $data_encrypt  = mcrypt_encrypt(MCRYPT_DES,$deskey,$data1,MCRYPT_MODE_ECB);//加密函数
+            $datastr = bin2hex($data_encrypt);
+            return $datastr;
+        }
+
+    }
+    /*
+     *  DES 解密
+     *  @param string $data 待解密密文
+     *  @param string $deskey 加密秘钥
+     *  @return string
+     */
+    private static function DesDecrypt($endata,$deskey=''){
+        $deskey=$deskey=='' ? self::$sKey : $deskey;
+        if(strlen($deskey) > 8) $deskey=substr($deskey,0,8);//php加密秘钥只能为8位
+        if(function_exists('openssl_encrypt')){
+            $decrypted = openssl_decrypt(hex2bin($endata), 'AES-128-ECB', $deskey, OPENSSL_RAW_DATA);
+            return $decrypted;
+        }else{
+            $de_datastr = $endata !== false && preg_match('/^[0-9a-fA-F]+$/i',$endata) ? pack('H*',$endata):false;
+            $data_decrypt = mcrypt_decrypt(MCRYPT_DES,$deskey,$de_datastr,MCRYPT_MODE_ECB,null);//解密函数
+            $ret = self::_pkcs5Unpad($data_decrypt);
+            $de_data = trim($ret);
+            return $de_data;
+        }
+    }
+
+    private static function _pkcs5Unpad($text){
+        $pad = ord($text{strlen($text)-1});
+        if($pad > strlen($text)) return false;
+        if(strspn($text,chr($pad),strlen($text)-$pad) != $pad) return false;
+        $ret = substr($text,0,-1*$pad);
+        return trim($ret);
+    }
+    /**
+     * 生成随机填充码
+     * @return string 10位
+     * @return string
+     */
+    private static function createNonceStr($length = 5)
+    {
+        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+        $str = "";
+        for ($i = 0; $i < $length; $i++) {
+            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
+        }
+        return "crmeb".$str;
+    }
+}

Разница между файлами не показана из-за своего большого размера
+ 559 - 0
application/core/util/WechatService.php


+ 189 - 0
application/core/util/WechatTemplateService.php

@@ -0,0 +1,189 @@
+<?php
+/**
+ *
+ * @author: xaboy<365615158@qq.com>
+ * @day: 2018/01/06
+ */
+
+namespace app\core\util;
+
+use app\wap\model\user\WechatUser;
+use app\admin\model\wechat\WechatTemplate as WechatTemplateModel;//待完善
+use app\admin\model\wechat\StoreService as ServiceModel;
+
+class WechatTemplateService
+{
+    /**
+     * 主营行业:IT科技 互联网|电子商务
+     * 副营行业:IT科技 IT软件与服务
+     */
+
+    //订单生成通知
+    const ORDER_CREATE = 'OPENTM205213550';
+
+    //订单支付成功
+    const ORDER_PAY_SUCCESS = 'OPENTM207791277';
+
+    //订单发货提醒(快递)
+    const ORDER_POSTAGE_SUCCESS = 'OPENTM200565259';
+
+    //订单发货提醒(送货)
+    const ORDER_DELIVER_SUCCESS = 'OPENTM207707249';
+
+    //订单收货通知
+    const ORDER_TAKE_SUCCESS = 'OPENTM413386489';
+
+    //退款进度通知
+    const ORDER_REFUND_STATUS = 'OPENTM410119152';
+
+    //帐户资金变动提醒
+    const USER_BALANCE_CHANGE = 'OPENTM405847076';
+
+    //客服通知提醒
+    const SERVICE_NOTICE = 'OPENTM204431262';
+
+    //服务进度提醒
+    const ADMIN_NOTICE = 'OPENTM408237350';
+
+    //拼团成功通知
+    const ORDER_USER_GROUPS_SUCCESS = 'OPENTM407456411';
+
+    //拼团失败通知
+    const ORDER_USER_GROUPS_LOSE   = 'OPENTM401113750';
+
+    public static function getConstants($code='') {
+        $oClass = new \ReflectionClass(__CLASS__);
+        $stants=$oClass->getConstants();
+        if($code) return isset($stants[$code]) ? $stants[$code] : '';
+        else return $stants;
+    }
+
+    public static function sendTemplate($openid,$templateId,array $data,$url = null,$defaultColor = '')
+    {
+        $tempid = WechatTemplateModel::where('tempkey',$templateId)->where('status',1)->value('tempid');
+        if(!$tempid) return false;
+        try{
+            return WechatService::sendTemplate($openid,$tempid,$data,$url,$defaultColor);
+        }catch (\Exception $e){
+            return false;
+        }
+    }
+
+    /**服务进度通知
+     * @param array $data
+     * @param null $url
+     * @param string $defaultColor
+     * @return bool
+     */
+    public static function sendAdminNoticeTemplate(array $data,$url = null,$defaultColor = '')
+    {
+        $adminIds = explode(',',trim(SystemConfigService::get('site_store_admin_uids')));
+        $kefuIds = ServiceModel::where('notify',1)->column('uid');
+        if(empty($adminIds[0])){
+            $adminList = array_unique($kefuIds);
+        }else{
+            $adminList = array_unique(array_merge($adminIds,$kefuIds));
+        }
+        if(!is_array($adminList) || empty($adminList)) return false;
+        foreach ($adminList as $uid){
+            try{
+                $openid = WechatUser::uidToOpenid($uid);
+            }catch (\Exception $e){
+                continue;
+            }
+            self::sendTemplate($openid,self::ADMIN_NOTICE,$data,$url,$defaultColor);
+        }
+    }
+
+    /**
+     * 返回所有支持的行业列表
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function getIndustry()
+    {
+        return WechatService::noticeService()->getIndustry();
+    }
+
+    /**
+     * 修改账号所属行业
+     * 主行业	副行业	代码
+     * IT科技	互联网/电子商务	1
+     * IT科技	IT软件与服务	2
+     * IT科技	IT硬件与设备	3
+     * IT科技	电子技术	4
+     * IT科技	通信与运营商	5
+     * IT科技	网络游戏	6
+     * 金融业	银行	7
+     * 金融业	基金|理财|信托	8
+     * 金融业	保险	9
+     * 餐饮	餐饮	10
+     * 酒店旅游	酒店	11
+     * 酒店旅游	旅游	12
+     * 运输与仓储	快递	13
+     * 运输与仓储	物流	14
+     * 运输与仓储	仓储	15
+     * 教育	培训	16
+     * 教育	院校	17
+     * 政府与公共事业	学术科研	18
+     * 政府与公共事业	交警	19
+     * 政府与公共事业	博物馆	20
+     * 政府与公共事业	公共事业|非盈利机构	21
+     * 医药护理	医药医疗	22
+     * 医药护理	护理美容	23
+     * 医药护理	保健与卫生	24
+     * 交通工具	汽车相关	25
+     * 交通工具	摩托车相关	26
+     * 交通工具	火车相关	27
+     * 交通工具	飞机相关	28
+     * 房地产	建筑	29
+     * 房地产	物业	30
+     * 消费品	消费品	31
+     * 商业服务	法律	32
+     * 商业服务	会展	33
+     * 商业服务	中介服务	34
+     * 商业服务	认证	35
+     * 商业服务	审计	36
+     * 文体娱乐	传媒	37
+     * 文体娱乐	体育	38
+     * 文体娱乐	娱乐休闲	39
+     * 印刷	印刷	40
+     * 其它	其它	41
+     * @param $industryId1
+     * @param $industryId2
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function setIndustry($industryId1, $industryId2)
+    {
+        return WechatService::noticeService()->setIndustry($industryId1, $industryId2);
+    }
+
+    /**
+     * 获取所有模板列表
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function getPrivateTemplates()
+    {
+        return WechatService::noticeService()->getPrivateTemplates();
+    }
+
+    /**
+     * 删除指定ID的模板
+     * @param $templateId
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function deletePrivateTemplate($templateId)
+    {
+        return WechatService::noticeService()->deletePrivateTemplate($templateId);
+    }
+
+
+    /**
+     * 添加模板并获取模板ID
+     * @param $shortId
+     * @return \EasyWeChat\Support\Collection
+     */
+    public static function addTemplate($shortId)
+    {
+        return WechatService::noticeService()->addTemplate($shortId);
+    }
+}