Xây dựng hệ thống nạp tiền ngân hàng
Như các bạn đã biết thì hiện nay các ngân hàng Việt Nam hiện nay không cung cấp API cho các bên phát triển .Với việc phát triển thanh toán online hiện nay chúng ta muốn 1 sự thuận tiện tối đa cho khách thanh toán khi mua các sản phẩm bên mình . Và việc thanh toán online qua ngân hàng cũng dần trở thành 1 vấn đề cần thiết .
Về mục đích thì chúng ta muốn thanh toán qua ngân hàng thực tế thì chưa có bên nào có api chính thức từ ngân hàng ,dùng nguồn thứ 3 thì không yên tâm về việc bảo mật thông tin .
Về thực tế thì ta nhận thấy ngân hàng có 2 phương thức thông báo cho chúng ta ,1 là thông báo qua app ,2 là thông báo qua sms .Can thiệp vào app ngân hàng thì khó mà can thiệp đọc tin nhắn thì dễ .Mà đời cái nào dễ thì ta làm trước .Nên hôm nay mình sẽ hướng dẫn các bạn cách xây dựng hệ thống nạp tiền ngân hàng qua đọc tin nhắn sms
Chuẩn bị :
- Laravel start kits : Laravel Breeze mình dùng bản này cho nhẹ
- Tải file apk cài đặt trên điện thoại android tại đây
- Vào https://smsgateway.me/ để đăng kí 1 tài khoản
Ok vậy tiếp theo chúng ta sẽ code hệ thống nạp tiền qua ngân hàng:
I Migration các bảng dữ liệu
Để tạo các bảng dữ liệu ta chạy các command sau :
1 Tạo bảng sms lưu thông tin sms về
php artisan make:migration create_sms_table
Code như sau :
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('sms', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('id_sms');
$table->unsignedBigInteger('deviceId')->nullable();
$table->string('message',500)->nullable();
$table->string('status',50)->nullable();
$table->tinyInteger('stautus_read_sms')->default(0)->comment('trạng thái đọc dữ liệu 0 là chưa xử lý 1 là xử lý ');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('sms');
}
};
2 Tạo bảng trans lưu thông tin di chuyển của dòng tiền
php artisan make:migration create_trans_table
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('trans', function (Blueprint $table) {
$table->id();
$table->integer('from')->comment('tài khoản đến');
$table->integer('to')->comment('tài khoản nhận');
$table->integer('amount')->comment('Số tiền');
$table->integer('before_transaction')->comment('Số dư trước giao dịch của người gửi mục đích là kiểm tra trước khi gửi xem đủ tiền không')->default(0);
$table->unsignedTinyInteger('source')->comment('0 là nạp tiền vào tài khoản ,1 là thanh toán trong tài khoản ,2 là rút ra ngoài tài khoản')->default(0);
$table->string('content')->comment('Nội dung chuyển tiền');
$table->integer('id_sms')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('trans');
}
};
3 : Tạo thêm cột coin trong user table
php artisan make:migration add_coin_collum_to_users_table
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->integer('coin')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
//
});
}
};
II Tạo service API
Chúng ta tạo 1 service app/Service/APISMS.php như sau :
namespace App\Service;
use App\Jobs\AddMoneyToAccount;
use App\Models\Sms;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use SMSGatewayMe\Client\Api\MessageApi;
use SMSGatewayMe\Client\ApiClient;
use SMSGatewayMe\Client\Configuration;
class APISMS
{
public static function readsms($device_id, $last_id = 0)
{
$config = Configuration::getDefaultConfiguration();
$config->setApiKey('Authorization', env('SMS_API'));
$api_client = new ApiClient($config);
$messageClient = new MessageApi($api_client);
$messages = $messageClient->searchMessages([
'filters' => [
[
[
'field' => 'device_id',
'operator' => '=',
'value' => $device_id,
],
[
'field' => 'status',
'operator' => '=',
//'value' => 'sent'
'value' => 'Received',
],
[
'field' => 'id',
'operator' => '>',
//'value' => 'sent'
// 'value' => '186799770',
'value' => $last_id,
],
],
],
'order_by' => [
[
'field' => 'created_at',
'direction' => 'ASC'
//'direction' => 'DESC'
],
[
'field' => 'device_id',
'direction' => 'DESC'
]
],
'limit' => 15,
// 'offset' => 10
]
);
return $messages['results'];
}
public static function transsms($sms_kitu = '',$user)
{
// truy vấn dữ liệu mà chưa xử lý vào trong database với thời gian cách 1 tiếng trước
$sms_return = DB::table('sms')->where([['message', 'LIKE', '%' . $sms_kitu . '%'], ['stautus_read_sms', 0],['created_at','>',Carbon::now()->subHours(1)]])
->get(['id', 'stautus_read_sms', 'message']);
if(count($sms_return) > 0)
{
foreach ($sms_return as $key => $value) {
$subject = $value->message;
preg_match_all('/^(.+):\s(\+|-)(.+)VND\s\((.+)$/', $subject, $match);
$sotien_string = $match[3];
$array_thongtin = $match[4][0];
$sotien = str_replace(',', '', $sotien_string[0]);
$return_data['sotien'] = $sotien;
preg_match('/^(.+)\).(.+)$/', $array_thongtin, $match1);
$noidung_chuyenkhoan = $match1[1];
// tìm kiếm chuỗi trong nội dung
$search = strpos($noidung_chuyenkhoan,$user->name);
if($search)
{
$return_data['noidung'] = $noidung_chuyenkhoan;
$return_data['id'] = $value->id;
$return_data['to'] = $user->id;
//xử lý dữ liệu nạp tiền vào tài khoản
AddMoneyToAccount::dispatch($return_data);
}
}
return 1;
}
else{
return 0;
}
}
}
3 Tạo command chạy auto
Tiếp theo chúng ta tạo command để chạy auto quá trình nạp tiền
php artisan make:command SmsTrans
php artisan make:command SmsUpdate
Ở file app/Console/Commands/SmsUpdate.php
namespace App\Console\Commands;
use App\Models\Sms;
use App\Service\APISMS;
use Illuminate\Console\Command;
class SmsUpdate extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sms:update';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Update sms từ server smsgateway về database';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$deviced_id = 129188;
$last_sms = Sms::latest('id')->first();
// nếu có dữ liệu trong bảng sms
if($last_sms)
{
$return_data = APISMS::readsms($deviced_id,$last_sms['id_sms']);
foreach ($return_data as $return_datum) {
$data_input['id_sms'] = $return_datum['id'];
$data_input['deviceId'] = $return_datum['deviceId'];
$data_input['message'] = $return_datum['message'];
$data_input['status'] = $return_datum['status'];
$result_create = Sms::create($data_input);
}
}
else
{
$return_data = APISMS::readsms($deviced_id);
foreach ($return_data as $return_datum) {
$data_input['id_sms'] = $return_datum['id'];
$data_input['deviceId'] = $return_datum['deviceId'];
$data_input['message'] = $return_datum['message'];
$data_input['status'] = $return_datum['status'];
$result_create = Sms::create($data_input);
}
}
return 0;
}
}
Ở file app/Console/Commands/SmsTrans.php
namespace App\Console\Commands;
use App\Models\User;
use App\Service\APISMS;
use Illuminate\Console\Command;
class SmsTrans extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sms:trans';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Cộng tiền cho người dùng khi nạp thành công';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// lấy tất cả người dùng
$alluser = User::all();
foreach ($alluser as $user) {
// sau đó kiểm tra dựa trên name
$data = APISMS::transsms('Agribank',$user);
}
return 0;
}
}
Để schedule được ta phải thêm 2 command vào trong file app/Console/Kernel.php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
$schedule->command('sms:update')->everyMinute();
$schedule->command('sms:trans')->everyMinute();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
4 Chạy chương trình
Chúng ta chạy lệnh để chạy chương trình :
php artisan serve
Tiếp theo chạy command sau :
php artisan schedule:run
kết quả nhận được
Link code github ở cuối bài .Các bạn có thể download về tham khảo