chore(addon-huaweipay): 支持华为支付参数配置

This commit is contained in:
2025-12-01 15:28:38 +08:00
parent 39ce5882cb
commit 981779126c
7 changed files with 154 additions and 74 deletions

View File

@@ -0,0 +1,17 @@
<?php
namespace addon\wechatpay\event;
/**
* 应用安装
*/
class Install
{
/**
* 执行安装
*/
public function handle()
{
return success();
}
}

View File

@@ -15,18 +15,19 @@ class PayType
/** /**
* 支付方式及配置 * 支付方式及配置
*/ */
public function handle($param) public function handle($params)
{ {
$app_type = $param['app_type'] ?? ''; $config_model = new Config();
$config_result = $config_model->getPayConfig($params[ 'site_id' ] ?? 1);
$config = $config_result[ "data" ][ "value" ] ?? [];
$pay_status = $config[ "pay_status" ] ?? 0;
$app_type = $params['app_type'] ?? '';
if (!empty($app_type)) { if (!empty($app_type)) {
if (!in_array($app_type, [ "h5", "app", "pc", "hwapp" ])) { $app_type_array = [ 'h5', 'wechat', 'weapp', 'pc', 'app', 'hwapp'];
if (!in_array($app_type, $app_type_array)) {
return ''; return '';
} }
$config_model = new Config();
$config_result = $config_model->getPayConfig($param[ 'site_id' ]);
$config = $config_result[ "data" ][ "value" ] ?? [];
$pay_status = $config[ "pay_status" ] ?? 0;
if ($pay_status == 0) { if ($pay_status == 0) {
return ''; return '';
} }
@@ -37,8 +38,10 @@ class PayType
"edit_url" => "huaweipay://shop/pay/config", "edit_url" => "huaweipay://shop/pay/config",
"shop_url" => "huaweipay://shop/pay/config", "shop_url" => "huaweipay://shop/pay/config",
"logo" => "addon/huaweipay/icon.png", "logo" => "addon/huaweipay/icon.png",
"desc" => "华为支付(www.huawei.com) 是华为公司提供的网上支付平台。" "desc" => "华为支付(www.huawei.com) 是华为公司提供的网上支付平台。",
"pay_status" => $pay_status,
); );
return $info; return $info;
} }
} }

View File

