Browse Source

feat: add paypal & remove theadpay

M1Screw 2 years ago
parent
commit
ee6dcb69b5

+ 1 - 0
composer.json

@@ -31,6 +31,7 @@
         "slim/http": "^1.3",
         "slim/slim": "^4.11",
         "smarty/smarty": "^4",
+        "srmklive/paypal": "~3.0",
         "stripe/stripe-php": "^7",
         "symfony/console": "*",
         "symfony/yaml": "^6",

+ 66 - 1
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "24ce3f1554aebe8915f558f72513deeb",
+    "content-hash": "9735ac4ca5eeae105f3dda31ee943500",
     "packages": [
         {
             "name": "anankke/omnipay-alipay",
@@ -4592,6 +4592,71 @@
             },
             "time": "2023-03-28T19:47:03+00:00"
         },
+        {
+            "name": "srmklive/paypal",
+            "version": "3.0.20",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/srmklive/laravel-paypal.git",
+                "reference": "e5d5d91b21b38922c8130eedf0ee2d3a64527a4e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/srmklive/laravel-paypal/zipball/e5d5d91b21b38922c8130eedf0ee2d3a64527a4e",
+                "reference": "e5d5d91b21b38922c8130eedf0ee2d3a64527a4e",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "guzzlehttp/guzzle": "~7.0",
+                "illuminate/support": "~6.0|~7.0|~8.0|~9.0|^10.0",
+                "nesbot/carbon": "~2.0",
+                "php": ">=7.2|^8.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.0|^9.0",
+                "symfony/var-dumper": "~5.0"
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "Srmklive\\PayPal\\Providers\\PayPalServiceProvider"
+                    ],
+                    "aliases": {
+                        "PayPal": "Srmklive\\PayPal\\Facades\\PayPal"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Srmklive\\PayPal\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Raza Mehdi",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "Laravel plugin For Processing Payments Through Paypal Express Checkout. Can Be Used Independently With Other Applications.",
+            "keywords": [
+                "http",
+                "laravel paypal",
+                "paypal",
+                "rest",
+                "web service"
+            ],
+            "support": {
+                "issues": "https://github.com/srmklive/laravel-paypal/issues",
+                "source": "https://github.com/srmklive/laravel-paypal/tree/3.0.20"
+            },
+            "time": "2023-03-29T18:18:45+00:00"
+        },
         {
             "name": "starkbank/ecdsa",
             "version": "0.0.5",

+ 52 - 32
config/settings.json

@@ -109,44 +109,14 @@
         "default": "",
         "mark": "payjs_key"
     },
-    {
-        "id": null,
-        "item": "theadpay_url",
-        "value": "",
-        "class": "theadpay",
-        "is_public": 0,
-        "type": "string",
-        "default": "",
-        "mark": "theadpay_url"
-    },
-    {
-        "id": null,
-        "item": "theadpay_mchid",
-        "value": "",
-        "class": "theadpay",
-        "is_public": 0,
-        "type": "string",
-        "default": "",
-        "mark": "theadpay_mchid"
-    },
-    {
-        "id": null,
-        "item": "theadpay_key",
-        "value": "",
-        "class": "theadpay",
-        "is_public": 0,
-        "type": "string",
-        "default": "",
-        "mark": "theadpay_key"
-    },
     {
         "id": null,
         "item": "stripe_currency",
-        "value": "HKD",
+        "value": "USD",
         "class": "stripe",
         "is_public": 0,
         "type": "string",
-        "default": "HKD",
+        "default": "USD",
         "mark": "货币代码"
     },
     {
@@ -299,6 +269,56 @@
         "default": "0",
         "mark": "启用USDT"
     },
