Compare commits

...

39 Commits

Author SHA1 Message Date
wouiSB
3d747adb7c
Merge c8baf937dc into d57c3ca60d 2025-01-14 10:42:17 +01:00
xboard
d57c3ca60d Revert "update docs"
Some checks failed
Docker / build (push) Has been cancelled
This reverts commit 558834b154.
2025-01-13 07:57:07 +08:00
Xboard
558834b154
update docs 2025-01-13 07:55:19 +08:00
Xboard
a60b23b17d
Merge pull request #280 from longdoer/patch-1
Some checks failed
Docker / build (push) Has been cancelled
Update ClashMeta.php
2025-01-10 13:37:11 +08:00
Xboard
6aee3ea40e
Merge pull request #295 from sechk777/patch-1
Update default.sing-box.json
2025-01-10 13:36:28 +08:00
Xboard
89d2aed46d Revert "Update 1panel安装指南.md"
Some checks are pending
Docker / build (push) Waiting to run
This reverts commit ae249f8e96.
2025-01-09 23:57:38 +00:00
xboard
cf44a62db7 Revert "Update 1panel安装指南.md"
Some checks failed
Docker / build (push) Has been cancelled
This reverts commit cddcb144ef.
2025-01-09 10:15:24 +08:00
xboard
5b3474a06d Revert "update docker-compose安装指南.md"
This reverts commit dde41da139.
2025-01-09 10:15:21 +08:00
Xboard
dde41da139
update docker-compose安装指南.md
Some checks are pending
Docker / build (push) Waiting to run
2025-01-08 10:43:06 -05:00
Xboard
cddcb144ef
Update 1panel安装指南.md
Some checks are pending
Docker / build (push) Waiting to run
2025-01-07 17:14:46 -05:00
Xboard
ae249f8e96
Update 1panel安装指南.md 2025-01-07 17:14:07 -05:00
Xboard
9bc1d7a286
Merge pull request #136 from linusxiong/dev
Some checks are pending
Docker / build (push) Waiting to run
[update] 新增stripe聚合支付方式,采用全新的paymentIntents API
2025-01-07 10:56:12 +08:00
大大白
256ca28e00
Merge branch 'cedar2025:dev' into dev 2024-12-31 13:36:02 -05:00
seck
d6b7ae6404
Update default.sing-box.json
The inet4_address and inet6_address types have been consolidated into a unified address type, in alignment with the official documentation.
2024-12-19 15:34:58 +08:00
大大白
654f1f84fb
Update supervisord.conf 2024-12-08 04:58:38 -05:00
Linus Xiong
aa3ff5cb66
fix bug 2024-12-08 01:48:49 -05:00
大大白
22ffe0dace
Update Dockerfile 2024-12-08 01:38:27 -05:00
大大白
dee7525bb4
Update Dockerfile 2024-12-08 01:10:00 -05:00
Linus Xiong
cfc8a05cba
fix bugs 2024-12-08 01:05:38 -05:00
Linus Xiong
1378fdb45b
fix bugs 2024-12-08 00:58:58 -05:00
Linus Xiong
c4595bc665
use docker env on .env file 2024-12-08 00:53:43 -05:00
大大白
1d9cb2295c
Merge branch 'cedar2025:dev' into dev 2024-12-01 21:04:35 -05:00
longdoer
ddac216e2d
Update ClashMeta.php
增加ClashMeta首页链接
2024-11-19 16:45:52 +08:00
大大白
e482b72430
Merge branch 'cedar2025:dev' into dev 2024-11-14 17:05:23 -05:00
大大白
6cfdd1c9b1
Update Surge.php
support surge ss2022
2024-10-18 12:42:51 -04:00
大大白
1d36069726
Merge branch 'cedar2025:dev' into dev 2024-10-16 19:37:04 -04:00
大大白
190e64b7c2
Merge branch 'cedar2025:dev' into dev 2024-09-16 00:09:09 -04:00
大大白
b0fcc9244a
Merge branch 'cedar2025:dev' into dev 2024-07-20 04:11:24 +08:00
LinusX
acb40cc1f9
[update] 新增credit card跳转至checkout页面付款 2024-07-02 19:02:29 +08:00
LinusX
f0c620cbc2
[fix] 删除重复包导入 2024-06-17 22:58:53 +08:00
LinusX
8cc247b653
[feat] 新增telegram机器人/start指令 2024-06-15 02:16:54 +08:00
LinusX
bab7ed8e97
[fix] 修复catch的时候变量可能undefined的问题 2024-06-15 01:42:43 +08:00
大大白
0389edd4d0
Merge branch 'cedar2025:dev' into dev 2024-06-15 01:05:54 +08:00
大大白
338aad7f6c
Fix PaymentController.php
修复由Jun 8, 2024提交的2个commit产生的报错
2024-06-13 23:25:23 +08:00
大大白
fc283af60f
Update StripeALLInOne.php
删除调试冗余代码
2024-06-13 18:47:04 +08:00
大大白
9270d94668
Update StripeALLInOne.php
修复部分报错语句不规范
2024-06-13 18:40:40 +08:00
大大白
5cc0b77982
Merge branch 'cedar2025:dev' into dev 2024-06-13 18:39:03 +08:00
wouiSB
c8baf937dc
feat: distribute vless nodes to stash 2024-06-05 09:42:32 +08:00
LinusX
261487437b [update] 新增stripe聚合支付方式,采用全新的paymentIntents API
[fix] 修改支付方式中的小bug
[update] 将stripe-php版本升级至最新
2024-06-05 07:55:49 +08:00
14 changed files with 292 additions and 51 deletions

