179 lines
5.3 KiB
PHP
179 lines
5.3 KiB
PHP
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||
use Modules\SystemTool\Models\SysFileModel;
|
||
use Modules\SystemUser\Models\SysUserModel;
|
||
|
||
/**
|
||
* 支付记录模型(小程序选择门店账单合并付款)
|
||
*
|
||
* 支付类型 pay_type:
|
||
* - 1 线下凭证支付:门店提交汇款凭证,后台审核通过后关联账单批量置已支付
|
||
* - 2 旺铺在线支付:调起微信/支付宝在线支付,网关回调(或主动查询)确认后自动结账
|
||
*/
|
||
class PaymentModel extends Model
|
||
{
|
||
use HasFactory;
|
||
|
||
/** 支付类型:线下凭证支付 */
|
||
public const int TYPE_OFFLINE = 1;
|
||
/** 支付类型:旺铺在线支付 */
|
||
public const int TYPE_ONLINE = 2;
|
||
|
||
/** 支付类型中文名 */
|
||
public const array TYPE_NAMES = [
|
||
self::TYPE_OFFLINE => '凭证支付',
|
||
self::TYPE_ONLINE => '在线支付',
|
||
];
|
||
|
||
/** 支付方式:微信 */
|
||
public const int METHOD_WECHAT = 1;
|
||
/** 支付方式:支付宝 */
|
||
public const int METHOD_ALIPAY = 2;
|
||
/** 支付方式:对公汇款(银行卡) */
|
||
public const int METHOD_BANK = 3;
|
||
/** 支付方式:旺铺在线支付(微信/支付宝小程序 JSAPI) */
|
||
public const int METHOD_WANGPU = 4;
|
||
|
||
/** 支付方式中文名 */
|
||
public const array METHOD_NAMES = [
|
||
self::METHOD_WECHAT => '微信支付',
|
||
self::METHOD_ALIPAY => '支付宝',
|
||
self::METHOD_BANK => '对公汇款',
|
||
self::METHOD_WANGPU => '旺铺支付',
|
||
];
|
||
|
||
/** 状态:待审核(线下凭证)/ 待支付(在线支付) */
|
||
public const int STATUS_PENDING = 0;
|
||
/** 状态:已通过(线下凭证)/ 支付成功(在线支付) */
|
||
public const int STATUS_APPROVED = 1;
|
||
/** 状态:已拒绝(线下凭证)/ 支付失败(在线支付) */
|
||
public const int STATUS_REJECTED = 2;
|
||
|
||
/** 状态中文名 */
|
||
public const array STATUS_NAMES = [
|
||
self::STATUS_PENDING => '待审核',
|
||
self::STATUS_APPROVED => '已通过',
|
||
self::STATUS_REJECTED => '已拒绝',
|
||
];
|
||
|
||
/** 在线支付状态中文名(pay_type=2 时使用) */
|
||
public const array ONLINE_STATUS_NAMES = [
|
||
self::STATUS_PENDING => '待支付',
|
||
self::STATUS_APPROVED => '支付成功',
|
||
self::STATUS_REJECTED => '支付失败',
|
||
];
|
||
|
||
protected $table = 'payment';
|
||
protected $primaryKey = 'id';
|
||
|
||
protected $fillable = [
|
||
'payment_no',
|
||
'store_id',
|
||
'amount',
|
||
'pay_type',
|
||
'pay_method',
|
||
'voucher_ids',
|
||
'status',
|
||
'order_id',
|
||
'trade_no',
|
||
'openid',
|
||
'paid_at',
|
||
'pay_params',
|
||
'remark',
|
||
'audited_at',
|
||
'auditor_id',
|
||
'audit_remark',
|
||
];
|
||
|
||
protected $casts = [
|
||
'store_id' => 'integer',
|
||
'amount' => 'decimal:2',
|
||
'pay_type' => 'integer',
|
||
'pay_method' => 'integer',
|
||
'status' => 'integer',
|
||
'paid_at' => 'datetime:Y-m-d H:i:s',
|
||
'audited_at' => 'datetime:Y-m-d H:i:s',
|
||
'auditor_id' => 'integer',
|
||
'created_at' => 'datetime:Y-m-d H:i:s',
|
||
];
|
||
|
||
/**
|
||
* 旺铺下单返回的调起支付参数(JSON 字符串 ↔ 数组)
|
||
*
|
||
* @return Attribute<array<string, mixed>, string>
|
||
*/
|
||
public function payParams(): Attribute
|
||
{
|
||
return Attribute::make(
|
||
get: fn ($value) => $value === '' || $value === null ? [] : (json_decode((string) $value, true) ?: []),
|
||
set: fn ($value) => is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 汇款凭证图片ID(逗号分隔字符串 ↔ 数组)
|
||
*/
|
||
public function voucherIds(): Attribute
|
||
{
|
||
return Attribute::make(
|
||
get: fn ($value) => $value === '' || $value === null ? [] : explode(',', (string) $value),
|
||
set: fn ($value) => is_array($value) ? implode(',', $value) : $value,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 汇款凭证图片URL列表(保持提交顺序)
|
||
*
|
||
* @return string[]
|
||
*/
|
||
public function voucherUrls(): array
|
||
{
|
||
$ids = array_map('intval', $this->voucher_ids);
|
||
if ($ids === []) {
|
||
return [];
|
||
}
|
||
$urls = [];
|
||
foreach (SysFileModel::query()->whereIn('id', $ids)->get() as $file) {
|
||
$urls[$file->id] = $file->preview_url;
|
||
}
|
||
$result = [];
|
||
foreach ($ids as $id) {
|
||
if (isset($urls[$id])) {
|
||
$result[] = $urls[$id];
|
||
}
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 所属门店(含软删除门店,保证历史记录可见)
|
||
*/
|
||
public function store(): BelongsTo
|
||
{
|
||
return $this->belongsTo(StoreModel::class, 'store_id', 'id')->withTrashed();
|
||
}
|
||
|
||
/**
|
||
* 本支付记录合并付款的账单
|
||
*/
|
||
public function bills(): HasMany
|
||
{
|
||
return $this->hasMany(BillModel::class, 'payment_id', 'id');
|
||
}
|
||
|
||
/**
|
||
* 审核人(后台系统用户)
|
||
*/
|
||
public function auditor(): BelongsTo
|
||
{
|
||
return $this->belongsTo(SysUserModel::class, 'auditor_id', 'id');
|
||
}
|
||
}
|