You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yanzong/app/common/model/Payment.php

358 lines
12 KiB

<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace app\common\model;
use cores\BaseModel;
use cores\exception\BaseException;
use think\facade\Cache;
use think\model\relation\BelongsTo;
use app\common\library\helper;
use app\common\model\PaymentTemplate as PaymentTemplateModel;
use app\common\enum\Client as ClientEnum;
use app\common\enum\payment\Method as PaymentMethodEnum;
/**
* 模型类:支付方式记录
* Class Payment
* @package app\common\model
*/
class Payment extends BaseModel
{
// 定义表名
protected $name = 'payment';
// 定义主键
protected $pk = 'payment_id';
/**
* 关联支付模板记录表
* @return BelongsTo
*/
public function template(): BelongsTo
{
return $this->belongsTo('PaymentTemplate');
}
/**
* 获取器:其他选项
* @param $value
* @return array
*/
public function getOthersAttr($value): array
{
return helper::jsonDecode($value);
}
/**
* 修改器:其他选项
* @param $value
* @return string
*/
public function setOthersAttr($value): string
{
return helper::jsonEncode($value);
}
/**
* 支付方式详情
* @param int $paymentId
* @return static|array|null
*/
public static function detail(int $paymentId)
{
return self::get($paymentId);
}
/**
* 获取支付方式配置
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\DataNotFoundException
*/
public static function getAll(int $storeId, int $merchantId = null): array
{
// 实例化当前模型
$model = new static;
// 默认的支付方式数据
$defaultData = $model->defaultData();
if (!$data = Cache::get("11payment_{$storeId}_{$merchantId}")) {
// 获取所有支付方式
$data = $model->dataByStorage($storeId, $defaultData, $merchantId);
// 写入缓存中
Cache::tag('cache')->set("11payment_{$storeId}_{$merchantId}", $data);
}
// 重组缓存数据 (多维)
return static::reorganize2($defaultData, $data);
}
/**
* 获取指定客户端的支付方式
* @param string $client
* @param int $storeId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function getItem(string $client, int $storeId, int $merchantId = null): array
{
return static::getAll($storeId, $merchantId)[$client];
}
/**
* 重组缓存数据 (多维)
* @param array $defaultData
* @param array $data
* @return array
*/
private static function reorganize2(array $defaultData, array $data): array
{
$data = static::reorganize($defaultData, $data, $type = 'cache');
foreach ($data as &$item) {
$item['methods'] = array_values($item['methods']);
}
return $data;
}
/**
* 获取所有支付方式 (从数据库中)
* @param int $storeId
* @param array $defaultData
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function dataByStorage(int $storeId, array $defaultData, int $merchantId = 0): array
{
// 获取数据库中所有的支付方式
$where = [];
if (isset($merchantId) && $merchantId) {
$where['merchant_id'] = $merchantId;
}
$list = $this->where($where)->where('store_id', '=', $storeId)->select();
if ($list->isEmpty()) {
return [];
}
// 客户端标识合集
$clientKeys = helper::getArrayColumn($defaultData, 'client');
// 整理数据格式
$data = [];
$listArr = $list->toArray();
foreach ($clientKeys as $client) {
$listAsClient = $this->listAsClient($listArr, $client);
$methods = empty($listAsClient) ? [] : $this->buildMethods($client, $listAsClient);
if (!empty($methods)) {
$data[$client] = ['client' => $client, 'methods' => $this->buildMethods($client, $listAsClient)];
}
}
return $data;
}
/**
* 格式化支付方式数据 (赋值key用于合并默认数据)
* @param string $client
* @param array $listAsClient
* @return array
*/
private function buildMethods(string $client, array $listAsClient): array
{
$methods = helper::getArrayColumns($listAsClient, [
'method', 'client', 'is_must_template', 'template_id',
'is_enable', 'is_default', 'others'
]);
$data = [];
foreach ($methods as $item) {
if ($item['client'] === $client) {
$data["$client-{$item['method']}"] = $item;
}
}
return $data;
}
/**
* 默认的支付方式数据
* @return array[]
*/
protected function defaultData(): array
{
$data = [
ClientEnum::MP_WEIXIN => $this->defaultGroup(ClientEnum::MP_WEIXIN, [
PaymentMethodEnum::WECHAT,
PaymentMethodEnum::BALANCE,
]),
ClientEnum::H5 => $this->defaultGroup(ClientEnum::H5, [
PaymentMethodEnum::WECHAT,
PaymentMethodEnum::ALIPAY,
PaymentMethodEnum::BALANCE,
]),
ClientEnum::WXOFFICIAL => $this->defaultGroup(ClientEnum::WXOFFICIAL, [
PaymentMethodEnum::WECHAT,
PaymentMethodEnum::BALANCE,
]),
ClientEnum::APP => $this->defaultGroup(ClientEnum::APP, [
PaymentMethodEnum::WECHAT,
PaymentMethodEnum::ALIPAY,
PaymentMethodEnum::BALANCE,
]),
];
if (\config('plugin.mpAlipay.enable', false)) {
$data[ClientEnum::MP_ALIPAY] = $this->defaultGroup(ClientEnum::MP_ALIPAY, [
PaymentMethodEnum::ALIPAY,
PaymentMethodEnum::BALANCE,
]);
}
return $data;
}
/**
* 默认的支付客户端分组
* @param string $client
* @param array $designated
* @return array
*/
private function defaultGroup(string $client, array $designated): array
{
return [
'client' => $client,
'name' => ClientEnum::getName($client),
'desc' => '在' . ClientEnum::getName($client) . '付款时使用',
'methods' => $this->defaultMethods($client, $designated)
];
}
/**
* 默认的methods数据
* @param string $client
* @param array $designated
* @return array
*/
private function defaultMethods(string $client, array $designated): array
{
$record = [
'key' => 1,
'method' => PaymentMethodEnum::WECHAT, // 支付方式
'is_must_template' => true, // 是否必须使用模板
'template_id' => 0, // 模板ID
'is_enable' => false, // 是否启用该支付方式
'is_default' => false, // 是否为默认支付方式
'others' => [] // 其他配置
];
$defaultMethods = [];
foreach ($designated as $key => $method) {
$defaultMethods["{$client}-{$method}"] = array_merge($record, [
'key' => $key + 1,
'method' => $method,
'is_must_template' => $method != PaymentMethodEnum::BALANCE,
'is_enable' => $method == PaymentMethodEnum::BALANCE,
]);
}
return $defaultMethods;
}
/**
* 根据client过滤list
* @param array $listArr
* @param string $client
* @return array|iterable
*/
private function listAsClient(array $listArr, string $client)
{
$listAsClient = helper::arrayFilterAsVal($listArr, 'client', $client);
foreach ($listAsClient as &$item) {
$item['is_must_template'] = (bool)$item['is_must_template'];
$item['is_enable'] = (bool)$item['is_enable'];
$item['is_default'] = (bool)$item['is_default'];
}
return $listAsClient;
}
/**
* 根据指定客户端获取可用的支付方式
* @param string $client 客户端来源
* @param bool $balance 是否支持余额支付
* @param int|null $storeId 商城ID
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws BaseException
*/
public function getMethodsByClient(string $client, bool $balance = true, int $storeId = null, int $merchantId = null): array
{
$storeId = $storeId ?: self::$storeId;
$group = static::getItem($client, $storeId, $merchantId);
$methods = [];
foreach ($group['methods'] as $method) {
if ($method['is_enable'] && ($balance || $method['method'] !== PaymentMethodEnum::BALANCE)) {
$methods[] = $method;
}
}
if (empty($methods)) {
throwError('很抱歉,当前没有可用的支付方式,请检查后台支付设置');
}
return $methods;
}
/**
* 获取指定的支付方式及模板
* @param string $method 支付方式
* @param string $client 客户端来源
* @param int|null $storeId 商城ID
* @return bool|mixed
* @throws BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getPaymentInfo(string $method, string $client, int $storeId = null, int $merchantId = null)
{
// 获取当前指定的支付方式
$methodInfo = $this->getCurrentMethod($method, $client, $storeId, $merchantId);
// 获取支付模板信息
$methodInfo['template'] = !$methodInfo['is_must_template'] ? [] : $this->getTemplateInfo($methodInfo['template_id']);
return $methodInfo;
}
/**
* 获取支付模板
* @param int $templateId 支付模板ID
* @return array
* @throws BaseException
*/
private function getTemplateInfo(int $templateId): array
{
return (new PaymentTemplateModel)->getTemplateInfo($templateId);
}
/**
* 获取当前指定的支付方式
* @param string $method 指定的支付方式
* @param string $client 客户端来源
* @param int|null $storeId 商城ID
* @return bool|mixed
* @throws BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function getCurrentMethod(string $method, string $client, int $storeId = null, int $merchantId = null)
{
$methods = $this->getMethodsByClient($client, true, $storeId, $merchantId);
$method = helper::arraySearch($methods, 'method', $method);
if (empty($method)) {
throwError('很抱歉,当前未找到指定的支付方式');
}
return $method;
}
}