| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- <?php
- namespace App\Services;
- use App\Util;
- class WDPay
- {
- public $config;
- public $key;
- public $customerNo;
- public $apiUrl;
- public function __construct()
- {
- $payConfigService = new PayConfig();
- $this->config = $payConfigService->getConfig('WDPay');
-
- $this->key = $this->config['key'] ?? '';
- $this->customerNo = $this->config['customerNo'] ?? '';
- // WDPay官方接口:/charging/create-pay-in
- $this->apiUrl = $this->config['apiUrl'] ?? '';
- }
- /**
- * 签名 - WDPay专用签名算法
- *
- * 规则:
- * 1. 按参数名ASCII码从小到大排序(字典序)
- * 2. 空值不参与签名
- * 3. sign参数不参与签名
- * 4. 拼接格式:key1=value1&key2=value2&key=商户密钥
- * 5. MD5后转大写
- */
- public function sign(array $params): array
- {
- // 移除sign和空值
- $signParams = [];
- foreach ($params as $key => $value) {
- if ($key !== 'sign' && $value !== null && $value !== '') {
- // 如果是对象或数组,需要递归处理
- if (is_array($value) || is_object($value)) {
- $signParams[$key] = $this->buildObjectString($value);
- } else {
- $signParams[$key] = $value;
- }
- }
- }
-
- // 按ASCII码排序
- ksort($signParams);
-
- // 拼接字符串:key1=value1&key2=value2
- $stringA = urldecode(http_build_query($signParams));
-
- // 拼接商户密钥:stringA&key=商户密钥
- $stringSignTemp = $stringA . '&key=' . $this->key;
-
- // MD5并转大写
- $sign = strtoupper(md5($stringSignTemp));
-
- // 将签名添加到参数中
- $params['sign'] = $sign;
-
- Util::WriteLog('WDPay_sign', "待签名字符串: " . $stringSignTemp);
- Util::WriteLog('WDPay_sign', "签名结果: " . $sign);
-
- return $params;
- }
- /**
- * 验签 - WDPay专用验签算法
- */
- public function verifySign(array $params): bool
- {
- if (!isset($params['sign'])) {
- return false;
- }
-
- $receivedSign = $params['sign'];
-
- // 移除sign和空值
- $signParams = [];
- foreach ($params as $key => $value) {
- if ($key !== 'sign' && $value !== null && $value !== '') {
- if (is_array($value) || is_object($value)) {
- $signParams[$key] = $this->buildObjectString($value);
- } else {
- $signParams[$key] = $value;
- }
- }
- }
-
- // 按ASCII码排序
- ksort($signParams);
-
- // 拼接字符串
- $stringA = urldecode(http_build_query($signParams));
-
- // 拼接商户密钥
- $stringSignTemp = $stringA . '&key=' . $this->key;
-
- // MD5并转大写
- $calculatedSign = strtoupper(md5($stringSignTemp));
-
- Util::WriteLog('WDPay_verify', "待验签字符串: " . $stringSignTemp);
- Util::WriteLog('WDPay_verify', "计算签名: " . $calculatedSign);
- Util::WriteLog('WDPay_verify', "接收签名: " . $receivedSign);
-
- return $calculatedSign === $receivedSign;
- }
-
- /**
- * 递归处理对象/数组为字符串
- */
- private function buildObjectString($data): string
- {
- if (is_array($data)) {
- $parts = [];
- ksort($data);
- foreach ($data as $k => $v) {
- if ($v !== null && $v !== '') {
- if (is_array($v) || is_object($v)) {
- $parts[] = $k . '=' . $this->buildObjectString($v);
- } else {
- $parts[] = $k . '=' . $v;
- }
- }
- }
- return implode('&', $parts);
- }
- return (string)$data;
- }
- /**
- * 生成随机字符串
- */
- public function getNonceStr($length = 16): string
- {
- $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
- $str = "";
- for ($i = 0; $i < $length; $i++) {
- $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
- }
- return $str;
- }
- /**
- * POST请求 - application/x-www-form-urlencoded
- */
- public function curlPost($url, $payload)
- {
- $timeout = 20;
-
- // WDPay使用 application/x-www-form-urlencoded 格式
- $data = http_build_query($payload);
-
- $headers = [
- 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
- ];
- $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, $data);
- 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);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- if (curl_errno($ch)) {
- $error = curl_error($ch);
- Util::WriteLog('WDPay_error', 'CURL Error: ' . $error);
- curl_close($ch);
- return false;
- }
- if ($httpCode != 200) {
- Util::WriteLog('WDPay_error', 'HTTP Code: ' . $httpCode . " | Response: " . $result);
- }
- curl_close($ch);
- return $result;
- }
- }
|