浏览代码

refactor: stripe gateway

M1Screw 1 年之前
父节点
当前提交
e2843171f7

+ 4 - 0
app/routes.php

@@ -231,6 +231,10 @@ return static function (Slim\App $app): void {
         // 设置中心
         $group->get('/setting/billing', App\Controllers\Admin\Setting\BillingController::class . ':index');
         $group->post('/setting/billing', App\Controllers\Admin\Setting\BillingController::class . ':save');
+        $group->post(
+            '/setting/billing/set_stripe_webhook',
+            App\Controllers\Admin\Setting\BillingController::class . ':setStripeWebhook'
+        );
         $group->get('/setting/captcha', App\Controllers\Admin\Setting\CaptchaController::class . ':index');
         $group->post('/setting/captcha', App\Controllers\Admin\Setting\CaptchaController::class . ':save');
         $group->get('/setting/cron', App\Controllers\Admin\Setting\CronController::class . ':index');

+ 26 - 26
composer.lock

@@ -622,16 +622,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.303.0",
+            "version": "3.303.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "34ace61fdffcea032826b0aac61ff3135b24b727"
+                "reference": "e695623e9f6f278bed69172fddb932de3705030f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/34ace61fdffcea032826b0aac61ff3135b24b727",
-                "reference": "34ace61fdffcea032826b0aac61ff3135b24b727",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e695623e9f6f278bed69172fddb932de3705030f",
+                "reference": "e695623e9f6f278bed69172fddb932de3705030f",
                 "shasum": ""
             },
             "require": {
@@ -711,9 +711,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.303.0"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.303.1"
             },
