Xây dựng hệ thống nạp tiền ngân hàng

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ị :

  1. Laravel start kits : Laravel Breeze mình dùng bản này cho nhẹ 
  2. Tải file apk cài đặt trên điện thoại android tại đây 
  3. 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