@@ -4,17 +4,32 @@
*/ */
namespace addon\huaweipay\event; namespace addon\huaweipay\event;
use addon\huaweipay\model\config;
/** /**
* 转账类型 * 转账类型 (前后台调用)
*/ */
class TransferType class TransferType
{ {
/** /**
* 转账类型处理 * 转账类型处理
*/ */
public function handle($param) public function handle($params)
{ {
$app_type = $params['app_type'] ?? '';
if (!empty($app_type)) {
$config_model = new Config();
$app_type_array = $config_model->app_type;
if (!in_array($app_type, $app_type_array)) {
return '';
}
$config_result = $config_model->getPayConfig($params[ 'site_id' ]);
$config = $config_result[ "data" ][ "value" ] ?? [];
$transfer_status = $config[ "transfer_status" ] ?? 0;
if ($transfer_status == 0) {
return '';
}
}
$info = array ( $info = array (
"pay_type" => "huaweipay", "pay_type" => "huaweipay",
"pay_type_name" => "华为支付", "pay_type_name" => "华为支付",

View File

@@ -0,0 +1,17 @@
<?php
namespace addon\wechatpay\event;
/**
* 应用卸载
*/
class UnInstall
{
/**
* 执行卸载
*/
public function handle()
{
return success();
}
}

View File

@@ -1,6 +1,10 @@
<?php <?php
/** /**
* 华为支付配置模型 * 华为支付配置模型
* 用于存储和管理华为支付的配置信息
* 版本1.0.0
* 日期2025-12-01
*/ */
namespace addon\huaweipay\model; namespace addon\huaweipay\model;
@@ -13,9 +17,19 @@ use app\model\BaseModel;
*/ */
class Config extends BaseModel class Config extends BaseModel
{ {
// 加密标识
private $encrypt = '******'; private $encrypt = '******';
// 加密字段
private $encrypt_fields = [
// 'mch_id',
// 'app_id',
// 'mch_auth_id',
'private_key',
'huawei_public_key',
'huawei_public_key_for_sessionkey'
];
/** /**
* 设置支付配置 * 设置支付配置
* @param $data * @param $data
@@ -28,23 +42,22 @@ class Config extends BaseModel
$config = new ConfigModel(); $config = new ConfigModel();
// 未加密前的数据 // 未加密前的数据
$original_config = $this->getPayConfig($site_id)[ 'data' ][ 'value' ] ?? []; $original_config = $this->getPayConfig($site_id)['data']['value'] ?? [];
// 检测数据是否发生变化,如果没有变化,则保持未加密前的数据 // 检测数据是否发生变化,如果没有变化,则保持未加密前的数据
if (!empty($data[ 'app_id' ]) && $data[ 'app_id' ] == $this->encrypt) { // 定义一个数组,用于存储需要加密的字段
$data[ 'app_id' ] = $original_config[ 'app_id' ]; // 应用ID $encrypt_fields = $this->encrypt_fields;
} $is_change = false;
if (!empty($data[ 'private_key' ]) && $data[ 'private_key' ] == $this->encrypt) {
$data[ 'private_key' ] = $original_config[ 'private_key' ]; // 应用私钥 // 遍历需要加密的字段
} foreach ($encrypt_fields as $field) {
if (!empty($data[ 'public_key' ]) && $data[ 'public_key' ] == $this->encrypt) { if (!empty($data[$field]) && $data[$field] == $this->encrypt) {
$data[ 'public_key' ] = $original_config[ 'public_key' ]; // 应用公钥 $data[$field] = $original_config[$field]; // 应用ID
} $is_change = true;
if (!empty($data[ 'huawei_public_key' ]) && $data[ 'huawei_public_key' ] == $this->encrypt) { }
$data[ 'huawei_public_key' ] = $original_config[ 'huawei_public_key' ]; // 华为公钥
} }
$res = $config->setConfig($data, '华为支付配置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'HUAWEI_PAY_CONFIG' ] ]); $res = $config->setConfig($data, '华为支付配置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'HUAWEI_PAY_CONFIG']]);
return $res; return $res;
} }
@@ -58,20 +71,16 @@ class Config extends BaseModel
public function getPayConfig($site_id = 0, $app_module = 'shop', $need_encrypt = false) public function getPayConfig($site_id = 0, $app_module = 'shop', $need_encrypt = false)
{ {
$config = new ConfigModel(); $config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'HUAWEI_PAY_CONFIG' ] ]); $res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'HUAWEI_PAY_CONFIG']]);
if ($need_encrypt) { if ($need_encrypt) {
// 加密敏感信息 // 加密敏感信息
if (!empty($res[ 'data' ][ 'value' ][ 'app_id' ])) { $encrypt_fields = $this->encrypt_fields;
$res[ 'data' ][ 'value' ][ 'app_id' ] = $this->encrypt; // 应用ID
} // 遍历需要加密的字段
if (!empty($res[ 'data' ][ 'value' ][ 'private_key' ])) { foreach ($encrypt_fields as $field) {
$res[ 'data' ][ 'value' ][ 'private_key' ] = $this->encrypt; // 应用私钥 if (!empty($res['data']['value'][$field])) {
} $res['data']['value'][$field] = $this->encrypt; // 加密敏感信息
if (!empty($res[ 'data' ][ 'value' ][ 'public_key' ])) { }
$res[ 'data' ][ 'value' ][ 'public_key' ] = $this->encrypt; // 应用公钥
}
if (!empty($res[ 'data' ][ 'value' ][ 'huawei_public_key' ])) {
$res[ 'data' ][ 'value' ][ 'huawei_public_key' ] = $this->encrypt; // 华为公钥
} }
} }
return $res; return $res;

View File

@@ -25,7 +25,8 @@ class Pay extends BaseShop
$mch_auth_id = input("mch_auth_id", "");//商户证书id, // PETALPAY.MERC_AUTH_ID, 商户证书id $mch_auth_id = input("mch_auth_id", "");//商户证书id, // PETALPAY.MERC_AUTH_ID, 商户证书id
$sign_type = input("sign_type", "RSA");//商户公私钥签名类型, // PETALPAY.SIGN_TYPE, 签名类型, 默认使用RSA $sign_type = input("sign_type", "RSA");//商户公私钥签名类型, // PETALPAY.SIGN_TYPE, 签名类型, 默认使用RSA
$huawei_public_key = input("huawei_public_key", ""); //华为公钥, // PETALPAY.HW_PAY_PUBLIC_KEY_FOR_CALLBACK, 华为公钥 $huawei_public_key = input("huawei_public_key", ""); //华为公钥, // PETALPAY.HW_PAY_PUBLIC_KEY_FOR_CALLBACK, 华为公钥
$app_type = input("app_type", "");//支持端口 如web app $huawei_public_key_for_sessionkey = input("huawei_public_key_for_sessionkey", ""); //华为公钥, // PETALPAY.HW_PAY_PUBLIC_KEY_FOR_SESSIONKEY, 华为公钥
$enable_app_types = input("enable_app_types", '');//支持端口 如web app,app // PETALPAY.ENABLE_APP_TYPES, 支持的支付端口
$pay_status = input("pay_status", 0);//支付启用状态 $pay_status = input("pay_status", 0);//支付启用状态
$refund_status = input("refund_status", 0);//退款启用状态 $refund_status = input("refund_status", 0);//退款启用状态
$transfer_status = input("transfer_status", 0);//转账启用状态 $transfer_status = input("transfer_status", 0);//转账启用状态
@@ -37,10 +38,11 @@ class Pay extends BaseShop
"mch_auth_id" => $mch_auth_id, "mch_auth_id" => $mch_auth_id,
"sign_type" => $sign_type, "sign_type" => $sign_type,
"huawei_public_key" => $huawei_public_key, "huawei_public_key" => $huawei_public_key,
"huawei_public_key_for_sessionkey" => $huawei_public_key_for_sessionkey,
"refund_status" => $refund_status, "refund_status" => $refund_status,
"pay_status" => $pay_status, "pay_status" => $pay_status,
"transfer_status" => $transfer_status, "transfer_status" => $transfer_status,
"app_type" => $app_type "enable_app_types" => $enable_app_types
); );
$result = $config_model->setPayConfig($data, $this->site_id, $this->app_module); $result = $config_model->setPayConfig($data, $this->site_id, $this->app_module);
return $result; return $result;
@@ -48,14 +50,14 @@ class Pay extends BaseShop
$info = $config_model->getPayConfig($this->site_id, $this->app_module, true)[ 'data' ][ 'value' ] ?? []; $info = $config_model->getPayConfig($this->site_id, $this->app_module, true)[ 'data' ][ 'value' ] ?? [];
if (!empty($info)) { if (!empty($info)) {
$app_type_arr = []; $enable_app_type_arr = [];
if (!empty($info[ 'app_type' ])) { if (!empty($info[ 'enable_app_types' ])) {
$app_type_arr = explode(',', $info[ 'app_type' ]); $enable_app_type_arr = explode(',', $info[ 'enable_app_types' ]);
} }
$info[ 'app_type_arr' ] = $app_type_arr; $info[ 'enable_app_type_arr' ] = $enable_app_type_arr; // 当前支持的支付端口
} }
$this->assign("info", $info); $this->assign("info", $info);
$this->assign("app_type", Config::get("app_type")); $this->assign("support_app_types", Config::get("app_type")); // 获取所有支持的支付端口
return $this->fetch("pay/config"); return $this->fetch("pay/config");
} }
@@ -66,17 +68,17 @@ class Pay extends BaseShop
*/ */
public function uploadHuaweiCrt() public function uploadHuaweiCrt()
{ {
$upload_model = new Upload();
$site_id = request()->siteid(); $site_id = request()->siteid();
$upload_model = new Upload($site_id);
$name = input("name", ""); $name = input("name", "");
$extend_type = [ 'crt', 'pem' ]; $extend_type = [ 'pem' ];
$param = array ( $param = array (
"name" => "file", "name" => "file",
"extend_type" => $extend_type "extend_type" => $extend_type
); );
$site_id = max($site_id, 0); $result = $upload_model->setPath("common/huaweipay/cert/")->file($param);
$result = $upload_model->setPath("common/huaweipay/crt/" . $site_id . "/")->file($param);
return $result; return $result;
} }
} }

View File

@@ -5,7 +5,7 @@
<div class="layui-form form-wrap"> <div class="layui-form form-wrap">
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>商户号:</label> <label class="layui-form-label" name="mch_id"><span class="required">*</span>商户号:</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input name="mch_id" type="text" value="{$info.mch_id ?? ''}" class="layui-input len-long" lay-verify="required"> <input name="mch_id" type="text" value="{$info.mch_id ?? ''}" class="layui-input len-long" lay-verify="required">
</div> </div>
@@ -13,7 +13,7 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>华为应用ID</label> <label class="layui-form-label" name="app_id"><span class="required">*</span>华为应用ID</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input name="app_id" type="text" value="{$info.app_id ?? ''}" class="layui-input len-long" lay-verify="required"> <input name="app_id" type="text" value="{$info.app_id ?? ''}" class="layui-input len-long" lay-verify="required">
</div> </div>
@@ -21,10 +21,10 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>商户应用私钥:</label> <label class="layui-form-label" name="private_key_upload"><span class="required">*</span>商户应用私钥:</label>
<div class="layui-input-block"> <div class="layui-input-block">
{notempty name="$info.private_key"} {notempty name="$info.private_key"}
<p class="file-upload">已上传</p> <p class="file-upload">已上传</p>
{else/} {else/}
<p class="file-upload">未上传</p> <p class="file-upload">未上传</p>
{/notempty} {/notempty}
@@ -38,7 +38,7 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>商户证书ID</label> <label class="layui-form-label" name="mch_auth_id"><span class="required">*</span>商户证书ID</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input name="mch_auth_id" type="text" value="{$info.mch_auth_id ?? ''}" class="layui-input len-long" lay-verify="required"> <input name="mch_auth_id" type="text" value="{$info.mch_auth_id ?? ''}" class="layui-input len-long" lay-verify="required">
</div> </div>
@@ -46,10 +46,10 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>华为支付证书:</label> <label class="layui-form-label" name="huawei_public_key_upload"><span class="required">*</span>华为支付证书:</label>
<div class="layui-input-block"> <div class="layui-input-block">
{notempty name="$info.huawei_public_key"} {notempty name="$info.huawei_public_key"}
<p class="file-upload">已上传</p> <p class="file-upload">已上传</p>
{else/} {else/}
<p class="file-upload">未上传</p> <p class="file-upload">未上传</p>
{/notempty} {/notempty}
@@ -63,10 +63,10 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">(可选)华为支付服务加密公钥:</label> <label class="layui-form-label" name="huawei_public_key_for_sessionkey_upload">(可选)华为支付服务加密公钥:</label>
<div class="layui-input-block"> <div class="layui-input-block">
{notempty name="$info.huawei_public_key_for_sessionkey"} {notempty name="$info.huawei_public_key_for_sessionkey"}
<p class="file-upload">已上传</p> <p class="file-upload">已上传</p>
{else/} {else/}
<p class="file-upload">未上传</p> <p class="file-upload">未上传</p>
{/notempty} {/notempty}
@@ -80,32 +80,32 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>支持端</label> <label class="layui-form-label" name="app_types"><span class="required">*</span>支持客户端:</label>
<div class="input-text"> <div class="layui-input-block">
{foreach $app_type as $app_type_k => $app_type_v} <!-- 支持客户端微信小程序、微信公众号、H5、PC端多选 -->
{if condition="$app_type_v['name'] !='微信小程序' && $app_type_v['name'] !='微信公众号'"} {foreach support_app_types as $app_type_k => $app_type_v}
<span>{$app_type_v['name']}</span> <input type="checkbox" name="enable_app_types[]" value="{$app_type_k}" lay-skin="switch" {if condition="$info && in_array($app_type_k, $info.enable_app_type_arr)"} checked {/if} />
{/if} <label>{$app_type_v['name']}</label>
{/foreach} {/foreach}
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>是否启用支付:</label> <label class="layui-form-label" name="pay_status"><span class="required">*</span>是否启用支付:</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="checkbox" name="pay_status" value="1" lay-skin="switch" {if condition="$info && $info.pay_status == 1"} checked {/if} /> <input type="checkbox" name="pay_status" value="1" lay-skin="switch" {if condition="$info && $info.pay_status == 1"} checked {/if} />
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>是否启用退款:</label> <label class="layui-form-label" name="refund_status"><span class="required">*</span>是否启用退款:</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="checkbox" name="refund_status" value="1" lay-skin="switch" {if condition="$info && $info.refund_status == 1"} checked {/if} /> <input type="checkbox" name="refund_status" value="1" lay-skin="switch" {if condition="$info && $info.refund_status == 1"} checked {/if} />
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="required">*</span>是否启用转账:</label> <label class="layui-form-label" name="transfer_status"><span class="required">*</span>是否启用转账:</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="checkbox" name="transfer_status" value="1" lay-skin="switch" {if condition="$info && $info.transfer_status == 1"} checked {/if} /> <input type="checkbox" name="transfer_status" value="1" lay-skin="switch" {if condition="$info && $info.transfer_status == 1"} checked {/if} />
</div> </div>
@@ -125,39 +125,39 @@
// 上传商户应用私钥.pem 文件 // 上传商户应用私钥.pem 文件
new Upload({ new Upload({
el: '#private_key', elem: '#private_key_upload',
url: ns.url("huaweipay://shop/pay/uploadHuaweiCrt"), url: ns.url("huaweipay://shop/pay/uploadHuaweiCrt"),
accept: 'file', accept: 'file',
callback: function(res){ callback: function(res){
if (res.code >= 0) { if (res.code >= 0) {
$('input[name="private_key"]').val(res.data.path); $('input[name="private_key"]').val(res.data.path);
$('input[name="private_key"]').siblings(".file-upload").text("已上传"); $('input[name="private_key"]').siblings(".file-upload").text("已上传");
} }
} }
}); });
// 上传华为支付服务加密公钥.pem文件 // 上传华为支付服务加密公钥.pem文件
new Upload({ new Upload({
el: '#huawei_public_key_for_sessionkey_upload', elem: '#huawei_public_key_for_sessionkey_upload',
url: ns.url("huaweipay://shop/pay/uploadHuaweiCrt"), url: ns.url("huaweipay://shop/pay/uploadHuaweiCrt"),
accept: 'file', accept: 'file',
callback: function(res){ callback: function(res){
if (res.code >= 0) { if (res.code >= 0) {
$('input[name="huawei_public_key_for_sessionkey"]').val(res.data.path); $('input[name="huawei_public_key_for_sessionkey"]').val(res.data.path);
$('input[name="huawei_public_key_for_sessionkey"]').siblings(".file-upload").text("已上传"); $('input[name="huawei_public_key_for_sessionkey"]').siblings(".file-upload").text("已上传");
} }
} }
}); });
// 上传华为支付证书.pem文件 // 上传华为支付证书.pem文件
new Upload({ new Upload({
el: '#huawei_public_key_upload', elem: '#huawei_public_key_upload',
url: ns.url("huaweipay://shop/pay/uploadHuaweiCrt"), url: ns.url("huaweipay://shop/pay/uploadHuaweiCrt"),
accept: 'file', accept: 'file',
callback: function(res){ callback: function(res){
if (res.code >= 0) { if (res.code >= 0) {
$('input[name="huawei_public_key"]').val(res.data.path); $('input[name="huawei_public_key"]').val(res.data.path);
$('input[name="huawei_public_key"]').siblings(".file-upload").text("已上传"); $('input[name="huawei_public_key"]').siblings(".file-upload").text("已上传");
} }
} }
}); });
@@ -185,6 +185,23 @@
form.on('submit(save)', function(data) { form.on('submit(save)', function(data) {
if (repeat_flag) return false; if (repeat_flag) return false;
repeat_flag = true; repeat_flag = true;
// 处理 enable_app_types 字段
{
const values = [];
let i = 0;
while (data.field.hasOwnProperty(`enable_app_types[${i}]`)) {
const val = data.field[`enable_app_types[${i}]`];
if (val != null && val !== '') {
values.push(val);
}
delete data.field[`enable_app_types[${i}]`]; // 可选:清理旧字段
i++;
}
data.field.enable_app_types = values.join(',');
}
$.ajax({ $.ajax({
url: ns.url("huaweipay://shop/pay/config"), url: ns.url("huaweipay://shop/pay/config"),
data: data.field, data: data.field,