添加后台推送
parent
f4beb2e5b3
commit
3b87d84079
|
|
@ -3,6 +3,8 @@
|
|||
namespace App\Admin\Controllers;
|
||||
|
||||
use App\Admin\Repositories\Message;
|
||||
use App\Models\Message as MessageModel;
|
||||
use App\Services\Push\MallUnipushService;
|
||||
use Dcat\Admin\Admin;
|
||||
use Dcat\Admin\Form;
|
||||
use Dcat\Admin\Grid;
|
||||
|
|
@ -29,6 +31,7 @@ class MessageController extends AdminController
|
|||
'2'=>__('admin_message.ad.jump_type.radio.2'),
|
||||
])->label();
|
||||
$grid->column('jump_link');
|
||||
$grid->column('is_push')->bool();
|
||||
$grid->column('created_at')->sortable();
|
||||
|
||||
$grid->model()->orderBy('created_at', 'desc');
|
||||
|
|
@ -94,6 +97,19 @@ class MessageController extends AdminController
|
|||
'2'=>__('admin_message.ad.jump_type.radio.2'),
|
||||
])->default(0);
|
||||
$form->text('jump_link');
|
||||
if ($form->isEditing()) {
|
||||
$form->switch('is_push')->disable();
|
||||
} else {
|
||||
$form->switch('is_push')->default(0);
|
||||
}
|
||||
$form->saved(function (Form $form, $result) {
|
||||
// 判断是否是新增操作
|
||||
if ($form->isCreating() && $form->is_push) {
|
||||
$pushService = new MallUnipushService();
|
||||
$pushService->pushAllMessage(MessageModel::findOrFail($result));
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
$form->display('created_at');
|
||||
$form->display('updated_at');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Endpoint\Api\Http\Controllers;
|
||||
|
||||
use App\Exceptions\BizException;
|
||||
use App\Models\UserCid;
|
||||
use App\Services\Push\MallUnipushService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Throwable;
|
||||
|
||||
class PushController extends Controller
|
||||
{
|
||||
/**
|
||||
* 绑定cid
|
||||
*
|
||||
* @param Request $request
|
||||
* @return void
|
||||
*/
|
||||
public function bindUniCid(Request $request, MallUnipushService $mallUnipushService)
|
||||
{
|
||||
if (!$request->user()) {
|
||||
throw new BizException('绑定失败,请稍后再试');
|
||||
}
|
||||
|
||||
$input = $request->validate([
|
||||
'cid' => ['bail', 'required', 'string', 'max:64'],
|
||||
]);
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
//查询目前有没有人已绑定这个cid, 有就解绑
|
||||
UserCid::where('u_cid', $input['cid'])->where('user_id', '<>', $request->user()->id)->update([
|
||||
'u_cid' => null,
|
||||
]);
|
||||
$request->user()->cid()->updateOrCreate([
|
||||
'u_cid'=>$input['cid'],
|
||||
]);
|
||||
DB::commit();
|
||||
} catch (Throwable $th) {
|
||||
DB::rollBack();
|
||||
report($th);
|
||||
throw new BizException('绑定失败,请稍后再试');
|
||||
}
|
||||
return response()->noContent();
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ use App\Endpoint\Api\Http\Controllers\Product\ProductCategoryController;
|
|||
use App\Endpoint\Api\Http\Controllers\Product\ProductFavoriteController;
|
||||
use App\Endpoint\Api\Http\Controllers\Product\ProductSkuController;
|
||||
use App\Endpoint\Api\Http\Controllers\Product\ProductViewLogController;
|
||||
use App\Endpoint\Api\Http\Controllers\PushController;
|
||||
use App\Endpoint\Api\Http\Controllers\ShippingAddressController;
|
||||
use App\Endpoint\Api\Http\Controllers\ShoppingCartItemController;
|
||||
use App\Endpoint\Api\Http\Controllers\SmsCodeController;
|
||||
|
|
@ -66,6 +67,8 @@ Route::group([
|
|||
Route::get('article-config', [ArticleController::class, 'config']);
|
||||
//获取最新app版本信息
|
||||
Route::get('app-version', [AppVersionController::class, 'index']);
|
||||
//绑定用户端cid
|
||||
Route::post('push-bind-uni', [PushController::class, 'bindUniCid']);
|
||||
|
||||
Route::middleware(['auth:api'])->group(function () {
|
||||
// 我的信息
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class Message extends Model
|
|||
|
||||
protected $casts = [
|
||||
'ext'=>JsonArray::class,
|
||||
'is_push'=>'bool',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
|
|
@ -30,6 +31,11 @@ class Message extends Model
|
|||
return $this->hasMany(MessageReadLog::class);
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public static function userMessages(User $user)
|
||||
{
|
||||
return self::where(function ($q) use ($user) {
|
||||
|
|
|
|||
|
|
@ -118,6 +118,14 @@ class User extends Model implements AuthorizableContract, AuthenticatableContrac
|
|||
return $this->hasMany(ProductSkuFavorite::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 属于此用户的推送cid
|
||||
*/
|
||||
public function cid()
|
||||
{
|
||||
return $this->hasOne(UserCid::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认此用户是否是 VIP
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UserCid extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
protected $table = 'user_cids';
|
||||
|
||||
protected $fillable = [
|
||||
'user_id', 'u_cid', 'm_cid',
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Push;
|
||||
|
||||
use App\Models\Message;
|
||||
|
||||
class MallUnipushService extends UniPushService
|
||||
{
|
||||
protected $appId;
|
||||
|
||||
protected $appKey;
|
||||
|
||||
protected $appSecret;
|
||||
|
||||
protected $masterSecret;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->appId = config('settings.mall_push_app_id', '');
|
||||
$this->appKey = config('settings.mall_push_app_key', '');
|
||||
$this->appSecret = config('settings.mall_push_app_secret', '');
|
||||
$this->masterSecret = config('settings.mall_push_master_secret', '');
|
||||
parent::__construct($this->appId, $this->appKey, $this->appSecret, $this->masterSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送公告消息
|
||||
*
|
||||
* @param [type] $message
|
||||
* @return void
|
||||
*/
|
||||
public function pushAllMessage(Message $message)
|
||||
{
|
||||
$this->pushAll($message->title, $message->content, [
|
||||
'jump_type' => $message->jump_type == 0 ? 1 : $message->jump_type,
|
||||
'jump_link' => $message->type == 1 || empty($message->jump_link) ? '/pages/news/index' : $message->jump_link,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送单条消息
|
||||
*
|
||||
* @param Message $message
|
||||
* @return void
|
||||
*/
|
||||
public function pushMessage(Message $message)
|
||||
{
|
||||
//如果不是指定消息,直接退出;
|
||||
if (is_null($message->user)) {
|
||||
return;
|
||||
}
|
||||
//如果拿不到u_cid直接退出
|
||||
if (!$message->user->cid->u_cid) {
|
||||
return;
|
||||
}
|
||||
$this->pushCid($message->user->cid->u_cid, $message->title, $message->content, [
|
||||
'jump_type' => $message->jump_type == 0 ? 1 : $message->jump_type,
|
||||
'jump_link' => $message->type == 1 || empty($message->jump_link) ? '/pages/news/index' : $message->jump_link,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Push;
|
||||
|
||||
class MerchantUnipushService
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Push;
|
||||
|
||||
use App\Helpers\Order as OrderHelper;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class UniPushService
|
||||
{
|
||||
protected $appId;
|
||||
|
||||
protected $appKey;
|
||||
|
||||
protected $appSecret;
|
||||
|
||||
protected $masterSecret;
|
||||
|
||||
protected $cacheKey;
|
||||
|
||||
protected $uri = 'https://restapi.getui.com/v2/';
|
||||
|
||||
public function __construct(string $appId, string $appKey, string $appSecret, string $masterSecret)
|
||||
{
|
||||
$this->appId = $appId;
|
||||
$this->appKey = $appKey;
|
||||
$this->appSecret = $appSecret;
|
||||
$this->masterSecret = $masterSecret;
|
||||
|
||||
$this->cacheKey = 'uni-push-'.$this->appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例token
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
if (Cache::has($this->cacheKey)) {
|
||||
return Cache::get($this->cacheKey);
|
||||
} else {
|
||||
return $this->getTokenFromServer();
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUri($uri)
|
||||
{
|
||||
return $this->uri.$this->appId.'/'.$uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取unix毫秒时间戳
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function msectime()
|
||||
{
|
||||
list($msec, $sec) = explode(' ', microtime());
|
||||
$msectime = (float) sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
|
||||
return $msectime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建签名
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function makeSign($param)
|
||||
{
|
||||
return hash('sha256', $param['appkey'].$param['timestamp'].$this->masterSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新获取token
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function getTokenFromServer()
|
||||
{
|
||||
$token = '';
|
||||
$param = [
|
||||
'appkey'=>$this->appKey,
|
||||
'timestamp'=>$this->msectime(),
|
||||
];
|
||||
$param['sign'] = $this->makeSign($param);
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
])->post($this->getUri('auth'), $param);
|
||||
|
||||
if ($response->successful()) {
|
||||
$data = $response->json();
|
||||
$token = $data['data']['token'];
|
||||
Cache::put($this->cacheKey, $data['data']['token'], $data['data']['expire_time']);
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装公共请求
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function post($uri, $params)
|
||||
{
|
||||
$token = $this->getToken();
|
||||
// dd($params);
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
'token' => $token,
|
||||
])->post($this->getUri($uri), $params);
|
||||
|
||||
$resData = [];
|
||||
if ($response->successful()) {
|
||||
$resData = $response->json();
|
||||
}
|
||||
return $resData;
|
||||
}
|
||||
|
||||
protected function get($uri, $params = null)
|
||||
{
|
||||
$token = $this->getToken();
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
'token' => $token,
|
||||
])->get($this->getUri($uri), $params);
|
||||
|
||||
$resData = [];
|
||||
if ($response->successful()) {
|
||||
$resData = $response->json();
|
||||
}
|
||||
return $resData;
|
||||
}
|
||||
|
||||
protected function createPushData($title, $body, $params = [])
|
||||
{
|
||||
$payload = urlencode(json_encode($params));
|
||||
return [
|
||||
'request_id' => OrderHelper::serialNumber(),
|
||||
'settings'=>[
|
||||
'ttl'=> 3600000,
|
||||
'strategy'=> [
|
||||
'default'=>1,
|
||||
'ios'=>4,
|
||||
],
|
||||
],
|
||||
'push_message'=>[
|
||||
'transmission'=> json_encode([
|
||||
'title' => $title,
|
||||
'content'=> $body,
|
||||
'payload'=> $payload,
|
||||
]),
|
||||
// 'notification'=>[
|
||||
// 'title' => $title,
|
||||
// 'body' => $body,
|
||||
// 'click_type'=> 'payload', //默认打开首页
|
||||
// 'payload'=> $payload,
|
||||
// ],
|
||||
],
|
||||
'push_channel'=>[
|
||||
'android'=>[
|
||||
'ups'=> [
|
||||
'transmission'=> json_encode([
|
||||
'title' => $title,
|
||||
'content'=> $body,
|
||||
'payload'=> $payload,
|
||||
]),
|
||||
// 'notification'=>[
|
||||
// 'title' => $title,
|
||||
// 'body' => $body,
|
||||
// 'click_type'=> 'payload', //默认打开首页
|
||||
// 'payload'=> $payload,
|
||||
// ],
|
||||
],
|
||||
],
|
||||
'ios'=>[
|
||||
'type'=>'notify',
|
||||
'payload' => $payload,
|
||||
'aps'=>[
|
||||
'alert'=>[
|
||||
'title'=>$title,
|
||||
'body'=>$body,
|
||||
],
|
||||
'content-available'=> 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定cid和user_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function bindCid($userId, $cid)
|
||||
{
|
||||
$this->post('user/alias', [
|
||||
'data_list'=>[
|
||||
'cid' => $cid,
|
||||
'alias'=>$userId,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑所有与该别名绑定的cid
|
||||
*/
|
||||
public function unbindCid($userId)
|
||||
{
|
||||
$res = $this->get('user/alias/'.$userId);
|
||||
|
||||
if (Arr::get($res, 'code', 1) === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据cid单推
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function pushCid(string $cid, string $title, string $body, array $params = [])
|
||||
{
|
||||
$this->post('push/single/cid', array_merge([
|
||||
'audience'=>[
|
||||
'cid'=>[
|
||||
$cid,
|
||||
],
|
||||
],
|
||||
], $this->createPushData($title, $body, $params)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 给所有人推送
|
||||
*
|
||||
* @param string $title
|
||||
* @param string $body
|
||||
* @param array $params
|
||||
* @return void
|
||||
*/
|
||||
public function pushAll(string $title, string $body, array $params = [])
|
||||
{
|
||||
$this->post('push/all', array_merge([
|
||||
'audience'=>'all',
|
||||
], $this->createPushData($title, $body, $params)));
|
||||
}
|
||||
}
|
||||
|
|
@ -32,4 +32,18 @@ return [
|
|||
'kuaidi100_secret'=> '1bd287d1981749f2a30ea74cac0ab99c',
|
||||
'kuaidi100_userid'=> 'ec0b6ec7729d4f22824cfd3c519dd45b',
|
||||
|
||||
//推送
|
||||
'mall_push_app_id'=>'iikmCoESID8bC1LhOPG1r8',
|
||||
'mall_push_app_key'=>'JX33P0wP8bAQprI953hpN6',
|
||||
'mall_push_app_secret'=>'a3u3B6lXjq6fPTBlOGiOc9',
|
||||
'mall_push_master_secret'=>'MAxmqomwo597xJeDuMCvx1',
|
||||
|
||||
'merchant_push_app_id'=>'',
|
||||
'merchant_push_app_key'=>'',
|
||||
'merchant_push_app_secret'=>'',
|
||||
'merchant_push_master_secret'=>'',
|
||||
|
||||
//app配置
|
||||
'user_center_is_open'=>true,
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddIsPushToMessagesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('messages', function (Blueprint $table) {
|
||||
//
|
||||
$table->unsignedTinyInteger('is_push')->default(0)->comment('是否推送');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('messages', function (Blueprint $table) {
|
||||
//
|
||||
$table->dropColumn('is_push');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateUserCidsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('user_cids', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('user_id')->comment('用户ID');
|
||||
$table->string('u_cid')->nullable()->comment('用户推送cid');
|
||||
$table->string('m_cid')->nullable()->comment('商户推送cid');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('user_cids');
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ return [
|
|||
'ext' => '扩展内容',
|
||||
'jump_type' => '跳转类型',
|
||||
'jump_link' => '跳转地址',
|
||||
'is_push'=>'推送',
|
||||
],
|
||||
'options' => [
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in New Issue