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/gateway.do', $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; } }