-            "time": "2024-04-01T18:48:47+00:00"
+            "time": "2024-04-02T18:09:38+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -1703,7 +1703,7 @@
         },
         {
             "name": "illuminate/collections",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/collections.git",
@@ -1758,7 +1758,7 @@
         },
         {
             "name": "illuminate/conditionable",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/conditionable.git",
@@ -1804,7 +1804,7 @@
         },
         {
             "name": "illuminate/container",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/container.git",
@@ -1855,7 +1855,7 @@
         },
         {
             "name": "illuminate/contracts",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/contracts.git",
@@ -1903,16 +1903,16 @@
         },
         {
             "name": "illuminate/database",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/database.git",
-                "reference": "3e4e41b278146ad645ccc5901ccaf343efd850ea"
+                "reference": "c7ee848e6a0bc5466c17549bdd118ca99283a65f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/database/zipball/3e4e41b278146ad645ccc5901ccaf343efd850ea",
-                "reference": "3e4e41b278146ad645ccc5901ccaf343efd850ea",
+                "url": "https://api.github.com/repos/illuminate/database/zipball/c7ee848e6a0bc5466c17549bdd118ca99283a65f",
+                "reference": "c7ee848e6a0bc5466c17549bdd118ca99283a65f",
                 "shasum": ""
             },
             "require": {
@@ -1967,11 +1967,11 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-03-28T14:12:19+00:00"
+            "time": "2024-04-01T22:47:30+00:00"
         },
         {
             "name": "illuminate/macroable",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/macroable.git",
@@ -2017,16 +2017,16 @@
         },
         {
             "name": "illuminate/pagination",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/pagination.git",
-                "reference": "ccb66b9161177aaf8072ff41151f5a62c91dbefb"
+                "reference": "ab541626a692597278bae9dabaf7ae3c3657e035"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/pagination/zipball/ccb66b9161177aaf8072ff41151f5a62c91dbefb",
-                "reference": "ccb66b9161177aaf8072ff41151f5a62c91dbefb",
+                "url": "https://api.github.com/repos/illuminate/pagination/zipball/ab541626a692597278bae9dabaf7ae3c3657e035",
+                "reference": "ab541626a692597278bae9dabaf7ae3c3657e035",
                 "shasum": ""
             },
             "require": {
@@ -2063,20 +2063,20 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-01-17T13:06:14+00:00"
+            "time": "2024-04-02T13:11:56+00:00"
         },
         {
             "name": "illuminate/support",
-            "version": "v11.1.1",
+            "version": "v11.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/support.git",
-                "reference": "9fdd4fc622524787185264faeadfe14f2f0e356b"
+                "reference": "abedd71609c48606735754192c15e7eb7c9f1248"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/support/zipball/9fdd4fc622524787185264faeadfe14f2f0e356b",
-                "reference": "9fdd4fc622524787185264faeadfe14f2f0e356b",
+                "url": "https://api.github.com/repos/illuminate/support/zipball/abedd71609c48606735754192c15e7eb7c9f1248",
+                "reference": "abedd71609c48606735754192c15e7eb7c9f1248",
                 "shasum": ""
             },
             "require": {
@@ -2137,7 +2137,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-03-27T16:39:25+00:00"
+            "time": "2024-04-01T15:22:25+00:00"
         },
         {
             "name": "irazasyed/telegram-bot-sdk",

+ 15 - 24
config/settings.json

@@ -54,40 +54,31 @@
         "mark": "当面付自定义回调地址"
     },
     {
-        "item": "stripe_currency",
-        "value": "USD",
-        "class": "billing",
-        "is_public": 0,
-        "type": "string",
-        "default": "USD",
-        "mark": "货币代码"
-    },
-    {
-        "item": "stripe_sk",
-        "value": "stripe_sk",
+        "item": "stripe_api_key",
+        "value": "",
         "class": "billing",
         "is_public": 0,
         "type": "string",
         "default": "",
-        "mark": "stripe_sk"
+        "mark": "Stripe API Key"
     },
     {
-        "item": "stripe_pk",
-        "value": "stripe_pk",
+        "item": "stripe_endpoint_secret",
+        "value": "",
         "class": "billing",
         "is_public": 0,
         "type": "string",
         "default": "",
-        "mark": "stripe_pk"
+        "mark": "Stripe Endpoint Secret"
     },
     {
-        "item": "stripe_webhook_key",
-        "value": "stripe_webhook_key",
+        "item": "stripe_currency",
+        "value": "USD",
         "class": "billing",
         "is_public": 0,
         "type": "string",
-        "default": "",
-        "mark": "web_hook密钥"
+        "default": "USD",
+        "mark": "Stripe Currency"
     },
     {
         "item": "stripe_min_recharge",
@@ -96,7 +87,7 @@
         "is_public": 1,
         "type": "int",
         "default": "10",
-        "mark": "最低充值限额"
+        "mark": "Stripe minimum recharge amount"
     },
     {
         "item": "stripe_max_recharge",
@@ -105,7 +96,7 @@
         "is_public": 1,
         "type": "int",
         "default": "1000",
-        "mark": "最高充值限额"
+        "mark": "Stripe maximum recharge amount"
     },
     {
         "item": "stripe_card",
@@ -114,7 +105,7 @@
         "is_public": 0,
         "type": "bool",
         "default": "0",
-        "mark": "银行卡支付"
+        "mark": "Stripe Card Payment"
     },
     {
         "item": "stripe_alipay",
@@ -123,7 +114,7 @@
         "is_public": 0,
         "type": "bool",
         "default": "0",
-        "mark": "支付宝支付"
+        "mark": "Stripe Alipay Payment"
     },
     {
         "item": "stripe_wechat",
@@ -132,7 +123,7 @@
         "is_public": 0,
         "type": "bool",
         "default": "0",
-        "mark": "微信支付"
+        "mark": "Stripe WeChat Payment"
     },
     {
         "item": "epay_url",

+ 17 - 16
resources/views/tabler/admin/footer.tpl

@@ -112,22 +112,23 @@
 </div>
 <!-- js -->
 <script>
-    $("#switch_theme_mode").click(function () {
-        $.ajax({
-            type: "POST",
-            url: "/user/switch_theme_mode",
-            dataType: "json",
-            success: function (data) {
-                if (data.ret === 1) {
-                    $('#success-message').text(data.msg);
-                    $('#success-dialog').modal('show');
-                    window.setTimeout("location.reload()", {$config['jump_delay']});
-                } else {
-                    $('#fail-message').text(data.msg);
-                    $('#fail-dialog').modal('show');
-                }
-            }
-        })
+    let successDialog = new bootstrap.Modal(document.getElementById('success-dialog'));
+    let failDialog = new bootstrap.Modal(document.getElementById('fail-dialog'));
+
+    htmx.on("htmx:afterRequest", function(evt) {
+        if (evt.detail.xhr.getResponseHeader('HX-Refresh') === 'true' ||
+            evt.detail.xhr.getResponseHeader('HX-Trigger'))
+        {
+            return;
+        }
+
+        if (res.ret === 1) {
+            document.getElementById("success-message").innerHTML = res.msg;
+            successDialog.show();
+        } else {
+            document.getElementById("fail-message").innerHTML = res.msg;
+            failDialog.show();
+        }
     });
 
     $("#success-confirm").click(function () {

+ 7 - 2
resources/views/tabler/admin/header.tpl

@@ -14,6 +14,7 @@
     <script src="//{$config['jsdelivr_url']}/npm/qrcode_js@latest/qrcode.min.js"></script>
     <script src="//{$config['jsdelivr_url']}/npm/clipboard@latest/dist/clipboard.min.js"></script>
     <script src="//{$config['jsdelivr_url']}/npm/jquery/dist/jquery.min.js"></script>
+    <script src="//{$config['jsdelivr_url']}/npm/htmx.org@latest/dist/htmx.min.js"></script>
     <style>
         .home-subtitle {
             font-size: 14px;
@@ -53,9 +54,13 @@
                     </a>
                     <div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
                         {if $user->is_dark_mode}
-                            <a id="switch_theme_mode" class="dropdown-item">浅色模式</a>
+                            <a class="dropdown-item" hx-post="/user/switch_theme_mode" hx-swap="none">
+                                浅色模式
+                            </a>
                         {else}
-                            <a id="switch_theme_mode" class="dropdown-item">深色模式</a>
+                            <a class="dropdown-item" hx-post="/user/switch_theme_mode" hx-swap="none">
+                                深色模式
+                            </a>
                         {/if}
                         <a href="/user/logout" class="dropdown-item">登出</a>
                     </div>

+ 30 - 28
resources/views/tabler/admin/setting/billing.tpl

@@ -103,6 +103,36 @@
                                 </div>
                                 <div class="tab-pane" id="stripe">
                                     <div class="card-body">
+                                        <div class="form-group mb-3 row">
+                                            <label class="form-label col-3 col-form-label">API Key</label>
+                                            <div class="col">
+                                                <input id="stripe_api_key" type="text" class="form-control"
+                                                       value="{$settings['stripe_api_key']}">
+                                            </div>
+                                        </div>
+                                        <div class="form-group mb-3 row">
+                                            <label class="form-label col-3 col-form-label">Endpoint Secret</label>
+                                            <div class="col">
+                                                <input id="stripe_endpoint_secret" type="text" class="form-control"
+                                                       value="{$settings['stripe_endpoint_secret']}">
+                                            </div>
+                                            <div class="col-auto">
+                                                <button class="btn btn-primary"
+                                                        hx-post="/admin/setting/billing/set_stripe_webhook" hx-swap="none"
+                                                        hx-vals='js:{
+                                                            stripe_api_key: document.getElementById("stripe_api_key").value
+                                                        }'>
+                                                    Set Webhook
+                                                </button>
+                                            </div>
+                                        </div>
+                                        <div class="form-group mb-3 row">
+                                            <label class="form-label col-3 col-form-label">网关货币</label>
+                                            <div class="col">
+                                                <input id="stripe_currency" type="text" class="form-control"
+                                                       value="{$settings['stripe_currency']}">
+                                            </div>
+                                        </div>
                                         <div class="form-group mb-3 row">
                                             <label class="form-label col-3 col-form-label">银行卡支付</label>
                                             <div class="col">
@@ -138,13 +168,6 @@
                                                 </select>
                                             </div>
                                         </div>
-                                        <div class="form-group mb-3 row">
-                                            <label class="form-label col-3 col-form-label">网关货币</label>
-                                            <div class="col">
-                                                <input id="stripe_currency" type="text" class="form-control"
-                                                       value="{$settings['stripe_currency']}">
-                                            </div>
-                                        </div>
                                         <div class="form-group mb-3 row">
                                             <label class="form-label col-3 col-form-label">最低充值限额(整数)</label>
                                             <div class="col">
@@ -159,27 +182,6 @@
                                                        value="{$settings['stripe_max_recharge']}">
                                             </div>
                                         </div>
-                                        <div class="form-group mb-3 row">
-                                            <label class="form-label col-3 col-form-label">公钥</label>
-                                            <div class="col">
-                                                <input id="stripe_pk" type="text" class="form-control"
-                                                       value="{$settings['stripe_pk']}">
-                                            </div>
-                                        </div>
-                                        <div class="form-group mb-3 row">
-                                            <label class="form-label col-3 col-form-label">私钥</label>
-                                            <div class="col">
-                                                <input id="stripe_sk" type="text" class="form-control"
-                                                       value="{$settings['stripe_sk']}">
-                                            </div>
-                                        </div>
-                                        <div class="form-group mb-3 row">
-                                            <label class="form-label col-3 col-form-label">WebHook密钥</label>
-                                            <div class="col">
-                                                <input id="stripe_webhook_key" type="text" class="form-control"
-                                                       value="{$settings['stripe_webhook_key']}">
-                                            </div>
-                                        </div>
                                     </div>
                                 </div>
                                 <div class="tab-pane" id="epay">

+ 2 - 4
resources/views/tabler/user/header.tpl

@@ -55,13 +55,11 @@
                     </a>
                     <div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
                         {if $user->is_dark_mode}
-                            <a id="switch-theme-mode" class="dropdown-item"
-                               hx-post="/user/switch_theme_mode" hx-swap="none">
+                            <a class="dropdown-item" hx-post="/user/switch_theme_mode" hx-swap="none">
                                 浅色模式
                             </a>
                         {else}
-                            <a id="switch_theme_mode" class="dropdown-item"
-                               hx-post="/user/switch_theme_mode" hx-swap="none">
+                            <a class="dropdown-item" hx-post="/user/switch_theme_mode" hx-swap="none">
                                 深色模式
                             </a>
                         {/if}

+ 39 - 6
src/Controllers/Admin/Setting/BillingController.php

@@ -8,6 +8,12 @@ use App\Controllers\BaseController;
 use App\Models\Config;
 use App\Services\Payment;
 use Exception;
+use Psr\Http\Message\ResponseInterface;
+use Slim\Http\Response;
+use Slim\Http\ServerRequest;
+use Stripe\Exception\ApiErrorException;
+use Stripe\Stripe;
+use Stripe\WebhookEndpoint;
 use function json_decode;
 use function json_encode;
 
@@ -21,13 +27,12 @@ final class BillingController extends BaseController
         'f2f_pay_private_key',
         'f2f_pay_notify_url',
         // Stripe
+        'stripe_api_key',
+        'stripe_endpoint_secret',
+        'stripe_currency',
         'stripe_card',
         'stripe_alipay',
         'stripe_wechat',
-        'stripe_currency',
-        'stripe_pk',
-        'stripe_sk',
-        'stripe_webhook_key',
         'stripe_min_recharge',
         'stripe_max_recharge',
         // EPay
@@ -50,7 +55,7 @@ final class BillingController extends BaseController
     /**
      * @throws Exception
      */
-    public function index($request, $response, $args)
+    public function index(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
         $settings = Config::getClass('billing');
 
@@ -64,12 +69,13 @@ final class BillingController extends BaseController
         );
     }
 
-    public function save($request, $response, $args)
+    public function save(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
         $gateway_in_use = [];
 
         foreach (self::returnGatewaysList() as $value) {
             $payment_enable = $request->getParam($value);
+
             if ($payment_enable === 'true') {
                 $gateway_in_use[] = $value;
             }
@@ -100,6 +106,32 @@ final class BillingController extends BaseController
         ]);
     }
 
+    public function setStripeWebhook(ServerRequest $request, Response $response, array $args): ResponseInterface
+    {
+        $stripe_api_key = $request->getParam('stripe_api_key');
+
+        Stripe::setApiKey($stripe_api_key);
+
+        try {
+            WebhookEndpoint::create([
+                'url' => $_ENV['baseUrl'] . '/payment/notify/stripe',
+                'enabled_events' => [
+                    'payment_intent.succeeded',
+                ],
+            ]);
+
+            return $response->withJson([
+                'ret' => 1,
+                'msg' => '设置 Stripe Webhook 成功',
+            ]);
+        } catch (ApiErrorException) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '设置 Stripe Webhook 失败',
+            ]);
+        }
+    }
+
     public function returnGatewaysList(): array
     {
         $result = [];
@@ -114,6 +146,7 @@ final class BillingController extends BaseController
     public function returnActiveGateways()
     {
         $payment_gateways = (new Config())->where('item', 'payment_gateway')->first();
+
         return json_decode($payment_gateways->value);
     }
 }

