760 lines
26 KiB
PHP
760 lines
26 KiB
PHP
<?php
|
||
|
||
namespace app\api\controller;
|
||
|
||
use app\common\controller\Api;
|
||
use app\common\library\pay\VirtualPayService;
|
||
use app\common\model\order\Order;
|
||
use app\common\model\order\Log as OrderLog;
|
||
use think\Db;
|
||
|
||
/**
|
||
* 虚拟支付
|
||
*/
|
||
class VirtualPay extends Api
|
||
{
|
||
protected $noNeedLogin = [];
|
||
protected $noNeedRight = ['*'];
|
||
|
||
/**
|
||
* @var VirtualPayService
|
||
*/
|
||
protected $virtualPayService = null;
|
||
|
||
/**
|
||
* 初始化虚拟支付服务
|
||
*/
|
||
public function _initialize()
|
||
{
|
||
parent::_initialize();
|
||
$this->virtualPayService = new VirtualPayService();
|
||
}
|
||
|
||
/**
|
||
* 获取虚拟支付配置信息(是否开启等)
|
||
* @return mixed
|
||
*/
|
||
public function getConfig()
|
||
{
|
||
$virtualPayConfig = \app\common\model\config\System::getConfig('virtual_pay');
|
||
|
||
$data = [
|
||
'status' => $virtualPayConfig['status'] ?? 'close',
|
||
'ios_refund_policy' => $virtualPayConfig['ios_refund_policy'] ?? 'none',
|
||
'virtual_goods_types' => $virtualPayConfig['virtual_goods_types'] ?? [],
|
||
'exchange_rate' => $virtualPayConfig['exchange_rate'] ?? '1',
|
||
];
|
||
|
||
$this->success('获取成功', $data);
|
||
}
|
||
|
||
/**
|
||
* 查询用户代币余额
|
||
* @return mixed
|
||
*/
|
||
public function queryBalance()
|
||
{
|
||
$oauth = \app\common\model\user\Oauth::where([
|
||
'user_id' => $this->auth->id,
|
||
'provider' => 'Wechat',
|
||
'platform' => 'wxMiniProgram'
|
||
])->find();
|
||
|
||
if (!$oauth || empty($oauth->openid)) {
|
||
$this->error('用户微信小程序授权信息不存在');
|
||
}
|
||
|
||
$result = $this->virtualPayService->queryUserBalance($oauth->openid);
|
||
|
||
if (isset($result['errcode']) && $result['errcode'] !== 0) {
|
||
$this->error('查询余额失败:' . ($result['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$this->success('查询成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 检查余额并支付(代币模式)
|
||
* 支付前先查询余额,如果足够直接扣减代币完成支付
|
||
* 如果不足返回需要充值的信息,充值后再次调用此接口
|
||
* @return mixed
|
||
*/
|
||
public function checkAndPay()
|
||
{
|
||
$orderNo = $this->request->post('order_no');
|
||
$mode = $this->request->post('mode', 'short_series_coin');
|
||
|
||
if (empty($orderNo)) {
|
||
$this->error('订单号不能为空');
|
||
}
|
||
|
||
$order = Order::where([
|
||
'order_no' => $orderNo,
|
||
'status' => \app\common\constant\order\Status::STATUS_UNPAID
|
||
])->find();
|
||
|
||
if (!$order) {
|
||
$this->error('订单不存在或已支付');
|
||
}
|
||
|
||
if ($order['user_id'] != $this->auth->id) {
|
||
$this->error('无权操作此订单');
|
||
}
|
||
|
||
$oauth = $this->getOrderWxOauth($order);
|
||
|
||
try {
|
||
$balanceResult = $this->virtualPayService->queryUserBalance($oauth->openid);
|
||
|
||
if (isset($balanceResult['errcode']) && $balanceResult['errcode'] !== 0) {
|
||
$this->error('查询余额失败:' . ($balanceResult['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$currentBalance = intval($balanceResult['balance'] ?? 0);
|
||
$requiredAmount = $this->getRequiredCoinAmount($order, $mode);
|
||
|
||
if ($currentBalance >= $requiredAmount) {
|
||
return $this->executeCurrencyPay($order, $oauth, $requiredAmount);
|
||
} else {
|
||
$deficit = $requiredAmount - $currentBalance;
|
||
return $this->returnRechargeInfo($order, $currentBalance, $requiredAmount, $deficit, $balanceResult);
|
||
}
|
||
} catch (\Exception $e) {
|
||
$this->error('检查余额异常:' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取订单需要的代币数量
|
||
* @param Order $order 订单对象
|
||
* @param string $mode 支付模式
|
||
* @return int
|
||
*/
|
||
private function getRequiredCoinAmount($order, $mode)
|
||
{
|
||
$exchangeRate = VirtualPayService::getExchangeRate();
|
||
$priceInYuan = floatval($order->real_price);
|
||
|
||
if ($mode === 'short_series_coin') {
|
||
return intval($priceInYuan * $exchangeRate);
|
||
}
|
||
|
||
return intval($priceInYuan * $exchangeRate);
|
||
}
|
||
|
||
/**
|
||
* 执行代币扣减支付
|
||
* @param Order $order 订单对象
|
||
* @param mixed $oauth 用户授权信息
|
||
* @param int $amount 扣减的代币数量
|
||
* @return void
|
||
*/
|
||
private function executeCurrencyPay($order, $oauth, $amount)
|
||
{
|
||
$payItem = $this->buildPayItem($order);
|
||
|
||
try {
|
||
$result = $this->virtualPayService->currencyPay(
|
||
$oauth->openid,
|
||
$amount,
|
||
$order->order_no,
|
||
$payItem
|
||
);
|
||
|
||
if (isset($result['errcode']) && $result['errcode'] !== 0) {
|
||
$errMsg = $result['errmsg'] ?? '未知错误';
|
||
|
||
if ($result['errcode'] == 268490006) {
|
||
$this->error('代币余额不足,请先充值');
|
||
} elseif ($result['errcode'] == 268490004) {
|
||
$this->success('支付成功(重复操作)', [
|
||
'status' => 'success',
|
||
'order_no' => $order->order_no,
|
||
'balance' => $result['balance'] ?? 0,
|
||
'message' => '订单已处理'
|
||
]);
|
||
} else {
|
||
$this->error('扣减代币失败:' . $errMsg);
|
||
}
|
||
}
|
||
|
||
$newBalance = $result['balance'] ?? 0;
|
||
|
||
$this->success('支付成功', [
|
||
'status' => 'success',
|
||
'order_no' => $order->order_no,
|
||
'amount' => $amount,
|
||
'balance' => $newBalance,
|
||
'used_present' => $result['used_present_amount'] ?? 0,
|
||
'message' => '代币扣减成功,等待微信推送确认'
|
||
]);
|
||
} catch (\Exception $e) {
|
||
$this->error('执行代币支付异常:' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 返回充值信息(余额不足时)
|
||
* @param Order $order 订单对象
|
||
* @param int $currentBalance 当前余额
|
||
* @param int $requiredAmount 需要的金额
|
||
* @param int $deficit 差额
|
||
* @param array $balanceResult 余额查询结果
|
||
* @return void
|
||
*/
|
||
private function returnRechargeInfo($order, $currentBalance, $requiredAmount, $deficit, $balanceResult)
|
||
{
|
||
$this->success('余额不足,请先充值', [
|
||
'status' => 'insufficient_balance',
|
||
'order_no' => $order->order_no,
|
||
'current_balance' => $currentBalance,
|
||
'required_amount' => $requiredAmount,
|
||
'deficit' => $deficit,
|
||
'present_balance' => $balanceResult['present_balance'] ?? 0,
|
||
'sum_save' => $balanceResult['sum_save'] ?? 0,
|
||
'sum_present' => $balanceResult['sum_present'] ?? 0,
|
||
'first_save_flag' => $balanceResult['first_save_flag'] ?? false,
|
||
'message' => "当前代币余额:{$currentBalance},需要:{$requiredAmount},还差:{$deficit}"
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 构建支付项信息
|
||
* @param Order $order 订单对象
|
||
* @return array
|
||
*/
|
||
private function buildPayItem($order)
|
||
{
|
||
$orderItems = \app\admin\model\order\Item::where(['order_no' => $order->order_no])->select()->toArray();
|
||
$payItems = [];
|
||
|
||
foreach ($orderItems as $item) {
|
||
$payItems[] = [
|
||
'productid' => $item['item_id'] ?? '',
|
||
'unit_price' => floatval($item['unit_price'] ?? $item['real_price'] ?? 0),
|
||
'quantity' => intval($item['goods_count'] ?? 1),
|
||
'title' => $item['item_name'] ?? '',
|
||
'goods_type' => $item['goods_type'] ?? ''
|
||
];
|
||
}
|
||
|
||
return $payItems;
|
||
}
|
||
|
||
/**
|
||
* 拉起虚拟支付(客户端调用wx.requestVirtualPayment前获取参数)
|
||
* @return mixed
|
||
*/
|
||
public function handle()
|
||
{
|
||
$orderNo = $this->request->post('order_no');
|
||
$code = $this->request->post('code', '');
|
||
|
||
$order = Order::where([
|
||
'order_no' => $orderNo,
|
||
'status' => 'unpaid'
|
||
])->find();
|
||
|
||
if (!$order) {
|
||
$this->error('订单不存在或已支付');
|
||
}
|
||
|
||
if ($order['user_id'] != $this->auth->id) {
|
||
$this->error('无权支付此订单');
|
||
}
|
||
|
||
$oauth = \app\common\model\user\Oauth::where([
|
||
'user_id' => $this->auth->id,
|
||
'provider' => 'Wechat',
|
||
'platform' => 'wxMiniProgram'
|
||
])->find();
|
||
|
||
if (!$oauth || empty($oauth->openid)) {
|
||
$this->error('请先登录微信小程序');
|
||
}
|
||
|
||
$this->tryResumeExistingWxOrder($order, $oauth);
|
||
|
||
if (empty($code)) {
|
||
$this->error('请先调用wx.login并传入code');
|
||
}
|
||
|
||
$wechat = new \app\common\library\Wechat('wxMiniProgram');
|
||
$session = $wechat->code($code);
|
||
if (empty($session['session_key'])) {
|
||
$this->error('获取session_key失败:' . ($session['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
if (!empty($session['openid']) && $session['openid'] !== $oauth->openid) {
|
||
$this->error('微信登录态与当前用户不一致,请重新登录');
|
||
}
|
||
|
||
$sessionKey = $session['session_key'];
|
||
$oauth->session_key = $sessionKey;
|
||
$oauth->expiretime = time() + 7200;
|
||
$oauth->save();
|
||
|
||
$orderData = [
|
||
'openid' => $oauth->openid,
|
||
'session_key' => $sessionKey,
|
||
'out_trade_no' => $order->order_no,
|
||
'total_fee' => $order->real_price,
|
||
'mode' => $this->request->post('mode', 'short_series_coin'),
|
||
'product_id' => $this->request->post('product_id', ''),
|
||
];
|
||
|
||
try {
|
||
$result = $this->virtualPayService->getClientPayConfig(
|
||
$orderData['openid'],
|
||
$orderData['session_key'],
|
||
$orderData['out_trade_no'],
|
||
$orderData['total_fee'],
|
||
$orderData['mode'],
|
||
$orderData['product_id']
|
||
);
|
||
} catch (\Exception $e) {
|
||
$this->error('获取支付参数失败:' . $e->getMessage());
|
||
}
|
||
|
||
$this->success('获取成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 历史订单再次发起支付前,先检查微信侧是否已经存在同订单号的支付单。
|
||
* 如果微信侧已成功,则直接补齐本地订单;如果已存在未完成支付单,则阻止重复拉起。
|
||
* @param Order $order
|
||
* @param mixed $oauth
|
||
* @return void
|
||
*/
|
||
private function tryResumeExistingWxOrder($order, $oauth)
|
||
{
|
||
try {
|
||
$queryResult = $this->virtualPayService->queryOrder($oauth->openid, $order->order_no);
|
||
} catch (\Exception $e) {
|
||
return;
|
||
}
|
||
|
||
if (isset($queryResult['errcode']) && $queryResult['errcode'] !== 0) {
|
||
return;
|
||
}
|
||
|
||
$wxOrder = $queryResult['order'] ?? [];
|
||
$status = intval($wxOrder['status'] ?? -1);
|
||
|
||
if (in_array($status, [2, 3, 4], true)) {
|
||
if ($order['status'] == \app\common\constant\order\Status::STATUS_UNPAID) {
|
||
if ($order['is_virtual_pay'] == 1) {
|
||
$this->processCoinPayAfterRecharge($order, $oauth, $queryResult);
|
||
} else {
|
||
$this->processCashOrderDeliver($order, $oauth, $queryResult);
|
||
}
|
||
}
|
||
|
||
$this->success('订单已存在微信支付记录,已自动处理', [
|
||
'status' => 'completed',
|
||
'order_no' => $order->order_no,
|
||
]);
|
||
}
|
||
|
||
if ($status >= 0) {
|
||
$this->error('该订单已存在微信侧支付单,请先查询支付结果;若需重新支付,请重新下单');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 虚拟支付成功回调(小程序端支付成功后调用,用于确认发货)
|
||
* 余额不足充值场景:queryOrder确认充值成功 -> query_user_balance -> currency_pay -> paySuccess
|
||
* @return mixed
|
||
*/
|
||
public function notify()
|
||
{
|
||
$orderNo = $this->request->post('order_no');
|
||
|
||
$order = Order::where('order_no', $orderNo)->find();
|
||
|
||
if (!$order) {
|
||
$this->error('订单不存在');
|
||
}
|
||
|
||
if ($order->user_id != $this->auth->id) {
|
||
$this->error('无权处理此订单');
|
||
}
|
||
|
||
$oauth = $this->getOrderWxOauth($order);
|
||
|
||
if ($order->status != \app\common\constant\order\Status::STATUS_UNPAID) {
|
||
$this->success('订单已处理');
|
||
}
|
||
|
||
try {
|
||
$orderResult = $this->virtualPayService->queryOrder($oauth->openid, $orderNo);
|
||
} catch (\Exception $e) {
|
||
$this->error('查询虚拟支付订单失败:' . $e->getMessage());
|
||
}
|
||
|
||
if (isset($orderResult['errcode']) && $orderResult['errcode'] !== 0) {
|
||
$this->error('查询虚拟支付订单失败:' . ($orderResult['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$wxOrder = $orderResult['order'] ?? [];
|
||
if (!in_array(intval($wxOrder['status'] ?? -1), [2, 3, 4])) {
|
||
$this->error('微信侧订单尚未支付成功');
|
||
}
|
||
|
||
if ($order['is_virtual_pay'] == 1) {
|
||
$this->processCoinPayAfterRecharge($order, $oauth, $orderResult);
|
||
} else {
|
||
$this->processCashOrderDeliver($order, $oauth, $orderResult);
|
||
}
|
||
|
||
$this->success('发货通知成功');
|
||
}
|
||
|
||
/**
|
||
* 处理代币充值成功后的扣币流程
|
||
* queryOrder确认充值成功 -> query_user_balance -> currency_pay -> paySuccess
|
||
* @param Order $order 订单对象
|
||
* @param mixed $oauth 用户授权信息
|
||
* @param array $orderResult 微信订单查询结果
|
||
* @return void
|
||
*/
|
||
private function processCoinPayAfterRecharge($order, $oauth, $orderResult)
|
||
{
|
||
$orderNo = $order->order_no;
|
||
|
||
try {
|
||
$balanceResult = $this->virtualPayService->queryUserBalance($oauth->openid);
|
||
|
||
if (isset($balanceResult['errcode']) && $balanceResult['errcode'] !== 0) {
|
||
throw new \Exception('查询余额失败:' . ($balanceResult['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$currentBalance = intval($balanceResult['balance'] ?? 0);
|
||
$requiredAmount = $this->getRequiredCoinAmount($order, 'short_series_coin');
|
||
|
||
if ($currentBalance < $requiredAmount) {
|
||
throw new \Exception("充值后余额仍不足,当前:{$currentBalance},需要:{$requiredAmount}");
|
||
}
|
||
|
||
$payItem = $this->buildPayItem($order);
|
||
$result = $this->virtualPayService->currencyPay(
|
||
$oauth->openid,
|
||
$requiredAmount,
|
||
$orderNo,
|
||
$payItem
|
||
);
|
||
|
||
if (isset($result['errcode']) && $result['errcode'] !== 0) {
|
||
if ($result['errcode'] == 268490004) {
|
||
$this->handleDuplicateCurrencyPay($order, $oauth, $orderResult);
|
||
return;
|
||
}
|
||
throw new \Exception('扣减代币失败:' . ($result['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$notify = [
|
||
'order_no' => $orderNo,
|
||
'transaction_id' => $orderResult['order']['wxpay_order_id'] ?? ($orderResult['order']['wx_order_id'] ?? $orderNo),
|
||
'pay_time' => time(),
|
||
'real_pay_price' => $order->real_price,
|
||
'pay_type' => 'virtual_pay',
|
||
'payment_json' => json_encode([
|
||
'query_order' => $orderResult,
|
||
'balance_result' => $balanceResult,
|
||
'currency_pay' => $result,
|
||
], JSON_UNESCAPED_UNICODE),
|
||
];
|
||
|
||
Db::transaction(function () use ($order, $notify) {
|
||
$order->paySuccess($order, $notify);
|
||
});
|
||
|
||
OrderLog::set($orderNo, "充值后扣减代币成功,余额:{$result['balance'] ?? 0}");
|
||
} catch (\Exception $e) {
|
||
OrderLog::set($orderNo, "充值后扣币失败:{$e->getMessage()}");
|
||
$this->error($e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理重复扣减代币的情况(currency_pay返回268490004)
|
||
* 查询微信订单确认是否已扣币,然后完成本地订单
|
||
* @param Order $order 订单对象
|
||
* @param mixed $oauth 用户授权信息
|
||
* @param array $orderResult 微信订单查询结果
|
||
* @return void
|
||
*/
|
||
private function handleDuplicateCurrencyPay($order, $oauth, $orderResult)
|
||
{
|
||
$orderNo = $order->order_no;
|
||
|
||
try {
|
||
$queryResult = $this->virtualPayService->queryOrder($oauth->openid, $orderNo);
|
||
|
||
if (isset($queryResult['errcode']) && $queryResult['errcode'] !== 0) {
|
||
throw new \Exception('查询订单失败:' . ($queryResult['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$wxOrder = $queryResult['order'] ?? [];
|
||
$orderStatus = intval($wxOrder['status'] ?? -1);
|
||
|
||
if ($orderStatus === 3 || $orderStatus === 4) {
|
||
$notify = [
|
||
'order_no' => $orderNo,
|
||
'transaction_id' => $wxOrder['wxpay_order_id'] ?? ($wxOrder['wx_order_id'] ?? $orderNo),
|
||
'pay_time' => time(),
|
||
'real_pay_price' => $order->real_price,
|
||
'pay_type' => 'virtual_pay',
|
||
'payment_json' => json_encode([
|
||
'query_order' => $orderResult,
|
||
'duplicate_check' => $queryResult,
|
||
], JSON_UNESCAPED_UNICODE),
|
||
];
|
||
|
||
Db::transaction(function () use ($order, $notify) {
|
||
$order->paySuccess($order, $notify);
|
||
});
|
||
|
||
OrderLog::set($orderNo, '重复扣币,订单已完成支付');
|
||
} else {
|
||
throw new \Exception('订单状态异常,status=' . $orderStatus);
|
||
}
|
||
} catch (\Exception $e) {
|
||
OrderLog::set($orderNo, "重复扣币处理异常:{$e->getMessage()}");
|
||
$this->error($e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理现金订单发货(道具直购模式)
|
||
* @param Order $order 订单对象
|
||
* @param mixed $oauth 用户授权信息
|
||
* @param array $orderResult 微信订单查询结果
|
||
* @return void
|
||
*/
|
||
private function processCashOrderDeliver($order, $oauth, $orderResult)
|
||
{
|
||
$orderNo = $order->order_no;
|
||
|
||
try {
|
||
$result = $this->virtualPayService->notifyProvideGoods($orderNo);
|
||
} catch (\Exception $e) {
|
||
$this->error('通知发货失败:' . $e->getMessage());
|
||
}
|
||
|
||
if (isset($result['errcode']) && $result['errcode'] !== 0) {
|
||
$this->error('通知发货失败:' . ($result['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$wxOrder = $orderResult['order'] ?? [];
|
||
$notify = [
|
||
'order_no' => $orderNo,
|
||
'transaction_id' => $wxOrder['wxpay_order_id'] ?? ($wxOrder['wx_order_id'] ?? $orderNo),
|
||
'pay_time' => time(),
|
||
'real_pay_price' => $order->real_price,
|
||
'pay_type' => 'virtual_pay',
|
||
'payment_json' => json_encode(['query_order' => $orderResult, 'notify_provide_goods' => $result], JSON_UNESCAPED_UNICODE),
|
||
];
|
||
|
||
Db::transaction(function () use ($order, $notify) {
|
||
$order->paySuccess($order, $notify);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 代币支付退款
|
||
* @return mixed
|
||
*/
|
||
public function refund()
|
||
{
|
||
$orderNo = $this->request->post('order_no');
|
||
$amount = $this->request->post('amount');
|
||
|
||
$order = Order::where('order_no', $orderNo)->find();
|
||
|
||
if (!$order) {
|
||
$this->error('订单不存在');
|
||
}
|
||
|
||
if ($order->user_id != $this->auth->id) {
|
||
$this->error('无权处理此订单');
|
||
}
|
||
|
||
if (!is_numeric($amount) || intval($amount) <= 0) {
|
||
$this->error('退款金额不合法');
|
||
}
|
||
|
||
if (!in_array($order->status, [
|
||
\app\common\constant\order\Status::STATUS_PAID,
|
||
\app\common\constant\order\Status::STATUS_UNRECEIVE,
|
||
\app\common\constant\order\Status::STATUS_UNSEND,
|
||
\app\common\constant\order\Status::STATUS_SUREUNRECEIVE,
|
||
\app\common\constant\order\Status::STATUS_SUCCESS,
|
||
])) {
|
||
$this->error('订单状态不支持退款');
|
||
}
|
||
|
||
$oauth = $this->getOrderWxOauth($order);
|
||
|
||
$refundId = 'RF' . date('YmdHis') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
|
||
|
||
try {
|
||
$result = $this->virtualPayService->cancelCurrencyPay(
|
||
$oauth->openid,
|
||
$amount,
|
||
$orderNo,
|
||
$refundId
|
||
);
|
||
} catch (\Exception $e) {
|
||
$this->error('退款失败:' . $e->getMessage());
|
||
}
|
||
|
||
if (isset($result['errcode']) && $result['errcode'] !== 0) {
|
||
$this->error('退款失败:' . ($result['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$this->success('退款成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 查询虚拟支付订单
|
||
* 余额不足充值场景:queryOrder确认充值成功 -> query_user_balance -> currency_pay -> paySuccess
|
||
* @return mixed
|
||
*/
|
||
public function queryOrder()
|
||
{
|
||
$orderNo = $this->request->post('order_no', '');
|
||
$wxOrderId = $this->request->post('wx_order_id', '');
|
||
$autoComplete = $this->request->post('auto_complete', 0);
|
||
|
||
if (empty($orderNo) && empty($wxOrderId)) {
|
||
$this->error('订单号不能为空');
|
||
}
|
||
|
||
if (!empty($orderNo)) {
|
||
$order = Order::where('order_no', $orderNo)->find();
|
||
if (!$order) {
|
||
$this->error('订单不存在');
|
||
}
|
||
if ($order->user_id != $this->auth->id) {
|
||
$this->error('无权查询此订单');
|
||
}
|
||
$oauth = $this->getOrderWxOauth($order);
|
||
} else {
|
||
$oauth = $this->getCurrentWxOauth();
|
||
}
|
||
|
||
$result = $this->virtualPayService->queryOrder($oauth->openid, $orderNo, $wxOrderId);
|
||
|
||
if (isset($result['errcode']) && $result['errcode'] !== 0) {
|
||
$this->error('查询失败:' . ($result['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
if ($autoComplete && !empty($orderNo) && $order['is_virtual_pay'] == 1
|
||
&& $order['status'] == \app\common\constant\order\Status::STATUS_UNPAID) {
|
||
$wxOrder = $result['order'] ?? [];
|
||
if (in_array(intval($wxOrder['status'] ?? -1), [2, 3, 4])) {
|
||
$this->processCoinPayAfterRecharge($order, $oauth, $result);
|
||
}
|
||
}
|
||
|
||
$this->success('查询成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 查询现金订单并启动退款
|
||
* @return mixed
|
||
*/
|
||
public function refundOrder()
|
||
{
|
||
$orderNo = $this->request->post('order_no');
|
||
$refundFee = $this->request->post('refund_fee', null);
|
||
$reason = $this->request->post('refund_reason', '0');
|
||
$reqFrom = $this->request->post('req_from', '3');
|
||
|
||
if (empty($orderNo)) {
|
||
$this->error('订单号不能为空');
|
||
}
|
||
|
||
$order = Order::where('order_no', $orderNo)->find();
|
||
if (!$order) {
|
||
$this->error('订单不存在');
|
||
}
|
||
|
||
if ($order->user_id != $this->auth->id) {
|
||
$this->error('无权处理此订单');
|
||
}
|
||
|
||
$oauth = $this->getOrderWxOauth($order);
|
||
|
||
$orderResult = $this->virtualPayService->queryOrder($oauth->openid, $orderNo);
|
||
if (isset($orderResult['errcode']) && $orderResult['errcode'] !== 0) {
|
||
$this->error('查询订单失败:' . ($orderResult['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$leftFee = intval($orderResult['order']['left_fee'] ?? 0);
|
||
if ($leftFee <= 0) {
|
||
$this->error('订单无可退金额');
|
||
}
|
||
|
||
if ($refundFee === null || $refundFee === '') {
|
||
$refundFee = $leftFee;
|
||
} else {
|
||
$refundFee = intval($refundFee);
|
||
}
|
||
|
||
if ($refundFee <= 0 || $refundFee > $leftFee) {
|
||
$this->error('退款金额不合法');
|
||
}
|
||
|
||
$refundId = 'RF' . date('YmdHis') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
|
||
|
||
$result = $this->virtualPayService->refundOrder($oauth->openid, $orderNo, $refundId, $leftFee, $refundFee, $reason, $reqFrom);
|
||
|
||
if (isset($result['errcode']) && $result['errcode'] !== 0) {
|
||
$this->error('退款失败:' . ($result['errmsg'] ?? '未知错误'));
|
||
}
|
||
|
||
$this->success('退款任务已启动', $result);
|
||
}
|
||
|
||
/**
|
||
* 获取订单所属用户的小程序授权信息。
|
||
* @param Order $order
|
||
* @return \think\Model
|
||
*/
|
||
private function getOrderWxOauth($order)
|
||
{
|
||
$oauth = \app\common\model\user\Oauth::where([
|
||
'user_id' => $order->user_id,
|
||
'provider' => 'Wechat',
|
||
'platform' => 'wxMiniProgram'
|
||
])->find();
|
||
|
||
if (!$oauth || empty($oauth->openid)) {
|
||
$this->error('用户微信授权信息不存在');
|
||
}
|
||
|
||
return $oauth;
|
||
}
|
||
|
||
/**
|
||
* 获取当前用户的小程序授权信息。
|
||
* @return \think\Model
|
||
*/
|
||
private function getCurrentWxOauth()
|
||
{
|
||
$oauth = \app\common\model\user\Oauth::where([
|
||
'user_id' => $this->auth->id,
|
||
'provider' => 'Wechat',
|
||
'platform' => 'wxMiniProgram'
|
||
])->find();
|
||
|
||
if (!$oauth || empty($oauth->openid)) {
|
||
$this->error('用户微信授权信息不存在');
|
||
}
|
||
|
||
return $oauth;
|
||
}
|
||
}
|