+    {
+        "id": null,
+        "item": "paypal_mode",
+        "value": "live",
+        "class": "paypal",
+        "is_public": 0,
+        "type": "string",
+        "default": "live",
+        "mark": "PayPal模式"
+    },
+    {
+        "id": null,
+        "item": "paypal_client_id",
+        "value": "",
+        "class": "paypal",
+        "is_public": 1,
+        "type": "string",
+        "default": "",
+        "mark": "PayPal客戶ID"
+    },
+    {
+        "id": null,
+        "item": "paypal_client_secret",
+        "value": "",
+        "class": "paypal",
+        "is_public": 0,
+        "type": "string",
+        "default": "",
+        "mark": "PayPal客戶密钥"
+    },
+    {
+        "id": null,
+        "item": "paypal_currency",
+        "value": "USD",
+        "class": "paypal",
+        "is_public": 1,
+        "type": "string",
+        "default": "USD",
+        "mark": "PayPal货币"
+    },
+    {
+        "id": null,
+        "item": "paypal_locale",
+        "value": "en_US",
+        "class": "paypal",
+        "is_public": 0,
+        "type": "string",
+        "default": "en_US",
+        "mark": "PayPal语言"
+    },
     {
         "id": null,
         "item": "smtp_host",

+ 40 - 25
resources/views/tabler/admin/setting/billing.tpl

@@ -42,15 +42,15 @@
                         <li class="nav-item">
                             <a href="#payjs" class="nav-link" data-bs-toggle="tab">PayJS</a>
                         </li>
-                        <li class="nav-item">
-                            <a href="#theadpay" class="nav-link" data-bs-toggle="tab">TheadPay</a>
-                        </li>
                         <li class="nav-item">
                             <a href="#stripe" class="nav-link" data-bs-toggle="tab">Stripe</a>
                         </li>
                         <li class="nav-item">
                             <a href="#epay" class="nav-link" data-bs-toggle="tab">EPay</a>
                         </li>
+                        <li class="nav-item">
+                            <a href="#paypal" class="nav-link" data-bs-toggle="tab">PayPal</a>
+                        </li>
                     </ul>
                 </div>
                 <div class="card-body">
@@ -140,28 +140,6 @@
                                 </div>
                             </div>
                         </div>
-                        <div class="tab-pane" id="theadpay">
-                            <div class="card-body">
-                                <div class="form-group mb-3 row">
-                                    <label class="form-label col-3 col-form-label">网关地址</label>
-                                    <div class="col">
-                                        <input id="theadpay_url" type="text" class="form-control" value="{$settings['theadpay_url']}">
-                                    </div>
-                                </div>
-                                <div class="form-group mb-3 row">
-                                    <label class="form-label col-3 col-form-label">商户ID</label>
-                                    <div class="col">
-                                        <input id="theadpay_mchid" type="text" class="form-control" value="{$settings['theadpay_mchid']}">
-                                    </div>
-                                </div>
-                                <div class="form-group mb-3 row">
-                                    <label class="form-label col-3 col-form-label">密钥</label>
-                                    <div class="col">
-                                        <input id="theadpay_key" type="text" class="form-control" value="{$settings['theadpay_key']}">
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
                         <div class="tab-pane" id="stripe">
                             <div class="card-body">
                                 <div class="form-group mb-3 row">
@@ -287,6 +265,43 @@
                                 </div>
                             </div>
                         </div>
+                        <div class="tab-pane" id="paypal">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">网关模式</label>
+                                    <div class="col">
+                                        <select id="paypal_mode" class="col form-select" value="{$settings['paypal_mode']}">
+                                            <option value="sandbox">Sandbox</option>
+                                            <option value="live" {if $settings['paypal_mode'] === 'live'}selected{/if}>Live</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">PayPal客戶ID</label>
+                                    <div class="col">
+                                        <input id="paypal_client_id" type="text" class="form-control" value="{$settings['paypal_client_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">PayPal客戶密钥</label>
+                                    <div class="col">
+                                        <input id="paypal_client_secret" type="text" class="form-control" value="{$settings['paypal_client_secret']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">PayPal货币</label>
+                                    <div class="col">
+                                        <input id="paypal_currency" type="text" class="form-control" value="{$settings['paypal_currency']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">PayPal语言</label>
+                                    <div class="col">
+                                        <input id="paypal_locale" type="text" class="form-control" value="{$settings['paypal_locale']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
                     </div>
                 </div>
             </div>

+ 4 - 10
resources/views/tabler/gateway/epay.tpl

@@ -4,30 +4,24 @@
     </h4>
     <p class="card-heading"></p>
     <form class="epay" name="epay" action="/user/payment/purchase/epay" method="post">
-        {if $user->use_new_shop}
         <input hidden id="price" name="price" value="{$invoice->price}">
         <input hidden id="invoice_id" name="invoice_id" value="{$invoice->id}">
-        {else}
-        <input class="form-control maxwidth-edit" id="price" name="price" placeholder="输入金额,选择以下要付款的渠道"
-            autofocus="autofocus" type="number" min="0.01" max="1000" step="0.01" required="required">
-        <br />
-        {/if}
-        {if $public_setting['epay_alipay'] == true}
+        {if $public_setting['epay_alipay']}
         <button class="btn btn-flat waves-attach" id="btnSubmit" type="submit" name="type" value="alipay">
             <img src="/images/alipay.png" height="50px" />
         </button>
         {/if}
-        {if $public_setting['epay_wechat'] == true}
+        {if $public_setting['epay_wechat']}
         <button class="btn btn-flat waves-attach" id="btnSubmit" type="submit" name="type" value="wxpay">
             <img src="/images/wechat.png" height="50px" />
         </button>
         {/if}
-        {if $public_setting['epay_qq'] == true}
+        {if $public_setting['epay_qq']}
         <button class="btn btn-flat waves-attach" id="btnSubmit" type="submit" name="type" value="qqpay">
             <img src="/images/qqpay.png" height="50px" />
         </button>
         {/if}
-        {if $public_setting['epay_usdt'] == true}
+        {if $public_setting['epay_usdt']}
         <button class="btn btn-flat waves-attach" id="btnSubmit" type="submit" name="type" value="usdt">
             <img src="/images/usdt.png" height="50px" />
         </button>

+ 44 - 0
resources/views/tabler/gateway/paypal.tpl

@@ -0,0 +1,44 @@
+<script src="https://www.paypal.com/sdk/js?client-id={$public_setting['paypal_client_id']}&currency={$public_setting['paypal_currency']}"></script>
+
+<div class="card-inner">
+    <h4>
+        PayPal 快速结账
+    </h4>
+    <p class="card-heading"></p>
+    <div id="paypal-button-container"></div>
+</div>
+
+<script>
+    paypal.Buttons({
+        createOrder() {
+            return fetch("/user/payment/purchase/paypal", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                body: JSON.stringify({
+                    price: {$invoice->price},
+                    invoice_id: {$invoice->id},
+                }),
+            })
+                .then((response) => response.json())
+                .then((order) => order.id);
+        },
+        onApprove(data) {
+            return fetch("/payment/notify/paypal", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                body: JSON.stringify({
+                    order_id: data.orderID,
+                }),
+            })
+                .then((response) => response.json())
+                .then(() => {
+                    window.location.href = '/user/invoice';
+                });
+        }
+    }).render('#paypal-button-container');
+
+</script>

