diff --git a/src/addon/huaweipay/data/sdk/HuaweiPayClient.php b/src/addon/huaweipay/data/sdk/HuaweiPayClient.php index 071edd32d..6efdd10bc 100644 --- a/src/addon/huaweipay/data/sdk/HuaweiPayClient.php +++ b/src/addon/huaweipay/data/sdk/HuaweiPayClient.php @@ -32,6 +32,45 @@ class HuaweiPayClient // 是否加载了华为平台支付服务加密证书 private $has_huawei_public_key_certificate_instance_encrypt = false; + /** + * 格式化证书内容,添加适当的格式头尾 + * @param string $content 证书内容 + * @param string $type 证书类型:private_key, public_key + * @return string 格式化后的证书内容 + */ + private function formatCertificateContent($content, $type) + { + // 移除空白字符和换行 + $content = preg_replace('/\s+/', '', $content); + + // 检查是否已经包含格式头尾 + if (preg_match('/-----BEGIN.*-----/', $content) && preg_match('/-----END.*-----/', $content)) { + return $content; + } + + // 添加适当的格式头尾 + $header = ''; + $footer = ''; + + if ($type == 'private_key') { + $header = "-----BEGIN PRIVATE KEY-----\n"; + $footer = "\n-----END PRIVATE KEY-----"; + } elseif ($type == 'public_key') { + $header = "-----BEGIN PUBLIC KEY-----\n"; + $footer = "\n-----END PUBLIC KEY-----"; + } + + // 每64个字符添加一个换行 + $formattedContent = $header; + $length = strlen($content); + for ($i = 0; $i < $length; $i += 64) { + $formattedContent .= substr($content, $i, 64) . "\n"; + } + $formattedContent .= $footer; + + return $formattedContent; + } + /** * 构造函数 * @param array $config 华为支付配置 @@ -53,37 +92,58 @@ class HuaweiPayClient try { // 加载商户应用私有证书 - if (!empty($this->config['private_key'])) { + $private_key_content = ''; + if (!empty($this->config['private_key_text'])) { + // 文本模式,需要格式化 + $private_key_content = $this->formatCertificateContent($this->config['private_key_text'], 'private_key'); + } elseif (!empty($this->config['private_key'])) { + // 文件模式 $private_key_path = realpath($cert_base_path . $this->config['private_key']); if (!$private_key_path) { throw new \Exception('商户应用私有证书文件不存在: ' . $this->config['private_key']); } $private_key_content = file_get_contents($private_key_path); - $this->private_key_certificate_instance = openssl_pkey_get_private($private_key_content); - if (!$this->private_key_certificate_instance) { - throw new \Exception('加载商户应用私有证书失败,请检查证书格式是否正确'); - } } else { - throw new \Exception('缺少必要配置:private_key'); + throw new \Exception('缺少必要配置:private_key或private_key_text'); + } + + $this->private_key_certificate_instance = openssl_pkey_get_private($private_key_content); + if (!$this->private_key_certificate_instance) { + throw new \Exception('加载商户应用私有证书失败,请检查证书格式是否正确'); } // 加载华为平台支付证书 - if (!empty($this->config['huawei_public_key'])) { + $huawei_public_key_content = ''; + if (!empty($this->config['huawei_public_key_text'])) { + // 文本模式,需要格式化 + $huawei_public_key_content = $this->formatCertificateContent($this->config['huawei_public_key_text'], 'public_key'); + } elseif (!empty($this->config['huawei_public_key'])) { + // 文件模式 $huawei_public_key_path = realpath($cert_base_path . $this->config['huawei_public_key']); if (!$huawei_public_key_path) { throw new \Exception('华为平台支付证书文件不存在: ' . $this->config['huawei_public_key']); } $huawei_public_key_content = file_get_contents($huawei_public_key_path); - $this->huawei_public_key_certificate_instance = openssl_pkey_get_public($huawei_public_key_content); - if (!$this->huawei_public_key_certificate_instance) { - throw new \Exception('加载华为平台支付证书失败,请检查证书格式是否正确'); - } } else { - throw new \Exception('缺少必要配置:huawei_public_key'); + throw new \Exception('缺少必要配置:huawei_public_key或huawei_public_key_text'); + } + + $this->huawei_public_key_certificate_instance = openssl_pkey_get_public($huawei_public_key_content); + if (!$this->huawei_public_key_certificate_instance) { + throw new \Exception('加载华为平台支付证书失败,请检查证书格式是否正确'); } // 加载华为平台支付服务加密证书(可选) - if (!empty($this->config['huawei_public_key_for_sessionkey'])) { + if (!empty($this->config['huawei_public_key_for_sessionkey_text'])) { + // 文本模式,需要格式化 + $huawei_public_key_encrypt_content = $this->formatCertificateContent($this->config['huawei_public_key_for_sessionkey_text'], 'public_key'); + $this->huawei_public_key_certificate_instance_encrypt = openssl_pkey_get_public($huawei_public_key_encrypt_content); + if (!$this->huawei_public_key_certificate_instance_encrypt) { + throw new \Exception('加载华为平台支付服务加密证书失败'); + } + $this->has_huawei_public_key_certificate_instance_encrypt = true; + } elseif (!empty($this->config['huawei_public_key_for_sessionkey'])) { + // 文件模式 $huawei_public_key_encrypt_path = realpath($cert_base_path . $this->config['huawei_public_key_for_sessionkey']); if (!$huawei_public_key_encrypt_path) { throw new \Exception('华为平台支付服务加密证书文件不存在: ' . $this->config['huawei_public_key_for_sessionkey']); diff --git a/src/addon/huaweipay/model/Config.php b/src/addon/huaweipay/model/Config.php index 3371fedf6..1834b9bf3 100644 --- a/src/addon/huaweipay/model/Config.php +++ b/src/addon/huaweipay/model/Config.php @@ -28,8 +28,11 @@ class Config extends BaseModel // 'app_id', // 'mch_auth_id', 'private_key', + 'private_key_text', 'huawei_public_key', - 'huawei_public_key_for_sessionkey' + 'huawei_public_key_text', + 'huawei_public_key_for_sessionkey', + 'huawei_public_key_for_sessionkey_text' ]; /** diff --git a/src/addon/huaweipay/shop/controller/Pay.php b/src/addon/huaweipay/shop/controller/Pay.php index bfcf8d9fb..9425ed03c 100644 --- a/src/addon/huaweipay/shop/controller/Pay.php +++ b/src/addon/huaweipay/shop/controller/Pay.php @@ -21,10 +21,14 @@ class Pay extends BaseShop $app_id = input("app_id", "");//华为应用ID, // PETALPAY.APPID, 商户号关联的APPID $mch_id = input("mch_id", "");//商户号, // PETALPAY.MERC_NO, 商户号 $private_key = input("private_key", "");//商户应用私钥, // PETALPAY.MERC_PRIVATE_KEY, 商户应用私钥 + $private_key_text = input("private_key_text", "");//商户应用私钥文本, // PETALPAY.MERC_PRIVATE_KEY_TEXT, 商户应用私钥文本 $mch_auth_id = input("mch_auth_id", "");//商户证书id, // PETALPAY.MERC_AUTH_ID, 商户证书id $sign_type = input("sign_type", "RSA2");//商户公私钥签名类型, // PETALPAY.SIGN_TYPE, 签名类型, 默认使用RSA $huawei_public_key = input("huawei_public_key", ""); //华为公钥, // PETALPAY.HW_PAY_PUBLIC_KEY_FOR_CALLBACK, 华为公钥 + $huawei_public_key_text = input("huawei_public_key_text", ""); //华为公钥文本, // PETALPAY.HW_PAY_PUBLIC_KEY_TEXT_FOR_CALLBACK, 华为公钥文本 $huawei_public_key_for_sessionkey = input("huawei_public_key_for_sessionkey", ""); //华为公钥, // PETALPAY.HW_PAY_PUBLIC_KEY_FOR_SESSIONKEY, 华为公钥 + $huawei_public_key_for_sessionkey_text = input("huawei_public_key_for_sessionkey_text", ""); //华为公钥文本, // PETALPAY.HW_PAY_PUBLIC_KEY_TEXT_FOR_SESSIONKEY, 华为公钥文本 + $cert_type = input("cert_type", "file");//证书配置方式, // PETALPAY.CERT_TYPE, 证书配置方式: file(文件上传), text(文本填写) $enable_app_types = input("enable_app_types", '');//支持端口 如web app,app // PETALPAY.ENABLE_APP_TYPES, 支持的支付端口 $pay_status = input("pay_status", 0);//支付启用状态 $refund_status = input("refund_status", 0);//退款启用状态 @@ -34,10 +38,14 @@ class Pay extends BaseShop "app_id" => $app_id, "mch_id" => $mch_id, "private_key" => $private_key, + "private_key_text" => $private_key_text, "mch_auth_id" => $mch_auth_id, "sign_type" => $sign_type, "huawei_public_key" => $huawei_public_key, + "huawei_public_key_text" => $huawei_public_key_text, "huawei_public_key_for_sessionkey" => $huawei_public_key_for_sessionkey, + "huawei_public_key_for_sessionkey_text" => $huawei_public_key_for_sessionkey_text, + "cert_type" => $cert_type, "refund_status" => $refund_status, "pay_status" => $pay_status, "transfer_status" => $transfer_status, diff --git a/src/addon/huaweipay/shop/view/pay/config.html b/src/addon/huaweipay/shop/view/pay/config.html index 68e652936..1ddbff235 100644 --- a/src/addon/huaweipay/shop/view/pay/config.html +++ b/src/addon/huaweipay/shop/view/pay/config.html @@ -1,9 +1,19 @@
+
+ +
+ + +
+
+
@@ -23,15 +33,22 @@
- {notempty name="$info.private_key"} -

