通過 Laravel 訊息通知使用 EasySms 簡訊服務,讓你的程式碼更簡潔

sureyee發表於2018-09-19

首先什麼是EasySms
請走傳送門: 又一個輪子:一款滿足你的多種傳送需求的簡訊傳送元件: overtrue/easy-sms
什麼是訊息通知
請看文件 訊息通知

下面來說說我是如何整合EasySms的。
閱讀原始碼發現,包中提供了許多介面供我們進行擴充套件,也有很多方法可以進行整合,下面來看看我整合Easysms的一種方法。

通過ServiceProvider整合EasySms服務

  1. 新增一個ServiceProvider,名稱自定義

    php artisan make:provider MessageServiceProvider

  2. 在服務提供者中註冊服務。

    namespace App\Providers;
    
    use App\Channels\EasySmsChannel;
    use App\Gateways\ChanZorGateway;
    use Illuminate\Notifications\ChannelManager;
    use Illuminate\Support\ServiceProvider;
    use Overtrue\EasySms\EasySms;
    
    class MessageServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap services.
         *
         * @return void
         */
        public function boot()
        {
    
        }
    
        /**
         * Register services.
         *
         * @return void
         */
        public function register()
        {
            // 這裡將easySms註冊為一個單例,並且新增門面訪問
            $this->app->singleton('easySms', function () {
                $config = config('easysms');
                return new EasySms($config);
            });
        }
    }
  3. 新增門面,方便訪問。(這裡並不是必要的,如果不使用門面,在channel中使用app()->make('easySms')->send()也可以實現)

    namespace App\Facades;
    use Illuminate\Support\Facades\Facade;
    
    class EasySms extends Facade
    {
        protected static function getFacadeAccessor()
        {
            return 'easySms';
        }
    }
  4. app.php中註冊門面和服務

    'providers' => [
         App\Providers\MessageServiceProvider::class,
    ],
    'aliases' => [
        'EasySms' => App\Facades\EasySms::class,
    ]

    這樣服務就整合完畢了,下面我們來新增自定義閘道器。

新增自定義閘道器

新增自定義閘道器需要實現 GatewayInterface,這裡我直接整合抽象類 Overtrue\EasySms\Gateways\Gateway

  1. 新增自定義閘道器

    namespace App\Gateways;
    
    use Overtrue\EasySms\Contracts\MessageInterface;
    use Overtrue\EasySms\Contracts\PhoneNumberInterface;
    use Overtrue\EasySms\Gateways\Gateway;
    use Overtrue\EasySms\Support\Config;
    use Overtrue\EasySms\Traits\HasHttpRequest;
    
    class ChanZorGateway extends Gateway
    {
        use HasHttpRequest;
    
        const ENDPOINT_HOST = 'http://api.chanzor.com';
    
        const ENDPOINT_URI = '/send';
    
        protected $account;
    
        protected $password;
    
        protected $sign = null;
    
        protected $client;
    
        /**
         * Send a short message.
         *
         * @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
         * @param \Overtrue\EasySms\Contracts\MessageInterface $message
         * @param \Overtrue\EasySms\Support\Config $config
         *
         * @return array
         */
        public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
        {
            $params = [
                'account' => $config->get('account'),
                'password' => $config->get('password'),
                'content' => $message->getContent() . '【' . $config->get('sign') . '】',
                'mobile' => $to->getNumber(),
            ];
    
            return $this->post(self::ENDPOINT_URI, $params);
        }
    
        protected function getBaseUri()
        {
            return self::ENDPOINT_HOST;
        }
    }
  2. 定義laravel通知頻道

    namespace App\Channels;
    
    use App\Facades\EasySms;
    use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;
    use Overtrue\EasySms\PhoneNumber;
    
    class EasySmsChannel
    {
    
        /**
         * 傳送給定通知
         * @param Model $notifiable
         * @param Notification $notification
         * @return mixed
         */
        public function send($notifiable, $notification)
        {
            return EasySms::send($notifiable->routeNotificationFor('easySms'), $notification->toSms($notifiable));
        }
    }
  3. 現在需要在剛剛定義的服務提供者中匯入閘道器否則閘道器是無法使用的,由於在laravel中開箱即用的只有database, mail, nexmo,slack這些,所以,也需要將easySms註冊到服務提供者中
    public function boot()
    {
        // 匯入閘道器
        $this->app->make('easySms')->extend('chanzor', function () {
            return new ChanZorGateway(config('easysms.gateways.chanzor'));
        });
        // 設定頻道
        $this->app->make(ChannelManager::class)
            ->extend('easySms', function ($app) {
                return $app->make(EasySmsChannel::class);
            });
    }

最後就是定義簡訊通知類了

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Overtrue\EasySms\Message;

class OrderPaidNotification extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['easySms'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return Message
     */
    public function toSms($notifiable)
    {
        return (new Message())->setContent( $notifiable->username . ',您好! 這是簡訊內容。');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

注意
需要注意的是,定義好之後需要在User中新增一個獲取手機號碼的方法。

public function routeNotificationForEasySms()
{
    return $this->mobile;
}

為什麼需要定義這個方法,為了擴充套件,如果在Channel中寫死了之後,UserAdmin使用不同的欄位名作為手機號碼就會出錯了。

使用

首先配置easysms的配置項

  'gateways' => [
        'errorlog' => [
            'file' => '/tmp/easy-sms.log',
        ],
        'yunpian' => [
            'api_key' => '824f0ff2f71cab52936axxxxxxxxxx',
        ],
        'aliyun' => [
            'access_key_id' => '',
            'access_key_secret' => '',
            'sign_name' => '',
        ],
        'chanzor' => [
            'account' => env('SMS_CHANZOR_ACCOUNT'),
            'password' => env('SMS_CHANZOR_PASSWORD'),
            'sign' => env('SMS_CHANZOR_SIGN')
        ]
        //...
    ],

然後使用laravel開箱的方式進行呼叫。

$user = App\User::first();
$user->notify(new  App\Notifications\OrderPaidNotification());

如果有不優雅的地方,請指正!謝謝~~~

相關文章