View File

@ -17,6 +17,7 @@ directory=/www
command=sh -c "chown -R www:www /www && chmod -R 775 /www"
autostart=true
autorestart=false
priority=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
@ -25,6 +26,7 @@ stderr_logfile_maxbytes=0
[program:nginx]
command=nginx -g 'daemon off;'
user=root
priority=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
@ -36,6 +38,7 @@ startretries=10
[program:cron]
command=crond -f -l 8
user=root
priority=4
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
@ -62,6 +65,8 @@ command=php -c php.ini webman.php start
directory=/www
user=www
numprocs=1
priority=2
startsecs=3
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
@ -74,6 +79,7 @@ startretries=10
command=php artisan horizon
directory=/www
user=www
priority=3
stdout_logfile=/www/storage/logs/queue.log
stdout_logfile_maxbytes=0
stderr_logfile=/www/storage/logs/queue_error.log

2
.env.example Executable file → Normal file
View File

@ -40,4 +40,4 @@ GOOGLE_CLOUD_KEY_FILE=config/googleCloudStorageKey.json
GOOGLE_CLOUD_STORAGE_BUCKET=
# 用于阻止重复安装
INSTALLED=false
INSTALLED=false

View File

@ -11,7 +11,8 @@ COPY .docker /
COPY . /www
RUN composer install --optimize-autoloader --no-cache --no-dev \
&& php artisan storage:link \
&& cp /www/.env.example /www/.env \
&& chown -R www:www /www \
&& chmod -R 775 /www
CMD /usr/bin/supervisord --nodaemon -c /etc/supervisor/supervisord.conf
CMD ["/usr/bin/supervisord", "--nodaemon", "-c", "/etc/supervisor/supervisord.conf"]

View File

@ -26,9 +26,10 @@ class BackupDatabase extends Command
}
// 数据库备份逻辑
$databaseBackupPath = storage_path('backup/' . now()->format('Y-m-d_H-i-s') . '_' . config('database.connections.mysql.database') . '_database_backup.sql');
$compressedBackupPath = $databaseBackupPath . '.gz';
try{
if (config('database.default') === 'mysql'){
$databaseBackupPath = storage_path('backup/' . now()->format('Y-m-d_H-i-s') . '_' . config('database.connections.mysql.database') . '_database_backup.sql');
$this->info("1开始备份Mysql");
\Spatie\DbDumper\Databases\MySql::create()
->setHost(config('database.connections.mysql.host'))
@ -83,7 +84,7 @@ class BackupDatabase extends Command
$bucket->upload(fopen($compressedBackupPath, 'r'), [
'name' => $objectName,
]);
// 输出文件链接
\Log::channel('backup')->info("🎉:数据库备份已上传到 Google Cloud Storage: $objectName");
$this->info("🎉:数据库备份已上传到 Google Cloud Storage: $objectName");

View File

@ -57,7 +57,7 @@ class PaymentController extends Controller
$payment->name,
$order->trade_no
);
$telegramService->sendMessageWithAdmin($message);
return true;
}

View File