已上传✅

- {else/} -

未上传

- {/notempty} - - + +
+ {notempty name="$info.private_key" && empty($info.private_key_text)} +

已上传✅

+ {else/} +

未上传

+ {/notempty} + + +
+ +
+ +
上传商户应用私钥.pem 文件
如何获取商户应用私钥.pem文件 查看指引
@@ -48,15 +65,22 @@
- {notempty name="$info.huawei_public_key"} -

已上传✅

- {else/} -

未上传

- {/notempty} - - + +
+ {notempty name="$info.huawei_public_key" && empty($info.huawei_public_key_text)} +

已上传✅

+ {else/} +

未上传

+ {/notempty} + + +
+ +
+ +
上传华为支付证书.pem文件
如何获取华为支付证书.pem文件,查看指引
@@ -65,15 +89,22 @@
- {notempty name="$info.huawei_public_key_for_sessionkey"} -

已上传✅

- {else/} -

未上传

- {/notempty} - - + +
+ {notempty name="$info.huawei_public_key_for_sessionkey" && empty($info.huawei_public_key_for_sessionkey_text)} +

已上传✅

+ {else/} +

未上传

+ {/notempty} + + +
+ +
+ +
上传华为支付服务加密公钥.pem文件
(可选)加密公钥, 没有可以不填 查看指引
@@ -118,115 +149,163 @@