WechatController.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace api\controllers;
  3. use common\enums\StatusEnum;
  4. use common\events\census\SubscribeEvent;
  5. use common\helpers\FormatHelper;
  6. use common\helpers\WechatHelper;
  7. use common\models\wechat\ReplyRule;
  8. use common\models\wechat\RuleKeyword;
  9. use common\models\wechat\WechatSubscribe;
  10. use EasyWeChat\Kernel\Messages\Text;
  11. use Yii;
  12. use yii\web\NotFoundHttpException;
  13. use common\models\order\Order;
  14. use common\models\common\PaymentTradeOrder;
  15. use common\models\user\User;
  16. use addons\YunfastPay\common\models\PaymentTrade;
  17. class WechatController extends OnAuthController
  18. {
  19. public $enableCsrfValidation = false;
  20. public $modelClass = '';
  21. protected $authOptional = ['index'];
  22. protected function verbs() {
  23. $verbs = parent::verbs();
  24. $verbs['index'] = ['POST','GET','HEAD']; //methods you need in action
  25. return $verbs;
  26. }
  27. /**
  28. *
  29. * 接收公众号信息
  30. * @Author: lun
  31. * @DateTime: 2021/12/8 0008 17:38
  32. * @Copyright: copyright (c) 2021 广东七件事集团
  33. * @return array|mixed|null
  34. * @throws NotFoundHttpException
  35. * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
  36. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  37. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  38. * @throws \ReflectionException
  39. */
  40. public function actionIndex()
  41. {
  42. $mall_id = $this->mall_id;
  43. // 微信公众号配置
  44. $request = Yii::$app->request;
  45. Yii::$app->params['wechatConfig'] = Yii::$app->services->setting->mall->get($mall_id, 'wechat');
  46. switch ($request->getMethod()) {
  47. // 激活公众号
  48. case 'GET':
  49. if (WechatHelper::verifyToken($request->get('signature'), $request->get('timestamp'), $request->get('nonce'))) {
  50. echo $request->get('echostr');
  51. exit;
  52. }
  53. throw new NotFoundHttpException('签名验证失败.');
  54. break;
  55. // 接收数据
  56. case 'POST':
  57. /** @var \jianyan\easywechat\Wechat $wechat */
  58. $wechat = Yii::$app->wechat;
  59. $app = $wechat->app;
  60. $app->server->push(function ($message) use ($mall_id) {
  61. try {
  62. Yii::error('接收到微信信息:'.json_encode($message));
  63. switch ($message['MsgType']) {
  64. case 'event': // '收到事件消息';
  65. $reply = $this->event($mall_id, $message);
  66. break;
  67. case 'text':
  68. //文字消息
  69. $reply = RuleKeyword::match($message['Content'],$mall_id);
  70. break;
  71. default:
  72. // ... 其它消息(image、voice、video、location、link、file ...)
  73. $reply = new Text('您好,系统暂不支持接受此类信息');
  74. break;
  75. }
  76. return $reply;
  77. } catch (\Exception $e) {
  78. // 记录行为日志
  79. if (YII_DEBUG) return $e->getMessage();
  80. return '系统出错,请联系管理员';
  81. }
  82. });
  83. // 将响应输出
  84. $response = $app->server->serve();
  85. $response->send();
  86. break;
  87. default:
  88. throw new NotFoundHttpException('所请求的页面不存在.');
  89. }
  90. exit();
  91. }
  92. /**
  93. * 公众号事件
  94. * @Author: lun
  95. * @DateTime: 2021/12/8 0008 17:37
  96. * @Copyright: copyright (c) 2021 广东七件事集团
  97. * @param $mall_id
  98. * @param $message
  99. * @return bool
  100. */
  101. protected function event($mall_id, $message)
  102. {
  103. // dd($message);
  104. switch ($message['Event']) {
  105. // 关注事件
  106. case 'subscribe':
  107. // 取消关注事件
  108. case 'unsubscribe':
  109. $res = self::handleSubscrible($mall_id, $message);
  110. break;
  111. // 二维码扫描事件
  112. case 'SCAN':
  113. $res = true;
  114. break;
  115. // 上报地理位置事件
  116. case 'LOCATION':
  117. //TODO 暂时不处理
  118. $res = true;
  119. break;
  120. // 自定义菜单(点击)事件
  121. case 'trade_manage_order_settlement':
  122. $res = self::tradeManageOrderSettlement($mall_id, $message);
  123. break;
  124. case 'CLICK':
  125. $content = $message['EventKey'];
  126. $res = RuleKeyword::match($content,$mall_id);
  127. }
  128. return $res;
  129. }
  130. /**
  131. * 关注公众号处理
  132. * @Author: lun
  133. * @DateTime: 2021/12/9 0009 14:46
  134. * @Copyright: copyright (c) 2021 广东七件事集团
  135. * @param $message
  136. * @return bool
  137. */
  138. private static function handleSubscrible($mall_id, $message)
  139. {
  140. // 数据为空不做处理
  141. if (empty($message)) return true;
  142. try {
  143. $params = [
  144. 'to_user_name' => $message['ToUserName'] ?? '',
  145. 'from_user_name' => $message['FromUserName'] ?? '',// open_id
  146. 'create_time' => $message['CreateTime'] ?? '',
  147. 'msg_type' => $message['MsgType'] ?? '',
  148. 'event' => $message['Event'] ?? '',
  149. 'subscribe_status' => $message['Event'] === 'subscribe' ? 1 : 2,// 1=关注公众号,2=取消关注
  150. ];
  151. $res = WechatSubscribe::setData($mall_id, $params);
  152. if ($res == false) throw new \Exception(WechatSubscribe::getStaticError());
  153. if($params['subscribe_status'] == 1){
  154. \Yii::error('触发关注事件');
  155. $event = new SubscribeEvent($mall_id);
  156. $data = ['subscribe_status' => $params['subscribe_status'],'mall_id'=>$mall_id];
  157. \Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  158. $model = ReplyRule::getOne([['mall_id'=>$mall_id,'status'=>StatusEnum::ENABLED,'is_follow_reply'=>1]]);
  159. if($model){
  160. return RuleKeyword::sendMessage($model);
  161. }
  162. }
  163. return true;
  164. } catch (\Exception $e) {
  165. $exception = FormatHelper::exception($e, "关注公众号处理");
  166. Yii::error($exception);
  167. return false;
  168. }
  169. }
  170. public static function tradeManageOrderSettlement($mall_id, $message){
  171. try {
  172. $where = [
  173. ['mall_id'=>$mall_id]
  174. ];
  175. if(!empty($message['transaction_id'])) $where[]= ['third_trade_no'=>$message['transaction_id']];
  176. if(!empty($message['merchant_trade_no'])) $where[]= ['out_trade_no'=>$message['merchant_trade_no']];
  177. if(empty($message['confirm_receive_time']))return true;
  178. $payment_trade = PaymentTrade::getOne($where);
  179. if(empty($payment_trade)) return true;
  180. $list = PaymentTradeOrder::lists(['where'=>[['trade_id'=>$payment_trade['id']]]]);
  181. if(empty($list)) return true;
  182. $order_nos = array_column($list,'order_no');
  183. $list = Order::lists([
  184. 'where'=>[['trade_id'=>$order_nos]]
  185. ]);
  186. $user = User::findOne(['id'=>$payment_trade['user_id']]);
  187. foreach ($list as $item){
  188. $params['mall_id'] = $mall_id;
  189. $params['user_id'] = $item['user_id'];
  190. $params['operator_id'] = $item['user_id'];
  191. $params['operator_name'] = !empty($user->nickname) ?$user->nickname:$user->mobile;
  192. $res = Order::takeDelivery($params);
  193. }
  194. return true;
  195. }catch (\Exception $e){
  196. $exception = FormatHelper::exception($e, "订单完成发货时");
  197. Yii::error($exception);
  198. return false;
  199. }
  200. }
  201. }