EventController.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace addons\WechatVideoShop\api\modules\v1\controllers;
  3. use addons\WechatVideoShop\common\enums\WechatVideoShopEnums;
  4. use addons\WechatVideoShop\common\expand\sdk\weixin\src\crypto\Crypto;
  5. use addons\WechatVideoShop\common\logic\WeChatCallbackLogic;
  6. use addons\WechatVideoShop\common\models\WechatVideoShop;
  7. use addons\WechatVideoShop\common\models\WechatVideoShopEvents;
  8. use addons\WechatVideoShop\common\service\ShopService;
  9. use common\enums\RabbitMqEnum;
  10. use common\enums\StatusEnum;
  11. use common\models\mall\Mall;
  12. use yii\helpers\Json;
  13. use yii\web\Controller;
  14. class EventController extends Controller
  15. {
  16. public $enableCsrfValidation = false;
  17. /**
  18. * Token校验
  19. * @return bool
  20. * @throws \Exception
  21. */
  22. public function actionIndex()
  23. {
  24. $data = $this->request->get();
  25. $valid = \Yii::$app->services->validate->validate($data, [
  26. [['signature', 'timestamp', 'nonce', 'echostr'], 'required'],
  27. ]);
  28. \Yii::error(__METHOD__ . '->params: ' . var_export($data, true));
  29. if ($valid === false) return false;
  30. $signature = $data["signature"];
  31. $timestamp = $data["timestamp"];
  32. $nonce = $data["nonce"];
  33. $mall_ids = Mall::getEnableMallIds();
  34. foreach ($mall_ids as $mall_id) {
  35. $config = \Yii::$app->services->setting->addons->get($mall_id, WechatVideoShopEnums::ADDONS_NAME, 'basic');
  36. if (empty($config['is_enable'])) continue;
  37. $shop_list = WechatVideoShop::lists(['where' => [['mall_id' => $mall_id], ['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]]]);
  38. if (empty($shop_list)) continue;
  39. foreach ($shop_list as $val) {
  40. if(empty($val['wechat_token'])) continue;
  41. $token = $val['wechat_token'];
  42. $tmpArr = array($token, $timestamp, $nonce);
  43. sort($tmpArr, SORT_STRING);
  44. $tmpStr = implode($tmpArr);
  45. $tmpStr = sha1($tmpStr);
  46. if ($tmpStr == $signature) {
  47. // 执行验证
  48. \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK, RabbitMqEnum::TASK_QUEUE,
  49. ['mall_id' => $mall_id], ShopService::class, 'auth');
  50. return $data['echostr'];
  51. }
  52. }
  53. }
  54. return false;
  55. }
  56. public function actionCallback()
  57. {
  58. try {
  59. // 校验token
  60. if (\Yii::$app->request->isGet && !empty(\Yii::$app->request->get('echostr'))) {
  61. return $this->actionIndex();
  62. }
  63. $params = $this->request->get();
  64. $encryptData = $this->request->post();
  65. \Yii::error(__METHOD__ . '->params: ' . var_export($params, true) . '->encryptData: ' . var_export($encryptData, true));
  66. $save_data['req'] = $params ?? [];
  67. $save_data['org_post'] = !empty($encryptData) ? var_export($encryptData, true) : '';
  68. // 解密?
  69. $mall_ids = Mall::getEnableMallIds();
  70. $decryptData = null;
  71. /** @var int|null $current_mall_id */
  72. $current_mall_id = null;
  73. /** @var int|null $current_shop_id */
  74. $current_shop_id = null;
  75. foreach ($mall_ids as $mall_id) {
  76. $config = \Yii::$app->services->setting->addons->get($mall_id, WechatVideoShopEnums::ADDONS_NAME, 'basic');
  77. if (empty($config['is_enable'])) continue;
  78. $shop_list = WechatVideoShop::lists(['where' => [['mall_id' => $mall_id], ['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]]]);
  79. if (empty($shop_list)) continue;
  80. foreach ($shop_list as $val) {
  81. if (empty($val['wechat_token']) || empty($val['wechat_secret']) || empty($val['wechat_aes_key'])) continue;
  82. try {
  83. $crypto = new Crypto($val['wechat_token'], $val['wechat_aes_key']);
  84. $ret = $crypto->de($encryptData['Encrypt'], $params['msg_signature'], $params['nonce'], $params['timestamp']);
  85. if ($ret[0] != StatusEnum::DISABLED) throw new \Exception("解密失败");
  86. if ($ret[1]['wechat_appid'] != $val['wechat_appid']) throw new \Exception("不属于同一个应用"); // 不属于同一个应用
  87. $current_mall_id = $mall_id;
  88. $current_shop_id = $val['id'];
  89. $decryptData = $ret[1];
  90. break;
  91. } catch (\Exception $e) {
  92. // 有可能是解密失败的 这里不需要管
  93. }
  94. }
  95. }
  96. // 解密成功 - 不一定要解密
  97. if (!empty($decryptData)) {
  98. $decryptData['local_shop_id'] = $current_shop_id;
  99. $save_data['post'] = $decryptData;
  100. $save_data['mall_id'] = $current_mall_id;
  101. $callback = new WeChatCallbackLogic($current_mall_id, $current_shop_id, 0, $decryptData);
  102. $method = $decryptData['Event'] ?? 'call';
  103. if (method_exists($callback, $method)) {
  104. $callback->{$method}([]);
  105. } else {
  106. $callback->call([]);
  107. // $method = 'call';
  108. }
  109. // 投递
  110. // \Yii::$app->services->rabbitMq->delay(600, ['mall_id' => $current_mall_id, 'shop_id' => $current_shop_id, 'data' => $decryptData],
  111. // WeChatCallbackLogic::class, $method);
  112. } else {
  113. $save_data['exception'] = [
  114. 'msg' => '解密失败'
  115. ];
  116. }
  117. } catch (\Exception $e) {
  118. $save_data['exception'] = [
  119. 'file' => $e->getFile(),
  120. 'code' => $e->getCode(),
  121. 'line' => $e->getLine(),
  122. 'msg' => $e->getMessage(),
  123. ];
  124. }
  125. if (empty($save_data['post'])) $save_data['post'] = [];
  126. if (empty($save_data['exception'])) $save_data['exception'] = [];
  127. // 记录事件
  128. $eventModel = new WechatVideoShopEvents();
  129. if ($eventModel->load($save_data, '')) {
  130. if ($eventModel->save() && !empty($eventModel->getErrorMessage())) {
  131. \Yii::error(__METHOD__ . " event model error: {$eventModel->getErrorMessage()}");
  132. }
  133. } else {
  134. \Yii::error(__METHOD__ . " event model error: {$eventModel->getErrorMessage()}");
  135. }
  136. return empty($eventModel['exception']) ? 'success' : 'fail';
  137. }
  138. }