541 lines
22 KiB
PHP
541 lines
22 KiB
PHP
<?php
|
||
|
||
namespace app\api\logic;
|
||
|
||
use app\common\logic\BaseLogic;
|
||
use app\common\logic\RefundLogic;
|
||
use app\common\model\order\Order;
|
||
use app\common\model\order\OrderAll;
|
||
use app\common\model\order\OrderGroup;
|
||
use app\common\model\order\OrderStore;
|
||
use app\common\model\order\OrderStoreRenew;
|
||
use app\common\model\pay\Pay;
|
||
use app\common\model\refund\RefundRecord;
|
||
use app\common\model\store\Store;
|
||
use app\common\model\store\StoreUserAccountLog;
|
||
use app\common\model\teastore\TeaStore;
|
||
use app\common\model\teastore\TeaStoreGroup;
|
||
use app\common\model\teastore\TeaStoreRoom;
|
||
use app\common\model\user\User;
|
||
use app\common\model\user\UserAccountLog;
|
||
use app\common\model\user\UserCoupon;
|
||
use app\common\model\user\UserGroup;
|
||
use app\common\model\user\UserStoreMoney;
|
||
use app\common\service\FileService;
|
||
use app\common\service\pay\WeChatPayService;
|
||
use think\facade\{Db, Config};
|
||
class PayLogic extends BaseLogic
|
||
{
|
||
// public static function yuePay($data,$user_id){
|
||
// $result = Pay::where("id",$data['id'])->find();
|
||
// $user = User::where("id",$user_id)->find();
|
||
// if($user['user_money'] < $result['order_amount']){
|
||
// throw new \Exception('余额不足');
|
||
// }
|
||
// $user->dec('user_money', $result['order_amount']);
|
||
// $user->save();
|
||
// $order_data['order_status'] = 1;
|
||
// $order_data['pay_status'] = 1;
|
||
// $order_data['update_dtime'] = date("Y-m-d H:i:s");
|
||
// Order::where("id",$result['order_id'])->update($order_data);
|
||
// $d['order_sn'] = createSn('pay','order_sn');
|
||
// $d['create_time'] = date("Y-m-d H:i:s");
|
||
// $d['pay_time'] = date("Y-m-d H:i:s");
|
||
// $result = Pay::where("id",$data['id'])->update($d);
|
||
// return $result;
|
||
// }
|
||
public static function yuePay($data, $user_id)
|
||
{
|
||
Db::startTrans();
|
||
try {
|
||
$payId = $data['id'];
|
||
$currentTime = date("Y-m-d H:i:s");
|
||
|
||
// 1. 查询支付记录(悲观锁)
|
||
$pay = Pay::where("id", $payId)->lock(true)->find();
|
||
if (!$pay) {
|
||
throw new \Exception('支付记录不存在');
|
||
}
|
||
|
||
// 支付记录状态检查
|
||
if ($pay['pay_status'] == 1) {
|
||
throw new \Exception('该支付记录已完成支付');
|
||
}
|
||
// 2. 查询关联订单
|
||
if($pay['order_type'] == 1){
|
||
$order = OrderStore::where("id", $pay['order_id'])->find();
|
||
}elseif($pay['order_type'] == 2){
|
||
$order = OrderGroup::where("id", $pay['order_id'])->find();
|
||
}elseif($pay['order_type'] == 7){
|
||
$order = OrderStoreRenew::where("id", $pay['order_id'])->find();
|
||
}
|
||
if (!$order) {
|
||
throw new \Exception('关联订单不存在');
|
||
}
|
||
// 3. 查询用户并检查余额(悲观锁)
|
||
$user = User::where("id", $user_id)->lock(true)->find();
|
||
if (!$user) {
|
||
throw new \Exception('用户不存在');
|
||
}
|
||
|
||
// 金额处理:保持数值类型用于计算,字符串类型用于显示
|
||
$amount = (float)$pay['order_amount'];
|
||
// 区分门店余额支付还是平台余额
|
||
if($data['pay_way'] == 3){
|
||
$user_store_money = UserStoreMoney::where("user_id",$user_id)->where("store_id",$data['store_id'])->find();
|
||
$userMoney = (float)$user_store_money['money'];
|
||
}else{
|
||
$userMoney = (float)$user['user_money'];
|
||
}
|
||
|
||
|
||
// 用于显示的格式化金额
|
||
$displayAmount = number_format($amount, 2);
|
||
$displayUserMoney = number_format($userMoney, 2);
|
||
|
||
if ($userMoney < $amount) {
|
||
throw new \Exception("余额不足,当前余额: {$displayUserMoney},需支付: {$displayAmount}");
|
||
}
|
||
|
||
// 4. 扣减用户余额(使用数值类型的 $amount)
|
||
// $userSave = User::where("id", $user_id)->setDec('user_money', $amount);
|
||
$newBalance = round($userMoney - $amount, 2);
|
||
if($data['pay_way'] == 3){
|
||
$userSave = UserStoreMoney::where("user_id", $user_id)->where("store_id",$data['store_id'])->update(['money' => $newBalance,"update_dtime"=>date("Y-m-d H:i:s")]);
|
||
}else{
|
||
$userSave = User::where("id", $user_id)->update(['user_money' => $newBalance,"update_time"=>time()]);
|
||
|
||
}
|
||
if (!$userSave) {
|
||
throw new \Exception('用户余额扣减失败');
|
||
}
|
||
$change_type = 0;
|
||
$sub_sn = 0;
|
||
// 5. 更新订单状态
|
||
if($pay['order_type'] == 1) {
|
||
$change_type = 1;
|
||
$type = 3;
|
||
// 修改优惠券使用状态
|
||
if($order['group_coupon_id']>=0){
|
||
UserGroup::where("id", $order['group_coupon_id'])->update(["status"=>1]);
|
||
}
|
||
if($order['user_coupon_id']>=0){
|
||
UserCoupon::where('id',$order['user_coupon_id'])->update(["status"=>1]);
|
||
}
|
||
|
||
$amount = $order['order_amount'];
|
||
$orderUpdate = OrderStore::where("id", $pay['order_id'])->update([
|
||
'order_status' => 1,
|
||
'pay_status' => 1,
|
||
'update_dtime' => $currentTime
|
||
]);
|
||
if(isset($order['room_id'])){
|
||
if($order['room_id']!=0&&$order['room_id']!=""&&$order['room_id']!=null){
|
||
TeaStoreRoom::where('id', $order['room_id'])->inc('sold', 1)->update();
|
||
}
|
||
}
|
||
|
||
if (!$orderUpdate) {
|
||
throw new \Exception('订单状态更新失败');
|
||
}
|
||
}elseif($pay['order_type'] == 2){
|
||
$change_type = 4;
|
||
$type = 6;
|
||
$orderUpdate = OrderGroup::where("id", $pay['order_id'])->update([
|
||
'order_status' => 1,
|
||
'pay_status' => 1,
|
||
'update_dtime' => $currentTime
|
||
]);
|
||
if (!$orderUpdate) {
|
||
throw new \Exception('订单状态更新失败');
|
||
}
|
||
$qr_sn = createSn("user_group","qr_sn");
|
||
$qr_url = CommonLogic::qrcode($qr_sn);
|
||
$group = TeaStoreGroup::where('id', $order['group_id'])->find();
|
||
UserGroup::create([
|
||
"user_id"=>$user_id,
|
||
"group_id"=>$order['group_id'],
|
||
"qr_sn"=>$qr_sn,
|
||
"qr_url"=>$qr_url['file_url'],
|
||
"type"=>$group['type'],
|
||
"order_id"=>$order['id'],
|
||
"store_id"=>$order['store_id'],
|
||
"dtime"=>date("Y-m-d H:i:s")
|
||
]);
|
||
if(isset($order['group_id'])){
|
||
if($order['group_id']!=0&&$order['group_id']!=""&&$order['group_id']!=null){
|
||
TeaStoreGroup::where('id', $order['group_id'])->inc('sold', 1)->update();
|
||
}
|
||
}
|
||
}elseif($pay['order_type'] == 7){
|
||
$renew_order = OrderStoreRenew::where('id',$pay['order_id'])->find();
|
||
if(!$renew_order){
|
||
throw new \Exception('付款失败,订单不存在');
|
||
}
|
||
$source_id = $renew_order->source_id;
|
||
$store_order = OrderStore::where('id',$source_id)->find();
|
||
if(!$store_order){
|
||
throw new \Exception('包间订单错误,订单不存在');
|
||
}
|
||
$renew_timeslot = explode(',', $renew_order->timeslot);
|
||
$store_timeslot = explode(',', $store_order->timeslot);
|
||
$timeList = array_merge($store_timeslot, $renew_timeslot);
|
||
$end = end($timeList);
|
||
|
||
$renew_price = $renew_order->price;
|
||
$renew_order->pay_status = 1;
|
||
$renew_order->pay_dtime = 1;
|
||
$renew_order->save();
|
||
|
||
$transfer_order = OrderStore::where('transfer_order_id',$store_order['id'])->select();
|
||
$ids = explode(',',$store_order->id);
|
||
if($transfer_order->count() > 0){
|
||
$orderIds = $transfer_order->column('id');
|
||
$ids = array_merge($ids,$orderIds);
|
||
}
|
||
OrderStore::whereIn("id",$ids)->update([
|
||
"end_time"=>$end,
|
||
'timeslot'=>implode(',', $timeList),
|
||
'renew_dtime'=>implode(',', $timeList),
|
||
'is_renewal'=>1,
|
||
'renew_price'=>$renew_order->price+$store_order->renew_price,
|
||
'renew_hour'=>$renew_order->hour + $store_order->renew_hour,
|
||
'store_income_price'=>$store_order->store_income_price+$renew_price
|
||
|
||
]);
|
||
$change_type = 2;
|
||
$type = 7;
|
||
$sub_sn =$renew_order->order_sn;
|
||
$order['order_sn'] =$store_order->order_sn;
|
||
$order['store_id'] =$store_order->store_id;
|
||
$order['room_id'] =$store_order->room_id;
|
||
$amount = $renew_order->price;
|
||
|
||
}
|
||
OrderAll::where("source_sn", $order['order_sn'])->where("type", $type)->update([
|
||
'order_status' => 1,
|
||
'pay_status' => 1,
|
||
'pay_way'=>$order['pay_way'],
|
||
'update_time' => time()
|
||
]);
|
||
|
||
|
||
// 6. 更新支付记录
|
||
$payUpdate = Pay::where("id", $payId)->update([
|
||
'order_sn' => createSn('pay', 'order_sn'),
|
||
'pay_status' => 1,
|
||
'pay_time' => $currentTime
|
||
]);
|
||
if (!$payUpdate) {
|
||
throw new \Exception('支付记录更新失败');
|
||
}
|
||
|
||
// 7. 记录资金流水(使用数值类型的金额)
|
||
$moneyLog = self::addUserAccountLog(
|
||
$user_id,
|
||
$change_type,
|
||
$amount,
|
||
$userMoney,
|
||
$newBalance,
|
||
$order
|
||
);
|
||
$change_object = 1;
|
||
if($data['pay_way'] == 3){
|
||
$amount = 0;
|
||
$change_object = 3;
|
||
|
||
}
|
||
if($pay['order_type'] != 2){
|
||
// 记录店家资金流水(使用数值类型的金额)
|
||
self::addStoreUserAccountLog(
|
||
$data['pay_way'],
|
||
$pay['order_type'],
|
||
$user_id,
|
||
$change_object,
|
||
$change_type,
|
||
$amount,
|
||
$order,
|
||
$sub_sn
|
||
);
|
||
|
||
}
|
||
|
||
// 8. 记录支付日志
|
||
self::addPayLog($payId, $user_id, $amount, 'success');
|
||
|
||
Db::commit();
|
||
|
||
// 9. 支付成功后的后续操作(可异步处理)
|
||
self::afterPaySuccess($pay['order_id'], $user_id);
|
||
|
||
return [
|
||
'success' => true,
|
||
'pay_id' => $payId,
|
||
'order_id' => $pay['order_id'],
|
||
'order_sn' => $order['order_sn'],
|
||
'amount' => $displayAmount, // 返回格式化后的金额用于显示
|
||
'balance' => number_format($userMoney - $amount, 2) // 格式化余额
|
||
];
|
||
|
||
} catch (\Exception $e) {
|
||
Db::rollback();
|
||
// 记录支付失败日志
|
||
if (isset($payId)) {
|
||
self::addPayLog($payId, $user_id, $amount ?? 0, 'fail', $e->getMessage());
|
||
}
|
||
self::$error = $e->getMessage();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
private static function addUserAccountLog($user_id,$change_type, $amount,$userMoney, $newBalance,$order)
|
||
{
|
||
return Db::name('user_account_log')->insert([
|
||
'sn'=>createSn("user_account_log","sn"),
|
||
'user_id' => $user_id,
|
||
'change_object'=>1,
|
||
'change_type'=>$change_type,
|
||
'action'=>2,
|
||
'amount' => $amount,
|
||
'before_amount'=>$userMoney,
|
||
'after_amount' => $newBalance,
|
||
'source_sn' => $order['order_sn'],
|
||
'store_id'=>$order['store_id'],
|
||
'create_time' => time()
|
||
]);
|
||
}
|
||
private static function addStoreUserAccountLog($pay_way,$order_type,$user_id,$change_object,$change_type, $amount,$order,$sub_sn)
|
||
{
|
||
|
||
|
||
$tea_store = TeaStore::where("id",$order['store_id'])->find();
|
||
// if($amount != 0){
|
||
StoreUserAccountLog::create([
|
||
'sn'=>createSn("store_user_account_log","sn"),
|
||
'change_object'=>$change_object,
|
||
'change_type'=>$change_type,
|
||
'user_id'=>$user_id,
|
||
'action'=>1,
|
||
'amount' => $amount,
|
||
'before_amount'=>$tea_store['balance'],
|
||
'after_amount' => round($amount+$tea_store['balance'],2),
|
||
'source_sn' => $order['order_sn'],
|
||
'store_id'=>$order['store_id'],
|
||
'sub_sn'=>$sub_sn,
|
||
'room_id'=>$order['room_id'],
|
||
'create_time' => time()
|
||
]);
|
||
|
||
// if($order_type == 7 ){
|
||
// TeaStore::where('id', $order['store_id'])->inc('total_amount', $amount)->update();
|
||
// TeaStore::where('id', $order['store_id'])->inc('balance', $amount)->update();
|
||
// }
|
||
if($pay_way != 3){
|
||
TeaStore::where('id', $order['store_id'])->inc('total_amount',$amount)->update();
|
||
TeaStore::where('id', $order['store_id'])->inc('balance', $amount)->update();
|
||
}
|
||
// }
|
||
|
||
|
||
if($order['group_coupon_id'] != 0&&$order_type == 1){
|
||
$group = UserGroup::where("id",$order['group_coupon_id'])->find();
|
||
$store_group = TeaStoreGroup::where("id",$group['group_id'])->find();
|
||
$change_object = 4;
|
||
|
||
if($group['type'] == 2){
|
||
$store_group['discount_price'] = 0;
|
||
$change_object = 5;
|
||
$amount = 0;
|
||
}
|
||
|
||
StoreUserAccountLog::create([
|
||
'sn'=>createSn("store_user_account_log","sn"),
|
||
'change_object'=>$change_object,
|
||
'change_type'=>1,
|
||
'user_id'=>$user_id,
|
||
'action'=>1,
|
||
'amount' => $store_group['discount_price'],
|
||
'before_amount'=>round($tea_store['balance']+$amount,2),
|
||
'after_amount' => round($tea_store['balance']+$amount+$store_group['discount_price'],2),
|
||
'source_sn' => $order['order_sn'],
|
||
'store_id'=>$order['store_id'],
|
||
'room_id'=>$order['room_id'],
|
||
'remark'=>"团购套餐",
|
||
'create_time' => time()
|
||
]);
|
||
TeaStore::where('id', $order['store_id'])->inc('total_amount', $store_group['discount_price'])->update();
|
||
TeaStore::where('id', $order['store_id'])->inc('balance', $store_group['discount_price'])->update();
|
||
}
|
||
return true;
|
||
}
|
||
/**
|
||
* 记录支付日志
|
||
*/
|
||
private static function addPayLog($pay_id, $user_id, $amount, $status, $message = '')
|
||
{
|
||
return Db::name('pay_log')->insert([
|
||
'pay_id' => $pay_id,
|
||
'user_id' => $user_id,
|
||
'amount' => $amount,
|
||
'status' => $status,
|
||
'message' => $message,
|
||
'create_time' => time()
|
||
]);
|
||
}
|
||
|
||
// 退款
|
||
public static function refund($data, $user_id){
|
||
$refund_msg = RefundRecord::where("id",$data['id'])->find();
|
||
$remark = "";
|
||
$change_type = 0;
|
||
// 判断是否为微信支付
|
||
// 0为茶艺师 1为茶室支付 2购买套餐 3购买会员 4充值 5团购退款 6茶室退款
|
||
|
||
if($refund_msg['order_type'] == 5){
|
||
$order = OrderGroup::where("order_sn",$refund_msg['source_sn'])->find();
|
||
$remark = "团购套餐退款";
|
||
$order_amount = $order['order_amount'];
|
||
}elseif($refund_msg['order_type'] == 1){
|
||
$order = OrderStore::where("order_sn",$refund_msg['source_sn'])->find();
|
||
$remark = "包间预定退款";
|
||
$order_amount = $order['store_income_price'];
|
||
$change_type = 1;
|
||
}
|
||
if(isset($order)){
|
||
// 微信支付
|
||
if($order['pay_way'] == 2){
|
||
if($order['order_amount'] <= 0){
|
||
//查询是否使用优惠券
|
||
if($order['user_coupon_id'] != 0){
|
||
$r = UserCoupon::where("id",$order['user_coupon_id'])->update(['status'=>0]);
|
||
}
|
||
//查询是否使用团购券
|
||
if($order['group_coupon_id'] != 0){
|
||
$r = UserGroup::where("id",$order['user_coupon_id'])->update(['status'=>0]);
|
||
}
|
||
if(!isset($r)){
|
||
throw new \Exception('退款失败100001');
|
||
}
|
||
}else{
|
||
if($refund_msg['order_type'] == 5){
|
||
UserGroup::where('order_id',$order['id'])->update(['status'=>4]);
|
||
}
|
||
$refundData = [
|
||
'transaction_id'=>$order->transaction_id,
|
||
'refund_sn'=>$refund_msg->order_sn,
|
||
'total_amount'=>$order->order_amount,
|
||
'notify_url'=>FileService::getFileUrl('api/pay/notifyMnp'),
|
||
];
|
||
$payService = (new WeChatPayService(1, $user_id ?? null));
|
||
$result = $payService->refund($refundData);
|
||
if($result['status'] !=='PROCESSING'){
|
||
throw new \Exception('押金退款失败请联系客服');
|
||
}
|
||
return true;
|
||
}
|
||
}else{
|
||
|
||
// 余额退款
|
||
RefundRecord::where("id",$data['id'])->update(['refund_way'=>3,'refund_status'=>1]);
|
||
// 更新总表状态
|
||
OrderAll::where("source_sn",$refund_msg['order_sn'])->where("type",$refund_msg['order_type'])->update([
|
||
"pay_way"=>$order['pay_way'],
|
||
"order_status"=>5,
|
||
"pay_status"=>1,
|
||
"pay_time"=>time(),
|
||
"update_time"=>time()
|
||
]);
|
||
$user = User::where("id",$user_id)->find();
|
||
$money = 0;
|
||
$user_money = 0;
|
||
if($order['pay_way'] == 1){
|
||
// 平台余额
|
||
$money = $user['user_money'];
|
||
$user_money = round($user['user_money']+$refund_msg['refund_amount'],2);
|
||
User::where("id",$user_id)->update(['user_money'=>$user_money]);
|
||
}else{
|
||
// 门店余额
|
||
$user_store_money = UserStoreMoney::where("user_id",$user_id)->where("store_id",$order['store_id'])->find();
|
||
$money = $user_store_money['money'];
|
||
$user_money = round($user_store_money['money']+$refund_msg['refund_amount'],2);
|
||
UserStoreMoney::where("user_id",$user_id)->where("store_id",$order['store_id'])->update(['money'=>$user_money]);
|
||
}
|
||
|
||
// 更新用户流水
|
||
UserAccountLog::create([
|
||
"sn"=>createSn("user_account_log","sn"),
|
||
"user_id"=>$user_id,
|
||
"change_object"=>1,
|
||
"change_type"=>5,
|
||
"action"=>1,
|
||
"amount"=>$refund_msg['refund_amount'],
|
||
"before_amount"=>$money,
|
||
"after_amount"=>$user_money,
|
||
"source_sn"=>$refund_msg['order_sn'],
|
||
"store_id"=>$refund_msg['store_id'],
|
||
"remark"=>$remark,
|
||
"create_time"=>time()
|
||
]);
|
||
|
||
}
|
||
// 修改订单状态
|
||
if($refund_msg['order_type'] == 5){
|
||
$rs = OrderGroup::where("order_sn",$refund_msg['source_sn'])->update(['order_status'=>5]);
|
||
UserGroup::where("id",$refund_msg['content_id'])->update(['status'=>3]);
|
||
}elseif($refund_msg['order_type'] == 1){
|
||
$rs = OrderStore::where("order_sn",$refund_msg['source_sn'])->update(['order_status'=>5]);
|
||
}
|
||
if(isset($rs)){
|
||
if(!$rs){
|
||
throw new \Exception('退款失败100002');
|
||
}
|
||
}else{
|
||
throw new \Exception('退款失败100003');
|
||
}
|
||
// if($refund_msg['order_type'] == 5){
|
||
// // 扣除店家余额
|
||
// $tes_store = TeaStore::where('id', $order['store_id'])->find();
|
||
// $total_amount = round($tes_store['total_amount'] - $order_amount,2);
|
||
// $balance = round($tes_store['balance'] - $order_amount,2);
|
||
// TeaStore::where('id', $order['store_id'])->update(['total_amount'=>$total_amount,'balance'=>$balance]);
|
||
// // 添加店家流水
|
||
// StoreUserAccountLog::create([
|
||
// 'order_sn'=>createSn("store_user_account_log","order_sn"),
|
||
// 'change_object'=>1,
|
||
// 'change_type'=>$change_type,
|
||
// 'action'=>2,
|
||
// 'amount' => $order_amount,
|
||
// 'before_amount'=>$tes_store['balance'],
|
||
// 'after_amount' => $balance,
|
||
// 'source_sn' => $order['order_sn'],
|
||
// 'store_id'=>$order['store_id'],
|
||
// 'room_id'=>$order['room_id'],
|
||
// 'remark'=>$remark,
|
||
// 'create_time' => time()
|
||
// ]);
|
||
// }
|
||
|
||
return true;
|
||
}else{
|
||
throw new \Exception('暂无订单信息');
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/**
|
||
* 支付成功后置操作
|
||
*/
|
||
private static function afterPaySuccess($order_id, $user_id)
|
||
{
|
||
// 可以在这里处理:
|
||
// 1. 发送通知
|
||
// 2. 更新库存
|
||
// 3. 记录日志
|
||
// 4. 触发其他业务逻辑
|
||
|
||
// 示例:发送支付成功通知
|
||
// NoticeService::sendPaySuccessNotice($user_id, $order_id);
|
||
}
|
||
|
||
} |