@ -76,14 +76,13 @@ class BTCPay
//NOT BTCPay-Sig
//API doc is WRONG!
$headerName = 'Btcpay-Sig';
$signraturHeader = isset($headers[$headerName]) ? $headers[$headerName] : '';
$signatureHeader = isset($headers[$headerName]) ? $headers[$headerName] : '';
$json_param = json_decode($payload, true);
$computedSignature = "sha256=" . \hash_hmac('sha256', $payload, $this->config['btcpay_webhook_key']);
if (!self::hashEqual($signraturHeader, $computedSignature)) {
if (!self::hashEqual($signatureHeader, $computedSignature)) {
throw new ApiException('HMAC signature does not match', 400);
return false;
}
//get order id store in metadata

View File

@ -0,0 +1,210 @@
<?php
/**
* 自己写别抄抄NMB抄
*/
namespace App\Payments;
use App\Exceptions\ApiException;
class StripeALLInOne {
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'currency' => [
'label' => '货币单位',
'description' => '请使用符合ISO 4217标准的三位字母例如GBP',
'type' => 'input',
],
'stripe_sk_live' => [
'label' => 'SK_LIVE',
'description' => '',
'type' => 'input',
],
'stripe_webhook_key' => [
'label' => 'WebHook密钥签名',
'description' => 'whsec_....',
'type' => 'input',
],
'description' => [
'label' => '自定义商品介绍',
'description' => '',
'type' => 'input',
],
'payment_method' => [
'label' => '支付方式',
'description' => '请输入alipay, wechat_pay, cards',
'type' => 'input',
]
];
}
public function pay($order)
{
$currency = $this->config['currency'];
$exchange = $this->exchange('CNY', strtoupper($currency));
if (!$exchange) {
throw new ApiException('Currency conversion has timed out, please try again later', 500);
}
//jump url
$jumpUrl = null;
$actionType = 0;
$stripe = new \Stripe\StripeClient($this->config['stripe_sk_live']);
if ($this->config['payment_method'] != "cards"){
$stripePaymentMethod = $stripe->paymentMethods->create([
'type' => $this->config['payment_method'],
]);
// 准备支付意图的基础参数
$params = [
'amount' => floor($order['total_amount'] * $exchange),
'currency' => $currency,
'confirm' => true,
'payment_method' => $stripePaymentMethod->id,
'automatic_payment_methods' => ['enabled' => true],
'statement_descriptor' => 'sub-' . $order['user_id'] . '-' . substr($order['trade_no'], -8),
'description' => $this->config['description'],
'metadata' => [
'user_id' => $order['user_id'],
'out_trade_no' => $order['trade_no'],
'identifier' => ''
],
'return_url' => $order['return_url']
];
// 如果支付方式为 wechat_pay添加相应的支付方式选项
if ($this->config['payment_method'] === 'wechat_pay') {
$params['payment_method_options'] = [
'wechat_pay' => [
'client' => 'web'
],
];
}
//更新支持最新的paymentIntents方法Sources API将在今年被彻底替
$stripeIntents = $stripe->paymentIntents->create($params);
$nextAction = null;
if (!$stripeIntents['next_action']) {
throw new ApiException(__('Payment gateway request failed'));
}else {
$nextAction = $stripeIntents['next_action'];
}
switch ($this->config['payment_method']){
case "alipay":
if (isset($nextAction['alipay_handle_redirect'])){
$jumpUrl = $nextAction['alipay_handle_redirect']['url'];
$actionType = 1;
}else {
throw new ApiException('unable get Alipay redirect url', 500);
}
break;
case "wechat_pay":
if (isset($nextAction['wechat_pay_display_qr_code'])){
$jumpUrl = $nextAction['wechat_pay_display_qr_code']['data'];
}else {
throw new ApiException('unable get WeChat Pay redirect url', 500);
}
}
} else {
$creditCheckOut = $stripe->checkout->sessions->create([
'success_url' => $order['return_url'],
'client_reference_id' => $order['trade_no'],
'payment_method_types' => ['card'],
'line_items' => [
[
'price_data' => [
'currency' => $currency,
'unit_amount' => floor($order['total_amount'] * $exchange),
'product_data' => [
'name' => 'sub-' . $order['user_id'] . '-' . substr($order['trade_no'], -8),
'description' => $this->config['description'],
]
],
'quantity' => 1,
],
],
'mode' => 'payment',
]);
$jumpUrl = $creditCheckOut['url'];
$actionType = 1;
}
return [
'type' => $actionType,
'data' => $jumpUrl
];
}
public function notify($params)
{
try {
\Stripe\Stripe::setApiKey($this->config['stripe_sk_live']);
//Workerman不支持使用php://input, stripe同时要求验证签名的payload不能经过修改所以使用这个方法
$payload = $GLOBALS['HTTP_RAW_POST_DATA'];
$headers = getallheaders();
$headerName = 'Stripe-Signature';
$signatureHeader = $headers[$headerName] ?? '';
$event = \Stripe\Webhook::constructEvent(
$payload,
$signatureHeader,
$this->config['stripe_webhook_key']
);
} catch (\UnexpectedValueException $e){
throw new ApiException('Error parsing payload', 400);
}
catch (\Stripe\Exception\SignatureVerificationException $e) {
throw new ApiException('signature not match', 400);
}
switch ($event->type) {
case 'payment_intent.succeeded':
$object = $event->data->object;
if ($object->status === 'succeeded') {
if (!isset($object->metadata->out_trade_no)) {
return('order error');
}
$metaData = $object->metadata;
$tradeNo = $metaData->out_trade_no;
return [
'trade_no' => $tradeNo,
'callback_no' => $object->id
];
}
break;
case 'checkout.session.completed':
$object = $event->data->object;
if ($object->payment_status === 'paid') {
return [
'trade_no' => $object->client_reference_id,
'callback_no' => $object->payment_intent
];
}
break;
case 'checkout.session.async_payment_succeeded':
$object = $event->data->object;
return [
'trade_no' => $object->client_reference_id,
'callback_no' => $object->payment_intent
];
break;
default:
throw new ApiException('event is not support');
}
return('success');
}
private function exchange($from, $to)
{
$from = strtolower($from);
$to = strtolower($to);
$result = file_get_contents("https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/" . $from . ".min.json");
$result = json_decode($result, true);
return $result[$from][$to];
}
}

