jh-admin/addon/coupon/model/Coupon.php

709 lines
28 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* SaaSMall商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都SAAS云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.gobuysaas.com
* =========================================================
*/
namespace addon\coupon\model;
use addon\aliapp\model\CloudPay;
use addon\aliapp\model\MinCode;
use addon\coupon\model\alipay\AlistoreCouponType;
use app\model\BaseModel;
use app\model\system\Stat;
use think\Exception;
use think\facade\Log;
/**
* 优惠券
*/
class Coupon extends BaseModel
{
/**
* Common: 领取优惠券 —— 归属平台优惠券领取信息处理
* Author: wu-hui
* Time: 2023/07/10 11:34
* @param $params
* @return array
*/
public function newReceiveCoupon($params)
{
model('promotion_coupon')->startTrans();
try {
// 参数处理
$couponTypeId = (int)($params['coupon_type_id'] ?? 0);// 优惠券id
$getType = (int)($params['get_type'] ?? 2);//获取方式:1订单2.直接领取3.活动领取
$appType = (string)($params['app_type'] ?? '');// 卡卷归属平台weapp=微信aliapp=支付宝;为空则没有归属平台仅允许在本平台使用
// 根据平台进行对应的操作
$updateData = [];
switch ($appType) {
case "weapp":
// 微信端
$stockId = (int)($params['stock_id'] ?? 0);
$couponTypeId = (int)model('promotion_coupon_type')->getValue([
['weapp_stock_id', '=', $stockId]
], 'coupon_type_id', 0);
if ($couponTypeId <= 0) throw new Exception('优惠券不存在');
$updateData = [
'weapp_out_request_no' => $params['out_request_no'],
'weapp_stock_id' => $params['stock_id'],
'coupon_code' => $params['coupon_code']
];
break;
case "aliapp" :
break;
default:
break;
}
// 本平台领券操作
$result = $this->receiveCoupon($couponTypeId, $params['site_id'], $params['member_id'], $getType);
// 判断:是否操作修改信息 存在则进行修改操作
if ($result['code'] == 0 && $updateData) {
// 修改内容
model('promotion_coupon')->update($updateData, [
['coupon_id', '=', $result['data']]
]);
} else if ($result['code'] != 0) {
throw new Exception($result['message']);
}
model('promotion_coupon')->commit();
// 返回信息处理
$result['data'] = [
'id' => $result['data'],
'coupon_type_id' => $couponTypeId
];
return $result;
} catch (\Exception $e) {
model('promotion_coupon')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* Common: 领取优惠券 - 记录本平台优惠券领取信息
* @param $coupon_type_id
* @param $site_id
* @param $member_id
* @param $get_type
* @param int $is_stock
* @param int $is_limit
* @return array
* @throws \think\db\exception\DbException
*/
public function receiveCoupon($coupon_type_id, $site_id, $member_id, $get_type, $is_stock = 0, $is_limit = 1)
{
// 用户已领取数量
if (empty($member_id)) return $this->error('', '请先进行登录');
$coupon_type_info = model('promotion_coupon_type')->getInfo(['coupon_type_id' => $coupon_type_id, 'site_id' => $site_id]);
if (!empty($coupon_type_info)) {
if ($coupon_type_info['count'] != -1 || $is_stock == 0) {
if ($coupon_type_info['count'] == $coupon_type_info['lead_count']) {
return $this->error('', '来迟了该优惠券已被领取完了');
}
}
if ($coupon_type_info['max_fetch'] != 0 && $get_type == 2) {
//限制领取
$member_receive_num = model('promotion_coupon')->getCount([
'coupon_type_id' => $coupon_type_id,
'member_id' => $member_id,
'get_type' => 2
]);
if ($member_receive_num >= $coupon_type_info['max_fetch'] && $is_limit == 1) {
return $this->error('', '该优惠券领取已达到上限');
}
}
//只有正在进行中的优惠券可以添加或者发送领取)
if ($coupon_type_info['status'] != 1) return $this->error('', '该优惠券已过期');
$data = [
'coupon_type_id' => $coupon_type_id,
'site_id' => $site_id,
'coupon_code' => $this->getCode(),
'member_id' => $member_id,
'money' => $coupon_type_info['money'],
'state' => 1,
'get_type' => $get_type,
'goods_type' => $coupon_type_info['goods_type'],
'fetch_time' => time(),
'coupon_name' => $coupon_type_info['coupon_name'],
'at_least' => $coupon_type_info['at_least'],
'type' => $coupon_type_info['type'],
'discount' => $coupon_type_info['discount'],
'discount_limit' => $coupon_type_info['discount_limit'],
'goods_ids' => $coupon_type_info['goods_ids'],
];
if ($coupon_type_info['validity_type'] == 0) $data['end_time'] = $coupon_type_info['end_time'];
elseif ($coupon_type_info['validity_type'] == 1) $data['end_time'] = (time() + $coupon_type_info['fixed_term'] * 86400);
$res = model('promotion_coupon')->add($data);
if ($is_stock == 0) model('promotion_coupon_type')->setInc([['coupon_type_id', '=', $coupon_type_id]], 'lead_count');
$stat_model = new Stat();
$stat_model->switchStat([
'type' => 'receive_coupon',
'data' => [
'site_id' => $site_id,
'coupon_id' => $res
]
]);
return $this->success($res);
} else {
return $this->error('', '未查找到该优惠券');
}
}
/**
* 获取优惠券来源方式
* @param $type
*/
public function getCouponGetType($type = '')
{
$get_type = [
1 => '消费奖励',
2 => '直接领取',
3 => '会员升级奖励',
4 => '商家发放',
6 => '活动奖励'
];
$event = event('CouponGetType');
if (!empty($event)) {
foreach ($event as $k => $v) {
$get_type[array_keys($v)[0]] = array_values($v)[0];
}
}
if ($type) return $get_type[$type] ?? '';
else return $get_type;
}
/**
* 获取编码
*/
public function getCode()
{
return random_keys(8);
}
public function alipayPassInstanceAdd($site_id, $data)
{
// 获取支付宝支付参数(统一支付到平台账户)
$config_model = new \addon\aliapp\model\Config();
$config_info = $config_model->getAppConfig($site_id)['data'];
$ali = new CloudPay();
$params = [
"tpl_id" => $data['tpl_id'],
'tpl_params' => '{"activeTime":"' . $data['activeTime'] . '","expireTime":"' . $data['expireTime'] . '","url":"' . $data['url'] . '","serialNumber":"' . substr($this->uuid(), 0, 20) . '"}',//alipays://platformapi/startapp?appId=2021002103632101
'recognition_type' => '2',
'recognition_info' => '{"recognition_info":{"user_id":"' . $data['user_id'] . '","user_token":"' . $data['user_token'] . '"},"user_id":"' . $data['user_id'] . '","user_token":"' . $data['user_token'] . '"}'
];
// 发起请求
$result = (new MinCode($site_id))->requestApi('alipay.pass.instance.add', $params, []);
$result = $result['alipay_pass_instance_add_response'];
if ($result['code'] == 10000) {
return $this->success($result);
} else {
return $this->error('', $result['sub_msg']);
}
}
/**
* 更新卡券
* @param $site_id
* @param $data
* @return array
*/
public function alipayPassInstanceUpdate($site_id, $coupon_id, $status = 'USED')
{
// 获取支付宝支付参数(统一支付到平台账户)
$config_model = new \addon\aliapp\model\Config();
$config_info = $config_model->getAppConfig($site_id)['data'];
$field = 'm.ali_openid,c.alipay_serial_number';
$join = [
['member m', 'm.member_id = c.member_id', 'LEFT']
];
$data = model('promotion_coupon')->getInfo(['coupon_id' => $coupon_id], $field, 'c', $join);
$ali = new CloudPay();
$params = [
"user_id" => $data['ali_openid'],
"serial_number" => $data['alipay_serial_number'],
"channel_id" => model('uni_account')->getInfo([['site_id', '=', $site_id]], 'appid')['appid'],
"status" => $status,
];
// 发起请求
$result = (new MinCode($site_id))->requestApi('alipay.pass.instance.update', $params, []);
// Log::write('优惠券核销结果-优惠券-alipayPassInstanceUpdate' . json_encode($result, JSON_UNESCAPED_UNICODE));
$result = $result['alipay_pass_instance_update_response'];
if ($result['code'] == 10000) {
return $this->success($result);
} else {
return $this->error('', $result['sub_msg']);
}
}
/**
* 发放优惠券
* @param array $coupon_data [ ['coupon_type_id' => xx, 'num' => xx ] ]
* @param int $site_id
* @param int $member_id
* @param int $get_type
* @param int $related_id
*/
public function giveCoupon(array $coupon_data, int $site_id, int $member_id, $get_type = 4, $related_id = 0)
{
if (empty($member_id)) return $this->error('', '请先选择会员');
try {
$coupon_list = [];
foreach ($coupon_data as $item) {
$coupon_type_info = model('promotion_coupon_type')->getInfo(['coupon_type_id' => $item['coupon_type_id'], 'site_id' => $site_id, 'status' => 1]);
if (!empty($coupon_type_info)) {
$data = [
'coupon_type_id' => $item['coupon_type_id'],
'site_id' => $site_id,
'coupon_code' => $this->getCode(),
'member_id' => $member_id,
'money' => $coupon_type_info['money'],
'state' => 1,
'get_type' => $get_type,
'goods_type' => $coupon_type_info['goods_type'],
'fetch_time' => time(),
'coupon_name' => $coupon_type_info['coupon_name'],
'at_least' => $coupon_type_info['at_least'],
'type' => $coupon_type_info['type'],
'discount' => $coupon_type_info['discount'],
'discount_limit' => $coupon_type_info['discount_limit'],
'goods_ids' => $coupon_type_info['goods_ids'],
'related_id' => $related_id,
'end_time' => 0
];
if ($coupon_type_info['validity_type'] == 0) {
$data['end_time'] = $coupon_type_info['end_time'];
} elseif ($coupon_type_info['validity_type'] == 1) {
$data['end_time'] = (time() + $coupon_type_info['fixed_term'] * 86400);
}
for ($i = 0; $i < $item['num']; $i++) {
$data['coupon_code'] = $this->getCode();
array_push($coupon_list, $data);
}
model('promotion_coupon_type')->setInc([['coupon_type_id', '=', $item['coupon_type_id']]], 'lead_count', $item['num']);
}
}
if (empty($coupon_list)) return $this->error('', '没有可发放的优惠券');
$res = model('promotion_coupon')->addList($coupon_list);
return $this->success($res);
} catch (\Exception $e) {
return $this->error('', '发放失败');
}
}
/**
* Common: 使用优惠券
* Time: 2023/07/18 9:56
* @param $coupon_id
* @param $member_id
* @param $use_order_id
* @return array
*/
public function useCoupon($coupon_id, $member_id, $use_order_id)
{
model('promotion_coupon')->startTrans();
try {
// 获取优惠券信息
$couponInfo = model('promotion_coupon')->getInfo(['coupon_id' => $coupon_id]);
if (!$couponInfo) throw new Exception('无领券信息!');
$couponTypeInfo = model('promotion_coupon_type')->getInfo(['coupon_type_id' => $couponInfo['coupon_type_id']]);
if (!$couponTypeInfo) throw new Exception('优惠券不存在!');
// 根据归属平台 进行对应的操作 app_type=归属平台weapp=微信aliapp=支付宝
if ($couponTypeInfo['app_type'] == 'weapp') {
// 微信优惠券核销操作 weapp_channel=微信小程序优惠券类型store=商家券voucher=代金券
$couponWeChatModel = new CouponWeChat($couponInfo['site_id']);
if ($couponTypeInfo['weapp_channel'] == 'store') {
// 商家券使用
$orderNo = model('order')->getValue(['order_id' => $use_order_id], 'order_no');
$memberInfo = model('member')->getInfo(['member_id' => $member_id], 'weapp_openid,wx_openid');
$openId = $memberInfo['weapp_openid'] ?? $memberInfo['wx_openid'];
$couponWeChatModel->storeMemberUse($couponTypeInfo['weapp_stock_id'], $couponInfo['coupon_code'], $orderNo, $openId);
} else {
// 微信代金券使用:修改订单信息
$orderInfo = model('order')->getInfo(['order_id' => $use_order_id]);
if ($couponTypeInfo['type'] == 'reward') {
// 满减
$orderUpdateData = [
'coupon_id' => $coupon_id,
'coupon_money' => $couponTypeInfo['money'],
'order_money' => sprintf("%.2f", $orderInfo['goods_money'] - $couponTypeInfo['money']),
'pay_money' => sprintf("%.2f", $orderInfo['pay_money'] - $couponTypeInfo['money']),
];
model('order')->update($orderUpdateData, [['order_id', '=', $use_order_id]]);
} else if ($couponTypeInfo['type'] == 'discount') {
// 折扣
$deductionMoney = sprintf("%.2f", $orderInfo['goods_money'] - ($orderInfo['goods_money'] * ($couponTypeInfo['discount'] / 10)));// 优惠金额
$orderUpdateData = [
'coupon_id' => $coupon_id,
'coupon_money' => $deductionMoney,
'order_money' => sprintf("%.2f", $orderInfo['goods_money'] - $deductionMoney),
'pay_money' => sprintf("%.2f", $orderInfo['pay_money'] - $deductionMoney),
];
model('order')->update($orderUpdateData, [['order_id', '=', $use_order_id]]);
}
}
} else if ($couponTypeInfo['app_type'] == 'aliapp') {
// 支付宝优惠券核销操作
switch ($couponTypeInfo['channel']) {
case 'alicard':
$this->alipayPassInstanceUpdate($couponInfo['site_id'], $coupon_id);
break;
case 'alistore':
$orderInfo = model('order')->getInfo(['order_id' => $use_order_id]);
(new AlistoreCouponType())->alipayMarketingActivityOrdervoucherUse($couponInfo['site_id'], $couponTypeInfo['alipay_pass_template_id'], $couponInfo['alipay_serial_number'], 'ZHIFUBAO_TRADE_CHANNEL', $orderInfo['out_trade_no'], $orderInfo['goods_money']);
break;
case 'alipaydiscount':
break;
}
}
// 修改本平台优惠券信息
$result = model("promotion_coupon")->update([
'use_order_id' => $use_order_id,
'use_time' => time(),
'state' => 2
], [
['coupon_id', '=', $coupon_id],
['member_id', '=', $member_id],
['state', '=', 1]
]);
model('promotion_coupon')->commit();
return $this->success($result);
} catch (Exception $e) {
model('promotion_coupon')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 退还优惠券
* @param $coupon_id
* @param $member_id
*/
public function refundCoupon($coupon_id, $member_id)
{
//获取优惠券信息
$info = model("promotion_coupon")->getInfo([['coupon_id', '=', $coupon_id], ['member_id', '=', $member_id], ['state', '=', 2]]);
if (empty($info)) {
return $this->success();
}
$data = ['use_time' => 0, 'state' => 1];
//判断优惠券是否过期
if ($info['end_time'] <= time()) {
$data['state'] = 3;
}
$couponInfo = model('promotion_coupon')->getInfo(['coupon_id' => $coupon_id]);
$CouponTypeInfo = model('promotion_coupon_type')->getInfo(['coupon_type_id' => $couponInfo['coupon_type_id']]);
switch ($CouponTypeInfo['channel']) {
case 'alicard':
break;
case 'alistore':
(new AlistoreCouponType())->alipayMarketingActivityOrdervoucherRefund($couponInfo['site_id'],
$CouponTypeInfo['alipay_pass_template_id'],
$couponInfo['alipay_serial_number']
);
break;
case 'alipaydiscount':
break;
}
$result = model("promotion_coupon")->update($data, [['coupon_id', '=', $coupon_id], ['member_id', '=', $member_id], ['state', '=', 2]]);
return $this->success($result);
}
/**
* 获取优惠券信息
* @param $condition $coupon_code 优惠券编码
* @param $field
* @return array
*/
public function getCouponInfo($condition, $field)
{
$info = model("promotion_coupon")->getInfo($condition, $field);
return $this->success($info);
}
/**
* 获取优惠券数量
* @param $condition $coupon_code 优惠券编码
* @return array
*/
public function getCouponCount($condition)
{
$info = model("promotion_coupon")->getCount($condition);
return $this->success($info);
}
/**
* 获取优惠券列表
* @param array $condition
* @param bool $field
* @param string $order
* @param null $limit
* @return array
*/
public function getCouponList($condition = [], $field = true, $order = '', $limit = null)
{
$list = model("promotion_coupon")->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 获取优惠券列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @param string $alias
* @param array $join
* @return array
*/
public function getCouponPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'fetch_time desc', $field = 'coupon_id,type,discount,coupon_type_id,coupon_name,site_id,coupon_code,member_id,use_order_id,at_least,money,state,get_type,fetch_time,use_time,end_time', $alias = 'a', $join = [])
{
$list = model('promotion_coupon')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取会员优惠券列表
* @param $condition
* @param int $page
* @param int $page_size
* @return array
*/
public function getMemberCouponPageList($condition, $page = 1, $page_size = PAGE_LIST_ROWS)
{
$field = 'npc.coupon_name,npc.goods_type,npc.type,npc.use_order_id,npc.coupon_id,npc.coupon_type_id,npc.site_id,npc.coupon_code,npc.member_id,npc.discount_limit,
npc.at_least,npc.money,npc.discount,npc.state,npc.get_type,npc.fetch_time,npc.use_time,npc.start_time,npc.end_time,mem.nickname,on.order_no,mem.nickname,mem.headimg,mem.mobile';
$alias = 'npc';
$join = [
[
'member mem',
'npc.member_id = mem.member_id',
'inner'
],
[
'order on',
'npc.use_order_id = on.order_id',
'left'
]
];
$list = model("promotion_coupon")->pageList($condition, $field, 'fetch_time desc', $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取优惠券信息
* @param $condition
* @param string $field
* @return array
*/
public function getCouponTypeInfo($condition, $field = 'coupon_type_id,site_id,coupon_name,money,count,lead_count,max_fetch,at_least,end_time,image,validity_type,fixed_term,status,type,discount,alipay_pass_template_id,channel,app_type,weapp_channel,weapp_stock_id')
{
$info = model("promotion_coupon_type")->getInfo($condition, $field);
return $this->success($info);
}
/**
* 获取优惠券列表
* @param array $condition
* @param bool $field
* @param string $order
* @param null $limit
* @return array
*/
public function getCouponTypeList($condition = [], $field = true, $order = '', $limit = null, $alias = '', $join = [])
{
$list = model("promotion_coupon_type")->getList($condition, $field, $order, $alias, $join, '', $limit);
return $this->success($list);
}
/**
* 获取优惠券分页列表
* @param $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getCouponTypePageList($condition, $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'coupon_type_id desc', $field = '*', $alias = '', $join = [])
{
$list = model("promotion_coupon_type")->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取会员已领取优惠券优惠券
* @param $member_id
* @param $state
* @param int $site_id
* @param int $money
* @param string $order
* @return array
*/
public function getMemberCouponList($member_id, $state, $site_id = 0, $money = 0, $order = "fetch_time desc")
{
$condition = array(
["member_id", "=", $member_id],
["state", "=", $state],
// [ "end_time", ">", time()]
);
if ($site_id > 0) {
$condition[] = ["site_id", "=", $site_id];
}
if ($money > 0) {
// $condition[] = [ "at_least", "=", 0 ];
$condition[] = ["at_least", "<=", $money];
}
$list = model("promotion_coupon")->getList($condition, "*", $order, '', '', '', 0);
return $this->success($list);
}
public function getMemberCouponCount($condition)
{
$list = model("promotion_coupon")->getCount($condition);
return $this->success($list);
}
/**
* 增加库存
* @param $param
* @return array
*/
public function incStock($param)
{
$condition = array(
["coupon_type_id", "=", $param["coupon_type_id"]]
);
$num = $param["num"];
$coupon_info = model("promotion_coupon_type")->getInfo($condition, "count,lead_count");
if (empty($coupon_info))
return $this->error(-1, "");
//更新优惠券库存
$result = model("promotion_coupon_type")->setDec($condition, "lead_count", $num);
return $this->success($result);
}
/**
* 减少库存
* @param $param
* @return array
*/
public function decStock($param)
{
$condition = array(
["coupon_type_id", "=", $param["coupon_type_id"]]
);
$num = $param["num"];
$coupon_info = model("promotion_coupon_type")->getInfo($condition, "count,lead_count");
if (empty($coupon_info))
return $this->error(-1, "找不到优惠券");
//编辑sku库存
if ($coupon_info["count"] != -1) {
if (($coupon_info["count"] - $coupon_info["lead_count"]) < $num)
return $this->error(-1, "库存不足");
}
$result = model("promotion_coupon_type")->setInc($condition, "lead_count", $num);
if ($result === false)
return $this->error();
return $this->success($result);
}
/**
* 定时关闭
* @return mixed
*/
public function cronCouponEnd()
{
$couponList = model("promotion_coupon")->getList([['end_time', '>', 0], ['end_time', '<=', time()]]);
foreach ($couponList as $coupon) {
if ($coupon['alipay_serial_number']) {
$this->alipayPassInstanceUpdate($coupon['site_id'], $coupon['coupon_id'], 'CLOSED');
}
}
$res = model("promotion_coupon")->update(['state' => 3], [['state', '=', 1], ['end_time', '>', 0], ['end_time', '<=', time()]]);
return $res;
}
/**
* 核验会员是否还可以领用某一张优惠券
* @param $params
* @return array
*/
public function checkMemberReceiveCoupon($params)
{
$member_id = $params['member_id'];//会员id
$coupon_type_info = $params['coupon_type_info'];
$site_id = $params['site_id'];
$coupon_type_id = $params['coupon_type_id'] ?? 0;
if ($coupon_type_id > 0) {
$coupon_type_info = model('promotion_coupon_type')->getInfo(['coupon_type_id' => $coupon_type_id, 'site_id' => $site_id]);
}
if (!empty($coupon_type_info)) {
$coupon_type_id = $coupon_type_info['coupon_type_id'] ?? 0;
if ($coupon_type_info['count'] != -1) {
if ($coupon_type_info['count'] == $coupon_type_info['lead_count']) {
return $this->error('', '来迟了该优惠券已被领取完了');
}
}
if ($coupon_type_info['max_fetch'] != 0) {
//限制领取
$member_receive_num = model('promotion_coupon')->getCount([
'coupon_type_id' => $coupon_type_id,
'member_id' => $member_id,
'get_type' => 2
]);
if ($member_receive_num >= $coupon_type_info['max_fetch']) {
return $this->error('', '该优惠券领取已达到上限');
}
}
//只有正在进行中的优惠券可以添加或者发送领取)
if ($coupon_type_info['status'] != 1) {
return $this->error('', '该优惠券已过期');
}
}
return $this->success();
}
/**
* 生成UUID
*/
public function uuid()
{
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr($chars, 0, 8) . '-'
. substr($chars, 8, 4) . '-'
. substr($chars, 12, 4) . '-'
. substr($chars, 16, 4) . '-'
. substr($chars, 20, 12);
return $uuid;
}
}