WeChatController.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Lib\WeApp\WeApp;
  4. use App\Models\Mp\WxMpFreePublish;
  5. use App\Models\Mp\WxMpMessage;
  6. use App\Models\Mp\WxMpMessageReply;
  7. use App\Models\Shop\WxShopOrder;
  8. use App\Models\User\WxUser;
  9. use App\Models\WxOrder;
  10. use App\Wen\Utils\GatewayUtils;
  11. use App\Wen\Utils\OrderUtils;
  12. use App\Wen\Utils\Settings;
  13. use App\Wen\Utils\ShopUtils;
  14. use App\Wen\Utils\StrUtils;
  15. use App\Wen\Utils\StudentUtils;
  16. use Illuminate\Http\Request;
  17. use Illuminate\Support\Carbon;
  18. use Illuminate\Support\Facades\Cache;
  19. use Illuminate\Support\Facades\DB;
  20. class WeChatController extends BaseController
  21. {
  22. public function mini_event_handler(Request $request){
  23. $weapp = new WeApp('mini');
  24. if($weapp){
  25. $messageEvent = $weapp->getMessageEvent();
  26. if($messageEvent){
  27. $messageEvent
  28. ->with(function($message, \Closure $next) use (&$messageEvent, &$request, &$weapp){
  29. // 处理事件
  30. if($message->MsgType === 'event'){
  31. if($message->Event == 'debug_demo'){
  32. return 'minisns debug_demo 测试成功';
  33. }else if($message->Event == 'trade_manage_order_settlement'){
  34. $transaction_id = $message->transaction_id;
  35. $the_order = WxOrder::where('order_serial_number', $transaction_id)->first();
  36. if($the_order){
  37. if($the_order->order_state == 5 && !_empty_($the_order->order_serial_number) && $the_order->order_serial_platform === 0 && $the_order->order_serial_platform_type == 'mini'){
  38. // 在等待确认收货
  39. $infomange = $weapp->getDeliverInfoManage();
  40. $wechat_order = $infomange->getDeliverOrder($transaction_id);
  41. if($wechat_order){
  42. if(in_array(_array_key($wechat_order, 'order_state', 0), [3,4])){
  43. DB::beginTransaction();
  44. try {
  45. WxOrder::where('id', $the_order->id)->update([
  46. 'order_state' => 1
  47. ]);
  48. OrderUtils::order_obtains($the_order, 0);
  49. DB::commit();
  50. return '';
  51. } catch (\Exception $e) {
  52. DB::rollBack();
  53. _logger_(__file__, __line__, $e->getMessage());
  54. }
  55. }
  56. }
  57. }
  58. }else{
  59. $shop_order = WxShopOrder::where('serial_number', $transaction_id)->first();
  60. if($shop_order){
  61. if($shop_order->status == 8){
  62. if($shop_order->pay_status == 2 && !_empty_($shop_order->serial_number) && $shop_order->serial_platform === 0 && $shop_order->serial_platform_type == 'mini'){
  63. $infomange = $weapp->getDeliverInfoManage();
  64. $wechat_order = $infomange->getDeliverOrder($transaction_id);
  65. if($wechat_order){
  66. if(in_array(_array_key($wechat_order, 'order_state', 0), [3,4])){
  67. if(ShopUtils::coupon_to_finish($shop_order, 0, '')){
  68. // GatewayUtils::success(GatewayUtils::uid2client_id($scanner), 17);
  69. GatewayUtils::success(GatewayUtils::uid2client_id($shop_order->user_id), 17);
  70. return '';
  71. }
  72. }
  73. }
  74. }
  75. }else if($shop_order->status == 10){
  76. if($shop_order->pay_status == 2 && !_empty_($shop_order->serial_number) && $shop_order->serial_platform === 0 && $shop_order->serial_platform_type == 'mini'){
  77. $deliver_manage = $weapp->getDeliverInfoManage();
  78. $wechat_order = $deliver_manage->getDeliverOrder($shop_order->serial_number);
  79. if($wechat_order){
  80. if(in_array(_array_key($wechat_order, 'order_state', 0), [3,4])){
  81. DB::beginTransaction();
  82. try {
  83. // todo:
  84. $ship_at = date('Y-m-d H:i:s', time());
  85. WxShopOrder::withTrashed()->where('id', $shop_order->id)->update([
  86. 'has_virtual' => 1,
  87. 'ship_at' => $ship_at,
  88. 'status' => 2,
  89. ]);
  90. ShopUtils::paied_content_process($shop_order->id);
  91. DB::commit();
  92. return '';
  93. } catch (\Exception $e) {
  94. DB::rollBack();
  95. _logger_(__file__, __line__, $e->getMessage());
  96. }
  97. }
  98. }
  99. }
  100. }
  101. }
  102. }
  103. }else{
  104. return '';
  105. }
  106. return '';
  107. }
  108. return $next($message);
  109. })
  110. ->with(function($message, \Closure $next) use (&$messageEvent, &$request){
  111. $mp_open_id = $message->FromUserName;
  112. // 处理消息
  113. if($message->MsgType == 'text'){
  114. $chat_content = $message->Content;
  115. return '';
  116. }
  117. return $next($message);
  118. })
  119. ->with(function($message, \Closure $next) use (&$messageEvent){
  120. // 处理客服消息
  121. return $next($message);
  122. });
  123. return $messageEvent->response($request);
  124. }
  125. }
  126. }
  127. public function mp_event_handler(Request $request){
  128. $weapp = new WeApp('mp');
  129. if($weapp){
  130. $mpServicer = $weapp->getMpServicer();
  131. if($mpServicer){
  132. $mpServicer
  133. ->with(function($message, \Closure $next) use (&$mpServicer, &$request){
  134. // 处理事件
  135. if($message->MsgType === 'event'){
  136. if($message->Event == 'debug_demo'){
  137. return 'minisns debug_demo 测试成功';
  138. }else if( $message->Event == 'unsubscribe'){
  139. // 取消关注
  140. $mp_open_id = $message->FromUserName;
  141. _logger_(__file__, __line__, $mp_open_id . '已取消关注公众号' . $message->ToUserName);
  142. return '';
  143. }else if( $message->Event == 'subscribe' || $message->Event == 'SCAN'){
  144. $mp_open_id = $message->FromUserName;
  145. $eventKey = $message->EventKey;
  146. if(StrUtils::startsWith($eventKey, 'qrscene_user:bind:') || StrUtils::startsWith($eventKey, 'user:bind:')){
  147. if(StrUtils::startsWith($eventKey, 'user:bind:')){
  148. $user_id = (int)(str_replace('user:bind:', '', $eventKey));
  149. }else{
  150. $user_id = (int)(str_replace('qrscene_user:bind:', '', $eventKey));
  151. }
  152. if($user_id > 0){
  153. $alread_user = WxUser::withTrashed()->where('weixin_mp_openid', $mp_open_id)->first();
  154. if($alread_user && $alread_user->id > 0){
  155. if(_empty_($alread_user->weixin_unionid)){
  156. DB::beginTransaction();
  157. try {
  158. // todo:
  159. WxUser::withTrashed()->where('id', $alread_user->id)->update([
  160. 'weixin_mp_openid' => null
  161. ]);
  162. WxUser::withTrashed()->where('id', $user_id)->update([
  163. 'weixin_mp_openid' => $mp_open_id
  164. ]);
  165. DB::commit();
  166. } catch (\Exception $e) {
  167. DB::rollBack();
  168. _logger_(__file__, __line__, $e->getMessage());
  169. }
  170. }
  171. }else{
  172. WxUser::withTrashed()->where('id', $user_id)->update([
  173. 'weixin_mp_openid' => $mp_open_id
  174. ]);
  175. }
  176. }
  177. }else if(StrUtils::startsWith($eventKey, 'user:scene:') || StrUtils::startsWith($eventKey, 'qrscene_user:scene:')){
  178. if(StrUtils::startsWith($eventKey, 'qrscene_user:scene:')){
  179. $scene_arr = explode(':', str_replace('qrscene_user:scene:', '', $eventKey));
  180. }else{
  181. $scene_arr = explode(':', str_replace('user:scene:', '', $eventKey));
  182. }
  183. $user_id = $scene_arr[0] ?? 0;
  184. $to_scene = $scene_arr[1] ?? 0;
  185. $to_scene_id = $scene_arr[2] ?? 0;
  186. $tenant_id = $scene_arr[3] ?? 0;
  187. if($user_id > 0){
  188. $alread_user = WxUser::withTrashed()->where('weixin_mp_openid', $mp_open_id)->first();
  189. if($alread_user && $alread_user->id > 0){
  190. if(_empty_($alread_user->weixin_unionid)){
  191. DB::beginTransaction();
  192. try {
  193. // todo:
  194. WxUser::withTrashed()->where('id', $alread_user->id)->update([
  195. 'weixin_mp_openid' => null
  196. ]);
  197. WxUser::withTrashed()->where('id', $user_id)->update([
  198. 'weixin_mp_openid' => $mp_open_id
  199. ]);
  200. DB::commit();
  201. } catch (\Exception $e) {
  202. DB::rollBack();
  203. _logger_(__file__, __line__, $e->getMessage());
  204. }
  205. }
  206. }else{
  207. WxUser::withTrashed()->where('id', $user_id)->update([
  208. 'weixin_mp_openid' => $mp_open_id
  209. ]);
  210. }
  211. if($to_scene == 31){
  212. return [
  213. "MsgType" => "text",
  214. "Content" => '<a href="'.Settings::get('app_h5_home', '').'/#/pagesA/mine/members/members'.'">购买会员点这里</a>'
  215. ];
  216. }else if($to_scene == 84){
  217. return [
  218. "MsgType" => "text",
  219. "Content" => '<a href="'.Settings::get('app_h5_home', '').'/#/pagesC/promotion/post?id='.$to_scene_id.'">笔记推广点这里</a>'
  220. ];
  221. }else if($to_scene == 163){
  222. return [
  223. "MsgType" => "text",
  224. "Content" => '<a href="'.Settings::get('app_h5_home', '').'/#/pagesA/mine/unlock/unlock?user_id='.$to_scene_id.'">解除账号限制点这里</a>'
  225. ];
  226. }else if($to_scene == 80001){
  227. return [
  228. "MsgType" => "text",
  229. "Content" => '<a href="'.Settings::get('app_h5_home', '').'/#/pages/user/user?id='.$to_scene_id.'&contact_apply=1'.'">付费获取Ta的联系方式点这里</a>'
  230. ];
  231. }else{
  232. return [
  233. "MsgType" => "text",
  234. "Content" => '无效的参数'
  235. ];
  236. }
  237. }
  238. }else{
  239. $res = $mpServicer->getUserInfo($mp_open_id);
  240. if($res['code'] == 200 && _array_key($res, 'unionid', '')){
  241. // 如果不存在这个用户
  242. $data = [
  243. 'openId'=>$mp_open_id, 'avatarUrl'=>'', 'city'=>'', 'country'=>'',
  244. 'province'=>'', 'language'=>'','nickName' => Settings::get('default_user_name', '微信用户'),
  245. 'gender'=>0, 'unionId'=>$res['unionid']
  246. ];
  247. $wxUserModel = new WxUser();
  248. $user_id = $wxUserModel->registerUser($data, 'mp');
  249. }
  250. }
  251. $mp_message_id = WxMpMessageReply::where('word', 'event_subscribe')->value('mp_message_id');
  252. if($mp_message_id && $mp_message_id > 0){
  253. $mp_message = WxMpMessage::find($mp_message_id);
  254. if($mp_message){
  255. return $mp_message->normal();
  256. }
  257. }
  258. return '';
  259. }else if( $message->Event == 'TEMPLATESENDJOBFINISH'){
  260. return '';
  261. }else if( $message->Event == 'PUBLISHJOBFINISH'){
  262. if($message->publish_id){
  263. $updates = [
  264. 'publish_status' => $message->publish_status,
  265. 'article_id' => $message->article_id,
  266. 'article_url' => $message->article_url
  267. ];
  268. if(!_empty_($updates['article_id'])){
  269. $updates['media_id'] = null;
  270. }
  271. WxMpFreePublish::where('publish_id', $message->publish_id)->update($updates);
  272. }
  273. }else{
  274. return '';
  275. }
  276. return '';
  277. }
  278. return $next($message);
  279. })
  280. ->with(function($message, \Closure $next) use (&$mpServicer, &$request){
  281. $mp_open_id = $message->FromUserName;
  282. // 处理消息
  283. if($message->MsgType == 'text'){
  284. $chat_content = $message->Content;
  285. if($chat_content == '退订'){
  286. update_user_meta(WxUser::withTrashed()->where('weixin_mp_openid', $mp_open_id)->value('id'), 'is_mp_free_publish_notice', 2, 'n');
  287. return [
  288. "MsgType" => "text",
  289. "Content" => '退订成功,不再收到公众号的推文提醒,输入“订阅推文”,可重新订阅'
  290. ];
  291. }else if($chat_content == '订阅推文'){
  292. update_user_meta(WxUser::withTrashed()->where('weixin_mp_openid', $mp_open_id)->value('id'), 'is_mp_free_publish_notice', 1, 'n');
  293. return [
  294. "MsgType" => "text",
  295. "Content" => '订阅成功'
  296. ];
  297. }else if($chat_content == '课表'){
  298. return [
  299. "MsgType" => "text",
  300. "Content" => $this->get_student_2day_course_text(WxUser::withTrashed()->where('weixin_mp_openid', $mp_open_id)->value('id'))
  301. ];
  302. }
  303. $query = "SELECT * FROM wx_mp_message_reply WHERE (type = 1 AND word = ?) OR (type = 3 AND word LIKE CONCAT('%', ?, '%')) OR (type = 2 AND ? LIKE CONCAT('%', word, '%'))";
  304. $matches = DB::select($query, [$chat_content, $chat_content,$chat_content]);
  305. foreach ($matches as $record) {
  306. $mp_message = WxMpMessage::find($record->mp_message_id);
  307. if($mp_message){
  308. return $mp_message->normal();
  309. }
  310. }
  311. return '';
  312. }
  313. return $next($message);
  314. })
  315. ->with(function($message, \Closure $next) use (&$mpServicer){
  316. // 处理客服消息
  317. return '';
  318. return $next($message);
  319. });
  320. return $mpServicer->response($request);
  321. }
  322. }
  323. }
  324. private function get_student_2day_course_text($uid){
  325. if(_empty_($uid)){
  326. return '';
  327. }
  328. $today_course = StudentUtils::get_student_day_course($uid, 0);
  329. $tomorrow_course = StudentUtils::get_student_day_course($uid, 1);
  330. $today_date = Carbon::now()->toDateString();
  331. $tomorrow_date = Carbon::now()->addDay()->toDateString();
  332. $url_link = Cache::remember(md5('urllink:pages/tabbar_clone/schedule/schedule'), 3600 * 24, function (){
  333. $new_app = new WeApp();
  334. $wxlink = $new_app->getWxLink();
  335. try {
  336. $url_link = $wxlink->genWxUrllink('pages/tabbar_clone/schedule/schedule', 'back=1');
  337. }catch (\Exception $e){
  338. $url_link = $e->getMessage();
  339. }
  340. return $url_link;
  341. });
  342. $today_course_tip = '';
  343. if($today_course){
  344. foreach ($today_course as $course){
  345. $today_course_tip .= "⭐️".$course->name."\n 老师: ".$course->teacher."\n 地址: ".$course->address."\n 节次: ".$course->getSectionRange()."\n";
  346. }
  347. }else{
  348. $today_course_tip = "无\n";
  349. }
  350. $tomorrow_course_tip = '';
  351. if($tomorrow_course){
  352. foreach ($tomorrow_course as $course){
  353. $tomorrow_course_tip .= "⭐️".$course->name."\n 老师: ".$course->teacher."\n 地址: ".$course->address."\n 节次: ".$course->getSectionRange()."\n";
  354. }
  355. }else{
  356. $tomorrow_course_tip = "无\n";
  357. }
  358. return $today_date."课表\n".$today_course_tip."—————————\n".$tomorrow_date."课表\n".$tomorrow_course_tip."—————————\n点击可查看「<a href=\"".$url_link."\">本周课表</a>」";
  359. }
  360. }