diff --git a/app/Exceptions/FieldNotExistsException.php b/app/Exceptions/FieldNotExistsException.php new file mode 100644 index 00000000..793cbe37 --- /dev/null +++ b/app/Exceptions/FieldNotExistsException.php @@ -0,0 +1,10 @@ +runningInConsole()) { + // static::addGlobalScope( new OrderByIdScope ); + // } + } + + public function getPerPage() + { + $pageSize = (int) request( 'per_page' , $this->perPage ); + return min( $pageSize , $this->pageSizeLimit ); + } + + public function attributeExists( $attr ): bool + { + + return array_key_exists( $attr , $this->attributes ); + } + + public function getField( $name ) + { + $columnName = static::getColumn( $name ); + return $this->$columnName; + } + + public function setField( $name , $value ): void + { + $columnName = static::getColumn( $name ); + $this->$columnName = $value; + } + + public static function getColumnTable( $name ): string + { + return static::getTableName() . '.' . static::getColumn( $name ); + } + + public static function getColumn( $name ) + { + $fieldName = Arr::get( static::$maps , $name ); + + if ( is_null( $fieldName ) ) { + throw new FieldNotExistsException( "field $name not exists" ); + } + + return $fieldName; + } + + public function getTable() + { + return static::getTableName(); + } + + public function fieldValue( $name ) + { + return $this->$name; + } + + public function getAttributes() + { + + return $this->attributes; + } + + public function isLoaded( $relationName ): bool + { + return isset( $this->relations[ $relationName ] ) and $this->$relationName != null; + } + + abstract public static function getTableName(); +} diff --git a/app/Models/Sms.php b/app/Models/Sms.php new file mode 100644 index 00000000..631111f2 --- /dev/null +++ b/app/Models/Sms.php @@ -0,0 +1,35 @@ +morphTo( null , 'rel_type' , 'rel_id' ); + } + + public function smsBatch(): BelongsTo + { + return $this->belongsTo( SmsBatch::class ); + } + +} diff --git a/app/Models/SmsBatch.php b/app/Models/SmsBatch.php new file mode 100644 index 00000000..0a091f2b --- /dev/null +++ b/app/Models/SmsBatch.php @@ -0,0 +1,40 @@ +hasMany( Sms::class ); + } + + public function scopeSingle( $query ) + { + return $query->whereCategory( 'single' ); + } + + public function scopeBatch( $query ) + { + return $query->whereCategory( 'batch' ); + } + +} diff --git a/app/Scopes/OrderByIdScope.php b/app/Scopes/OrderByIdScope.php new file mode 100644 index 00000000..31ce139a --- /dev/null +++ b/app/Scopes/OrderByIdScope.php @@ -0,0 +1,15 @@ +orderBy($model->getTable().'.id', 'desc'); + } +} diff --git a/app/Services/Notification/Batch/BatchTransmitter.php b/app/Services/Notification/Batch/BatchTransmitter.php new file mode 100644 index 00000000..2106cd13 --- /dev/null +++ b/app/Services/Notification/Batch/BatchTransmitter.php @@ -0,0 +1,52 @@ +collection = $collection; + $this->config = config( 'notification.drivers.rahyab_advertise' ); + $this->client = new \SoapClient( $this->config[ 'url' ] ); + } + + public function send( string $message ) + { + $this->message = $message; + if ( $this->collection->count() <= config( 'notification.max_phone_size.do_send_sms' ) ) { + return $result = $this->client->doSendSMS( $this->payload() ); + } + } + + protected function getPhones() + { + $phones = []; + foreach ( $this->collection as $key => $item ) { + $phones[] = $item->getPhone(); + } + return array_unique( $phones ); + } + + protected function payload() + { + return array( + 'uUsername' => $this->config[ 'username' ] , + 'uPassword' => $this->config[ 'password' ] , + 'uNumber' => $this->config[ 'from' ] , + 'uCellphones' => implode( ';' , $this->getPhones() ) , + 'uMessage' => $this->message , + 'uFarsi' => true , + 'uTopic' => false , + 'uFlash' => false , + 'uUDH' => '' + ); + } + } diff --git a/app/Services/Notification/Batch/PeerToPeer.php b/app/Services/Notification/Batch/PeerToPeer.php new file mode 100644 index 00000000..5fe6fc40 --- /dev/null +++ b/app/Services/Notification/Batch/PeerToPeer.php @@ -0,0 +1,164 @@ +isValidCost() || $operator == 'service') { + $this->operator = ($operator == 'advertise') ? 'rahyab_advertise' : 'rahyab_service'; + $this->collection = $collection; + $this->messagePatternClass = new Pattern($message); + $this->messagePattern = $this->messagePatternClass->getPattern(); + $this->config = array_merge($this->createExtra($category, $uniqueCode), config('notification.drivers.' . $this->operator)); + + if (isset($this->config['operator'])) { + if (str_contains($this->config['operator'], 'advertise')) { + $this->config['type'] = 'advertise'; + } else { + $this->config['type'] = 'service'; + } + } + + try { + $this->client = new SoapClient( $this->config[ 'url' ] ); + } catch ( \SoapFault $e ) { + dd($e->getMessage()); + } + } + } + + private function isValidCost(): bool + { + if ( $this->price > -50000.00) { + return true; + } else { + return false; + } + } + + public function isSystematic($isSystematic = 0): static + { + $this->isSystematic = $isSystematic; + return $this; + } + + public function isAdmin($isAdmin = 0): static + { + $this->isAdmin = $isAdmin; + return $this; + } + + public function send($userData): void + { + if ($this->collection->count() <= config('notification.max_phone_size.do_send_sms_array_c')) { + $this->setIsAdminAndIsSystematicInConfig(); + $payload = $this->payload($userData); + $response = $this->client->doSendSMSArrayC($payload)->doSendSMSArrayCResult->DataSendOut; + $this->serializeToDatabase($payload['uDataSendIn'], $response); + } + } + + public function sendAgain($userData, SmsBatch $smsBatch): void + { + if ($this->collection->count() <= config('notification.max_phone_size.do_send_sms_array_c')) { + $payload = $this->payload($userData); + $response = $this->client->doSendSMSArrayC($payload)->doSendSMSArrayCResult->DataSendOut; + $this->updateToDatabase($payload['uDataSendIn'], $response, $smsBatch); + } + } + + protected function payload($userData): array + { + $data = []; + foreach ($this->collection as $key => $item) { + $data[$key] = $this->prepareData($item, $userData); + } + return array( + 'uUsername' => $this->config['username'], + 'uPassword' => $this->config['password'], + 'uDataSendIn' => $data + ); + } + + protected function prepareData(Model $model, $userData): array + { + $fillable = is_null($userData) ? $model : $userData; + + return [ + 'ClientID' => rand(1, 1000000000000000), + 'ShortCode' => $this->findFrom(), + 'Cellphone' => $model->getPhone(), + 'Message' => $this->messagePatternClass->fill($fillable), + 'Farsi' => true, + 'Flash' => false, + 'UDH' => '', + 'ServiceID' => '' + ]; + } + + protected function findFrom() + { + $smsOperatorConfig = collect(config('notification.config_system')); + + if (is_null($smsOperatorConfig) or $smsOperatorConfig->isEmpty()) { + return $this->config['from']; + } + + $customConfig = $smsOperatorConfig->getConfig($this->operator); + + if (is_null($customConfig)) { + return $this->config['from']; + } + + return $customConfig['from']; + } + + protected function serializeToDatabase($payload, $response): void + { + $this->collection->count() > 1 ?: $response = [$response]; + event(new SmsSent($this->collection, json_decode(json_encode($response), true), $payload, $this->config)); + } + + protected function updateToDatabase($payload, $response, $smsBatch): void + { + $this->collection->count() > 1 ?: $response = [$response]; + event(new SmsSentAgain($this->collection, json_decode(json_encode($response), true), $payload, $this->config, $smsBatch)); + } + + protected function createExtra($category, $uniqueCode): array + { + $extra ['is_admin'] = $this->isAdmin; + $extra ['is_systematic'] = $this->isSystematic; + $extra ['category'] = $category; + $extra ['operator'] = 'rahyab_advertise'; + $extra ['code'] = $uniqueCode; + $extra ['messagePattern'] = $this->messagePattern; + $extra['className'] = $this->collection->isEmpty() ? null : getNamespaceMap($this->collection->first()); + return $extra; + } + + private function setIsAdminAndIsSystematicInConfig(): void + { + $this->config['is_admin'] = $this->isAdmin; + $this->config['is_systematic'] = $this->isSystematic; + } +} diff --git a/app/Services/Notification/Batch/SimCard.php b/app/Services/Notification/Batch/SimCard.php new file mode 100644 index 00000000..d65cd3ed --- /dev/null +++ b/app/Services/Notification/Batch/SimCard.php @@ -0,0 +1,143 @@ +collection = $collection; + $this->messagePatternClass = new Pattern( $message ); + $this->messagePattern = $this->messagePatternClass->getPattern(); + $this->config = array_merge( $this->createExtra( $category , $uniqueCode ) , config( 'notification.drivers.simcard' ) ); + + if ( isset( $this->config[ 'operator' ] ) ) { + $this->config[ 'type' ] = 'simcard'; + } + + $this->client = new \SoapClient( $this->config[ 'url' ] , array( 'trace' => 1 ) ); + } + + public function isSystematic( $isSystematic = 0 ): static + { + $this->isSystematic = $isSystematic; + return $this; + } + + public function isAdmin( $isAdmin = 0 ): static + { + $this->isAdmin = $isAdmin; + return $this; + } + + public function send( $userData ): void + { + if ( $this->collection->count() <= config( 'notification.max_phone_size.do_send_sms_array_c' ) ) { + $this->setIsAdminAndIsSystematicInConfig(); + $payload = $this->payload( $userData ); + $response = $this->client->SendSMS( $payload[ 'from' ] , $payload[ 'numbers' ] , $payload[ 'messages' ] , $payload[ 'username' ] , $payload[ 'password' ] , $payload[ 'time' ] , $payload[ 'op' ] ); + $response = json_decode( $response ); + $this->serializeToDatabase( json_decode( $response[ count( $response ) - 1 ] )[ 1 ] ); + } + } + + public function sendAgain( $userData , SmsBatch $smsBatch ): void + { + if ( $this->collection->count() <= config( 'notification.max_phone_size.do_send_sms_array_c' ) ) { + $payload = $this->payload( $userData ); + $response = $this->client->SendSMS( $payload[ 'from' ] , $payload[ 'numbers' ] , $payload[ 'messages' ] , $payload[ 'username' ] , $payload[ 'password' ] , $payload[ 'time' ] , $payload[ 'op' ] ); + $response = json_decode( $response ); + $this->updateToDatabase( $response , $smsBatch ); + } + } + + protected function payload( $userData ): array + { + $data = [ + 'username' => $this->config[ 'username' ] , + 'password' => $this->config[ 'password' ] , + 'from' => $this->config[ 'from' ] , + 'op' => "pointtopoint" , + 'time' => '' , + ]; + + foreach ( $this->collection as $key => $item ) { + $modelData = $this->prepareData( $item , $userData ); + $this->payload[] = $modelData; + $data[ 'numbers' ][] = $modelData[ 'Cellphone' ]; + $data[ 'messages' ][] = $modelData[ 'Message' ]; + } + + return $data; + } + + protected function prepareData( Model $model , $userData ): array + { + $fillable = is_null( $userData ) ? $model : $userData; + return [ + 'Cellphone' => $model->getPhone() , + 'Message' => $this->messagePatternClass->fill( $fillable ) , + ]; + } + + protected function serializeToDatabase( $response ): void + { + $response = $this->prepareResponse( $response ); + event( new SmsSent( $this->collection , json_decode( json_encode( $response ) , true ) , $this->payload , $this->config ) ); + } + + + protected function updateToDatabase( $response , $smsBatch ): void + { + $response = $this->prepareResponse( $response ); + event( new SmsSentAgain( $this->collection , json_decode( json_encode( $response ) , true ) , $this->payload , $this->config , $smsBatch ) ); + } + + protected function prepareResponse( $response ): array + { + $result = []; + foreach ( $response as $value ) { + $result[] = [ + 'ClientID' => null , + 'ServerID' => is_numeric( $value ) ? $value : -1 , + 'Status' => is_numeric( $value ) ? 'Send OK.' : $value , + ]; + } + return $result; + } + + protected function createExtra( $category , $uniqueCode ): array + { + $extra [ 'is_admin' ] = $this->isAdmin; + $extra [ 'is_systematic' ] = $this->isSystematic; + $extra [ 'category' ] = $category; + $extra [ 'operator' ] = 'simcard'; + $extra [ 'code' ] = $uniqueCode; + $extra [ 'messagePattern' ] = $this->messagePattern; + $extra [ 'className' ] = $this->collection->isEmpty() ? null : getNamespaceMap( $this->collection->first() ); + return $extra; + } + + private function setIsAdminAndIsSystematicInConfig(): void + { + $this->config[ 'is_admin' ] = $this->isAdmin; + $this->config[ 'is_systematic' ] = $this->isSystematic; + } + } diff --git a/app/Services/Notification/Events/SmsSent.php b/app/Services/Notification/Events/SmsSent.php new file mode 100644 index 00000000..b337629d --- /dev/null +++ b/app/Services/Notification/Events/SmsSent.php @@ -0,0 +1,32 @@ +collection = $collection; + $this->response = $response; + $this->payload = $payload; + $this->extra = $extra; + } + } diff --git a/app/Services/Notification/Events/SmsSentAgain.php b/app/Services/Notification/Events/SmsSentAgain.php new file mode 100644 index 00000000..923e301f --- /dev/null +++ b/app/Services/Notification/Events/SmsSentAgain.php @@ -0,0 +1,36 @@ +collection = $collection; + $this->response = $response; + $this->payload = $payload; + $this->extra = $extra; + $this->smsBatch = $smsBatch; + } + } diff --git a/app/Services/Notification/Listeners/StoreSmsInDatabase.php b/app/Services/Notification/Listeners/StoreSmsInDatabase.php new file mode 100644 index 00000000..0a3c56c4 --- /dev/null +++ b/app/Services/Notification/Listeners/StoreSmsInDatabase.php @@ -0,0 +1,52 @@ + 0 ? : 60; + $smsList = []; + + foreach ( $event->collection as $key => $value ) { + $smsList[ $key ] = new Sms( [ + 'client_id' => $event->response[ $key ][ 'ClientID' ] , + 'status' => $event->response[ $key ][ 'Status' ] , + 'message' => $event->payload[ $key ][ 'Message' ] , + 'rel_id' => $value->id , + 'segment_count' => ceil( strlen( $event->extra[ 'messagePattern' ] ) / $chars_in_every_sms_part ) , + 'cell_number' => $event->payload[ $key ][ 'Cellphone' ] , + 'rel_type' => $event->extra[ 'className' ] , + 'fee' => $event->extra[ 'fee' ] , + ] ); + } + + Log::alert( 'store SmsBatch' , [ 'hasSms' => SmsBatch::where( 'code' , $event->extra[ 'code' ] )->first() ] ); + + $smsBatch = SmsBatch::firstOrCreate( + [ + 'code' => $event->extra[ 'code' ] + ] , + [ + 'category' => $event->extra[ 'category' ] , + 'operator' => $event->extra[ 'operator' ] , + 'type' => $event->extra[ 'type' ] , + 'pattern' => $event->extra[ 'messagePattern' ] , + 'is_admin' => $event->extra[ 'is_admin' ] , + 'is_systematic' => $event->extra[ 'is_systematic' ] , + 'from' => $event->extra[ 'from' ] , + ] + ); + + $smsBatch->smsList()->saveMany( $smsList ); + } + } diff --git a/app/Services/Notification/MessagePattern/Pattern.php b/app/Services/Notification/MessagePattern/Pattern.php new file mode 100644 index 00000000..7b498fc9 --- /dev/null +++ b/app/Services/Notification/MessagePattern/Pattern.php @@ -0,0 +1,70 @@ +pattern = $pattern; + } + + public function fill( $model ): string + { + $replacements = $this->findReplacements( $model ); + return strtr( $this->pattern , $replacements ); + } + + protected function findReplacements( $model , $prefix = '{' , $postfix = '}' ): array + { + $replacements = []; + foreach ( $model->messageFields as $field ) { + list( $nickName , $value ) = $this->getFieldValue( $model , $field ); + $replacements[ $prefix . $nickName . $postfix ] = $value; + } + if ( config( 'notification.fields' ) ) { + foreach ( config( 'notification.fields' ) as $name => $field ) { + $replacements[ $prefix . $name . $postfix ] = $field; + } + } + return $replacements; + } + + protected function getFieldValue( Model $model , string $messageField ): array + { + $parts = explode( ' as ' , $messageField ); + if ( count( $parts ) == 2 and $this->isRelation( $parts[ 0 ] ) ) { + list( $relation , $field ) = $this->splitRelationField( $parts[ 0 ] ); + $model->loadMissing( $relation ); + $key = $parts[ 1 ]; + $value = $model->$relation ? $model->$relation->$field : ''; + } else { + $key = $messageField; + $value = $model->$messageField; + } + return [ $key , $value ]; + } + + protected function isRelation( $field ): bool + { + return str_contains( $field , ':' ); + } + + protected function splitRelationField( $field ): array + { + $parts = explode( ':' , $field ); + $partsCount = count( $parts ); + return [ implode( '.' , array_slice( $parts , 0 , $partsCount - 1 ) ) , $parts[ $partsCount - 1 ] ]; + } + + public function getPattern(): string + { + return $this->pattern; + } + + } diff --git a/app/Services/Notification/SendSmsToAdmins.php b/app/Services/Notification/SendSmsToAdmins.php new file mode 100644 index 00000000..39541d6e --- /dev/null +++ b/app/Services/Notification/SendSmsToAdmins.php @@ -0,0 +1,46 @@ +mobiles = [ + "09101526570", + "09128529050" + ]; + } + + public function sendRequestNotification($device_title, $smsUser) + { + $adminCollection = User::query() + ->orWhere('role', 'admin'); + + $adminText = "کاربر %s +با شماره ی همراه %s +درخواستی زیر را ثبت کرد\n +%s\n"; + $adminText = sprintf($adminText, $smsUser->full_name, $smsUser->cell_number, $device_title); + SmsNotification::to($adminCollection)->isSystematic()->send( + $adminText, + 'service' + ); + + + $userText = "%s عزیز\n +درخواست شما را دریافت کردیم\n +به زودی همکاران ما با شما تماس خواهند گرفت\n +از اعتماد شما سپاسگزاریم\n"; + $userText = sprintf($userText, $smsUser->full_name); + $userCollection = User::query()->where('id', $smsUser->id); + $res = SmsNotification::to($userCollection)->isSystematic()->send( + $userText, + 'service' + ); + } +} diff --git a/app/Services/Notification/SmsNotification.php b/app/Services/Notification/SmsNotification.php new file mode 100644 index 00000000..c4e1a241 --- /dev/null +++ b/app/Services/Notification/SmsNotification.php @@ -0,0 +1,121 @@ +builder = $builder; + $this->userData = $userData; + $this->category = $this->builder->limit(2)->count() > 1 ? 'batch' : 'single'; + + } + + public function setBuilder($builder): static + { + $this->builder = $builder; + $this->category = $this->builder->limit(2)->count() > 1 ? 'batch' : 'single'; + return $this; + } + + public function setUserData($userData): static + { + $this->userData = $userData; + return $this; + } + + public static function to($builder, $userData = null) + { + if (static::$self === null) { + static::$self = new static($builder, $userData); + } + return static::$self; + } + + public function isSystematic(): static + { + $this->isSystematic = true; + return $this; + } + + public function isAdmin(): static + { + $this->isAdmin = true; + return $this; + } + + public function sendAgain(SmsBatch $smsBatch): void + { + $uniqueCode = Str::random(40); + foreach ($this->chuncks() as $notification) { + switch ($smsBatch->type) { + case 'advertise': + (new PeerToPeer($smsBatch->pattern, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->sendAgain($this->userData, + $smsBatch); + break; + case 'simcard' : + (new SimCard($smsBatch->pattern, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->sendAgain($this->userData, $smsBatch); + break; + case 'service': + (new PeerToPeer($smsBatch->pattern, $notification, $this->category, $uniqueCode, 'service'))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->sendAgain($this->userData, + $smsBatch); + break; + } + } + } + + public function send($message, $method = 'advertise'): void + { + $uniqueCode = Str::random(40); + foreach ($this->chuncks() as $notification) { + switch ($method) { + case 'advertise': + (new PeerToPeer($message, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->send($this->userData); + break; + case 'simcard' : + (new SimCard($message, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->send($this->userData); + break; + case 'service': + (new PeerToPeer($message, $notification, $this->category, $uniqueCode, 'service'))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->send($this->userData); + break; + } + } + } + + public function sendWithTemplate($template): void + { + if ( ! is_null($template)) { + $this->send($template->template, $template->operator); + } + } + + protected function chuncks(): \Generator + { + $limit = config('notification.max_phone_size.do_send_sms_array_c'); + $iteration = 0; + while (true) { + $offset = $iteration * $limit; + $chunk = $this->builder->offset($offset)->limit($limit)->get(); + if ($chunk->isEmpty()) { + break; + } + $iteration++; + yield $chunk; + } + } + +} diff --git a/config/notification.php b/config/notification.php new file mode 100644 index 00000000..b0c53682 --- /dev/null +++ b/config/notification.php @@ -0,0 +1,125 @@ + 'willaengine', + + 'morph_models' => [], + + /* + |-------------------------------------------------------------------------- + | Default Driver + |-------------------------------------------------------------------------- + | + | This value determines which of drivers should be used. + | + */ + 'default' => 'advertise', + + /* + |-------------------------------------------------------------------------- + | Notification Configs + |-------------------------------------------------------------------------- + | + | These are the list of configs to use for sending sms. + | + */ + + 'drivers' => [ + 'advertise' => [ + 'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl', + 'username' => env('SMS_USERNAME'), + 'password' => env('SMS_PASSWORD'), + 'from' => env('SMS_NUMBER_ADVERTISE'), + ], + 'service' => [ + 'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl', + 'username' => env('SMS_USERNAME'), + 'password' => env('SMS_PASSWORD'), + 'from' => env('SMS_NUMBER_SERVICE'), + ], + 'simcard' => [ + 'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl', + 'username' => env('SMS_USERNAME'), + 'password' => env('SMS_PASSWORD'), + 'from' => env('SMS_NUMBER_SIM_CARD'), + 'fee' => 150 + ], + 'pattern' => [ + 'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl', + 'username' => env('SMS_USERNAME'), + 'password' => env('SMS_PASSWORD'), + 'from' => env('SMS_NUMBER_SERVICE'), + ], + 'rahyab_advertise' => [ + 'url' => 'https://sms.igama.ir/webservice/sms.asmx?wsdl', + 'username' => env('RAHYAB_SMS_USERNAME'), + 'password' => env('RAHYAB_SMS_PASSWORD'), + 'from' => env('RAHYAB_SMS_NUMBER_ADVERTISE'), + 'fee' => 100 + ], + 'rahyab_service' => [ + 'url' => 'https://sms.igama.ir/webservice/sms.asmx?wsdl', + 'username' => env('RAHYAB_SMS_USERNAME'), + 'password' => env('RAHYAB_SMS_PASSWORD'), + 'from' => env('RAHYAB_SMS_NUMBER_SERVICE'), + 'fee' => 80 + ], + ], + + + /* + |-------------------------------------------------------------------------- + | Class Maps + |-------------------------------------------------------------------------- + | + | This is the array of Classes that maps to Drivers above. + | + */ + 'map' => [ + 'advertise' => Sms::class, + 'service' => Sms::class, + 'simcard' => Sms::class, + 'pattern' => SmsPattern::class, + 'rahyab_advertise' => HelloWorld::class, + ], + + /* + |-------------------------------------------------------------------------- + | Fields Pattern + |-------------------------------------------------------------------------- + | + | This is the array of fields that used in sms patterns. + | + */ + + 'fields' => [ + 'time' => now('Asia/Tehran')->format('H:i:s'), + 'date' => now('Asia/Tehran')->format('Y/m/d') + ], + + /* + |-------------------------------------------------------------------------- + | MAXIMUM NUMBER OF PHONE NUMBERS IN ONE BATCH + |-------------------------------------------------------------------------- + | + | CAUTION!! DONT TOUCH THESE NUMBERS + | + */ + + 'max_phone_size' => [ + 'do_send_sms' => 83, + 'do_send_sms_array_c' => 100, + ], + 'max_update_devlivery_status_bulk_items' => 100, + 'sms_length_calculator' => [ + 'encoding' => '8', //bit + 'chars_in_every_sms_part' => 63 + ], + + + 'config_system' => [], + +]; diff --git a/database/migrations/2025_05_01_142512_create_sms_table.php b/database/migrations/2025_05_01_142512_create_sms_table.php new file mode 100644 index 00000000..5996ab6b --- /dev/null +++ b/database/migrations/2025_05_01_142512_create_sms_table.php @@ -0,0 +1,37 @@ +increments( 'id' ); + $table->unsignedBigInteger( 'client_id' )->nullable(); + $table->string( 'status' ); + $table->string( 'message' , 100 ); + $table->unsignedInteger( 'rel_id' ); + $table->string( 'rel_type' , 50 ); + $table->string( 'cell_number' , 20 ); + $table->unsignedInteger( 'fee' )->default( 0 ); + $table->unsignedInteger( 'sms_batch_id' ); + $table->index( 'sms_batch_id' ); + $table->integer( 'segment_count' )->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('sms'); + } +}; diff --git a/database/migrations/2025_05_01_142536_create_sms_batch_table.php b/database/migrations/2025_05_01_142536_create_sms_batch_table.php new file mode 100644 index 00000000..134760e1 --- /dev/null +++ b/database/migrations/2025_05_01_142536_create_sms_batch_table.php @@ -0,0 +1,36 @@ +increments( 'id' ); + $table->string( 'category' ); + $table->string( 'operator' , 100 ); + $table->enum( 'type' , [ 'service' , 'simcard' , 'advertise' ] ); + $table->string( 'code' , 40 ); + $table->string( 'pattern' )->nullable(); + $table->boolean( 'is_admin' )->default( 0 ); + $table->boolean( 'is_systematic' )->default( 0 ); + $table->string( 'from' )->nullable(); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('sms_batch'); + } +}; diff --git a/packages/Auth/SendsPasswordResetEmails.php b/packages/Auth/SendsPasswordResetEmails.php index 6fe2662b..aa061a91 100644 --- a/packages/Auth/SendsPasswordResetEmails.php +++ b/packages/Auth/SendsPasswordResetEmails.php @@ -4,10 +4,11 @@ namespace Packages\Auth; use App\Http\Controllers\Api\Auth\LoginController; use App\Models\User; +use App\Services\Notification\SmsNotification; use Carbon\Carbon; use Illuminate\Http\Request; use Packages\Messaging\src\Facades\MessageResponse; -use Packages\SMSSender\SMSSender; +// use Packages\SMSSender\SMSSender; trait SendsPasswordResetEmails { @@ -61,7 +62,13 @@ trait SendsPasswordResetEmails if ($user) { $code = rand(100000, 999999); \Cache::put($code, $user->id, Carbon::now()->addMinutes(30)); - SMSSender::instance()->patternSend($request->cell_number, 'jqomyn42wo', ["verification-code" => $code]); + SmsNotification::to( $user )->isSystematic()->send( + trans( 'sms.reset_password' , [ + 'activation_code' => $code + ] ) , + 'service' + ); + // SMSSender::instance()->patternSend($request->cell_number, 'jqomyn42wo', ["verification-code" => $code]); return MessageResponse::success('Send Disposable Password'); } return MessageResponse::error('User Not Found'); diff --git a/resources/lang/en/sms.php b/resources/lang/en/sms.php new file mode 100644 index 00000000..f376c824 --- /dev/null +++ b/resources/lang/en/sms.php @@ -0,0 +1,5 @@ + 'لطفا پس از ورود یک پسوورد جدید بذارید', +];