+ 5 - 5
resources/views/tabler/user/invoice/view.tpl

@@ -109,21 +109,21 @@
                           </div>
                         </div>
                     </div>
+                    {if count($payments) > 0}
                     <div class="card my-3">
                         <div class="card-header">
                             <h3 class="card-title">网关支付</h3>
                         </div>
                         <div class="card-body">
-                            {if count($payments) > 0}
-                                {foreach from=$payments item=payment}
+                            {foreach from=$payments item=payment}
                                 <div class="mb-3">
                                     {$payment_name = $payment::_name()}
                                     {include file="../../gateway/$payment_name.tpl"}
                                 </div>
-                                {/foreach}
-                            {/if}
+                            {/foreach}
                         </div>
                     </div>
+                    {/if}
                 </div>
                 {/if}
             </div>
@@ -140,7 +140,7 @@
                     invoice_id: {$invoice->id},
                 },
                 success: function(data) {
-                    if (data.ret == 1) {
+                    if (data.ret === 1) {
                         $('#success-message').text(data.msg);
                         $('#success-dialog').modal('show');
                         setTimeout(function() {

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

@@ -27,10 +27,6 @@ final class BillingController extends BaseController
         'payjs_url',
         'payjs_mchid',
         'payjs_key',
-        // TheadPay
-        'theadpay_url',
-        'theadpay_mchid',
-        'theadpay_key',
         // Stripe
         'stripe_card',
         'stripe_alipay',
@@ -49,6 +45,12 @@ final class BillingController extends BaseController
         'epay_wechat',
         'epay_qq',
         'epay_usdt',
+        // PayPal
+        'paypal_mode',
+        'paypal_client_id',
+        'paypal_client_secret',
+        'paypal_currency',
+        'paypal_locale',
     ];
 
     /**

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

@@ -64,9 +64,9 @@ abstract class AbstractPayment
 
     abstract public static function getPurchaseHTML(): string;
 
-    public function postPayment($pid, $method): false|int|string
+    public function postPayment($tradeno): false|int|string
     {
-        $paylist = Paylist::where('tradeno', $pid)->first();
+        $paylist = Paylist::where('tradeno', $tradeno)->first();
 
         if ($paylist->status === 1) {
             return \json_encode(['errcode' => 0]);
@@ -110,6 +110,19 @@ abstract class AbstractPayment
         return substr(Uuid::uuid4()->toString(), 0, 8);
     }
 
+    public static function exchange($currency)
+    {
+        $ch = curl_init();
+        $url = 'https://api.exchangerate.host/latest?symbols=CNY&base=' . strtoupper($currency);
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_HEADER, 0);
+        $currency = json_decode(curl_exec($ch));
+        curl_close($ch);
+
+        return $currency->rates->CNY;
+    }
+
     protected static function getCallbackUrl(): string
     {
         return $_ENV['baseUrl'] . '/payment/notify/' . get_called_class()::_name();

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

@@ -20,6 +20,7 @@ use Exception;
 use Psr\Http\Message\ResponseInterface;
 use Slim\Http\Response;
 use Slim\Http\ServerRequest;
+use voku\helper\AntiXSS;
 
 final class Epay extends AbstractPayment
 {
@@ -52,23 +53,27 @@ final class Epay extends AbstractPayment
 
     public function purchase(Request $request, Response $response, array $args): ResponseInterface
     {
-        $type = $request->getParam('type');
-        $price = $request->getParam('price');
-        $invoice_id = $request->getParam('invoice_id') ?? 0;
+        $antiXss = new AntiXSS();
+
+        $price = $antiXss->xss_clean($request->getParam('price'));
+        $invoice_id = $antiXss->xss_clean($request->getParam('invoice_id'));
+        // EPay 特定参数
+        $type = $antiXss->xss_clean($request->getParam('type'));
 
         if ($price <= 0) {
-            return $response->withJson(['errcode' => -1, 'errmsg' => '非法的金额.']);
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '非法的金额',
+            ]);
         }
 
         $user = Auth::getUser();
-
         $pl = new Paylist();
 
-        if ($user->use_new_shop) {
-            $pl->invoice_id = $invoice_id;
-        } else {
-            $pl->invoice_id = 0;
-        }
+        $pl->userid = $user->id;
+        $pl->total = $price;
+        $pl->invoice_id = $invoice_id;
+        $pl->tradeno = self::generateGuid();
 
         $type_text = match ($type) {
             'qqpay' => 'QQ',
@@ -78,10 +83,7 @@ final class Epay extends AbstractPayment
         };
 
         $pl->gateway = self::_readableName() . ' ' . $type_text;
-        $pl->userid = $user->id;
-        $pl->total = $price;
-        //订单号
-        $pl->tradeno = self::generateGuid();
+
         $pl->save();
         //请求参数
         $data = [
@@ -117,10 +119,12 @@ final class Epay extends AbstractPayment
                 default => 'Alipay',
             };
             $trade_status = $_GET['trade_status'];
+
             if ($trade_status === 'TRADE_SUCCESS') {
-                $this->postPayment($out_trade_no, $type . ' ' . $out_trade_no);
+                $this->postPayment($out_trade_no);
                 return $response->withJson(['state' => 'success', 'msg' => '支付成功']);
             }
+
             return $response->withJson(['state' => 'fail', 'msg' => '支付失败']);
         }
 

+ 153 - 0
src/Services/Gateway/PayPal.php

@@ -0,0 +1,153 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Services\Gateway;
+
+use App\Models\Paylist;
+use App\Models\Setting;
+use App\Services\Auth;
+use App\Services\View;
+use Exception;
+use Psr\Http\Message\ResponseInterface;
+use Slim\Http\Response;
+use Slim\Http\ServerRequest;
+use Srmklive\PayPal\Services\PayPal as PayPalClient;
+use Throwable;
+use voku\helper\AntiXSS;
+use function json_decode;
+
+final class PayPal extends AbstractPayment
+{
+    private array $gateway_config;
+
+    public function __construct()
+    {
+        $configs = Setting::getClass('paypal');
+
+        $this->gateway_config = [
+            'mode' => $configs['paypal_mode'],
+            'sandbox' => [
+                'client_id' => $configs['paypal_client_id'],
+                'client_secret' => $configs['paypal_client_secret'],
+                'app_id' => '',
+            ],
+            'live' => [
+                'client_id' => $configs['paypal_client_id'],
+                'client_secret' => $configs['paypal_client_secret'],
+                'app_id' => '',
+            ],
+            'payment_action' => 'Sale',
+            'currency' => $configs['paypal_currency'],
+            'notify_url' => '',
+            'locale' => $configs['paypal_locale'],
+            'validate_ssl' => true,
+        ];
+    }
+
+    public static function _name(): string
+    {
+        return 'paypal';
+    }
+
+    public static function _enable(): bool
+    {
+        return self::getActiveGateway('paypal');
+    }
+
+    public static function _readableName(): string
+    {
+        return 'PayPal';
+    }
+
+    /**
+     * @throws Throwable
+     */
+    public function purchase(ServerRequest $request, Response $response, array $args): ResponseInterface
+    {
+        $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 <= 0) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '非法的金额',
+            ]);
+        }
+
+        $exchange_amount = round($price / self::exchange(Setting::obtain('paypal_currency')), 2);
+
+        $order_data = [
+            "intent" => "CAPTURE",
+            "purchase_units" => [
+                [
+                    "amount" => [
+                        "currency_code" => Setting::obtain('paypal_currency'),
+                        "value" => $exchange_amount,
+                    ],
+                    "reference_id" => $trade_no,
+                ],
+            ],
+        ];
+
+        $pp = new PayPalClient($this->gateway_config);
+        $pp->getAccessToken();
+
+        $order = $pp->createOrder($order_data);
+
+        $user = Auth::getUser();
+        $pl = new Paylist();
+
+        $pl->userid = $user->id;
+        $pl->total = $price;
+        $pl->invoice_id = $invoice_id;
+        $pl->tradeno = $trade_no;
+        $pl->gateway = self::_readableName();
+
+        $pl->save();
+
+        return $response->withJson($order);
+    }
+
+    /**
+     * @throws Throwable
+     */
+    public function notify($request, $response, $args): ResponseInterface
+    {
+        $antiXss = new AntiXSS();
+
+        $order_id = $antiXss->xss_clean($request->getParam('order_id'));
+
+        $pp = new PayPalClient($this->gateway_config);
+        $pp->getAccessToken();
+
+        $result = $pp->capturePaymentOrder($order_id);
+
+        if ($result['status'] === 'COMPLETED') {
+            $trade_no = $result['purchase_units'][0]['reference_id'];
+            $this->postPayment($trade_no);
+
+            return $response->withJson([
+                'ret' => 1,
+                'msg' => '支付成功',
+            ]);
+        }
+
+        return $response->withJson([
+            'ret' => 0,
+            'msg' => '支付失败',
+        ]);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public static function getPurchaseHTML(): string
+    {
+        return View::getSmarty()->fetch('gateway/paypal.tpl');
+    }
+}

