소스 검색

最新萤火改日再用,bye

zhangdehua 1 년 전
부모
커밋
61835fa0ab

+ 1 - 1
app/api/common.php

@@ -18,7 +18,7 @@ declare (strict_types=1);
  */
 function getPlatform(): ?string
 {
-    return '1';
+    return 'H5';
     static $value = null;
     // 从header中获取 channel
     empty($value) && $value = request()->header('platform');

+ 2 - 0
app/api/controller/Cashier.php

@@ -14,6 +14,8 @@ namespace app\api\controller;
 
 use think\response\Json;
 use app\api\service\Cashier as CashierService;
+use app\api\service\recharge\Payment as PaymentService;
+
 
 /**
  * 订单付款控制器 (收银台)

+ 1 - 1
app/api/controller/Index.php

@@ -23,7 +23,7 @@ class Index
     {
         //echo '当前访问的index.php,请将index.html设为默认站点入口';
 
-        return view('index', [
+        return view('index.index', [
             'name'  => 'ThinkPHP',
             'email' => 'thinkphp@qq.com'
         ]);

+ 2 - 2
app/api/service/cashier/Payment.php

@@ -141,7 +141,7 @@ class Payment extends BaseService
     public function tradeQuery(string $outTradeNo): bool
     {
         // 判断支付方式是否合法
-        if (!in_array($this->method, [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY])) {
+        if (!in_array($this->method, [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY, PaymentMethodEnum::PAYPAL, PaymentMethodEnum::STRIPE])) {
             return false;
         }
         // 获取支付方式的配置信息
@@ -224,7 +224,7 @@ class Payment extends BaseService
     private function unifiedorder(array $extra = []): array
     {
         // 判断支付方式是否合法
-        if (!in_array($this->method, [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY])) {
+        if (!in_array($this->method, [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY, PaymentMethodEnum::PAYPAL, PaymentMethodEnum::STRIPE])) {
             return [];
         }
         // 生成第三方交易订单号 (并非主订单号)

+ 13 - 0
app/common/enum/payment/Method.php

@@ -30,6 +30,11 @@ class Method extends EnumBasics
     // 余额支付
     const BALANCE = 'balance';
 
+    // 余额支付
+    const PAYPAL = 'paypal';
+    // 余额支付
+    const STRIPE = 'stripe';
+
     /**
      * 获取类型值
      * @return array
@@ -48,6 +53,14 @@ class Method extends EnumBasics
             self::BALANCE => [
                 'name' => '余额支付',
                 'value' => self::BALANCE,
+            ],
+            self::PAYPAL => [
+                'name' => 'paypal支付',
+                'value' => self::PAYPAL,
+            ],
+            self::STRIPE => [
+                'name' => 'stripe支付',
+                'value' => self::STRIPE,
             ]
         ];
     }

+ 115 - 75
app/common/library/payment/gateway/driver/PayPal.php

@@ -19,13 +19,19 @@ use app\common\enum\Client as ClientEnum;
 use app\common\library\Log;
 use app\common\library\payment\gateway\Driver;
 use cores\exception\BaseException;
+use cores\Request;
 use PayPal\Api\Amount;
+use PayPal\Api\Order;
 use PayPal\Api\Payer;
 use PayPal\Api\Payment;
+use PayPal\Api\PaymentExecution;
 use PayPal\Api\RedirectUrls;
 use PayPal\Api\Transaction;
+use PayPal\Api\VerifyWebhookSignature;
 use PayPal\Auth\OAuthTokenCredential;
+use PayPal\Exception\PayPalConnectionException;
 use PayPal\Rest\ApiContext;
+use think\exception\HttpException;
 
 /**
  * paypal驱动
@@ -40,9 +46,37 @@ class PayPal extends Driver
     // 异步通知的请求参数 (由第三方支付发送)
     private $notifyParams;
 
+    protected $config;
+
+    protected $notifyWebHookId;//	3NP026061E6858914
     // 异步通知的验证结果
     private $notifyResult;
 
+    public $apiContext;
+
+    public function __construct($config)
+    {
+        // 秘钥配置
+        $this->config = $config;
+
+        $this->notifyWebHookId = $this->config['web_hook_id'];
+
+        $this->apiContext = new ApiContext(
+            new OAuthTokenCredential(
+                $this->config['client_id'],
+                $this->config['secret']
+            )
+        );
+
+        $this->apiContext->setConfig([
+            'mode' => $this->config['mode'],
+            'log.LogEnabled' => true,
+            'log.FileName' => app()->getRootPath() . 'runtime/log/PayPal.log', // 记录日志
+            'log.LogLevel' => 'debug', // 在live上用info
+            'cache.enable' => true,
+        ]);
+    }
+
     /**
      * 统一下单API
      * @param string $outTradeNo 交易订单号
@@ -81,24 +115,23 @@ class PayPal extends Driver
             ->setTransactions(array($transaction))
             ->setRedirectUrls($redirectUrls);
 
-        $payment->create($apiContext);
+        //$payment->create($apiContext);
 
         try {
-            $payment->create($apiContext);
-            echo "\n\nRedirect user to approval_url: " . $payment->getApprovalLink() . "\n";
-            // 记录日志
-            Log::append('PayPal-unify', ['client' => $this->client, 'result' => $this->result]);
-            redirect($payment->getApprovalLink());
-            // 请求成功
-            return true;
+            $this->result = $payment->create($apiContext);
         } catch (\PayPal\Exception\PayPalConnectionException $ex) {
             // This will print the detailed information on the exception.
             //REALLY HELPFUL FOR DEBUGGING
             echo $ex->getData();
             $this->throwError('支付宝API交易查询失败:' . $ex->getMessage(), true, 'tradeQuery');
-
+            return false;
         }
-        return false;
+        echo "\n\nRedirect user to approval_url: " . $payment->getApprovalLink() . "\n";
+        // 记录日志
+        Log::append('PayPal-unify', ['client' => $this->client, 'result' => $this->result]);
+        redirect($payment->getApprovalLink());
+        // 请求成功
+        return true;
     }
 
     /**
@@ -109,58 +142,92 @@ class PayPal extends Driver
      */
     public function tradeQuery(string $outTradeNo): ?array
     {
-
-
         try {
-            // 发起API调用
-            // https://opendocs.alipay.com/apis/028pxp
-            $result = Factory::payment()->common()->query($outTradeNo);
+
+            $result = Order::get($outTradeNo, $this->apiContext);
             // 记录日志
-            Log::append('Alipay-tradeQuery', ['outTradeNo' => $outTradeNo, 'result' => $result->toMap()]);
+            Log::append('Paypal-tradeQuery', ['outTradeNo' => $outTradeNo, 'result' => json_encode($result)]);
             // 处理响应或异常
-            $responseChecker = new ResponseChecker();
-            if (!$responseChecker->success($result)) {
-                $this->throwError($result->msg . "," . $result->subMsg);
-            }
+            //$this->throwError($result->msg . "," . $result->subMsg);
             // 返回查询成功的结果
-            return [
-                // 支付状态: true成功 false失败
-                'paySuccess' => $result->tradeStatus === 'TRADE_SUCCESS',
-                // 第三方交易流水号
-                'tradeNo' => $result->tradeNo
-            ];
+            return $result->toArray();
         } catch (\Throwable $e) {
             $this->throwError('支付宝API交易查询失败:' . $e->getMessage(), true, 'tradeQuery');
         }
         return null;
     }
 
+    public function executePayment($paymentId)
+    {
+        try {
+            $payment = Payment::get($paymentId, $this->apiContext);
+            $execution = new PaymentExecution();
+            $execution->setPayerId($payment->getPayer()->getPayerInfo()->getPayerId());
+
+            // 执行付款
+            $payment->execute($execution, $this->apiContext);
+            return $payment::get($payment->getId(), $this->apiContext);
+
+        } catch (\Exception $e) {
+            \think\facade\Log::error('executePayment', ['paymentId' => $paymentId, 'errMsg' => $e->getMessage()]);
+            $this->throwError('执行失败:' . $e->getMessage(), true, 'tradeQuery');
+            return false;
+        }
+    }
+
     /**
      * 支付成功后的异步通知
      * @return bool
      */
-    public function notify(): bool
+    public function notify(Request $request, $webHookId): bool
     {
+
         // 接收表单数据
-        $this->notifyParams = request()->filter([])->post();
-        // 验证异步请求的参数是否合法
-        // https://opendocs.alipay.com/open/270/105902
-        $verifyNotify = Factory::payment()->common()->verifyNotify($this->notifyParams);
-        // 判断交易单状态必须是支付成功
-        $this->notifyResult = $verifyNotify && $this->notifyParams['trade_status'] === 'TRADE_SUCCESS';
+        try {
+            $headers = $request->header();
+            $headers = array_change_key_case($headers, CASE_UPPER);
+
+            $content = $request->getContent();
+            \think\facade\Log::error('notify::' . json_encode($headers));
+
+            // 如果是laravel,这里获请求头的方法可能要变,现在是$headers['PAYPAL-AUTH-ALGO'],去到laravel的话可能要$headers['PAYPAL-AUTH-ALGO'][0],到时试试就知道了,实在不行打日志看看数据结构再确定如何获取
+            $signatureVerification = new VerifyWebhookSignature();
+            $signatureVerification->setAuthAlgo($headers['PAYPAL-AUTH-ALGO']);
+            $signatureVerification->setTransmissionId($headers['PAYPAL-TRANSMISSION-ID']);
+            $signatureVerification->setCertUrl($headers['PAYPAL-CERT-URL']);
+            $signatureVerification->setWebhookId($webHookId ?: $this->notifyWebHookId);
+            $signatureVerification->setTransmissionSig($headers['PAYPAL-TRANSMISSION-SIG']);
+            $signatureVerification->setTransmissionTime($headers['PAYPAL-TRANSMISSION-TIME']);
+            $signatureVerification->setRequestBody($content);
+
+            $result = clone $signatureVerification;
+
+            $output = $signatureVerification->post($this->apiContext);
+            \think\facade\Log::error('notify' . json_encode($output));
+            if ($output->getVerificationStatus() == 'SUCCESS') {
+                return true;
+            }
+
+            throw new HttpException(400, 'Verify Failed.');
+
+        } catch (HttpException $exception) {
+            \think\facade\Log::error('PayPal Notification Verify Failed' . $exception->getMessage());
+            return false;
+        }
+
         // 记录日志
-        Log::append('Alipay-notify', [
-            'params' => $this->notifyParams,
-            'verifyNotify' => $verifyNotify,
-            'response' => $this->getNotifyResponse(),
-            'result' => $this->notifyResult,
-            'message' => '支付宝异步回调验证' . ($this->notifyResult ? '成功' : '失败')
-        ]);
+//        Log::append('PayPal-notify', [
+//            'params' => $this->notifyParams,
+//            'verifyNotify' => $verifyNotify,
+//            'response' => $this->getNotifyResponse(),
+//            'result' => $this->notifyResult,
+//            'message' => '支付宝异步回调验证' . ($this->notifyResult ? '成功' : '失败')
+//        ]);
         return $this->notifyResult;
     }
 
     /**
-     * 支付宝退款API
+     * PAYPAL退款API
      * @param string $outTradeNo 第三方交易单号
      * @param string $refundAmount 退款金额
      * @param array $extra 附加的数据
@@ -171,22 +238,8 @@ class PayPal extends Driver
     {
         try {
             // 发起API调用
-            // https://opendocs.alipay.com/apis/028xqg
             $outRequestNo = (string)time();
-            $result = Factory::payment()->common()->refund($outTradeNo, $refundAmount, $outRequestNo);
-            // 记录日志
-            Log::append('Alipay-refund', [
-                'outTradeNo' => $outTradeNo,
-                'refundAmount' => $refundAmount,
-                'result' => $result->toMap()
-            ]);
-            // 处理响应或异常
-            empty($result) && $this->throwError('API无返回结果');
-            $responseChecker = new ResponseChecker();
-            if (!$responseChecker->success($result)) {
-                $this->throwError($result->msg . "," . $result->subMsg);
-            }
-            // 请求成功
+
             return true;
         } catch (\Throwable $e) {
             $this->throwError('支付宝API退款请求:' . $e->getMessage(), true, 'refund');
@@ -215,7 +268,8 @@ class PayPal extends Driver
     {
         return [
             // 第三方交易流水号
-            'tradeNo' => $this->notifyParams['trade_no']
+            'buyerId' => $this->notifyParams['PayerID'],
+            'paymentId' => $this->notifyParams['paymentId']
         ];
     }
 
@@ -228,27 +282,14 @@ class PayPal extends Driver
         return $this->notifyResult ? 'success' : 'FAIL';
     }
 
-    /**
-     * 返回统一下单API的结果 (用于前端)
-     * @return array
-     * @throws BaseException
-     */
     public function getUnifyResult(): array
     {
-        if (empty($this->result)) {
-            $this->throwError('当前没有unify结果', true, 'getUnifyResult');
+        if (empty($this->result->getApprovalLink())) {
+            $this->throwError('paypal当前没有unify结果', true, 'getUnifyResult');
+            return [];
         }
         // 整理返回的数据
-        $result = ['out_trade_no' => $this->result['out_trade_no']];
-        // H5端使用的支付数据
-        if ($this->client === ClientEnum::H5) {
-            $result['formHtml'] = $this->deleteHtmlTags(['script'], $this->result['body']);
-        }
-        // APP端使用的支付数据
-        if ($this->client === ClientEnum::APP) {
-            $result['orderInfo'] = $this->result['body'];
-        }
-        return $result;
+        return ['approval_link' => $this->result->getApprovalLink(), 'id' => $this->result->getId()];
     }
 
     /**
@@ -261,7 +302,6 @@ class PayPal extends Driver
     {
 
 
-
         return $this;
     }
 

+ 6 - 0
config/paypal.php

@@ -0,0 +1,6 @@
+<?php
+return [
+    'web_hook_id' => '3NP026061E6858914',
+    'client_id' => 'AS0FH780ZGtSAdpT1NTjwkFzryCPf69rZb_FR9Rt_rZdasB80cmjqTQ6CQELWiFVh_MU9e31CSnyz7Ai',
+    'client_secret' => 'EDqRQhgLNHCb5bxld98T8-JJJZKvMIeqxudO7lMwDFOxBfy138PjM5A21FnDNyb3q4yYUh8r7Qr2BnVi'
+];