原因:
最近因為專案(基於laravel)需要一個使用者錢包功能,於是準備手擼一個,分析了一下我們專案對錢包需求的功能點,大概有:充值、消費(購買平臺服務)、轉賬、提現、並且需要檢視所有的資金變動記錄。
契機:
本著程式設計師最高的神聖規則:不重複製造輪子 。在 github 上搜尋 wallet,果然有人開源了一個:https://github.com/bavix/laravel-wallet 有兩百多個 start ,懷著試試的想法,我探索一下。
搭建實驗室:
安裝laravel框架:composer create-project --prefer-dist laravel/laravel laravel
修改.env 的資料
引入UI:composer require laravel/ui
建立使用者系統:artisan ui vue --auth
執行遷移:artisan migrate
編譯資源:yarn dev
開始引入laravel-wallet:
引入laravel-wallet:composer require bavix/laravel-wallet
【如果是用lumen需要在bootstrap/app.php新增:
$app->register(\Bavix\Wallet\WalletServiceProvider::class);】
生成遷移檔案:artisan vendor:publish --tag=laravel-wallet-migrations
生成配置檔案:artisan vendor:publish --tag=laravel-wallet-config
資料庫中增加了三張表:
wallet表:
transfers:表
transactions表:
開始簡單的測試:
先在系統中註冊兩個使用者,conner1, conner2;
修改 User 模型:
use Bavix\Wallet\Traits\HasWallet;
use Bavix\Wallet\Interfaces\Wallet;
class User extends Model implements Wallet {
use HasWallet;
}
然後修改 預設的 HomeControoler.php, 根據文件測試功能
public function index(){
//獲取當前使用者
$user = Auth::user();
//初始化錢包
$user->balance;
}
上面程式碼會在 wallet 中建立一條使用者關聯的錢包,格式如下:
接下來我們看看簡單的充值和提現功能
public function index(){
//獲取當前使用者
$user = Auth::user();
//初始化錢包
$user->balance;
//充值 100
$user->deposit(100);
//列印看一下是個啥
dd($user->balance); // 字串型別的一百
// 繼續充兩次看看資料庫有些什麼記錄
$user->deposit(100);
$user->deposit(100);
}
transactions表中有這樣三條記錄:
wallet表中為:
然後繼續,我們試試提現:
$user->withdrap(50);
transactions表 增加一條記錄:
wallet表 少50
到目前沒感覺不到有什麼特殊的地方,接下來我們來看看程式碼是怎麼實現的,首先是充值,deposit():
首先這個 Bavix\Wallet\Interfaces\Wallet 檔案中找到方法如下
/**
* @param int $amount
* @param array|null $meta
* @param bool $confirmed
* @return Transaction
*/
public function deposit($amount, ?array $meta = null, bool $confirmed = true): Transaction;
註釋很清楚,繼續看 trait Bavix\Wallet\Traits\HasWallet; 中
/**
* The input means in the system
*
* @param int $amount
* @param array|null $meta
* @param bool $confirmed
*
* @return Transaction
* @throws
*/
public function deposit($amount, ?array $meta = null, bool $confirmed = true): Transaction
{
$self = $this;
return app(DbService::class)->transaction(static function () use ($self, $amount, $meta, $confirmed) {
return app(CommonService::class)
->deposit($self, $amount, $meta, $confirmed);
});
}
到這裡還是沒有看到處理邏輯,只是加了一個當前錢包例項進去,$self,繼續深入,在commonService中:
/**
* @param Wallet $wallet
* @param int $amount
* @param array|null $meta
* @param bool $confirmed
* @return Transaction
*/
public function deposit(Wallet $wallet, $amount, ?array $meta, bool $confirmed = true): Transaction
{
return app(LockService::class)->lock($this, __FUNCTION__, function () use ($wallet, $amount, $meta, $confirmed) {
$walletService = app(WalletService::class);
$walletService->checkAmount($amount);
/**
* @var WalletModel $wallet
*/
$wallet = $walletService->getWallet($wallet);
$transactions = $this->multiOperation($wallet, [
app(Operation::class)
->setType(Transaction::TYPE_DEPOSIT)
->setConfirmed($confirmed)
->setAmount($amount)
->setMeta($meta)
]);
return current($transactions);
});
}
這裡就是具體的呼叫了,驗證金額等,呼叫 Operation 定義的方法 來處理。
感覺還是挺優雅的………
有興趣的童鞋一起來探索吧:
bavix.github.io/laravel-wallet/
本作品採用《CC 協議》,轉載必須註明作者和本文連結