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.
218 lines
7.7 KiB
218 lines
7.7 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
|
// +----------------------------------------------------------------------
|
|
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
|
// +----------------------------------------------------------------------
|
|
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
|
// +----------------------------------------------------------------------
|
|
// | Author: 萤火科技 <admin@yiovo.com>
|
|
// +----------------------------------------------------------------------
|
|
declare (strict_types=1);
|
|
|
|
namespace app\store\model;
|
|
|
|
use think\facade\Filesystem;
|
|
use cores\exception\BaseException;
|
|
use app\common\library\helper;
|
|
use app\store\model\Payment as PaymentModel;
|
|
use app\common\enum\payment\Method as PaymentMethodEnum;
|
|
use app\common\model\PaymentTemplate as PaymentTemplateModel;
|
|
use app\common\library\wechat\payment\PlatformCertDown;
|
|
|
|
/**
|
|
* 模型类:支付方式记录
|
|
* Class PaymentTemplate
|
|
* @package app\store\model
|
|
*/
|
|
class PaymentTemplate extends PaymentTemplateModel
|
|
{
|
|
/**
|
|
* 获取列表
|
|
* @return \think\Paginator
|
|
* @throws \think\db\exception\DbException
|
|
*/
|
|
public function getList($merchantId = 0): \think\Paginator
|
|
{
|
|
$where = [];
|
|
if (isset($merchantId) && $merchantId) {
|
|
$where = ['merchant_id', '=', $merchantId];
|
|
}
|
|
return $this->where($where)->where('is_delete', '=', 0)
|
|
->order(['sort' => 'asc', $this->getPk()])
|
|
->paginate(15);
|
|
}
|
|
|
|
/**
|
|
* 新增记录
|
|
* @param array $data
|
|
* @return bool|false
|
|
* @throws BaseException
|
|
*/
|
|
public function add(array $data): bool
|
|
{
|
|
// 整理保存的数据
|
|
$config = helper::jsonDecode(htmlspecialchars_decode($data['config']));
|
|
$methodConfig = $config[$data['method']];
|
|
$data['store_id'] = self::$storeId;
|
|
// 写入证书文件
|
|
$data['config'] = [$data['method'] => $this->certFileName($data['method'], $methodConfig)];
|
|
// 写入到数据库
|
|
return $this->save($data);
|
|
}
|
|
|
|
/**
|
|
* 更新记录
|
|
* @param array $data
|
|
* @return bool
|
|
* @throws BaseException
|
|
*/
|
|
public function edit(array $data): bool
|
|
{
|
|
// 整理保存的数据
|
|
$config = helper::jsonDecode(htmlspecialchars_decode($data['config']));
|
|
$methodConfig = $config[$data['method']];
|
|
$data['store_id'] = self::$storeId;
|
|
// 记录证书文件名
|
|
$data['config'] = [
|
|
$data['method'] => array_merge($methodConfig, $this->certFileName($data['method'], $methodConfig))
|
|
];
|
|
// 记录微信支付v3平台证书序号
|
|
if ($data['method'] === 'wechat' && $data['config']['wechat']['version'] === 'v3') {
|
|
$data['wechatpay_serial'] = $data['config']['wechat'][$data['config']['wechat']['mchType']]['platformCertSerial'];
|
|
}
|
|
// 更新到数据库
|
|
return $this->save($data) !== false;
|
|
}
|
|
|
|
/**
|
|
* 记录证书文件名
|
|
* @param string $method 支付方式类型
|
|
* @param array $config 支付配置
|
|
* @return array
|
|
* @throws BaseException
|
|
*/
|
|
private function certFileName(string $method, array $config): array
|
|
{
|
|
if ($method === PaymentMethodEnum::WECHAT) {
|
|
$config['normal'] = $this->saveCertFileNames($config['normal'], $method, [
|
|
'apiclientCert',
|
|
'apiclientKey'
|
|
], 'pem');
|
|
$config['provider'] = $this->saveCertFileNames($config['provider'], $method, [
|
|
'spApiclientCert',
|
|
'spApiclientKey'
|
|
], 'pem');
|
|
// 微信支付v3下载 [微信平台证书]
|
|
$config['version'] === 'v3' && $this->downloadPlatformCert($config);
|
|
}
|
|
if ($method === PaymentMethodEnum::ALIPAY && $config['signMode'] == 10) {
|
|
$config = $this->saveCertFileNames($config, $method, [
|
|
'appCertPublicKey',
|
|
'alipayCertPublicKey',
|
|
'alipayRootCert'
|
|
], 'crt');
|
|
}
|
|
return $config;
|
|
}
|
|
|
|
/**
|
|
* 微信支付v3下载 [微信平台证书]
|
|
* @param array $config
|
|
* @return void
|
|
* @throws BaseException
|
|
*/
|
|
private function downloadPlatformCert(array &$config): void
|
|
{
|
|
// 配置项的字段(用于区分普通商户和子商户)
|
|
$field = $config['mchType'] === 'normal' ? ['normal', 'apiclientCert', 'apiclientKey', 'apiKey', 'mchId']
|
|
: ['provider', 'spApiclientCert', 'spApiclientKey', 'spApiKey', 'spMchId'];
|
|
// 微信商户API证书 [公钥]
|
|
$publicKey = parent::realPathCertFile(PaymentMethodEnum::WECHAT, $config[$field[0]][$field[1]], self::$storeId);
|
|
// 微信商户API证书 [私钥]
|
|
$privatekey = parent::realPathCertFile(PaymentMethodEnum::WECHAT, $config[$field[0]][$field[2]], self::$storeId);
|
|
// 生成平台证书文件名
|
|
$platformCertName = $this->buildCertFileName('platformCert', 'pem');
|
|
// 证书保存的目录
|
|
$certFolder = parent::certFolder(PaymentMethodEnum::WECHAT, self::$storeId);
|
|
// 下载平台证书
|
|
$downloader = new PlatformCertDown([
|
|
'key' => $config[$field[0]][$field[3]],
|
|
'mchid' => $config[$field[0]][$field[4]],
|
|
'privatekey' => $privatekey,
|
|
'publicKey' => $publicKey,
|
|
'output' => $certFolder,
|
|
'fileName' => $platformCertName
|
|
]);
|
|
$downloader->run();
|
|
// 记录平台证书
|
|
$config[$field[0]]['platformCert'] = $platformCertName;
|
|
$config[$field[0]]['platformCertSerial'] = $downloader->getPlatformCertSerial();
|
|
}
|
|
|
|
/**
|
|
* 批量设置证书文件名
|
|
* @param array $config 配置项
|
|
* @param string $method 支付方式类型
|
|
* @param array $certNames
|
|
* @param string $ext 文件后缀
|
|
* @return array
|
|
*/
|
|
private function saveCertFileNames(array $config, string $method, array $certNames, string $ext): array
|
|
{
|
|
foreach ($certNames as $name) {
|
|
$config[$name] = $this->writeFile($method, $name, $ext) ?: $config[$name];
|
|
}
|
|
return $config;
|
|
}
|
|
|
|
/**
|
|
* 写入证书文件
|
|
* @param string $method 支付方式类型
|
|
* @param string $name 证书名称
|
|
* @param string $ext 文件后缀
|
|
* @return string|false
|
|
*/
|
|
private function writeFile(string $method, string $name, string $ext)
|
|
{
|
|
// 接收上传的文件
|
|
$file = request()->file($name);
|
|
if (empty($file)) {
|
|
return false;
|
|
}
|
|
// 证书文件夹路径
|
|
$dirPath = "payment/{$method}/" . self::$storeId;
|
|
// 证书文件名
|
|
$fileName = $this->buildCertFileName($name, $ext);
|
|
// 写入到本地服务器
|
|
Filesystem::disk('data')->putFileAs($dirPath, $file, $fileName);
|
|
return $fileName;
|
|
}
|
|
|
|
/**
|
|
* 生成证书文件名
|
|
* @param string $name
|
|
* @param string $ext
|
|
* @return string
|
|
*/
|
|
private function buildCertFileName(string $name, string $ext): string
|
|
{
|
|
$hash = str_substr(md5(get_guid_v4()), 8);
|
|
return "{$name}-{$hash}.{$ext}";
|
|
}
|
|
|
|
/**
|
|
* 删除记录
|
|
* @return bool
|
|
*/
|
|
public function setDelete(): bool
|
|
{
|
|
// 验证模板是否被引用
|
|
if (PaymentModel::existsTemplateId($this['template_id'])) {
|
|
$this->error = '当前支付模板已被引用,需解除后才可删除';
|
|
return false;
|
|
}
|
|
// 标记为已删除
|
|
return $this->save(['is_delete' => 1]);
|
|
}
|
|
}
|
|
|