浏览代码

refactor: better null handle & add missing xss filter

M1Screw 2 年之前
父节点
当前提交
8fa018cd11

+ 1 - 1
README.md

@@ -27,7 +27,7 @@ SSPanel UIM 是一款专为 Shadowsocks / V2Ray / Trojan 协议设计的多用
 
 ## 特性
 
-- 集成 支付宝当面付,Stripe 银行卡,彩虹易支付 等多种支付系统
+- 集成 支付宝当面付,PayPal,Stripe 等多种支付系统
 - 支持多种邮件服务,内置队列功能,无需第三方组件即可使用
 - 内置基于 Bootstrap 5 的 tabler 主题,模板引擎支持
 - 支持 Shadowsocks 2022,TUIC 等最新代理协议

+ 58 - 58
composer.lock

@@ -123,16 +123,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.283.8",
+            "version": "3.283.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "0f73ec85852312a6e971cfe2eebfd7c8091cca34"
+                "reference": "0233b9f3f2155dac35c829ce4fc1b7cdb6ff8c0a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0f73ec85852312a6e971cfe2eebfd7c8091cca34",
-                "reference": "0f73ec85852312a6e971cfe2eebfd7c8091cca34",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0233b9f3f2155dac35c829ce4fc1b7cdb6ff8c0a",
+                "reference": "0233b9f3f2155dac35c829ce4fc1b7cdb6ff8c0a",
                 "shasum": ""
             },
             "require": {
@@ -212,9 +212,9 @@
             "support": {
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.283.8"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.283.9"
             },
-            "time": "2023-10-19T19:26:52+00:00"
+            "time": "2023-10-20T20:03:26+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -2660,39 +2660,39 @@
         },
         {
             "name": "openai-php/client",
-            "version": "v0.7.3",
+            "version": "v0.7.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/openai-php/client.git",
-                "reference": "86ffa2abe167d6192f01d4df90f83a97c8533303"
+                "reference": "bfa2f7e15909c01317064021cd3b15bc5bbd929b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/openai-php/client/zipball/86ffa2abe167d6192f01d4df90f83a97c8533303",
-                "reference": "86ffa2abe167d6192f01d4df90f83a97c8533303",
+                "url": "https://api.github.com/repos/openai-php/client/zipball/bfa2f7e15909c01317064021cd3b15bc5bbd929b",
+                "reference": "bfa2f7e15909c01317064021cd3b15bc5bbd929b",
                 "shasum": ""
             },
             "require": {
                 "php": "^8.1.0",
-                "php-http/discovery": "^1.19.0",
+                "php-http/discovery": "^1.19.1",
                 "php-http/multipart-stream-builder": "^1.3.0",
-                "psr/http-client": "^1.0.2",
+                "psr/http-client": "^1.0.3",
                 "psr/http-client-implementation": "^1.0.1",
                 "psr/http-factory-implementation": "*",
                 "psr/http-message": "^1.1.0|^2.0.0"
             },
             "require-dev": {
-                "guzzlehttp/guzzle": "^7.7.0",
-                "guzzlehttp/psr7": "^2.5.0",
-                "laravel/pint": "^1.10.3",
-                "nunomaduro/collision": "^7.7.0",
-                "pestphp/pest": "^2.16.0",
-                "pestphp/pest-plugin-arch": "^2.2.1",
+                "guzzlehttp/guzzle": "^7.8.0",
+                "guzzlehttp/psr7": "^2.6.1",
+                "laravel/pint": "^1.13.2",
+                "nunomaduro/collision": "^7.9.0",
+                "pestphp/pest": "^2.19.2",
+                "pestphp/pest-plugin-arch": "^2.3.3",
                 "pestphp/pest-plugin-mock": "^2.0.0",
-                "pestphp/pest-plugin-type-coverage": "^2.0.0",
-                "phpstan/phpstan": "^1.10.25",
+                "pestphp/pest-plugin-type-coverage": "^2.2.0",
+                "phpstan/phpstan": "^1.10.35",
                 "rector/rector": "^0.16.0",
-                "symfony/var-dumper": "^6.3.1"
+                "symfony/var-dumper": "^6.3.4"
             },
             "type": "library",
             "autoload": {
@@ -2732,7 +2732,7 @@
             ],
             "support": {
                 "issues": "https://github.com/openai-php/client/issues",
-                "source": "https://github.com/openai-php/client/tree/v0.7.3"
+                "source": "https://github.com/openai-php/client/tree/v0.7.4"
             },
             "funding": [
                 {
@@ -2748,7 +2748,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2023-09-08T08:48:59+00:00"
+            "time": "2023-10-21T09:00:06+00:00"
         },
         {
             "name": "ozdemir/datatables",
@@ -4966,16 +4966,16 @@
         },
         {
             "name": "symfony/http-client",
-            "version": "v6.3.5",
+            "version": "v6.3.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-client.git",
-                "reference": "213e564da4cbf61acc9728d97e666bcdb868c10d"
+                "reference": "ab8446f997efb9913627e9da10fa784d2182fe92"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-client/zipball/213e564da4cbf61acc9728d97e666bcdb868c10d",
-                "reference": "213e564da4cbf61acc9728d97e666bcdb868c10d",
+                "url": "https://api.github.com/repos/symfony/http-client/zipball/ab8446f997efb9913627e9da10fa784d2182fe92",
+                "reference": "ab8446f997efb9913627e9da10fa784d2182fe92",
                 "shasum": ""
             },
             "require": {
@@ -5038,7 +5038,7 @@
                 "http"
             ],
             "support": {
-                "source": "https://github.com/symfony/http-client/tree/v6.3.5"
+                "source": "https://github.com/symfony/http-client/tree/v6.3.6"
             },
             "funding": [
                 {
@@ -5054,7 +5054,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-09-29T15:57:12+00:00"
+            "time": "2023-10-06T10:08:56+00:00"
         },
         {
             "name": "symfony/http-client-contracts",
@@ -5136,16 +5136,16 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v6.3.5",
+            "version": "v6.3.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-foundation.git",
-                "reference": "b50f5e281d722cb0f4c296f908bacc3e2b721957"
+                "reference": "c186627f52febe09c6d5270b04f8462687a250a6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b50f5e281d722cb0f4c296f908bacc3e2b721957",
-                "reference": "b50f5e281d722cb0f4c296f908bacc3e2b721957",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/c186627f52febe09c6d5270b04f8462687a250a6",
+                "reference": "c186627f52febe09c6d5270b04f8462687a250a6",
                 "shasum": ""
             },
             "require": {
@@ -5155,12 +5155,12 @@
                 "symfony/polyfill-php83": "^1.27"
             },
             "conflict": {
-                "symfony/cache": "<6.2"
+                "symfony/cache": "<6.3"
             },
             "require-dev": {
-                "doctrine/dbal": "^2.13.1|^3.0",
+                "doctrine/dbal": "^2.13.1|^3|^4",
                 "predis/predis": "^1.1|^2.0",
-                "symfony/cache": "^5.4|^6.0",
+                "symfony/cache": "^6.3",
                 "symfony/dependency-injection": "^5.4|^6.0",
                 "symfony/expression-language": "^5.4|^6.0",
                 "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
@@ -5193,7 +5193,7 @@
             "description": "Defines an object-oriented layer for the HTTP specification",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-foundation/tree/v6.3.5"
+                "source": "https://github.com/symfony/http-foundation/tree/v6.3.6"
             },
             "funding": [
                 {
@@ -5209,7 +5209,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-09-04T21:33:54+00:00"
+            "time": "2023-10-17T11:32:53+00:00"
         },
         {
             "name": "symfony/options-resolver",
@@ -6014,16 +6014,16 @@
         },
         {
             "name": "symfony/translation",
-            "version": "v6.3.3",
+            "version": "v6.3.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/translation.git",
-                "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd"
+                "reference": "869b26c7a9d4b8a48afdd77ab36031909c87e3a2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation/zipball/3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd",
-                "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/869b26c7a9d4b8a48afdd77ab36031909c87e3a2",
+                "reference": "869b26c7a9d4b8a48afdd77ab36031909c87e3a2",
                 "shasum": ""
             },
             "require": {
@@ -6089,7 +6089,7 @@
             "description": "Provides tools to internationalize your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/translation/tree/v6.3.3"
+                "source": "https://github.com/symfony/translation/tree/v6.3.6"
             },
             "funding": [
                 {
@@ -6105,7 +6105,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-07-31T07:08:24+00:00"
+            "time": "2023-10-17T11:32:53+00:00"
         },
         {
             "name": "symfony/translation-contracts",
@@ -9239,16 +9239,16 @@
         },
         {
             "name": "symfony/cache",
-            "version": "v6.3.5",
+            "version": "v6.3.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/cache.git",
-                "reference": "6c1a3ea078c4d88ee892530945df63a87981b2da"
+                "reference": "84aff8d948d6292d2b5a01ac622760be44dddc72"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/cache/zipball/6c1a3ea078c4d88ee892530945df63a87981b2da",
-                "reference": "6c1a3ea078c4d88ee892530945df63a87981b2da",
+                "url": "https://api.github.com/repos/symfony/cache/zipball/84aff8d948d6292d2b5a01ac622760be44dddc72",
+                "reference": "84aff8d948d6292d2b5a01ac622760be44dddc72",
                 "shasum": ""
             },
             "require": {
@@ -9257,7 +9257,7 @@
                 "psr/log": "^1.1|^2|^3",
                 "symfony/cache-contracts": "^2.5|^3",
                 "symfony/service-contracts": "^2.5|^3",
-                "symfony/var-exporter": "^6.2.10"
+                "symfony/var-exporter": "^6.3.6"
             },
             "conflict": {
                 "doctrine/dbal": "<2.13.1",
@@ -9272,7 +9272,7 @@
             },
             "require-dev": {
                 "cache/integration-tests": "dev-master",
-                "doctrine/dbal": "^2.13.1|^3.0",
+                "doctrine/dbal": "^2.13.1|^3|^4",
                 "predis/predis": "^1.1|^2.0",
                 "psr/simple-cache": "^1.0|^2.0|^3.0",
                 "symfony/config": "^5.4|^6.0",
@@ -9315,7 +9315,7 @@
                 "psr6"
             ],
             "support": {
-                "source": "https://github.com/symfony/cache/tree/v6.3.5"
+                "source": "https://github.com/symfony/cache/tree/v6.3.6"
             },
             "funding": [
                 {
@@ -9331,7 +9331,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-09-26T15:48:55+00:00"
+            "time": "2023-10-17T14:44:58+00:00"
         },
         {
             "name": "symfony/cache-contracts",
@@ -10072,16 +10072,16 @@
         },
         {
             "name": "symfony/var-exporter",
-            "version": "v6.3.4",
+            "version": "v6.3.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-exporter.git",
-                "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691"
+                "reference": "374d289c13cb989027274c86206ddc63b16a2441"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df1f8aac5751871b83d30bf3e2c355770f8f0691",
-                "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691",
+                "url": "https://api.github.com/repos/symfony/var-exporter/zipball/374d289c13cb989027274c86206ddc63b16a2441",
+                "reference": "374d289c13cb989027274c86206ddc63b16a2441",
                 "shasum": ""
             },
             "require": {
@@ -10126,7 +10126,7 @@
                 "serialize"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-exporter/tree/v6.3.4"
+                "source": "https://github.com/symfony/var-exporter/tree/v6.3.6"
             },
             "funding": [
                 {
@@ -10142,7 +10142,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-08-16T18:14:47+00:00"
+            "time": "2023-10-13T09:16:49+00:00"
         },
         {
             "name": "theseer/tokenizer",

+ 26 - 16
config/settings.json

@@ -109,6 +109,16 @@
         "default": "10",
         "mark": "最低充值限额"
     },
+    {
+        "id": null,
+        "item": "stripe_max_recharge",
+        "value": "1000",
+        "class": "billing",
+        "is_public": 1,
+        "type": "int",
+        "default": "1000",
+        "mark": "最高充值限额"
+    },
     {
         "id": null,
         "item": "stripe_card",
@@ -139,46 +149,46 @@
         "default": "0",
         "mark": "微信支付"
     },
-    {
-        "id": null,
-        "item": "stripe_max_recharge",
-        "value": "1000",
-        "class": "billing",
-        "is_public": 1,
-        "type": "int",
-        "default": "1000",
-        "mark": "最高充值限额"
-    },
     {
         "id": null,
         "item": "epay_url",
-        "value": "1000",
+        "value": "",
         "class": "billing",
         "is_public": 0,
         "type": "string",
-        "default": "1000",
+        "default": "",
         "mark": "易支付url"
     },
 	{
         "id": null,
         "item": "epay_pid",
-        "value": "1000",
+        "value": "",
         "class": "billing",
         "is_public": 0,
         "type": "string",
-        "default": "1000",
+        "default": "",
         "mark": "易支付商户ID"
     },
 	{
         "id": null,
         "item": "epay_key",
-        "value": "1000",
+        "value": "",
         "class": "billing",
         "is_public": 0,
         "type": "string",
-        "default": "1000",
+        "default": "",
         "mark": "易支付商户Key"
     },
+    {
+        "id": null,
+        "item": "epay_sign_type",
+        "value": "sha256",
+        "class": "billing",
+        "is_public": 0,
+        "type": "string",
+        "default": "sha256",
+        "mark": "易支付签名方式"
+    },
     {
         "id": null,
         "item": "epay_alipay",

+ 8 - 1
resources/views/tabler/admin/setting/billing.tpl

@@ -199,12 +199,19 @@
                                             </div>
                                         </div>
                                         <div class="form-group mb-3 row">
-                                            <label class="form-label col-3 col-form-label">密钥</label>
+                                            <label class="form-label col-3 col-form-label">商户Key</label>
                                             <div class="col">
                                                 <input id="epay_key" type="text" class="form-control"
                                                        value="{$settings['epay_key']}">
                                             </div>
                                         </div>
+                                        <div class="form-group mb-3 row">
+                                            <label class="form-label col-3 col-form-label">签名方式</label>
+                                            <div class="col">
+                                                <input id="epay_sign_type" type="text" class="form-control"
+                                                       value="{$settings['epay_sign_type']}">
+                                            </div>
+                                        </div>
                                         <div class="form-group mb-3 row">
                                             <label class="form-label col-3 col-form-label">支付宝</label>
                                             <div class="col">

+ 2 - 4
resources/views/tabler/gateway/stripe.tpl

@@ -13,10 +13,8 @@
         等标识的信用卡或借记卡</p>
     <form action="/user/payment/purchase/stripe" method="post">
         <div class="form-group form-group-label">
-            <label class="floating-label" for="amount-stripe-card">金额</label>
-            <input class="form-control maxwidth-edit" id="price" name="price"
-                   min="{$public_setting['stripe_min_recharge']}" max="{$public_setting['stripe_max_recharge']}"
-                   step="0.1" type="number" required="required">
+            <input id="price" name="price" value="{$invoice->price}" hidden>
+            <input id="invoice_id" name="invoice_id" value="{$invoice->id}" hidden>
             <button class="btn btn-flat waves-attach" type="submit"><i class="icon ti ti-credit-card"></i></button>
         </div>
     </form>

+ 1 - 0
src/Controllers/Admin/Setting/BillingController.php

@@ -34,6 +34,7 @@ final class BillingController extends BaseController
         'epay_url',
         'epay_pid',
         'epay_key',
+        'epay_sign_type',
         'epay_alipay',
         'epay_wechat',
         'epay_qq',

+ 15 - 18
src/Services/Gateway/AbstractPayment.php

@@ -16,7 +16,6 @@ use Slim\Http\ServerRequest;
 use function get_called_class;
 use function in_array;
 use function json_decode;
-use function json_encode;
 use function time;
 
 abstract class AbstractPayment
@@ -57,32 +56,30 @@ abstract class AbstractPayment
 
     abstract public static function getPurchaseHTML(): string;
 
-    public function postPayment($tradeno): false|int|string
+    public function postPayment($trade_no): void
     {
-        $paylist = Paylist::where('tradeno', $tradeno)->first();
+        $paylist = Paylist::where('tradeno', $trade_no)->first();
 
-        if ($paylist->status === 1) {
-            return json_encode(['errcode' => 0]);
+        if ($paylist?->status === 0) {
+            $paylist->datetime = time();
+            $paylist->status = 1;
+            $paylist->save();
         }
 
-        $paylist->datetime = time();
-        $paylist->status = 1;
-        $paylist->save();
+        $invoice = Invoice::where('id', $paylist?->invoice_id)->first();
 
-        $user = User::find($paylist->userid);
-
-        $invoice = Invoice::where('id', $paylist->invoice_id)->first();
-        $invoice->status = 'paid_gateway';
-        $invoice->update_time = time();
-        $invoice->pay_time = time();
-        $invoice->save();
+        if ($invoice?->status === 'unpaid' && (int) $invoice?->price === (int) $paylist?->total) {
+            $invoice->status = 'paid_gateway';
+            $invoice->update_time = time();
+            $invoice->pay_time = time();
+            $invoice->save();
+        }
 
+        $user = User::find($paylist?->userid);
         // 返利
-        if ($user->ref_by > 0 && Setting::obtain('invitation_mode') === 'after_paid') {
+        if ($user !== null && $user->ref_by > 0 && Setting::obtain('invitation_mode') === 'after_paid') {
             (new Payback())->rebate($user->id, $paylist->total);
         }
-
-        return 0;
     }
 
     public static function generateGuid(): string

+ 7 - 6
src/Services/Gateway/AopF2F.php

@@ -40,6 +40,7 @@ final class AopF2F extends AbstractPayment
 
         $price = $antiXss->xss_clean($request->getParam('amount'));
         $invoice_id = $antiXss->xss_clean($request->getParam('invoice_id'));
+        $trade_no = self::generateGuid();
 
         if ($price <= 0) {
             return $response->withJson([
@@ -54,7 +55,7 @@ final class AopF2F extends AbstractPayment
         $pl->userid = $user->id;
         $pl->total = $price;
         $pl->invoice_id = $invoice_id;
-        $pl->tradeno = self::generateGuid();
+        $pl->tradeno = $trade_no;
         $pl->gateway = self::_readableName();
 
         $pl->save();
@@ -63,9 +64,9 @@ final class AopF2F extends AbstractPayment
 
         $request = $gateway->purchase();
         $request->setBizContent([
-            'subject' => $pl->tradeno,
-            'out_trade_no' => $pl->tradeno,
-            'total_amount' => $pl->total,
+            'subject' => $trade_no,
+            'out_trade_no' => $trade_no,
+            'total_amount' => $price,
         ]);
 
         $aliResponse = $request->send();
@@ -76,8 +77,8 @@ final class AopF2F extends AbstractPayment
         return $response->withJson([
             'ret' => 1,
             'qrcode' => $qrCodeContent,
-            'amount' => $pl->total,
-            'pid' => $pl->tradeno,
+            'amount' => $price,
+            'pid' => $trade_no,
         ]);
     }
 

+ 2 - 1
src/Services/Gateway/Epay.php

@@ -31,7 +31,7 @@ final class Epay extends AbstractPayment
         $this->epay['apiurl'] = Setting::obtain('epay_url');//易支付API地址
         $this->epay['partner'] = Setting::obtain('epay_pid');//易支付商户pid
         $this->epay['key'] = Setting::obtain('epay_key');//易支付商户Key
-        $this->epay['sign_type'] = strtoupper('SHA256'); //签名方式
+        $this->epay['sign_type'] = strtoupper(Setting::obtain('epay_sign_type')); //签名方式
         $this->epay['input_charset'] = strtolower('utf-8');//字符编码
         $this->epay['transport'] = 'https';//协议 http 或者https
     }
@@ -123,6 +123,7 @@ final class Epay extends AbstractPayment
 
             if ($trade_status === 'TRADE_SUCCESS') {
                 $this->postPayment($out_trade_no);
+
                 return $response->withJson(['state' => 'success', 'msg' => '支付成功']);
             }
 

+ 3 - 2
src/Services/Gateway/Epay/EpayTool.php

@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace App\Services\Gateway\Epay;
 
+use App\Models\Setting;
 use function hash;
 use function strlen;
 
@@ -13,13 +14,13 @@ final class EpayTool
     {
         $prestr .= $key;
 
-        return hash('sha256', $prestr);
+        return hash(Setting::obtain('epay_sign_type'), $prestr);
     }
 
     public static function verify($prestr, $sign, $key): bool
     {
         $prestr .= $key;
-        $correct_sign = hash('sha256', $prestr);
+        $correct_sign = hash(Setting::obtain('epay_sign_type'), $prestr);
 
         return $correct_sign === $sign;
     }

+ 1 - 2
src/Services/Gateway/PayPal.php

@@ -131,8 +131,7 @@ final class PayPal extends AbstractPayment
         $result = $pp->capturePaymentOrder($order_id);
 
         if (isset($result['status']) && $result['status'] === 'COMPLETED') {
-            $trade_no = $result['purchase_units'][0]['reference_id'];
-            $this->postPayment($trade_no);
+            $this->postPayment($result['purchase_units'][0]['reference_id']);
 
             return $response->withJson([
                 'ret' => 1,

+ 36 - 35
src/Services/Gateway/StripeCard.php

@@ -19,6 +19,7 @@ use Stripe\Checkout\Session;
 use Stripe\Exception\ApiErrorException;
 use Stripe\Stripe;
 use Stripe\StripeClient;
+use voku\helper\AntiXSS;
 
 final class StripeCard extends AbstractPayment
 {
@@ -43,50 +44,59 @@ final class StripeCard extends AbstractPayment
      */
     public function purchase(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
-        $user = Auth::getUser();
-        $configs = Setting::getClass('billing');
-        $price = $request->getParam('price');
+        $antiXss = new AntiXSS();
+
+        $price = $antiXss->xss_clean($request->getParam('price'));
+        $invoice_id = $antiXss->xss_clean($request->getParam('invoice_id'));
         $trade_no = self::generateGuid();
 
+        if ($price < Setting::obtain('stripe_min_recharge') ||
+            $price > Setting::obtain('stripe_max_recharge')
+        ) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '非法的金额',
+            ]);
+        }
+
+        $user = Auth::getUser();
         $pl = new Paylist();
+
         $pl->userid = $user->id;
         $pl->total = $price;
+        $pl->invoice_id = $invoice_id;
         $pl->tradeno = $trade_no;
         $pl->save();
 
-        $params = [
-            'trade_no' => $trade_no,
-            'sign' => hash('sha256', $trade_no . ':' . $configs['stripe_webhook_key']),
-        ];
-
-        $exchange_amount = Exchange::exchange($price, 'CNY', $configs['stripe_currency']);
+        $exchange_amount = Exchange::exchange($price, 'CNY', Setting::obtain('stripe_currency'));
 
-        Stripe::setApiKey($configs['stripe_sk']);
+        Stripe::setApiKey(Setting::obtain('stripe_sk'));
         $session = null;
 
         try {
             $session = Session::create([
                 'customer_email' => $user->email,
-                'line_items' => [[
-                    'price_data' => [
-                        'currency' => $configs['stripe_currency'],
-                        'product_data' => [
-                            'name' => 'Account Recharge',
+                'line_items' => [
+                    [
+                        'price_data' => [
+                            'currency' => Setting::obtain('stripe_currency'),
+                            'product_data' => [
+                                'name' => 'Account Recharge',
+                            ],
+                            'unit_amount' => (int) $exchange_amount,
                         ],
-                        'unit_amount' => (int) $exchange_amount,
+                        'quantity' => 1,
                     ],
-                    'quantity' => 1,
-                ],
                 ],
                 'mode' => 'payment',
-                'success_url' => self::getUserReturnUrl() .
-                    '?session_id={CHECKOUT_SESSION_ID}&' . http_build_query($params),
+                'client_reference_id' => $trade_no,
+                'success_url' => self::getUserReturnUrl() . '?session_id={CHECKOUT_SESSION_ID}',
                 'cancel_url' => $_ENV['baseUrl'] . '/user/invoice',
             ]);
         } catch (ApiErrorException $e) {
             return $response->withJson([
                 'ret' => 0,
-                'msg' => $e->getMessage(),
+                'msg' => 'Stripe API error',
             ]);
         }
 
@@ -108,18 +118,9 @@ final class StripeCard extends AbstractPayment
 
     public function getReturnHTML($request, $response, $args): ResponseInterface
     {
-        $sign = $request->getParam('sign');
-        $trade_no = $request->getParam('trade_no');
-        $session_id = $request->getParam('session_id');
-
-        $correct_sign = hash('sha256', $trade_no . ':' . Setting::obtain('stripe_webhook_key'));
+        $antiXss = new AntiXSS();
 
-        if ($correct_sign !== $sign) {
-            return $response->withJson([
-                'ret' => 0,
-                'msg' => 'Sign error',
-            ]);
-        }
+        $session_id = $antiXss->xss_clean($request->getParam('session_id'));
 
         $stripe = new StripeClient(Setting::obtain('stripe_sk'));
         $session = null;
@@ -129,12 +130,12 @@ final class StripeCard extends AbstractPayment
         } catch (ApiErrorException $e) {
             return $response->withJson([
                 'ret' => 0,
-                'msg' => $e->getMessage(),
+                'msg' => 'Stripe API error',
             ]);
         }
 
-        if ($session->payment_status === 'paid') {
-            $this->postPayment($trade_no);
+        if ($session !== null && $session->payment_status === 'paid') {
+            $this->postPayment($session->client_reference_id);
         }
 
         return $response->withRedirect($_ENV['baseUrl'] . '/user/invoice');