mirror of
https://github.com/v2board/v2board.git
synced 2024-11-15 00:09:13 +08:00
commit
229a3022ac
@ -49,7 +49,7 @@ class CheckCommission extends Command
|
|||||||
if ((int)config('v2board.commission_auto_check_enable', 1)) {
|
if ((int)config('v2board.commission_auto_check_enable', 1)) {
|
||||||
Order::where('commission_status', 0)
|
Order::where('commission_status', 0)
|
||||||
->where('invite_user_id', '!=', NULL)
|
->where('invite_user_id', '!=', NULL)
|
||||||
->whereIn('status', [3, 4])
|
->whereNotIn('status', [0, 2])
|
||||||
->where('updated_at', '<=', strtotime('-3 day', time()))
|
->where('updated_at', '<=', strtotime('-3 day', time()))
|
||||||
->update([
|
->update([
|
||||||
'commission_status' => 1
|
'commission_status' => 1
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Services\PaymentService;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
class Test extends Command
|
class Test extends Command
|
||||||
@ -37,5 +38,7 @@ class Test extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
$paymentService = new PaymentService('MGate');
|
||||||
|
var_dump($paymentService->form());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use App\Models\StatOrder;
|
|||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class V2BoardStatistics extends Command
|
class V2boardStatistics extends Command
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
@ -52,11 +52,11 @@ class V2BoardStatistics extends Command
|
|||||||
$startAt = strtotime('-1 day', $endAt);
|
$startAt = strtotime('-1 day', $endAt);
|
||||||
$builder = Order::where('created_at', '>=', $startAt)
|
$builder = Order::where('created_at', '>=', $startAt)
|
||||||
->where('created_at', '<', $endAt)
|
->where('created_at', '<', $endAt)
|
||||||
->whereIn('status', [3, 4]);
|
->whereNotIn('status', [0, 2]);
|
||||||
$orderCount = $builder->count();
|
$orderCount = $builder->count();
|
||||||
$orderAmount = $builder->sum('total_amount');
|
$orderAmount = $builder->sum('total_amount');
|
||||||
$builder = $builder->where('commission_balance', '!=', NULL)
|
$builder = $builder->where('commission_balance', '!=', 0)
|
||||||
->whereIn('commission_status', [1, 2]);
|
->where('commission_status', 0);
|
||||||
$commissionCount = $builder->count();
|
$commissionCount = $builder->count();
|
||||||
$commissionAmount = $builder->sum('commission_balance');
|
$commissionAmount = $builder->sum('commission_balance');
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -66,7 +66,8 @@ class ConfigController extends Controller
|
|||||||
'email_gmail_limit_enable' => config('v2board.email_gmail_limit_enable', 0),
|
'email_gmail_limit_enable' => config('v2board.email_gmail_limit_enable', 0),
|
||||||
'recaptcha_enable' => (int)config('v2board.recaptcha_enable', 0),
|
'recaptcha_enable' => (int)config('v2board.recaptcha_enable', 0),
|
||||||
'recaptcha_key' => config('v2board.recaptcha_key'),
|
'recaptcha_key' => config('v2board.recaptcha_key'),
|
||||||
'recaptcha_site_key' => config('v2board.recaptcha_site_key')
|
'recaptcha_site_key' => config('v2board.recaptcha_site_key'),
|
||||||
|
'tos_url' => config('v2board.tos_url')
|
||||||
],
|
],
|
||||||
'subscribe' => [
|
'subscribe' => [
|
||||||
'plan_change_enable' => (int)config('v2board.plan_change_enable', 1),
|
'plan_change_enable' => (int)config('v2board.plan_change_enable', 1),
|
||||||
@ -110,7 +111,9 @@ class ConfigController extends Controller
|
|||||||
'frontend_theme_header' => config('v2board.frontend_theme_header', 'dark'),
|
'frontend_theme_header' => config('v2board.frontend_theme_header', 'dark'),
|
||||||
'frontend_theme_color' => config('v2board.frontend_theme_color', 'default'),
|
'frontend_theme_color' => config('v2board.frontend_theme_color', 'default'),
|
||||||
'frontend_background_url' => config('v2board.frontend_background_url'),
|
'frontend_background_url' => config('v2board.frontend_background_url'),
|
||||||
'frontend_admin_path' => config('v2board.frontend_admin_path', 'admin')
|
'frontend_admin_path' => config('v2board.frontend_admin_path', 'admin'),
|
||||||
|
'frontend_customer_service_method' => config('v2board.frontend_customer_service_method', 0),
|
||||||
|
'frontend_customer_service_id' => config('v2board.frontend_customer_service_id'),
|
||||||
],
|
],
|
||||||
'server' => [
|
'server' => [
|
||||||
'server_token' => config('v2board.server_token'),
|
'server_token' => config('v2board.server_token'),
|
||||||
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin;
|
|||||||
|
|
||||||
use App\Http\Requests\Admin\OrderAssign;
|
use App\Http\Requests\Admin\OrderAssign;
|
||||||
use App\Http\Requests\Admin\OrderUpdate;
|
use App\Http\Requests\Admin\OrderUpdate;
|
||||||
|
use App\Http\Requests\Admin\OrderFetch;
|
||||||
use App\Services\OrderService;
|
use App\Services\OrderService;
|
||||||
use App\Utils\Helper;
|
use App\Utils\Helper;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -15,25 +16,36 @@ use Illuminate\Support\Facades\DB;
|
|||||||
|
|
||||||
class OrderController extends Controller
|
class OrderController extends Controller
|
||||||
{
|
{
|
||||||
public function fetch(Request $request)
|
private function filter(Request $request, &$builder)
|
||||||
|
{
|
||||||
|
if ($request->input('filter')) {
|
||||||
|
foreach ($request->input('filter') as $filter) {
|
||||||
|
if ($filter['key'] === 'email') {
|
||||||
|
$user = User::where('email', "%{$filter['value']}%")->first();
|
||||||
|
if (!$user) continue;
|
||||||
|
$builder->where('user_id', $user->id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($filter['condition'] === '模糊') {
|
||||||
|
$filter['condition'] = 'like';
|
||||||
|
$filter['value'] = "%{$filter['value']}%";
|
||||||
|
}
|
||||||
|
$builder->where($filter['key'], $filter['condition'], $filter['value']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetch(OrderFetch $request)
|
||||||
{
|
{
|
||||||
$current = $request->input('current') ? $request->input('current') : 1;
|
$current = $request->input('current') ? $request->input('current') : 1;
|
||||||
$pageSize = $request->input('pageSize') >= 10 ? $request->input('pageSize') : 10;
|
$pageSize = $request->input('pageSize') >= 10 ? $request->input('pageSize') : 10;
|
||||||
$orderModel = Order::orderBy('created_at', 'DESC');
|
$orderModel = Order::orderBy('created_at', 'DESC');
|
||||||
if ($request->input('trade_no')) {
|
|
||||||
$orderModel->where('trade_no', $request->input('trade_no'));
|
|
||||||
}
|
|
||||||
if ($request->input('is_commission')) {
|
if ($request->input('is_commission')) {
|
||||||
$orderModel->where('invite_user_id', '!=', NULL);
|
$orderModel->where('invite_user_id', '!=', NULL);
|
||||||
$orderModel->whereIn('status', [3, 4]);
|
$orderModel->whereNotIn('status', [0, 2]);
|
||||||
$orderModel->where('commission_balance', '>', 0);
|
$orderModel->where('commission_balance', '>', 0);
|
||||||
}
|
}
|
||||||
if ($request->input('id')) {
|
$this->filter($request, $orderModel);
|
||||||
$orderModel->where('id', $request->input('id'));
|
|
||||||
}
|
|
||||||
if ($request->input('user_id')) {
|
|
||||||
$orderModel->where('user_id', $request->input('user_id'));
|
|
||||||
}
|
|
||||||
$total = $orderModel->count();
|
$total = $orderModel->count();
|
||||||
$res = $orderModel->forPage($current, $pageSize)
|
$res = $orderModel->forPage($current, $pageSize)
|
||||||
->get();
|
->get();
|
||||||
|
78
app/Http/Controllers/Admin/PaymentController.php
Normal file
78
app/Http/Controllers/Admin/PaymentController.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Services\PaymentService;
|
||||||
|
use App\Utils\Helper;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Payment;
|
||||||
|
|
||||||
|
class PaymentController extends Controller
|
||||||
|
{
|
||||||
|
public function getPaymentMethods()
|
||||||
|
{
|
||||||
|
$methods = [];
|
||||||
|
foreach (glob(base_path('app//Payments') . '/*.php') as $file) {
|
||||||
|
array_push($methods, pathinfo($file)['filename']);
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => $methods
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetch()
|
||||||
|
{
|
||||||
|
$payments = Payment::all();
|
||||||
|
foreach ($payments as $k => $v) {
|
||||||
|
$payments[$k]['notify_url'] = url("/api/v1/guest/payment/notify/{$v->payment}/{$v->uuid}");
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => $payments
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPaymentForm(Request $request)
|
||||||
|
{
|
||||||
|
$paymentService = new PaymentService($request->input('payment'), $request->input('id'));
|
||||||
|
return response([
|
||||||
|
'data' => $paymentService->form()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->input('id')) {
|
||||||
|
$payment = Payment::find($request->input('id'));
|
||||||
|
if (!$payment) abort(500, '支付方式不存在');
|
||||||
|
try {
|
||||||
|
$payment->update($request->input());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
abort(500, '更新失败');
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (!Payment::create([
|
||||||
|
'name' => $request->input('name'),
|
||||||
|
'payment' => $request->input('payment'),
|
||||||
|
'config' => $request->input('config'),
|
||||||
|
'uuid' => Helper::guid()
|
||||||
|
])) {
|
||||||
|
abort(500, '保存失败');
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function drop(Request $request)
|
||||||
|
{
|
||||||
|
$payment = Payment::find($request->input('id'));
|
||||||
|
if (!$payment) abort(500, '支付方式不存在');
|
||||||
|
return response([
|
||||||
|
'data' => $payment->delete()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -2,13 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Admin\Server;
|
namespace App\Http\Controllers\Admin\Server;
|
||||||
|
|
||||||
use App\Http\Requests\Admin\ServerTrojanSort;
|
|
||||||
use App\Models\Plan;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\ServerGroup;
|
|
||||||
use App\Models\ServerShadowsocks;
|
use App\Models\ServerShadowsocks;
|
||||||
use App\Models\ServerTrojan;
|
use App\Models\ServerTrojan;
|
||||||
use App\Models\User;
|
|
||||||
use App\Services\ServerService;
|
use App\Services\ServerService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
@ -24,6 +20,7 @@ class ManageController extends Controller
|
|||||||
$serverService->getV2rayServers(),
|
$serverService->getV2rayServers(),
|
||||||
$serverService->getTrojanServers()
|
$serverService->getTrojanServers()
|
||||||
);
|
);
|
||||||
|
$serverService->mergeData($servers);
|
||||||
$tmp = array_column($servers, 'sort');
|
$tmp = array_column($servers, 'sort');
|
||||||
array_multisort($tmp, SORT_ASC, $servers);
|
array_multisort($tmp, SORT_ASC, $servers);
|
||||||
return response([
|
return response([
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
namespace App\Http\Controllers\Admin\Server;
|
namespace App\Http\Controllers\Admin\Server;
|
||||||
|
|
||||||
use App\Http\Requests\Admin\ServerShadowsocksSave;
|
use App\Http\Requests\Admin\ServerShadowsocksSave;
|
||||||
use App\Http\Requests\Admin\ServerShadowsocksSort;
|
|
||||||
use App\Http\Requests\Admin\ServerShadowsocksUpdate;
|
use App\Http\Requests\Admin\ServerShadowsocksUpdate;
|
||||||
use App\Models\ServerShadowsocks;
|
use App\Models\ServerShadowsocks;
|
||||||
use App\Utils\CacheKey;
|
use App\Services\ServerService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Server;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class ShadowsocksController extends Controller
|
class ShadowsocksController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
namespace App\Http\Controllers\Admin\Server;
|
namespace App\Http\Controllers\Admin\Server;
|
||||||
|
|
||||||
use App\Http\Requests\Admin\ServerTrojanSave;
|
use App\Http\Requests\Admin\ServerTrojanSave;
|
||||||
use App\Http\Requests\Admin\ServerTrojanSort;
|
|
||||||
use App\Http\Requests\Admin\ServerTrojanUpdate;
|
use App\Http\Requests\Admin\ServerTrojanUpdate;
|
||||||
use App\Services\ServerService;
|
use App\Services\ServerService;
|
||||||
use App\Utils\CacheKey;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\ServerTrojan;
|
use App\Models\ServerTrojan;
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class TrojanController extends Controller
|
class TrojanController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -3,15 +3,11 @@
|
|||||||
namespace App\Http\Controllers\Admin\Server;
|
namespace App\Http\Controllers\Admin\Server;
|
||||||
|
|
||||||
use App\Http\Requests\Admin\ServerV2raySave;
|
use App\Http\Requests\Admin\ServerV2raySave;
|
||||||
use App\Http\Requests\Admin\ServerV2raySort;
|
|
||||||
use App\Http\Requests\Admin\ServerV2rayUpdate;
|
use App\Http\Requests\Admin\ServerV2rayUpdate;
|
||||||
use App\Services\ServerService;
|
use App\Services\ServerService;
|
||||||
use App\Utils\CacheKey;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class V2rayController extends Controller
|
class V2rayController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@ class StatController extends Controller
|
|||||||
'data' => [
|
'data' => [
|
||||||
'month_income' => Order::where('created_at', '>=', strtotime(date('Y-m-1')))
|
'month_income' => Order::where('created_at', '>=', strtotime(date('Y-m-1')))
|
||||||
->where('created_at', '<', time())
|
->where('created_at', '<', time())
|
||||||
->whereIn('status', [3, 4])
|
->whereNotIn('status', [0, 2])
|
||||||
->sum('total_amount'),
|
->sum('total_amount'),
|
||||||
'month_register_total' => User::where('created_at', '>=', strtotime(date('Y-m-1')))
|
'month_register_total' => User::where('created_at', '>=', strtotime(date('Y-m-1')))
|
||||||
->where('created_at', '<', time())
|
->where('created_at', '<', time())
|
||||||
@ -35,16 +35,16 @@ class StatController extends Controller
|
|||||||
->count(),
|
->count(),
|
||||||
'commission_pendding_total' => Order::where('commission_status', 0)
|
'commission_pendding_total' => Order::where('commission_status', 0)
|
||||||
->where('invite_user_id', '!=', NULL)
|
->where('invite_user_id', '!=', NULL)
|
||||||
->where('status', [3, 4])
|
->whereNotIn('status', [0, 2])
|
||||||
->where('commission_balance', '>', 0)
|
->where('commission_balance', '>', 0)
|
||||||
->count(),
|
->count(),
|
||||||
'day_income' => Order::where('created_at', '>=', strtotime(date('Y-m-d')))
|
'day_income' => Order::where('created_at', '>=', strtotime(date('Y-m-d')))
|
||||||
->where('created_at', '<', time())
|
->where('created_at', '<', time())
|
||||||
->whereIn('status', [3, 4])
|
->whereNotIn('status', [0, 2])
|
||||||
->sum('total_amount'),
|
->sum('total_amount'),
|
||||||
'last_month_income' => Order::where('created_at', '>=', strtotime('-1 month', strtotime(date('Y-m-1'))))
|
'last_month_income' => Order::where('created_at', '>=', strtotime('-1 month', strtotime(date('Y-m-1'))))
|
||||||
->where('created_at', '<', strtotime(date('Y-m-1')))
|
->where('created_at', '<', strtotime(date('Y-m-1')))
|
||||||
->whereIn('status', [3, 4])
|
->whereNotIn('status', [0, 2])
|
||||||
->sum('total_amount')
|
->sum('total_amount')
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
@ -99,12 +99,13 @@ class StatController extends Controller
|
|||||||
'server_id',
|
'server_id',
|
||||||
'server_type',
|
'server_type',
|
||||||
'u',
|
'u',
|
||||||
'd'
|
'd',
|
||||||
|
DB::raw('(u+d) as total')
|
||||||
])
|
])
|
||||||
->where('record_at', '>=', $timestamp)
|
->where('record_at', '>=', $timestamp)
|
||||||
->where('record_type', 'd')
|
->where('record_type', 'd')
|
||||||
->limit(10)
|
->limit(10)
|
||||||
->orderBy('record_at', 'DESC')
|
->orderBy('total', 'DESC')
|
||||||
->get()
|
->get()
|
||||||
->toArray();
|
->toArray();
|
||||||
foreach ($statistics as $k => $v) {
|
foreach ($statistics as $k => $v) {
|
||||||
@ -113,7 +114,7 @@ class StatController extends Controller
|
|||||||
$statistics[$k]['server_name'] = $server['name'];
|
$statistics[$k]['server_name'] = $server['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$statistics[$k]['total'] = ($v['u'] + $v['d']) / 1073741824;
|
$statistics[$k]['total'] = $statistics[$k]['total'] / 1073741824;
|
||||||
}
|
}
|
||||||
array_multisort(array_column($statistics, 'total'), SORT_DESC, $statistics);
|
array_multisort(array_column($statistics, 'total'), SORT_DESC, $statistics);
|
||||||
return response([
|
return response([
|
||||||
|
@ -265,4 +265,30 @@ class UserController extends Controller
|
|||||||
'data' => true
|
'data' => true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setInviteUser(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'user_id' => 'required|integer',
|
||||||
|
'invite_user' => 'required',
|
||||||
|
], [
|
||||||
|
'user_id.required' => '用户ID不能为空',
|
||||||
|
'user_id.integer' => '用户ID参数有误',
|
||||||
|
'invite_user.required' => '邀请人不能为空'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::find($request->input('user_id'));
|
||||||
|
if (!$user) abort(500, '用户不存在');
|
||||||
|
if (strpos($request->input('invite_user'), '@') !== -1) {
|
||||||
|
$inviteUser = User::where('email', $request->input('invite_user'))->first();
|
||||||
|
} else {
|
||||||
|
$inviteUser = User::find($request->input('invite_user'));
|
||||||
|
}
|
||||||
|
if (!$inviteUser) abort(500, '邀请人不存在');
|
||||||
|
$user->invite_user_id = $inviteUser->id;
|
||||||
|
|
||||||
|
return response([
|
||||||
|
'data' => $user->save()
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
18
app/Http/Controllers/Guest/CommController.php
Normal file
18
app/Http/Controllers/Guest/CommController.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Guest;
|
||||||
|
|
||||||
|
use App\Utils\Dict;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class CommController extends Controller
|
||||||
|
{
|
||||||
|
public function config()
|
||||||
|
{
|
||||||
|
return response([
|
||||||
|
'data' => [
|
||||||
|
'tos_url' => config('v2board.tos_url')
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -1,192 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Guest;
|
|
||||||
|
|
||||||
use App\Services\OrderService;
|
|
||||||
use App\Services\TelegramService;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\Order;
|
|
||||||
use Library\Epay;
|
|
||||||
use Omnipay\Omnipay;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Library\BitpayX;
|
|
||||||
use Library\MGate;
|
|
||||||
|
|
||||||
class OrderController extends Controller
|
|
||||||
{
|
|
||||||
public function alipayNotify(Request $request)
|
|
||||||
{
|
|
||||||
if (!(int)config('v2board.alipay_enable')) {
|
|
||||||
die('fail');
|
|
||||||
}
|
|
||||||
// Log::info('alipayNotifyData: ' . json_encode($_POST));
|
|
||||||
$gateway = Omnipay::create('Alipay_AopF2F');
|
|
||||||
$gateway->setSignType('RSA2'); //RSA/RSA2
|
|
||||||
$gateway->setAppId(config('v2board.alipay_appid'));
|
|
||||||
$gateway->setPrivateKey(config('v2board.alipay_privkey')); // 可以是路径,也可以是密钥内容
|
|
||||||
$gateway->setAlipayPublicKey(config('v2board.alipay_pubkey')); // 可以是路径,也可以是密钥内容
|
|
||||||
$request = $gateway->completePurchase();
|
|
||||||
$request->setParams($_POST); //Optional
|
|
||||||
try {
|
|
||||||
/** @var \Omnipay\Alipay\Responses\AopCompletePurchaseResponse $response */
|
|
||||||
$response = $request->send();
|
|
||||||
|
|
||||||
if ($response->isPaid()) {
|
|
||||||
/**
|
|
||||||
* Payment is successful
|
|
||||||
*/
|
|
||||||
if (!$this->handle($_POST['out_trade_no'], $_POST['trade_no'])) {
|
|
||||||
abort(500, 'fail');
|
|
||||||
}
|
|
||||||
|
|
||||||
die('success'); //The response should be 'success' only
|
|
||||||
} else {
|
|
||||||
/**
|
|
||||||
* Payment is not successful
|
|
||||||
*/
|
|
||||||
die('fail');
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
/**
|
|
||||||
* Payment is not successful
|
|
||||||
*/
|
|
||||||
die('fail');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function stripeNotify(Request $request)
|
|
||||||
{
|
|
||||||
// Log::info('stripeNotifyData: ' . json_encode($request->input()));
|
|
||||||
|
|
||||||
if (!(int)config('v2board.stripe_alipay_enable') && !(int)config('v2board.stripe_wepay_enable')) {
|
|
||||||
die('fail');
|
|
||||||
}
|
|
||||||
\Stripe\Stripe::setApiKey(config('v2board.stripe_sk_live'));
|
|
||||||
try {
|
|
||||||
$event = \Stripe\Webhook::constructEvent(
|
|
||||||
file_get_contents('php://input'),
|
|
||||||
$_SERVER['HTTP_STRIPE_SIGNATURE'],
|
|
||||||
config('v2board.stripe_webhook_key')
|
|
||||||
);
|
|
||||||
} catch (\Stripe\Error\SignatureVerification $e) {
|
|
||||||
abort(400);
|
|
||||||
}
|
|
||||||
switch ($event->type) {
|
|
||||||
case 'source.chargeable':
|
|
||||||
$object = $event->data->object;
|
|
||||||
\Stripe\Charge::create([
|
|
||||||
'amount' => $object->amount,
|
|
||||||
'currency' => $object->currency,
|
|
||||||
'source' => $object->id,
|
|
||||||
'metadata' => json_decode($object->metadata, true)
|
|
||||||
]);
|
|
||||||
die('success');
|
|
||||||
break;
|
|
||||||
case 'charge.succeeded':
|
|
||||||
$object = $event->data->object;
|
|
||||||
if ($object->status === 'succeeded') {
|
|
||||||
$metaData = isset($object->metadata->out_trade_no) ? $object->metadata : $object->source->metadata;
|
|
||||||
$tradeNo = $metaData->out_trade_no;
|
|
||||||
if (!$tradeNo) {
|
|
||||||
abort(500, 'trade no is not found in metadata');
|
|
||||||
}
|
|
||||||
if (!$this->handle($tradeNo, $object->balance_transaction)) {
|
|
||||||
abort(500, 'fail');
|
|
||||||
}
|
|
||||||
die('success');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort(500, 'event is not support');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function bitpayXNotify(Request $request)
|
|
||||||
{
|
|
||||||
if (!(int)config('v2board.bitpayx_enable')) {
|
|
||||||
die('fail');
|
|
||||||
}
|
|
||||||
$inputString = file_get_contents('php://input', 'r');
|
|
||||||
// Log::info('bitpayXNotifyData: ' . $inputString);
|
|
||||||
$inputStripped = str_replace(array("\r", "\n", "\t", "\v"), '', $inputString);
|
|
||||||
$inputJSON = json_decode($inputStripped, true); //convert JSON into array
|
|
||||||
|
|
||||||
$bitpayX = new BitpayX(config('v2board.bitpayx_appsecret'));
|
|
||||||
$params = [
|
|
||||||
'status' => $inputJSON['status'],
|
|
||||||
'order_id' => $inputJSON['order_id'],
|
|
||||||
'merchant_order_id' => $inputJSON['merchant_order_id'],
|
|
||||||
'price_amount' => $inputJSON['price_amount'],
|
|
||||||
'price_currency' => $inputJSON['price_currency'],
|
|
||||||
'pay_amount' => $inputJSON['pay_amount'],
|
|
||||||
'pay_currency' => $inputJSON['pay_currency'],
|
|
||||||
'created_at_t' => $inputJSON['created_at_t']
|
|
||||||
];
|
|
||||||
$strToSign = $bitpayX->prepareSignId($inputJSON['merchant_order_id']);
|
|
||||||
if (!$bitpayX->verify($strToSign, $inputJSON['token'])) {
|
|
||||||
abort(500, 'sign error');
|
|
||||||
}
|
|
||||||
if ($params['status'] !== 'PAID') {
|
|
||||||
abort(500, 'order is not paid');
|
|
||||||
}
|
|
||||||
if (!$this->handle($params['merchant_order_id'], $params['order_id'])) {
|
|
||||||
abort(500, 'order process fail');
|
|
||||||
}
|
|
||||||
die(json_encode([
|
|
||||||
'status' => 200
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function mgateNotify(Request $request)
|
|
||||||
{
|
|
||||||
if (!(int)config('v2board.mgate_enable')) {
|
|
||||||
die('fail');
|
|
||||||
}
|
|
||||||
$mgate = new MGate(config('v2board.mgate_url'), config('v2board.mgate_app_id'), config('v2board.mgate_app_secret'));
|
|
||||||
if (!$mgate->verify($request->input())) {
|
|
||||||
abort(500, 'fail');
|
|
||||||
}
|
|
||||||
if (!$this->handle($request->input('out_trade_no'), $request->input('trade_no'))) {
|
|
||||||
abort(500, 'fail');
|
|
||||||
}
|
|
||||||
die('success');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function epayNotify(Request $request)
|
|
||||||
{
|
|
||||||
if (!(int)config('v2board.epay_enable')) {
|
|
||||||
die('fail');
|
|
||||||
}
|
|
||||||
$epay = new Epay(config('v2board.epay_url'), config('v2board.epay_pid'), config('v2board.epay_key'));
|
|
||||||
if (!$epay->verify($request->input())) {
|
|
||||||
abort(500, 'fail');
|
|
||||||
}
|
|
||||||
if (!$this->handle($request->input('out_trade_no'), $request->input('trade_no'))) {
|
|
||||||
abort(500, 'fail');
|
|
||||||
}
|
|
||||||
die('success');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function handle($tradeNo, $callbackNo)
|
|
||||||
{
|
|
||||||
$order = Order::where('trade_no', $tradeNo)->first();
|
|
||||||
if ($order->status === 1) return true;
|
|
||||||
if (!$order) {
|
|
||||||
abort(500, 'order is not found');
|
|
||||||
}
|
|
||||||
$orderService = new OrderService($order);
|
|
||||||
if (!$orderService->success($callbackNo)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$telegramService = new TelegramService();
|
|
||||||
$message = sprintf(
|
|
||||||
"💰成功收款%s元\n———————————————\n订单号:%s",
|
|
||||||
$order->total_amount / 100,
|
|
||||||
$order->trade_no
|
|
||||||
);
|
|
||||||
$telegramService->sendMessageWithAdmin($message);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
49
app/Http/Controllers/Guest/PaymentController.php
Normal file
49
app/Http/Controllers/Guest/PaymentController.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Guest;
|
||||||
|
|
||||||
|
use App\Models\Order;
|
||||||
|
use App\Services\OrderService;
|
||||||
|
use App\Services\PaymentService;
|
||||||
|
use App\Services\TelegramService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class PaymentController extends Controller
|
||||||
|
{
|
||||||
|
public function notify($method, $uuid, Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$paymentService = new PaymentService($method, null, $uuid);
|
||||||
|
$verify = $paymentService->notify($request->input());
|
||||||
|
if (!$verify) abort(500, 'verify error');
|
||||||
|
if (!$this->handle($verify['trade_no'], $verify['callback_no'])) {
|
||||||
|
abort(500, 'handle error');
|
||||||
|
}
|
||||||
|
die('success');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
abort(500, 'fail');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handle($tradeNo, $callbackNo)
|
||||||
|
{
|
||||||
|
$order = Order::where('trade_no', $tradeNo)->first();
|
||||||
|
if (!$order) {
|
||||||
|
abort(500, 'order is not found');
|
||||||
|
}
|
||||||
|
if ($order->status === 1) return true;
|
||||||
|
$orderService = new OrderService($order);
|
||||||
|
if (!$orderService->success($callbackNo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$telegramService = new TelegramService();
|
||||||
|
$message = sprintf(
|
||||||
|
"💰成功收款%s元\n———————————————\n订单号:%s",
|
||||||
|
$order->total_amount / 100,
|
||||||
|
$order->trade_no
|
||||||
|
);
|
||||||
|
$telegramService->sendMessageWithAdmin($message);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -131,7 +131,8 @@ class AuthController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'token' => $user->token
|
'token' => $user->token,
|
||||||
|
'auth_data' => base64_encode("{$user->email}:{$user->password}")
|
||||||
];
|
];
|
||||||
$request->session()->put('email', $user->email);
|
$request->session()->put('email', $user->email);
|
||||||
$request->session()->put('id', $user->id);
|
$request->session()->put('id', $user->id);
|
||||||
@ -202,7 +203,10 @@ class AuthController extends Controller
|
|||||||
|
|
||||||
public function getQuickLoginUrl(Request $request)
|
public function getQuickLoginUrl(Request $request)
|
||||||
{
|
{
|
||||||
$user = User::where('token', $request->input('token'))->first();
|
$authData = explode(':', base64_decode($request->input('auth_data')));
|
||||||
|
$user = User::where('email', $authData[0])
|
||||||
|
->where('password', $authData[1])
|
||||||
|
->first();
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
abort(500, '令牌有误');
|
abort(500, '令牌有误');
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ class DeepbworkController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
|
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_PUSH_AT', $server->id), time(), 3600);
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
|
@ -67,6 +67,7 @@ class PoseidonController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
|
Cache::put(CacheKey::get('SERVER_V2RAY_LAST_PUSH_AT', $server->id), time(), 3600);
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
foreach ($data as $item) {
|
foreach ($data as $item) {
|
||||||
$u = $item['u'] * $server->rate;
|
$u = $item['u'] * $server->rate;
|
||||||
|
@ -70,6 +70,7 @@ class ShadowsocksTidalabController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
|
Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_LAST_PUSH_AT', $server->id), time(), 3600);
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
|
@ -71,6 +71,7 @@ class TrojanTidalabController extends Controller
|
|||||||
$data = file_get_contents('php://input');
|
$data = file_get_contents('php://input');
|
||||||
$data = json_decode($data, true);
|
$data = json_decode($data, true);
|
||||||
Cache::put(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server->id), count($data), 3600);
|
Cache::put(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server->id), count($data), 3600);
|
||||||
|
Cache::put(CacheKey::get('SERVER_TROJAN_LAST_PUSH_AT', $server->id), time(), 3600);
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\User;
|
namespace App\Http\Controllers\User;
|
||||||
|
|
||||||
|
use App\Models\Payment;
|
||||||
use App\Utils\Dict;
|
use App\Utils\Dict;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
@ -19,4 +20,16 @@ class CommController extends Controller
|
|||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getStripePublicKey(Request $request)
|
||||||
|
{
|
||||||
|
$payment = Payment::where('id', $request->input('id'))
|
||||||
|
->where('payment', 'StripeCredit')
|
||||||
|
->first();
|
||||||
|
if (!$payment) abort(500, 'payment is not found');
|
||||||
|
$config = json_decode($payment->config, true);
|
||||||
|
return response([
|
||||||
|
'data' => $config['stripe_pk_live']
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,14 @@ class KnowledgeController extends Controller
|
|||||||
if (!$knowledge) abort(500, __('user.knowledge.fetch.knowledge_not_exist'));
|
if (!$knowledge) abort(500, __('user.knowledge.fetch.knowledge_not_exist'));
|
||||||
$user = User::find($request->session()->get('id'));
|
$user = User::find($request->session()->get('id'));
|
||||||
$userService = new UserService();
|
$userService = new UserService();
|
||||||
$appleId = $userService->isAvailable($user) ? config('v2board.apple_id') : __('user.knowledge.fetch.apple_id_must_be_plan');
|
if ($userService->isAvailable($user)) {
|
||||||
$appleIdPassword = $userService->isAvailable($user) ? config('v2board.apple_id_password') : __('user.knowledge.fetch.apple_id_must_be_plan');
|
$appleId = config('v2board.apple_id');
|
||||||
|
$appleIdPassword = config('v2board.apple_id_password');
|
||||||
|
} else {
|
||||||
|
$appleId = __('user.knowledge.fetch.apple_id_must_be_plan');
|
||||||
|
$appleIdPassword = __('user.knowledge.fetch.apple_id_must_be_plan');
|
||||||
|
$this->formatAccessData($knowledge['body']);
|
||||||
|
}
|
||||||
$subscribeUrl = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'];
|
$subscribeUrl = config('v2board.subscribe_url', config('v2board.app_url', env('APP_URL'))) . '/api/v1/client/subscribe?token=' . $user['token'];
|
||||||
$knowledge['body'] = str_replace('{{siteName}}', config('v2board.app_name', 'V2Board'), $knowledge['body']);
|
$knowledge['body'] = str_replace('{{siteName}}', config('v2board.app_name', 'V2Board'), $knowledge['body']);
|
||||||
$knowledge['body'] = str_replace('{{appleId}}', $appleId, $knowledge['body']);
|
$knowledge['body'] = str_replace('{{appleId}}', $appleId, $knowledge['body']);
|
||||||
@ -51,4 +57,13 @@ class KnowledgeController extends Controller
|
|||||||
'data' => $knowledges
|
'data' => $knowledges
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function formatAccessData(&$body)
|
||||||
|
{
|
||||||
|
function getBetween($input, $start, $end){$substr = substr($input, strlen($start)+strpos($input, $start),(strlen($input) - strpos($input, $end))*(-1));return $substr;}
|
||||||
|
$accessData = getBetween($body, '<!--access start-->', '<!--access end-->');
|
||||||
|
if ($accessData) {
|
||||||
|
$body = str_replace($accessData, '<div class="v2board-no-access">'. __('user.knowledge.formatAccessData.no_access') .'</div>', $body);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ namespace App\Http\Controllers\User;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\User\OrderSave;
|
use App\Http\Requests\User\OrderSave;
|
||||||
|
use App\Models\Payment;
|
||||||
use App\Services\CouponService;
|
use App\Services\CouponService;
|
||||||
use App\Services\OrderService;
|
use App\Services\OrderService;
|
||||||
|
use App\Services\PaymentService;
|
||||||
use App\Services\UserService;
|
use App\Services\UserService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
@ -40,7 +42,7 @@ class OrderController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response([
|
return response([
|
||||||
'data' => $order
|
'data' => $order->makeHidden(['id', 'user_id'])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,71 +177,20 @@ class OrderController extends Controller
|
|||||||
'data' => true
|
'data' => true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
switch ($method) {
|
$payment = Payment::find($method);
|
||||||
// return type => 0: QRCode / 1: URL / 2: No action
|
if (!$payment || $payment->enable !== 1) abort(500, __('user.order.checkout.pay_method_not_use'));
|
||||||
case 0:
|
$paymentService = new PaymentService($payment->payment, $payment->id);
|
||||||
// alipayF2F
|
$result = $paymentService->pay([
|
||||||
if (!(int)config('v2board.alipay_enable')) {
|
'trade_no' => $tradeNo,
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
'total_amount' => $order->total_amount,
|
||||||
}
|
'user_id' => $order->user_id,
|
||||||
return response([
|
'stripe_token' => $request->input('token')
|
||||||
'type' => 0,
|
]);
|
||||||
'data' => $this->alipayF2F($tradeNo, $order->total_amount)
|
$order->update(['payment_id' => $method]);
|
||||||
]);
|
return response([
|
||||||
case 2:
|
'type' => $result['type'],
|
||||||
// stripeAlipay
|
'data' => $result['data']
|
||||||
if (!(int)config('v2board.stripe_alipay_enable')) {
|
]);
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'type' => 1,
|
|
||||||
'data' => $this->stripeAlipay($order)
|
|
||||||
]);
|
|
||||||
case 3:
|
|
||||||
// stripeWepay
|
|
||||||
if (!(int)config('v2board.stripe_wepay_enable')) {
|
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'type' => 0,
|
|
||||||
'data' => $this->stripeWepay($order)
|
|
||||||
]);
|
|
||||||
case 4:
|
|
||||||
// bitpayX
|
|
||||||
if (!(int)config('v2board.bitpayx_enable')) {
|
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'type' => 1,
|
|
||||||
'data' => $this->bitpayX($order)
|
|
||||||
]);
|
|
||||||
case 5:
|
|
||||||
if (!(int)config('v2board.mgate_enable')) {
|
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'type' => 1,
|
|
||||||
'data' => $this->mgate($order)
|
|
||||||
]);
|
|
||||||
case 6:
|
|
||||||
if (!(int)config('v2board.stripe_card_enable')) {
|
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'type' => 2,
|
|
||||||
'data' => $this->stripeCard($order, $request->input('token'))
|
|
||||||
]);
|
|
||||||
case 7:
|
|
||||||
if (!(int)config('v2board.epay_enable')) {
|
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
|
||||||
}
|
|
||||||
return response([
|
|
||||||
'type' => 1,
|
|
||||||
'data' => $this->epay($order)
|
|
||||||
]);
|
|
||||||
default:
|
|
||||||
abort(500, __('user.order.checkout.pay_method_not_use'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function check(Request $request)
|
public function check(Request $request)
|
||||||
@ -258,65 +209,15 @@ class OrderController extends Controller
|
|||||||
|
|
||||||
public function getPaymentMethod()
|
public function getPaymentMethod()
|
||||||
{
|
{
|
||||||
$data = [];
|
$methods = Payment::select([
|
||||||
if ((int)config('v2board.alipay_enable')) {
|
'id',
|
||||||
$alipayF2F = new \StdClass();
|
'name',
|
||||||
$alipayF2F->name = '支付宝';
|
'payment'
|
||||||
$alipayF2F->method = 0;
|
])
|
||||||
$alipayF2F->icon = 'alipay';
|
->where('enable', 1)->get();
|
||||||
array_push($data, $alipayF2F);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)config('v2board.stripe_alipay_enable')) {
|
|
||||||
$stripeAlipay = new \StdClass();
|
|
||||||
$stripeAlipay->name = '支付宝';
|
|
||||||
$stripeAlipay->method = 2;
|
|
||||||
$stripeAlipay->icon = 'alipay';
|
|
||||||
array_push($data, $stripeAlipay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)config('v2board.stripe_wepay_enable')) {
|
|
||||||
$stripeWepay = new \StdClass();
|
|
||||||
$stripeWepay->name = '微信';
|
|
||||||
$stripeWepay->method = 3;
|
|
||||||
$stripeWepay->icon = 'wechat';
|
|
||||||
array_push($data, $stripeWepay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)config('v2board.bitpayx_enable')) {
|
|
||||||
$bitpayX = new \StdClass();
|
|
||||||
$bitpayX->name = config('v2board.bitpayx_name', '在线支付');
|
|
||||||
$bitpayX->method = 4;
|
|
||||||
$bitpayX->icon = 'wallet';
|
|
||||||
array_push($data, $bitpayX);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)config('v2board.mgate_enable')) {
|
|
||||||
$obj = new \StdClass();
|
|
||||||
$obj->name = config('v2board.mgate_name', '在线支付');
|
|
||||||
$obj->method = 5;
|
|
||||||
$obj->icon = 'wallet';
|
|
||||||
array_push($data, $obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)config('v2board.stripe_card_enable')) {
|
|
||||||
$obj = new \StdClass();
|
|
||||||
$obj->name = '信用卡';
|
|
||||||
$obj->method = 6;
|
|
||||||
$obj->icon = 'card';
|
|
||||||
array_push($data, $obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)config('v2board.epay_enable')) {
|
|
||||||
$obj = new \StdClass();
|
|
||||||
$obj->name = config('v2board.epay_name', '在线支付');
|
|
||||||
$obj->method = 7;
|
|
||||||
$obj->icon = 'wallet';
|
|
||||||
array_push($data, $obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response([
|
return response([
|
||||||
'data' => $data
|
'data' => $methods
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,157 +243,4 @@ class OrderController extends Controller
|
|||||||
'data' => true
|
'data' => true
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function alipayF2F($tradeNo, $totalAmount)
|
|
||||||
{
|
|
||||||
$gateway = Omnipay::create('Alipay_AopF2F');
|
|
||||||
$gateway->setSignType('RSA2'); //RSA/RSA2
|
|
||||||
$gateway->setAppId(config('v2board.alipay_appid'));
|
|
||||||
$gateway->setPrivateKey(config('v2board.alipay_privkey')); // 可以是路径,也可以是密钥内容
|
|
||||||
$gateway->setAlipayPublicKey(config('v2board.alipay_pubkey')); // 可以是路径,也可以是密钥内容
|
|
||||||
$gateway->setNotifyUrl(url('/api/v1/guest/order/alipayNotify'));
|
|
||||||
$request = $gateway->purchase();
|
|
||||||
$request->setBizContent([
|
|
||||||
'subject' => config('v2board.app_name', 'V2Board') . ' - 订阅',
|
|
||||||
'out_trade_no' => $tradeNo,
|
|
||||||
'total_amount' => $totalAmount / 100
|
|
||||||
]);
|
|
||||||
/** @var \Omnipay\Alipay\Responses\AopTradePreCreateResponse $response */
|
|
||||||
$response = $request->send();
|
|
||||||
$result = $response->getAlipayResponse();
|
|
||||||
if ($result['code'] !== '10000') {
|
|
||||||
abort(500, $result['sub_msg']);
|
|
||||||
}
|
|
||||||
// 获取收款二维码内容
|
|
||||||
return $response->getQrCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function stripeAlipay($order)
|
|
||||||
{
|
|
||||||
$currency = config('v2board.stripe_currency', 'hkd');
|
|
||||||
$exchange = Helper::exchange('CNY', strtoupper($currency));
|
|
||||||
if (!$exchange) {
|
|
||||||
abort(500, __('user.order.stripeAlipay.currency_convert_timeout'));
|
|
||||||
}
|
|
||||||
Stripe::setApiKey(config('v2board.stripe_sk_live'));
|
|
||||||
$source = Source::create([
|
|
||||||
'amount' => floor($order->total_amount * $exchange),
|
|
||||||
'currency' => $currency,
|
|
||||||
'type' => 'alipay',
|
|
||||||
'statement_descriptor' => $order->trade_no,
|
|
||||||
'metadata' => [
|
|
||||||
'user_id' => $order->user_id,
|
|
||||||
'out_trade_no' => $order->trade_no,
|
|
||||||
'identifier' => ''
|
|
||||||
],
|
|
||||||
'redirect' => [
|
|
||||||
'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order'
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
if (!$source['redirect']['url']) {
|
|
||||||
abort(500, __('user.order.stripeAlipay.gateway_request_failed'));
|
|
||||||
}
|
|
||||||
return $source['redirect']['url'];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function stripeWepay($order)
|
|
||||||
{
|
|
||||||
$currency = config('v2board.stripe_currency', 'hkd');
|
|
||||||
$exchange = Helper::exchange('CNY', strtoupper($currency));
|
|
||||||
if (!$exchange) {
|
|
||||||
abort(500, __('user.order.stripeWepay.currency_convert_timeout'));
|
|
||||||
}
|
|
||||||
Stripe::setApiKey(config('v2board.stripe_sk_live'));
|
|
||||||
$source = Source::create([
|
|
||||||
'amount' => floor($order->total_amount * $exchange),
|
|
||||||
'currency' => $currency,
|
|
||||||
'type' => 'wechat',
|
|
||||||
'metadata' => [
|
|
||||||
'user_id' => $order->user_id,
|
|
||||||
'out_trade_no' => $order->trade_no,
|
|
||||||
'identifier' => ''
|
|
||||||
],
|
|
||||||
'redirect' => [
|
|
||||||
'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order'
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
if (!$source['wechat']['qr_code_url']) {
|
|
||||||
abort(500, __('user.order.stripeWepay.gateway_request_failed'));
|
|
||||||
}
|
|
||||||
return $source['wechat']['qr_code_url'];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function stripeCard($order, string $token)
|
|
||||||
{
|
|
||||||
$currency = config('v2board.stripe_currency', 'hkd');
|
|
||||||
$exchange = Helper::exchange('CNY', strtoupper($currency));
|
|
||||||
if (!$exchange) {
|
|
||||||
abort(500, __('user.order.stripeCard.currency_convert_timeout'));
|
|
||||||
}
|
|
||||||
Stripe::setApiKey(config('v2board.stripe_sk_live'));
|
|
||||||
try {
|
|
||||||
$charge = \Stripe\Charge::create([
|
|
||||||
'amount' => floor($order->total_amount * $exchange),
|
|
||||||
'currency' => $currency,
|
|
||||||
'source' => $token,
|
|
||||||
'metadata' => [
|
|
||||||
'user_id' => $order->user_id,
|
|
||||||
'out_trade_no' => $order->trade_no,
|
|
||||||
'identifier' => ''
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
abort(500, __('user.order.stripeCard.was_problem'));
|
|
||||||
}
|
|
||||||
info($charge);
|
|
||||||
if (!$charge->paid) {
|
|
||||||
abort(500, __('user.order.stripeCard.deduction_failed'));
|
|
||||||
}
|
|
||||||
return $charge->paid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function bitpayX($order)
|
|
||||||
{
|
|
||||||
$bitpayX = new BitpayX(config('v2board.bitpayx_appsecret'));
|
|
||||||
$params = [
|
|
||||||
'merchant_order_id' => $order->trade_no,
|
|
||||||
'price_amount' => $order->total_amount / 100,
|
|
||||||
'price_currency' => 'CNY',
|
|
||||||
'title' => '支付单号:' . $order->trade_no,
|
|
||||||
'description' => '充值:' . $order->total_amount / 100 . ' 元',
|
|
||||||
'callback_url' => url('/api/v1/guest/order/bitpayXNotify'),
|
|
||||||
'success_url' => config('v2board.app_url', env('APP_URL')) . '/#/order',
|
|
||||||
'cancel_url' => config('v2board.app_url', env('APP_URL')) . '/#/order'
|
|
||||||
];
|
|
||||||
$strToSign = $bitpayX->prepareSignId($params['merchant_order_id']);
|
|
||||||
$params['token'] = $bitpayX->sign($strToSign);
|
|
||||||
$result = $bitpayX->mprequest($params);
|
|
||||||
// Log::info('bitpayXSubmit: ' . json_encode($result));
|
|
||||||
return isset($result['payment_url']) ? $result['payment_url'] : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function mgate($order)
|
|
||||||
{
|
|
||||||
$mgate = new MGate(config('v2board.mgate_url'), config('v2board.mgate_app_id'), config('v2board.mgate_app_secret'));
|
|
||||||
$result = $mgate->pay([
|
|
||||||
'app_id' => config('v2board.mgate_app_id'),
|
|
||||||
'out_trade_no' => $order->trade_no,
|
|
||||||
'total_amount' => $order->total_amount,
|
|
||||||
'notify_url' => url('/api/v1/guest/order/mgateNotify'),
|
|
||||||
'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order'
|
|
||||||
]);
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function epay($order)
|
|
||||||
{
|
|
||||||
$epay = new Epay(config('v2board.epay_url'), config('v2board.epay_pid'), config('v2board.epay_key'));
|
|
||||||
return $epay->pay([
|
|
||||||
'money' => $order->total_amount / 100,
|
|
||||||
'name' => $order->trade_no,
|
|
||||||
'notify_url' => url('/api/v1/guest/order/epayNotify'),
|
|
||||||
'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order',
|
|
||||||
'out_trade_no' => $order->trade_no
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,11 @@ class User
|
|||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
if ($request->input('access_token')) {
|
if ($request->input('auth_data')) {
|
||||||
$user = \App\Models\User::where('token', $request->input('access_token'))->first();
|
$authData = explode(':', base64_decode($request->input('auth_data')));
|
||||||
|
$user = \App\Models\User::where('password', $authData[1])
|
||||||
|
->where('email', $authData[0])
|
||||||
|
->first();
|
||||||
if ($user) {
|
if ($user) {
|
||||||
$request->session()->put('email', $user->email);
|
$request->session()->put('email', $user->email);
|
||||||
$request->session()->put('id', $user->id);
|
$request->session()->put('id', $user->id);
|
||||||
|
@ -41,6 +41,7 @@ class ConfigSave extends FormRequest
|
|||||||
'recaptcha_enable' => 'in:0,1',
|
'recaptcha_enable' => 'in:0,1',
|
||||||
'recaptcha_key' => '',
|
'recaptcha_key' => '',
|
||||||
'recaptcha_site_key' => '',
|
'recaptcha_site_key' => '',
|
||||||
|
'tos_url' => 'nullable|url',
|
||||||
// subscribe
|
// subscribe
|
||||||
'plan_change_enable' => 'in:0,1',
|
'plan_change_enable' => 'in:0,1',
|
||||||
'reset_traffic_method' => 'in:0,1',
|
'reset_traffic_method' => 'in:0,1',
|
||||||
@ -87,6 +88,8 @@ class ConfigSave extends FormRequest
|
|||||||
'frontend_theme_color' => 'in:default,darkblue,black',
|
'frontend_theme_color' => 'in:default,darkblue,black',
|
||||||
'frontend_background_url' => 'nullable|url',
|
'frontend_background_url' => 'nullable|url',
|
||||||
'frontend_admin_path' => '',
|
'frontend_admin_path' => '',
|
||||||
|
'frontend_customer_service_method' => '',
|
||||||
|
'frontend_customer_service_id' => '',
|
||||||
// tutorial
|
// tutorial
|
||||||
'apple_id' => 'nullable|email',
|
'apple_id' => 'nullable|email',
|
||||||
'apple_id_password' => '',
|
'apple_id_password' => '',
|
||||||
@ -118,7 +121,9 @@ class ConfigSave extends FormRequest
|
|||||||
// illiteracy prompt
|
// illiteracy prompt
|
||||||
return [
|
return [
|
||||||
'app_url.url' => '站点URL格式不正确,必须携带http(s)://',
|
'app_url.url' => '站点URL格式不正确,必须携带http(s)://',
|
||||||
'subscribe_url.url' => '订阅URL格式不正确,必须携带http(s)://'
|
'subscribe_url.url' => '订阅URL格式不正确,必须携带http(s)://',
|
||||||
|
'server_token.min' => '通讯密钥长度必须大于16位',
|
||||||
|
'tos_url.url' => '服务条款URL格式不正确'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
app/Http/Requests/Admin/OrderFetch.php
Normal file
32
app/Http/Requests/Admin/OrderFetch.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Admin;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class OrderFetch extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'filter.*.key' => 'required|in:email,trade_no,status,commission_status,user_id,invite_user_id',
|
||||||
|
'filter.*.condition' => 'required|in:>,<,=,>=,<=,模糊,!=',
|
||||||
|
'filter.*.value' => ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'filter.*.key.required' => '过滤键不能为空',
|
||||||
|
'filter.*.key.in' => '过滤键参数有误',
|
||||||
|
'filter.*.condition.required' => '过滤条件不能为空',
|
||||||
|
'filter.*.condition.in' => '过滤条件参数有误',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ class UserFetch extends FormRequest
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'filter.*.key' => 'required|in:id,email,transfer_enable,d,expired_at,uuid,token,invite_by_email,invite_user_id,plan_id,banned',
|
'filter.*.key' => 'required|in:id,email,transfer_enable,d,expired_at,uuid,token,invite_by_email,invite_user_id,plan_id,banned',
|
||||||
'filter.*.condition' => 'required|in:>,<,=,>=,<=,模糊',
|
'filter.*.condition' => 'required|in:>,<,=,>=,<=,模糊,!=',
|
||||||
'filter.*.value' => 'required'
|
'filter.*.value' => 'required'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -23,6 +23,11 @@ class UserFetch extends FormRequest
|
|||||||
public function messages()
|
public function messages()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'filter.*.key.required' => '过滤键不能为空',
|
||||||
|
'filter.*.key.in' => '过滤键参数有误',
|
||||||
|
'filter.*.condition.required' => '过滤条件不能为空',
|
||||||
|
'filter.*.condition.in' => '过滤条件参数有误',
|
||||||
|
'filter.*.value.required' => '过滤值不能为空'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ class UserUpdate extends FormRequest
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
'password' => 'nullable',
|
'password' => 'nullable|min:8',
|
||||||
'transfer_enable' => 'numeric',
|
'transfer_enable' => 'numeric',
|
||||||
'expired_at' => 'nullable|integer',
|
'expired_at' => 'nullable|integer',
|
||||||
'banned' => 'required|in:0,1',
|
'banned' => 'required|in:0,1',
|
||||||
@ -57,7 +57,8 @@ class UserUpdate extends FormRequest
|
|||||||
'u.integer' => '上行流量格式不正确',
|
'u.integer' => '上行流量格式不正确',
|
||||||
'd.integer' => '下行流量格式不正确',
|
'd.integer' => '下行流量格式不正确',
|
||||||
'balance.integer' => '余额格式不正确',
|
'balance.integer' => '余额格式不正确',
|
||||||
'commission_balance.integer' => '佣金格式不正确'
|
'commission_balance.integer' => '佣金格式不正确',
|
||||||
|
'password.min' => '密码长度最小8位'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ class AdminRoute
|
|||||||
$router->post('/user/sendMail', 'Admin\\UserController@sendMail');
|
$router->post('/user/sendMail', 'Admin\\UserController@sendMail');
|
||||||
$router->post('/user/ban', 'Admin\\UserController@ban');
|
$router->post('/user/ban', 'Admin\\UserController@ban');
|
||||||
$router->post('/user/resetSecret', 'Admin\\UserController@resetSecret');
|
$router->post('/user/resetSecret', 'Admin\\UserController@resetSecret');
|
||||||
|
$router->post('/user/setInviteUser', 'Admin\\UserController@setInviteUser');
|
||||||
// StatOrder
|
// StatOrder
|
||||||
$router->get ('/stat/getOverride', 'Admin\\StatController@getOverride');
|
$router->get ('/stat/getOverride', 'Admin\\StatController@getOverride');
|
||||||
$router->get ('/stat/getServerLastRank', 'Admin\\StatController@getServerLastRank');
|
$router->get ('/stat/getServerLastRank', 'Admin\\StatController@getServerLastRank');
|
||||||
@ -98,6 +99,12 @@ class AdminRoute
|
|||||||
$router->post('/knowledge/show', 'Admin\\KnowledgeController@show');
|
$router->post('/knowledge/show', 'Admin\\KnowledgeController@show');
|
||||||
$router->post('/knowledge/drop', 'Admin\\KnowledgeController@drop');
|
$router->post('/knowledge/drop', 'Admin\\KnowledgeController@drop');
|
||||||
$router->post('/knowledge/sort', 'Admin\\KnowledgeController@sort');
|
$router->post('/knowledge/sort', 'Admin\\KnowledgeController@sort');
|
||||||
|
// Payment
|
||||||
|
$router->get ('/payment/fetch', 'Admin\\PaymentController@fetch');
|
||||||
|
$router->get ('/payment/getPaymentMethods', 'Admin\\PaymentController@getPaymentMethods');
|
||||||
|
$router->post('/payment/getPaymentForm', 'Admin\\PaymentController@getPaymentForm');
|
||||||
|
$router->post('/payment/save', 'Admin\\PaymentController@save');
|
||||||
|
$router->post('/payment/drop', 'Admin\\PaymentController@drop');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,12 @@ class GuestRoute
|
|||||||
], function ($router) {
|
], function ($router) {
|
||||||
// Plan
|
// Plan
|
||||||
$router->get ('/plan/fetch', 'Guest\\PlanController@fetch');
|
$router->get ('/plan/fetch', 'Guest\\PlanController@fetch');
|
||||||
// Order
|
|
||||||
$router->post('/order/alipayNotify', 'Guest\\OrderController@alipayNotify');
|
|
||||||
$router->post('/order/stripeNotify', 'Guest\\OrderController@stripeNotify');
|
|
||||||
$router->post('/order/bitpayXNotify', 'Guest\\OrderController@bitpayXNotify');
|
|
||||||
$router->post('/order/mgateNotify', 'Guest\\OrderController@mgateNotify');
|
|
||||||
$router->post('/order/epayNotify', 'Guest\\OrderController@epayNotify');
|
|
||||||
// Telegram
|
// Telegram
|
||||||
$router->post('/telegram/webhook', 'Guest\\TelegramController@webhook');
|
$router->post('/telegram/webhook', 'Guest\\TelegramController@webhook');
|
||||||
|
// Payment
|
||||||
|
$router->match(['get', 'post'], '/payment/notify/{method}/{uuid}', 'Guest\\PaymentController@notify');
|
||||||
|
// Comm
|
||||||
|
$router->get ('/comm/config', 'Guest\\CommController@config');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ class UserRoute
|
|||||||
$router->get ('/telegram/getBotInfo', 'User\\TelegramController@getBotInfo');
|
$router->get ('/telegram/getBotInfo', 'User\\TelegramController@getBotInfo');
|
||||||
// Comm
|
// Comm
|
||||||
$router->get ('/comm/config', 'User\\CommController@config');
|
$router->get ('/comm/config', 'User\\CommController@config');
|
||||||
|
$router->Post('/comm/getStripePublicKey', 'User\\CommController@getStripePublicKey');
|
||||||
// Knowledge
|
// Knowledge
|
||||||
$router->get ('/knowledge/fetch', 'User\\KnowledgeController@fetch');
|
$router->get ('/knowledge/fetch', 'User\\KnowledgeController@fetch');
|
||||||
$router->get ('/knowledge/getCategory', 'User\\KnowledgeController@getCategory');
|
$router->get ('/knowledge/getCategory', 'User\\KnowledgeController@getCategory');
|
||||||
|
12
app/Models/Payment.php
Normal file
12
app/Models/Payment.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Payment extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_payment';
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
}
|
96
app/Payments/AlipayF2F.php
Normal file
96
app/Payments/AlipayF2F.php
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自己写别抄,抄NMB抄
|
||||||
|
*/
|
||||||
|
namespace App\Payments;
|
||||||
|
|
||||||
|
use Omnipay\Omnipay;
|
||||||
|
|
||||||
|
class AlipayF2F {
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'app_id' => [
|
||||||
|
'label' => '支付宝APPID',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'private_key' => [
|
||||||
|
'label' => '支付宝私钥',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'public_key' => [
|
||||||
|
'label' => '支付宝公钥',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay($order)
|
||||||
|
{
|
||||||
|
$gateway = Omnipay::create('Alipay_AopF2F');
|
||||||
|
$gateway->setSignType('RSA2'); //RSA/RSA2
|
||||||
|
$gateway->setAppId($this->config['app_id']);
|
||||||
|
$gateway->setPrivateKey($this->config['private_key']); // 可以是路径,也可以是密钥内容
|
||||||
|
$gateway->setAlipayPublicKey($this->config['public_key']); // 可以是路径,也可以是密钥内容
|
||||||
|
$gateway->setNotifyUrl($order['notify_url']);
|
||||||
|
$request = $gateway->purchase();
|
||||||
|
$request->setBizContent([
|
||||||
|
'subject' => config('v2board.app_name', 'V2Board') . ' - 订阅',
|
||||||
|
'out_trade_no' => $order['trade_no'],
|
||||||
|
'total_amount' => $order['total_amount'] / 100
|
||||||
|
]);
|
||||||
|
/** @var \Omnipay\Alipay\Responses\AopTradePreCreateResponse $response */
|
||||||
|
$response = $request->send();
|
||||||
|
$result = $response->getAlipayResponse();
|
||||||
|
if ($result['code'] !== '10000') {
|
||||||
|
abort(500, $result['sub_msg']);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'type' => 0, // 0:qrcode 1:url
|
||||||
|
'data' => $response->getQrCode()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notify($params)
|
||||||
|
{
|
||||||
|
$gateway = Omnipay::create('Alipay_AopF2F');
|
||||||
|
$gateway->setSignType('RSA2'); //RSA/RSA2
|
||||||
|
$gateway->setAppId($this->config['app_id']);
|
||||||
|
$gateway->setPrivateKey($this->config['private_key']); // 可以是路径,也可以是密钥内容
|
||||||
|
$gateway->setAlipayPublicKey($this->config['public_key']); // 可以是路径,也可以是密钥内容
|
||||||
|
$request = $gateway->completePurchase();
|
||||||
|
$request->setParams($_POST); //Optional
|
||||||
|
try {
|
||||||
|
/** @var \Omnipay\Alipay\Responses\AopCompletePurchaseResponse $response */
|
||||||
|
$response = $request->send();
|
||||||
|
if ($response->isPaid()) {
|
||||||
|
/**
|
||||||
|
* Payment is successful
|
||||||
|
*/
|
||||||
|
return [
|
||||||
|
'trade_no' => $params['out_trade_no'],
|
||||||
|
'callback_no' => $params['trade_no']
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* Payment is not successful
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
/**
|
||||||
|
* Payment is not successful
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
app/Payments/EPay.php
Normal file
69
app/Payments/EPay.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Payments;
|
||||||
|
|
||||||
|
class EPay {
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'url' => [
|
||||||
|
'label' => 'URL',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'pid' => [
|
||||||
|
'label' => 'PID',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'key' => [
|
||||||
|
'label' => 'KEY',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay($order)
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'money' => $order['total_amount'] / 100,
|
||||||
|
'name' => $order['trade_no'],
|
||||||
|
'notify_url' => $order['notify_url'],
|
||||||
|
'return_url' => $order['return_url'],
|
||||||
|
'out_trade_no' => $order['trade_no'],
|
||||||
|
'pid' => $this->config['pid']
|
||||||
|
];
|
||||||
|
ksort($params);
|
||||||
|
reset($params);
|
||||||
|
$str = stripslashes(urldecode(http_build_query($params))) . $this->config['key'];
|
||||||
|
$params['sign'] = md5($str);
|
||||||
|
$params['sign_type'] = 'MD5';
|
||||||
|
return [
|
||||||
|
'type' => 1, // 0:qrcode 1:url
|
||||||
|
'data' => $this->config['url'] . '/submit.php?' . http_build_query($params)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notify($params)
|
||||||
|
{
|
||||||
|
$sign = $params['sign'];
|
||||||
|
unset($params['sign']);
|
||||||
|
unset($params['sign_type']);
|
||||||
|
ksort($params);
|
||||||
|
reset($params);
|
||||||
|
$str = stripslashes(urldecode(http_build_query($params))) . $this->config['key'];
|
||||||
|
if ($sign !== md5($str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'trade_no' => $params['out_trade_no'],
|
||||||
|
'callback_no' => $params['trade_no']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
90
app/Payments/MGate.php
Normal file
90
app/Payments/MGate.php
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自己写别抄,抄NMB抄
|
||||||
|
*/
|
||||||
|
namespace App\Payments;
|
||||||
|
|
||||||
|
use \Curl\Curl;
|
||||||
|
|
||||||
|
class MGate {
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'mgate_url' => [
|
||||||
|
'label' => 'API地址',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'mgate_app_id' => [
|
||||||
|
'label' => 'APPID',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'mgate_app_secret' => [
|
||||||
|
'label' => 'AppSecret',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay($order)
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'out_trade_no' => $order['trade_no'],
|
||||||
|
'total_amount' => $order['total_amount'],
|
||||||
|
'notify_url' => $order['notify_url'],
|
||||||
|
'return_url' => $order['return_url']
|
||||||
|
];
|
||||||
|
$params['app_id'] = $this->config['mgate_app_id'];
|
||||||
|
ksort($params);
|
||||||
|
$str = http_build_query($params) . $this->config['mgate_app_secret'];
|
||||||
|
$params['sign'] = md5($str);
|
||||||
|
$curl = new Curl();
|
||||||
|
$curl->post($this->config['mgate_url'] . '/v1/gateway/fetch', http_build_query($params));
|
||||||
|
$result = $curl->response;
|
||||||
|
if (!$result) {
|
||||||
|
abort(500, '网络异常');
|
||||||
|
}
|
||||||
|
if ($curl->error) {
|
||||||
|
if (isset($result->errors)) {
|
||||||
|
$errors = (array)$result->errors;
|
||||||
|
abort(500, $errors[array_keys($errors)[0]][0]);
|
||||||
|
}
|
||||||
|
if (isset($result->message)) {
|
||||||
|
abort(500, $result->message);
|
||||||
|
}
|
||||||
|
abort(500, '未知错误');
|
||||||
|
}
|
||||||
|
$curl->close();
|
||||||
|
if (!isset($result->data->trade_no)) {
|
||||||
|
abort(500, '接口请求失败');
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'type' => 1, // 0:qrcode 1:url
|
||||||
|
'data' => $result->data->pay_url
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notify($params)
|
||||||
|
{
|
||||||
|
$sign = $params['sign'];
|
||||||
|
unset($params['sign']);
|
||||||
|
ksort($params);
|
||||||
|
reset($params);
|
||||||
|
$str = http_build_query($params) . $this->config['mgate_app_secret'];
|
||||||
|
if ($sign !== md5($str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'trade_no' => $params['out_trade_no'],
|
||||||
|
'callback_no' => $params['trade_no']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
114
app/Payments/StripeAlipay.php
Normal file
114
app/Payments/StripeAlipay.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自己写别抄,抄NMB抄
|
||||||
|
*/
|
||||||
|
namespace App\Payments;
|
||||||
|
|
||||||
|
use Stripe\Source;
|
||||||
|
use Stripe\Stripe;
|
||||||
|
|
||||||
|
class StripeAlipay {
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'currency' => [
|
||||||
|
'label' => '货币单位',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'stripe_sk_live' => [
|
||||||
|
'label' => 'SK_LIVE',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'stripe_webhook_key' => [
|
||||||
|
'label' => 'WebHook密钥签名',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay($order)
|
||||||
|
{
|
||||||
|
$currency = $this->config['currency'];
|
||||||
|
$exchange = $this->exchange('CNY', strtoupper($currency));
|
||||||
|
if (!$exchange) {
|
||||||
|
abort(500, __('user.order.stripeAlipay.currency_convert_timeout'));
|
||||||
|
}
|
||||||
|
Stripe::setApiKey($this->config['stripe_sk_live']);
|
||||||
|
$source = Source::create([
|
||||||
|
'amount' => floor($order['total_amount'] * $exchange),
|
||||||
|
'currency' => $currency,
|
||||||
|
'type' => 'alipay',
|
||||||
|
'statement_descriptor' => $order['trade_no'],
|
||||||
|
'metadata' => [
|
||||||
|
'user_id' => $order['user_id'],
|
||||||
|
'out_trade_no' => $order['trade_no'],
|
||||||
|
'identifier' => ''
|
||||||
|
],
|
||||||
|
'redirect' => [
|
||||||
|
'return_url' => $order['return_url']
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
if (!$source['redirect']['url']) {
|
||||||
|
abort(500, __('user.order.stripeAlipay.gateway_request_failed'));
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'type' => 1,
|
||||||
|
'data' => $source['redirect']['url']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notify($params)
|
||||||
|
{
|
||||||
|
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
|
||||||
|
try {
|
||||||
|
$event = \Stripe\Webhook::constructEvent(
|
||||||
|
file_get_contents('php://input'),
|
||||||
|
$_SERVER['HTTP_STRIPE_SIGNATURE'],
|
||||||
|
$this->config['stripe_webhook_key']
|
||||||
|
);
|
||||||
|
} catch (\Stripe\Error\SignatureVerification $e) {
|
||||||
|
abort(400);
|
||||||
|
}
|
||||||
|
switch ($event->type) {
|
||||||
|
case 'source.chargeable':
|
||||||
|
$object = $event->data->object;
|
||||||
|
\Stripe\Charge::create([
|
||||||
|
'amount' => $object->amount,
|
||||||
|
'currency' => $object->currency,
|
||||||
|
'source' => $object->id,
|
||||||
|
'metadata' => json_decode($object->metadata, true)
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'charge.succeeded':
|
||||||
|
$object = $event->data->object;
|
||||||
|
if ($object->status === 'succeeded') {
|
||||||
|
$metaData = isset($object->metadata->out_trade_no) ? $object->metadata : $object->source->metadata;
|
||||||
|
$tradeNo = $metaData->out_trade_no;
|
||||||
|
return [
|
||||||
|
'trade_no' => $tradeNo,
|
||||||
|
'callback_no' => $object->balance_transaction
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort(500, 'event is not support');
|
||||||
|
}
|
||||||
|
die('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function exchange($from, $to)
|
||||||
|
{
|
||||||
|
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
|
||||||
|
$result = json_decode($result, true);
|
||||||
|
return $result['rates'][$to];
|
||||||
|
}
|
||||||
|
}
|
121
app/Payments/StripeCredit.php
Normal file
121
app/Payments/StripeCredit.php
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自己写别抄,抄NMB抄
|
||||||
|
*/
|
||||||
|
namespace App\Payments;
|
||||||
|
|
||||||
|
use Stripe\Source;
|
||||||
|
use Stripe\Stripe;
|
||||||
|
|
||||||
|
class StripeCredit {
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'currency' => [
|
||||||
|
'label' => '货币单位',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'stripe_sk_live' => [
|
||||||
|
'label' => 'SK_LIVE',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'stripe_pk_live' => [
|
||||||
|
'label' => 'PK_LIVE',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'stripe_webhook_key' => [
|
||||||
|
'label' => 'WebHook密钥签名',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay($order)
|
||||||
|
{
|
||||||
|
info($order);
|
||||||
|
$currency = $this->config['currency'];
|
||||||
|
$exchange = $this->exchange('CNY', strtoupper($currency));
|
||||||
|
if (!$exchange) {
|
||||||
|
abort(500, __('user.order.stripeCard.currency_convert_timeout'));
|
||||||
|
}
|
||||||
|
Stripe::setApiKey($this->config['stripe_sk_live']);
|
||||||
|
try {
|
||||||
|
$charge = \Stripe\Charge::create([
|
||||||
|
'amount' => floor($order['total_amount'] * $exchange),
|
||||||
|
'currency' => $currency,
|
||||||
|
'source' => $order['stripe_token'],
|
||||||
|
'metadata' => [
|
||||||
|
'user_id' => $order['user_id'],
|
||||||
|
'out_trade_no' => $order['trade_no'],
|
||||||
|
'identifier' => ''
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
info($e);
|
||||||
|
abort(500, __('user.order.stripeCard.was_problem'));
|
||||||
|
}
|
||||||
|
if (!$charge->paid) {
|
||||||
|
abort(500, __('user.order.stripeCard.deduction_failed'));
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'type' => 2,
|
||||||
|
'data' => $charge->paid
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notify($params)
|
||||||
|
{
|
||||||
|
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
|
||||||
|
try {
|
||||||
|
$event = \Stripe\Webhook::constructEvent(
|
||||||
|
file_get_contents('php://input'),
|
||||||
|
$_SERVER['HTTP_STRIPE_SIGNATURE'],
|
||||||
|
$this->config['stripe_webhook_key']
|
||||||
|
);
|
||||||
|
} catch (\Stripe\Error\SignatureVerification $e) {
|
||||||
|
abort(400);
|
||||||
|
}
|
||||||
|
switch ($event->type) {
|
||||||
|
case 'source.chargeable':
|
||||||
|
$object = $event->data->object;
|
||||||
|
\Stripe\Charge::create([
|
||||||
|
'amount' => $object->amount,
|
||||||
|
'currency' => $object->currency,
|
||||||
|
'source' => $object->id,
|
||||||
|
'metadata' => json_decode($object->metadata, true)
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'charge.succeeded':
|
||||||
|
$object = $event->data->object;
|
||||||
|
if ($object->status === 'succeeded') {
|
||||||
|
$metaData = isset($object->metadata->out_trade_no) ? $object->metadata : $object->source->metadata;
|
||||||
|
$tradeNo = $metaData->out_trade_no;
|
||||||
|
return [
|
||||||
|
'trade_no' => $tradeNo,
|
||||||
|
'callback_no' => $object->balance_transaction
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort(500, 'event is not support');
|
||||||
|
}
|
||||||
|
die('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function exchange($from, $to)
|
||||||
|
{
|
||||||
|
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
|
||||||
|
$result = json_decode($result, true);
|
||||||
|
return $result['rates'][$to];
|
||||||
|
}
|
||||||
|
}
|
114
app/Payments/StripeWepay.php
Normal file
114
app/Payments/StripeWepay.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自己写别抄,抄NMB抄
|
||||||
|
*/
|
||||||
|
namespace App\Payments;
|
||||||
|
|
||||||
|
use Stripe\Source;
|
||||||
|
use Stripe\Stripe;
|
||||||
|
|
||||||
|
class StripeWepay {
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'currency' => [
|
||||||
|
'label' => '货币单位',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'stripe_sk_live' => [
|
||||||
|
'label' => 'SK_LIVE',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
],
|
||||||
|
'stripe_webhook_key' => [
|
||||||
|
'label' => 'WebHook密钥签名',
|
||||||
|
'description' => '',
|
||||||
|
'type' => 'input',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay($order)
|
||||||
|
{
|
||||||
|
$currency = $this->config['currency'];
|
||||||
|
$exchange = $this->exchange('CNY', strtoupper($currency));
|
||||||
|
if (!$exchange) {
|
||||||
|
abort(500, __('user.order.stripeAlipay.currency_convert_timeout'));
|
||||||
|
}
|
||||||
|
Stripe::setApiKey($this->config['stripe_sk_live']);
|
||||||
|
$source = Source::create([
|
||||||
|
'amount' => floor($order['total_amount'] * $exchange),
|
||||||
|
'currency' => $currency,
|
||||||
|
'type' => 'wechat',
|
||||||
|
'statement_descriptor' => $order['trade_no'],
|
||||||
|
'metadata' => [
|
||||||
|
'user_id' => $order['user_id'],
|
||||||
|
'out_trade_no' => $order['trade_no'],
|
||||||
|
'identifier' => ''
|
||||||
|
],
|
||||||
|
'redirect' => [
|
||||||
|
'return_url' => $order['return_url']
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
if (!$source['wechat']['qr_code_url']) {
|
||||||
|
abort(500, __('user.order.stripeWepay.gateway_request_failed'));
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'type' => 0,
|
||||||
|
'data' => $source['wechat']['qr_code_url']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notify($params)
|
||||||
|
{
|
||||||
|
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
|
||||||
|
try {
|
||||||
|
$event = \Stripe\Webhook::constructEvent(
|
||||||
|
file_get_contents('php://input'),
|
||||||
|
$_SERVER['HTTP_STRIPE_SIGNATURE'],
|
||||||
|
$this->config['stripe_webhook_key']
|
||||||
|
);
|
||||||
|
} catch (\Stripe\Error\SignatureVerification $e) {
|
||||||
|
abort(400);
|
||||||
|
}
|
||||||
|
switch ($event->type) {
|
||||||
|
case 'source.chargeable':
|
||||||
|
$object = $event->data->object;
|
||||||
|
\Stripe\Charge::create([
|
||||||
|
'amount' => $object->amount,
|
||||||
|
'currency' => $object->currency,
|
||||||
|
'source' => $object->id,
|
||||||
|
'metadata' => json_decode($object->metadata, true)
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'charge.succeeded':
|
||||||
|
$object = $event->data->object;
|
||||||
|
if ($object->status === 'succeeded') {
|
||||||
|
$metaData = isset($object->metadata->out_trade_no) ? $object->metadata : $object->source->metadata;
|
||||||
|
$tradeNo = $metaData->out_trade_no;
|
||||||
|
return [
|
||||||
|
'trade_no' => $tradeNo,
|
||||||
|
'callback_no' => $object->balance_transaction
|
||||||
|
];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort(500, 'event is not support');
|
||||||
|
}
|
||||||
|
die('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function exchange($from, $to)
|
||||||
|
{
|
||||||
|
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
|
||||||
|
$result = json_decode($result, true);
|
||||||
|
return $result['rates'][$to];
|
||||||
|
}
|
||||||
|
}
|
@ -141,7 +141,7 @@ class OrderService
|
|||||||
private function haveValidOrder(User $user)
|
private function haveValidOrder(User $user)
|
||||||
{
|
{
|
||||||
return Order::where('user_id', $user->id)
|
return Order::where('user_id', $user->id)
|
||||||
->whereIn('status', [3, 4])
|
->whereNotIn('status', [0, 2])
|
||||||
->first();
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
54
app/Services/PaymentService.php
Normal file
54
app/Services/PaymentService.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Models\Payment;
|
||||||
|
|
||||||
|
class PaymentService
|
||||||
|
{
|
||||||
|
public function __construct($method, $id = NULL, $uuid = NULL)
|
||||||
|
{
|
||||||
|
$this->method = $method;
|
||||||
|
$this->class = '\\App\\Payments\\' . $this->method;
|
||||||
|
if (!class_exists($this->class)) abort(500, 'gate is not found');
|
||||||
|
if ($id) $payment = Payment::find($id)->toArray();
|
||||||
|
if ($uuid) $payment = Payment::where('uuid', $uuid)->first()->toArray();
|
||||||
|
$this->config = [];
|
||||||
|
if (isset($payment)) {
|
||||||
|
$this->config = json_decode($payment['config'], true);
|
||||||
|
$this->config['enable'] = $payment['enable'];
|
||||||
|
$this->config['id'] = $payment['id'];
|
||||||
|
$this->config['uuid'] = $payment['uuid'];
|
||||||
|
};
|
||||||
|
$this->payment = new $this->class($this->config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notify($params)
|
||||||
|
{
|
||||||
|
if (!$this->config['enable']) abort(500, 'gate is not enable');
|
||||||
|
return $this->payment->notify($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pay($order)
|
||||||
|
{
|
||||||
|
return $this->payment->pay([
|
||||||
|
'notify_url' => url("/api/v1/guest/payment/notify/{$this->method}/{$this->config['uuid']}"),
|
||||||
|
'return_url' => config('v2board.app_url', env('APP_URL')) . '/#/order/' . $order['trade_no'],
|
||||||
|
'trade_no' => $order['trade_no'],
|
||||||
|
'total_amount' => $order['total_amount'],
|
||||||
|
'user_id' => $order['user_id'],
|
||||||
|
'stripe_token' => $order['stripe_token']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function form()
|
||||||
|
{
|
||||||
|
$form = $this->payment->form();
|
||||||
|
$keys = array_keys($form);
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (isset($this->config[$key])) $form[$key]['value'] = $this->config[$key];
|
||||||
|
}
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
}
|
@ -298,13 +298,6 @@ class ServerService
|
|||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
||||||
}
|
}
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
||||||
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
|
||||||
if ($server[$i]['parent_id']) {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server[$i]['parent_id']));
|
|
||||||
} else {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server[$i]['id']));
|
|
||||||
}
|
|
||||||
$server[$i]['available'] = (time() - 300) < $server[$i]['last_check_at'];
|
|
||||||
}
|
}
|
||||||
return $server->toArray();
|
return $server->toArray();
|
||||||
}
|
}
|
||||||
@ -327,13 +320,6 @@ class ServerService
|
|||||||
$server[$i]['ruleSettings'] = json_decode($server[$i]['ruleSettings']);
|
$server[$i]['ruleSettings'] = json_decode($server[$i]['ruleSettings']);
|
||||||
}
|
}
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
||||||
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_V2RAY_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
|
||||||
if ($server[$i]['parent_id']) {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server[$i]['parent_id']));
|
|
||||||
} else {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_V2RAY_LAST_CHECK_AT', $server[$i]['id']));
|
|
||||||
}
|
|
||||||
$server[$i]['available'] = (time() - 300) < $server[$i]['last_check_at'];
|
|
||||||
}
|
}
|
||||||
return $server->toArray();
|
return $server->toArray();
|
||||||
}
|
}
|
||||||
@ -347,14 +333,29 @@ class ServerService
|
|||||||
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
$server[$i]['tags'] = json_decode($server[$i]['tags']);
|
||||||
}
|
}
|
||||||
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
$server[$i]['group_id'] = json_decode($server[$i]['group_id']);
|
||||||
$server[$i]['online'] = Cache::get(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server[$i]['parent_id'] ? $server[$i]['parent_id'] : $server[$i]['id']));
|
|
||||||
if ($server[$i]['parent_id']) {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server[$i]['parent_id']));
|
|
||||||
} else {
|
|
||||||
$server[$i]['last_check_at'] = Cache::get(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server[$i]['id']));
|
|
||||||
}
|
|
||||||
$server[$i]['available'] = (time() - 300) < $server[$i]['last_check_at'];
|
|
||||||
}
|
}
|
||||||
return $server->toArray();
|
return $server->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function mergeData(&$servers)
|
||||||
|
{
|
||||||
|
foreach ($servers as $k => $v) {
|
||||||
|
$serverType = strtoupper($servers[$k]['type']);
|
||||||
|
$servers[$k]['online'] = Cache::get(CacheKey::get("SERVER_{$serverType}_ONLINE_USER", $servers[$k]['parent_id'] ? $servers[$k]['parent_id'] : $servers[$k]['id']));
|
||||||
|
if ($servers[$k]['parent_id']) {
|
||||||
|
$servers[$k]['last_check_at'] = Cache::get(CacheKey::get("SERVER_{$serverType}_LAST_CHECK_AT", $servers[$k]['parent_id']));
|
||||||
|
$servers[$k]['last_push_at'] = Cache::get(CacheKey::get("SERVER_{$serverType}_LAST_PUSH_AT", $servers[$k]['parent_id']));
|
||||||
|
} else {
|
||||||
|
$servers[$k]['last_check_at'] = Cache::get(CacheKey::get("SERVER_{$serverType}_LAST_CHECK_AT", $servers[$k]['id']));
|
||||||
|
$servers[$k]['last_push_at'] = Cache::get(CacheKey::get("SERVER_{$serverType}_LAST_PUSH_AT", $servers[$k]['id']));
|
||||||
|
}
|
||||||
|
if ((time() - 300) >= $servers[$k]['last_check_at']) {
|
||||||
|
$servers[$k]['available_status'] = 0;
|
||||||
|
} else if ((time() - 300) >= $servers[$k]['last_push_at']) {
|
||||||
|
$servers[$k]['available_status'] = 1;
|
||||||
|
} else {
|
||||||
|
$servers[$k]['available_status'] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,13 @@ class CacheKey
|
|||||||
'LAST_SEND_EMAIL_VERIFY_TIMESTAMP' => '最后一次发送邮箱验证码时间',
|
'LAST_SEND_EMAIL_VERIFY_TIMESTAMP' => '最后一次发送邮箱验证码时间',
|
||||||
'SERVER_V2RAY_ONLINE_USER' => '节点在线用户',
|
'SERVER_V2RAY_ONLINE_USER' => '节点在线用户',
|
||||||
'SERVER_V2RAY_LAST_CHECK_AT' => '节点最后检查时间',
|
'SERVER_V2RAY_LAST_CHECK_AT' => '节点最后检查时间',
|
||||||
|
'SERVER_V2RAY_LAST_PUSH_AT' => '节点最后推送时间',
|
||||||
'SERVER_TROJAN_ONLINE_USER' => 'trojan节点在线用户',
|
'SERVER_TROJAN_ONLINE_USER' => 'trojan节点在线用户',
|
||||||
'SERVER_TROJAN_LAST_CHECK_AT' => 'trojan节点最后检查时间',
|
'SERVER_TROJAN_LAST_CHECK_AT' => 'trojan节点最后检查时间',
|
||||||
|
'SERVER_TROJAN_LAST_PUSH_AT' => 'trojan节点最后推送时间',
|
||||||
'SERVER_SHADOWSOCKS_ONLINE_USER' => 'ss节点在线用户',
|
'SERVER_SHADOWSOCKS_ONLINE_USER' => 'ss节点在线用户',
|
||||||
'SERVER_SHADOWSOCKS_LAST_CHECK_AT' => 'ss节点最后检查时间',
|
'SERVER_SHADOWSOCKS_LAST_CHECK_AT' => 'ss节点最后检查时间',
|
||||||
|
'SERVER_SHADOWSOCKS_LAST_PUSH_AT' => 'ss节点最后推送时间',
|
||||||
'TEMP_TOKEN' => '临时令牌',
|
'TEMP_TOKEN' => '临时令牌',
|
||||||
'LAST_SEND_EMAIL_REMIND_TRAFFIC'
|
'LAST_SEND_EMAIL_REMIND_TRAFFIC'
|
||||||
];
|
];
|
||||||
|
@ -25,7 +25,7 @@ class Helper
|
|||||||
|
|
||||||
public static function exchange($from, $to)
|
public static function exchange($from, $to)
|
||||||
{
|
{
|
||||||
$result = file_get_contents('https://api.exchangeratesapi.io/latest?symbols=' . $to . '&base=' . $from);
|
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
|
||||||
$result = json_decode($result, true);
|
$result = json_decode($result, true);
|
||||||
return $result['rates'][$to];
|
return $result['rates'][$to];
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,9 @@ class URLSchemes
|
|||||||
"v" => "2",
|
"v" => "2",
|
||||||
"ps" => $server['name'],
|
"ps" => $server['name'],
|
||||||
"add" => $server['host'],
|
"add" => $server['host'],
|
||||||
"port" => $server['port'],
|
"port" => (string)$server['port'],
|
||||||
"id" => $user['uuid'],
|
"id" => $user['uuid'],
|
||||||
"aid" => $server['alter_id'],
|
"aid" => (string)$server['alter_id'],
|
||||||
"net" => $server['network'],
|
"net" => $server['network'],
|
||||||
"type" => "none",
|
"type" => "none",
|
||||||
"host" => "",
|
"host" => "",
|
||||||
|
@ -236,5 +236,5 @@ return [
|
|||||||
| The only modification by laravel config
|
| The only modification by laravel config
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
'version' => '1.5.0'
|
'version' => '1.5.1.1621339182281'
|
||||||
];
|
];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
-- Adminer 4.7.8 MySQL dump
|
-- Adminer 4.8.0 MySQL 5.7.29 dump
|
||||||
|
|
||||||
SET NAMES utf8;
|
SET NAMES utf8;
|
||||||
SET time_zone = '+00:00';
|
SET time_zone = '+00:00';
|
||||||
@ -14,7 +14,7 @@ CREATE TABLE `failed_jobs` (
|
|||||||
`queue` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
`queue` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
`exception` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
`exception` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
`failed_at` timestamp NOT NULL DEFAULT current_timestamp(),
|
`failed_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
@ -41,8 +41,8 @@ CREATE TABLE `v2_invite_code` (
|
|||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`user_id` int(11) NOT NULL,
|
`user_id` int(11) NOT NULL,
|
||||||
`code` char(32) NOT NULL,
|
`code` char(32) NOT NULL,
|
||||||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
`status` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
`pv` int(11) NOT NULL DEFAULT 0,
|
`pv` int(11) NOT NULL DEFAULT '0',
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@ -57,7 +57,7 @@ CREATE TABLE `v2_knowledge` (
|
|||||||
`title` varchar(255) NOT NULL COMMENT '標題',
|
`title` varchar(255) NOT NULL COMMENT '標題',
|
||||||
`body` text NOT NULL COMMENT '內容',
|
`body` text NOT NULL COMMENT '內容',
|
||||||
`sort` int(11) DEFAULT NULL COMMENT '排序',
|
`sort` int(11) DEFAULT NULL COMMENT '排序',
|
||||||
`show` tinyint(1) NOT NULL DEFAULT 0 COMMENT '顯示',
|
`show` tinyint(1) NOT NULL DEFAULT '0' COMMENT '顯示',
|
||||||
`created_at` int(11) NOT NULL COMMENT '創建時間',
|
`created_at` int(11) NOT NULL COMMENT '創建時間',
|
||||||
`updated_at` int(11) NOT NULL COMMENT '更新時間',
|
`updated_at` int(11) NOT NULL COMMENT '更新時間',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@ -70,7 +70,7 @@ CREATE TABLE `v2_mail_log` (
|
|||||||
`email` varchar(64) NOT NULL,
|
`email` varchar(64) NOT NULL,
|
||||||
`subject` varchar(255) NOT NULL,
|
`subject` varchar(255) NOT NULL,
|
||||||
`template_name` varchar(255) NOT NULL,
|
`template_name` varchar(255) NOT NULL,
|
||||||
`error` text DEFAULT NULL,
|
`error` text,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@ -96,6 +96,7 @@ CREATE TABLE `v2_order` (
|
|||||||
`user_id` int(11) NOT NULL,
|
`user_id` int(11) NOT NULL,
|
||||||
`plan_id` int(11) NOT NULL,
|
`plan_id` int(11) NOT NULL,
|
||||||
`coupon_id` int(11) DEFAULT NULL,
|
`coupon_id` int(11) DEFAULT NULL,
|
||||||
|
`payment_id` int(11) DEFAULT NULL,
|
||||||
`type` int(11) NOT NULL COMMENT '1新购2续费3升级',
|
`type` int(11) NOT NULL COMMENT '1新购2续费3升级',
|
||||||
`cycle` varchar(255) NOT NULL,
|
`cycle` varchar(255) NOT NULL,
|
||||||
`trade_no` varchar(36) NOT NULL,
|
`trade_no` varchar(36) NOT NULL,
|
||||||
@ -105,26 +106,41 @@ CREATE TABLE `v2_order` (
|
|||||||
`surplus_amount` int(11) DEFAULT NULL COMMENT '剩余价值',
|
`surplus_amount` int(11) DEFAULT NULL COMMENT '剩余价值',
|
||||||
`refund_amount` int(11) DEFAULT NULL COMMENT '退款金额',
|
`refund_amount` int(11) DEFAULT NULL COMMENT '退款金额',
|
||||||
`balance_amount` int(11) DEFAULT NULL COMMENT '使用余额',
|
`balance_amount` int(11) DEFAULT NULL COMMENT '使用余额',
|
||||||
`surplus_order_ids` text DEFAULT NULL COMMENT '折抵订单',
|
`surplus_order_ids` text COMMENT '折抵订单',
|
||||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '0待支付1开通中2已取消3已完成4已折抵',
|
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待支付1开通中2已取消3已完成4已折抵',
|
||||||
`commission_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '0待确认1发放中2有效3无效',
|
`commission_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0待确认1发放中2有效3无效',
|
||||||
`commission_balance` int(11) NOT NULL DEFAULT 0,
|
`commission_balance` int(11) NOT NULL DEFAULT '0',
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `v2_payment`;
|
||||||
|
CREATE TABLE `v2_payment` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`uuid` char(32) NOT NULL,
|
||||||
|
`payment` varchar(16) NOT NULL,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`config` text NOT NULL,
|
||||||
|
`enable` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`sort` int(11) DEFAULT NULL,
|
||||||
|
`created_at` int(11) NOT NULL,
|
||||||
|
`updated_at` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `v2_plan`;
|
DROP TABLE IF EXISTS `v2_plan`;
|
||||||
CREATE TABLE `v2_plan` (
|
CREATE TABLE `v2_plan` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`group_id` int(11) NOT NULL,
|
`group_id` int(11) NOT NULL,
|
||||||
`transfer_enable` int(11) NOT NULL,
|
`transfer_enable` int(11) NOT NULL,
|
||||||
`name` varchar(255) NOT NULL,
|
`name` varchar(255) NOT NULL,
|
||||||
`show` tinyint(1) NOT NULL DEFAULT 0,
|
`show` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
`sort` int(11) DEFAULT NULL,
|
`sort` int(11) DEFAULT NULL,
|
||||||
`renew` tinyint(1) NOT NULL DEFAULT 1,
|
`renew` tinyint(1) NOT NULL DEFAULT '1',
|
||||||
`content` text DEFAULT NULL,
|
`content` text,
|
||||||
`month_price` int(11) DEFAULT NULL,
|
`month_price` int(11) DEFAULT NULL,
|
||||||
`quarter_price` int(11) DEFAULT NULL,
|
`quarter_price` int(11) DEFAULT NULL,
|
||||||
`half_year_price` int(11) DEFAULT NULL,
|
`half_year_price` int(11) DEFAULT NULL,
|
||||||
@ -148,18 +164,18 @@ CREATE TABLE `v2_server` (
|
|||||||
`host` varchar(255) NOT NULL,
|
`host` varchar(255) NOT NULL,
|
||||||
`port` int(11) NOT NULL,
|
`port` int(11) NOT NULL,
|
||||||
`server_port` int(11) NOT NULL,
|
`server_port` int(11) NOT NULL,
|
||||||
`tls` tinyint(4) NOT NULL DEFAULT 0,
|
`tls` tinyint(4) NOT NULL DEFAULT '0',
|
||||||
`tags` varchar(255) DEFAULT NULL,
|
`tags` varchar(255) DEFAULT NULL,
|
||||||
`rate` varchar(11) NOT NULL,
|
`rate` varchar(11) NOT NULL,
|
||||||
`network` text NOT NULL,
|
`network` text NOT NULL,
|
||||||
`alter_id` int(11) NOT NULL DEFAULT 1,
|
`alter_id` int(11) NOT NULL DEFAULT '1',
|
||||||
`settings` text DEFAULT NULL,
|
`settings` text,
|
||||||
`rules` text DEFAULT NULL,
|
`rules` text,
|
||||||
`networkSettings` text DEFAULT NULL,
|
`networkSettings` text,
|
||||||
`tlsSettings` text DEFAULT NULL,
|
`tlsSettings` text,
|
||||||
`ruleSettings` text DEFAULT NULL,
|
`ruleSettings` text,
|
||||||
`dnsSettings` text DEFAULT NULL,
|
`dnsSettings` text,
|
||||||
`show` tinyint(1) NOT NULL DEFAULT 0,
|
`show` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
`sort` int(11) DEFAULT NULL,
|
`sort` int(11) DEFAULT NULL,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
@ -206,7 +222,7 @@ CREATE TABLE `v2_server_shadowsocks` (
|
|||||||
`port` int(11) NOT NULL,
|
`port` int(11) NOT NULL,
|
||||||
`server_port` int(11) NOT NULL,
|
`server_port` int(11) NOT NULL,
|
||||||
`cipher` varchar(255) NOT NULL,
|
`cipher` varchar(255) NOT NULL,
|
||||||
`show` tinyint(4) NOT NULL DEFAULT 0,
|
`show` tinyint(4) NOT NULL DEFAULT '0',
|
||||||
`sort` int(11) DEFAULT NULL,
|
`sort` int(11) DEFAULT NULL,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
@ -225,9 +241,9 @@ CREATE TABLE `v2_server_trojan` (
|
|||||||
`host` varchar(255) NOT NULL COMMENT '主机名',
|
`host` varchar(255) NOT NULL COMMENT '主机名',
|
||||||
`port` int(11) NOT NULL COMMENT '连接端口',
|
`port` int(11) NOT NULL COMMENT '连接端口',
|
||||||
`server_port` int(11) NOT NULL COMMENT '服务端口',
|
`server_port` int(11) NOT NULL COMMENT '服务端口',
|
||||||
`allow_insecure` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否允许不安全',
|
`allow_insecure` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否允许不安全',
|
||||||
`server_name` varchar(255) DEFAULT NULL,
|
`server_name` varchar(255) DEFAULT NULL,
|
||||||
`show` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否显示',
|
`show` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否显示',
|
||||||
`sort` int(11) DEFAULT NULL,
|
`sort` int(11) DEFAULT NULL,
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
@ -276,7 +292,7 @@ CREATE TABLE `v2_ticket` (
|
|||||||
`last_reply_user_id` int(11) NOT NULL,
|
`last_reply_user_id` int(11) NOT NULL,
|
||||||
`subject` varchar(255) NOT NULL,
|
`subject` varchar(255) NOT NULL,
|
||||||
`level` tinyint(1) NOT NULL,
|
`level` tinyint(1) NOT NULL,
|
||||||
`status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '0:已开启 1:已关闭',
|
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0:已开启 1:已关闭',
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@ -303,27 +319,27 @@ CREATE TABLE `v2_user` (
|
|||||||
`email` varchar(64) NOT NULL,
|
`email` varchar(64) NOT NULL,
|
||||||
`password` varchar(64) NOT NULL,
|
`password` varchar(64) NOT NULL,
|
||||||
`password_algo` char(10) DEFAULT NULL,
|
`password_algo` char(10) DEFAULT NULL,
|
||||||
`balance` int(11) NOT NULL DEFAULT 0,
|
`balance` int(11) NOT NULL DEFAULT '0',
|
||||||
`discount` int(11) DEFAULT NULL,
|
`discount` int(11) DEFAULT NULL,
|
||||||
`commission_rate` int(11) DEFAULT NULL,
|
`commission_rate` int(11) DEFAULT NULL,
|
||||||
`commission_balance` int(11) NOT NULL DEFAULT 0,
|
`commission_balance` int(11) NOT NULL DEFAULT '0',
|
||||||
`t` int(11) NOT NULL DEFAULT 0,
|
`t` int(11) NOT NULL DEFAULT '0',
|
||||||
`u` bigint(20) NOT NULL DEFAULT 0,
|
`u` bigint(20) NOT NULL DEFAULT '0',
|
||||||
`d` bigint(20) NOT NULL DEFAULT 0,
|
`d` bigint(20) NOT NULL DEFAULT '0',
|
||||||
`transfer_enable` bigint(20) NOT NULL DEFAULT 0,
|
`transfer_enable` bigint(20) NOT NULL DEFAULT '0',
|
||||||
`banned` tinyint(1) NOT NULL DEFAULT 0,
|
`banned` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
`is_admin` tinyint(1) NOT NULL DEFAULT 0,
|
`is_admin` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
`is_staff` tinyint(1) NOT NULL DEFAULT 0,
|
`is_staff` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
`last_login_at` int(11) DEFAULT NULL,
|
`last_login_at` int(11) DEFAULT NULL,
|
||||||
`last_login_ip` int(11) DEFAULT NULL,
|
`last_login_ip` int(11) DEFAULT NULL,
|
||||||
`uuid` varchar(36) NOT NULL,
|
`uuid` varchar(36) NOT NULL,
|
||||||
`group_id` int(11) DEFAULT NULL,
|
`group_id` int(11) DEFAULT NULL,
|
||||||
`plan_id` int(11) DEFAULT NULL,
|
`plan_id` int(11) DEFAULT NULL,
|
||||||
`remind_expire` tinyint(4) DEFAULT 1,
|
`remind_expire` tinyint(4) DEFAULT '1',
|
||||||
`remind_traffic` tinyint(4) DEFAULT 1,
|
`remind_traffic` tinyint(4) DEFAULT '1',
|
||||||
`token` char(32) NOT NULL,
|
`token` char(32) NOT NULL,
|
||||||
`remarks` text DEFAULT NULL,
|
`remarks` text,
|
||||||
`expired_at` bigint(20) DEFAULT 0,
|
`expired_at` bigint(20) DEFAULT '0',
|
||||||
`created_at` int(11) NOT NULL,
|
`created_at` int(11) NOT NULL,
|
||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
@ -331,4 +347,4 @@ CREATE TABLE `v2_user` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
-- 2021-01-21 14:25:17
|
-- 2021-05-06 16:14:04
|
||||||
|
@ -394,3 +394,20 @@ DROP `enable`;
|
|||||||
|
|
||||||
ALTER TABLE `v2_user`
|
ALTER TABLE `v2_user`
|
||||||
ADD `remarks` text COLLATE 'utf8_general_ci' NULL AFTER `token`;
|
ADD `remarks` text COLLATE 'utf8_general_ci' NULL AFTER `token`;
|
||||||
|
|
||||||
|
CREATE TABLE `v2_payment` (
|
||||||
|
`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`payment` varchar(16) NOT NULL,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`config` text NOT NULL,
|
||||||
|
`enable` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`sort` int(11) DEFAULT NULL,
|
||||||
|
`created_at` int(11) NOT NULL,
|
||||||
|
`updated_at` int(11) NOT NULL
|
||||||
|
) COLLATE 'utf8mb4_general_ci';
|
||||||
|
|
||||||
|
ALTER TABLE `v2_order`
|
||||||
|
ADD `payment_id` int(11) NULL AFTER `coupon_id`;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_payment`
|
||||||
|
ADD `uuid` char(32) NOT NULL AFTER `id`;
|
||||||
|
2
init.sh
2
init.sh
@ -1,3 +1,3 @@
|
|||||||
wget https://getcomposer.org/download/1.9.0/composer.phar
|
wget https://getcomposer.org/download/2.0.13/composer.phar
|
||||||
php composer.phar install -vvv
|
php composer.phar install -vvv
|
||||||
php artisan v2board:install
|
php artisan v2board:install
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Library;
|
|
||||||
|
|
||||||
class BitpayX
|
|
||||||
{
|
|
||||||
private $bitpayxAppSecret;
|
|
||||||
private $bitpayxGatewayUri;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 签名初始化
|
|
||||||
* @param merKey 签名密钥
|
|
||||||
*/
|
|
||||||
public function __construct($bitpayxAppSecret)
|
|
||||||
{
|
|
||||||
$this->bitpayxAppSecret = $bitpayxAppSecret;
|
|
||||||
$this->bitpayxGatewayUri = 'https://api.mugglepay.com/v1/';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function prepareSignId($tradeno)
|
|
||||||
{
|
|
||||||
$data_sign = array();
|
|
||||||
$data_sign['merchant_order_id'] = $tradeno;
|
|
||||||
$data_sign['secret'] = $this->bitpayxAppSecret;
|
|
||||||
$data_sign['type'] = 'FIAT';
|
|
||||||
ksort($data_sign);
|
|
||||||
return http_build_query($data_sign);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sign($data)
|
|
||||||
{
|
|
||||||
return strtolower(md5(md5($data) . $this->bitpayxAppSecret));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function verify($data, $signature)
|
|
||||||
{
|
|
||||||
$mySign = $this->sign($data);
|
|
||||||
return $mySign === $signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function mprequest($data)
|
|
||||||
{
|
|
||||||
$headers = array('content-type: application/json', 'token: ' . $this->bitpayxAppSecret);
|
|
||||||
$curl = curl_init();
|
|
||||||
$url = $this->bitpayxGatewayUri . 'orders';
|
|
||||||
curl_setopt($curl, CURLOPT_URL, $url);
|
|
||||||
curl_setopt($curl, CURLOPT_POST, 1);
|
|
||||||
$data_string = json_encode($data);
|
|
||||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
|
||||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
|
||||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
|
||||||
$data = curl_exec($curl);
|
|
||||||
curl_close($curl);
|
|
||||||
return json_decode($data, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function mpcheckout($orderId, $data)
|
|
||||||
{
|
|
||||||
$headers = array('content-type: application/json', 'token: ' . $this->bitpayxAppSecret);
|
|
||||||
$curl = curl_init();
|
|
||||||
$url = $this->bitpayxGatewayUri . 'orders/' . $orderId . '/checkout';
|
|
||||||
curl_setopt($curl, CURLOPT_URL, $url);
|
|
||||||
curl_setopt($curl, CURLOPT_POST, 1);
|
|
||||||
$data_string = json_encode($data);
|
|
||||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
|
||||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
|
||||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
|
||||||
$data = curl_exec($curl);
|
|
||||||
curl_close($curl);
|
|
||||||
return json_decode($data, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function refund($merchantTradeNo)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function buildHtml($params, $method = 'post', $target = '_self')
|
|
||||||
{
|
|
||||||
// var_dump($params);exit;
|
|
||||||
$html = "<form id='submit' name='submit' action='" . $this->gatewayUri . "' method='$method' target='$target'>";
|
|
||||||
foreach ($params as $key => $value) {
|
|
||||||
$html .= "<input type='hidden' name='$key' value='$value'/>";
|
|
||||||
}
|
|
||||||
$html .= "</form><script>document.forms['submit'].submit();</script>";
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Library;
|
|
||||||
|
|
||||||
class Epay
|
|
||||||
{
|
|
||||||
private $pid;
|
|
||||||
private $key;
|
|
||||||
private $url;
|
|
||||||
|
|
||||||
public function __construct($url, $pid, $key)
|
|
||||||
{
|
|
||||||
$this->pid = $pid;
|
|
||||||
$this->key = $key;
|
|
||||||
$this->url = $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pay($params)
|
|
||||||
{
|
|
||||||
$params['pid'] = $this->pid;
|
|
||||||
ksort($params);
|
|
||||||
reset($params);
|
|
||||||
$str = stripslashes(urldecode(http_build_query($params))) . $this->key;
|
|
||||||
$params['sign'] = md5($str);
|
|
||||||
$params['sign_type'] = 'MD5';
|
|
||||||
return $this->url . '/submit.php?' . http_build_query($params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function verify($params)
|
|
||||||
{
|
|
||||||
$sign = $params['sign'];
|
|
||||||
unset($params['sign']);
|
|
||||||
unset($params['sign_type']);
|
|
||||||
ksort($params);
|
|
||||||
reset($params);
|
|
||||||
$str = stripslashes(urldecode(http_build_query($params))) . $this->key;
|
|
||||||
if ($sign !== md5($str)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Library;
|
|
||||||
|
|
||||||
use \Curl\Curl;
|
|
||||||
|
|
||||||
class MGate
|
|
||||||
{
|
|
||||||
private $appId;
|
|
||||||
private $appSecret;
|
|
||||||
private $url;
|
|
||||||
|
|
||||||
public function __construct($url, $appId, $appSecret)
|
|
||||||
{
|
|
||||||
$this->appId = $appId;
|
|
||||||
$this->appSecret = $appSecret;
|
|
||||||
$this->url = $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pay($params)
|
|
||||||
{
|
|
||||||
ksort($params);
|
|
||||||
$str = http_build_query($params) . $this->appSecret;
|
|
||||||
$params['sign'] = md5($str);
|
|
||||||
$curl = new Curl();
|
|
||||||
$curl->post($this->url . '/v1/gateway/fetch', http_build_query($params));
|
|
||||||
$result = $curl->response;
|
|
||||||
if (!$result) {
|
|
||||||
abort(500, '网络异常');
|
|
||||||
}
|
|
||||||
if ($curl->error) {
|
|
||||||
if (isset($result->errors)) {
|
|
||||||
$errors = (array)$result->errors;
|
|
||||||
abort(500, $errors[array_keys($errors)[0]][0]);
|
|
||||||
}
|
|
||||||
if (isset($result->message)) {
|
|
||||||
abort(500, $result->message);
|
|
||||||
}
|
|
||||||
abort(500, '未知错误');
|
|
||||||
}
|
|
||||||
$curl->close();
|
|
||||||
if (!isset($result->data->trade_no)) {
|
|
||||||
abort(500, '接口请求失败');
|
|
||||||
}
|
|
||||||
return $result->data->pay_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function verify($params)
|
|
||||||
{
|
|
||||||
$sign = $params['sign'];
|
|
||||||
unset($params['sign']);
|
|
||||||
ksort($params);
|
|
||||||
reset($params);
|
|
||||||
$str = http_build_query($params) . $this->appSecret;
|
|
||||||
if ($sign !== md5($str)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
2
public/assets/admin/components.async.js
vendored
2
public/assets/admin/components.async.js
vendored
File diff suppressed because one or more lines are too long
16
public/assets/admin/components.chunk.css
vendored
16
public/assets/admin/components.chunk.css
vendored
File diff suppressed because one or more lines are too long
2
public/assets/admin/umi.js
vendored
2
public/assets/admin/umi.js
vendored
File diff suppressed because one or more lines are too long
2
public/assets/admin/vendors.async.js
vendored
2
public/assets/admin/vendors.async.js
vendored
File diff suppressed because one or more lines are too long
2
public/assets/user/components.async.js
vendored
2
public/assets/user/components.async.js
vendored
File diff suppressed because one or more lines are too long
4
public/assets/user/env.example.js
vendored
4
public/assets/user/env.example.js
vendored
@ -12,5 +12,7 @@ window.settings = {
|
|||||||
color: 'default'
|
color: 'default'
|
||||||
},
|
},
|
||||||
// 背景
|
// 背景
|
||||||
background_url: ''
|
background_url: '',
|
||||||
|
// crisp
|
||||||
|
crisp_id: ''
|
||||||
}
|
}
|
||||||
|
2
public/assets/user/umi.css
vendored
2
public/assets/user/umi.css
vendored
File diff suppressed because one or more lines are too long
2
public/assets/user/umi.js
vendored
2
public/assets/user/umi.js
vendored
File diff suppressed because one or more lines are too long
2
public/assets/user/vendors.async.js
vendored
2
public/assets/user/vendors.async.js
vendored
File diff suppressed because one or more lines are too long
@ -104,7 +104,7 @@ return [
|
|||||||
],
|
],
|
||||||
'stripeCard' => [
|
'stripeCard' => [
|
||||||
'currency_convert_timeout' => 'Currency conversion has timed out, please try again later',
|
'currency_convert_timeout' => 'Currency conversion has timed out, please try again later',
|
||||||
'was_problem' => 'Oops, there's a problem... Please refresh the page and try again later',
|
'was_problem' => "Oops, there's a problem... Please refresh the page and try again later",
|
||||||
'deduction_failed' => 'Payment failed. Please check your credit card information'
|
'deduction_failed' => 'Payment failed. Please check your credit card information'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
@ -112,6 +112,9 @@ return [
|
|||||||
'fetch' => [
|
'fetch' => [
|
||||||
'knowledge_not_exist' => 'Article does not exist',
|
'knowledge_not_exist' => 'Article does not exist',
|
||||||
'apple_id_must_be_plan' => 'No active subscription. Unable to use our provided Apple ID'
|
'apple_id_must_be_plan' => 'No active subscription. Unable to use our provided Apple ID'
|
||||||
|
],
|
||||||
|
'formatAccessData' => [
|
||||||
|
'no_access' => 'You must have a valid subscription to view content in this area'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'invite' => [
|
'invite' => [
|
||||||
|
@ -112,6 +112,9 @@ return [
|
|||||||
'fetch' => [
|
'fetch' => [
|
||||||
'knowledge_not_exist' => '文章不存在',
|
'knowledge_not_exist' => '文章不存在',
|
||||||
'apple_id_must_be_plan' => '无有效订阅,无法使用本站提供的 AppleID'
|
'apple_id_must_be_plan' => '无有效订阅,无法使用本站提供的 AppleID'
|
||||||
|
],
|
||||||
|
'formatAccessData' => [
|
||||||
|
'no_access' => '你必须拥有有效的订阅才可以查看该区域的内容'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'invite' => [
|
'invite' => [
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
},
|
},
|
||||||
verison: '{{$verison}}',
|
verison: '{{$verison}}',
|
||||||
background_url: '{{$backgroun_url}}',
|
background_url: '{{$backgroun_url}}',
|
||||||
description: '{{$description}}'
|
description: '{{$description}}',
|
||||||
|
crisp_id: '{{$crisp_id}}'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
@ -26,7 +26,8 @@ Route::get('/', function (Request $request) {
|
|||||||
'theme_color' => config('v2board.frontend_theme_color', 'default'),
|
'theme_color' => config('v2board.frontend_theme_color', 'default'),
|
||||||
'backgroun_url' => config('v2board.frontend_background_url'),
|
'backgroun_url' => config('v2board.frontend_background_url'),
|
||||||
'verison' => config('app.version'),
|
'verison' => config('app.version'),
|
||||||
'description' => config('v2board.app_description', 'V2Board is best')
|
'description' => config('v2board.app_description', 'V2Board is best'),
|
||||||
|
'crisp_id' => config('v2board.frontend_customer_service_method') === 'crisp' ? config('v2board.frontend_customer_service_id') : ''
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user