Files
2026-08-27 21:17:02 +08:00

179 lines
5.3 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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');
}
}