Lae/app/Http/Controllers/Web/BalanceController.php

291 lines
7.7 KiB
PHP
Raw Normal View History

<?php
namespace App\Http\Controllers\Web;
2022-12-27 16:24:41 +00:00
use App\Exceptions\ChargeException;
use App\Http\Controllers\Controller;
use App\Models\Balance;
2022-11-16 10:06:51 +00:00
use App\Models\Module;
use App\Models\Transaction;
use Illuminate\Contracts\View\View;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
2022-12-27 16:24:41 +00:00
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
2022-12-27 16:24:41 +00:00
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Yansongda\LaravelPay\Facades\Pay;
class BalanceController extends Controller
{
//
public function index(Request $request): View
{
$balance = $request->user()->balance;
2022-11-17 00:22:18 +00:00
$balances = Balance::thisUser()->latest()->paginate(100);
2022-11-16 10:06:51 +00:00
2022-11-19 14:42:47 +00:00
return view('balances.index', compact('balance', 'balances'));
}
public function store(Request $request)
{
// 充值
$this->validate($request, [
2022-12-18 03:16:27 +00:00
'amount' => 'required|integer|min:0.1|max:10000',
2022-12-27 16:24:41 +00:00
'payment' => 'required|in:wechat,alipay',
]);
$user = $request->user();
$balance = new Balance();
$data = [
'user_id' => $user->id,
2022-12-18 03:16:27 +00:00
'amount' => $request->input('amount'),
2022-12-27 16:24:41 +00:00
'payment' => $request->input('payment'),
];
$balance = $balance->create($data);
// 生成 18 位订单号
$order_id = date('YmdHis') . $balance->id . rand(1000, 9999);
$balance->order_id = $order_id;
$balance->save();
2022-12-27 16:24:41 +00:00
return redirect()->route('balances.show', compact('balance'));
}
/**
2022-12-27 16:24:41 +00:00
* 显示充值页面和状态(ajax)
*/
2022-12-27 16:24:41 +00:00
public function show(Request $request, Balance $balance)
{
2022-12-27 16:24:41 +00:00
if ($balance->paid_at !== null) {
2022-12-27 16:24:41 +00:00
if ($request->ajax()) {
return $this->success($balance);
}
return view('balances.process', compact('balance'));
} else {
if ($request->ajax()) {
return $this->success($balance);
}
}
2022-12-27 16:24:41 +00:00
if (now()->diffInDays($balance->created_at) > 1) {
2022-12-27 16:24:41 +00:00
if ($request->ajax()) {
return $this->forbidden($balance);
}
return redirect()->route('index')->with('error', '订单已逾期。');
}
2022-12-27 16:24:41 +00:00
$balance->load('user');
$subject = config('app.display_name') . ' 充值';
$order = [
'out_trade_no' => $balance->order_id,
2022-12-27 16:24:41 +00:00
];
$code = QrCode::size(150);
if ($balance->payment === 'wechat') {
$pay = $this->xunhu_wechat($balance, $subject);
$qr_code = $code->generate($pay['url']);
} else {
$order['subject'] = $subject;
$order['total_amount'] = $balance->amount;
2022-12-27 17:03:52 +00:00
$pay = Pay::alipay()->web($order);
2022-12-27 16:24:41 +00:00
2022-12-27 17:03:52 +00:00
return view('balances.alipay', ['html' => (string)$pay->getBody()]);
2022-12-27 16:24:41 +00:00
}
if (!isset($qr_code)) {
abort(500, '支付方式错误');
}
return view('balances.pay', compact('balance', 'qr_code'));
}
private function xunhu_wechat(Balance $balance, $subject = '支付')
{
$data = [
'version' => '1.1',
'lang' => 'zh-cn',
'plugins' => config('app.name'),
'appid' => config('pay.xunhu.app_id'),
'trade_order_id' => $balance->order_id,
'payment' => 'wechat',
'type' => 'WAP',
'wap_url' => config('app.url'),
'wap_name' => config('app.display_name'),
'total_fee' => $balance->amount,
'title' => $subject,
'time' => time(),
'notify_url' => route('balances.notify', 'wechat'),
'return_url' => route('balances.notify', 'wechat'),
'callback_url' => route('balances.show', $balance),
'modal' => null,
'nonce_str' => str_shuffle(time()),
];
$data['hash'] = $this->xunhu_hash($data);
$response = Http::post(config('pay.xunhu.gateway'), $data);
if (!$response->successful()) {
abort(500, '支付网关错误');
}
$response = $response->json();
$hash = $this->xunhu_hash($response);
2022-12-27 16:24:41 +00:00
if (!isset($response['hash']) || $response['hash'] !== $hash) {
abort(500, '无法校验支付网关返回数据');
}
return $response;
}
private function xunhu_hash(array $arr)
{
ksort($arr);
$pre = [];
foreach ($arr as $key => $data) {
if (is_null($data) || $data === '') {
continue;
}
if ($key == 'hash') {
continue;
}
$pre[$key] = stripslashes($data);
}
$arg = '';
$qty = count($pre);
$index = 0;
foreach ($pre as $key => $val) {
$arg .= "$key=$val";
if ($index++ < ($qty - 1)) {
$arg .= "&";
}
}
return md5($arg . config('pay.xunhu.app_secret'));
}
/**
* @throws ValidationException
*/
2022-12-27 16:24:41 +00:00
public function notify(Request $request, $payment): View|JsonResponse
{
2022-12-27 16:24:41 +00:00
$is_paid = false;
// $pay_amount = 0;
if ($payment === 'alipay') {
$out_trade_no = $request->input('out_trade_no');
} else if ($payment === 'wechat') {
$out_trade_no = $request->input('trade_order_id');
} else {
abort(400, '支付方式错误');
}
// 检测订单是否存在
2022-12-27 16:24:41 +00:00
$balance = Balance::where('order_id', $out_trade_no)->with('user')->first();
if (!$balance) {
abort(404, '找不到订单。');
}
// 检测订单是否已支付
2022-12-27 16:24:41 +00:00
if ($balance->paid_at !== null) {
if ($request->ajax()) {
return $this->success($balance);
}
return view('balances.process', compact('balance'));
}
2022-11-17 06:43:18 +00:00
2022-12-27 16:24:41 +00:00
// 处理验证
2022-12-27 17:08:44 +00:00
if ($payment === 'wechat') {
2022-12-27 16:24:41 +00:00
if (!($request->filled('hash') || $request->filled('trade_order_id'))) {
return $this->error('参数错误。');
}
if ($request->filled('plugins') && $request->input('plugins') != config('app.name')) {
return $this->error('插件不匹配。');
}
$hash = $this->xunhu_hash($request->toArray());
if ($request->input('hash') != $hash) {
Log::debug('hash error', $request->toArray());
}
if ($request->input('status') === 'OD') {
$is_paid = true;
}
}
if ($is_paid) {
try {
(new Transaction)->addAmount($balance->user_id, 'alipay', $balance->amount);
$balance->update([
'paid_at' => now()
]);
} catch (ChargeException $e) {
abort(500, $e->getMessage());
}
}
if ($request->ajax()) {
return $this->success($balance);
}
2022-11-17 06:43:18 +00:00
return view('balances.process', compact('balance'));
2022-11-16 10:06:51 +00:00
}
/**
* 获取交易记录
*
* @param mixed $request
*
* @return View
*/
2022-12-27 17:08:44 +00:00
public
function transactions(
Request $request
): View {
2022-11-16 10:06:51 +00:00
$modules = Module::all();
$transactions = Transaction::where('user_id', auth()->id());
if ($request->has('type')) {
$transactions = $transactions->where('type', $request->type);
}
2022-11-16 10:06:51 +00:00
if ($request->has('payment')) {
$transactions = $transactions->where('payment', $request->payment);
}
2022-11-17 00:22:18 +00:00
$transactions = $transactions->latest()->paginate(100)->withQueryString();
2022-11-16 10:06:51 +00:00
return view('balances.transactions', compact('transactions', 'modules'));
}
}