diff --git a/WeChat/Contracts/BasicAliPay.php b/WeChat/Contracts/BasicAliPay.php index d50f1cd..e43c040 100644 --- a/WeChat/Contracts/BasicAliPay.php +++ b/WeChat/Contracts/BasicAliPay.php @@ -63,8 +63,6 @@ abstract class BasicAliPay */ public function __construct($options) { - $this->params = new DataArray([]); - $this->config = new DataArray($options); if (empty($options['appid'])) { throw new InvalidArgumentException('Missing Config -- [appid]'); } @@ -81,8 +79,10 @@ abstract class BasicAliPay throw new InvalidArgumentException('Missing Config -- [private_key]'); } if (!empty($options['debug'])) { - $this->gateway = 'https://openapi.alipaydev.com/gateway.do?charset=utf-8'; + $this->gateway = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do?charset=utf-8'; } + $this->params = new DataArray([]); + $this->config = new DataArray($options); $this->options = new DataArray([ 'app_id' => $this->config->get('appid'), 'charset' => empty($options['charset']) ? 'utf-8' : $options['charset'], @@ -108,7 +108,7 @@ abstract class BasicAliPay $this->config->set('app_cert', file_get_contents($appCertPath)); } if (!$this->config->get('root_cert') && !empty($aliRootPath) && is_file($aliRootPath)) { - $this->config->set('root_cert', file_get_contents($appCertPath)); + $this->config->set('root_cert', file_get_contents($aliRootPath)); } } @@ -197,13 +197,14 @@ abstract class BasicAliPay */ protected function verify($data, $sign) { + unset($data['sign']); if ($this->options->get('sign_type') === 'RSA2') { if (openssl_verify(json_encode($data, 256), base64_decode($sign), $this->getAliPublicKey(), OPENSSL_ALGO_SHA256) !== 1) { - throw new InvalidResponseException('Data signature verification failed.'); + throw new InvalidResponseException('Data signature verification failed by RSA2.'); } } else { if (openssl_verify(json_encode($data, 256), base64_decode($sign), $this->getAliPublicKey(), OPENSSL_ALGO_SHA1) !== 1) { - throw new InvalidResponseException('Data signature verification failed.'); + throw new InvalidResponseException('Data signature verification failed by RSA.'); } } return $data; @@ -284,9 +285,9 @@ abstract class BasicAliPay $data[$method]['code'], $data ); } - return $data[$method]; - // 去除返回结果签名检查 - // return $this->verify($data[$method], $data['sign']); + // return $data[$method]; + // 返回结果签名检查 + return $this->verify($data[$method], $data['sign']); } /** @@ -318,10 +319,17 @@ abstract class BasicAliPay * 获取支付公钥内容 * @return string */ - private function getAliPublicKey() + public function getAliPublicKey() { - $content = wordwrap($this->trimCert($this->config->get('public_key')), 64, "\n", true); - return "-----BEGIN PUBLIC KEY-----\n{$content}\n-----END PUBLIC KEY-----"; + $cert = $this->config->get('public_key'); + if (strpos(trim($cert), '-----BEGIN CERTIFICATE-----') !== false) { + $pkey = openssl_pkey_get_public($cert); + $keyData = openssl_pkey_get_details($pkey); + return trim($keyData['key']); + } else { + $content = wordwrap($this->trimCert($cert), 64, "\n", true); + return "-----BEGIN PUBLIC KEY-----\n{$content}\n-----END PUBLIC KEY-----"; + } } /** @@ -347,9 +355,9 @@ abstract class BasicAliPay for ($i = 0; $i < count($array) - 1; $i++) { $ssl[$i] = openssl_x509_parse($array[$i] . '-----END CERTIFICATE-----', true); if (strpos($ssl[$i]['serialNumber'], '0x') === 0) { - $ssl[$i]['serialNumber'] = $this->_hex2dec(isset($ssl[$i]['serialNumberHex']) ? $ssl[$i]['serialNumberHex'] : $ssl[$i]['serialNumber']); + $ssl[$i]['serialNumber'] = $this->_hex2dec($ssl[$i]['serialNumberHex']); } - if ($ssl[$i]['signatureTypeLN'] == "sha1WithRSAEncryption" || $ssl[$i]['signatureTypeLN'] == "sha256WithRSAEncryption") { + if ($ssl[$i]['signatureTypeLN'] == 'sha1WithRSAEncryption' || $ssl[$i]['signatureTypeLN'] == 'sha256WithRSAEncryption') { if ($sn == null) { $sn = md5($this->_arr2str(array_reverse($ssl[$i]['issuer'])) . $ssl[$i]['serialNumber']); } else { @@ -394,7 +402,7 @@ abstract class BasicAliPay $string[] = $key . '=' . $value; } } - return implode(',', $string); + return join(',', $string); } /** diff --git a/_test/alipay-app.php b/_test/alipay-app.php index 5ecbdd8..fa0d8d4 100644 --- a/_test/alipay-app.php +++ b/_test/alipay-app.php @@ -32,7 +32,13 @@ try { 'total_amount' => '1', // 支付金额 'subject' => '支付宝订单标题', // 支付订单描述 ]); - echo $result; + echo $result . PHP_EOL .'

'. PHP_EOL; + + // 请求关闭订单 + $result = $pay->close([ + 'out_trade_no' => strval(time()) + ]); + echo PHP_EOL . PHP_EOL . $result; } catch (\Exception $e) { echo $e->getMessage(); } diff --git a/_test/alipay-transfer.php b/_test/alipay-transfer.php index 2c709c3..ceacc01 100644 --- a/_test/alipay-transfer.php +++ b/_test/alipay-transfer.php @@ -18,7 +18,7 @@ include "../include.php"; // 2. 准备公众号配置参数 -$config = include "./alipay.php"; +$config = include "./alipay2.php"; try { // 实例支付对象 @@ -30,10 +30,10 @@ try { $result = $pay->apply([ 'out_biz_no' => time(), // 订单号 'payee_type' => 'ALIPAY_LOGONID', // 收款方账户类型(ALIPAY_LOGONID | ALIPAY_USERID) - 'payee_account' => 'demo@sandbox.com', // 收款方账户 + 'payee_account' => 'yvvfcr3065@sandbox.com', // 收款方账户 'amount' => '10', // 转账金额 'payer_show_name' => '未寒', // 付款方姓名 - 'payee_real_name' => '张三', // 收款方真实姓名 + 'payee_real_name' => 'yvvfcr3065', // 收款方真实姓名 'remark' => '张三', // 转账备注 ]); diff --git a/_test/alipay2.php b/_test/alipay2.php new file mode 100644 index 0000000..4e89d9a --- /dev/null +++ b/_test/alipay2.php @@ -0,0 +1,58 @@ + true, + // 签名类型 ( RSA|RSA2 ) + 'sign_type' => 'RSA2', + // 应用ID + 'appid' => '2021000122667306', + // 应用私钥内容 ( 需1行填写,特别注意:这里的应用私钥通常由支付宝密钥管理工具生成 ) + 'private_key' => 'MIIEowIBAAKCAQEAndH26KVe3Iy+8GxVxDuG9ZolYrqGNm8Jpdi9GrQdM81ad4pPyul2NVO+9C2Kr6a6jK6Qw1gyzcwYxtkUC7xoLZUSPpmSH7sH3sD6r2B7Mf5FsrVSa29lcm1+3UkyFgZjYTkx45lfbLmAFHOzOl0WfGkMW0Sq3N/5OMr074E4EnYtALdE3jVQCDf8bzqN3j/Kwe7f10Aglvxili2BrFM564silqcbiJ8U1zDmTdZvmEkP7ia/YVkmt5w3rh7ZBoaubtcM/rVGYXL2hQPwr/pquNCTu7Eh1RcWfpcnbuw+gOnaNyXmNFmZkeNlegXIifcunt1GK6a1pX090R8eFN3LjQIDAQABAoIBACrLY4OETCvL8n6pMbyLU7ZHfTm/UGN0So5xLh4OlxiT56MgmzBvjAE72zzFGKU2tcEuGM0Pnn8Vh+ZruLbR+QHbOV5GMExwX9r0Q0XJCL7uryGdb2L4iu6zaEJC9dTpGIulgbSwwyJtTqC9Gu2Jjm5f4dzhyt8n0KGozzAevwCqI9RaJSD96gGWLbMlHCyWKGy1OdBP4V/+agPyHAGZ9gqpfKY7y4L0My8gUxhWzQWOwihtFACjV66ULhutUYT2bro3j1k9UekKlX7IiWrssPmmmw2vfUbrKiNugF6zkfyStPt7jGJ0CdzAHWe3pyF72TyO5NU2NGcX8eKgYlY2crUCgYEAzOcg5Zot9X+Ao+fYH/Oq/3eGZd6krzByiXfcjuRco7mGODwmUnzt3PpPT1fPry9TxarTajt+A9LuxqWawfQ9eWAfrTGAbtDJB0LYo6CynDqUoRqBukROuNaLQiUqEreOQqt08o6VVblgVLv8475ij8s4z/6C2NSSjgUJHf0PL38CgYEAxS0bcXGI+WtempZ4Q3QMTUmp/+B3zuw9JzSV1gvbVi7MleI9V62V2IXHPSXL5mRhYOuQWR0MnVOhbo69fkEA8HpdSd1q2JjaeS+OiZ0ditcJISQJbqWtvmF2+XtQcbVwfID69GWGxyBEHHTW8AtAzIPc6T7x2izyzBw0lXDHSvMCgYEAi+Y61ckhG/9EC6TeMWKjG+21u5P6CQshCK7nzkAo6DhhZb/bwnI9zaSxxdCEom3D2rA5zMx1y5KXKNYlBcwGtPpmZk/oCsFOoECJvZ6YlIaCuERq0oyU2yrQxgat5T2iSe7a2El1uKPrG6+GiNCSZu8wCQMSv4zTy1ew0+LWHW0CgYAvX7ESRpcEZjmqprBqdH1oLGS9566hdr0SqF2/ucWPJVteP6dBY6F3Dl1aYbRlvIRxBuf9oS8gtbE5oO4CYZfaL2wujRZYyBDlwPlcMvWgIB4/aish/IiMD1rIgkpHp7JJF6w0ABiryyLSO3hQ4ENHX/85wzfUlawYQkaYCSq45QKBgCdqrv58KD8tDYn4JnaHJNE+5TgKK5cNhYLZLAsYz7x1KfPdkiC7y/hnenn3TWkm4xw8Tw1rJ1ZIJ24iZgTCTO7EEsB7jZegvg4z/4zVbSK2Y4VI1lJ7jlyqmwg0ArimXTNZFoy66h9c9t2smG40YEZCmmmTLEqVlWgyR1MU5iM5', + // 公钥模式,支付宝公钥内容 ( 需1行填写,特别注意:这里不是应用公钥而是支付宝公钥,通常是上传应用公钥换取支付宝公钥,在网页可以复制 ) + 'public_key' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuQ70Xj4AHsIsjjuFK2EexkUVDGc6KCBzhHylt5vbgGTJFzrElV6Ri3O4nxwtKzLWykRfjOC5M9z5vt7NrmSc3WPal0B82TNt0SDVO3gDRvnFswB9pC1WHBTRqiGEsX6LpNOCiykyYHAmc3b74R1rotxytOpLt9/HwjZuGStouUQ7gLqnFRwYLKis8tW9FY5NEL9HPENREcRoaUE8zHE6l4jNi5g2Dvs4r5KqnTNvmeRTc87ZylKs4JPhSWskOaqBJmDAcTR770x0G694tKjW5sbm4a/PxWOV3eEG9XLA4CcS6gwHG1KsRu+eTPszQwkEOZCT8PxZJ6SbaUwZsUO4ZQIDAQAB', + // 证书模式,应用公钥证书路径 ( 新版资金类接口转 app_cert_sn,如文件 appCertPublicKey.crt ) + 'app_cert_path' => __DIR__ . '/alipay/appPublicCert.crt', // 'app_cert' => '证书内容', + // 证书模式,支付宝根证书路径 ( 新版资金类接口转 alipay_root_cert_sn,如文件 alipayRootCert.crt ) + 'alipay_root_path' => __DIR__ . '/alipay/alipayRootCert.crt', // 'root_cert' => '证书内容', + // 证书模式,支付宝公钥证书路径 ( 未填写 public_key 时启用此参数,如文件 alipayPublicCert.crt ) + // 'alipay_cert_path' => __DIR__ . '/alipay/alipayPublicCert.crt', // 'public_key' => '证书内容' + // 支付成功通知地址 + 'notify_url' => '', + // 网页支付回跳地址 + 'return_url' => '', +]; \ No newline at end of file