+ 2 - 2
src/Services/Gateway/Base.php

@@ -59,7 +59,7 @@ abstract class Base
 
     abstract public static function getPurchaseHTML(): string;
 
-    public function postPayment($trade_no): void
+    public function postPayment(string $trade_no): void
     {
         $paylist = (new Paylist())->where('tradeno', $trade_no)->first();
 
@@ -100,7 +100,7 @@ abstract class Base
         return $_ENV['baseUrl'] . '/user/payment/return/' . get_called_class()::_name();
     }
 
-    protected static function getActiveGateway($key): bool
+    protected static function getActiveGateway(string $key): bool
     {
         $payment_gateways = (new Config())->where('item', 'payment_gateway')->first();
         $active_gateways = json_decode($payment_gateways->value);

+ 3 - 15
src/Services/Gateway/Epay.php

@@ -95,7 +95,7 @@ final class Epay extends Base
             'pid' => trim($this->epay['partner']),
             'type' => $type,
             'out_trade_no' => $pl->tradeno,
-            'notify_url' => $_ENV['baseUrl'] . '/payment/notify/epay',
+            'notify_url' => self::getCallbackUrl(),
             'return_url' => $redir,
             'name' => $pl->tradeno,
             'money' => $price,
@@ -139,20 +139,8 @@ final class Epay extends Base
         $verify_result = $epayNotify->verifyNotify();
 
         if ($verify_result) {
-            $out_trade_no = $_GET['out_trade_no'];
-            $type = $_GET['type'];
-
-            $type = match ($type) {
-                'qqpay' => 'QQ',
-                'wxpay' => 'WeChat',
-                'epusdt' => 'USDT',
-                default => 'Alipay',
-            };
-
-            $trade_status = $_GET['trade_status'];
-
-            if ($trade_status === 'TRADE_SUCCESS') {
-                $this->postPayment($out_trade_no);
+            if ($_GET['trade_status'] === 'TRADE_SUCCESS') {
+                $this->postPayment($_GET['out_trade_no']);
 
                 return $response->withJson(['state' => 'success', 'msg' => 'Payment success']);
             }

+ 53 - 34
src/Services/Gateway/StripeCard.php → src/Services/Gateway/Stripe.php

@@ -17,11 +17,13 @@ use Slim\Http\Response;
 use Slim\Http\ServerRequest;
 use Stripe\Checkout\Session;
 use Stripe\Exception\ApiErrorException;
-use Stripe\Stripe;
-use Stripe\StripeClient;
+use Stripe\Exception\SignatureVerificationException;
+use Stripe\Stripe as StripeSDK;
+use Stripe\Webhook;
+use UnexpectedValueException;
 use voku\helper\AntiXSS;
 
-final class StripeCard extends Base
+final class Stripe extends Base
 {
     public function __construct()
     {
@@ -69,11 +71,12 @@ final class StripeCard extends Base
         $pl->total = $price;
         $pl->invoice_id = $invoice_id;
         $pl->tradeno = $trade_no;
+        $pl->gateway = self::_readableName();
         $pl->save();
 
         $exchange_amount = (new Exchange())->exchange((float) $price, 'CNY', Config::obtain('stripe_currency'));
 
-        Stripe::setApiKey(Config::obtain('stripe_sk'));
+        StripeSDK::setApiKey(Config::obtain('stripe_sk'));
         $session = null;
 
         try {
@@ -84,7 +87,7 @@ final class StripeCard extends Base
                         'price_data' => [
                             'currency' => Config::obtain('stripe_currency'),
                             'product_data' => [
-                                'name' => 'Account Recharge',
+                                'name' => 'Invoice #' . $invoice_id,
                             ],
                             'unit_amount' => (int) $exchange_amount,
                         ],
@@ -92,9 +95,13 @@ final class StripeCard extends Base
                     ],
                 ],
                 'mode' => 'payment',
-                'client_reference_id' => $trade_no,
-                'success_url' => self::getUserReturnUrl() . '?session_id={CHECKOUT_SESSION_ID}',
-                'cancel_url' => $_ENV['baseUrl'] . '/user/invoice',
+                'payment_intent_data' => [
+                    'metadata' => [
+                        'trade_no' => $trade_no,
+                    ],
+                ],
+                'success_url' => $_ENV['baseUrl'] . '/user/invoice/' . $invoice_id,
+                'cancel_url' => $_ENV['baseUrl'] . '/user/invoice/' . $invoice_id,
             ]);
         } catch (ApiErrorException $e) {
             return $response->withJson([
@@ -103,42 +110,54 @@ final class StripeCard extends Base
             ]);
         }
 
-        return $response->withRedirect($session->url);
-    }
-
-    public function notify($request, $response, $args): ResponseInterface
-    {
-        return $response->write('ok');
+        return $response->withHeader('HX-Redirect', $session->url)->withJson([
+            'ret' => 1,
+            'msg' => '订单发起成功,正在跳转到支付页面...',
+        ]);
     }
 