View File

@ -7,7 +7,7 @@ use App\Plugins\Telegram\Telegram;
class GetLatestUrl extends Telegram {
public $command = '/getlatesturl';
public $description = '将Telegram账号绑定到网站';
public $description = '获取网站最新网址';
public function handle($message, $match = []) {
$telegramService = $this->telegramService;

View File

@ -0,0 +1,17 @@
<?php
namespace App\Plugins\Telegram\Commands;
use App\Plugins\Telegram\Telegram;
class Start extends Telegram {
public $command = '/start';
public $description = 'telegram机器人初始化';
public function handle($message, $match = []) {
if (!$message->is_private) return;
$telegramService = $this->telegramService;
$text = "/start 显示所有可用指令\n /bind+空格+订阅链接将telegram绑定至账户\n /traffic 获取当前使用流量 \n /getlatesturl 获取网站最新网址 \n /unbind 解绑telegram账户";
$telegramService->sendMessage($message->chat_id, $text, 'markdown');
}
}

View File

@ -88,7 +88,8 @@ class ClashMeta
return response($yaml, 200)
->header('subscription-userinfo', "upload={$user['u']}; download={$user['d']}; total={$user['transfer_enable']}; expire={$user['expired_at']}")
->header('profile-update-interval', '24')
->header('content-disposition', 'attachment;filename*=UTF-8\'\'' . rawurlencode($appName));
->header('content-disposition', 'attachment;filename*=UTF-8\'\'' . rawurlencode($appName))
->header('profile-web-page-url', admin_setting('app_url'));
}
/**

View File

@ -52,10 +52,16 @@ class Stash
array_push($proxy, self::buildVmess($user['uuid'], $item));
array_push($proxies, $item['name']);
}
// if ($item['type'] === 'vless') {
// array_push($proxy, self::buildVless($user['uuid'], $item));
// array_push($proxies, $item['name']);
// }
if ($item['type'] === 'vless') {
if ($item['flow'] === 'xtls-rprx-vision') {
continue;
}
if ($item['tls'] === 2) {
continue;
}
array_push($proxy, self::buildVless($user['uuid'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'hysteria') {
array_push($proxy, self::buildHysteria($user['uuid'], $item));
array_push($proxies, $item['name']);
@ -169,56 +175,50 @@ class Stash
return $array;
}
public static function buildVless($uuid, $server)
{
public static function buildVless($password, $server){
$array = [];
$array['name'] = $server['name'];
$array['type'] = 'vless';
$array['server'] = $server['host'];
$array['port'] = $server['port'];
$array['uuid'] = $uuid;
$array['flow'] = !empty($server['flow']) ? $server['flow']: "";
$array['uuid'] = $password;
$array['alterId'] = 0;
$array['cipher'] = 'auto';
$array['udp'] = true;
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
$array['client-fingerprint'] = $fingerprints[rand(0,count($fingerprints) - 1)];
// XTLS流控算法
if($server['flow']) ($array['flow'] = $server['flow']);
if ($server['tls']) {
$array['tls'] = true;
switch($server['tls']){
case 1:
case 1: //开启TLS
$array['tls'] = true;
if ($server['tls_settings']) {
$tlsSettings = $server['tls_settings'];
if (isset($tlsSettings['allowInsecure']) && !empty($tlsSettings['allowInsecure']))
$array['skip-cert-verify'] = ($tlsSettings['allowInsecure'] ? true : false);
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
$array['servername'] = $tlsSettings['server_name'];
}
break;
case 2:
if (!isset($server['network_settings'])) break;
$networkSettings = $server['network_settings'];
if (isset($networkSettings['reality-opts'])){
$realitySettings = $networkSettings['reality-opts'];
$array['reality-opts'] = [];
$array['reality-opts']['public-key'] = $realitySettings['public-key'];
$array['reality-opts']['short-id'] = $realitySettings['short-id'];
}
case 2: //开启reality
$array['tls'] = true;
$tls_settings = $server['tls_settings'];
if (!empty($tls_settings['allowInsecure'])) $array['skip-cert-verify'] = (bool)$tls_settings['allowInsecure'];
if(($tls_settings['public_key'] ?? null)
&& ($tls_settings['short_id'] ?? null)
&& ($tls_settings['server_name'] ?? null)){
$array['servername'] = $tls_settings['server_name'];
$array['reality-opts'] = [
'public-key' => $tls_settings['public_key'],
'short-id' => $tls_settings['short_id']
];
$fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; //随机客户端指纹
$array['client-fingerprint'] = $fingerprints[rand(0,count($fingerprints) - 1)];
};
break;
}
}
if ($server['network'] === 'tcp') {
$tcpSettings = $server['networkSettings'];
if (isset($tcpSettings['header']['type']) && $tcpSettings['header']['type'] == 'http') {
$array['network'] = $tcpSettings['header']['type'];
if (isset($tcpSettings['header']['request']['headers']['Host'])){
$array['http-opts']['headers']['Host'] = $tcpSettings['header']['request']['headers']['Host'];
}
if (isset($tcpSettings['header']['request']['path'][0])){
$paths = $tcpSettings['header']['request']['path'];
$array['http-opts']['path'] = $paths[array_rand($paths)];
};
}
}
if ($server['network'] === 'ws') {
@ -241,7 +241,9 @@ class Stash
if ($server['network_settings']) {
$grpcSettings = $server['network_settings'];
$array['grpc-opts'] = [];
if (isset($grpcSettings['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
if (isset($grpcSettings['serviceName'])) {
$array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
};
}
}

View File

@ -32,7 +32,9 @@ class Surge
'aes-128-gcm',
'aes-192-gcm',
'aes-256-gcm',
'chacha20-ietf-poly1305'
'chacha20-ietf-poly1305',
'2022-blake3-aes-128-gcm',
'2022-blake3-aes-256-gcm',
])
) {
// [Proxy]

View File

@ -28,7 +28,7 @@
"paragonie/sodium_compat": "^1.20",
"php-curl-class/php-curl-class": "^8.6",
"spatie/db-dumper": "^3.4",
"stripe/stripe-php": "^7.36.1",
"stripe/stripe-php": "^v14.9.0",
"symfony/http-client": "^6.4",
"symfony/mailgun-mailer": "^6.4",
"symfony/yaml": "*",

View File

@ -49,8 +49,10 @@
"auto_route": true,
"domain_strategy": "prefer_ipv4",
"endpoint_independent_nat": true,
"inet4_address": "172.19.0.1/30",
"inet6_address": "2001:0470:f9da:fdfa::1/64",
"address": [
"172.19.0.1/30",
"2001:0470:f9da:fdfa::1/64"
],
"mtu": 9000,
"sniff": true,
"sniff_override_destination": true,