ToutiaoNotifyService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Bear
  5. * Date: 2020/2/4
  6. * Time: 上午11:42
  7. */
  8. namespace app\main\service;
  9. use app\admin\model\Postbackklreferral;
  10. use app\common\model\Postbackrules;
  11. use app\common\library\Redis;
  12. use app\main\constants\AdminConstants;
  13. use app\main\constants\CacheConstants;
  14. use app\main\constants\KafkaDotConstants;
  15. use app\main\constants\PostbackConstants;
  16. use app\main\helper\ArrayHelper;
  17. use app\main\helper\DateHelper;
  18. use app\main\model\object\AnalysisObject;
  19. use app\main\model\object\OrderObject;
  20. use app\main\model\object\ReturnObject;
  21. use app\main\model\object\UserObject;
  22. use GuzzleHttp\Client;
  23. use GuzzleHttp\Client as Http;
  24. use Jenssegers\Agent\Agent;
  25. use think\Config;
  26. use think\db\Query;
  27. /**
  28. * Class ToutiaoNotifyService
  29. * @package app\main\service
  30. */
  31. class ToutiaoNotifyService extends BaseService
  32. {
  33. const EVENT_TYPE_ACTIVATE = 0;//激活
  34. const EVENT_TYPE_FORM = 3;//表单提交
  35. const EVENT_TYPE_ADVISE = 5;//有效咨询
  36. const EVENT_TYPE_NEW = 19;//有效获客
  37. const EVENT_TYPE_PAY = 2;//付费￿
  38. const ORANGE_EVENT_TYPE_NEW = 'in_wechat_login';
  39. const ORANGE_EVENT_TYPE_PAY = 'in_wechat_pay';
  40. /**
  41. * 定义属性
  42. *
  43. * @var ToutiaoNotifyService
  44. */
  45. protected static $self = null;
  46. /**
  47. * 返回实例
  48. *
  49. * @return ToutiaoNotifyService
  50. */
  51. public static function instance()
  52. {
  53. if (self::$self == null) {
  54. self::$self = new self();
  55. }
  56. return self::$self;
  57. }
  58. /**
  59. * 头条回传
  60. * @param $link
  61. * @param $user_id
  62. * @param int $type
  63. * @return ReturnObject
  64. */
  65. public function notify($link, $user_id, $type = self::EVENT_TYPE_ACTIVATE, $money = 0)
  66. {
  67. $urlback = Config::get('wechat.tturlback');
  68. //调用打点api
  69. LogService::info('geturl:' . $urlback . ':' . $type . ':' . $link);
  70. $linkInfo = explode('和', $link);
  71. $id = $linkInfo[0];
  72. $link = $linkInfo[1];
  73. $get = $urlback . '?event_type=' . $type . '&link=' . urlencode($link);
  74. if ($id) {
  75. $oAna = new AnalysisObject();
  76. $oAna->data = [
  77. 'toutiao_id' => $id,
  78. ];
  79. switch ($type) {
  80. case self::EVENT_TYPE_ACTIVATE:
  81. $oAna->type = KafkaDotConstants::TYPE_SUBSCRIBE;
  82. $cacheKey = CacheConstants::getGuideWxNewCount($id);
  83. $cacheDayKey = CacheConstants::getGuideWxDayNewCount($id);
  84. $update = [
  85. 'follow' => ['exp', "(follow+1)"],
  86. ];
  87. model("ToutiaoLandingPage")->update($update, ['id' => $id]);
  88. Redis::instance()->incr($cacheKey);
  89. Redis::instance()->incr($cacheDayKey);
  90. Redis::instance()->expire($cacheDayKey, 86400);
  91. break;
  92. case self::EVENT_TYPE_PAY:
  93. $oAna->type = KafkaDotConstants::TYPE_ORDER_COMPLETE;
  94. $oAna->data['money'] = $money;
  95. $cacheKey = CacheConstants::getGuideWxPayCount($id);
  96. $cacheDayKey = CacheConstants::getGuideWxDayPayCount($id);
  97. $cacheMoney = CacheConstants::getGuideWxPayMoney($id);
  98. $cacheDayMoney = CacheConstants::getGuideWxDayPayMoney($id);
  99. $update = [
  100. 'orders_count' => ['exp', "(orders_count+1)"],
  101. 'orders_money' => ['exp', "(orders_money+{$money})"],
  102. ];
  103. model("ToutiaoLandingPage")->update($update, ['id' => $id]);
  104. Redis::instance()->incr($cacheKey);
  105. Redis::instance()->incr($cacheDayKey);
  106. Redis::instance()->expire($cacheDayKey, 86400);
  107. Redis::instance()->expire($cacheDayMoney, 86400);
  108. Redis::instance()->incrByFloat($cacheMoney, $money);
  109. Redis::instance()->incrByFloat($cacheDayMoney, $money);
  110. break;
  111. }
  112. KafkaDotService::instance()->sendMsg($user_id, $oAna);
  113. }
  114. $client = new Client();
  115. $client->get($get);
  116. return $this->setData(true)->getReturn();
  117. }
  118. /**
  119. * 橘子建站上报
  120. * @param $adminConfig
  121. * @param UserObject $user
  122. * @param $type
  123. * @param OrderObject|null $orderObject
  124. * @return ReturnObject
  125. */
  126. public function OrangeNotify($adminConfig, UserObject $user, $type, OrderObject $orderObject = null)
  127. {
  128. $return = false;
  129. try {
  130. if (!ArrayHelper::array_find($adminConfig, 'orange_callback')) {
  131. LogService::info('回传未开启,不需要回传');
  132. return $this->setData($return)->getReturn();
  133. }
  134. $cache = Redis::instance()->hGetAll(CacheConstants::getUserClientCache($user->id));
  135. if (!$cache) {
  136. LogService::info('缓存失效,不需要回传');
  137. return $this->setData($return)->getReturn();
  138. }
  139. $wxname = ArrayHelper::array_find($adminConfig, 'json.authorizer_info.alias');
  140. if (!$wxname) {
  141. LogService::info('微信号为空,不需要回传');
  142. return $this->setData($return)->getReturn();
  143. }
  144. $data = [
  145. "_legacy_event_type" => $type,
  146. "context" => [
  147. "ad" => [
  148. "attributed" => "false"
  149. ],
  150. "device" => [
  151. "open_id" => $user->openid
  152. ],
  153. "ip" => $cache['ip'],
  154. "userAgent" => $cache['ua']
  155. ],
  156. "properties" => [
  157. "source" => Config::get('site.theme'),
  158. "we_chat_app_id" => $adminConfig['appid'],
  159. "we_chat_official_account_id" => $wxname
  160. ],
  161. "timestamp" => DateHelper::ios_8601()
  162. ];
  163. if ($type == self::ORANGE_EVENT_TYPE_PAY) {
  164. if (!$orderObject) {
  165. LogService::info('订单为空,不需要回传');
  166. return $this->setData($return)->getReturn();
  167. } else {
  168. $data['properties']['book_id'] = (string)$orderObject->book_id;
  169. $data['properties']['amount'] = (string)($orderObject->money * 100);
  170. }
  171. }
  172. $httpConfig = [
  173. 'base_uri' => 'https://analytics.oceanengine.com/api/v1/',
  174. 'connect_timeout' => 10,
  175. 'timeout' => 30,
  176. 'http_errors' => true, //抛出异常 true是 false否
  177. 'verify' => false, //不验证ssl证书
  178. ];
  179. $client = new Http($httpConfig);
  180. $result = $client->request('POST',
  181. "track/wechat",
  182. [
  183. 'headers' => [
  184. 'Content-Type' => 'application/json',
  185. 'charset' => 'utf-8'
  186. ],
  187. 'body' => json_encode($data, JSON_UNESCAPED_UNICODE)
  188. ]
  189. );
  190. $status = $result->getStatusCode();
  191. if ($status == 200) {
  192. LogService::info("JuiceNotify: Success Data:" . json_encode($data));
  193. } else {
  194. LogService::error("JuiceNotify: Fail Data:" . json_encode($data) . ',body:' . $result->getBody() . ',code:' . $status);
  195. }
  196. return $this->setData($return)->getReturn();
  197. } catch (\Exception $e) {
  198. LogService::exception($e);
  199. return $this->setData($return)->getReturn();
  200. }
  201. }
  202. /**
  203. * 获取请求设备信息
  204. * @param $ua
  205. * @return ReturnObject
  206. */
  207. public function getUaInfo($ua)
  208. {
  209. $agent = new Agent();
  210. LogService::info("REF_UA:" . $ua);
  211. if ($ua) {
  212. $agent->setUserAgent($ua);
  213. $device = $agent->device();
  214. $pt = $agent->platform();
  215. $pt_version = $agent->version($pt);
  216. $info = $device . ':' . $pt . ':' . rtrim($pt_version, 0);
  217. // $info = $pt . ':' . $pt_version;
  218. } else {
  219. $info = 'default:default:default';
  220. }
  221. return $this->setData($info)->getReturn();
  222. }
  223. /**
  224. * 获取金额阈值
  225. * @param $rule_id
  226. * @param $type
  227. * @param $field
  228. * @return ReturnObject
  229. */
  230. public function getKlValue($rule_id, $type, $field = 'money')
  231. {
  232. $where = [
  233. 'id' => $rule_id,
  234. 'state' => PostbackConstants::STATE_SHOW
  235. ];
  236. $mPostRule = new PostbackRules();
  237. $data = $mPostRule->where($where)->find();
  238. if ($data) {
  239. $return = Config::get('site.' . $type . '_' . $field);
  240. if ($data[$field] != -1) {
  241. $return = $data[$field];
  242. }
  243. } else {
  244. $return = '-1';
  245. }
  246. return $this->setData($return)->getReturn();
  247. }
  248. /**
  249. * 检测是否非KL
  250. * @param $money
  251. * @param $kl
  252. * @param $order_money
  253. * @return ReturnObject
  254. */
  255. public function checkNotKl($money, $kl, $order_money)
  256. {
  257. if ($money == '-1' || $kl == '-1') {
  258. LogService::info('klresult:!k');
  259. return $this->setData(true)->getReturn();
  260. }
  261. $rate = rand(1, 100);
  262. $kl *= 100;
  263. if ($order_money >= $money && $rate > $kl) {
  264. LogService::info('klinfo:' . $order_money . '>=' . $money . ' and ' . $rate . '>' . $kl);
  265. LogService::info('klresult:!k');
  266. return $this->setData(true)->getReturn();
  267. } else {
  268. if ($order_money < $money) {
  269. LogService::info('klinfo:money:' . $order_money . '<' . $money);
  270. }
  271. if ($rate <= $kl) {
  272. LogService::info('klinfo:kl:' . $rate . '<=' . $kl);
  273. }
  274. LogService::info('klresult:k');
  275. return $this->setData(false)->getReturn();
  276. }
  277. }
  278. /**
  279. * 渠道获取规则id
  280. * @param $channel_id
  281. * @param $type
  282. * @return ReturnObject
  283. */
  284. public function getKlRuleId($channel_id, $type = PostbackConstants::TYPE_TOUTIAO)
  285. {
  286. $mPostBackRule = new PostbackRules();
  287. $data = $mPostBackRule
  288. ->where(function (Query $query) use ($channel_id) {
  289. $query->where('find_in_set(' . $channel_id . ', channel_ids)')
  290. ->whereOr('channel_ids', '*');
  291. })
  292. ->where('type', $type)
  293. ->where('state', PostbackConstants::STATE_SHOW)
  294. ->order('weight', 'desc')
  295. ->value('id');
  296. return $this->setData($data)->getReturn();
  297. }
  298. /**
  299. * 获取KL配置
  300. * @param $channel_id
  301. * @param string $type
  302. * @param string $referral_id
  303. * @return ReturnObject
  304. */
  305. public function getKlConfig($channel_id, $type = PostbackConstants::TYPE_TOUTIAO, $referral_id = '')
  306. {
  307. $ruleId = $this->getKlRuleId($channel_id, $type)->data;
  308. if ($ruleId) {
  309. $config = [
  310. 'money' => ToutiaoNotifyService::instance()->getKlValue($ruleId, $type, 'money')->data,
  311. 'kl' => ToutiaoNotifyService::instance()->getKlValue($ruleId, $type, 'kl')->data
  312. ];
  313. if ($referral_id) {
  314. $where = [
  315. 'rule_id' => $ruleId,
  316. 'type' => $type,
  317. 'referral_id' => $referral_id,
  318. 'state' => 'show'
  319. ];
  320. $mPostReferral = new Postbackklreferral();
  321. $referral = $mPostReferral->where($where)->find();
  322. if ($referral) {
  323. if ($referral['money'] != '-1') {
  324. $config['money'] = $referral['money'];
  325. }
  326. if ($referral['kl'] != '-1') {
  327. $config['kl'] = $referral['kl'];
  328. }
  329. }
  330. }
  331. } else {
  332. $config = [
  333. 'money' => '-1',
  334. 'kl' => '-1',
  335. ];
  336. }
  337. return $this->setData($config)->getReturn();
  338. }
  339. /**
  340. * 检查cache
  341. * @param $ip
  342. * @param $ua
  343. * @param $appid
  344. * @return ReturnObject
  345. */
  346. public function checkCache($ip, $ua, $appid)
  347. {
  348. $cacheSub = CacheConstants::getGuideWxSubscribe($ip, $ua);
  349. $link = Redis::instance()->get($cacheSub);
  350. if ($link) {
  351. $params = explode('和', $link);
  352. if (count($params) == 2) {
  353. Redis::instance()->del($cacheSub);
  354. return $this->setData($link)->getReturn();
  355. } else if (count($params) >= 3) {
  356. if ($params[0] == $appid) {
  357. Redis::instance()->del($cacheSub);
  358. array_shift($params);
  359. $link = implode('和', $params);
  360. return $this->setData($link)->getReturn();
  361. }
  362. }
  363. }
  364. return $this->setData(false)->getReturn();
  365. }
  366. /**
  367. * 检测关注时间
  368. * @param $subscribe_time
  369. * @param $type
  370. * @return ReturnObject
  371. */
  372. public function checkCallbackTime($subscribe_time, $type)
  373. {
  374. $return = false;
  375. switch ($type) {
  376. case AdminConstants::CALLBACK_TIME_ALL_DAY:
  377. case AdminConstants::CALLBACK_TIME_ONCE_DAY:
  378. $return = date('Ymd', $subscribe_time) == date('Ymd');
  379. break;
  380. case AdminConstants::CALLBACK_TIME_ALL_24:
  381. case AdminConstants::CALLBACK_TIME_ONCE_24:
  382. $return = $subscribe_time + 86400 > time();
  383. break;
  384. }
  385. if ($return) {
  386. LogService::info('关注时间:需要回传');
  387. } else {
  388. LogService::info('关注时间:不需要回传');
  389. }
  390. return $this->setData($return)->getReturn();
  391. }
  392. }