first
This commit is contained in:
56
modules/Payment/Models/Alipay.php
Normal file
56
modules/Payment/Models/Alipay.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Alipay extends Model
|
||||
{
|
||||
|
||||
use Cachable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'payment_alipays';
|
||||
|
||||
protected $casts = [
|
||||
'log' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* Notes : 生成配置文件
|
||||
*
|
||||
* @Date : 2021/5/26 2:21 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return int[]
|
||||
*/
|
||||
public function toConfig(): array
|
||||
{
|
||||
$ali_public_key = $this->ali_public_key ?? '';
|
||||
if ($this->alipay_cert_path) {
|
||||
$ali_public_key = storage_path('app/'.$this->alipay_cert_path);
|
||||
}
|
||||
|
||||
return [
|
||||
'app_id' => $this->app_id ?? '',
|
||||
'notify_url' => $this->notify_url ?? '',
|
||||
'return_url' => $this->return_url ?? '',
|
||||
'ali_public_key' => $ali_public_key,
|
||||
'app_secret_cert' => $this->private_key ?? '',
|
||||
//应用公钥证书
|
||||
'app_public_cert_path' => $this->app_cert_path ? storage_path('app/'.$this->app_cert_path) : '',
|
||||
//支付宝公钥证书
|
||||
'alipay_public_cert_path' => $this->alipay_cert_path ? storage_path('app/'.$this->alipay_cert_path) : '',
|
||||
'alipay_root_cert_path' => $this->alipay_root_cert_path ? storage_path('app/'.$this->alipay_root_cert_path) : '',
|
||||
'logger' => [
|
||||
'enable' => true,
|
||||
'file' => storage_path('logs/alipay/'.$this->log['file'].'.log'),
|
||||
'level' => $this->log['level'],
|
||||
'type' => $this->log['type'],
|
||||
'max_file' => (int) $this->log['max_file'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
12
modules/Payment/Models/Bill.php
Normal file
12
modules/Payment/Models/Bill.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
|
||||
class Bill extends Model
|
||||
{
|
||||
|
||||
protected $table = 'payment_bills';
|
||||
|
||||
}
|
||||
256
modules/Payment/Models/Payment.php
Normal file
256
modules/Payment/Models/Payment.php
Normal file
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use App\Traits\OrderByIdDesc;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Modules\Payment\Events\Paid;
|
||||
use Modules\Payment\Facades\Pay;
|
||||
use Modules\User\Models\User;
|
||||
use Modules\User\Traits\BelongsToUser;
|
||||
|
||||
class Payment extends Model
|
||||
{
|
||||
|
||||
use BelongsToUser,
|
||||
OrderByIdDesc;
|
||||
|
||||
protected $table = 'payments';
|
||||
|
||||
protected $dates = [
|
||||
'paid_at',
|
||||
];
|
||||
|
||||
const STATUS_NOPAY = 'nopay';
|
||||
const STATUS_SUCCESS = 'success';
|
||||
const STATUS_FAIL = 'fail';
|
||||
const STATUS_REFUND = 'refund';
|
||||
const STATUS_CLOSED = 'closed';
|
||||
const STATUS_REVOKED = 'revoked';
|
||||
const STATUS_ERROR = 'error';
|
||||
const STATUS_FINISHED = 'finished';
|
||||
|
||||
const STATUS_MAP = [
|
||||
self::STATUS_NOPAY => '未支付',
|
||||
self::STATUS_SUCCESS => '支付成功',
|
||||
self::STATUS_FAIL => '支付失败',
|
||||
self::STATUS_REFUND => '转入退款',
|
||||
self::STATUS_CLOSED => '支付关闭',
|
||||
self::STATUS_REVOKED => '支付撤销',
|
||||
self::STATUS_ERROR => '支付错误',
|
||||
self::STATUS_FINISHED => '支付完结',
|
||||
];
|
||||
|
||||
const STATUS_LABEL_MAP = [
|
||||
self::STATUS_NOPAY => 'default',
|
||||
self::STATUS_SUCCESS => 'success',
|
||||
self::STATUS_FAIL => 'warning',
|
||||
self::STATUS_REFUND => 'info',
|
||||
self::STATUS_CLOSED => 'primary',
|
||||
self::STATUS_REVOKED => 'primary',
|
||||
self::STATUS_ERROR => 'danger',
|
||||
self::STATUS_FINISHED => 'success',
|
||||
];
|
||||
|
||||
/**
|
||||
* 支付方式
|
||||
*/
|
||||
const DRIVER_ALIPAY = 'alipay';
|
||||
const DRIVER_WECHAT = 'wechat';
|
||||
const DRIVER_SCORE = 'score';
|
||||
|
||||
const DRIVER_MAP = [
|
||||
self::DRIVER_ALIPAY => '支付宝',
|
||||
self::DRIVER_WECHAT => '微信支付',
|
||||
self::DRIVER_SCORE => '水滴支付',
|
||||
];
|
||||
|
||||
const DRIVER_LABEL_MAP = [
|
||||
self::DRIVER_ALIPAY => 'info',
|
||||
self::DRIVER_WECHAT => 'success',
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
self::creating(function ($model) {
|
||||
$time = explode(' ', microtime());
|
||||
|
||||
$counter = $model->whereDate('created_at', Carbon::today())->count() + 1;
|
||||
|
||||
$len = Setting::orderByDesc('in_use')->value('trade_id_counter_length');
|
||||
|
||||
$len = $len < 6 ? 6 : $len;
|
||||
$len = $len > 16 ? 16 : $len;
|
||||
|
||||
$model->trade_id = date('YmdHis').
|
||||
sprintf('%06d', $time[0] * 1e6).
|
||||
sprintf('%0'.$len.'d', $counter);
|
||||
|
||||
$model->state = self::STATUS_NOPAY;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 支付渠道
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/18 11:14
|
||||
* @return string
|
||||
*/
|
||||
public function getDriverTextAttribute(): string
|
||||
{
|
||||
return self::DRIVER_MAP[$this->driver];
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 支付状态
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/18 11:17
|
||||
* @return string
|
||||
*/
|
||||
public function getStateTextAttribute(): string
|
||||
{
|
||||
return self::STATUS_MAP[$this->state];
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 要支付的模型
|
||||
*
|
||||
* @Date : 2021/4/21 1:59 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function order(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 结果通知
|
||||
*
|
||||
* @Date : 2021/4/23 11:49 上午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function notifies(): HasMany
|
||||
{
|
||||
return $this->hasMany(PaymentNotify::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 退款单
|
||||
*
|
||||
* @Date : 2021/6/1 11:13 上午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function refunds(): HasMany
|
||||
{
|
||||
return $this->hasMany(Refund::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 退款状态
|
||||
*
|
||||
* @Date : 2021/6/1 11:40 上午
|
||||
* @Author : < Jason.C >
|
||||
* @return string
|
||||
*/
|
||||
public function getRefundStatusTextAttribute(): string
|
||||
{
|
||||
if ($this->refunds->count()) {
|
||||
return ($this->refunds->sum('total') == $this->total) ? '全额退款' : '部分退款';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 直接通过 order 来设置关联的支付订单
|
||||
*
|
||||
* @Date : 2021/4/21 12:43 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param \App\Models\Model $order
|
||||
*/
|
||||
public function setOrderAttribute(Model $order)
|
||||
{
|
||||
$this->attributes['order_type'] = get_class($order);
|
||||
$this->attributes['order_id'] = $order->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 通过模型来设置所属用户
|
||||
*
|
||||
* @Date : 2021/4/21 1:48 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Modules\User\Models\User $user
|
||||
*/
|
||||
public function setUserAttribute(User $user)
|
||||
{
|
||||
$this->attributes['user_id'] = $user->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 支付成功,调用的方法
|
||||
*
|
||||
* @Date : 2021/4/20 5:42 下午
|
||||
* @Author : < Jason.C >
|
||||
*/
|
||||
public function paid(): void
|
||||
{
|
||||
$this->state = self::STATUS_SUCCESS;
|
||||
$this->paid_at = now();
|
||||
$this->save();
|
||||
|
||||
event(new Paid($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 根据支付订单,获取支付渠道需要的接口数据
|
||||
*
|
||||
* @Date : 2021/4/21 4:24 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param string $title 订单标题
|
||||
* @param array $extends 扩展数据, 微信公众号 ['openid' => OPENID]
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getPaymentParams(string $title, array $extends = [])
|
||||
{
|
||||
$order['out_trade_no'] = $this->trade_id;
|
||||
|
||||
$driver = $this->driver;
|
||||
$gateway = $this->gateway;
|
||||
|
||||
if ($driver === self::DRIVER_WECHAT) {
|
||||
$order['out_trade_no'] = $this->trade_id;
|
||||
if (config('payment.version', 2) == 2) {
|
||||
$order['body'] = $title;
|
||||
$order['total_fee'] = $this->total * 100;
|
||||
} else {
|
||||
$order['description'] = $title;
|
||||
$order['amount']['total'] = $this->total * 100;
|
||||
}
|
||||
} elseif ($driver === self::DRIVER_ALIPAY) {
|
||||
$order['total_amount'] = $this->total;
|
||||
$order['out_trade_no'] = $this->trade_id;
|
||||
$order['subject'] = $title;
|
||||
} else {
|
||||
throw new Exception('unsupported driver');
|
||||
}
|
||||
|
||||
if (! empty($extends)) {
|
||||
$order = array_merge($order, $extends);
|
||||
}
|
||||
|
||||
return Pay::$driver()->$gateway($order);
|
||||
}
|
||||
|
||||
}
|
||||
27
modules/Payment/Models/PaymentNotify.php
Normal file
27
modules/Payment/Models/PaymentNotify.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class PaymentNotify extends Model
|
||||
{
|
||||
|
||||
protected $casts = [
|
||||
'payload' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* Notes : 所属支付单
|
||||
*
|
||||
* @Date : 2021/5/26 9:55 上午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function payment(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Payment::class);
|
||||
}
|
||||
|
||||
}
|
||||
25
modules/Payment/Models/Redpack.php
Normal file
25
modules/Payment/Models/Redpack.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use App\Traits\OrderByIdDesc;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Redpack extends Model
|
||||
{
|
||||
|
||||
use OrderByIdDesc,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'payment_redpacks';
|
||||
|
||||
const COMMON_REDPACK = 0;
|
||||
const GROUP_REDPACK = 1;
|
||||
|
||||
const TYPE_MAP = [
|
||||
self::COMMON_REDPACK => '普通红包',
|
||||
self::GROUP_REDPACK => '裂变红包',
|
||||
];
|
||||
|
||||
}
|
||||
49
modules/Payment/Models/Refund.php
Normal file
49
modules/Payment/Models/Refund.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Refund extends Model
|
||||
{
|
||||
|
||||
protected $table = 'payment_refunds';
|
||||
|
||||
protected $dates = [
|
||||
'refund_at',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
self::creating(function ($model) {
|
||||
$time = explode(' ', microtime());
|
||||
$counter = $model->whereDate('created_at', Carbon::today())->count() + 1;
|
||||
$len = config('payment.refund_no_counter_length');
|
||||
$prefix = config('payment.refund_no_counter_prefix');
|
||||
|
||||
$len = $len < 6 ? 6 : $len;
|
||||
$len = $len > 16 ? 16 : $len;
|
||||
|
||||
$model->refund_no = $prefix.date('YmdHis').
|
||||
sprintf('%06d', $time[0] * 1e6).
|
||||
sprintf('%0'.$len.'d', $counter);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 支付订单
|
||||
*
|
||||
* @Date : 2021/6/1 11:13 上午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function payment(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Payment::class);
|
||||
}
|
||||
|
||||
}
|
||||
83
modules/Payment/Models/Setting.php
Normal file
83
modules/Payment/Models/Setting.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use Exception;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class Setting extends Model
|
||||
{
|
||||
|
||||
use Cachable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'payment_settings';
|
||||
|
||||
protected $casts = [
|
||||
'in_use' => 'boolean',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
self::saved(function ($model) {
|
||||
if ($model->in_use && $model->id) {
|
||||
self::where('id', '<>', $model->id)
|
||||
->where('in_use', 1)
|
||||
->update(['in_use' => 0]);
|
||||
}
|
||||
|
||||
// Cache::tags('payment_config')->flush();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 挂载的微信支付
|
||||
*
|
||||
* @Date : 2021/5/26 2:01 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function wechat(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Wechat::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 挂载的支付宝
|
||||
*
|
||||
* @Date : 2021/5/26 2:18 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function alipay(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Alipay::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 获取微信/支付宝的配置
|
||||
*
|
||||
* @Date : 2021/5/26 2:19 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param string $type
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getDefaultConfig(string $type): array
|
||||
{
|
||||
if (! in_array($type, ['wechat', 'alipay'])) {
|
||||
throw new Exception('不支持的支付渠道');
|
||||
}
|
||||
|
||||
$setting = self::orderByDesc('in_use')->first();
|
||||
|
||||
return $setting->$type->toConfig();
|
||||
}
|
||||
|
||||
}
|
||||
37
modules/Payment/Models/Traits/WithConfig.php
Normal file
37
modules/Payment/Models/Traits/WithConfig.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models\Traits;
|
||||
|
||||
use Modules\Payment\Models\Setting;
|
||||
|
||||
trait WithConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes: 获取配置文件
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/11/2 15:27
|
||||
* @param string $driver
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getPayConfig(string $driver, $gateway = '')
|
||||
{
|
||||
$defaule_config = Setting::getDefaultConfig($driver);
|
||||
|
||||
if (config('payment.version', 2) == 3) {
|
||||
$config = [
|
||||
$driver => [
|
||||
'default' => $defaule_config,
|
||||
],
|
||||
'logger' => array_merge($defaule_config['logger'], [
|
||||
'enable' => config('payment.logger', true),
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
return $config;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
17
modules/Payment/Models/Transfer.php
Normal file
17
modules/Payment/Models/Transfer.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use App\Traits\OrderByIdDesc;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Transfer extends Model
|
||||
{
|
||||
|
||||
use OrderByIdDesc,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'payment_transfers';
|
||||
|
||||
}
|
||||
50
modules/Payment/Models/Wechat.php
Normal file
50
modules/Payment/Models/Wechat.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Payment\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Wechat extends Model
|
||||
{
|
||||
|
||||
use Cachable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'payment_wechats';
|
||||
|
||||
protected $casts = [
|
||||
'log' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* Notes : 生成配置文件
|
||||
*
|
||||
* @Date : 2021/5/26 2:21 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return int[]
|
||||
*/
|
||||
public function toConfig(): array
|
||||
{
|
||||
return [
|
||||
'app_id' => $this->appid,//app
|
||||
'mp_app_id' => $this->app_id,//mp
|
||||
'mini_app_id' => $this->miniapp_id,//mini
|
||||
'mch_id' => $this->mch_id,
|
||||
// 必填-商户秘钥
|
||||
'mch_secret_key' => $this->key,
|
||||
// 必填-商户私钥 字符串或路径
|
||||
'mch_secret_cert' => $this->cert_key ? storage_path('app/'.$this->cert_key) : '',
|
||||
// 必填-商户公钥证书路径
|
||||
'mch_public_cert_path' => $this->cert_client ? storage_path('app/'.$this->cert_client) : '',
|
||||
'logger' => [
|
||||
'file' => storage_path('logs/wechat/'.$this->log['file'].'.log'),
|
||||
'level' => $this->log['level'],
|
||||
'type' => $this->log['type'],
|
||||
'max_file' => (int) $this->log['max_file'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user