diff --git a/app/Payments/AlipayF2F.php b/app/Payments/AlipayF2F.php index 12fe91b7..87d6a62f 100644 --- a/app/Payments/AlipayF2F.php +++ b/app/Payments/AlipayF2F.php @@ -5,8 +5,6 @@ */ namespace App\Payments; -use Omnipay\Omnipay; - class AlipayF2F { public function __construct($config) { @@ -36,28 +34,25 @@ class AlipayF2F { 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) diff --git a/composer.json b/composer.json index b475e43c..b219618c 100755 --- a/composer.json +++ b/composer.json @@ -20,7 +20,6 @@ "laravel/horizon": "^4.3.5", "laravel/tinker": "^2.5", "linfo/linfo": "^4.0", - "lokielse/omnipay-alipay": "3.1.2", "lokielse/omnipay-wechatpay": "^3.0", "php-curl-class/php-curl-class": "^8.6", "stripe/stripe-php": "^7.36.1", diff --git a/library/AlipayF2F.php b/library/AlipayF2F.php new file mode 100644 index 00000000..a82bdbad --- /dev/null +++ b/library/AlipayF2F.php @@ -0,0 +1,164 @@ +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; + } +}