| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- <?php
- namespace App\Services;
- use App\Util;
- class SfPay
- {
- public $config;
- public $merchantKey;
- public $aesKey;
- public $aesIv;
- public $apiUrl;
- public function __construct()
- {
- $payConfigService = new PayConfig();
- $this->config = $payConfigService->getConfig('SfPay');
- $this->merchantKey = $this->config['merchant_key'] ?? '';
- $this->aesKey = $this->config['aes_key'] ?? '';
- $this->aesIv = $this->config['aes_iv'] ?? '';
- $this->apiUrl = $this->config['apiUrl'] ?? 'https://sfgateway.sforest.io';
- }
- /**
- * AES/CBC/PKCS5Padding 加密
- *
- * @param string $str 待加密JSON字符串
- * @return string base64编码的密文
- */
- public function encrypt($str)
- {
- return base64_encode(openssl_encrypt($str, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv));
- }
- /**
- * AES/CBC/PKCS5Padding 解密
- *
- * @param string $encrypted base64编码的密文
- * @return string 解密后的JSON字符串
- */
- public function decrypt($encrypted)
- {
- return openssl_decrypt(base64_decode($encrypted), 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
- }
- /**
- * 验证回调签名
- *
- * signature_n = MD5(merchantKey + message + amount + status + merchantOrderNo + orderNo + aeskey)
- *
- * 注意:如果amount为空,则拼接"null"字符串(代付回调可能出现amount为空的情况)
- *
- * @param array $data 回调data参数
- * @param string $signatureN 签名值
- * @return bool
- */
- public function verifySign($data, $signatureN)
- {
- $message = $data['message'] ?? '';
- $amount = $data['amount'] ?? '';
- $status = $data['status'] ?? '';
- $merchantOrderNo = $data['merchantOrderNo'] ?? '';
- $orderNo = $data['orderNo'] ?? '';
- // 代付回调中amount为空时,拼接"null"字符串
- if ($amount === '' || $amount === null) {
- $amount = 'null';
- }
- $signStr = $this->merchantKey . $message . $amount . $status . $merchantOrderNo . $orderNo . $this->aesKey;
- $expectedSign = md5($signStr);
- Util::WriteLog('SfPay', "待签名字符串: {$signStr}");
- Util::WriteLog('SfPay', "期望签名: {$expectedSign}, 实际签名: {$signatureN}");
- return strtolower($expectedSign) === strtolower($signatureN);
- }
- /**
- * POST JSON请求(SfPay格式:data字段AES加密,merchant_key放在header)
- *
- * @param string $url 请求地址
- * @param array $params 待加密的请求参数
- * @return string|false
- */
- public function curlPost($url, $params)
- {
- $timeout = 30;
- $jsonStr = json_encode($params, JSON_UNESCAPED_UNICODE);
- // AES加密
- $encrypted = $this->encrypt($jsonStr);
- $body = json_encode(['data' => $encrypted], JSON_UNESCAPED_UNICODE);
- $headers = [
- 'Content-Type: application/json;charset=UTF-8',
- 'merchant_key: ' . $this->merchantKey,
- ];
- Util::WriteLog('SfPay', "SfPay请求URL: {$url}");
- Util::WriteLog('SfPay', "SfPay请求明文: {$jsonStr}");
- Util::WriteLog('SfPay', "SfPay请求密文: {$body}");
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
- curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
- $result = curl_exec($ch);
- if (curl_errno($ch)) {
- $error = curl_error($ch);
- Util::WriteLog('SfPay_error', 'CURL Error: ' . $error);
- curl_close($ch);
- return false;
- }
- curl_close($ch);
- Util::WriteLog('SfPay', "SfPay响应: {$result}");
- return $result;
- }
- }
|