-    /**
-     * @throws Exception
-     */
-    public static function getPurchaseHTML(): string
+    public function notify(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
-        return View::getSmarty()->fetch('gateway/stripe.tpl');
-    }
+        try {
+            $event = Webhook::constructEvent(
+                $request->getBody()->getContents(),
+                $request->getHeaderLine('Stripe-Signature'),
+                Config::obtain('stripe_endpoint_secret')
+            );
+        } catch (UnexpectedValueException) {
+            return $response->withStatus(400)->withJson([
+                'ret' => 0,
+                'msg' => 'Unexpected Value error',
+            ]);
+        } catch (SignatureVerificationException) {
+            return $response->withStatus(400)->withJson([
+                'ret' => 0,
+                'msg' => 'Signature Verification error',
+            ]);
+        }
 
-    public function getReturnHTML($request, $response, $args): ResponseInterface
-    {
-        $session_id = $this->antiXss->xss_clean($request->getParam('session_id'));
+        $payment_intent = $event->data->object;
 
-        $stripe = new StripeClient(Config::obtain('stripe_sk'));
-        $session = null;
+        if ($event->type === 'payment_intent.succeeded' && $payment_intent->status === 'succeeded') {
+            $this->postPayment($payment_intent->metadata->trade_no);
 
-        try {
-            $session = $stripe->checkout->sessions->retrieve($session_id, []);
-        } catch (ApiErrorException $e) {
             return $response->withJson([
-                'ret' => 0,
-                'msg' => 'Stripe API error',
+                'ret' => 1,
+                'msg' => 'Payment success',
             ]);
         }
 
-        if ($session !== null && $session->payment_status === 'paid') {
-            $this->postPayment($session->client_reference_id);
-        }
+        return $response->withJson([
+            'ret' => 0,
+            'msg' => 'Payment failed',
+        ]);
+    }
 
-        return $response->withRedirect($_ENV['baseUrl'] . '/user/invoice');
+    /**
+     * @throws Exception
+     */
+    public static function getPurchaseHTML(): string
+    {
+        return View::getSmarty()->fetch('gateway/stripe.tpl');
     }
 }