appId = getSetting('pay_alipay_appid', ''); $this->privateKey = getSetting('pay_alipay_private_key', ''); $this->publicKey = getSetting('pay_alipay_public_key', ''); // 沙箱模式(开发测试用) if (getSetting('pay_alipay_sandbox', '0') === '1') { $this->gatewayUrl = $this->sandboxUrl; } } public function getName() { return '支付宝'; } /** * 创建支付宝电脑网站支付订单。 */ public function createOrder(array $order) { $params = [ 'app_id' => $this->appId, 'method' => 'alipay.trade.page.pay', 'format' => 'JSON', 'return_url' => $order['return_url'], 'notify_url' => $order['notify_url'], 'charset' => 'utf-8', 'sign_type' => 'RSA2', 'timestamp' => date('Y-m-d H:i:s'), 'version' => '1.0', 'biz_content' => json_encode([ 'out_trade_no' => $order['order_no'], 'total_amount' => sprintf('%.2f', $order['amount']), 'subject' => $order['subject'], 'product_code' => 'FAST_INSTANT_TRADE_PAY', ], JSON_UNESCAPED_UNICODE), ]; $params['sign'] = $this->sign($params); // 构建跳转 URL(GET 方式) $url = $this->gatewayUrl . '?' . http_build_query($params); return ['url' => $url, 'form' => '']; } public function verifyNotify(array $params) { if (empty($params['sign'])) return false; $sign = $params['sign']; unset($params['sign'], $params['sign_type']); return $this->rsaVerify($this->buildSignData($params), $sign); } public function getTradeNo(array $params) { return $params['trade_no'] ?? ''; } public function isPaid(array $params) { return ($params['trade_status'] ?? '') === 'TRADE_SUCCESS'; } public function respondSuccess() { echo 'success'; } // ─── 签名相关 ─── private function sign($params) { ksort($params); $data = $this->buildSignData($params); $res = openssl_sign($data, $signature, $this->loadPrivateKey(), OPENSSL_ALGO_SHA256); return base64_encode($signature); } private function rsaVerify($data, $sign) { $result = openssl_verify($data, base64_decode($sign), $this->loadPublicKey(), OPENSSL_ALGO_SHA256); return $result === 1; } private function buildSignData($params) { $pairs = []; foreach ($params as $k => $v) { if ($v === '' || is_array($v)) continue; $pairs[] = $k . '=' . $v; } return implode('&', $pairs); } private function loadPrivateKey() { $key = trim($this->privateKey); $key = preg_replace('/-----BEGIN RSA PRIVATE KEY-----/', '', $key); $key = preg_replace('/-----END RSA PRIVATE KEY-----/', '', $key); $key = str_replace(["\r", "\n", " "], '', $key); return "-----BEGIN RSA PRIVATE KEY-----\n" . chunk_split($key, 64, "\n") . "-----END RSA PRIVATE KEY-----"; } private function loadPublicKey() { $key = trim($this->publicKey); $key = preg_replace('/-----BEGIN PUBLIC KEY-----/', '', $key); $key = preg_replace('/-----END PUBLIC KEY-----/', '', $key); $key = str_replace(["\r", "\n", " "], '', $key); return "-----BEGIN PUBLIC KEY-----\n" . chunk_split($key, 64, "\n") . "-----END PUBLIC KEY-----"; } }