// +---------------------------------------------------------------------- namespace App\Services; use App\Models\DynamicNoticeModel; use App\Models\GongdengOrderModel; use App\Models\MemberModel; use App\Models\OrdersModel; use App\Models\RechargeModel; use App\Models\SignsModel; use App\Models\TradeModel; use Illuminate\Support\Facades\DB; use Psr\Http\Message\MessageInterface; /** * 支付回调管理-服务类 * @author wesmiler * @since 2020/11/11 * Class NotifyService * @package App\Services */ class NotifyService extends BaseService { protected static $instance = null; /** * 构造函数 * @author wesmiler * @since 2020/11/11 * NotifyService constructor. */ public function __construct() { $this->model = new GongdengOrderModel(); $this->rechargeModel = new RechargeModel(); $this->orderModel = new OrdersModel(); } /** * 静态入口 * @return NotifyService|null */ public static function make(){ if(!self::$instance){ self::$instance = new NotifyService(); } return self::$instance; } /** * 供灯订单回调处理 * @param $notifyData * @param $outTradeNo * @return false */ public function notifyGongdeng($notifyData, $outTradeNo){ $errorKey = "caches:orders:gongdeng:{$outTradeNo}"; // 验证订单是否存在 $orderInfo = $this->model::where(['order_sn'=> $outTradeNo]) ->select(['id','source_id','buy_type','user_id','sf_name','qf_content','num','total','status']) ->first(); // 验证参数 RedisService::set($errorKey.':order',['order'=> $orderInfo,'notify'=> $notifyData], 3600); $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : 0; $userId = isset($orderInfo['user_id']) ? intval($orderInfo['user_id']) : 0; if (empty($orderInfo) || $userId<=0) { return NotifyService::rebackMsg('订单数据不存在', 'success'); } // 订单用户 $memberInfo = MemberModel::where(['id'=> $userId])->select(['id','openid','nickname','balance','coupon','merits_num','status'])->first(); if(!$memberInfo){ return NotifyService::rebackMsg('订单用户不存在', 'success'); } // 验证订单状态是否可处理 if ($orderStatus != 1) { return NotifyService::rebackMsg('订单已处理', 'success'); } // 验证订单金额是否正确 $payDebug = config('weixin.payDebug'); $amount = isset($notifyData['amount'])? $notifyData['amount'] : []; $payMoney = isset($amount['total']) ? moneyFormat($amount['total']) : 0; $orderMoney = isset($orderInfo['total']) ? moneyFormat($orderInfo['total']) : 0.00; $orderAmount = moneyFormat($orderMoney); if (!$payDebug && intval($orderAmount * 100) != intval($payMoney)) { RedisService::set($errorKey.':error_money',['notify'=> $notifyData, 'error'=> '实付金额与订单金额不一致','order'=> $orderInfo ], 3600); return NotifyService::rebackMsg('实付金额与订单金额不一致', 'error'); } // 更新订单数据 DB::beginTransaction(); $tradeNo = isset($notifyData['transaction_id'])? $notifyData['transaction_id'] : ''; if(!$this->model::where(['order_sn'=> $outTradeNo])->update(['status'=> 2,'trade_no'=> $tradeNo,'pay_at'=> date('Y-m-d H:i:s'),'pay_money'=> moneyFormat($payMoney/100),'remark'=> '已支付'])){ RedisService::set($errorKey.':error_update',['notify'=> $notifyData, 'error'=> '更新订单信息失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('更新订单数据失败', 'error'); } // 处理支付明细 $data = [ 'user_id'=> $userId, 'type'=> 1, 'coin_type'=> 2, 'pay_type'=> 2, 'money'=> moneyFormat($payMoney/100), 'change_type'=> 2, 'balance'=> $memberInfo->balance? $memberInfo->balance : 0, 'create_time'=> time(), 'remark'=> '供灯订单支付', 'status'=> 1 ]; if(!TradeModel::insertGetId($data)){ RedisService::set($errorKey.':error_account',['notify'=> $notifyData, 'error'=> '处理交易明细失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('处理交易明细失败', 'error'); } // 项目完成 $giveGd = ConfigService::make()->getConfigByCode('gongdeng_give_gd'); $giveGd = $giveGd? $giveGd : 0; if($giveGd>0){ if(!MemberModel::where(['id'=> $userId])->increment('merits_num', $giveGd)){ DB::rollBack(); return NotifyService::rebackMsg('奖励功德失败', 'error'); } $data = [ 'user_id'=> $userId, 'type'=> 3, 'coin_type'=> 4, 'pay_type'=> 4, 'money'=> $giveGd, 'change_type'=> 1, 'balance'=> $memberInfo->merits_num? $memberInfo->merits_num : 0, 'create_time'=> time(), 'remark'=> '供灯奖励', 'status'=> 1 ]; if(!TradeModel::insertGetId($data)){ RedisService::set($errorKey.':error_gd',['notify'=> $notifyData, 'error'=> '功德奖励交易明细失败','data'=> $data ], 3600); DB::rollBack(); return NotifyService::rebackMsg('功德奖励处理失败', 'error'); } // 完成供灯项目 PracticesService::make()->saveLog($userId, 4,'供灯祈福'); } DB::commit(); // 记录 $data = [ 'user_id'=> $userId, 'remark'=> "供灯祈福,福报绵延。", 'create_time'=> time(), 'update_time'=> time(), 'status'=> 1, ]; RedisService::set("caches:dynamic:notice_{$userId}", $data, 300); DynamicNoticeModel::insertGetId($data); // 开灯处理,续费不处理 $buyType = isset($orderInfo['buy_type'])? $orderInfo['buy_type'] : 0; if($buyType == 1){ DevicesService::make()->catchLamp($outTradeNo, $orderInfo); } // 消息处理 return NotifyService::rebackMsg('支付处理成功','success'); } /** * 充值订单回调处理 * @param $notifyData * @param $outTradeNo * @return false */ public function notifyRecharge($notifyData, $outTradeNo){ $errorKey = "caches:orders:recharge:{$outTradeNo}"; // 验证订单是否存在 $orderInfo = $this->rechargeModel::where(['order_sn'=> $outTradeNo]) ->select(['id','type','user_id','num','money','status']) ->first(); // 验证参数 RedisService::set($errorKey.':order',['order'=> $orderInfo,'notify'=> $notifyData], 3600); $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : 0; $userId = isset($orderInfo['user_id']) ? intval($orderInfo['user_id']) : 0; if (empty($orderInfo) || $userId<=0) { return NotifyService::rebackMsg('订单数据不存在', 'success'); } // 订单用户 $memberInfo = MemberModel::where(['id'=> $userId])->select(['id','openid','nickname','balance','coupon','status'])->first(); if(!$memberInfo){ return NotifyService::rebackMsg('订单用户不存在', 'success'); } // 验证订单状态是否可处理 if ($orderStatus != 2) { return NotifyService::rebackMsg('订单已处理', 'success'); } // 验证订单金额是否正确 $payDebug = config('weixin.payDebug'); $amount = isset($notifyData['amount'])? $notifyData['amount'] : []; $payMoney = isset($amount['total']) ? moneyFormat($amount['total']) : 0; $orderMoney = isset($orderInfo['money']) ? moneyFormat($orderInfo['money']) : 0.00; $orderAmount = moneyFormat($orderMoney); if (!$payDebug && intval($orderAmount * 100) != intval($payMoney)) { RedisService::set($errorKey.':error_money',['notify'=> $notifyData, 'error'=> '实付金额与订单金额不一致','order'=> $orderInfo ], 3600); return NotifyService::rebackMsg('实付金额与订单金额不一致', 'error'); } // 更新订单数据 DB::beginTransaction(); $tradeNo = isset($notifyData['transaction_id'])? $notifyData['transaction_id'] : ''; if(!$this->rechargeModel::where(['order_sn'=> $outTradeNo])->update(['status'=> 1,'trade_no'=> $tradeNo,'pay_at'=> date('Y-m-d H:i:s'),'pay_money'=> moneyFormat($payMoney/100),'remark'=> '已支付'])){ RedisService::set($errorKey.':error_update',['notify'=> $notifyData, 'error'=> '更新订单信息失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('更新订单数据失败', 'error'); } $num = isset($orderInfo['num'])? intval($orderInfo['num']) : 0; if($num && !MemberModel::where(['id'=> $userId])->increment('coupon',$num)){ RedisService::set($errorKey.':error_coupon',['notify'=> $notifyData, 'error'=> '更新账户数据失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('更新账户数据失败', 'error'); } // 处理支付明细 $data = [ 'user_id'=> $userId, 'type'=> 2, 'coin_type'=> 2, 'pay_type'=> 2, 'money'=> moneyFormat($payMoney/100), 'change_type'=> 2, 'balance'=> 0, 'create_time'=> time(), 'remark'=> '充值订单支付', 'status'=> 1 ]; if(!TradeModel::insertGetId($data)){ RedisService::set($errorKey.':error_account',['notify'=> $notifyData, 'error'=> '处理交易明细失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('处理交易明细失败', 'error'); } if($num>0){ $data = [ 'user_id'=> $userId, 'type'=> 2, 'coin_type'=> 1, 'pay_type'=> 1, 'money'=> $num, 'change_type'=> 1, 'balance'=> $memberInfo->coupon? $memberInfo->coupon : 0, 'create_time'=> time(), 'remark'=> '充值花灯券到账', 'status'=> 1 ]; if(!TradeModel::insertGetId($data)){ RedisService::set($errorKey.':error_account',['notify'=> $notifyData, 'error'=> '处理交易明细失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('处理花灯券交易明细失败', 'error'); } } DB::commit(); return NotifyService::rebackMsg('支付处理成功','success'); } /** * 商城订单回调处理 * @param $notifyData * @param $outTradeNo * @return false */ public function notifyShop($notifyData, $outTradeNo){ $errorKey = "caches:orders:shop:{$outTradeNo}"; // 验证订单是否存在 $orderInfo = $this->orderModel::where(['order_sn'=> $outTradeNo]) ->select(['id','type','user_id','goods_id','order_sn','num','total','status']) ->first(); // 验证参数 RedisService::set($errorKey.':order',['order'=> $orderInfo,'notify'=> $notifyData], 3600); $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : 0; $userId = isset($orderInfo['user_id']) ? intval($orderInfo['user_id']) : 0; if (empty($orderInfo) || $userId<=0) { return NotifyService::rebackMsg('订单数据不存在', 'success'); } // 订单用户 $memberInfo = MemberModel::where(['id'=> $userId])->select(['id','openid','nickname','balance','coupon','status'])->first(); if(!$memberInfo){ return NotifyService::rebackMsg('订单用户不存在', 'success'); } // 验证订单状态是否可处理 if ($orderStatus != 1) { return NotifyService::rebackMsg('订单已处理', 'success'); } // 验证订单金额是否正确 $payDebug = config('weixin.payDebug'); $amount = isset($notifyData['amount'])? $notifyData['amount'] : []; $payMoney = isset($amount['total']) ? moneyFormat($amount['total']) : 0; $orderMoney = isset($orderInfo['total']) ? moneyFormat($orderInfo['total']) : 0.00; $orderAmount = moneyFormat($orderMoney); if (!$payDebug && intval($orderAmount * 100) != intval($payMoney)) { RedisService::set($errorKey.':error_money',['notify'=> $notifyData, 'error'=> '实付金额与订单金额不一致','order'=> $orderInfo ], 3600); return NotifyService::rebackMsg('实付金额与订单金额不一致', 'error'); } // 更新订单数据 DB::beginTransaction(); $tradeNo = isset($notifyData['transaction_id'])? $notifyData['transaction_id'] : ''; if(!$this->orderModel::where(['order_sn'=> $outTradeNo])->update(['status'=> 2,'trade_no'=> $tradeNo,'pay_at'=> date('Y-m-d H:i:s'),'pay_money'=> moneyFormat($payMoney/100),'remark'=> '已支付'])){ RedisService::set($errorKey.':error_update',['notify'=> $notifyData, 'error'=> '更新订单信息失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('更新订单数据失败', 'error'); } // 处理支付明细 $data = [ 'user_id'=> $userId, 'type'=> 1, 'coin_type'=> 2, 'pay_type'=> 2, 'money'=> moneyFormat($payMoney/100), 'change_type'=> 2, 'balance'=> 0, 'create_time'=> time(), 'remark'=> '商城订单支付', 'status'=> 1 ]; if(!TradeModel::insertGetId($data)){ RedisService::set($errorKey.':error_account',['notify'=> $notifyData, 'error'=> '处理交易明细失败','order'=> $orderInfo ], 3600); DB::rollBack(); return NotifyService::rebackMsg('处理交易明细失败', 'error'); } DB::commit(); return NotifyService::rebackMsg('支付处理成功','success'); } /** * 回去回调报文内容 * @param $message * @return string */ public static function getBody($message){ $body = ''; $bodyStream = $message->getBody(); if ($bodyStream->isSeekable()) { $body = (string)$bodyStream; $bodyStream->rewind(); } return $body; } /** * 返回成功 */ public static function rebackOk(){ echo ''; exit; } /** * V3支付回调应答 * @param $code * @param string $msg * @return false|string */ public static function rebackMsg($msg='失败', $code='error'){ return ['code'=> $code, 'message'=> $msg]; } }