+ 0 - 14
src/Services/Gateway/StripeCard.php

@@ -16,7 +16,6 @@ use Stripe\Checkout\Session;
 use Stripe\Exception\ApiErrorException;
 use Stripe\Stripe;
 use Stripe\StripeClient;
-use function json_decode;
 
 final class StripeCard extends AbstractPayment
 {
@@ -132,17 +131,4 @@ final class StripeCard extends AbstractPayment
 
         return $response->withRedirect($_ENV['baseUrl'] . '/user/code');
     }
-
-    public static function exchange($currency)
-    {
-        $ch = curl_init();
-        $url = 'https://api.exchangerate.host/latest?symbols=CNY&base=' . strtoupper($currency);
-        curl_setopt($ch, CURLOPT_URL, $url);
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-        curl_setopt($ch, CURLOPT_HEADER, 0);
-        $currency = json_decode(curl_exec($ch));
-        curl_close($ch);
-
-        return $currency->rates->CNY;
-    }
 }

+ 0 - 104
src/Services/Gateway/THeadPay.php

@@ -1,104 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Services\Gateway;
-
-use App\Models\Paylist;
-use App\Models\Setting;
-use App\Services\Auth;
-use App\Services\View;
-use Exception;
-use JetBrains\PhpStorm\NoReturn;
-use Psr\Http\Message\ResponseInterface;
-use Slim\Http\Response;
-use Slim\Http\ServerRequest;
-
-final class THeadPay extends AbstractPayment
-{
-    protected THeadPaySDK $sdk;
-
-    public function __construct()
-    {
-        $configs = Setting::getClass('theadpay');
-
-        $this->sdk = new THeadPaySDK([
-            'theadpay_url' => $configs['theadpay_url'],
-            'theadpay_mchid' => $configs['theadpay_mchid'],
-            'theadpay_key' => $configs['theadpay_key'],
-        ]);
-    }
-    public static function _name(): string
-    {
-        return 'theadpay';
-    }
-
-    public static function _enable(): bool
-    {
-        return self::getActiveGateway('theadpay');
-    }
-
-    public static function _readableName(): string
-    {
-        return 'THeadPay 平头哥支付';
-    }
-
-    public function purchase(Request $request, Response $response, array $args): ResponseInterface
-    {
-        $amount = (int) $request->getParam('amount');
-        $user = Auth::getUser();
-        if ($amount <= 0) {
-            return $response->withJson([
-                'ret' => 0,
-                'msg' => '订单金额错误:' . $amount,
-            ]);
-        }
-
-        $pl = new Paylist();
-        $pl->userid = $user->id;
-        $pl->tradeno = self::generateGuid();
-        $pl->total = $amount;
-        $pl->save();
-
-        try {
-            $res = $this->sdk->pay([
-                'trade_no' => $pl->tradeno,
-                'total_fee' => $pl->total * 100,
-                'notify_url' => self::getCallbackUrl(),
-                'return_url' => self::getUserReturnUrl(),
-            ]);
-
-            return $response->withJson([
-                'ret' => 1,
-                'qrcode' => $res['code_url'],
-                'amount' => $pl->total,
-                'pid' => $pl->tradeno,
-            ]);
-        } catch (Exception $e) {
-            return $response->withJson([
-                'ret' => 0,
-                'msg' => '创建支付订单错误:' . $e->getMessage(),
-            ]);
-        }
-    }
-
-    #[NoReturn] public function notify($request, $response, $args): ResponseInterface
-    {
-        $params = $request->getParsedBody();
-        if ($this->sdk->verify($params)) {
-            $pid = $params['out_trade_no'];
-            $this->postPayment($pid, 'THeadPay 平头哥支付 ' . $pid);
-            die('success'); //The response should be 'success' only
-        }
-
-        die('fail');
-    }
-
-    /**
-     * @throws Exception
-     */
-    public static function getPurchaseHTML(): string
-    {
-        return View::getSmarty()->fetch('gateway/theadpay.tpl');
-    }
-}

