Browse Source

update: rewrite alipay f2f sdk

tokumeikoi 3 years ago
parent
commit
36f87bd61f
3 changed files with 182 additions and 24 deletions
  1. 18 23
      app/Payments/AlipayF2F.php
  2. 0 1
      composer.json
  3. 164 0
      library/AlipayF2F.php

+ 18 - 23
app/Payments/AlipayF2F.php

@@ -5,8 +5,6 @@
  */
  */
 namespace App\Payments;
 namespace App\Payments;
 
 
-use Omnipay\Omnipay;
-
 class AlipayF2F {
 class AlipayF2F {
     public function __construct($config)
     public function __construct($config)
     {
     {
@@ -36,28 +34,25 @@ class AlipayF2F {
 
 
     public function pay($order)
     public function pay($order)
     {
     {
-        $gateway = Omnipay::create('Alipay_AopF2F');
-        $gateway->setSignType('RSA2'); //RSA/RSA2
-        $gateway->setAppId($this->config['app_id']);
-        $gateway->setPrivateKey($this->config['private_key']); // 可以是路径,也可以是密钥内容
-        $gateway->setAlipayPublicKey($this->config['public_key']); // 可以是路径,也可以是密钥内容
-        $gateway->setNotifyUrl($order['notify_url']);
-        $request = $gateway->purchase();
-        $request->setBizContent([
-            'subject' => config('v2board.app_name', 'V2Board') . ' - 订阅',
-            'out_trade_no' => $order['trade_no'],
-            'total_amount' => $order['total_amount'] / 100
-        ]);
-        /** @var \Omnipay\Alipay\Responses\AopTradePreCreateResponse $response */
-        $response = $request->send();
-        $result = $response->getAlipayResponse();
-        if ($result['code'] !== '10000') {
-            abort(500, $result['sub_msg']);
+        try {
+            $gateway = new \Library\AlipayF2F();
+            $gateway->setAppId($this->config['app_id']);
+            $gateway->setPrivateKey($this->config['private_key']); // 可以是路径,也可以是密钥内容
+            $gateway->setAlipayPublicKey($this->config['public_key']); // 可以是路径,也可以是密钥内容
+            $gateway->setNotifyUrl($order['notify_url']);
+            $gateway->setBizContent([
+                'subject' => config('v2board.app_name', 'V2Board') . ' - 订阅',
+                'out_trade_no' => $order['trade_no'],
+                'total_amount' => $order['total_amount'] / 100
+            ]);
+            $gateway->send();
+            return [
+                'type' => 0, // 0:qrcode 1:url
+                'data' => $gateway->getQrCodeUrl()
+            ];
+        } catch (\Exception $e) {
+            abort(500, $e->getMessage());
         }
         }
-        return [
-            'type' => 0, // 0:qrcode 1:url
-            'data' => $response->getQrCode()
-        ];
     }
     }
 
 
     public function notify($params)
     public function notify($params)

+ 0 - 1
composer.json

@@ -20,7 +20,6 @@
         "laravel/horizon": "^4.3.5",
         "laravel/horizon": "^4.3.5",
         "laravel/tinker": "^2.5",
         "laravel/tinker": "^2.5",
         "linfo/linfo": "^4.0",
         "linfo/linfo": "^4.0",
-        "lokielse/omnipay-alipay": "3.1.2",
         "lokielse/omnipay-wechatpay": "^3.0",
         "lokielse/omnipay-wechatpay": "^3.0",
         "php-curl-class/php-curl-class": "^8.6",
         "php-curl-class/php-curl-class": "^8.6",
         "stripe/stripe-php": "^7.36.1",
         "stripe/stripe-php": "^7.36.1",

+ 164 - 0
library/AlipayF2F.php

@@ -0,0 +1,164 @@
+<?php
+namespace Library;
+
+use Illuminate\Support\Facades\Http;
+
+class AlipayF2F {
+    private $appId;
+    private $privateKey;
+    private $alipayPublicKey;
+    private $signType = 'RSA2';
+    public $bizContent;
+    public $method;
+    public $notifyUrl;
+    public $response;
+
+    public function __construct()
+    {
+    }
+
+    public function verify($data): bool
+    {
+        if (is_string($data)) {
+            parse_str($data, $data);
+        }
+        $sign = $data['sign'];
+        unset($data['sign']);
+        unset($data['sign_type']);
+        ksort($data);
+        $data = $this->buildQuery($data);
+        $res = "-----BEGIN PUBLIC KEY-----\n" .
+            wordwrap($this->alipayPublicKey, 64, "\n", true) .
+            "\n-----END PUBLIC KEY-----";
+        if ("RSA2" == $this->signType) {
+            $result = (openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256) === 1);
+        } else {
+            $result = (openssl_verify($data, base64_decode($sign), $res) === 1);
+        }
+        openssl_free_key(openssl_get_publickey($res));
+        return $result;
+    }
+
+    public function setBizContent($bizContent = [])
+    {
+        $this->bizContent = json_encode($bizContent);
+    }
+
+    public function setMethod($method)
+    {
+        $this->method = $method;
+    }
+
+    public function setAppId($appId)
+    {
+        $this->appId = $appId;
+    }
+
+    public function setPrivateKey($privateKey)
+    {
+        $this->privateKey = $privateKey;
+    }
+
+    public function setAlipayPublicKey($alipayPublicKey)
+    {
+        $this->alipayPublicKey = $alipayPublicKey;
+    }
+
+    public function setNotifyUrl($url)
+    {
+        $this->notifyUrl = $url;
+    }
+
+    public function send()
+    {
+        $response = Http::get('https://openapi.alipay.com', $this->buildParam())->json();
+        $resKey = str_replace('.', '_', $this->method) . '_response';
+        if (!isset($response[$resKey])) throw new \Exception('从支付宝请求失败');
+        $response = $response[$resKey];
+        if ($response['msg'] !== 'Success') throw new \Exception($response['sub_msg']);
+        $this->response = $response;
+    }
+
+    public function getQrCodeUrl()
+    {
+        $response = $this->response;
+        if (!isset($response['qr_code'])) throw new \Exception('获取付款二维码失败');
+        return $response['qr_code'];
+    }
+
+    public function getResponse()
+    {
+        return $this->response;
+    }
+
+    public function buildParam(): array
+    {
+        $params = [
+            'app_id' => $this->appId,
+            'method' => $this->method,
+            'charset' => 'UTF-8',
+            'sign_type' => $this->signType,
+            'timestamp' => date('Y-m-d H:m:s'),
+            'biz_content' => $this->bizContent,
+            'version' => '1.0',
+            '_input_charset' => 'UTF-8'
+        ];
+        if ($this->notifyUrl) $params['notify_url'] = $this->notifyUrl;
+        ksort($params);
+        $params['sign'] = $this->buildSign($this->buildQuery($params));
+        return $params;
+    }
+
+    public function buildQuery($query)
+    {
+        if (!$query) {
+            throw new \Exception('参数构造错误');
+        }
+        //将要 参数 排序
+        ksort($query);
+
+        //重新组装参数
+        $params = array();
+        foreach ($query as $key => $value) {
+            $params[] = $key . '=' . $value;
+        }
+        $data = implode('&', $params);
+        return $data;
+    }
+
+    private function buildSign(string $signData): string
+    {
+        $privateKey = $this->privateKey;
+        $p_key = array();
+        //如果私钥是 1行
+        if (!stripos($privateKey, "\n")) {
+            $i = 0;
+            while ($key_str = substr($privateKey, $i * 64, 64)) {
+                $p_key[] = $key_str;
+                $i++;
+            }
+        }
+        $privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" . implode("\n", $p_key);
+        $privateKey = $privateKey . "\n-----END RSA PRIVATE KEY-----";
+
+        //私钥
+        $privateId = openssl_pkey_get_private($privateKey, '');
+
+        // 签名
+        $signature = '';
+
+        if ("RSA2" == $this->signType) {
+
+            openssl_sign($signData, $signature, $privateId, OPENSSL_ALGO_SHA256);
+        } else {
+
+            openssl_sign($signData, $signature, $privateId, OPENSSL_ALGO_SHA1);
+        }
+
+        openssl_free_key($privateId);
+
+        //加密后的内容通常含有特殊字符,需要编码转换下
+        $signature = base64_encode($signature);
+        return $signature;
+    }
+}