You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

410 lines
16 KiB

<?php
namespace App\Controller;
use App\Constants\LogLabel;
use App\Model\Goods;
use App\Model\Order;
use App\Model\OrderGoods;
use App\Model\OrderMain;
use App\Model\OrderSalesStatistic;
use App\Model\SpecCombination;
use App\Model\Store;
use App\Model\StoreAccount;
use App\Model\SystemConfig;
use App\Model\Users;
use App\Service\CouponRebateServiceInterface;
use App\Service\DeviceServiceInterface;
use App\Service\FeiePrintServiceInterface;
use App\Service\MiniprogramServiceInterface;
use App\Service\MqttServiceInterface;
use App\Service\OrderServiceInterface;
use App\Service\SeparateAccountsServiceInterface;
use App\Service\UserServiceInterface;
use EasyWeChat\Factory;
use Hyperf\DbConnection\Db;
use Hyperf\Guzzle\CoroutineHandler;
use Exception;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Symfony\Component\HttpFoundation\Request;
class NotifyController extends BaseController
{
const AWARD_LIMIT_AMOUNT = 3;
/**
* @Inject
* @var MqttServiceInterface
*/
protected $mqttSpeakerService;
/**
* @Inject
* @var DeviceServiceInterface
*/
protected $deviceService;
/**
* @Inject
* @var MiniprogramServiceInterface
*/
protected $miniprogramService;
/**
* @Inject
* @var FeiePrintServiceInterface
*/
protected $feiePrintService;
/**
* @Inject
* @var UserServiceInterface
*/
protected $userService;
/**
* @Inject
* @var CouponRebateServiceInterface
*/
protected $couponRebateService;
/**
* @Inject
* @var OrderServiceInterface
*/
protected $orderService;
/**
* @Inject
* @var SeparateAccountsServiceInterface
*/
protected $separateAccountsService;
public function wxminiOnline()
{
$config = config('wxpay');
$app = Factory::payment($config);
$app['guzzle_handler'] = CoroutineHandler::class;
$get = $this->request->getQueryParams();
$post = $this->request->getParsedBody();
$cookie = $this->request->getCookieParams();
$files = $this->request->getUploadedFiles();
$server = $this->request->getServerParams();
$xml = $this->request->getBody()->getContents();
$app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
// 通知回调,进行业务处理
$response = $app->handlePaidNotify(function ($message, $fail) use ($app) {
Db::beginTransaction();
try {
// 支付失败或者通知失败
if (
empty($message)
|| $message['return_code'] != 'SUCCESS'
|| !isset($message['result_code'])
|| $message['result_code'] != 'SUCCESS'
) {
$this->log->event(
LogLabel::PAY_NOTIFY_WXMINI,
$message
);
Db::rollBack();
return $fail('Unknown error but FAIL');
}
// 查询订单
$orderMain = OrderMain::query()
->where([
'global_order_id' => $message['out_trade_no'],
'type' => OrderMain::ORDER_TYPE_ONLINE
])
->first();
// 订单不存在
if (empty($orderMain) || $orderMain->state == OrderMain::ORDER_STATE_DELIVERY) {
$this->log->event(
LogLabel::PAY_NOTIFY_WXMINI,
['global_order_id_fail' => $message['out_trade_no']]
);
Db::rollBack();
return true;
}
$this->orderService->onlinePaid($message['out_trade_no']);
$this->separateAccountsService->orderOnlinePaid($message['out_trade_no']);
// // 修改订单、子订单状态
// $currentTime = time();
// $orderMain->state = OrderMain::ORDER_STATE_UNTAKE;
// $orderMain->time_pay = $currentTime;
// $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime);
// $orderMain->save();
//
// $upOrder = Order::query()
// ->where(['order_main_id' => $orderMain->id])
// ->update(['state' => OrderMain::ORDER_STATE_UNTAKE, 'pay_time' => $orderMain->pay_time]);
//
// // 更新商户销量
// $upStoreScore = Store::query()
// ->whereIn('id', explode(',', $orderMain->store_ids))
// ->update(['score' => Db::raw('score+1')]);
//
// // 更新商品库存和销量
// $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time'])
// ->where(['order_main_id' => $orderMain->id])
// ->get()
// ->toArray();
// $orderGoods = OrderGoods::query()->select(['good_id AS id', 'number', 'combination_id'])
// ->whereIn('order_id', array_values(array_column($orders, 'id')))
// ->get()
// ->toArray();
// foreach ($orderGoods as $key => &$goodsItem) {
//
// $goods = Goods::find($goodsItem['id']);
//
// // 库存处理,有规格
// if ($goodsItem['combination_id']) {
// $combination = SpecCombination::find($goodsItem['combination_id']);
// $combination->number = $combination->number - $goodsItem['number'];
// $combination->save();
// } else {
// $goods->inventory = $goods->inventory - $goodsItem['number'];
// }
//
// $goods->sales = $goods->sales - $goodsItem['number'];
// $goods->save();
//
// }
//
// // 月销流水
// $statistics = [];
// foreach ($orders as $key => &$order) {
// $statistics[] = [
// 'money' => $order['money'],
// 'user_id' => $order['user_id'],
// 'store_id' => $order['store_id'],
// 'market_id' => $orderMain->market_id,
// 'order_id' => $order['id'],
// 'createtime' => strtotime($order['pay_time']),
// ];
// }
//
// if (is_array($statistics) && !empty($statistics)) {
// $inSalesStatistics = OrderSalesStatistic::query()->insert($statistics);
// }
// 优惠券返券
$this->couponRebateService->couponRebateInTask($orderMain->id);
// 喇叭通知,兼容旧音响,MQTT+IOT
$res = $this->mqttSpeakerService->speakToStore($orderMain->id);
$res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id);
// 公众号模板消息
$res = $this->miniprogramService->sendTemMsgForOnlineOrder($orderMain->id);
// 打印订单,自动打印
$res = $this->feiePrintService->feiePrint($orderMain->global_order_id);
Db::commit();
return true;
} catch (Exception $e) {
$this->log->event(
LogLabel::PAY_NOTIFY_WXMINI,
['exception_fail' => $e->getMessage()]
);
Db::rollBack();
return $fail('Exception');
}
});
return $this->response
->withHeader('Content-Type', 'text/xml')
->withStatus(200)
->withBody(new SwooleStream($response->getContent()));
}
public function wxminiOffline()
{
$config = config('wxpay');
$app = Factory::payment($config);
$app['guzzle_handler'] = CoroutineHandler::class;
$get = $this->request->getQueryParams();
$post = $this->request->getParsedBody();
$cookie = $this->request->getCookieParams();
$files = $this->request->getUploadedFiles();
$server = $this->request->getServerParams();
$xml = $this->request->getBody()->getContents();
$app['request'] = new Request($get,$post,[],$cookie,$files,$server,$xml);
// 通知回调,进行业务处理
$response = $app->handlePaidNotify(function ($message, $fail) use ($app) {
Db::beginTransaction();
try {
// 支付失败或者通知失败
if (
empty($message)
|| $message['return_code'] != 'SUCCESS'
|| !isset($message['result_code'])
|| $message['result_code'] != 'SUCCESS'
) {
$this->log->event(
LogLabel::PAY_NOTIFY_WXMINI,
$message
);
Db::rollBack();
return $fail('Unknown error but FAIL');
}
// 查询订单
$orderMain = OrderMain::query()
->where([
'global_order_id' => $message['out_trade_no'],
'type' => OrderMain::ORDER_TYPE_OFFLINE
])
->first();
// 订单不存在
if (empty($orderMain)) {
$this->log->event(
LogLabel::PAY_NOTIFY_WXMINI,
['global_order_id_fail' => $message['out_trade_no']]
);
Db::rollBack();
return true;
}
$orderPaid = $this->orderService->offlinePaid($message['out_trade_no']);
$separate = $this->separateAccountsService->orderOfflinePaid($message['out_trade_no']);
// // 修改订单、子订单状态
// $currentTime = time();
// $orderMain->state = OrderMain::ORDER_STATE_UNTAKE;
// $orderMain->dm_state = OrderMain::ORDER_STATE_UNTAKE;
// $orderMain->time_pay = $currentTime;
// $orderMain->pay_time = date('Y-m-d H:i:s', $currentTime);
// $orderMain->save();
//
// $upOrder = Order::query()
// ->where(['order_main_id' => $orderMain->id])
// ->update([
// 'state' => OrderMain::ORDER_STATE_UNTAKE,
// 'dm_state' => OrderMain::ORDER_STATE_UNTAKE,
// 'pay_time' => date('Y-m-d H:i:s', $currentTime)
// ]);
// // 查询子订单,当面付目前实际上只有一个子订单
// $orders = Order::query()->select(['id', 'money', 'user_id', 'store_id', 'pay_time'])
// ->where(['order_main_id' => $orderMain->id])
// ->get()
// ->toArray();
//
// // 商户钱包、流水资金、奖励、发布模板消息处理
// foreach ($orders as $key => $orderItem) {
//
// $recordBase = [
// 'user_id' => $orderItem['user_id'],
// 'order_id' => $orderItem['id'],
// 'store_id' => $orderItem['store_id'],
// 'type' => 1,
// 'time' => date('Y-m-d H:i:s', $currentTime),
// 'add_time' => $currentTime,
// ];
//
// // 钱包
// $store = Store::find($orderItem['store_id']);
// $store->store_wallet = bcadd($store->store_wallet, $orderItem['money'], 2);
// $store->save();
//
// // 流水
// $record = [
// 'money' => $orderItem['money'],
// 'note' => '当面付订单收入',
// 'category' => 2,
// ];
// StoreAccount::query()->insert(array_merge($recordBase, $record));
//
// // 平台新用户奖励给商户
// $isStageNewUser = $this->userService->isPlatformNewUser($orderItem['user_id'], $orderMain->id);
// $needAward = false;
// $awardAmount = 0;
// if ($isStageNewUser) {
// $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_new_user'])->value('value');
// // 流水
// $record = [
// 'money' => $awardAmount,
// 'note' => '新用户下单成功,平台奖励',
// 'category' => 3,
// ];
// $needAward = true;
// } else {
// $isStoreFirstOrderToday = $this->userService->isStoreFirstOrderToday($orderItem['user_id'],$orderItem['store_id'],$orderItem['id'], self::AWARD_LIMIT_AMOUNT);
// if ($isStoreFirstOrderToday && $orderItem['money'] >= self::AWARD_LIMIT_AMOUNT) {
// $awardAmount = SystemConfig::query()->where(['type' => 1, 'menu_name' => 'award_each_order'])->value('value');
// // 流水
// $record = [
// 'money' => $awardAmount,
// 'note' => '用户下单成功,平台奖励',
// 'category' => 4,
// ];
// $needAward = true;
// }
// }
//
// if ($needAward && $awardAmount) {
// // 奖励钱包
// $store->refresh();
// $store->award_money = bcadd($store->award_money, $awardAmount, 2);
// $store->save();
//
// // 流水
// StoreAccount::query()->insert(array_merge($recordBase, $record));
//
// // 发布公众号消息
// $openid = Users::query()->where(['id' => $store['user_id']])->value('openid');
// $res = $this->miniprogramService->sendTemMsgForAward($record['money'], $record['note'], $openid, $recordBase['time']);
// }
// }
// 喇叭通知,兼容旧音响,MQTT+IOT
$res = $this->mqttSpeakerService->speakToStore($orderMain->id);
$res = $this->deviceService->pubMsgToStoreByOrderMainId($orderMain->id);
// 公众号模板消息
$res = $this->miniprogramService->sendTemMsgForOfflineOrder($orderMain->id);
Db::commit();
return true;
} catch (Exception $e) {
$this->log->event(
LogLabel::PAY_NOTIFY_WXMINI,
['exception_fail' => $e->getMessage()]
);
Db::rollBack();
return $fail('Exception');
}
});
return $this->response
->withHeader('Content-Type', 'text/xml')
->withStatus(200)
->withBody(new SwooleStream($response->getContent()));
}
}