+ 0 - 68
src/Services/Gateway/THeadPaySDK.php

@@ -1,68 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Services\Gateway;
-
-use Exception;
-use function is_array;
-use function json_decode;
-use function json_encode;
-
-final class THeadPaySDK
-{
-    private $config;
-
-    public function __construct($config)
-    {
-        $this->config = $config;
-    }
-
-    /**
-     * @throws Exception
-     */
-    public function pay($order): array
-    {
-        $params = [
-            'mchid' => $this->config['theadpay_mchid'],
-            'out_trade_no' => $order['trade_no'],
-            'total_fee' => (string) $order['total_fee'], // in cents
-            'notify_url' => $order['notify_url'],
-            'return_url' => $order['return_url'],
-        ];
-        $params['sign'] = $this->sign($params);
-        $data = json_encode($params);
-
-        $curl = curl_init();
-        curl_setopt($curl, CURLOPT_URL, $this->config['theadpay_url'] . "/{$this->config['theadpay_mchid']}");
-        curl_setopt($curl, CURLOPT_POST, 1);
-        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
-        curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
-        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
-        $data = curl_exec($curl);
-        curl_close($curl);
-
-        $result = json_decode((string) $data, true);
-        if (! is_array($result) || ! isset($result['status'])) {
-            throw new Exception('网络连接异常: 无法连接支付网关');
-        }
-        if ($result['status'] !== 'success') {
-            throw new Exception($result['message']);
-        }
-
-        return $result;
-    }
-
-    public function verify($params): bool
-    {
-        return $params['sign'] === $this->sign($params);
-    }
-
-    private function sign($params): string
-    {
-        unset($params['sign']);
-        ksort($params);
-        $data = http_build_query($params) . '&key=' . $this->config['theadpay_key'];
-        return strtoupper(md5($data));
-    }
-}