client = $client; if ($client == 'ghs') { $this->url = self::GHS_URL; } else if ($client == 'hd') { $this->url = self::HD_URL; } else { throw new \Exception('client not found'); } $this->msgType = $msgType; } /** * 实现部分厂商特定功能,包括仅部分厂商支持、不常用或厂商临时新增的功能(不依赖 uni-push,厂商文档支持的参数可直接使用)。 * 例如:推送渠道 ID、消息分类(部分厂商未配置时可能被限量推送或静默推送,即静音且需下拉系统通知栏才可见通知内容)、通知栏富文本 */ public function getOptions($client) { if ($client == 'ghs') { return $this->initGhsOptions(); } return $this->initHdOptions(); } /** * 花店的厂商options * @return array */ public function initHdOptions() { $optionsArr = []; switch ($this->msgType) { case self::MSG_TYPE_ORDER: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "142737" //小米后台申请的通知类别id -- https://admin.xmpush.xiaomi.com/zh_CN/channel/list?appId=2882303761520146676 ], "HW" => [ "/message/android/category" => "EXPRESS" ], "VV" => [ "/category" => "ORDER" ], ] ]; break; case self::MSG_TYPE_LOGISTICS: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "142737" ], "HW" => [ "/message/android/category" => "EXPRESS" ], "VV" => [ "/category" => "ORDER" ], ] ]; break; case self::MSG_TYPE_ACCOUNT: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "143019" ], "HW" => [ "/message/android/category" => "ACCOUNT" ], "VV" => [ "/category" => "ACCOUNT" ], ] ]; break; case self::MSG_TYPE_WORK: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "143018" ], "HW" => [ "/message/android/category" => "WORK" ], "VV" => [ "/category" => "TODO" ], ] ]; break; case self::MSG_TYPE_SUBSCRIPTION: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "0" // TODO 暂无 ], "HW" => [ "/message/android/category" => "SUBSCRIPTION" ], "VV" => [ "/category" => "SUBSCRIPTION" ], ] ]; break; } // 【荣耀】 $optionsArr["android"]["HO"] = [ "/android/notification/importance" => "NORMAL" ]; return $optionsArr; } /** * 批发商的厂商options * @return array */ public function initGhsOptions() { $optionsArr = []; switch ($this->msgType) { case self::MSG_TYPE_ORDER: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "142743" //小米后台申请的通知类别id -- https://admin.xmpush.xiaomi.com/zh_CN/channel/list?appId=2882303761520146676 ], "HW" => [ "/message/android/category" => "EXPRESS" ], "VV" => [ "/category" => "ORDER" ], ] ]; break; case self::MSG_TYPE_LOGISTICS: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "142744" ], "HW" => [ "/message/android/category" => "EXPRESS" ], "VV" => [ "/category" => "ORDER" ], ] ]; break; case self::MSG_TYPE_ACCOUNT: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "142895" ], "HW" => [ "/message/android/category" => "ACCOUNT" ], "VV" => [ "/category" => "ACCOUNT" ], ] ]; break; case self::MSG_TYPE_WORK: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "142892" ], "HW" => [ "/message/android/category" => "WORK" ], "VV" => [ "/category" => "TODO" ], ] ]; break; case self::MSG_TYPE_SUBSCRIPTION: $optionsArr = ["android" => [ "XM" => [ "/extra.channel_id" => "0" // TODO 暂无 ], "HW" => [ "/message/android/category" => "SUBSCRIPTION" ], "VV" => [ "/category" => "SUBSCRIPTION" ], ] ]; break; } return $optionsArr; } /** * 向设备端发送通知 * @param array $cids 设备ID * @param string $title 通知标题 * @param string $content 通知内容 * @param array $payload 通知的附加数据 * @return bool|string 返回设备的响应 * @throws \Exception 抛出异常 */ public function pushByCloud($cids, $title, $content, $payload = []) { $sign = md5($title . $content . self::SECRET); $optionsArr = $this->getOptions($this->client); // 测试环境的特殊处理 if (getenv('YII_ENV') == 'dev') { $optionsArr["android"]["HW"]["/message/android/target_user_type"] = 1; //华为 -- 值为int 类型。1 表示华为测试消息,华为每个应用每日可发送该测试消息500条,此target_user_type 参数请勿发布至线上。 $optionsArr["android"]["VV"]["/pushMode"] = 1; //VIVO -- 值为int 类型。0 表示正式推送;1 表示测试推送,不填默认为0。线上请勿使用测试推送 $optionsArr["android"]["HO"]["/android/targetUserType"] = 1; //荣耀 -- 值为int 类型。1 表示测试推送,不填默认为0。荣耀每个应用每日可发送该测试消息1000条。此测试参数请勿发布至线上。 } $data = [ 'cid' => is_array($cids) ? $cids : [$cids], 'title' => $title, 'content' => $content, 'payload' => $payload, 'force_notification' => true, // true: 无论是离线推送还是在线推送,都自创建通知栏消息 // 'force_notification' => false, // false: 客户端在线时不自动创建通知栏消息,需客户端自行处理(如弹窗或存入消息中心);离线时尝试厂商通道通知 'sign' => $sign, 'options' => $optionsArr ]; $ch = curl_init($this->url); if ($ch === false) { throw new \Exception('Failed to initialize curl'); } try { curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode($data), CURLOPT_TIMEOUT => 10, CURLOPT_CONNECTTIMEOUT => 10, ]); $response = curl_exec($ch); if ($response === false) { throw new \Exception('CURL Error: ' . curl_error($ch)); } return $response; } finally { curl_close($ch); } } /** * 向供货商 APP 发送新订单通知 * @param ActiveRecord $shop 供货商门店 * @param ActiveRecord $cgShop 采购花店门店 * @param ActiveRecord $order xhGhsOrder * @throws \Exception */ public function ghsOrderMessage($shop, $cgShop, $order) { $appNotice = dict::getDict('appNotice'); //app禁止通知 if($appNotice == 0) { return []; } try { $allDevices = \bizGhs\device\classes\GhsDeviceClass::getAllByCondition(['shopId' => $shop->id, 'status' => 1]); $cids = array_column($allDevices, 'clientId'); $title = '你有新的订单'; $customId = $order->customId ?? 0; $custom = CustomClass::getById($customId, true); $customName = $custom->name ?? ''; $actPrice = $order->actPrice ? floatval($order->actPrice) : 0; $content = $customName . ' ¥' . $actPrice; $payload = [ "page" => "pagesOrder/detail", "params" => ["id" => $order->id] ]; $this->pushByCloud($cids, $title, $content, $payload); } catch (\Exception $e) { Yii::error('向供货商 APP 发送新订单通知失败: ' . $e->getMessage()); } } }