其余文件

This commit is contained in:
2026-04-14 17:46:22 +08:00
parent 294b68fe37
commit 3691f4db22
1343 changed files with 189847 additions and 0 deletions

View File

@ -0,0 +1,66 @@
<?php
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\model\user\User;
use app\common\model\AccountLog;
use app\admin\logic\user\LevelLogic;
class AccountLogLogic extends Logic
{
/**
* Notes:记录会员账户流水,如果变动类型是成长值,且是增加的,则调用更新会员等级方法。该方法应在添加用户账户后调用
* @param int $user_id 用户id
* @param float $amount 变动数量
* @param int $change_type 变动类型1-增加2-减少
* @param int $source_type 来源类型
* @param string $remark 说明
* @param string $source_id 来源id
* @param string $source_sn 来源单号
* @param string $extra 额外字段说明
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function AccountRecord($user_id,$amount,$change_type,$source_type,$remark ='',$source_id ='',$source_sn='',$extra=''){
$user = User::findOrEmpty($user_id);
if($user->isEmpty()){
return false;
}
$type = AccountLog::getChangeType($source_type);
$left_amount = 0;
switch ($type){
case 'money':
$left_amount = $user->user_money;
break;
case 'integral':
$left_amount = $user->user_integral;
break;
case 'growth':
$left_amount = $user->user_growth;
break;
case 'earnings':
$left_amount = $user->earnings;
}
$account_log = new AccountLog();
$account_log->log_sn = createSn('account_log','log_sn','',4);
$account_log->user_id = $user_id;
$account_log->source_type = $source_type;
$account_log->source_id = $source_id;
$account_log->source_sn = $source_sn;
$account_log->change_amount = $amount;
$account_log->left_amount = $left_amount;
$account_log->remark = AccountLog::getRemarkDesc($source_type,$source_sn,$remark);
$account_log->extra = $extra;
$account_log->change_type = $change_type;
$account_log->create_time = time();
$account_log->save();
//更新会员等级
if($type === 'growth' && $change_type == 1){
LevelLogic::updateUserLevel([$user]);
}
return true;
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace app\common\logic;
use app\common\enum\OrderLogEnum;
use app\common\model\after_sale\AfterSaleLog;
use app\common\model\order\OrderLog;
use think\Model;
/**
* 售后记录日志
* Class OrderLogLogic
* @package app\common\logic
*/
class AfterSaleLogLogic
{
public static function record($type, $channel, $order_id, $after_sale_id, $handle_id, $content, $desc = '')
{
if (empty($content)) {
return true;
}
$log = new AfterSaleLog();
$log->type = $type;
$log->channel = $channel;
$log->order_id = $order_id;
$log->after_sale_id = $after_sale_id;
$log->handle_id = $handle_id;
$log->content = AfterSaleLog::getLogDesc($content);
$log->create_time = time();
if ($desc != ''){
$log->content = AfterSaleLog::getLogDesc($content).'('.$desc.')';
}
$log->save();
}
}

View File

@ -0,0 +1,314 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\enum\ChatMsgEnum;
use app\common\model\kefu\ChatRelation;
use app\common\model\kefu\Kefu;
use app\common\model\user\User;
use app\common\server\ConfigServer;
use app\common\server\UrlServer;
use app\common\utils\Redis;
class ChatLogic extends Logic
{
/**
* @notes
* @param $shop_id
* @return array|bool
* @author 段誉
* @date 2021/12/14 12:07
*/
public static function getOnlineKefu($shop_id)
{
$key = self::getChatPrefix() . 'shop_' . $shop_id . '_kefu';
return (new Redis())->getSmembersArray($key);
}
/**
* @notes 在线用户
* @return array|bool
* @author 段誉
* @date 2021/12/14 12:11
*/
public static function getOnlineUser()
{
$key = self::getChatPrefix() . 'user';
return (new Redis())->getSmembersArray($key);
}
/**
* @notes 格式化聊天记录
* @param $records
* @param $count
* @param $page
* @param $size
* @return array
* @author 段誉
* @date 2021/12/13 10:20
*/
public static function formatChatRecords($records, $count, $page, $size)
{
if (empty($records)) {
return [
'list' => $records,
'page' => $page,
'size' => $size,
'count' => $count,
'more' => is_more($count, $page, $size)
];
}
$kefu = [];
$user = [];
// 获取到客服和用户不同的两组id
foreach ($records as $item) {
if ($item['from_type'] == 'kefu') {
$kefu[] = $item['from_id'];
} else {
$user[] = $item['from_id'];
}
}
$kefu = array_unique($kefu);
$user = array_unique($user);
$kefu = Kefu::where('id', 'in', $kefu)->column('nickname, avatar', 'id');
$user = User::where('id', 'in', $user)->column('nickname, avatar', 'id');
foreach ($records as &$item) {
$item['from_nickname'] = '';
$item['from_avatar'] = '';
if ($item['from_type'] == 'kefu') {
$kefu_id = $item['from_id'];
if (isset($kefu[$kefu_id])) {
$item['from_nickname'] = $kefu[$kefu_id]['nickname'] ?? '';
$item['from_avatar'] = $kefu[$kefu_id]['avatar'] ?? '';
}
}
if ($item['from_type'] == 'user') {
$user_id = $item['from_id'];
if (isset($user[$user_id])) {
$item['from_nickname'] = $user[$user_id]['nickname'] ?? '';
$item['from_avatar'] = $user[$user_id]['avatar'] ?? '';
}
}
$item['goods'] = [];
if ($item['msg_type'] == ChatMsgEnum::TYPE_GOODS) {
$item['goods'] = json_decode($item['msg'], true);
}
$item['create_time_stamp'] = strtotime($item['create_time']);
}
$records = array_reverse($records);
return [
'list' => $records,
'page' => $page,
'size' => $size,
'count' => $count,
'more' => is_more($count, $page, $size)
];
}
/**
* @notes 配置
* @param $shop_id
* @return array
* @author 段誉
* @date 2021/12/17 11:24
* @remark code => 0时显示人工客服页,code => 1时显示在线客服页
*/
public static function getConfig($shop_id)
{
// 后台客服配置 1->人工客服; 2->在线客服
if (self::getConfigSetting($shop_id) == 1) {
return ['code' => 0, 'msg' => ''];
}
// 缓存配置
if ('redis' != self::getCacheDrive()) {
return ['code' => 0, 'msg' => '请参考部署文档配置在线客服'];
}
// 当前在线客服
$online = self::getOnlineKefu($shop_id);
if (empty($online)) {
return ['code' => 0, 'msg' => '当前客服不在线,有问题请联系人工客服'];
}
return ['code' => 1, 'msg' => ''];
}
/**
* @notes 检查配置
* @param int $shop_id
* @return bool
* @author 段誉
* @date 2021/12/20 14:11
*/
public static function checkConfig(int $shop_id = 0)
{
try {
if (self::getConfigSetting($shop_id) == 1) {
throw new \Exception('请联系管理员开启在线客服');
}
if ('redis' != self::getCacheDrive()) {
throw new \Exception('请参考部署文档配置在线客服');
}
return true;
} catch (\Exception $e) {
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 绑定关系
* @param $user_id
* @param $kefu_id
* @param $shop_id
* @param $data
* @author 段誉
* @date 2021/12/17 15:52
*/
public static function bindRelation($user_id, $kefu_id, $shop_id, $data, $is_read = 0)
{
$relation = ChatRelation::where(['user_id' => $user_id, 'shop_id' => $shop_id])->findOrEmpty();
$user = User::where(['id' => $user_id])->findOrEmpty();
if ($relation->isEmpty()) {
$relation = ChatRelation::create([
'shop_id' => $shop_id,
'user_id' => $user_id,
'kefu_id' => $kefu_id,
'nickname' => $user['nickname'],
'avatar' => $user['avatar'],
'client' => $data['client'] ?? 0,
'msg' => $data['msg'] ?? '',
'msg_type' => $data['msg_type'] ?? ChatMsgEnum::TYPE_TEXT,
'is_read' => 1, // 新创建关系都算已读
'create_time' => time(),
'update_time' => time(),
]);
} else {
ChatRelation::update(
[
'kefu_id' => $kefu_id,
'nickname' => $user['nickname'],
'avatar' => $user['avatar'],
'client' => $data['client'] ?? 0,
'msg' => $data['msg'] ?? '',
'msg_type' => $data['msg_type'] ?? ChatMsgEnum::TYPE_TEXT,
'update_time' => time(),
'is_read' => $is_read
],
['id' => $relation['id']]
);
}
return $relation['id'];
}
/**
* @notes 后台客服配置
* @param $shop_id
* @return array|int|mixed|string|null
* @author 段誉
* @date 2021/12/20 11:51
*/
public static function getConfigSetting($shop_id)
{
// 后台客服配置 1->人工客服; 2->在线客服
if ($shop_id > 0) {
$config = ConfigServer::get('shop_customer_service', 'type', 1, $shop_id);
} else {
$config = ConfigServer::get('customer_service', 'type', 1);
}
return $config;
}
/**
* @notes 当前缓存驱动
* @return mixed
* @author 段誉
* @date 2021/12/20 11:51
*/
public static function getCacheDrive()
{
return config('cache.default');
}
/**
* @notes 聊天前缀
* @return mixed
* @author 段誉
* @date 2022/4/14 17:42
*/
public static function getChatPrefix()
{
return config('default.websocket_prefix');
}
/**
* @notes 禁用客服
* @param $shop_id
* @param $kefu_id
* @author 段誉
* @date 2022/4/14 17:42
*/
public static function setChatDisable($shop_id, $kefu_id)
{
$cache = new Redis();
$prefix = self::getChatPrefix();
$key = $prefix . 'shop_' . $shop_id . '_kefu';
$result = $cache->getSmembersArray($key);
$fds = $cache->getSmembersArray($prefix . 'kefu_' . $kefu_id);
if (in_array($kefu_id, $result) && $fds) {
$cache->srem($key, $kefu_id);
foreach ($fds as $fd) {
$cache->srem($prefix . 'kefu_' . $kefu_id, $fd);
$cache->del($prefix . 'fd_' . $fd);
}
}
}
}

View File

@ -0,0 +1,57 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\server\UrlServer;
use think\facade\Db;
class CommonLogic{
/**
* note 修改指定表的某个字段
* author cjh 2020/10/14 14:51
* @param $table 表名
* @param $pk_name id
* @param $pk_value id的值
* @param $field 需要修改的字段
* @param $field_value 需要修改的值
* @return bool
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public static function changeTableValue($table,$pk_name,$pk_value,$field,$field_value){
//允许修改的字段
$allow_field = [
'is_show','sort','status','is_new','is_best','is_like','is_recommend', 'del'
];
if(!in_array($field,$allow_field)){
return false;
}
if(is_array($pk_value)){
$where[] = [$pk_name,'in',$pk_value];
}else{
$where[] = [$pk_name,'=',$pk_value];
}
$data= [
$field => $field_value,
'update_time' => time(),
];
return Db::name($table)->where($where)->update($data);
}
}

View File

@ -0,0 +1,92 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\cache\CommunityArticleCache;
use app\common\enum\CommunityArticleEnum;
use app\common\model\community\CommunityFollow;
class CommunityArticleLogic extends Logic
{
/**
* @notes 用户发布新文章通知粉丝
* @param $user_id
* @param $status
* @return bool
* @author 段誉
* @date 2022/5/12 16:45
*/
public static function noticeFans($user_id, $status)
{
if ($status != CommunityArticleEnum::STATUS_SUCCESS) {
return true;
}
$fans = CommunityFollow::where(['follow_id' => $user_id, 'status' => 1])
->column('user_id');
if (empty($fans)) {
return true;
}
// 设置未读缓存
foreach ($fans as $item) {
$cache = new CommunityArticleCache('unread_user'. $item, ['has_new' => 1]);
$cache->set();
}
return true;
}
/**
* @notes 用户是否有未读文章
* @param $user_id
* @return int
* @author 段誉
* @date 2022/5/12 16:47
*/
public static function hasNew($user_id)
{
if (empty($user_id)) {
return 0;
}
$cache = new CommunityArticleCache('unread_user'. $user_id);
$isEmpty = $cache->isEmpty();
return !$isEmpty ? 1 : 0;
}
/**
* @notes 删除未读状态
* @param $user_id
* @return bool
* @author 段誉
* @date 2022/5/12 16:51
*/
public static function delUnRead($user_id)
{
$cache = new CommunityArticleCache('unread_user'. $user_id);
return $cache->del();
}
}

View File

@ -0,0 +1,61 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\model\distribution\Distribution;
use app\common\model\distribution\DistributionLevel;
use app\common\server\ConfigServer;
/**
* 分销基础信息逻辑层
* Class DistributionLogic
* @package app\common\logic
*/
class DistributionLogic
{
/**
* @notes 添加分销基础信息记录
* @param $userId
* @author Tab
* @date 2021/9/2 11:55
*/
public static function add($userId)
{
// 默认分销会员等级
$defaultLevelId = DistributionLevel::where('is_default', 1)->value('id');
// 分销会员开通方式
$apply_condition = ConfigServer::get('distribution', 'apply_condition', 2);
$isDistribution = $apply_condition == 1 ? 1 : 0;
$data = [
'user_id' => $userId,
'level_id' => $defaultLevelId,
'is_distribution' => $isDistribution,
'is_freeze' => 0,
'remark' => '',
];
if($isDistribution) {
// 成为分销会员时间
$data['distribution_time'] = time();
}
Distribution::create($data);
}
}

View File

@ -0,0 +1,184 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\server\ConfigServer;
use app\common\server\UrlServer;
use think\facade\Db;
use think\Exception;
class ExpressLogic
{
/**
* 列表
* @param $get
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function lists($get)
{
$where = [];
$where[] = ['del', '=', '0'];
if (isset($get['express_name']) && $get['express_name'] != '') {
$where[] = ['name', 'like', '%' . trim($get['express_name']) . '%'];
}
$count = Db::name('express')
->where($where)
->count();
$lists = Db::name('express')
->where($where)
->page($get['page'], $get['limit'])
->select()->toArray();
foreach ($lists as $key => &$item) {
$item['icon'] = UrlServer::getFileUrl($item['icon']);
}
return ['lists' => $lists, 'count' => $count];
}
/**
* 添加
* @param $post
* @return array|\PDOStatement|string|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function addExpress($post)
{
$time = time();
$data = [
'name' => $post['name'],
'icon' => clearDomain($post['poster']),
'website' => $post['website'],
'code' => $post['code'],
'code100' => $post['code100'],
'codebird' => $post['codebird'],
'sort' => $post['sort'],
'create_time' => $time
];
$result = Db::name('express')->insert($data);
return $result;
}
/**
* 获取信息
* @param $id
* @return array|\PDOStatement|string|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function info($id)
{
$detail = Db::name('express')->where(['id' => $id, 'del' => 0])->find();
$detail['abs_icon'] = UrlServer::getFileUrl($detail['icon']);
return $detail;
}
/**
* 编辑
* @param $post
* @return int|string
* @throws Exception
* @throws \think\exception\PDOException
*/
public static function editExpress($post)
{
$data = [
'name' => $post['name'],
'icon' => UrlServer::setFileUrl($post['poster']),
'website' => $post['website'],
'code' => $post['code'],
'code100' => $post['code100'],
'codebird' => $post['codebird'],
'sort' => $post['sort'],
'update_time' => time()
];
$result = Db::name('express')->where(['id' => $post['id']])->update($data);
return $result;
}
/**
* 删除
* @param $delData
* @return int|string
* @throws Exception
* @throws \think\exception\PDOException
*/
public static function delExpress($delData)
{
$data = [
'del' => 1,
'update_time' => time(),
];
return Db::name('express')->where(['del' => 0, 'id' => $delData])->update($data);
}
public static function getExpress()
{
$config = [
'way' => ConfigServer::get('express', 'way', 'kd100'),
'kd100_appkey' => ConfigServer::get('kd100', 'appkey', ''),
'kd100_customer' => ConfigServer::get('kd100', 'appsecret', ''),
'kdniao_appkey' => ConfigServer::get('kdniao', 'appkey', ''),
'kdniao_ebussinessid' => ConfigServer::get('kdniao', 'appsecret', ''),
'kdniao_type' => ConfigServer::get('kdniao', 'type', 'free'),
];
return $config;
}
//快递100
public static function kd100(){
$config = [
'appkey' => ConfigServer::get('kd100', 'appkey', ''),
'appsecret' => ConfigServer::get('kd100', 'appsecret', ''),
];
return $config;
}
//快递鸟
public static function kdniao(){
$res=[
'appkey2' => ConfigServer::get('kdniao', 'appkey', ''),
'appsecret2' => ConfigServer::get('kdniao', 'appsecret', ''),
];
return $res;
}
//快递方式
public static function way(){
$way = ConfigServer::get('express', 'way', '');
return $way;
}
}

View File

@ -0,0 +1,249 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\model\Freight;
use app\common\model\FreightConfig;
use think\facade\Db;
use think\Exception;
class FreightLogic
{
public static function lists($get)
{
$freight = new Freight();
$where = [];
if (isset($get['name']) && $get['name'] != '') {
$where[] = ['name', 'like', '%' . $get['name'] . '%'];
}
if (isset($get['charge_way']) && $get['charge_way'] != '') {
$where[] = ['charge_way', '=', $get['charge_way']];
}
if (isset($get['shop_id'])){
$where[] = ['shop_id','=',$get['shop_id']];
}
$count = $freight->where($where)->count();
$list = $freight
->where($where)
->page($get['page'], $get['limit'])
->append(['charge_way_text'])
->order('id desc')
->select();
if (!$list) {
return ['count' => '', 'lists' => []];
}
return ['count' => $count, 'lists' => $list];
}
public static function add($post)
{
$freight = new Freight();
$freight->name = $post['name'];
$freight->charge_way = $post['charge_way'];
$freight->remark = $post['remark'];
$freight->shop_id = $post['shop_id'];
$freight->allowField(['name','charge_way','remark','shop_id'])->save();
$freight_config = new FreightConfig();
$config_data = [];
foreach ($post as &$item) {
if (is_array($item)) {
$item = array_values($item);
}
}
$post = form_to_linear($post);
foreach ($post as $v) {
$v['freight_id'] = $freight->id;
$v['create_time'] = time();
$config_data[] = $v;
}
$freight_config->allowField(['region','first_unit','first_money','continue_unit','continue_money','freight_id','create_time'])->insertAll($config_data);
}
public static function edit($post)
{
Db::startTrans();
try {
$freight = Freight::where(['id' => $post['id']])
->with('configs')
->find();
//删除之前保存的配置,再增加
FreightConfig::where(['freight_id' => $freight['id']])->delete();
$freight->where('id',$freight['id'])->save([
'name' => $post['name'],
'charge_way' => $post['charge_way'],
'remark' => $post['remark'],
]);
$config_data = [];
foreach ($post as &$item) {
if (is_array($item)) {
$item = array_values($item);
}
}
$post = form_to_linear($post);
foreach ($post as $v) {
$v['freight_id'] = $freight->id;
$config_data[] = $v;
}
$freight_config = new FreightConfig();
$freight_config->allowField(['region','first_unit','first_money','continue_unit','continue_money','freight_id','create_time'])->insertAll($config_data);
Db::commit();
} catch (Exception $e) {
Db::rollback();
}
}
public static function del($post)
{
Db::startTrans();
try {
Freight::where(['id' => $post['id']])->delete();
FreightConfig::where(['freight_id' => $post['id']])->delete();
Db::commit();
} catch (Exception $e) {
Db::rollback();
}
}
public static function detail($id)
{
$freight = Freight::where(['id' => $id])
->with('configs')
->append(['charge_way_text'])
->find()->toArray();
$regions = Db::name('dev_region')->column('name', 'id');
foreach ($freight['configs'] as &$item) {
$item['region_name'] = '';
if ($item['region'] == 'all'){
$item['region_name'] = '全国';
continue;
}
$region = explode(',', $item['region']);
foreach ($region as $v) {
if (isset($regions[$v])) {
$item['region_name'] .= $regions[$v] . ',';
}
}
$item['region_name'] = rtrim($item['region_name'], ',');
}
return $freight;
}
public static function areaTree()
{
$lists = Db::name('dev_region')
->field('id,parent_id,level,name as title')
->order('parent_id', 'desc')
->select();
$result = self::areaSort($lists);
return $result;
}
public static function areaSort(&$lists)
{
$tree = [];
foreach ($lists as $k1 => $province) {
if ($province['level'] == 1) {
//树形结构参数
$province['checkArr']['type'] = 0;
$province['checkArr']['checked'] = 0;
$province['last'] = false;
$province['parentId'] = -1;
//钓鱼岛这个没有下级
if ($province['id'] == 900000) {
$province['children'] = [];
$province['last'] = true;
}
$tree[$k1] = $province;
unset($lists[$k1]);
foreach ($lists as $k2 => $city) {
$city['parentId'] = $city['parent_id'];
if ($city['parentId'] == $province['id']) {
foreach ($lists as $k3 => $district) {
$district['parentId'] = $district['parent_id'];
if ($district['parentId'] == $city['id']) {
//树形结构参数
$district['checkArr']['type'] = 0;
$district['checkArr']['checked'] = 0;
$district['last'] = true;
$city['children'][] = $district;
unset($lists[$k3]);
}
}
//树形结构参数
$city['checkArr']['type'] = 0;
$city['checkArr']['checked'] = 0;
$city['last'] = false;
$tree[$k1]['children'][] = $city;
unset($lists[$k2]);
}
}
}
}
return array_values($tree);
}
/**
* note 获取全部运费模板
*/
public static function getFreightList()
{
return Db::name('freight')->field('id,name')->select();
}
}

View File

@ -0,0 +1,126 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\enum\GoodsEnum;
use app\common\enum\OrderEnum;
use app\common\model\goods\Goods;
use app\common\model\order\Order;
/**
* 虚拟商品逻辑
* Class GoodsVirtualLogic
* @package app\common\logic
*/
class GoodsVirtualLogic
{
/**
* @notes 订单之后虚拟配送
* @param $orderIds
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/4/12 11:37
*/
public static function afterPayVirtualDelivery($orderIds)
{
$orderIds = is_array($orderIds) ? $orderIds : [$orderIds];
$orders = Order::with(['order_goods'])->whereIn('id', $orderIds)->select()->toArray();
foreach ($orders as $order) {
$goodsId = $order['order_goods'][0]['goods_id'] ?? 0;
$goods = Goods::findOrEmpty($goodsId);
// 商品不存在,不是虚拟商品,买家付款后不是自动发货
if ($goods->isEmpty() || $goods['type'] != GoodsEnum::TYPE_VIRTUAL) {
continue;
}
$data = [
'delivery_content' => $goods['delivery_content'],
'update_time' => time(),
];
// 商品为支付后自动发货
if ($goods['after_pay'] == GoodsEnum::AFTER_PAY_AUTO_DELIVERY) {
$data['order_status'] = OrderEnum::ORDER_STATUS_GOODS; // 待收货状态
$data['delivery_type'] = OrderEnum::DELIVERY_TYPE_VIRTUAL; // 发货方式为虚拟发货
$data['shipping_status'] = OrderEnum::SHIPPING_FINISH; // 已发货
$data['shipping_time'] = time();
// 自动完成订单
if ($goods['after_delivery'] == GoodsEnum::AFTER_DELIVERY_AUTO_COMFIRM) {
$data['order_status'] = OrderEnum::ORDER_STATUS_COMPLETE;// 已完成
$data['confirm_take_time'] = time();
}
}
Order::where(['id' => $order['id']])->update($data);
}
return true;
}
/**
* @notes 商家手动发货
* @param $orderId
* @param null $content
* @return bool|string
* @author 段誉
* @date 2022/4/12 11:44
*/
public static function shopSelfDelivery($orderId, $content = null)
{
$order = Order::with(['order_goods'])->where('id', $orderId)->findOrEmpty()->toArray();
$goodsId = $order['order_goods'][0]['goods_id'] ?? 0;
$goods = Goods::findOrEmpty($goodsId);
// 商品不存在,不是虚拟商品,买家付款后不是自动发货
if ($goods->isEmpty() || $goods['type'] != GoodsEnum::TYPE_VIRTUAL) {
return '虚拟商品信息不存在';
}
$data = [
'order_status' => OrderEnum::ORDER_STATUS_GOODS, // 待收货状态
'delivery_type' => OrderEnum::DELIVERY_TYPE_VIRTUAL, // 发货方式为虚拟发货
'delivery_content' => empty($content) ? $goods['delivery_content'] : $content,
'shipping_status' => OrderEnum::SHIPPING_FINISH, // 已发货
'shipping_time' => time(),
'update_time' => time(),
];
// 自动完成订单
if ($goods['after_delivery'] == GoodsEnum::AFTER_DELIVERY_AUTO_COMFIRM) {
$data['order_status'] = OrderEnum::ORDER_STATUS_COMPLETE;// 已完成
$data['confirm_take_time'] = time();
}
Order::where(['id' => $order['id']])->update($data);
return true;
}
}

View File

@ -0,0 +1,309 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\enum\IntegralGoodsEnum;
use app\common\enum\IntegralOrderEnum;
use app\common\enum\PayEnum;
use app\common\model\integral\IntegralGoods;
use app\common\model\integral\IntegralOrder;
use app\common\model\AccountLog;
use app\common\model\integral\IntegralOrderRefund;
use app\common\model\user\User;
use app\common\server\AliPayServer;
use app\common\server\DouGong\pay\PayZhengsaoRefund;
use app\common\server\WeChatPayServer;
use app\common\server\WeChatServer;
use think\Exception;
/**
* 积分订单退款逻辑
* Class OrderRefundLogic
* @package app\common\logic
*/
class IntegralOrderRefundLogic
{
/**
* @notes 取消订单(标记订单状态,退回库存,扣减销量)
* @param int $order_id
* @author 段誉
* @date 2022/3/3 11:01
*/
public static function cancelOrder(int $order_id)
{
// 订单信息
$order = IntegralOrder::findOrEmpty($order_id);
$order->cancel_time = time();
$order->order_status = IntegralOrderEnum::ORDER_STATUS_DOWN;
$order->save();
// 订单商品信息
$goods_snap = $order['goods_snap'];
// 退回库存, 扣减销量
IntegralGoods::where([['id', '=', $goods_snap['id']], ['sales', '>=', $order['total_num']]])
->inc('stock', $order['total_num'])
->dec('sales', $order['total_num'])
->update();
}
/**
* @notes 退回已支付金额
* @param int $order_id
* @return bool
* @throws Exception
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/3/3 16:00
*/
public static function refundOrderAmount(int $order_id)
{
// 订单信息
$order = IntegralOrder::findOrEmpty($order_id);
// 订单商品信息
$goods_snap = $order['goods_snap'];
//已支付的商品订单,取消,退款
if ($goods_snap['type'] == IntegralGoodsEnum::TYPE_GOODS
&& $order['refund_status'] == IntegralOrderEnum::NO_REFUND
) {
if ($order['order_amount'] <= 0) {
return true;
}
// 更新订单退款状态为已退款
IntegralOrder::where(['id' => $order['id']])->update([
'refund_status' => IntegralOrderEnum::IS_REFUND,//订单退款状态; 0-未退款1-已退款
'refund_amount' => $order['order_amount'],
]);
// 发起退款
$refund_log = self::addRefundLog($order, $order['order_amount'], 1, $order['order_amount']);
switch ($order['pay_way']) {
//余额退款
case PayEnum::BALANCE_PAY:
self::balancePayRefund($order, $order['order_amount']);
break;
//微信退款
case PayEnum::WECHAT_PAY:
self::wechatPayRefund($order, $refund_log);
break;
//支付宝退款
case PayEnum::ALI_PAY:
self::aliPayRefund($order, $refund_log);
break;
case PayEnum::HFDG_WECHAT:
case PayEnum::HFDG_ALIPAY:
$payZsRefund = new PayZhengsaoRefund([
'refund' => [
'id' => $refund_log['id'],
'money' => $order['order_amount'],
],
'order' => [
'id' => $order['id'],
'transaction_id' => $order['transaction_id'],
'hfdg_params' => $order['hfdg_params'],
],
'from' => 'integral',
]);
$result = $payZsRefund->request()->getRefundResult();
if ($result['code'] != 1) {
throw new \Exception($result['msg']);
}
break;
}
}
return true;
}
/**
* @notes 退回已支付积分
* @param $id
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/3/3 16:02
*/
public static function refundOrderIntegral($id)
{
$order = IntegralOrder::findOrEmpty($id);
if ($order['order_integral'] > 0) {
// 退回积分
User::where(['id' => $order['user_id']])
->inc('user_integral', $order['order_integral'])
->update();
AccountLogLogic::AccountRecord(
$order['user_id'],
$order['order_integral'], 1,
AccountLog::cancel_integral_order,
'', $order['id'], $order['order_sn']
);
IntegralOrder::where(['id' => $id])->update([
'refund_integral' => $order['order_integral']
]);
}
return true;
}
/**
* @notes 增加退款记录
* @param $order
* @param $refund_amount
* @param $status
* @param string $msg
* @return IntegralOrderRefund|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/3/3 14:51
*/
public static function addRefundLog($order, $refund_amount, $status, $msg = '')
{
return IntegralOrderRefund::create([
'order_id' => $order['id'],
'user_id' => $order['user_id'],
'refund_sn' => createSn('order_refund', 'refund_sn'),
'order_amount' => $order['order_amount'],
'refund_amount' => $refund_amount,
'transaction_id' => $order['transaction_id'],
'create_time' => time(),
'refund_status' => $status,
'refund_at' => time(),
'refund_msg' => json_encode($msg, JSON_UNESCAPED_UNICODE),
]);
}
/**
* @notes 微信支付退款
* @param $order
* @param $refund_id
* @throws Exception
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @author 段誉
* @date 2022/3/3 14:52
*/
public static function wechatPayRefund($order, $refund)
{
$config = WeChatServer::getPayConfigBySource($order['order_source'])['config'];
if (empty($config)) {
throw new Exception('请联系管理员设置微信相关配置!');
}
if (!isset($config['cert_path']) || !isset($config['key_path'])) {
throw new Exception('请联系管理员设置微信证书!');
}
if (!file_exists($config['cert_path']) || !file_exists($config['key_path'])) {
throw new Exception('微信证书不存在,请联系管理员!');
}
$result = WeChatPayServer::refund($config, [
'transaction_id' => $order['transaction_id'],
'refund_sn' => $refund['refund_sn'],
'total_fee' => intval(strval($refund['order_amount'] * 100)),//订单金额,单位为分
'refund_fee' => intval(strval($refund['refund_amount'] * 100)),//退款金额
]);
if (isset($result['return_code']) && $result['return_code'] == 'FAIL') {
throw new Exception($result['return_msg']);
}
if (isset($result['err_code_des'])) {
throw new Exception($result['err_code_des']);
}
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
//更新退款日志记录
IntegralOrderRefund::where(['id' => $refund['id']])->update([
'wechat_refund_id' => $result['refund_id'] ?? 0,
'refund_msg' => json_encode($result, JSON_UNESCAPED_UNICODE),
]);
} else {
throw new Exception('微信支付退款失败');
}
}
/**
* @notes 支付宝退款
* @param $order
* @param $refund_id
* @throws Exception
* @author 段誉
* @date 2022/3/3 14:52
*/
public static function aliPayRefund($order, $refund)
{
$result = (new AliPayServer())->refund($order['order_sn'], $order['order_amount']);
// $result = (array)$result;
if ($result['code'] == '10000' && $result['msg'] == 'Success' && $result['fund_change'] == 'Y') {
//更新退款日志记录
IntegralOrderRefund::where(['id' => $refund])->update([
'refund_msg' => json_encode($result, JSON_UNESCAPED_UNICODE),
]);
} else {
throw new Exception('支付宝退款失败');
}
}
/**
* @notes 余额退款
* @param $order
* @param $refund_amount
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/3/3 14:52
*/
public static function balancePayRefund($order, $refund_amount)
{
$user = User::find($order['user_id']);
$user->user_money = ['inc', $refund_amount];
$user->save();
AccountLogLogic::AccountRecord(
$order['user_id'],
$refund_amount,
1,
AccountLog::cancel_order_refund,
'',
$order['id'],
$order['order_sn']
);
return true;
}
}

View File

@ -0,0 +1,268 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\model\Client_;
use app\common\Enum\NoticeEnum;
use app\common\model\Notice;
use app\common\model\NoticeSetting;
use app\common\model\order\Order;
use app\common\model\order\OrderGoods;
use app\common\model\user\User;
use app\common\server\SmsMessageServer;
use app\common\server\WxMessageServer;
use think\facade\Log;
/**
* 消息通知逻辑
* Class NoticeLogic
* @package app\common\logic
*/
class MessageNoticeLogic extends Logic
{
/**
* Notes: 根据各个场景发送通知
* @param $user_id
* @param $params
* @author 段誉(2021/4/28 18:21)
* @throws Exception
*/
public static function noticeByScene($user_id, $params)
{
// 记录调试信息
if (app()->isDebug()) {
Log::write(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 15), 'noticeByScene');
Log::write(func_get_args(), 'noticeByScene');
}
try {
$scene_config = NoticeSetting::where('scene', $params['scene'])->find();
if (empty($scene_config)) {
throw new \Exception('信息错误');
}
$params = self::mergeParams($params);
$res = false;
//发送系统消息
if (isset($scene_config['system_notice']['status']) && $scene_config['system_notice']['status'] == 1) {
$content = self::contentFormat($scene_config['system_notice']['content'], $params);
$notice_log = self::addNoticeLog($params, $scene_config,NoticeEnum::SYSTEM_NOTICE, $content);
if ($notice_log) {
$res = true;
}
}
//发送短信记录
if (isset($scene_config['sms_notice']['status']) && $scene_config['sms_notice']['status'] == 1) {
$res = (new SmsMessageServer())->send($params);
}
//发送公众号记录
if (isset($scene_config['oa_notice']['status']) && $scene_config['oa_notice']['status'] == 1) {
$res = (new WxMessageServer($user_id,Client_::oa))->send($params);
}
//发送小程序记录
if (isset($scene_config['mnp_notice']['status']) && $scene_config['mnp_notice']['status'] == 1) {
$res = (new WxMessageServer($user_id, Client_::mnp))->send($params);
}
// if (true !== $res) {
// throw new \Exception('发送失败');
// }
return true;
} catch (\Exception $e) {
self::$error = $e->getMessage();
Log::write($e->__toString(), 'message_notice');
return true;
}
}
/**
* Notes: 拼装额外参数
* @param $params
* @author 段誉(2021/6/22 16:16)
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function mergeParams($params)
{
//订单相关信息
if (!empty($params['params']['order_id'])) {
$order = Order::where(['id' => $params['params']['order_id']])->find();
$order_goods = OrderGoods::alias('og')
->field('g.name')
->join('goods g', 'og.goods_id = g.id')
->where('og.order_id', $params['params']['order_id'])
->find();
$goods_name = $order_goods['name'] ?? '商品';
if (mb_strlen($goods_name) > 8 ) {
$goods_name = mb_substr($goods_name,0,8) . '..';
}
$params['params']['goods_name'] = $goods_name;
$params['params']['order_sn'] = $order['order_sn'];
$params['params']['create_time'] = $order['create_time'];
$params['params']['pay_time'] = date('Y-m-d H:i', $order['pay_time']);
$params['params']['total_num'] = $order['total_num'];
$params['params']['order_amount'] = $order['order_amount'];
}
//用户相关信息
if (!empty($params['params']['user_id'])) {
$user = User::where('id', $params['params']['user_id'])->findOrEmpty();
$params['params']['nickname'] = replaceNickname($user['nickname']) ? : $user['sn'];
$params['params']['user_sn'] = $user['sn'];
}
//下级名称;(邀请人场景)
if (!empty($params['params']['lower_id'])) {
$lower = User::where('id', $params['params']['lower_id'])->findOrEmpty();
$params['params']['lower_name'] = replaceNickname($lower['nickname']) ? : $lower['sn'];
$params['params']['lower_sn'] = $lower['sn'];
}
//跳转路径
$jump_path = self::getPathByScene($params['scene'], $params['params']['order_id'] ?? 0);
$params['url'] = $jump_path['url'];
$params['page'] = $jump_path['page'];
return $params;
}
/**
* Notes: 根据场景获取跳转地址
* @param $scene
* @author 段誉(2021/4/27 17:01)
* @return array
*/
public static function getPathByScene($scene, $extra_id)
{
$page = '/pages/index/index'; // 小程序主页路径
$url = '/mobile/pages/index/index'; // 公众号主页路径
if (in_array($scene, NoticeEnum::ORDER_SCENE)) {
$url = '/mobile/bundle/pages/order_details/order_details?id='.$extra_id;
$page = '/bundle/pages/order_details/order_details?id='.$extra_id;
}
return ['url' => $url, 'page' => $page];
}
//格式化消息内容(替换文本)
public static function contentFormat($content, $params)
{
foreach ($params['params'] as $k => $v) {
$search_replace = '{'.$k.'}';
$content = str_replace($search_replace, $v, $content);
}
return $content;
}
//添加通知记录
public static function addNoticeLog($params, $scene_config, $send_type, $content, $extra = '')
{
return Notice::create([
'user_id' => $params['params']['user_id'] ?? 0,
'title' => self::getTitleByScene($send_type, $scene_config),
'content' => $content,
'scene' => $params['scene'],
'receive_type' => self::getReceiveTypeByScene($params['scene']),
'send_type' => $send_type,
'extra' => $extra,
'create_time' => time()
]);
}
//更新通知记录
public static function updateNotice($notice_id, $extra)
{
return Notice::where('id', $notice_id)->update(['extra' => $extra]);
}
/**
* Notes: 根据不同发送类型获取标题
* @param $send_type
* @param $scene_config
* @author 段誉(2021/6/23 3:03)
* @return string
*/
public static function getTitleByScene($send_type, $scene_config)
{
switch ($send_type) {
case NoticeEnum::SYSTEM_NOTICE:
$title = $scene_config['system_notice']['title'] ?? '';
break;
case NoticeEnum::SMS_NOTICE:
$title = '';
break;
case NoticeEnum::OA_NOTICE:
$title = $scene_config['oa_notice']['name'] ?? '';
break;
case NoticeEnum::MNP_NOTICE:
$title = $scene_config['mnp_notice']['name'] ?? '';
break;
default:
$title = '';
}
return $title;
}
/**
* Notes: 根据不同场景返回当前接收对象
* @param $scene
* @author 段誉(2021/6/23 3:02)
* @return int
*/
public static function getReceiveTypeByScene($scene)
{
//通知平台
if (in_array($scene, NoticeEnum::NOTICE_PLATFORM_SCENE)) {
return NoticeEnum::NOTICE_PLATFORM;
}
//通知商家
if (in_array($scene, NoticeEnum::NOTICE_SHOP_SCENE)) {
return NoticeEnum::NOTICE_SHOP;
}
//通知会员
if (in_array($scene, NoticeEnum::NOTICE_USER_SCENE)) {
return NoticeEnum::NOTICE_USER;
}
//通知游客(注册等场景)
if (in_array($scene, NoticeEnum::NOTICE_OTHER_SCENE)) {
return NoticeEnum::NOTICE_OTHER;
}
}
}

View File

@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\enum\OrderLogEnum;
use app\common\model\order\OrderLog;
/**
* 订单记录日志
* Class OrderLogLogic
* @package app\common\logic
*/
class OrderLogLogic
{
public static function record($type, $channel, $order_id, $handle_id, $content, $desc = '')
{
if (empty($content)) {
return true;
}
$log = new OrderLog();
$log->type = $type;
$log->order_id = $order_id;
$log->channel = $channel;
$log->handle_id = $handle_id;
$log->content = OrderLogEnum::getLogDesc($content);
$log->create_time = time();
if ($desc != '') {
$log->content = OrderLogEnum::getLogDesc($content) . '(' . $desc . ')';
}
$log->save();
}
}

View File

@ -0,0 +1,414 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\enum\OrderEnum;
use app\common\enum\OrderGoodsEnum;
use app\common\enum\OrderLogEnum;
use app\common\enum\OrderRefundEnum;
use app\common\enum\PayEnum;
use app\common\model\order\Order;
use app\common\model\AccountLog;
use app\common\model\order\Order as CommonOrder;
use app\common\model\order\OrderGoods;
use app\common\model\order\OrderLog;
use app\common\model\Pay;
use app\common\model\user\User;
use app\common\server\AliPayServer;
use app\common\server\DouGong\pay\PayZhengsaoRefund;
use app\common\server\WeChatPayServer;
use app\common\server\WeChatServer;
use think\Exception;
use think\facade\Db;
use think\facade\Event;
use think\facade\Log;
/**
* 订单退款逻辑
* Class OrderRefundLogic
* @package app\common\logic
*/
class OrderRefundLogic
{
/**
* Notes: 取消订单
* @param $order_id
* @param int $handle_type
* @param int $handle_id
* @author 段誉(2021/1/28 15:23)
* @return Order
*/
public static function cancelOrder($order_id, $handle_type = OrderLogEnum::TYPE_SYSTEM, $handle_id = 0)
{
//更新订单状态
// $order = order::get($order_id);
$order = Order::where('id',$order_id)->find();
$order->order_status = OrderEnum::ORDER_STATUS_DOWN;
$order->update_time = time();
$order->cancel_time = time();
$order->save();
// 取消订单后的操作
switch ($handle_type) {
case OrderLogEnum::TYPE_USER:
$channel = OrderLogEnum::USER_CANCEL_ORDER;
break;
case OrderLogEnum::TYPE_SHOP:
$channel = OrderLogEnum::SHOP_CANCEL_ORDER;
break;
case OrderLogEnum::TYPE_SYSTEM:
$channel = OrderLogEnum::SYSTEM_CANCEL_ORDER;
break;
}
event('AfterCancelOrder', [
'type' => $handle_type,
'channel' => $channel,
'order_id' => $order->id,
'handle_id' => $handle_id,
]);
}
/**
* @notes 处理订单退款(事务在取消订单逻辑处)
* @param $order
* @param $order_amount
* @param $refund_amount
* @return bool
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2021/12/20 15:13
*/
public static function refund($order, $order_amount, $refund_amount,$refund_way = OrderRefundEnum::REFUND_WAY_ORIGINAL)
{
//退款记录
$refund_id = self::addRefundLog($order, $order_amount, $refund_amount);
if ($refund_amount <= 0) {
return false;
}
$pay_way = $order['pay_way'];
if ($refund_way == OrderRefundEnum::REFUND_WAY_BALANCE) {
$pay_way = PayEnum::BALANCE_PAY;
}
switch ($pay_way) {
//余额退款
case PayEnum::BALANCE_PAY:
self::balancePayRefund($order, $refund_amount);
break;
//微信退款
case PayEnum::WECHAT_PAY:
self::wechatPayRefund($order, $refund_id);
break;
//支付宝退款
case PayEnum::ALI_PAY:
self::aliPayRefund($order, $refund_id);
break;
case PayEnum::HFDG_WECHAT:
case PayEnum::HFDG_ALIPAY:
$payZsRefund = new PayZhengsaoRefund([
'refund' => [
'id' => $refund_id,
'money' => $refund_amount,
],
'order' => [
'id' => $order['id'],
'transaction_id' => $order['transaction_id'],
'hfdg_params' => $order['hfdg_params'],
],
'from' => 'order',
]);
$result = $payZsRefund->request()->getRefundResult();
if ($result['code'] != 1) {
throw new \Exception($result['msg']);
}
break;
}
return true;
}
/**
* Notes: 微信支付退款
* @param $order mixed (订单信息)
* @param $refund_id mixed (退款记录id) 
* @author 段誉(2021/1/27 16:04)
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @throws \think\exception\PDOException
*/
public static function wechatPayRefund($order, $refund_id)
{
$config = WeChatServer::getPayConfigBySource($order['order_source'])['config'];
if (empty($config)) {
throw new Exception('请联系管理员设置微信相关配置!');
}
if (!isset($config['cert_path']) || !isset($config['key_path'])) {
throw new Exception('请联系管理员设置微信证书!');
}
if (!file_exists($config['cert_path']) || !file_exists($config['key_path'])) {
throw new Exception('微信证书不存在,请联系管理员!');
}
$refund_log = Db::name('order_refund')->where(['id' => $refund_id])->find();
$total_fee = Db::name('order_trade')->where(['transaction_id' => $order['transaction_id']])->value('order_amount');
// 单独支付的子订单 父订单未记录transaction_id 使用子订单的金额
$total_fee = $total_fee ? : $order['order_amount'];
$data = [
'transaction_id' => $order['transaction_id'],
'refund_sn' => $refund_log['refund_sn'],
'total_fee' => bcmul($total_fee, 100),//订单金额,单位为分
'refund_fee' => bcmul($refund_log['refund_amount'], 100),//退款金额
];
$result = WeChatPayServer::refund($config, $data);
if (isset($result['return_code']) && $result['return_code'] == 'FAIL') {
throw new Exception($result['return_msg']);
}
if (isset($result['err_code_des'])) {
throw new Exception($result['err_code_des']);
}
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
$update_data = [
'wechat_refund_id' => $result['refund_id'] ?? 0,
'refund_msg' => json_encode($result, JSON_UNESCAPED_UNICODE),
];
//更新退款日志记录
Db::name('order_refund')->where(['id' => $refund_id])->update($update_data);
} else {
throw new Exception('微信支付退款失败');
}
}
/**
* Notes: 支付宝退款
* @param $order
* @param $refund_id
* @author 段誉(2021/3/23 15:48)
* @throws Exception
* @throws \think\exception\PDOException
*/
public static function aliPayRefund($order, $refund_id)
{
$refund_log = Db::name('order_refund')->where(['id' => $refund_id])->find();
$trade_id = $order['trade_id'];
$trade = Db::name('order_trade')->where(['id' => $trade_id])->find();
$result = (new AliPayServer())->refund($trade['t_sn'], $refund_log['refund_amount'], $refund_log['refund_sn']);
// $result = (array)$result
if ($result['code'] == '10000' && $result['msg'] == 'Success' && $result['fund_change'] == 'Y') {
//更新退款日志记录
$update_data = [ 'refund_msg' => json_encode($result['msg'], JSON_UNESCAPED_UNICODE) ];
Db::name('order_refund')->where(['id' => $refund_id])->update($update_data);
} else {
$result = (new AliPayServer())->refund($order['order_sn'], $refund_log['refund_amount'], $refund_log['refund_sn']);
// $result = (array)$result;
if ($result['code'] == '10000' && $result['msg'] == 'Success' && $result['fund_change'] == 'Y') {
//更新退款日志记录
$update_data = [ 'refund_msg' => json_encode($result['msg'], JSON_UNESCAPED_UNICODE) ];
Db::name('order_refund')->where(['id' => $refund_id])->update($update_data);
}else{
throw new Exception('支付宝退款失败');
}
}
}
/**
* Notes: 增加退款记录
* @param $order
* @param $order_amount
* @param $refund_amount
* @param string $result_msg
* @author 段誉(2021/1/28 15:23)
* @return int|string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function addRefundLog($order, $order_amount, $refund_amount, $result_msg = '退款成功')
{
$data = [
'order_id' => $order['id'],
'user_id' => $order['user_id'],
'refund_sn' => createSn('order_refund', 'refund_sn'),
'order_amount' => $order_amount,
'refund_amount' => $refund_amount,
'transaction_id' => $order['transaction_id'],
'create_time' => time(),
'refund_status' => 1,
'refund_at' => time(),
'refund_msg' => json_encode($result_msg, JSON_UNESCAPED_UNICODE),
];
return Db::name('order_refund')->insertGetId($data);
}
/**
* Notes: 取消订单,退款后更新订单和订单商品信息
* @param $order
* @author 段誉(2021/1/28 14:21)
* @throws Exception
* @throws \think\exception\PDOException
*/
public static function cancelOrderRefundUpdate($order)
{
//订单商品=>标记退款成功状态
Db::name('order_goods')
->where(['order_id' => $order['id']])
->update(['refund_status' => OrderGoodsEnum::REFUND_STATUS_SUCCESS]);
//更新订单支付状态为已退款
Db::name('order')->where(['id' => $order['id']])->update([
'pay_status' => PayEnum::REFUNDED,
'refund_status' => OrderEnum::REFUND_STATUS_ALL_REFUND,//订单退款状态; 0-未退款1-部分退款2-全部退款
'refund_amount' => $order['order_amount'],
'is_cancel' => OrderEnum::ORDER_CANCEL,
]);
}
/**
* Notes:售后退款更新订单或订单商品状态
* @param $order
* @param $order_goods_id
* @author 段誉(2021/1/28 15:22)
*/
public static function afterSaleRefundUpdate($order, $order_goods_id, $admin_id = 0)
{
$order_goods = OrderGoods::find(['id' => $order_goods_id]);
$order_goods->refund_status = OrderGoodsEnum::REFUND_STATUS_SUCCESS;//退款成功
$order_goods->save();
//更新订单状态
$order = Order::find(['id' => $order['id']]);
$order->pay_status = PayEnum::REFUNDED;
$order->refund_amount += $order_goods['total_pay_price'];//退款金额 + 以前的退款金额
$order->refund_status = 1;//退款状态0-未退款1-部分退款2-全部退款
//如果订单商品已全部退款
if (self::checkOrderGoods($order['id'])) {
$order->order_status = CommonOrder::STATUS_CLOSE;
$order->refund_status = 2;
OrderLogLogic::record(
OrderLogEnum::TYPE_SHOP,
OrderLogEnum::SYSTEM_CANCEL_ORDER,
$order['id'],
$admin_id,
OrderLogEnum::getLogDesc(OrderLogEnum::SYSTEM_CANCEL_ORDER)
);
}
$order->save();
}
//订单内商品是否已全部
public static function checkOrderGoods($order_id)
{
$order_goods = OrderGoods::where('order_id', $order_id)->select();
if (empty($order_goods)) {
return false;
}
foreach ($order_goods as $item) {
if ($item['refund_status'] != OrderGoodsEnum::REFUND_STATUS_SUCCESS) {
return false;
}
}
return true;
}
/**
* Notes: 余额退款
* @param $order
* @param $refund_amount
* @author 段誉(2021/1/28 15:24)
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function balancePayRefund($order, $refund_amount)
{
$user = User::find($order['user_id']);
$user->user_money = ['inc', $refund_amount];
$user->save();
AccountLogLogic::AccountRecord(
$order['user_id'],
$refund_amount,
1,
AccountLog::cancel_order_refund,
'',
$order['id'],
$order['order_sn']
);
return true;
}
/**
* Notes: 退款失败增加错误记录
* @param $order
* @param $err_msg
* @author 段誉(2021/1/28 15:24)
* @return int|string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function addErrorRefund($order, $err_msg)
{
$refund_data = [
'order_id' => $order['id'],
'user_id' => $order['user_id'],
'refund_sn' => createSn('order_refund', 'refund_sn'),
'order_amount' => $order['order_amount'],//订单应付金额
'refund_amount' => $order['order_amount'],//订单退款金额
'transaction_id' => $order['transaction_id'],
'create_time' => time(),
'refund_status' => 2,
'refund_msg' => json_encode($err_msg, JSON_UNESCAPED_UNICODE),
];
return Db::name('order_refund')->insertGetId($refund_data);
}
}

View File

@ -0,0 +1,469 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\admin\logic\distribution\DistributionLevelLogic;
use app\api\logic\PayLogic;
use app\common\enum\IntegralGoodsEnum;
use app\common\enum\IntegralOrderEnum;
use app\common\enum\NoticeEnum;
use app\common\model\{AccountLog,
goods\Goods,
integral\IntegralGoods,
integral\IntegralOrder,
order\OrderGoods,
RechargeOrder,
shop\Shop};
use app\common\enum\OrderEnum;
use app\common\enum\OrderLogEnum;
use app\common\enum\PayEnum;
use app\common\model\order\Order;
use app\common\model\order\OrderTrade;
use app\common\server\DistributionServer;
use app\common\model\order\OrderLog;
use app\common\model\user\User;
use app\common\server\ConfigServer;
use think\facade\Db;
use think\Exception;
use think\facade\Log;
/**
* 支付成功后处理订单状态
* Class PayNotifyLogic
* @package app\api\logic
*/
class PayNotifyLogic
{
/**
* @notes 回调处理
* @param $action
* @param $order_sn
* @param array $extra
* @return bool|string
* @throws \think\exception\PDOException
* @author suny
* @date 2021/7/13 6:32 下午
*/
public static function handle($action, $order_sn, $extra = [])
{
Db::startTrans();
try {
self::$action($order_sn, $extra);
Db::commit();
return true;
} catch (Exception $e) {
Db::rollback();
$record = [
__CLASS__, __FUNCTION__, $e->getFile(), $e->getLine(), $e->getMessage()
];
Log::write(implode('-', $record));
return $e->getMessage();
}
}
/**
* @notes 添加订单日志表
* @param $order_id
* @param $user_id
* @param $shop_id
* @return array
* @author suny
* @date 2021/7/13 6:32 下午
*/
public static function getOrderLogData($order_id, $user_id, $shop_id)
{
$order_log_data = [];
$order_log_data['type'] = OrderLogEnum::TYPE_USER;
$order_log_data['channel'] = OrderLogEnum::USER_PAID_ORDER;
$order_log_data['order_id'] = $order_id;
$order_log_data['handle_id'] = $user_id;
$order_log_data['shop_id'] = $shop_id;
$order_log_data['content'] = OrderLogEnum::getLogDesc(OrderLogEnum::USER_PAID_ORDER);
$order_log_data['create_time'] = time();
return $order_log_data;
}
/**
* @notes 父订单回调
* @param $order_sn
* @param array $extra
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author suny
* @date 2021/7/13 6:33 下午
*/
private static function trade($order_sn, $extra = [])
{
//根据父订单号查找父订单
$trade = OrderTrade::where(['t_sn' => $order_sn])->find();
//根据父订单id查找子订单
$orders = Order::with(['order_goods', 'shop'])
->where('trade_id', $trade['id'])
->select()->toArray();
//修改用户消费累计额度
$user = User::find($trade['user_id']);
$user->total_order_amount = ['inc', $trade['order_amount']];
$user->save();
//赠送成长值
$growth_ratio = ConfigServer::get('transaction', 'money_to_growth', 0);
if ($growth_ratio > 0) {
$able_get_growth = floor($trade['total_amount'] / $growth_ratio);
$user->where('id', $trade['user_id'])
->inc('user_growth', $able_get_growth)
->update();
AccountLogLogic::AccountRecord($trade['user_id'], $able_get_growth, 1, AccountLog::order_give_growth, '', $trade['id'], $order_sn);
}
// 生成分销订单
PayLogic::distributionOrderGoods(array_column($orders, 'id'));
// 更新分销会员等级
DistributionLevelLogic::updateDistributionLevel($trade['user_id']);
foreach ($orders as $item) {
//赠送积分
$open_award = ConfigServer::get('order_award', 'open_award', 0);
if ($open_award == 1) {
$award_event = ConfigServer::get('order_award', 'award_event', 0);
$award_ratio = ConfigServer::get('order_award', 'award_ratio', 0);
if ($award_ratio > 0) {
$award_integral = floor($item['order_amount'] * ($award_ratio / 100));
}
}
$orderStatus = Order::STATUS_WAIT_DELIVERY;
//线下自提订单支付完成后订单状态改为待收货
if ($item['delivery_type'] == OrderEnum::DELIVERY_TYPE_SELF) {
$orderStatus = Order::STATUS_WAIT_RECEIVE;
}
//更新订单状态
$data = [
'pay_status' => PayEnum::ISPAID,
'pay_time' => time(),
'order_status' => $orderStatus,
'award_integral_status' => $award_event ?? 0,
'award_integral' => $award_integral ?? 0
];
//如果返回了第三方流水号
if (isset($extra['transaction_id'])) {
$data['transaction_id'] = $extra['transaction_id'];
}
$orderUpdate = Order::update($data, [
[ 'id', '=', $item['id'] ],
[ 'pay_status', '=', PayEnum::UNPAID ],
]);
if ($orderUpdate->getUpdateResult() <= 0) {
throw new \Exception('修改订单状态失败,订单可能已支付');
}
// 增加一条订单日志
$order_log_add_data = self::getOrderLogData($item['id'], $item['user_id'], $item['shop_id']);
$order_log_datas_insert[] = $order_log_add_data;
OrderLog::insertAll($order_log_datas_insert);
// if ($item['order_type'] == order::NORMAL_ORDER){
// DistributionServer::commission($item['id']);
// }
//通知用户
event('Notice', [
'scene' => NoticeEnum::ORDER_PAY_NOTICE,
'mobile' => $item['mobile'] ?? '',
'params' => ['order_id' => $item['id'], 'user_id' => $item['user_id']]
]);
//通知商家
if (!empty($item['shop']['mobile'])) {
event('Notice', [
'scene' => NoticeEnum::USER_PAID_NOTICE_SHOP,
'mobile' => $item['shop']['mobile'],
'params' => ['order_id' => $item['id'], 'user_id' => $item['user_id']]
]);
}
event('Printer', [
'order_id' => $item['id'],
]);
}
//如果返回了第三方流水号
if (isset($extra['transaction_id'])) {
$trade->transaction_id = $extra['transaction_id'];
$trade->save();
}
$order_ids = array_column($orders, 'id');
// 虚拟商品更新订单信息
GoodsVirtualLogic::afterPayVirtualDelivery($order_ids);
// 更新商品销量
self::updateGoodsSales($order_ids);
}
/**
* @notes 子订单回调
* @param $order_sn
* @param array $extra
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author suny
* @date 2021/7/13 6:33 下午
*/
private static function order($order_sn, $extra = [])
{
$time = time();
$order = Order::with(['order_goods', 'shop'])
->where('order_sn', $order_sn)
->find()->toArray();
//赠送积分
$open_award = ConfigServer::get('order_award', 'open_award', 0);
if ($open_award == 1) {
$award_event = ConfigServer::get('order_award', 'award_event', 0);
$award_ratio = ConfigServer::get('order_award', 'award_ratio', 0);
if ($award_ratio > 0) {
$award_integral = floor($order['order_amount'] * ($award_ratio / 100));
}
}
$orderStatus = Order::STATUS_WAIT_DELIVERY;
//线下自提订单支付完成后订单状态改为待收货
if ($order['delivery_type'] == OrderEnum::DELIVERY_TYPE_SELF) {
$orderStatus = Order::STATUS_WAIT_RECEIVE;
}
//更新订单状态
$data = [
'pay_status' => PayEnum::ISPAID,
'pay_time' => time(),
'order_status' => $orderStatus,
'award_integral_status' => $award_event ?? 0,
'award_integral' => $award_integral ?? 0
];
//如果返回了第三方流水号
if (isset($extra['transaction_id'])) {
$data['transaction_id'] = $extra['transaction_id'];
}
$orderUpdate = Order::update($data, [
[ 'id', '=', $order['id'] ],
[ 'pay_status', '=', PayEnum::UNPAID ],
]);
if ($orderUpdate->getUpdateResult() <= 0) {
throw new \Exception('修改订单状态失败,订单可能已支付');
}
// 增加商品销量
// 增加一条订单日志
$order_log_add_data = self::getOrderLogData($order['id'], $order['user_id'], $order['shop_id']);
$order_log_datas_insert[] = $order_log_add_data;
OrderLog::insertAll($order_log_datas_insert);
//修改用户消费累计额度
$user = User::find($order['user_id']);
$user->total_order_amount = ['inc', $order['order_amount']];
$user->save();
//赠送成长值
$growth_ratio = ConfigServer::get('transaction', 'money_to_growth', 0);
if ($growth_ratio > 0) {
$able_get_growth = floor($order['order_amount'] / $growth_ratio);
$user->where('id', $order['user_id'])
->inc('user_growth', $able_get_growth)
->update();
AccountLogLogic::AccountRecord($order['user_id'], $able_get_growth, 1, AccountLog::order_give_growth, '', $order['id'], $order_sn);
}
// 生成分销订单
PayLogic::distributionOrderGoods([$order['id']]);
// 更新分销会员等级
DistributionLevelLogic::updateDistributionLevel($order['user_id']);
// //拼购,砍价的订单不参与分销分佣
// if ($order['order_type'] == order::NORMAL_ORDER){
// DistributionServer::commission($order['id']);
// }
// 虚拟商品更新订单信息
GoodsVirtualLogic::afterPayVirtualDelivery($order['id']);
// 更新商品销量
self::updateGoodsSales($order['id']);
//通知用户
event('Notice', [
'scene' => NoticeEnum::ORDER_PAY_NOTICE,
'mobile' => $order['mobile'] ?? '',
'params' => ['order_id' => $order['id'], 'user_id' => $order['user_id']]
]);
//通知商家
if (!empty($order['shop']['mobile'])) {
event('Notice', [
'scene' => NoticeEnum::USER_PAID_NOTICE_SHOP,
'mobile' => $order['shop']['mobile'],
'params' => ['order_id' => $order['id'], 'user_id' => $order['user_id']]
]);
}
event('Printer', [
'order_id' => $order['id'],
]);
}
/**
* @notes 充值回调
* @param $order_sn
* @param array $extra
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author suny
* @date 2021/7/13 6:33 下午
*/
private static function recharge($order_sn, $extra = [])
{
$new = time();
$recharge_order = new RechargeOrder();
$order = $recharge_order->where(['order_sn' => $order_sn])->find();
$update_data['pay_time'] = $new;
$update_data['pay_status'] = PayEnum::ISPAID;
if (isset($extra['transaction_id'])) {
$update_data['transaction_id'] = $extra['transaction_id'];
}
$recharge_order->where(['id' => $order['id']])->update($update_data);
$user = User::find($order['user_id']);
$total_money = $order['order_amount'] + $order['give_money'];
$total_integral = $order['give_integral'];
$user->user_money = ['inc', $total_money];
$user->user_integral = ['inc', $total_integral];
$user->user_growth = ['inc', $order['give_growth']];
$user->total_recharge_amount = ['inc', $total_money];
$user->save();
//记录余额
$total_money > 0 && AccountLogLogic::AccountRecord($user->id, $total_money, 1, AccountLog::recharge_money, '', $order['id'], $order_sn);
//记录积分
$total_integral > 0 && AccountLogLogic::AccountRecord($user->id, $total_integral, 1, AccountLog::recharge_give_integral);
//记录成长值
$order['give_growth'] > 0 && AccountLogLogic::AccountRecord($user->id, $order['give_growth'], 1, AccountLog::recharge_give_growth);
}
/**
* @notes 积分订单回调
* @param $order_sn
* @param array $extra
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/3/1 14:36
*/
private static function integral($order_sn, $extra = [])
{
$order = IntegralOrder::where(['order_sn' => $order_sn])->findOrEmpty();
$goods = $order['goods_snap'];
// 更新订单状态
$data = [
'order_status' => IntegralOrderEnum::ORDER_STATUS_DELIVERY,
'pay_status' => PayEnum::ISPAID,
'pay_time' => time(),
];
// 红包类型 或者 无需物流 支付完即订单完成
if ($goods['type'] == IntegralGoodsEnum::TYPE_BALANCE || $goods['delivery_way'] == IntegralGoodsEnum::DELIVERY_NO_EXPRESS) {
$data['order_status'] = IntegralOrderEnum::ORDER_STATUS_COMPLETE;
$data['confirm_time'] = time();
}
// 第三方流水号
if (isset($extra['transaction_id'])) {
$data['transaction_id'] = $extra['transaction_id'];
}
IntegralOrder::update($data, ['id' => $order['id']]);
// 更新商品销量
IntegralGoods::where([['id', '=', $goods['id']], ['stock', '>=', $order['total_num']]])
->dec('stock', $order['total_num'])
->inc('sales', $order['total_num'])
->update();
// 红包类型,直接增加余额
if ($goods['type'] == IntegralGoodsEnum::TYPE_BALANCE) {
$reward = round($goods['balance'] * $order['total_num'], 2);
User::where(['id' => $order['user_id']])
->inc('user_money', $reward)
->update();
AccountLogLogic::AccountRecord(
$order['user_id'],
$reward, 1,
AccountLog::integral_order_inc_balance,
'', $order['id'], $order['order_sn']
);
}
}
/**
* @notes 更新商品销量
* @param $order_id
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/10/14 10:16
*/
private static function updateGoodsSales($order_ids)
{
if (!is_array($order_ids)) {
$order_ids = [$order_ids];
}
$order_goods = OrderGoods::whereIn('order_id', $order_ids)
->select()
->toArray();
if (empty($order_goods)) {
return false;
}
foreach ($order_goods as $item) {
// 增加商品销量
Goods::where('id', $item['goods_id'])
->inc('sales_actual', $item['goods_num'])
->update();
}
return true;
}
}

View File

@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use think\facade\Env;
class PaymentLogic
{
protected static $error = '';
protected static $return_code = 0;
/**
* Notes: 错误信息
* @return string
* @author 段誉(2021/2/1 11:19)
*/
public static function getError()
{
return self::$error;
}
/**
* Notes: 返回状态码
* @return int
* @author 段誉(2021/2/1 11:19)
*/
public static function getReturnCode()
{
return self::$return_code;
}
}

View File

@ -0,0 +1,652 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\enum\ClientEnum;
use app\common\model\RechargeTemplate;
use app\common\server\ConfigServer;
use app\common\server\FileServer;
use app\common\server\storage\Driver as StorageDriver;
use app\common\server\UrlServer;
use app\common\server\WeChatServer;
use app\common\server\JsonServer;
use EasyWeChat\Kernel\Http\StreamResponse;
use Endroid\QrCode\QrCode;
use think\facade\Cache;
use think\Exception;
use EasyWeChat\Factory;
use think\facade\Log;
use think\facade\Request;
class QrCodeLogic
{
//商品图片配置
public function goodsShareConfig(){
return [
//会员头像
'head_pic' => [
'w' => 64, 'h' => 64, 'x' => 40, 'y' => 20,
],
//会员昵称
'nickname' => [
'color' => '#555555', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 19, 'x' => 120, 'y' => 60,
],
//标题
'title' => [
'color' => '#333333', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Bold.otf', 'font_size' => 20, 'w' => 360, 'x' => 40, 'y' => 785,
],
//价格符号
'price_symbol' => [
'color' => '#FF2C3C', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 22, 'w' => 140, 'x' => 40, 'y' => 722,
],
//商品价格
'price' => [
'color' => '#FF2C3C', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Bold.otf', 'font_size' => 32, 'w' => 140, 'x' => 64, 'y' => 722,
],
//小数
'decimal'=> [
'color' => '#FF2C3C', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Bold.otf', 'font_size' => 22, 'w' => 140, 'x' => 114, 'y' => 722,
],
//市场价
'market_price_symbol' => [
'color' => '#999999', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 22, 'w' => 140, 'x' => 142, 'y' => 722,
],
//市场价符号
'market_price' => [
'color' => '#999999', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 20, 'w' => 140, 'x' => 168, 'y' => 722,
],
//推广主图商品主图
'main_pic' => [
'w' => 560, 'h' => 560, 'x' => 40, 'y' => 100,
],
//提醒长按扫码
'notice' => [
'color' => '#888888', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 18, 'x' => 432, 'y' => 895,
],
//二维码
'qr' => [
'w' => 165,'h' => 165, 'x' => 436, 'y' => 700,
],
];
}
//生成商品分享图
public function makeGoodsPoster($user,$goods,$url,$url_type){
try {
$save_dir = ROOT_PATH .'/uploads/qr_code/goods_share/';
$background_img = ROOT_PATH .'/images/share/share_goods_bg.png';
!file_exists($save_dir) && mkdir($save_dir, 0777, true);
$cache_key = 'gid' . $goods['id'].'uid'.$user['id'].$url_type;
$qr_src = md5($cache_key) . '.png';
$poster_url = $save_dir . $qr_src;
$base64 = Cache::get($cache_key);
if (!empty($base64)) {
$data = [
'code' => 1,
'msg' => '海报生成成功',
'show' => 0,
'data' => $base64
];
return json($data);
}
$poster_config = self::goodsShareConfig();
//生成二维码
if($url_type == 'path'){
$scene = 'id='.$goods['id'].'&invite_code='.$user['distribution_code'];
$result = $this->makeMnpQrcode($scene,$url,$qr_src,$save_dir);
if(true !== $result){
return JsonServer::error('微信配置错误:'.$result);
}
}else{
$qrCode = new QrCode();
$qrCode->setText($url);
$qrCode->setSize(1000);
$qrCode->setWriterByName('png');
$qrCode->writeFile($poster_url);
}
$user_avatar = UrlServer::getFileUrl($user['avatar']);
//判断头像是否存在
if(!check_file_exists($user_avatar)){
//如果不存在,使用默认头像
$user_avatar = ROOT_PATH.ConfigServer::get('website', 'user_image');
}
//默认商品主图
$goods_image = UrlServer::getFileUrl($goods['image']);
//判断是否有自定义分享海报图
if($goods['poster']){
$goods_image = UrlServer::getFileUrl($goods['poster']);
}
if(!check_file_exists($goods_image)){
//如果不存在,使用默认商品主图
$goods_image = ROOT_PATH.ConfigServer::get('website', 'goods_image');
}
$qr_code_logic = new QrCodeLogic();
//获取背景图
$share_background_img = imagecreatefromstring(file_get_contents($background_img));
//合成头像
$qr_code_logic->writeImg($share_background_img, $user_avatar, $poster_config['head_pic'],true);
//合并商品主图
$qr_code_logic->writeImg($share_background_img, $goods_image, $poster_config['main_pic'],false);
//合成昵称
$nickname = filterEmoji($user['nickname']);
$nickname = '来自'.$nickname.'的分享';
$qr_code_logic->writeText($share_background_img, $nickname, $poster_config['nickname']);
//长按识别
$notice = '长按识别二维码';
$qr_code_logic->writeText($share_background_img, $notice, $poster_config['notice']);
//合成价格
$qr_code_logic->writeText($share_background_img, '¥', $poster_config['price_symbol']);
$qr_code_logic->writeText($share_background_img, floatval($goods['min_price']), $poster_config['price']);
//合成商品标题
$goods_name = auto_adapt($poster_config['title']['font_size'], 0, $poster_config['title']['font_face'], $goods['name'], $poster_config['title']['w'],$poster_config['title']['y'],getimagesize($background_img));
$qr_code_logic->writeText($share_background_img, $goods_name, $poster_config['title']);
//合成二维码
$qr_code_logic->writeImg($share_background_img, $poster_url, $poster_config['qr'],false);
imagepng($share_background_img, $poster_url);
if ($fp = fopen($poster_url, "rb", 0)) {
$gambar = fread($fp, filesize($poster_url));
fclose($fp);
$base64 = chunk_split(base64_encode($gambar));
$base64 = 'data:image/png;base64,' . $base64;
}
//删除文件
// if (strstr($poster_url, $save_dir)) {
// unlink($poster_url);
// }
Cache::set($cache_key, $base64, 3600);
$data = [
'code' => 1,
'msg' => '海报生成成功',
'show' => 0,
'data' => $base64
];
return json($data);
}catch (Exception $e){
return JsonServer::error('海报生成错误:' . $e->getMessage());
}
}
//用户图片配置
public function userShareConfig()
{
return [
//会员头像
'head_pic' => [
'w' => 80, 'h' => 80, 'x' => 30, 'y' => 680,
],
//会员昵称
'nickname' => [
'color' => '#333333', 'font_face' => ROOT_PATH.'/font/SourceHanSansCN-Regular.otf', 'font_size' => 20, 'x' => 120, 'y' => 730,
],
//标题
'title' => [
'color' => '#333333', 'font_face' => ROOT_PATH.'/font/SourceHanSansCN-Regular.otf', 'font_size' => 20, 'w' => 360, 'x' => 30, 'y' => 810,
],
//提醒长按扫码
'notice' => [
'color' => '#333333', 'font_face' => ROOT_PATH.'/font/SourceHanSansCN-Regular.otf', 'font_size' => 20, 'x' => 30, 'y' => 880,
],
//邀请码文本
'code_text' => [
'color' => '#FF2C3C', 'font_face' => ROOT_PATH.'/font/SourceHanSansCN-Regular.otf', 'font_size' => 20, 'x' => 355, 'y' => 930,
],
//二维码
'qr' => [
'w' => 170,'h' => 170, 'x' => 370, 'y' => 730,
],
];
}
//生成用户小程序二维码
public function makeUserMnpQrcode($code,$content,$img_src)
{
try {
$config = WeChatServer::getMnpConfig();
$app = Factory::miniProgram($config);
$response = $app->app_code->get($content.'?invite_code='.$code, [
'width' => 170,
]);
if ($response instanceof StreamResponse) {
$response->saveAs('uploads/qr_code/user_share/', $img_src);
return true;
}
if(isset($response['errcode']) && 41030 === $response['errcode']){
return '商城小程序码,先提交审核并通过';
}
return $response['errmsg'];
} catch (\EasyWeChat\Kernel\Exceptions\Exception $e){
return $e->getMessage();
}
}
//生成用户分享图
public function makeUserPoster($user, $content, $url_type, $client)
{
try {
$save_dir = 'uploads/qr_code/user_share/';
$shareBg = ConfigServer::get('invite', 'poster', 'images/share/share_user_bg.png');
$background_img = ROOT_PATH .'/'.$shareBg;
!file_exists($save_dir) && mkdir($save_dir, 0777, true);
$save_key = 'uid'.$user['id'].$url_type.$client;
$qr_src = md5($save_key) . '.png';
$poster_url = ROOT_PATH.'/'.$save_dir . $qr_src;
$poster_config = $this->userShareConfig();
//生成二维码
if($url_type == 'path'){
$result = $this->makeUserMnpQrcode($user['distribution_code'], $content, $qr_src);
if(true !== $result){
return ['status' => 0, 'msg' => '微信配置错误:'.$result, 'data' => ''];
}
}else{
$qrCode = new QrCode();
$qrCode->setText($content);
$qrCode->setSize(1000);
$qrCode->setWriterByName('png');
$qrCode->writeFile($poster_url);
}
$user_avatar = UrlServer::getFileUrl($user['avatar'],'share');
//判断头像是否存在
if(!check_file_exists($user_avatar)){
//如果不存在,使用默认头像
$user_avatar = ROOT_PATH.ConfigServer::get('website', 'user_image');
}
$qr_code_logic = new QrCodeLogic();
//获取背景图
$share_background_img = imagecreatefromstring(file_get_contents($background_img));
//合成头像
$qr_code_logic->writeImg($share_background_img, $user_avatar, $poster_config['head_pic'],true);
//合成昵称
$nickname = filterEmoji($user['nickname']);
$qr_code_logic->writeText($share_background_img, $nickname, $poster_config['nickname']);
//长按识别
$notice = '长按识别二维码 >>';
$qr_code_logic->writeText($share_background_img, $notice, $poster_config['notice']);
//合成商品标题
$title = auto_adapt($poster_config['title']['font_size'], 0, $poster_config['title']['font_face'], '邀请你一起来赚大钱', $poster_config['title']['w'],$poster_config['title']['y'],getimagesize($background_img));
$qr_code_logic->writeText($share_background_img, $title, $poster_config['title']);
//邀请码
$qr_code_logic->writeText($share_background_img, '邀请码 '.$user['distribution_code'], $poster_config['code_text']);
//合成二维码
$qr_code_logic->writeImg($share_background_img, $poster_url, $poster_config['qr'],false);
imagepng($share_background_img, $poster_url);
$file_name = $save_dir . $qr_src;
$local_uir = ROOT_PATH.'/'.$file_name;
self::upload($local_uir, $file_name, [ 'delete_file' => 1 ]);
return ['status' => 1, 'msg' => '', 'data' => $file_name];
}catch (Exception $e){
return ['status' => 0, 'msg' => $e->getMessage(), 'data' => ''];
}
}
/**
* Notes: 生成的图片根据不同的存储方式储存
* @param $local_uri mixed 本地图片路径 绝对路径
* @param $file_name mixed 本地图片路径 相对路径
* @throws Exception
* @author 段誉(2021/3/2 18:47)
*/
public function upload($local_uri, $file_name, $params = [])
{
$delete_file = $params['delete_file'] ?? 0;
$config = [
'default' => ConfigServer::get('storage', 'default', 'local'),
'engine' => ConfigServer::get('storage_engine')
];
if (empty($config['engine']['local'])) {
$config['engine']['local'] = [];
}
if ($config['default'] != 'local') {
$StorageDriver = new StorageDriver($config);
if (!$StorageDriver->fetch($local_uri, $file_name)) {
throw new Exception('图片保存出错:' . $StorageDriver->getError());
}
//删除本地图片
if ($delete_file) {
@unlink($file_name);
}
}
}
//砍价图片配置
public function bargainShareConfig(){
return [
//会员头像
'head_pic' => [
'w' => 64, 'h' => 64, 'x' => 40, 'y' => 20,
],
//会员昵称
'nickname' => [
'color' => '#555555', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 19, 'x' => 120, 'y' => 60,
],
'bargain_title' => [
'color' => '#FF2C3C', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Bold.otf', 'font_size' => 24, 'w' => 360, 'x' => 40, 'y' => 735,
],
'brief_title' => [
'color' => '#F95F2F', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 16, 'w' => 360, 'x' => 40, 'y' => 765,
],
//标题
'title' => [
'color' => '#333333', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 20, 'w' => 360, 'x' => 40, 'y' => 795,
],
//推广主图商品主图
'main_pic' => [
'w' => 560, 'h' => 560, 'x' => 40, 'y' => 100,
],
//提醒长按扫码
'notice' => [
'color' => '#888888', 'font_face' => ROOT_PATH .'/font/SourceHanSansCN-Regular.otf', 'font_size' => 18, 'x' => 432, 'y' => 895,
],
//二维码
'qr' => [
'w' => 165,'h' => 165, 'x' => 436, 'y' => 700,
],
];
}
// 生成砍价海报
public function makeBargainPoster($user,$bargain_launch,$url,$url_type){
try {
$save_dir = ROOT_PATH .'/uploads/qr_code/bargain_share/';
$background_img = ROOT_PATH .'/images/share/share_goods_bg.png';
!file_exists($save_dir) && mkdir($save_dir,0777,true);
$cache_key = 'bid' . $bargain_launch['id'].'uid'.$user['id'].$url_type;
$qr_src = md5($cache_key) . '.png';
$poster_url = $save_dir . $qr_src;
$base64 = Cache::get($cache_key);
if (!empty($base64)) {
$data = [
'code' => 1,
'msg' => '海报生成成功',
'show' => 0,
'data' => $base64
];
return json($data);
}
$poster_config = self::bargainShareConfig();
//生成二维码
if($url_type == 'path'){
$scene = 'id='.$bargain_launch['id'];
$result = $this->makeMnpQrcode($scene,$url,$qr_src,$save_dir);
if(true !== $result){
return JsonServer::error('微信配置错误:'.$result);
}
}else{
$qrCode = new QrCode();
$qrCode->setText($url);
$qrCode->setSize(1000);
$qrCode->setWriterByName('png');
$qrCode->writeFile($poster_url);
}
$user_avatar = UrlServer::getFileUrl($user['avatar']);
//判断头像是否存在
if(!check_file_exists($user_avatar)){
//如果不存在,使用默认头像
$user_avatar = ROOT_PATH.ConfigServer::get('website', 'user_image');
}
//判断商品主图是否存在
$goods_image = UrlServer::getFileUrl($bargain_launch['goods_snap']['goods_iamge'],'share');
if(!check_file_exists($goods_image)){
//如果不存在,使用默认商品主图
$goods_image = ROOT_PATH.ConfigServer::get('website', 'goods_image');
}
$qr_code_logic = new QrCodeLogic();
//获取背景图
$share_background_img = imagecreatefromstring(file_get_contents($background_img));
//合成头像
$qr_code_logic->writeImg($share_background_img, $user_avatar, $poster_config['head_pic'],true);
//合并商品主图
$qr_code_logic->writeImg($share_background_img, $goods_image, $poster_config['main_pic'],false);
//合成昵称
$nickname = filterEmoji($user['nickname']);
$nickname = '来自'.$nickname.'的分享';
$qr_code_logic->writeText($share_background_img, $nickname, $poster_config['nickname']);
//长按识别
$notice = '长按识别二维码';
$qr_code_logic->writeText($share_background_img, $notice, $poster_config['notice']);
//合成砍价标题
$bargain_title = '我正在参与砍价 还差一步';
$qr_code_logic->writeText($share_background_img, $bargain_title, $poster_config['bargain_title']);
//合成简介
$brief_title = '帮忙砍一刀';
$qr_code_logic->writeText($share_background_img, $brief_title, $poster_config['brief_title']);
//合成商品标题
$goods_name = auto_adapt($poster_config['title']['font_size'], 0, $poster_config['title']['font_face'], $bargain_launch['goods_snap']['name'], $poster_config['title']['w'],$poster_config['title']['y'],getimagesize($background_img));
$qr_code_logic->writeText($share_background_img, $goods_name, $poster_config['title']);
//合成二维码
$qr_code_logic->writeImg($share_background_img, $poster_url, $poster_config['qr'],false);
imagepng($share_background_img, $poster_url);
if ($fp = fopen($poster_url, "rb", 0)) {
$gambar = fread($fp, filesize($poster_url));
fclose($fp);
$base64 = chunk_split(base64_encode($gambar));
$base64 = 'data:image/png;base64,' . $base64;
}
//删除文件
if (strstr($poster_url, $save_dir)) {
unlink($poster_url);
}
$expire = $bargain_launch['launch_end_time'] - time();
Cache::set($cache_key, $base64, $expire);
$data = [
'code' => 1,
'msg' => '海报生成成功',
'show' => 0,
'data' => $base64
];
return json($data);
}catch (Exception $e){
return JsonServer::error('海报生成错误:' . $e->getMessage());
}
}
//小程序生成二维码(非永久码)
public function makeMnpQrcode($scene,$url,$img_src,$save_dir){
try {
$config = WeChatServer::getMnpConfig();
$app = Factory::miniProgram($config);
$response = $app->app_code->getUnlimit($scene, [
'page' => $url,
]);
if ($response instanceof StreamResponse) {
$response->saveAs($save_dir, $img_src);
return true;
}
if(isset($response['errcode']) && 41030 === $response['errcode']){
return '商城小程序未上线或商城小程序页面发布';
}
return $response['errmsg'];
} catch (\EasyWeChat\Kernel\Exceptions\Exception $e){
return $e->getMessage();
}
}
//写入图片
public function writeImg($poster, $img_uri, $config, $is_rounded = false){
$pic_img = imagecreatefromstring(file_get_contents($img_uri));
$is_rounded?$pic_img = rounded_corner($pic_img):'';//切成圆角返回头像资源
$pic_w = imagesx($pic_img);
$pic_h = imagesy($pic_img);
//圆形头像大图合并到海报
imagecopyresampled($poster, $pic_img,
$config['x'],
$config['y'],
0, 0,
$config['w'],
$config['h'],
$pic_w,
$pic_h
);
return $poster;
}
//写入文字
public function writeText($poster, $text, $config){
$font_uri = $config['font_face'];
$font_size = $config['font_size'];
$color = substr($config['color'],1);
//颜色转换
$color= str_split($color, 2);
$color = array_map('hexdec', $color);
if (empty($color[3]) || $color[3] > 127) {
$color[3] = 0;
}
//写入文字
$font_col = imagecolorallocatealpha($poster, $color[0], $color[1], $color[2], $color[3]);
imagettftext($poster, $font_size,0, $config['x'], $config['y'], $font_col, $font_uri, $text);
return $poster;
}
/**
* @notes 店铺二维码
* @param $shop_id
* @param $terminal
* @return string
* @author lbzy
* @datetime 2024-04-01 10:59:40
*/
function shopQrCode($shop_id, $terminal = null) : string
{
try {
$url = '/pages/store_index/store_index?id=' . $shop_id;
$path = 'uploads/qr_code/shop/';
$filename = 'detail.' . md5($shop_id . $terminal) . '.png';
$local_file = $path . $filename;
$save_dir = ROOT_PATH . '/' . $path;
$poster_url = $save_dir . $filename;
//校验二维码是否已存在
$engine = ConfigServer::get('storage', 'default', 'local');
if (empty($engine) || $engine === 'local') {
//本地文件
if (file_exists($poster_url)) {
return UrlServer::getFileUrl($local_file);
}
} else {
$file = UrlServer::getFileUrl($local_file);
$header = get_headers($file, true);
if (isset($header[0]) && (strpos($header[0], '200') || strpos($header[0], '304'))) {
return $file;
}
}
//判断是否存在保存目录
! file_exists($save_dir) && mkdir($save_dir, 0777, true);
switch ($terminal) {
// 小程序 返回小程序码
case ClientEnum::mnp:
$config = WeChatServer::getMnpConfig();
$app = Factory::miniProgram($config);
$response = $app->app_code->get($url, [
'width' => 240,
//...
]);
if ($response instanceof StreamResponse) {
$response->saveAs($save_dir, $filename);
}
break;
// 其他 返回普通二维码
default:
$qrCode = new QrCode();
$qrCode->setText(Request::domain(true) . '/mobile' . $url);
$qrCode->setSize(240);
$qrCode->setWriterByName('png');
$qrCode->writeFile($poster_url);
break;
}
$this->upload($poster_url, $local_file, [ 'delete_file' => 0 ]);
return UrlServer::getFileUrl($local_file);
} catch(\Throwable $e) {
Log::write($e->__toString(), 'shop_qr_code_error');
return '';
}
}
}

View File

@ -0,0 +1,171 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\model\DevRegion;
class RegionLogic extends Logic
{
/**
* @notes 地级市
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author ljj
* @date 2022/9/20 5:49 下午
*/
public static function city()
{
$lists = DevRegion::where(['level'=>2])
->field('id,parent_id,level,name,short,city_code,zip_code,gcj02_lng,gcj02_lat,db09_lng,db09_lat,remark1,remark2')
->select()
->toArray();
$lists = self::groupByInitials($lists);
unset($lists[null]);
return $lists;
}
/**
* 二维数组根据首字母分组排序
* @param array $data 二维数组
* @param string $targetKey 首字母的键名
* @return array 根据首字母关联的二维数组
*/
public static function groupByInitials(array $data, $targetKey = 'name')
{
$data = array_map(function ($item) use ($targetKey) {
return array_merge($item, [
'initials' => self::getInitials($item[$targetKey]),
]);
}, $data);
$data = self::sortInitials($data);
return $data;
}
/**
* 按字母排序
* @param array $data
* @return array
*/
public static function sortInitials(array $data)
{
$sortData = [];
foreach ($data as $key => $value) {
$sortData[$value['initials']][] = $value;
}
ksort($sortData);
return $sortData;
}
/**
* 获取首字母
* @param string $str 汉字字符串
* @return string 首字母
*/
public static function getInitials($str)
{
if (empty($str)) {return '';}
$fchar = ord($str[0]);
if ($fchar >= ord('A') && $fchar <= ord('z')) {
return strtoupper($str[0]);
}
$s1 = iconv('UTF-8', 'GBK', $str);
$s2 = iconv('GBK', 'UTF-8', $s1);
$s = $s2 == $str ? $s1 : $str;
$asc = ord($s[0]) * 256 + ord($s[1]) - 65536;
if ($asc >= -20319 && $asc <= -20284) {
return 'A';
}
if ($asc >= -20283 && $asc <= -19776) {
return 'B';
}
if ($asc >= -19775 && $asc <= -19219) {
return 'C';
}
if ($asc >= -19218 && $asc <= -18711) {
return 'D';
}
if ($asc >= -18710 && $asc <= -18527) {
return 'E';
}
if ($asc >= -18526 && $asc <= -18240) {
return 'F';
}
if ($asc >= -18239 && $asc <= -17923) {
return 'G';
}
if ($asc >= -17922 && $asc <= -17418) {
return 'H';
}
if ($asc >= -17417 && $asc <= -16475) {
return 'J';
}
if ($asc >= -16474 && $asc <= -16213) {
return 'K';
}
if ($asc >= -16212 && $asc <= -15641) {
return 'L';
}
if ($asc >= -15640 && $asc <= -15166) {
return 'M';
}
if ($asc >= -15165 && $asc <= -14923) {
return 'N';
}
if ($asc >= -14922 && $asc <= -14915) {
return 'O';
}
if ($asc >= -14914 && $asc <= -14631) {
return 'P';
}
if ($asc >= -14630 && $asc <= -14150) {
return 'Q';
}
if ($asc >= -14149 && $asc <= -14091) {
return 'R';
}
if ($asc >= -14090 && $asc <= -13319) {
return 'S';
}
if ($asc >= -13318 && $asc <= -12839) {
return 'T';
}
if ($asc >= -12838 && $asc <= -12557) {
return 'W';
}
if ($asc >= -12556 && $asc <= -11848) {
return 'X';
}
if ($asc >= -11847 && $asc <= -11056) {
return 'Y';
}
if ($asc >= -11055 && $asc <= -10247) {
return 'Z';
}
return null;
}
}

View File

@ -0,0 +1,49 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\enum\ShopWithdrawEnum;
use app\common\server\ConfigServer;
class SettingLogic extends Logic
{
static function getShopWithdraw()
{
$detail['withdrawal_type'] = ConfigServer::get('shop_withdrawal', 'withdrawal_type', [ ShopWithdrawEnum::TYPE_BANK ]);
foreach ($detail['withdrawal_type'] as &$withdrawal_type) {
$withdrawal_type = intval($withdrawal_type);
}
$detail['min_withdrawal_money'] = ConfigServer::get('shop_withdrawal', 'min_withdrawal_money', 0);
$detail['max_withdrawal_money'] = ConfigServer::get('shop_withdrawal', 'max_withdrawal_money', 0);
$detail['withdrawal_service_charge'] = ConfigServer::get('shop_withdrawal', 'withdrawal_service_charge', 0);
return $detail;
}
static function setShopWithdraw($data)
{
ConfigServer::set('shop_withdrawal', 'withdrawal_type', array_values($data['withdrawal_type'] ?? []));
ConfigServer::set('shop_withdrawal', 'min_withdrawal_money', $data['min_withdrawal_money'] ?? 0);
ConfigServer::set('shop_withdrawal', 'max_withdrawal_money', $data['max_withdrawal_money'] ?? 0);
ConfigServer::set('shop_withdrawal', 'withdrawal_service_charge', $data['withdrawal_service_charge'] ?? 0);
}
}

View File

@ -0,0 +1,113 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\enum\NoticeEnum;
use app\common\model\SmsLog;
/**
* 短信
* Class SmsLogic
* @package app\common\logic
*/
class SmsLogic extends Logic
{
protected static $expire_time = 300; //验证码有效时间
protected static $check_num = 5; //验证次数
/**
* Notes: 发送验证码
* @param $mobile
* @param $scene
* @param int $user_id
* @author 段誉(2021/6/23 7:17)
* @return string
*/
public static function send($mobile, $scene, $user_id = 0)
{
try {
$code = create_sms_code(4);
$send_data = [
'scene' => NoticeEnum::SMS_SCENE[$scene],
'mobile' => $mobile,
'params' => ['code' => $code]
];
if (!empty($user_id)) {
$send_data['user_id'] = $user_id;
}
$res = event('Notice', $send_data);
if (false === $res) {
throw new \Exception('发送失败');
}
return true;
} catch (\Exception $e) {
return $e->getMessage();
}
}
/**
* Notes: 验证短信验证码是否正确
* @param $message_key
* @param $mobile
* @param int $code
* @author 段誉(2021/6/23 2:53)
* @return bool
* @remark 有效时间,检测次数内短信验证码是否正确
*/
public static function check($message_key, $mobile, $code = 0)
{
$log = SmsLog::where([
'mobile' => $mobile,
'message_key' => $message_key,
'is_verify' => 0
])->order('id desc')->find();
if (empty($log)) {
self::$error = '验证码错误';
return false;
}
$diff_time = time() - ($log->getData('create_time'));
if ($diff_time < self::$expire_time && $log['check_num'] <= self::$check_num) {
$check_num = $log['check_num'] + 1;
if ($log['code'] == $code) {
SmsLog::where(['id' => $log['id']])->update([
'is_verify' => 1,
'check_num' => $check_num,
'update_time' => time()
]);
return true;
}
SmsLog::where(['id' => $log['id']])->update([
'check_num' => $check_num,
'update_time' => time()
]);
self::$error = '验证码错误!';
return false;
}
self::$error = '验证码错误或失败次数过多';
return false;
}
}

View File

@ -0,0 +1,144 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\common\logic;
use app\common\basics\Logic;
use app\common\enum\NoticeEnum;
use app\common\model\Notice;
use app\common\server\ConfigServer;
use app\common\server\UrlServer;
/**
* 系统通知
* Class NoticeLogic
* @package app\api\logic
*/
class SystemNoticeLogic extends Logic
{
/**
* Notes: 消息主页
* @param $user_id
* @author 段誉(2021/6/22 1:18)
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function index($user_id)
{
//最新系统消息
$server = Notice::where([
['user_id', '=', $user_id],
['send_type', '=', NoticeEnum::SYSTEM_NOTICE],
['scene', 'not in', [NoticeEnum::GET_EARNINGS_NOTICE, NoticeEnum::GET_FUTURE_EARNINGS_NOTICE]],
])->order('id desc')->find();
//最新收益通知
$earning = Notice::where([
['user_id', '=', $user_id],
['send_type', '=', NoticeEnum::SYSTEM_NOTICE],
['scene', 'in', [NoticeEnum::GET_EARNINGS_NOTICE, NoticeEnum::GET_FUTURE_EARNINGS_NOTICE]],
])->order('id desc')->find();
$data['system'] = [
'title' => '系统通知',
'content' => $server['content'] ?? '暂无系统消息',
'img' => UrlServer::getFileUrl(ConfigServer::get('website', 'system_notice')),
'type' => 'system',
];
$data['earning'] = [
'title' => '收益通知',
'content' => $earning['content'] ?? '暂无收益消息',
'img' => UrlServer::getFileUrl(ConfigServer::get('website', 'earning_notice')),
'type' => 'earning',
];
$res = array_values($data);
return $res;
}
/**
* Notes: 消息列表
* @param $user_id
* @param $type
* @param $page
* @param $size
* @author 段誉(2021/6/22 1:18)
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function lists($user_id, $type, $page, $size)
{
$where = [];
$where[] = ['user_id', '=', $user_id];
$where[] = ['send_type', '=', NoticeEnum::SYSTEM_NOTICE];
if ($type == 'earning') {
$where[] = ['scene', 'in', [NoticeEnum::GET_EARNINGS_NOTICE, NoticeEnum::GET_FUTURE_EARNINGS_NOTICE]];
} else {
$where[] = ['scene', 'not in', [NoticeEnum::GET_EARNINGS_NOTICE, NoticeEnum::GET_FUTURE_EARNINGS_NOTICE]];
}
$count = Notice::where($where)->count();
$lists = Notice::where($where)
->order('id desc')
->page($page, $size)
->select();
//更新为已读
Notice::where($where)
->where('read', '<>', 1)
->update(['read' => 1]);
return [
'list' => $lists,
'page' => $page,
'size' => $size,
'count' => $count,
'more' => is_more($count, $page, $size)
];
}
/**
* Notes: 是否有未读的消息
* @param $user_id
* @author 段誉(2021/6/22 1:17)
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function unRead($user_id)
{
$un_read = Notice::where([
'user_id' => $user_id,
'read' => 0,
'send_type' => NoticeEnum::SYSTEM_NOTICE
])->find();
if ($un_read) {
return true;
}
return false;
}
}