|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace App\Support\Tencent; |
|
4
|
|
|
|
|
5
|
|
|
use ElfSundae\XgPush\ClickAction; |
|
6
|
|
|
use ElfSundae\XgPush\Message; |
|
7
|
|
|
use ElfSundae\XgPush\MessageIOS; |
|
8
|
|
|
use ElfSundae\XgPush\Style; |
|
9
|
|
|
use ElfSundae\XgPush\XingeApp; |
|
10
|
|
|
|
|
11
|
|
|
class XgPusher |
|
12
|
|
|
{ |
|
13
|
|
|
/** |
|
14
|
|
|
* The XingeApp instance. |
|
15
|
|
|
* |
|
16
|
|
|
* @var \ElfSundae\XgPush\XingeApp |
|
17
|
|
|
*/ |
|
18
|
|
|
protected $xinge; |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* The pusher environment. |
|
22
|
|
|
* |
|
23
|
|
|
* 向iOS设备推送时必填,1表示推送生产环境;2表示推送开发环境。推送Android平台不填或填0. |
|
24
|
|
|
* |
|
25
|
|
|
* @var int |
|
26
|
|
|
*/ |
|
27
|
|
|
protected $environment = XingeApp::IOSENV_DEV; |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* The key of custom payload. |
|
31
|
|
|
* |
|
32
|
|
|
* @var string |
|
33
|
|
|
*/ |
|
34
|
|
|
protected $customKey = 'custom'; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* Xinge account prefix. |
|
38
|
|
|
* |
|
39
|
|
|
* @warning 信鸽不允许使用简单的账号,例如纯数字的id。 |
|
40
|
|
|
* |
|
41
|
|
|
* @var string |
|
42
|
|
|
*/ |
|
43
|
|
|
protected $accountPrefix = 'user'; |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* Create a new instance. |
|
47
|
|
|
* |
|
48
|
|
|
* @param string $appKey |
|
49
|
|
|
* @param string $appSecret |
|
50
|
|
|
*/ |
|
51
|
|
|
public function __construct($appKey, $appSecret) |
|
52
|
|
|
{ |
|
53
|
|
|
$this->xinge = new XingeApp($appKey, $appSecret); |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* Get the XingeApp instance. |
|
58
|
|
|
* |
|
59
|
|
|
* @return \ElfSundae\XgPush\XingeApp |
|
60
|
|
|
*/ |
|
61
|
|
|
public function getXinge() |
|
62
|
|
|
{ |
|
63
|
|
|
return $this->xinge; |
|
64
|
|
|
} |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* Get the app key. |
|
68
|
|
|
* |
|
69
|
|
|
* @return string |
|
70
|
|
|
*/ |
|
71
|
|
|
public function getAppKey() |
|
72
|
|
|
{ |
|
73
|
|
|
return $this->xinge->accessId; |
|
74
|
|
|
} |
|
75
|
|
|
|
|
76
|
|
|
/** |
|
77
|
|
|
* Get the app secret. |
|
78
|
|
|
* |
|
79
|
|
|
* @return string |
|
80
|
|
|
*/ |
|
81
|
|
|
public function getAppSecret() |
|
82
|
|
|
{ |
|
83
|
|
|
return $this->xinge->secretKey; |
|
84
|
|
|
} |
|
85
|
|
|
|
|
86
|
|
|
/** |
|
87
|
|
|
* Get the pusher environment. |
|
88
|
|
|
* |
|
89
|
|
|
* @return int |
|
90
|
|
|
*/ |
|
91
|
|
|
public function getEnvironment() |
|
92
|
|
|
{ |
|
93
|
|
|
return $this->environment; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* Set the pusher environment. |
|
98
|
|
|
* |
|
99
|
|
|
* @param mixed $env |
|
100
|
|
|
* @return $this |
|
101
|
|
|
*/ |
|
102
|
|
|
public function setEnvironment($env) |
|
103
|
|
|
{ |
|
104
|
|
|
if (is_string($env)) { |
|
105
|
|
|
$env = $env == 'production' ? XingeApp::IOSENV_PROD : XingeApp::IOSENV_DEV; |
|
106
|
|
|
} |
|
107
|
|
|
|
|
108
|
|
|
if (is_numeric($env)) { |
|
109
|
|
|
$this->environment = $env; |
|
|
|
|
|
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
return $this; |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
/** |
|
116
|
|
|
* Get the key of custom payload. |
|
117
|
|
|
* |
|
118
|
|
|
* @return string |
|
119
|
|
|
*/ |
|
120
|
|
|
public function getCustomKey() |
|
121
|
|
|
{ |
|
122
|
|
|
return $this->customKey; |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
/** |
|
126
|
|
|
* Set the key of custom payload. |
|
127
|
|
|
* |
|
128
|
|
|
* @param string $key |
|
129
|
|
|
* @return $this |
|
130
|
|
|
*/ |
|
131
|
|
|
public function setCustomKey($key) |
|
132
|
|
|
{ |
|
133
|
|
|
if ($key) { |
|
134
|
|
|
$this->customKey = $key; |
|
135
|
|
|
} |
|
136
|
|
|
|
|
137
|
|
|
return $this; |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
/** |
|
141
|
|
|
* Get the account prefix. |
|
142
|
|
|
* |
|
143
|
|
|
* @return string |
|
144
|
|
|
*/ |
|
145
|
|
|
public function getAccountPrefix() |
|
146
|
|
|
{ |
|
147
|
|
|
return $this->accountPrefix; |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* Set the account prefix. |
|
152
|
|
|
* |
|
153
|
|
|
* @param string $prefix |
|
154
|
|
|
* @return $this |
|
155
|
|
|
*/ |
|
156
|
|
|
public function setAccountPrefix($prefix) |
|
157
|
|
|
{ |
|
158
|
|
|
$this->accountPrefix = $prefix; |
|
159
|
|
|
|
|
160
|
|
|
return $this; |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
/** |
|
164
|
|
|
* Determine if the Xinge response is success. |
|
165
|
|
|
* |
|
166
|
|
|
* @see http://developer.qq.com/wiki/xg/%E6%9C%8D%E5%8A%A1%E7%AB%AFAPI%E6%8E%A5%E5%85%A5/Rest%20API%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/Rest%20API%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97.html |
|
167
|
|
|
* |
|
168
|
|
|
* @param mixed $response |
|
169
|
|
|
* @return bool |
|
170
|
|
|
*/ |
|
171
|
|
|
public function succeed($response) |
|
172
|
|
|
{ |
|
173
|
|
|
return $this->code($response) === 0; |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
/** |
|
177
|
|
|
* Get the code of Xinge response. |
|
178
|
|
|
* |
|
179
|
|
|
* @param mixed $response |
|
180
|
|
|
* @return int |
|
181
|
|
|
*/ |
|
182
|
|
|
public function code($response) |
|
183
|
|
|
{ |
|
184
|
|
|
return is_array($response) && isset($response['ret_code']) ? $response['ret_code'] : -999999; |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
/** |
|
188
|
|
|
* Get the error message of Xinge response. |
|
189
|
|
|
* |
|
190
|
|
|
* @param mixed $response |
|
191
|
|
|
* @return string|null |
|
192
|
|
|
*/ |
|
193
|
|
|
public function message($response) |
|
194
|
|
|
{ |
|
195
|
|
|
if (is_array($response)) { |
|
196
|
|
|
return array_get($response, 'err_msg'); |
|
197
|
|
|
} |
|
198
|
|
|
} |
|
199
|
|
|
|
|
200
|
|
|
/** |
|
201
|
|
|
* Get the result data of Xinge response. |
|
202
|
|
|
* |
|
203
|
|
|
* @param mixed $response |
|
204
|
|
|
* @return mixed |
|
205
|
|
|
*/ |
|
206
|
|
|
public function result($response, $key = null) |
|
207
|
|
|
{ |
|
208
|
|
|
if (is_array($response)) { |
|
209
|
|
|
return array_get($response, $key ? "result.{$key}" : 'result'); |
|
210
|
|
|
} |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
/** |
|
214
|
|
|
* Encode the custom data. |
|
215
|
|
|
* |
|
216
|
|
|
* @param mixed $data |
|
217
|
|
|
* @return array|null |
|
218
|
|
|
*/ |
|
219
|
|
|
public function encodeCustomData($data) |
|
220
|
|
|
{ |
|
221
|
|
|
if (! empty($data)) { |
|
222
|
|
|
return [$this->customKey => $data]; |
|
223
|
|
|
} |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
/** |
|
227
|
|
|
* Get Xinge account for the given user. |
|
228
|
|
|
* |
|
229
|
|
|
* @param mixed $user |
|
230
|
|
|
* @return string |
|
231
|
|
|
*/ |
|
232
|
|
|
public function accountForUser($user) |
|
233
|
|
|
{ |
|
234
|
|
|
if ($this->accountPrefix && is_string($user) && starts_with($user, $this->accountPrefix)) { |
|
235
|
|
|
return $user; |
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
View Code Duplication |
if (is_object($user)) { |
|
|
|
|
|
|
239
|
|
|
$user = $user->id; |
|
240
|
|
|
} elseif (is_array($user)) { |
|
241
|
|
|
$user = $user['id']; |
|
242
|
|
|
} |
|
243
|
|
|
|
|
244
|
|
|
return $this->accountPrefix.$user; |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
/** |
|
248
|
|
|
* Creates a new MessageIOS instance. |
|
249
|
|
|
* |
|
250
|
|
|
* @param string $alert |
|
251
|
|
|
* @param mixed $custom |
|
252
|
|
|
* @param int $badge |
|
253
|
|
|
* @param string $sound |
|
254
|
|
|
* @return \ElfSundae\XgPush\MessageIOS |
|
255
|
|
|
*/ |
|
256
|
|
|
public function createIOSMessage($alert = '', $custom = null, $badge = 1, $sound = 'default') |
|
257
|
|
|
{ |
|
258
|
|
|
$message = new MessageIOS(); |
|
259
|
|
|
$message->setAlert($alert); |
|
260
|
|
|
if ($customData = $this->encodeCustomData($custom)) { |
|
261
|
|
|
$message->setCustom($customData); |
|
262
|
|
|
} |
|
263
|
|
|
if (is_numeric($badge) && $badge >= 0) { |
|
264
|
|
|
$message->setBadge($badge); |
|
265
|
|
|
} |
|
266
|
|
|
if ($sound) { |
|
267
|
|
|
$message->setSound($sound); |
|
268
|
|
|
} |
|
269
|
|
|
|
|
270
|
|
|
return $message; |
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* Create a new Message instance. |
|
275
|
|
|
* |
|
276
|
|
|
* @param string $content |
|
277
|
|
|
* @param mixed $custom |
|
278
|
|
|
* @param string $title |
|
279
|
|
|
* @param int $type |
|
280
|
|
|
* @return \ElfSundae\XgPush\Message |
|
281
|
|
|
*/ |
|
282
|
|
|
public function createAndroidMessage($content = '', $custom = null, $title = null, $type = Message::TYPE_NOTIFICATION) |
|
283
|
|
|
{ |
|
284
|
|
|
$message = new Message(); |
|
285
|
|
|
$message->setTitle($title ?: config('app.name')); |
|
286
|
|
|
$message->setContent($content); |
|
287
|
|
|
if ($customData = $this->encodeCustomData($custom)) { |
|
288
|
|
|
$message->setCustom($customData); |
|
289
|
|
|
} |
|
290
|
|
|
$message->setType($type); |
|
291
|
|
|
$message->setStyle(new Style(0, 1, 1, 1, 0)); |
|
292
|
|
|
$action = new ClickAction(); |
|
293
|
|
|
$action->setActionType(ClickAction::TYPE_ACTIVITY); |
|
294
|
|
|
$message->setAction($action); |
|
295
|
|
|
|
|
296
|
|
|
return $message; |
|
297
|
|
|
} |
|
298
|
|
|
|
|
299
|
|
|
/** |
|
300
|
|
|
* Query all device tokens for the given user. |
|
301
|
|
|
* |
|
302
|
|
|
* @param mixed $user |
|
303
|
|
|
* @return string[]|null |
|
304
|
|
|
*/ |
|
305
|
|
|
public function queryDeviceTokensForUser($user) |
|
306
|
|
|
{ |
|
307
|
|
|
return $this->result( |
|
308
|
|
|
$this->xinge->QueryTokensOfAccount($this->accountForUser($user)), |
|
309
|
|
|
'tokens' |
|
310
|
|
|
); |
|
311
|
|
|
} |
|
312
|
|
|
|
|
313
|
|
|
/** |
|
314
|
|
|
* Query all tags for the given device token. |
|
315
|
|
|
* |
|
316
|
|
|
* @param string $deviceToken |
|
317
|
|
|
* @return string[]|null |
|
318
|
|
|
*/ |
|
319
|
|
|
public function queryTagsForDeviceToken($deviceToken) |
|
320
|
|
|
{ |
|
321
|
|
|
return $this->result( |
|
322
|
|
|
$this->xinge->QueryTokenTags($deviceToken), |
|
323
|
|
|
'tags' |
|
324
|
|
|
); |
|
325
|
|
|
} |
|
326
|
|
|
|
|
327
|
|
|
/** |
|
328
|
|
|
* Query all tags for the given user. |
|
329
|
|
|
* |
|
330
|
|
|
* @param mixed $user |
|
331
|
|
|
* @param array &$deviceTokens |
|
332
|
|
|
* @return array|null |
|
333
|
|
|
*/ |
|
334
|
|
|
public function queryTagsForUser($user, &$deviceTokens = null) |
|
335
|
|
|
{ |
|
336
|
|
|
$deviceTokens = $this->queryDeviceTokensForUser($user); |
|
337
|
|
|
|
|
338
|
|
|
if (is_array($deviceTokens)) { |
|
339
|
|
|
$result = []; |
|
340
|
|
|
foreach ($deviceTokens as $token) { |
|
341
|
|
|
if ($tags = $this->queryTagsForDeviceToken($token)) { |
|
342
|
|
|
$result[$token] = $tags; |
|
343
|
|
|
} |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
return $result; |
|
347
|
|
|
} |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
|
|
/** |
|
351
|
|
|
* Push message to a device. |
|
352
|
|
|
* |
|
353
|
|
|
* @param string $deviceToken |
|
354
|
|
|
* @param \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS $message |
|
355
|
|
|
* @return array |
|
356
|
|
|
*/ |
|
357
|
|
|
public function toDevice($deviceToken, $message) |
|
358
|
|
|
{ |
|
359
|
|
|
return $this->xinge->PushSingleDevice($deviceToken, $message, $this->environment); |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
|
|
/** |
|
363
|
|
|
* Push message to an user. |
|
364
|
|
|
* |
|
365
|
|
|
* @param mixed $user |
|
366
|
|
|
* @param \ElfSundae\XgPush\Message|\ElfSundae\XgPush\MessageIOS $message |
|
367
|
|
|
* @return array |
|
368
|
|
|
*/ |
|
369
|
|
|
public function toUser($user, $message) |
|
370
|
|
|
{ |
|
371
|
|
|
return $this->xinge->PushSingleAccount(0, $this->accountForUser($user), $message, $this->environment); |
|
372
|
|
|
} |
|
373
|
|
|
|
|
374
|
|
|
/** |
|
375
|
|
|
* Dynamically handle calls to the XingeApp instance. |
|
376
|
|
|
* |
|
377
|
|
|
* @param string $method |
|
378
|
|
|
* @param array $parameters |
|
379
|
|
|
* @return mixed |
|
380
|
|
|
*/ |
|
381
|
|
|
public function __call($method, $parameters) |
|
382
|
|
|
{ |
|
383
|
|
|
return call_user_func_array([$this->xinge, $method], $parameters); |
|
384
|
|
|
} |
|
385
|
|
|
} |
|
386
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.