111
This commit is contained in:
parent
0109490d1c
commit
61c40f2eef
|
|
@ -23,29 +23,20 @@ class Config extends Base
|
|||
public function weixinpay(Request $request)
|
||||
{
|
||||
$config = getConfig('weixinpay_setting');
|
||||
if (empty($config)) {
|
||||
// 兼容旧数据,如果新配置为空,则尝试获取旧配置并转换格式
|
||||
$old_config = getConfig('weixinpay');
|
||||
if (!empty($old_config)) {
|
||||
$config = [
|
||||
'merchants' => [
|
||||
[
|
||||
'name' => '默认商户',
|
||||
'mch_id' => $old_config['mch_id'] ?? '',
|
||||
'keys' => $old_config['keys'] ?? '',
|
||||
'order_prefix' => $old_config['order_prefix'] ?? 'MYH',
|
||||
'weight' => 1
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
View::assign("key", "weixinpay_setting");
|
||||
View::assign("data", $config);
|
||||
return View::fetch('Config/weixinpay');
|
||||
}
|
||||
|
||||
//支付宝支付
|
||||
public function alipay(Request $request)
|
||||
{
|
||||
$config = getConfig('alipay_setting');
|
||||
View::assign("key", "alipay_setting");
|
||||
View::assign("data", $config);
|
||||
return View::fetch('Config/alipay');
|
||||
}
|
||||
|
||||
//签到设置
|
||||
public function sign(Request $request)
|
||||
{
|
||||
|
|
@ -79,10 +70,6 @@ class Config extends Base
|
|||
{
|
||||
// 获取小程序配置
|
||||
$config = getConfig('miniprogram_setting');
|
||||
|
||||
// 获取旧的微信小程序配置,用于兼容
|
||||
$wechat_setting = getConfig('wechat_setting');
|
||||
|
||||
// 获取所有微信支付商户信息
|
||||
$merchants = [];
|
||||
$weixinpay_setting = getConfig('weixinpay_setting');
|
||||
|
|
@ -95,13 +82,49 @@ class Config extends Base
|
|||
];
|
||||
}
|
||||
}
|
||||
|
||||
View::assign("data", $config);
|
||||
View::assign("wechat_setting", $wechat_setting);
|
||||
View::assign("merchants", $merchants);
|
||||
return View::fetch('Config/miniprogram');
|
||||
}
|
||||
|
||||
//H5页面
|
||||
public function h5(Request $request)
|
||||
{
|
||||
// 获取H5页面配置
|
||||
$config = getConfig('h5_setting');
|
||||
|
||||
// 获取所有微信支付商户信息
|
||||
$wxmerchants = [];
|
||||
$weixinpay_setting = getConfig('weixinpay_setting');
|
||||
if (!empty($weixinpay_setting) && !empty($weixinpay_setting['merchants'])) {
|
||||
foreach ($weixinpay_setting['merchants'] as $index => $merchant) {
|
||||
$wxmerchants[$index] = [
|
||||
'id' => $index,
|
||||
'name' => $merchant['name'],
|
||||
'mch_id' => $merchant['mch_id']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 获取所有支付宝商户信息
|
||||
$alimerchants = [];
|
||||
$alipay_setting = getConfig('alipay_setting');
|
||||
if (!empty($alipay_setting) && !empty($alipay_setting['merchants'])) {
|
||||
foreach ($alipay_setting['merchants'] as $index => $merchant) {
|
||||
$alimerchants[$index] = [
|
||||
'id' => $index,
|
||||
'name' => $merchant['name'],
|
||||
'appId' => $merchant['appId']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
View::assign("data", $config);
|
||||
View::assign("wxmerchants", $wxmerchants);
|
||||
View::assign("alimerchants", $alimerchants);
|
||||
return View::fetch('Config/h5');
|
||||
}
|
||||
|
||||
//系统设置
|
||||
public function systemconfig(Request $request)
|
||||
{
|
||||
|
|
@ -184,6 +207,39 @@ class Config extends Base
|
|||
($redis->getRedis())->del('config:miniprogram_setting');
|
||||
}
|
||||
|
||||
// 处理H5页面配置
|
||||
if ($data['key'] == 'h5_setting' && isset($data['h5apps']) && is_array($data['h5apps'])) {
|
||||
// 检查是否有默认H5
|
||||
$hasDefault = false;
|
||||
$prefixes = [];
|
||||
foreach ($data['h5apps'] as $index => $h5app) {
|
||||
if (isset($h5app['is_default']) && $h5app['is_default'] == 1) {
|
||||
$hasDefault = true;
|
||||
}
|
||||
|
||||
// 验证订单前缀
|
||||
if (!empty($h5app['order_prefix'])) {
|
||||
if (strlen($h5app['order_prefix']) != 2) {
|
||||
return $this->renderError('H5应用"' . $h5app['name'] . '"的订单前缀必须是2位字符');
|
||||
}
|
||||
|
||||
if (in_array($h5app['order_prefix'], $prefixes)) {
|
||||
return $this->renderError('订单前缀"' . $h5app['order_prefix'] . '"重复,每个H5应用的前缀必须唯一');
|
||||
}
|
||||
|
||||
$prefixes[] = $h5app['order_prefix'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasDefault) {
|
||||
return $this->renderError('请至少设置一个默认H5应用');
|
||||
}
|
||||
|
||||
// 清除旧的H5配置缓存
|
||||
$redis = new RedisHelper();
|
||||
($redis->getRedis())->del('config:h5_setting');
|
||||
}
|
||||
|
||||
// 处理同步地址数据格式
|
||||
if ($data['key'] == 'systemconfig') {
|
||||
$syncAddresses = [];
|
||||
|
|
@ -234,6 +290,12 @@ class Config extends Base
|
|||
($redis->getRedis())->del('config:tencent_sms_config');
|
||||
}
|
||||
|
||||
if ($data['key'] == 'alipay_setting') {
|
||||
//清除redis缓存:alipay_setting
|
||||
$redis = new RedisHelper();
|
||||
($redis->getRedis())->del('config:alipay_setting');
|
||||
}
|
||||
|
||||
$result = setConfig($data['key'], $data);
|
||||
if ($result) {
|
||||
return $this->renderSuccess('修改成功');
|
||||
|
|
|
|||
|
|
@ -272,14 +272,16 @@ Route::rule('admin_operationlog', 'Admins/admin_operationlog', 'GET|POST');
|
|||
Route::rule('admin_goods_log', 'Admins/admin_goods_log', 'GET|POST');
|
||||
|
||||
#============================
|
||||
#Config.网站配置
|
||||
#Config.php配置
|
||||
#============================
|
||||
Route::get('base', 'Config/base');
|
||||
Route::get('sign', 'Config/sign');//签到设置
|
||||
Route::get('weixinpay', 'Config/weixinpay');
|
||||
Route::get('alipay', 'Config/alipay');
|
||||
Route::get('sign', 'Config/sign');
|
||||
Route::get('uploadsFile', 'Config/uploads'); //上传设置
|
||||
Route::get('systemconfig', 'Config/systemconfig'); //系统设置
|
||||
Route::get('miniprogram', 'Config/miniprogram'); //微信小程序配置
|
||||
Route::get('miniprogram', 'Config/miniprogram'); //微信小程序
|
||||
Route::get('h5', 'Config/h5'); //H5页面配置
|
||||
Route::post('update', 'Config/update');
|
||||
Route::get('wechatofficialaccount', 'Config/wechatofficialaccount');
|
||||
|
||||
|
|
|
|||
231
app/admin/view/Config/alipay.html
Normal file
231
app/admin/view/Config/alipay.html
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
{include file="Public:header2"/}
|
||||
<body style="min-height: 100%;background-color: #fff">
|
||||
<style type="text/css">
|
||||
.ggg{
|
||||
width:600px !important
|
||||
}
|
||||
</style>
|
||||
<div class="layui-fluid">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-md12">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-body">
|
||||
<form onsubmit="return false;">
|
||||
<div class="layui-form" wid100 lay-filter="">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-alert layui-bg-gray">
|
||||
<i class="layui-icon layui-icon-tips"></i> 支付宝商户号配置。权重越高,支付几率越多。
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="key" value="alipay_setting" lay-verify="required" class="layui-input">
|
||||
|
||||
<div id="merchants-container">
|
||||
{if isset($data.merchants) && is_array($data.merchants)}
|
||||
{foreach $data.merchants as $index => $merchant}
|
||||
<div class="merchant-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商户名称</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="merchants[{$index}][name]" value="{$merchant.name|default=''}" lay-verify="required" class="layui-input" placeholder="请输入商户名称">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付宝AppId</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="merchants[{$index}][appId]" value="{$merchant.appId|default=''}" lay-verify="required" class="layui-input" placeholder="请输入支付宝AppId">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">应用私钥</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[{$index}][merchantPrivateKey]" lay-verify="required" class="layui-textarea" placeholder="请输入应用私钥" rows="4">{$merchant.merchantPrivateKey|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付宝公钥</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[{$index}][alipayPublicKey]" lay-verify="required" class="layui-textarea" placeholder="请输入支付宝公钥" rows="4">{$merchant.alipayPublicKey|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">权重</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="number" name="merchants[{$index}][weight]" value="{$merchant.weight|default='1'}" min="1" lay-verify="required" class="layui-input" placeholder="请输入权重,数值越大被选中的概率越高">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否启用</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="checkbox" name="merchants[{$index}][is_enabled]" value="1" lay-skin="switch" lay-text="启用|禁用" {if isset($merchant.is_enabled) && $merchant.is_enabled == 1}checked{/if}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[{$index}][remark]" class="layui-textarea" placeholder="请输入备注信息">{$merchant.remark|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-merchant" style="position: absolute; top: 10px; right: 10px;">删除商户</button>
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<!-- 默认商户项 -->
|
||||
<div class="merchant-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商户名称</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="merchants[0][name]" value="{$data.name|default='默认商户'}" lay-verify="required" class="layui-input" placeholder="请输入商户名称">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付宝AppId</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="merchants[0][appId]" value="{$data.appId|default=''}" lay-verify="required" class="layui-input" placeholder="请输入支付宝AppId">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">应用私钥</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[0][merchantPrivateKey]" lay-verify="required" class="layui-textarea" placeholder="请输入应用私钥" rows="4">{$data.merchantPrivateKey|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付宝公钥</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[0][alipayPublicKey]" lay-verify="required" class="layui-textarea" placeholder="请输入支付宝公钥" rows="4">{$data.alipayPublicKey|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">权重</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="number" name="merchants[0][weight]" value="1" min="1" lay-verify="required" class="layui-input" placeholder="请输入权重,数值越大被选中的概率越高">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否启用</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="checkbox" name="merchants[0][is_enabled]" value="1" lay-skin="switch" lay-text="启用|禁用" checked>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[0][remark]" class="layui-textarea" placeholder="请输入备注信息">{$data.remark|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-merchant" style="position: absolute; top: 10px; right: 10px;">删除商户</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn layui-btn-normal" id="add-merchant">添加商户</button>
|
||||
<button class="layui-btn" onclick="return check()">确认保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{include file="Public:footer"/}
|
||||
</body>
|
||||
</html>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','form','upload','element'], function(){
|
||||
var $ = layui.$;
|
||||
var form = layui.form;
|
||||
|
||||
// 添加商户按钮点击事件
|
||||
$('#add-merchant').on('click', function() {
|
||||
var index = $('.merchant-item').length;
|
||||
var newItemHtml = `
|
||||
<div class="merchant-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">商户名称</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="merchants[\${index}][name]" value="" lay-verify="required" class="layui-input" placeholder="请输入商户名称">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付宝AppId</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="merchants[\${index}][appId]" value="" lay-verify="required" class="layui-input" placeholder="请输入支付宝AppId">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">应用私钥</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[\${index}][merchantPrivateKey]" lay-verify="required" class="layui-textarea" placeholder="请输入应用私钥" rows="4"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付宝公钥</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[\${index}][alipayPublicKey]" lay-verify="required" class="layui-textarea" placeholder="请输入支付宝公钥" rows="4"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">权重</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="number" name="merchants[\${index}][weight]" value="1" min="1" lay-verify="required" class="layui-input" placeholder="请输入权重,数值越大被选中的概率越高">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否启用</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="checkbox" name="merchants[\${index}][is_enabled]" value="1" lay-skin="switch" lay-text="启用|禁用" checked>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[\${index}][remark]" class="layui-textarea" placeholder="请输入备注信息"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-merchant" style="position: absolute; top: 10px; right: 10px;">删除商户</button>
|
||||
</div>
|
||||
`;
|
||||
$('#merchants-container').append(newItemHtml);
|
||||
form.render();
|
||||
});
|
||||
|
||||
// 删除商户按钮点击事件(使用事件委托)
|
||||
$(document).on('click', '.remove-merchant', function() {
|
||||
if ($('.merchant-item').length <= 1) {
|
||||
layer.msg('至少保留一个商户信息', {icon: 2});
|
||||
} else {
|
||||
$(this).closest('.merchant-item').remove();
|
||||
// 重新排序索引
|
||||
$('.merchant-item').each(function(idx) {
|
||||
$(this).find('input, textarea').each(function() {
|
||||
var name = $(this).attr('name');
|
||||
if (name) {
|
||||
$(this).attr('name', name.replace(/merchants\[\d+\]/, 'merchants[' + idx + ']'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function check(){
|
||||
var $ = layui.$;
|
||||
var load=layer.load(2);
|
||||
var url="{:url('/admin/update')}";
|
||||
$.post(url,$("form").serialize(),function(data){
|
||||
if(data.status==1){
|
||||
layer.msg(data.msg,{icon:1,time:1000},function(){
|
||||
location.reload();
|
||||
});
|
||||
}else{
|
||||
layer.msg(data.msg,{icon:2,anim:6,time:1500},function(){
|
||||
layer.close(load);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
468
app/admin/view/Config/h5.html
Normal file
468
app/admin/view/Config/h5.html
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
{include file="Public:header2"/}
|
||||
<body style="min-height: 100%;background-color: #fff">
|
||||
<style type="text/css">
|
||||
.ggg{
|
||||
width:600px !important
|
||||
}
|
||||
.merchant-selector {
|
||||
width: 100%;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
border: 1px solid #e6e6e6;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.merchant-item-mini {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.payment-tabs {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.payment-tab {
|
||||
padding: 10px 15px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
border: 1px solid #e6e6e6;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.payment-tab.active {
|
||||
background-color: #1E9FFF;
|
||||
color: #fff;
|
||||
border-color: #1E9FFF;
|
||||
}
|
||||
</style>
|
||||
<div class="layui-fluid">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-md12">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">H5页面配置</div>
|
||||
<div class="layui-card-body">
|
||||
<form onsubmit="return false;">
|
||||
<div class="layui-form" wid100 lay-filter="">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-alert layui-bg-gray">
|
||||
<i class="layui-icon layui-icon-tips"></i> 配置多个H5应用,系统将根据域名自动匹配使用哪个H5应用。若请求域名未匹配到对应H5应用,则使用默认H5应用配置。
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="key" value="h5_setting" lay-verify="required" class="layui-input">
|
||||
|
||||
<div id="h5app-container">
|
||||
|
||||
{if isset($data.h5apps) && is_array($data.h5apps)}
|
||||
{foreach $data.h5apps as $index => $h5app}
|
||||
<div class="h5app-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">H5名称</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[{$index}][name]" value="{$h5app.name|default=''}" lay-verify="required" class="layui-input" placeholder="请输入H5应用名称">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否默认</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="checkbox" name="h5apps[{$index}][is_default]" value="1" title="设为默认" lay-filter="is_default" {if isset($h5app.is_default) && $h5app.is_default==1}checked{/if}>
|
||||
<div class="layui-form-mid layui-word-aux">设为默认后将用于未匹配域名的请求</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Appid</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[{$index}][appid]" value="{$h5app.appid|default=''}" lay-verify="required" class="layui-input" placeholder="请输入H5应用AppID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">AppSecret</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[{$index}][app_secret]" value="{$h5app.app_secret|default=''}" lay-verify="required" class="layui-input" placeholder="请输入H5应用AppSecret">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">域名</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[{$index}][domain]" value="{$h5app.domain|default=''}" class="layui-input" placeholder="请输入域名,多个域名用英文逗号分隔">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">多个域名使用英文逗号分隔,如:example.com,www.example.com</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">订单前缀</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="h5apps[{$index}][order_prefix]" value="{$h5app.order_prefix|default=''}" maxlength="2" class="layui-input" placeholder="请输入订单前缀">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">长度为2位字符,用于标识订单来源H5应用</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付方式</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="payment-tabs">
|
||||
<div class="payment-tab active" data-payment="alipay">支付宝支付</div>
|
||||
<div class="payment-tab" data-payment="wechat">微信支付</div>
|
||||
</div>
|
||||
|
||||
<!-- 支付宝商户 -->
|
||||
<div class="payment-content" id="alipay-payment-{$index}">
|
||||
<div class="merchant-selector">
|
||||
{if isset($alimerchants) && is_array($alimerchants) && count($alimerchants) > 0}
|
||||
{foreach $alimerchants as $merchant_id => $merchant}
|
||||
<div class="merchant-item-mini">
|
||||
<input type="checkbox" name="h5apps[{$index}][ali_merchants][]" value="{$merchant.appId}" title="{$merchant.name}" lay-skin="primary" {if isset($h5app.ali_merchants) && in_array($merchant.appId, $h5app.ali_merchants)}checked{/if}>
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<div class="layui-form-mid">暂无可用支付宝商户,请先在<a href="{:url('/admin/alipay')}" class="layui-btn layui-btn-xs">支付宝支付设置</a>中添加商户</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 微信支付商户 -->
|
||||
<div class="payment-content" id="wechat-payment-{$index}" style="display: none;">
|
||||
<div class="merchant-selector">
|
||||
{if isset($wxmerchants) && is_array($wxmerchants) && count($wxmerchants) > 0}
|
||||
{foreach $wxmerchants as $merchant_id => $merchant}
|
||||
<div class="merchant-item-mini">
|
||||
<input type="checkbox" name="h5apps[{$index}][wx_merchants][]" value="{$merchant.mch_id}" title="{$merchant.name}" lay-skin="primary" {if isset($h5app.wx_merchants) && in_array($merchant.mch_id, $h5app.wx_merchants)}checked{/if}>
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<div class="layui-form-mid">暂无可用微信商户,请先在<a href="{:url('/admin/weixinpay')}" class="layui-btn layui-btn-xs">微信支付设置</a>中添加商户</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-h5app" style="position: absolute; top: 10px; right: 10px;">删除H5应用</button>
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<!-- 默认H5应用项 -->
|
||||
<div class="h5app-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">H5名称</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[0][name]" value="默认H5应用" lay-verify="required" class="layui-input" placeholder="请输入H5应用名称">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否默认</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="checkbox" name="h5apps[0][is_default]" value="1" title="设为默认" lay-filter="is_default" checked>
|
||||
<div class="layui-form-mid layui-word-aux">设为默认后将用于未匹配域名的请求</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Appid</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[0][appid]" value="" lay-verify="required" class="layui-input" placeholder="请输入H5应用AppID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">AppSecret</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[0][app_secret]" value="" lay-verify="required" class="layui-input" placeholder="请输入H5应用AppSecret">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">域名</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[0][domain]" value="" class="layui-input" placeholder="请输入域名,多个域名用英文逗号分隔">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">多个域名使用英文逗号分隔,如:example.com,www.example.com</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">订单前缀</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="h5apps[0][order_prefix]" value="H5" maxlength="2" class="layui-input" placeholder="请输入订单前缀">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">长度为2位字符,用于标识订单来源H5应用</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付方式</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="payment-tabs">
|
||||
<div class="payment-tab active" data-payment="alipay">支付宝支付</div>
|
||||
<div class="payment-tab" data-payment="wechat">微信支付</div>
|
||||
</div>
|
||||
|
||||
<!-- 支付宝商户 -->
|
||||
<div class="payment-content" id="alipay-payment-0">
|
||||
<div class="merchant-selector">
|
||||
{if isset($alimerchants) && is_array($alimerchants) && count($alimerchants) > 0}
|
||||
{foreach $alimerchants as $merchant_id => $merchant}
|
||||
<div class="merchant-item-mini">
|
||||
<input type="checkbox" name="h5apps[0][ali_merchants][]" value="{$merchant.appId}" title="{$merchant.name}" lay-skin="primary">
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<div class="layui-form-mid">暂无可用支付宝商户,请先在<a href="{:url('/admin/alipay')}" class="layui-btn layui-btn-xs">支付宝支付设置</a>中添加商户</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 微信支付商户 -->
|
||||
<div class="payment-content" id="wechat-payment-0" style="display: none;">
|
||||
<div class="merchant-selector">
|
||||
{if isset($wxmerchants) && is_array($wxmerchants) && count($wxmerchants) > 0}
|
||||
{foreach $wxmerchants as $merchant_id => $merchant}
|
||||
<div class="merchant-item-mini">
|
||||
<input type="checkbox" name="h5apps[0][wx_merchants][]" value="{$merchant.mch_id}" title="{$merchant.name}" lay-skin="primary">
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<div class="layui-form-mid">暂无可用微信商户,请先在<a href="{:url('/admin/weixinpay')}" class="layui-btn layui-btn-xs">微信支付设置</a>中添加商户</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-h5app" style="position: absolute; top: 10px; right: 10px;">删除H5应用</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn layui-btn-normal" id="add-h5app">添加H5应用</button>
|
||||
<button class="layui-btn" onclick="return check()">确认保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{include file="Public:footer"/}
|
||||
</body>
|
||||
</html>
|
||||
<script type="text/javascript">
|
||||
layui.use(['layer','form','upload','element'], function(){
|
||||
var $ = layui.$;
|
||||
var form = layui.form;
|
||||
|
||||
// 监听默认H5应用复选框
|
||||
form.on('checkbox(is_default)', function(data){
|
||||
if(data.elem.checked){
|
||||
// 取消其他默认H5应用
|
||||
$('input[name$="[is_default]"]').not(this).prop('checked', false);
|
||||
form.render('checkbox');
|
||||
}
|
||||
});
|
||||
|
||||
// 支付方式选项卡切换
|
||||
$(document).on('click', '.payment-tab', function() {
|
||||
var $this = $(this);
|
||||
var payment = $this.data('payment');
|
||||
var $parent = $this.closest('.layui-input-block');
|
||||
|
||||
// 切换选项卡样式
|
||||
$this.addClass('active').siblings().removeClass('active');
|
||||
|
||||
// 切换内容显示
|
||||
$parent.find('.payment-content').hide();
|
||||
$parent.find('[id^=' + payment + '-payment-]').show();
|
||||
});
|
||||
|
||||
// 添加H5应用按钮点击事件
|
||||
$('#add-h5app').on('click', function() {
|
||||
var index = $('.h5app-item').length;
|
||||
|
||||
// 构建微信商户选择器HTML
|
||||
var wxMerchantSelectorHtml = '';
|
||||
{if isset($wxmerchants) && is_array($wxmerchants) && count($wxmerchants) > 0}
|
||||
wxMerchantSelectorHtml = `
|
||||
<div class="merchant-selector">
|
||||
{foreach $wxmerchants as $merchant_id => $merchant}
|
||||
<div class="merchant-item-mini">
|
||||
<input type="checkbox" name="h5apps[\${index}][wx_merchants][]" value="{$merchant.mch_id}" title="{$merchant.name}" lay-skin="primary">
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
`;
|
||||
{else}
|
||||
wxMerchantSelectorHtml = `
|
||||
<div class="merchant-selector">
|
||||
<div class="layui-form-mid">暂无可用微信商户,请先在<a href="{:url('/admin/weixinpay')}" class="layui-btn layui-btn-xs">微信支付设置</a>中添加商户</div>
|
||||
</div>
|
||||
`;
|
||||
{/if}
|
||||
|
||||
// 构建支付宝商户选择器HTML
|
||||
var aliMerchantSelectorHtml = '';
|
||||
{if isset($alimerchants) && is_array($alimerchants) && count($alimerchants) > 0}
|
||||
aliMerchantSelectorHtml = `
|
||||
<div class="merchant-selector">
|
||||
{foreach $alimerchants as $merchant_id => $merchant}
|
||||
<div class="merchant-item-mini">
|
||||
<input type="checkbox" name="h5apps[\${index}][ali_merchants][]" value="{$merchant.appId}" title="{$merchant.name}" lay-skin="primary">
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
`;
|
||||
{else}
|
||||
aliMerchantSelectorHtml = `
|
||||
<div class="merchant-selector">
|
||||
<div class="layui-form-mid">暂无可用支付宝商户,请先在<a href="{:url('/admin/alipay')}" class="layui-btn layui-btn-xs">支付宝支付设置</a>中添加商户</div>
|
||||
</div>
|
||||
`;
|
||||
{/if}
|
||||
|
||||
var newItemHtml = `
|
||||
<div class="h5app-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">H5名称</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[\${index}][name]" value="" lay-verify="required" class="layui-input" placeholder="请输入H5应用名称">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否默认</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="checkbox" name="h5apps[\${index}][is_default]" value="1" title="设为默认" lay-filter="is_default">
|
||||
<div class="layui-form-mid layui-word-aux">设为默认后将用于未匹配域名的请求</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Appid</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[\${index}][appid]" value="" lay-verify="required" class="layui-input" placeholder="请输入H5应用AppID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">AppSecret</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[\${index}][app_secret]" value="" lay-verify="required" class="layui-input" placeholder="请输入H5应用AppSecret">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">域名</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="h5apps[\${index}][domain]" value="" class="layui-input" placeholder="请输入域名,多个域名用英文逗号分隔">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">多个域名使用英文逗号分隔,如:example.com,www.example.com</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">订单前缀</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="h5apps[\${index}][order_prefix]" value="" maxlength="2" class="layui-input" placeholder="请输入订单前缀">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">长度为2位字符,用于标识订单来源H5应用</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">支付方式</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="payment-tabs">
|
||||
<div class="payment-tab active" data-payment="alipay">支付宝支付</div>
|
||||
<div class="payment-tab" data-payment="wechat">微信支付</div>
|
||||
</div>
|
||||
|
||||
<!-- 支付宝商户 -->
|
||||
<div class="payment-content" id="alipay-payment-\${index}">
|
||||
\${aliMerchantSelectorHtml}
|
||||
</div>
|
||||
|
||||
<!-- 微信支付商户 -->
|
||||
<div class="payment-content" id="wechat-payment-\${index}" style="display: none;">
|
||||
\${wxMerchantSelectorHtml}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-h5app" style="position: absolute; top: 10px; right: 10px;">删除H5应用</button>
|
||||
</div>
|
||||
`;
|
||||
$('#h5app-container').append(newItemHtml);
|
||||
form.render();
|
||||
});
|
||||
|
||||
// 删除H5应用按钮点击事件(使用事件委托)
|
||||
$(document).on('click', '.remove-h5app', function() {
|
||||
if ($('.h5app-item').length <= 1) {
|
||||
layer.msg('至少保留一个H5应用配置', {icon: 2});
|
||||
} else {
|
||||
$(this).closest('.h5app-item').remove();
|
||||
// 重新排序索引
|
||||
$('.h5app-item').each(function(idx) {
|
||||
$(this).find('input, select').each(function() {
|
||||
var name = $(this).attr('name');
|
||||
if (name) {
|
||||
// 修改索引,同时保持数组结构
|
||||
$(this).attr('name', name.replace(/h5apps\[\d+\]/, 'h5apps[' + idx + ']'));
|
||||
}
|
||||
});
|
||||
|
||||
// 更新支付选项卡的ID
|
||||
$(this).find('[id^=wechat-payment-]').attr('id', 'wechat-payment-' + idx);
|
||||
$(this).find('[id^=alipay-payment-]').attr('id', 'alipay-payment-' + idx);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function check(){
|
||||
var $ = layui.$;
|
||||
|
||||
// 确保至少有一个默认H5应用
|
||||
var hasDefault = false;
|
||||
$('input[name$="[is_default]"]').each(function() {
|
||||
if(this.checked) {
|
||||
hasDefault = true;
|
||||
return false; // 跳出循环
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasDefault) {
|
||||
layer.msg('请至少设置一个默认H5应用', {icon: 2, anim: 6, time: 2000});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查订单前缀长度
|
||||
var hasError = false;
|
||||
$('input[name$="[order_prefix]"]').each(function() {
|
||||
var prefix = $(this).val();
|
||||
if (prefix && prefix.length !== 2) {
|
||||
hasError = true;
|
||||
layer.msg('订单前缀必须是2位字符', {icon: 2, anim: 6, time: 2000});
|
||||
return false; // 跳出循环
|
||||
}
|
||||
});
|
||||
|
||||
if (hasError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
var url="{:url('/admin/update')}";
|
||||
var load=layer.load(2);
|
||||
$.post(url,$("form").serialize(),function(data){
|
||||
if(data.status==1){
|
||||
layer.msg(data.msg,{icon:1,time:1000},function(){
|
||||
location.reload();
|
||||
});
|
||||
}else{
|
||||
layer.msg(data.msg,{icon:2,anim:6,time:1500},function(){
|
||||
layer.close(load);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
<input type="hidden" name="key" value="miniprogram_setting" lay-verify="required" class="layui-input">
|
||||
|
||||
<div id="miniprogram-container">
|
||||
{if isset($data.miniprograms) && is_array($data.miniprograms)}
|
||||
|
||||
{foreach $data.miniprograms as $index => $miniprogram}
|
||||
<div class="miniprogram-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
|
|
@ -100,74 +100,7 @@
|
|||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-miniprogram" style="position: absolute; top: 10px; right: 10px;">删除小程序</button>
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<!-- 默认小程序项 -->
|
||||
<div class="miniprogram-item" style="border: 1px solid #e6e6e6; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小程序名称</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="miniprograms[0][name]" value="默认小程序" lay-verify="required" class="layui-input" placeholder="请输入小程序名称">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否默认</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="checkbox" name="miniprograms[0][is_default]" value="1" title="设为默认" lay-filter="is_default" checked>
|
||||
<div class="layui-form-mid layui-word-aux">设为默认后将用于未匹配域名的请求</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Appid</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="miniprograms[0][appid]" value="{$wechat_setting.appid|default=''}" lay-verify="required" class="layui-input" placeholder="请输入微信小程序AppID">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">AppSecret</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="miniprograms[0][app_secret]" value="{$wechat_setting.appSecret|default=''}" lay-verify="required" class="layui-input" placeholder="请输入微信小程序AppSecret">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">域名</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="text" name="miniprograms[0][domain]" value="" class="layui-input" placeholder="请输入域名,多个域名用英文逗号分隔">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">多个域名使用英文逗号分隔,如:example.com,www.example.com</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">订单前缀</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="miniprograms[0][order_prefix]" value="" maxlength="2" class="layui-input" placeholder="请输入订单前缀">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">长度为2位字符,用于标识订单来源小程序</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">关联商户</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="merchant-selector">
|
||||
{if isset($merchants) && is_array($merchants)}
|
||||
{foreach $merchants as $merchant_id => $merchant}
|
||||
<div class="merchant-item-mini">
|
||||
<input type="checkbox" name="miniprograms[0][merchants][]" value="{$merchant.mch_id}" title="{$merchant.name}" lay-skin="primary">
|
||||
</div>
|
||||
{/foreach}
|
||||
{else}
|
||||
<div class="layui-form-mid">暂无可用商户,请先在<a href="{:url('/admin/weixinpay')}" class="layui-btn layui-btn-xs">微信支付设置</a>中添加商户</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-miniprogram" style="position: absolute; top: 10px; right: 10px;">删除小程序</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
|
|
|
|||
|
|
@ -53,6 +53,18 @@
|
|||
<input type="number" name="merchants[{$index}][weight]" value="{$merchant.weight|default='1'}" min="1" lay-verify="required" class="layui-input" placeholder="请输入权重,数值越大被选中的概率越高">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否启用</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="checkbox" name="merchants[{$index}][is_enabled]" value="1" lay-skin="switch" lay-text="启用|禁用" {if isset($merchant.is_enabled) && $merchant.is_enabled == 1}checked{/if}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[{$index}][remark]" class="layui-textarea" placeholder="请输入备注信息">{$merchant.remark|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-merchant" style="position: absolute; top: 10px; right: 10px;">删除商户</button>
|
||||
</div>
|
||||
{/foreach}
|
||||
|
|
@ -89,6 +101,18 @@
|
|||
<input type="number" name="merchants[0][weight]" value="1" min="1" lay-verify="required" class="layui-input" placeholder="请输入权重,数值越大被选中的概率越高">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否启用</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="checkbox" name="merchants[0][is_enabled]" value="1" lay-skin="switch" lay-text="启用|禁用" checked>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[0][remark]" class="layui-textarea" placeholder="请输入备注信息">{$data.remark|default=''}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-merchant" style="position: absolute; top: 10px; right: 10px;">删除商户</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -199,6 +223,18 @@
|
|||
<input type="number" name="merchants[${index}][weight]" value="1" min="1" lay-verify="required" class="layui-input" placeholder="请输入权重,数值越大被选中的概率越高">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">是否启用</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<input type="checkbox" name="merchants[${index}][is_enabled]" value="1" lay-skin="switch" lay-text="启用|禁用" checked>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">备注</label>
|
||||
<div class="layui-input-inline ggg">
|
||||
<textarea name="merchants[${index}][remark]" class="layui-textarea" placeholder="请输入备注信息"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm remove-merchant" style="position: absolute; top: 10px; right: 10px;">删除商户</button>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@ class Infinite extends Base
|
|||
if (empty($user['mobile'])) {
|
||||
return $this->renderError('请先绑定手机号', [], -9);
|
||||
}
|
||||
|
||||
|
||||
$ad_id = request()->header('adid');
|
||||
$goods_id = request()->param('goods_id/d', 0); #盒子ID
|
||||
$prize_num = request()->param('prize_num/d', 0); #抽几发
|
||||
|
|
@ -516,9 +516,10 @@ class Infinite extends Base
|
|||
$use_money2_is = request()->param('use_money2_is/d', 0); #0不抵扣 1抵扣 货币2抵扣
|
||||
$coupon_id = request()->param('coupon_id'); //优惠券
|
||||
$is_mibao = request()->param('is_mibao/d', 0); //连击赏下 是否是抽的秘宝池 1是 0否
|
||||
$pay_type = request()->param('pay_type/d', 1); //1.小程序微信支付,2.h5支付宝,3.app微信,4.app支付宝
|
||||
|
||||
#盒子信息
|
||||
$goods = Goodsmodel::field('id,title,imgurl_detail,type,price,status,is_shou_zhe,choujiang_xianzhi,quanju_xiangou,daily_xiangou')->where(['id' => $goods_id])
|
||||
$goods = Goodsmodel::field('*')->where(['id' => $goods_id])
|
||||
->find();
|
||||
if (!$goods) {
|
||||
return $this->renderError("盒子不存在");
|
||||
|
|
@ -566,12 +567,6 @@ class Infinite extends Base
|
|||
return $this->renderError('请求错误');
|
||||
}
|
||||
|
||||
// $is_goodslist = GoodsList::field('id')
|
||||
// ->where($where)
|
||||
// ->find();
|
||||
// if (!$is_goodslist) {
|
||||
// return $this->renderError('暂无奖品信息');
|
||||
// }
|
||||
|
||||
if ($goods['type'] == 9) {
|
||||
$prize_num = intval($prize_num);
|
||||
|
|
@ -584,7 +579,7 @@ class Infinite extends Base
|
|||
return $this->renderError("秘宝池抽奖次数不足");
|
||||
}
|
||||
} else {
|
||||
if ($prize_num != 1 && $prize_num != 3 && $prize_num != 5 && $prize_num != 10 && $prize_num != 50) {
|
||||
if ($prize_num != 1 && $prize_num != 3 && $prize_num != 5 && $prize_num != 10) {
|
||||
return $this->renderError("请求参数错误!!!");
|
||||
}
|
||||
}
|
||||
|
|
@ -621,23 +616,36 @@ class Infinite extends Base
|
|||
$num = 1;
|
||||
}
|
||||
|
||||
$res = [];
|
||||
|
||||
if ($goods['quanju_xiangou'] > 0) {
|
||||
// 查看有没有未支付的订单,未支付的订单要先作废
|
||||
Order::where('goods_id', '=', $goods_id)
|
||||
->where('user_id', '=', $user['id'])
|
||||
->where('status', '=', 0)
|
||||
->update(['status' => 2]);
|
||||
}
|
||||
if ($goods['daily_xiangou'] > 0) {
|
||||
// 查看一天内有没有未支付的订单,未支付的订单要先作废
|
||||
$order_info = Order::where('goods_id', '=', $goods_id)
|
||||
Order::where('goods_id', '=', $goods_id)
|
||||
->where('user_id', '=', $user['id'])
|
||||
->where('num', '=', $num)
|
||||
->where('status', '=', 0)
|
||||
->where('addtime', '>=', time() - 86400)
|
||||
->find();
|
||||
if ($order_info) {
|
||||
$order_info->status = 2;
|
||||
$order_info->save();
|
||||
}
|
||||
->update(['status' => 2]);
|
||||
}
|
||||
|
||||
$res = [];
|
||||
$order_num = create_order_no('MH_', 'order', 'order_num');
|
||||
|
||||
$attach = 'order_wxs';
|
||||
if ($goods['type'] == 16) {
|
||||
$attach = 'order_fbs';
|
||||
}
|
||||
$title = '购买盒子' . $goods['title'];
|
||||
$payRes = \app\common\server\platform\PlatformFactory::createPay($user, $paymentResult['price'], $title, $attach, "MH_");
|
||||
if ($payRes['status'] !== 1) {
|
||||
Db::rollback();
|
||||
#删除redis
|
||||
$redis->del($redis_key);
|
||||
return $this->renderError("购买失败,请刷新重试");
|
||||
}
|
||||
$order_num = $payRes['data']['order_no'];
|
||||
#创建订单
|
||||
$res[] = $order_id = Order::insertGetId([
|
||||
'user_id' => $user['id'],
|
||||
|
|
@ -657,7 +665,7 @@ class Infinite extends Base
|
|||
'goods_imgurl' => $goods['imgurl_detail'],
|
||||
'prize_num' => $prize_num,
|
||||
'status' => 0,
|
||||
'pay_type' => 1,#1微信 2支付宝
|
||||
'pay_type' => $pay_type,#1微信 2支付宝
|
||||
'order_type' => $goods['type'],
|
||||
'addtime' => time(),
|
||||
'coupon_id' => $paymentResult['coupon_id'],
|
||||
|
|
@ -667,49 +675,14 @@ class Infinite extends Base
|
|||
'ad_id' => $ad_id,
|
||||
'click_id' => $user['click_id']
|
||||
]);
|
||||
if ($goods['quanju_xiangou'] > 0) {
|
||||
|
||||
// 查看有没有未支付的订单,未支付的订单要先作废
|
||||
Order::where('goods_id', '=', $goods_id)
|
||||
->where('user_id', '=', $user['id'])
|
||||
->where('status', '=', 0)
|
||||
->where('order_num', '!=', $order_num)
|
||||
->update(['status' => 2]);
|
||||
|
||||
}
|
||||
if ($goods['daily_xiangou'] > 0) {
|
||||
|
||||
// 查看一天内有没有未支付的订单,未支付的订单要先作废
|
||||
Order::where('goods_id', '=', $goods_id)
|
||||
->where('user_id', '=', $user['id'])
|
||||
->where('status', '=', 0)
|
||||
->where('addtime', '>=', time() - 86400)
|
||||
->where('order_num', '!=', $order_num)
|
||||
->update(['status' => 2]);
|
||||
|
||||
}
|
||||
|
||||
#微信支付金额大于0
|
||||
if ($paymentResult['price'] > 0) {
|
||||
$body = '购买盒子' . $goods['title'];
|
||||
$attach = 'order_wxs';
|
||||
if ($goods['type'] == 16) {
|
||||
$attach = 'order_fbs';
|
||||
}
|
||||
// $isTest = \app\common\helper\ConfigHelper::getSystemTestKey("disable_wechat_pay");
|
||||
// if ($isTest == "1") {
|
||||
// Db::rollback();
|
||||
// #删除redis
|
||||
// $redis->del($redis_key);
|
||||
// return $this->renderError("支付未开放");
|
||||
// }
|
||||
$payRes = (new Pay())->wxCreateOrder($order_num, $paymentResult['price'], $user['id'], $body, $attach);
|
||||
if ($payRes['status'] == 1) {
|
||||
#结果集
|
||||
$new_data = [
|
||||
'status' => 1,
|
||||
'order_num' => $order_num,
|
||||
'res' => $payRes['data'],
|
||||
'res' => $payRes['data']['res'],
|
||||
];
|
||||
} else {
|
||||
#删除redis
|
||||
|
|
|
|||
|
|
@ -196,10 +196,16 @@ class Login extends Base
|
|||
|
||||
$logMessages[] = '用户开始登录: ' . $code;
|
||||
$click_id = request()->header('clickid');
|
||||
$wxServer = new \app\common\server\Wx($this->app);
|
||||
$user_base = $wxServer->getOpenid($code);
|
||||
$openid = $user_base['openid'];
|
||||
|
||||
$wxPlatform = \app\common\server\platform\PlatformFactory::create();
|
||||
$openInfo = $wxPlatform->getOpenid($code);
|
||||
if ($openInfo['status'] == 0) {
|
||||
return $this->renderError($openInfo['msg']);
|
||||
}
|
||||
$openid = $openInfo['data']['openid'];
|
||||
$wx_unionid = null;
|
||||
if (isset($openInfo['data']['unionid'])) {
|
||||
$wx_unionid = $openInfo['data']['unionid'];
|
||||
}
|
||||
// 添加Redis防抖锁
|
||||
$redis = (new RedisHelper())->getRedis();
|
||||
$lockKey = 'login:debounce:' . $openid;
|
||||
|
|
@ -208,11 +214,9 @@ class Login extends Base
|
|||
Log::warning(end($logMessages));
|
||||
return $this->renderError('请勿频繁登录,请稍后再试');
|
||||
}
|
||||
|
||||
|
||||
$user = null;
|
||||
$wx_unionid = null;
|
||||
if ($user_base['unionid'] != null && $user_base['unionid'] != '') {
|
||||
$wx_unionid = $user_base['unionid'];
|
||||
if ($wx_unionid != null && $wx_unionid != '') {
|
||||
$user = User::getInfo(['unionid' => $wx_unionid]);
|
||||
}
|
||||
if ($user == null) {
|
||||
|
|
@ -257,7 +261,7 @@ class Login extends Base
|
|||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 检查UserAccount是否存在
|
||||
$userAccount = UserAccount::where(['user_id' => $user['id']])->find();
|
||||
if ($userAccount) {
|
||||
|
|
@ -462,7 +466,7 @@ class Login extends Base
|
|||
$retrieved_openid = $user_base['openid'];
|
||||
|
||||
$openid = $retrieved_openid;
|
||||
|
||||
|
||||
// 添加Redis防抖锁
|
||||
$redis = (new RedisHelper())->getRedis();
|
||||
$lockKey = 'login:h5:debounce:' . $openid;
|
||||
|
|
@ -470,7 +474,7 @@ class Login extends Base
|
|||
Log::warning('用户公众号登录请求过于频繁: ' . $openid);
|
||||
return $this->renderError('请勿频繁登录,请稍后再试');
|
||||
}
|
||||
|
||||
|
||||
$user = null;
|
||||
if ($user_base['unionid'] != null && $user_base['unionid'] != '') {
|
||||
|
||||
|
|
@ -670,15 +674,18 @@ class Login extends Base
|
|||
$user = $this->getUser();
|
||||
$user_id = $user['id'];
|
||||
$code = request()->param("code", '');
|
||||
$wxServer = new \app\common\server\Wx($this->app);
|
||||
$mobile = $wxServer->getMobile($code);
|
||||
// return $this->renderError($mobile,[$mobile,$code]);
|
||||
$wxPlatform = \app\common\server\platform\PlatformFactory::create();
|
||||
$mobileRes = $wxPlatform->getMobile($code);
|
||||
if ($mobileRes['status'] == 0 ) {
|
||||
return $this->renderError($mobileRes['msg']);
|
||||
}
|
||||
if (!isset($mobileRes['data']['phoneNumber'])) {
|
||||
return $this->renderError('获取手机号失败');
|
||||
}
|
||||
$mobile = $mobileRes['data']['phoneNumber'];
|
||||
Db::startTrans();
|
||||
$res = [];
|
||||
// $res[] = User::where(['id' => $user['id']])->update([
|
||||
// 'mobile' => $mobile,
|
||||
// 'update_time' => time(),
|
||||
// ]);
|
||||
|
||||
$data = [];
|
||||
$user_mobile = User::where(['mobile' => $mobile])->find();
|
||||
if ($user_mobile) {
|
||||
|
|
@ -707,9 +714,7 @@ class Login extends Base
|
|||
$res[] = User::where(['id' => $user['id']])->delete();
|
||||
$res[] = UserAccount::where(['user_id' => $user_id])->delete();
|
||||
$data['token'] = $account_token;
|
||||
// $res[] = UserAccount::where(['user_id' => $user['id']])->update([
|
||||
// 'token_time' => time(),
|
||||
// ]);
|
||||
|
||||
} else {
|
||||
$res[] = User::where(['id' => $user['id']])->update([
|
||||
'mobile' => $mobile,
|
||||
|
|
@ -864,7 +869,7 @@ class Login extends Base
|
|||
$mobile = request()->param("mobile", '');
|
||||
$code = request()->param("code", '');
|
||||
$pid_pid = request()->param('pid', 0);
|
||||
|
||||
|
||||
// 验证必要参数
|
||||
if (empty($mobile) || empty($code)) {
|
||||
$logMessages[] = '手机号或验证码为空: ' . $mobile;
|
||||
|
|
@ -874,21 +879,21 @@ class Login extends Base
|
|||
|
||||
$logMessages[] = '用户开始手机号登录: ' . $mobile;
|
||||
$click_id = request()->header('clickid');
|
||||
|
||||
|
||||
// 验证手机验证码
|
||||
$redis = (new RedisHelper())->getRedis();
|
||||
$redisKey = "VerificationCode:{$mobile}";
|
||||
$redisCode = $redis->get($redisKey);
|
||||
|
||||
|
||||
if (empty($redisCode) || $redisCode != $code) {
|
||||
$logMessages[] = '验证码错误: ' . $code . ',正确验证码: ' . $redisCode;
|
||||
Log::error(end($logMessages));
|
||||
return $this->renderError('验证码错误');
|
||||
}
|
||||
|
||||
|
||||
// 验证通过后删除Redis中的验证码
|
||||
$redis->del($redisKey);
|
||||
|
||||
|
||||
// 添加Redis防抖锁
|
||||
$lockKey = 'login:mobile:debounce:' . $mobile;
|
||||
if (!$redis->set($lockKey, 1, ['nx', 'ex' => 3])) {
|
||||
|
|
@ -896,7 +901,7 @@ class Login extends Base
|
|||
Log::warning(end($logMessages));
|
||||
return $this->renderError('请勿频繁登录,请稍后再试');
|
||||
}
|
||||
|
||||
|
||||
// 检查用户是否已存在
|
||||
$user = User::getInfo(['mobile' => $mobile]);
|
||||
|
||||
|
|
@ -926,7 +931,7 @@ class Login extends Base
|
|||
$ip_city = $result['city'];
|
||||
$ip_adcode = $result['adcode'];
|
||||
}
|
||||
|
||||
|
||||
// 检查UserAccount是否存在
|
||||
$userAccount = UserAccount::where(['user_id' => $user['id']])->find();
|
||||
if ($userAccount) {
|
||||
|
|
@ -982,22 +987,22 @@ class Login extends Base
|
|||
$pid = $pid_info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 开始事务
|
||||
Db::startTrans();
|
||||
|
||||
|
||||
// 生成随机昵称和头像
|
||||
$randx = rand(1000, 9999);
|
||||
$nickname = "手机用户" . $randx;
|
||||
$logMessages[] = $nickname;
|
||||
|
||||
|
||||
// 使用Identicon生成默认头像
|
||||
$randx = rand(10000, 99999);
|
||||
$identicon = new \Identicon\Identicon();
|
||||
$imageData = $identicon->getImageData($mobile . $nickname);
|
||||
$uploadResult = $this->uploader->uploadFile($imageData, "storage/users/icon/default/" . $randx . ".png");
|
||||
$headimg = $uploadResult['full_url'];
|
||||
|
||||
|
||||
// 插入用户记录
|
||||
$res[] = $user_id = User::insertGetId([
|
||||
'openid' => '', // 手机号注册无openid
|
||||
|
|
@ -1015,7 +1020,7 @@ class Login extends Base
|
|||
if ($uid) {
|
||||
User::where('id', $user_id)->update(['uid' => $uid]);
|
||||
}
|
||||
|
||||
|
||||
// 如果是测试环境,给新用户赠送钻石
|
||||
// $isTest = \app\common\helper\ConfigHelper::getSystemTestKey("enable_test");
|
||||
// if ($isTest == "1") {
|
||||
|
|
@ -1035,12 +1040,12 @@ class Login extends Base
|
|||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// 生成账号token
|
||||
$time = time();
|
||||
$token_num = getRandStr(10);
|
||||
$account_token = user_md5($user_id . $token_num . $time);
|
||||
|
||||
|
||||
// 获取IP和地理位置信息
|
||||
$last_login_ip1 = $this->getRealIp();
|
||||
$result = $this->ip_location($last_login_ip1);
|
||||
|
|
@ -1052,7 +1057,7 @@ class Login extends Base
|
|||
$ip_city = $result['city'];
|
||||
$ip_adcode = $result['adcode'];
|
||||
}
|
||||
|
||||
|
||||
// 插入用户账号信息
|
||||
$res[] = UserAccount::insert([
|
||||
'user_id' => $user_id,
|
||||
|
|
@ -1078,7 +1083,7 @@ class Login extends Base
|
|||
$res[] = User::changeDraw($pid, 1, 5, '获得一张抽奖券', $user_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (resCheck($res)) {
|
||||
// 新用户注册也要记录登录日志
|
||||
UserLoginLog::recordLogin(
|
||||
|
|
|
|||
|
|
@ -316,6 +316,28 @@ if (!function_exists('create_order_no')) {
|
|||
return $order_no;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('create_order_no_new')) {
|
||||
/**
|
||||
* 生成订单号
|
||||
* @param string $pre 订单前缀
|
||||
* @param string $tale 表名
|
||||
* @param string $field 字段名
|
||||
* @return string
|
||||
*/
|
||||
function create_order_no_new($pre = "", $merchant_prefix = "", $project_prefix = "", $pay_type = "")
|
||||
{
|
||||
$pre = $pre . $merchant_prefix . $project_prefix . $pay_type;
|
||||
$order_no = $pre . date('Ymd') . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8) . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
|
||||
$r = Db::name('order')->field('id')->where(['order_num' => $order_no])->find();
|
||||
if ($r) {
|
||||
$order_no = create_order_no_new($pre, $merchant_prefix, $project_prefix, $pay_type);
|
||||
}
|
||||
return $order_no;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!function_exists('getPrizeCode')) {
|
||||
|
||||
/**
|
||||
|
|
@ -724,20 +746,20 @@ if (!function_exists('order_callback')) {
|
|||
// 订单支付日志
|
||||
function writelog($filename, $content)
|
||||
{
|
||||
try {
|
||||
$date = date('Y-m-d');
|
||||
$file = "./pay_log/" . $date;
|
||||
if (!is_dir($file)) {
|
||||
mkdir($file);
|
||||
try {
|
||||
$date = date('Y-m-d');
|
||||
$file = "./pay_log/" . $date;
|
||||
if (!is_dir($file)) {
|
||||
mkdir($file);
|
||||
}
|
||||
$file = $file . "/" . $filename . ".txt";
|
||||
$content = "【收到信息" . date("Y-m-d H:i:s", time()) . "】" . $content . "\r\n\r\n";
|
||||
$open = fopen($file, "a");
|
||||
fwrite($open, $content);
|
||||
fclose($open);
|
||||
} catch (\Throwable $th) {
|
||||
|
||||
}
|
||||
$file = $file . "/" . $filename . ".txt";
|
||||
$content = "【收到信息" . date("Y-m-d H:i:s", time()) . "】" . $content . "\r\n\r\n";
|
||||
$open = fopen($file, "a");
|
||||
fwrite($open, $content);
|
||||
fclose($open);
|
||||
} catch (\Throwable $th) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -900,10 +922,8 @@ function generatePayNotifySign($data)
|
|||
foreach ($data as $key => $value) {
|
||||
$stringA .= "{$key}={$value}&";
|
||||
}
|
||||
|
||||
// 获取密钥
|
||||
$wxpay_config = getConfig('wxpay');
|
||||
$key = $wxpay_config['key'] ?? 'l044imysi1vsmobyrkkfnaniu5bhiupd'; // 默认密钥
|
||||
//加密
|
||||
$key = 'l044imysi1vsmobyrkkfnaniu5bhiupd'; // 默认密钥
|
||||
|
||||
// 加上密钥
|
||||
$stringA .= "key=" . $key;
|
||||
|
|
|
|||
|
|
@ -42,16 +42,7 @@ class GoodsExtend extends Base
|
|||
*/
|
||||
public static function getGoodsExtendByGoodsId($goodsId, $goods_type)
|
||||
{
|
||||
// // 生成缓存键
|
||||
// $redis = (new \app\common\server\RedisHelper())->getRedis();
|
||||
// $cache_key = "goods_extend:{$goodsId}:{$goods_type}";
|
||||
|
||||
// // 尝试从缓存获取数据
|
||||
// $cached_data = $redis->get($cache_key);
|
||||
// if ($cached_data) {
|
||||
// return json_decode($cached_data, true);
|
||||
// }
|
||||
|
||||
|
||||
$goods_extend = self::where('goods_id', $goodsId)->find();
|
||||
if (!$goods_extend) {
|
||||
// 从goods_type表获取默认值
|
||||
|
|
@ -73,12 +64,7 @@ class GoodsExtend extends Base
|
|||
];
|
||||
}
|
||||
}
|
||||
|
||||
// // 将数据存入缓存,设置5分钟过期时间
|
||||
// if ($goods_extend) {
|
||||
// $redis->set($cache_key, json_encode($goods_extend), 300);
|
||||
// }
|
||||
|
||||
|
||||
return $goods_extend;
|
||||
}
|
||||
}
|
||||
143
app/common/server/platform/BasePlatform.php
Normal file
143
app/common/server/platform/BasePlatform.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
namespace app\common\server\platform;
|
||||
/**
|
||||
* 多端平台支付抽象基类
|
||||
*/
|
||||
abstract class BasePlatform
|
||||
{
|
||||
protected string $code;
|
||||
protected string $env;
|
||||
|
||||
// 构造函数可被子类继承
|
||||
public function __construct()
|
||||
{
|
||||
$this->code = '';
|
||||
$this->env = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象方法:支付(子类必须实现)
|
||||
* @param object $data [$user,$price,order_type]
|
||||
|
||||
*/
|
||||
abstract public function pay(array $data): array;
|
||||
/**
|
||||
* 订单发货
|
||||
* @param mixed $user 用户
|
||||
* @param mixed $order_num 订单号
|
||||
* @return void
|
||||
*/
|
||||
abstract public function post_order($user, $order_num): int;
|
||||
/**
|
||||
* 获取urlLinks
|
||||
* @param mixed $userId
|
||||
* @return void
|
||||
*/
|
||||
abstract public function generateUrlLink($userId): array;
|
||||
/**
|
||||
* 获取用户openId
|
||||
* @param mixed $code
|
||||
* @return void
|
||||
*/
|
||||
abstract public function getOpenid($code): array;
|
||||
/**
|
||||
*
|
||||
* 获取手机号
|
||||
* @param mixed $code
|
||||
* @return void
|
||||
*/
|
||||
abstract public function getMobile($code = ''): array;
|
||||
/**
|
||||
* 普通方法(子类自动继承)
|
||||
*/
|
||||
public function getPlatformInfo(): array
|
||||
{
|
||||
return [
|
||||
'code' => $this->code,
|
||||
'env' => $this->env,
|
||||
'time' => date('Y-m-d H:i:s')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 产生一个指定长度的随机字符串,并返回给用户
|
||||
* @param type $len 产生字符串的长度
|
||||
* @return string 随机字符串
|
||||
*/
|
||||
protected function genRandomString($len = 32)
|
||||
{
|
||||
$chars = array(
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"e",
|
||||
"f",
|
||||
"g",
|
||||
"h",
|
||||
"i",
|
||||
"j",
|
||||
"k",
|
||||
"l",
|
||||
"m",
|
||||
"n",
|
||||
"o",
|
||||
"p",
|
||||
"q",
|
||||
"r",
|
||||
"s",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"L",
|
||||
"M",
|
||||
"N",
|
||||
"O",
|
||||
"P",
|
||||
"Q",
|
||||
"R",
|
||||
"S",
|
||||
"T",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"
|
||||
);
|
||||
$charsLen = count($chars) - 1;
|
||||
// 将数组打乱
|
||||
shuffle($chars);
|
||||
$output = "";
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$output .= $chars[mt_rand(0, $charsLen)];
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
70
app/common/server/platform/H5Platform.php
Normal file
70
app/common/server/platform/H5Platform.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
namespace app\common\server\platform;
|
||||
/**
|
||||
* 多端平台支付抽象基类
|
||||
*/
|
||||
class H5Platform extends BasePlatform
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->code = 'WEB_H5';
|
||||
$this->env = 'h5';
|
||||
}
|
||||
|
||||
public function pay(array $data): array
|
||||
{
|
||||
// echo "H5支付:{$amount}分,订单号:{$orderId}\n";
|
||||
// 实际项目中这里调用支付SDK
|
||||
return [];
|
||||
}
|
||||
/**
|
||||
* 发货
|
||||
* @param mixed $openid
|
||||
* @param mixed $access_token
|
||||
* @param mixed $order_num
|
||||
* @param mixed $title
|
||||
* @return int
|
||||
*/
|
||||
public function post_order($user, $order_num): int
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成URL链接
|
||||
* @param int $userId 用户ID
|
||||
* @return array
|
||||
*/
|
||||
public function generateUrlLink($userId): array
|
||||
{
|
||||
|
||||
return ['status' => 1, 'data' => ""];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机号
|
||||
* @param string $code 手机号获取凭证
|
||||
* @return array
|
||||
*/
|
||||
public function getMobile($code = ''): array
|
||||
{
|
||||
|
||||
|
||||
return ['status' => 1, 'data' => ""];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取openid
|
||||
* @param string $code 登录凭证
|
||||
* @return array
|
||||
*/
|
||||
public function getOpenid($code): array
|
||||
{
|
||||
|
||||
return ['status' => 1, 'data' => ""];
|
||||
}
|
||||
|
||||
}
|
||||
732
app/common/server/platform/MiniProgramPlatform.php
Normal file
732
app/common/server/platform/MiniProgramPlatform.php
Normal file
|
|
@ -0,0 +1,732 @@
|
|||
<?php
|
||||
namespace app\common\server\platform;
|
||||
use think\App;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
use app\common\helper\WxPayHelper;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* 多端平台支付抽象基类
|
||||
*/
|
||||
class MiniProgramPlatform extends BasePlatform
|
||||
{
|
||||
/**
|
||||
* 小程序配置
|
||||
* @var
|
||||
*/
|
||||
public $mp_miniprogram = null;
|
||||
/**
|
||||
* 微信app_id
|
||||
* @var
|
||||
*/
|
||||
public $wx_appid = null;
|
||||
/**
|
||||
* 微信密钥
|
||||
* @var
|
||||
*/
|
||||
public $wx_secret = null;
|
||||
/**
|
||||
* 商户配置
|
||||
* @var
|
||||
*/
|
||||
public $mp_merchant = null;
|
||||
/**
|
||||
* 商户id
|
||||
* @var
|
||||
*/
|
||||
private $mch_id = null;
|
||||
/**
|
||||
* 商户key
|
||||
* @var
|
||||
*/
|
||||
private $key = null;
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->code = 'MP-WEIXIN';
|
||||
$this->env = 'miniProgram';
|
||||
|
||||
$this->mp_miniprogram = \app\common\helper\MiniprogramHelper::getMiniprogramConfig();
|
||||
|
||||
if (!empty($this->mp_miniprogram['appid'])) {
|
||||
$this->wx_appid = $this->mp_miniprogram['appid'];
|
||||
$this->wx_secret = $this->mp_miniprogram['app_secret'];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Summary of pay [$user,$price,title,attach]
|
||||
* @param mixed $data
|
||||
* @return array{data: array, status: int|array{msg: string, status: int}}
|
||||
*/
|
||||
public function pay(array $data): array
|
||||
{
|
||||
$data += ['user' => null, 'price' => 0, 'title' => '', 'attach' => 'order_wxs', 'pre' => 'MH_'];
|
||||
[
|
||||
'user' => $user,
|
||||
'price' => $price,
|
||||
'title' => $title,
|
||||
'attach' => $attach,
|
||||
'pre' => $pre
|
||||
] = $data;
|
||||
if ($user == null) {
|
||||
//抛出异常
|
||||
throw new \Exception('用户信息为空');
|
||||
}
|
||||
$project_prefix = $this->mp_miniprogram['order_prefix'];
|
||||
if ($price <= 0) {
|
||||
//生成订单号,订单号为:ML_DRAYDMP02025018.... ML_ 前缀(固定3位),DRA 商户号(固定3位),YD 项目,固定2位,MP0 表示微信小程序支付
|
||||
$order_no = create_order_no_new($pre, "MON", $project_prefix, "MP0");
|
||||
return [
|
||||
'status' => 1,
|
||||
'data' => [
|
||||
'order_no' => $order_no,
|
||||
'res' => []
|
||||
]
|
||||
];
|
||||
}
|
||||
$title = mb_substr($title, 0, 30);
|
||||
|
||||
$prefix = $this->GetPrefix();
|
||||
//生成订单号,订单号为:ML_DRAYDMP02025018.... ML_ 前缀(固定3位),DRA 商户号(固定3位),YD 项目,固定2位,MP0 表示微信小程序支付
|
||||
$order_no = create_order_no_new($pre, $prefix, $project_prefix, "MP0");
|
||||
$openid = $user['openid'];
|
||||
$payment_type = 'wxpay';
|
||||
$order_type = $attach;
|
||||
$user_id = $user ? $user['id'] : 0;
|
||||
// 支付使用的随机数
|
||||
$nonce_str = $this->genRandomString();
|
||||
// 回调使用的随机数(与支付随机数分离)
|
||||
$callback_nonce_str = $this->genRandomString();
|
||||
// 生成新的支付通知URL
|
||||
$notifyUrl = generatePayNotifyUrl($payment_type, $order_type, $user_id, $order_no, $callback_nonce_str);
|
||||
$is_test = $user['istest'];
|
||||
if ($is_test == 2) {
|
||||
$price = 0.01;
|
||||
}
|
||||
$params['appid'] = $this->wx_appid;
|
||||
$params['mch_id'] = $this->getMchId();
|
||||
$params['nonce_str'] = $nonce_str;
|
||||
$params['body'] = $title;
|
||||
$params['attach'] = $attach;
|
||||
$params['out_trade_no'] = $order_no;
|
||||
$params['notify_url'] = $notifyUrl;
|
||||
$params['total_fee'] = round($price * 100, 2);
|
||||
$params['spbill_create_ip'] = $this->get_client_ip();
|
||||
$params['trade_type'] = 'JSAPI';
|
||||
$params['openid'] = $openid;
|
||||
$params['sign'] = $this->MakeSign($params);
|
||||
$xml = $this->data_to_xml($params);
|
||||
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
$response = $this->postXmlCurl($xml, $url);
|
||||
$result = $this->xml_to_data($response);
|
||||
if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
|
||||
// 将通知URL和随机字符串保存到order_notify表中
|
||||
Db::name('order_notify')->insert([
|
||||
'order_no' => $order_no,
|
||||
'notify_url' => $notifyUrl,
|
||||
'nonce_str' => $callback_nonce_str,
|
||||
'pay_time' => date('Y-m-d H:i:s'),
|
||||
'pay_amount' => $price,
|
||||
'status' => 0,
|
||||
'retry_count' => 0,
|
||||
'create_time' => date('Y-m-d H:i:s'),
|
||||
'update_time' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
$time = time();
|
||||
$res['appId'] = $this->wx_appid;
|
||||
$res["timeStamp"] = (string) $time;
|
||||
$res["nonceStr"] = $nonce_str;
|
||||
$res["package"] = "prepay_id=" . $result['prepay_id'];
|
||||
$res["signType"] = 'MD5';
|
||||
$res["paySign"] = $this->MakeSign($res);
|
||||
return [
|
||||
'status' => 1,
|
||||
'data' => [
|
||||
'order_no' => $order_no,
|
||||
'res' => $res
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// 记录支付失败日志
|
||||
$error_message = '';
|
||||
if (isset($result['return_code']) && $result['return_code'] === 'FAIL') {
|
||||
$error_message = $result['return_msg'] ?? '未知错误';
|
||||
} elseif (isset($result['result_code']) && $result['result_code'] === 'FAIL') {
|
||||
$error_code = $result['err_code'] ?? '';
|
||||
$error_message = $result['err_code_des'] ?? $this->error_code($error_code) ?? '未知错误';
|
||||
} else {
|
||||
$error_message = '微信支付接口返回异常';
|
||||
}
|
||||
// $redis = (new \app\common\server\RedisHelper())->getRedis();
|
||||
// 记录到ThinkPHP的日志系统中
|
||||
Log::error('微信支付失败: ' . json_encode([
|
||||
'order_no' => $order_no,
|
||||
'user_id' => $user_id,
|
||||
'openid' => $openid,
|
||||
'price' => $price,
|
||||
'error_message' => $error_message,
|
||||
'result' => $result,
|
||||
'time' => date('Y-m-d H:i:s')
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
return ['status' => 0, 'msg' => '支付失败:' . $error_message];
|
||||
}
|
||||
/**
|
||||
* 发货
|
||||
* @param mixed $openid
|
||||
* @param mixed $access_token
|
||||
* @param mixed $order_num
|
||||
* @param mixed $title
|
||||
* @return int
|
||||
*/
|
||||
public function post_order($user, $order_num): int
|
||||
{
|
||||
$msg = "本单购买商品已发放至[小程序盒柜]";
|
||||
if (strpos($order_num, 'FH_') === 0) {
|
||||
$msg = "本单购买的商品正在打包,请联系客服获取物流信息";
|
||||
}
|
||||
$openid = $user['openid'];
|
||||
// 根据订单号设置正确的商户配置
|
||||
$this->setMerchantByOrderNo($order_num);
|
||||
$date = new \DateTime();
|
||||
// $this->appid
|
||||
$access_token = $this->get_access_token();
|
||||
//订单发货时间
|
||||
$formattedDate = $date->format('Y-m-d\TH:i:s');
|
||||
$request_url = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=" . $access_token;
|
||||
$param = '{
|
||||
"order_key": {
|
||||
"order_number_type": 1,
|
||||
"mchid":"' . $this->getMchId() . '",
|
||||
"out_trade_no":"' . $order_num . '"
|
||||
},
|
||||
"logistics_type": 4,
|
||||
"delivery_mode": 1,
|
||||
"shipping_list": [
|
||||
{
|
||||
"item_desc": "' . $msg . '"
|
||||
}
|
||||
],
|
||||
"upload_time": "' . $formattedDate . '+08:00",
|
||||
"payer": {
|
||||
"openid":"' . $openid . '"
|
||||
}
|
||||
}';
|
||||
// 记录请求参数日志
|
||||
writelog('post_order_log', json_encode([
|
||||
'method' => 'post_order',
|
||||
'order_num' => $order_num,
|
||||
'openid' => $openid,
|
||||
'merchant' => $this->getMchId(),
|
||||
'request_url' => $request_url,
|
||||
'param' => $param,
|
||||
'time' => date('Y-m-d H:i:s')
|
||||
]));
|
||||
|
||||
$res = curlPost($request_url, $param);
|
||||
$res = json_decode($res, true);
|
||||
|
||||
// 记录响应结果日志
|
||||
writelog('post_order_log', json_encode([
|
||||
'method' => 'post_order_response',
|
||||
'order_num' => $order_num,
|
||||
'response' => $res,
|
||||
'time' => date('Y-m-d H:i:s')
|
||||
]));
|
||||
|
||||
if ($res['errcode'] == 0 && $res['errmsg'] == 'ok') {
|
||||
return 1;
|
||||
} else {
|
||||
// 发货失败,将订单信息存入Redis,等待定时任务重试
|
||||
$redis = (new \app\common\server\RedisHelper())->getRedis();
|
||||
$key = 'post_order:' . $order_num;
|
||||
|
||||
// 存储发货失败的订单信息
|
||||
$orderData = [
|
||||
'openid' => $openid,
|
||||
'appid' => $this->wx_appid,
|
||||
// 不存储access_token,因为可能过期
|
||||
'order_num' => $order_num,
|
||||
'title' => '订单发货',
|
||||
'merchant' => $this->getMchId(),
|
||||
'error_code' => $res['errcode'] ?? 'unknown',
|
||||
'error_msg' => $res['errmsg'] ?? 'unknown',
|
||||
'retry_count' => 0,
|
||||
'last_retry_time' => time(),
|
||||
'create_time' => time()
|
||||
];
|
||||
|
||||
// 存入Redis,设置过期时间为3天
|
||||
$redis->set($key, json_encode($orderData));
|
||||
$redis->expire($key, 3 * 24 * 3600);
|
||||
|
||||
// 记录存入Redis的日志
|
||||
writelog('post_order_log', json_encode([
|
||||
'method' => 'post_order_redis_save',
|
||||
'order_num' => $order_num,
|
||||
'redis_key' => $key,
|
||||
'data' => $orderData,
|
||||
'time' => date('Y-m-d H:i:s')
|
||||
]));
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成URL链接
|
||||
* @param int $userId 用户ID
|
||||
* @return array
|
||||
*/
|
||||
public function generateUrlLink($userId): array
|
||||
{
|
||||
// 获取access_token
|
||||
$access_token = $this->get_access_token();
|
||||
|
||||
$url = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=" . $access_token;
|
||||
$param = [
|
||||
'path' => 'pages/index/index',
|
||||
'query' => 'user_id=' . $userId,
|
||||
// 'expire_type' => 0,
|
||||
// 'expire_time' => time() + 7 * 86400, // 7天后过期
|
||||
// 'env_version' => 'release'
|
||||
];
|
||||
|
||||
$result = curlPost($url, json_encode($param));
|
||||
$result = json_decode($result, true);
|
||||
if (isset($result['errcode']) && $result['errcode'] != 0) {
|
||||
return ['status' => 0, 'msg' => $result['errmsg'] ?? '生成链接失败'];
|
||||
}
|
||||
|
||||
return ['status' => 1, 'data' => $result];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机号
|
||||
* @param string $code 手机号获取凭证
|
||||
* @return array
|
||||
*/
|
||||
public function getMobile($code = ''): array
|
||||
{
|
||||
if (empty($code)) {
|
||||
return ['status' => 0, 'msg' => '缺少code参数'];
|
||||
}
|
||||
|
||||
// 获取access_token
|
||||
$access_token = $this->get_access_token();
|
||||
|
||||
$url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" . $access_token;
|
||||
$param = [
|
||||
'code' => $code
|
||||
];
|
||||
|
||||
$result = $this->post_curl_data($url, $param);
|
||||
// $result = json_decode($result, true);
|
||||
if (isset($result['errcode']) && $result['errcode'] != 0) {
|
||||
return ['status' => 0, 'msg' => $result['errmsg'] ?? '获取手机号失败'];
|
||||
}
|
||||
|
||||
return ['status' => 1, 'data' => $result['phone_info'] ?? []];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取openid
|
||||
* @param string $code 登录凭证
|
||||
* @return array
|
||||
*/
|
||||
public function getOpenid($code): array
|
||||
{
|
||||
if (empty($code)) {
|
||||
return ['status' => 0, 'msg' => '缺少code参数'];
|
||||
}
|
||||
|
||||
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $this->wx_appid . "&secret=" . $this->wx_secret . "&js_code=" . $code . "&grant_type=authorization_code";
|
||||
$result = $this->get_curl_data($url);
|
||||
|
||||
if (isset($result['errcode']) && $result['errcode'] != 0) {
|
||||
return ['status' => 0, 'msg' => $result['errmsg'] ?? '获取openid失败'];
|
||||
}
|
||||
|
||||
return ['status' => 1, 'data' => $result];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单号设置商户环境
|
||||
*
|
||||
* @param string $orderNo 订单号
|
||||
* @return bool 设置成功返回 true,失败返回 false
|
||||
*/
|
||||
public function setMerchantByOrderNo(string $orderNo): bool
|
||||
{
|
||||
if (strlen($orderNo) < 6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$merchantCode = substr($orderNo, 3, 3); // 截取商户号部分
|
||||
|
||||
// 获取配置中的商户列表
|
||||
$weixinpay_setting = getConfig('weixinpay_setting');
|
||||
|
||||
if (empty($weixinpay_setting['merchants']) || !is_array($weixinpay_setting['merchants'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找对应的商户配置
|
||||
$merchant = null;
|
||||
foreach ($weixinpay_setting['merchants'] as $item) {
|
||||
if ($item['order_prefix'] == $merchantCode) {
|
||||
$merchant = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$merchant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置商户环境
|
||||
$this->mp_merchant = $merchant;
|
||||
$this->mch_id = $merchant['mch_id'];
|
||||
$this->key = $merchant['keys'];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取access_token
|
||||
*/
|
||||
public function get_access_token()
|
||||
{
|
||||
return $this->get_access_appid_token($this->wx_appid, $this->wx_secret);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取access_token
|
||||
*/
|
||||
public function get_access_appid_token($appid, $wx_secret)
|
||||
{
|
||||
$redis = (new \app\common\server\RedisHelper())->getRedis();
|
||||
$redis_key = 'wx_access_token:' . $appid;
|
||||
|
||||
$access_token_info = $redis->get($redis_key);
|
||||
if ($access_token_info) {
|
||||
$access_token_info = json_decode($access_token_info, true);
|
||||
if ($access_token_info['access_token_time'] > time()) {
|
||||
return $access_token_info['access_token'];
|
||||
}
|
||||
}
|
||||
|
||||
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $wx_secret;
|
||||
$res_access_token = $this->get_curl_data($url);
|
||||
if (isset($res_access_token['errcode'])) {
|
||||
throw new \Exception('获取access_token异常');
|
||||
}
|
||||
|
||||
$access_token = $res_access_token['access_token'];
|
||||
$expires_in = $res_access_token['expires_in'];
|
||||
$access_token_time = time() + $expires_in;
|
||||
|
||||
$data = [
|
||||
'access_token' => $access_token,
|
||||
'access_token_time' => $access_token_time,
|
||||
];
|
||||
|
||||
$redis->set($redis_key, json_encode($data), $expires_in - 1800);
|
||||
|
||||
return $access_token;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $url 请求链接
|
||||
*/
|
||||
public function get_curl_data($url)
|
||||
{
|
||||
$headerArray = array("Content-type:application/json;", "Accept:application/json");
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);
|
||||
$response = curl_exec($ch);
|
||||
if ($response) {
|
||||
curl_close($ch);
|
||||
return json_decode($response, true);
|
||||
} else {
|
||||
$error = curl_errno($ch);
|
||||
curl_close($ch);
|
||||
return ['errcode' => 1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url 链接
|
||||
* @param $data 参数
|
||||
* @return mixed
|
||||
*/
|
||||
public function post_curl_data($url, $data)
|
||||
{
|
||||
$data = json_encode($data);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Content-Type: application/json; charset=utf-8',
|
||||
'Content-Length: ' . strlen($data)
|
||||
));
|
||||
$return_content = curl_exec($ch);
|
||||
if ($return_content) {
|
||||
curl_close($ch);
|
||||
$return_content = json_decode($return_content, true);
|
||||
return $return_content;
|
||||
} else {
|
||||
$error = curl_errno($ch);
|
||||
curl_close($ch);
|
||||
return ['errcode' => 1];
|
||||
}
|
||||
}
|
||||
|
||||
// region 商户初始化相关代码
|
||||
/**
|
||||
* 获取当前商户信息(延迟加载)
|
||||
*/
|
||||
public function getMerchant(): ?array
|
||||
{
|
||||
if ($this->mp_merchant === null) {
|
||||
$this->initMerchant(); // 第一次访问时才加载
|
||||
}
|
||||
return $this->mp_merchant;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 mch_id(延迟加载)
|
||||
*/
|
||||
public function getMchId(): ?string
|
||||
{
|
||||
if ($this->mch_id === null) {
|
||||
$this->initMerchant();
|
||||
}
|
||||
return $this->mch_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 key(延迟加载)
|
||||
*/
|
||||
public function getKey(): ?string
|
||||
{
|
||||
if ($this->key === null) {
|
||||
$this->initMerchant();
|
||||
}
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function GetPrefix(): ?string
|
||||
{
|
||||
if ($this->mp_merchant === null) {
|
||||
$this->initMerchant();
|
||||
}
|
||||
return $this->mp_merchant['order_prefix'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 实际加载商户信息
|
||||
*/
|
||||
private function initMerchant(): void
|
||||
{
|
||||
if (
|
||||
empty($this->mp_miniprogram) ||
|
||||
empty($this->mp_miniprogram['merchants']) ||
|
||||
!is_array($this->mp_miniprogram['merchants'])
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$weixinpay_setting = getConfig('weixinpay_setting');
|
||||
if (empty($weixinpay_setting['merchants']) || !is_array($weixinpay_setting['merchants'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$associatedMerchants = array_values(array_filter($weixinpay_setting['merchants'], function ($merchant) {
|
||||
return isset($merchant['is_enabled'], $merchant['mch_id']) &&
|
||||
$merchant['is_enabled'] === "1" &&
|
||||
in_array($merchant['mch_id'], $this->mp_miniprogram['merchants']);
|
||||
}));
|
||||
|
||||
if (!empty($associatedMerchants)) {
|
||||
$merchant = WxPayHelper::getRandomMerchant($associatedMerchants);
|
||||
$this->mp_merchant = $merchant;
|
||||
$this->mch_id = $merchant['mch_id'];
|
||||
$this->key = $merchant['keys'];
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
* @return 签名
|
||||
*/
|
||||
public function MakeSign($params)
|
||||
{
|
||||
//签名步骤一:按字典序排序数组参数
|
||||
ksort($params);
|
||||
$string = $this->ToUrlParams($params);
|
||||
//签名步骤二:在string后加入KEY
|
||||
$string = $string . "&key=" . $this->getKey();
|
||||
//签名步骤三:MD5加密
|
||||
$string = md5($string);
|
||||
//签名步骤四:所有字符转为大写
|
||||
$result = strtoupper($string);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数拼接为url: key=value&key=value
|
||||
* @param $params
|
||||
* @return string
|
||||
*/
|
||||
public function ToUrlParams($params)
|
||||
{
|
||||
$string = '';
|
||||
if (!empty($params)) {
|
||||
$array = array();
|
||||
foreach ($params as $key => $value) {
|
||||
$array[] = $key . '=' . $value;
|
||||
}
|
||||
$string = implode("&", $array);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出xml字符
|
||||
* @param $params 参数名称
|
||||
* return string 返回组装的xml
|
||||
**/
|
||||
public function data_to_xml($params)
|
||||
{
|
||||
if (!is_array($params) || count($params) <= 0) {
|
||||
return false;
|
||||
}
|
||||
$xml = "<xml>";
|
||||
foreach ($params as $key => $val) {
|
||||
if (is_numeric($val)) {
|
||||
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
|
||||
} else {
|
||||
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
|
||||
}
|
||||
}
|
||||
$xml .= "</xml>";
|
||||
return $xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将xml转为array
|
||||
* @param string $xml
|
||||
* return array
|
||||
*/
|
||||
public function xml_to_data($xml)
|
||||
{
|
||||
if (!$xml) {
|
||||
return false;
|
||||
}
|
||||
//将XML转为array
|
||||
//禁止引用外部xml实体
|
||||
libxml_disable_entity_loader(true);
|
||||
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 以post方式提交xml到对应的接口url
|
||||
*
|
||||
* @param string $xml 需要post的xml数据
|
||||
* @param string $url url
|
||||
* @param bool $useCert 是否需要证书,默认不需要
|
||||
* @param int $second url执行超时时间,默认30s
|
||||
* @throws WxPayException
|
||||
*/
|
||||
private function postXmlCurl($xml, $url, $second = 30)
|
||||
{
|
||||
$ch = curl_init();
|
||||
//设置超时
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
//设置header
|
||||
curl_setopt($ch, CURLOPT_HEADER, FALSE);
|
||||
//要求结果为字符串且输出到屏幕上
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
|
||||
//post提交方式
|
||||
curl_setopt($ch, CURLOPT_POST, TRUE);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
|
||||
//运行curl
|
||||
$data = curl_exec($ch);
|
||||
//返回结果
|
||||
if ($data) {
|
||||
curl_close($ch);
|
||||
return $data;
|
||||
} else {
|
||||
$error = curl_errno($ch);
|
||||
curl_close($ch);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误代码
|
||||
* @param $code 服务器输出的错误代码
|
||||
* return string
|
||||
*/
|
||||
public function error_code($code)
|
||||
{
|
||||
$errList = array(
|
||||
'NOAUTH' => '商户未开通此接口权限',
|
||||
'NOTENOUGH' => '用户帐号余额不足',
|
||||
'ORDERNOTEXIST' => '订单号不存在',
|
||||
'ORDERPAID' => '商户订单已支付,无需重复操作',
|
||||
'ORDERCLOSED' => '当前订单已关闭,无法支付',
|
||||
'SYSTEMERROR' => '系统错误!系统超时',
|
||||
'APPID_NOT_EXIST' => '参数中缺少APPID',
|
||||
'MCHID_NOT_EXIST' => '参数中缺少MCHID',
|
||||
'APPID_MCHID_NOT_MATCH' => 'appid和mch_id不匹配',
|
||||
'LACK_PARAMS' => '缺少必要的请求参数',
|
||||
'OUT_TRADE_NO_USED' => '同一笔交易不能多次提交',
|
||||
'SIGNERROR' => '参数签名结果不正确',
|
||||
'XML_FORMAT_ERROR' => 'XML格式错误',
|
||||
'REQUIRE_POST_METHOD' => '未使用post传递参数 ',
|
||||
'POST_DATA_EMPTY' => 'post数据不能为空',
|
||||
'NOT_UTF8' => '未使用指定编码格式',
|
||||
);
|
||||
if (array_key_exists($code, $errList)) {
|
||||
return $errList[$code];
|
||||
}
|
||||
}
|
||||
|
||||
function get_client_ip()
|
||||
{
|
||||
if (isset($_SERVER['REMOTE_ADDR'])) {
|
||||
$cip = $_SERVER['REMOTE_ADDR'];
|
||||
} elseif (getenv("REMOTE_ADDR")) {
|
||||
$cip = getenv("REMOTE_ADDR");
|
||||
} elseif (getenv("HTTP_CLIENT_IP")) {
|
||||
$cip = getenv("HTTP_CLIENT_IP");
|
||||
} else {
|
||||
$cip = "127.0.0.1";
|
||||
}
|
||||
return $cip;
|
||||
}
|
||||
|
||||
}
|
||||
46
app/common/server/platform/PlatformFactory.php
Normal file
46
app/common/server/platform/PlatformFactory.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
namespace app\common\server\platform;
|
||||
use think\facade\Request;
|
||||
/**
|
||||
* 多端平台支付抽象基类
|
||||
*/
|
||||
class PlatformFactory
|
||||
{
|
||||
/**
|
||||
* 创建平台实例
|
||||
* @param string $client 客户端类型
|
||||
* @return BasePlatform 平台实例
|
||||
*/
|
||||
public static function create($client = null): BasePlatform
|
||||
{
|
||||
if (!isset($client)) {
|
||||
$client = request()->header('client', 'MP-WEIXIN');
|
||||
}
|
||||
if ($client == "WEB_H5") {
|
||||
return new H5Platform();
|
||||
}
|
||||
if ($client == "MP-WEIXIN") {
|
||||
return new MiniProgramPlatform();
|
||||
}
|
||||
return new MiniProgramPlatform();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建平台实例
|
||||
* @param string $client 客户端类型
|
||||
* @return
|
||||
*/
|
||||
public static function createPay($user, $price, $title, $attach, $pre = "MH_", $pay_type = 1, $client = null): array
|
||||
{
|
||||
$data = [
|
||||
'user' => $user,
|
||||
'price' => $price,
|
||||
'title' => $title,
|
||||
'attach' => $attach,
|
||||
'pre' => $pre,
|
||||
'pay_type' => $pay_type
|
||||
];
|
||||
$platform = self::create($client);
|
||||
return $platform->pay($data);
|
||||
}
|
||||
}
|
||||
41
app/common/service/PayService.php
Normal file
41
app/common/service/PayService.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\server\platform\MiniProgramPlatform;
|
||||
use app\common\model\User;
|
||||
use app\common\model\Reward;
|
||||
use app\common\model\CouponReceive;
|
||||
use app\common\model\Coupon;
|
||||
use app\common\model\Order;
|
||||
use think\facade\Request;
|
||||
use think\App;
|
||||
/**
|
||||
* 通用服务类
|
||||
*/
|
||||
class PayService
|
||||
{
|
||||
/**
|
||||
* Request实例
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
protected $client;
|
||||
//构造函数
|
||||
public function __construct(App $app)
|
||||
{
|
||||
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
//客户端
|
||||
$this->client = $this->request->header('client', 'MP-WEIXIN');
|
||||
//client
|
||||
$m = new MiniProgramPlatform();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,7 +31,8 @@
|
|||
"qcloud/cos-sdk-v5": "^2.6",
|
||||
"yzalis/identicon": "^2.0",
|
||||
"topthink/think-image": "^1.0",
|
||||
"topthink/think-migration": "^3.1"
|
||||
"topthink/think-migration": "^3.1",
|
||||
"alipaysdk/easysdk": "^2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "^4.2",
|
||||
|
|
|
|||
219
composer.lock
generated
219
composer.lock
generated
|
|
@ -4,8 +4,225 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d87efcd19adbf32a7bf40402f4f4d2e9",
|
||||
"content-hash": "0f1ac8c679e075e85ffcd1bd713e8421",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adbario/php-dot-notation",
|
||||
"version": "2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/adbario/php-dot-notation.git",
|
||||
"reference": "081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/adbario/php-dot-notation/zipball/081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae",
|
||||
"reference": "081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^5.5 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8|^5.7|^6.6|^7.5|^8.5|^9.5",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Adbar\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Riku Särkinen",
|
||||
"email": "riku@adbar.io"
|
||||
}
|
||||
],
|
||||
"description": "PHP dot notation access to arrays",
|
||||
"homepage": "https://github.com/adbario/php-dot-notation",
|
||||
"keywords": [
|
||||
"ArrayAccess",
|
||||
"dotnotation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/adbario/php-dot-notation/issues",
|
||||
"source": "https://github.com/adbario/php-dot-notation/tree/2.5.0"
|
||||
},
|
||||
"time": "2022-10-14T20:31:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "alibabacloud/tea",
|
||||
"version": "3.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aliyun/tea-php.git",
|
||||
"reference": "1619cb96c158384f72b873e1f85de8b299c9c367"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aliyun/tea-php/zipball/1619cb96c158384f72b873e1f85de8b299c9c367",
|
||||
"reference": "1619cb96c158384f72b873e1f85de8b299c9c367",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"adbario/php-dot-notation": "^2.4",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"guzzlehttp/guzzle": "^6.3|^7.0",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "*",
|
||||
"symfony/dotenv": "^3.4",
|
||||
"symfony/var-dumper": "^3.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-sockets": "To use client-side monitoring"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AlibabaCloud\\Tea\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alibaba Cloud SDK",
|
||||
"email": "sdk-team@alibabacloud.com",
|
||||
"homepage": "http://www.alibabacloud.com"
|
||||
}
|
||||
],
|
||||
"description": "Client of Tea for PHP",
|
||||
"homepage": "https://www.alibabacloud.com/",
|
||||
"keywords": [
|
||||
"alibabacloud",
|
||||
"client",
|
||||
"cloud",
|
||||
"tea"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/aliyun/tea-php/issues",
|
||||
"source": "https://github.com/aliyun/tea-php"
|
||||
},
|
||||
"time": "2023-05-16T06:43:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "alibabacloud/tea-fileform",
|
||||
"version": "0.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/alibabacloud-sdk-php/tea-fileform.git",
|
||||
"reference": "4bf0c75a045c8115aa8cb1a394bd08d8bb833181"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/alibabacloud-sdk-php/tea-fileform/zipball/4bf0c75a045c8115aa8cb1a394bd08d8bb833181",
|
||||
"reference": "4bf0c75a045c8115aa8cb1a394bd08d8bb833181",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"alibabacloud/tea": "^3.0",
|
||||
"php": ">5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35|^5.4.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AlibabaCloud\\Tea\\FileForm\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alibaba Cloud SDK",
|
||||
"email": "sdk-team@alibabacloud.com"
|
||||
}
|
||||
],
|
||||
"description": "Alibaba Cloud Tea File Library for PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/alibabacloud-sdk-php/tea-fileform/issues",
|
||||
"source": "https://github.com/alibabacloud-sdk-php/tea-fileform/tree/0.3.4"
|
||||
},
|
||||
"time": "2020-12-01T07:24:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "alipaysdk/easysdk",
|
||||
"version": "2.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/alipay/alipay-easysdk.git",
|
||||
"reference": "c6008839a22a5fca08e9f8536730f7abfed522d5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/alipay/alipay-easysdk/zipball/c6008839a22a5fca08e9f8536730f7abfed522d5",
|
||||
"reference": "c6008839a22a5fca08e9f8536730f7abfed522d5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"alibabacloud/tea": "^3.1",
|
||||
"alibabacloud/tea-fileform": "^0.3.2",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"guzzlehttp/guzzle": ">=6.3",
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Alipay\\EasySDK\\": "php/src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "junying.wjy",
|
||||
"email": "junying.wjy@antfin.com"
|
||||
}
|
||||
],
|
||||
"description": "支付宝官方 Alipay Easy SDK",
|
||||
"support": {
|
||||
"source": "https://github.com/alipay/alipay-easysdk/tree/v2.2.3"
|
||||
},
|
||||
"time": "2022-11-28T14:04:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
"version": "2.0.8",
|
||||
|
|
|
|||
|
|
@ -238,10 +238,18 @@ return [
|
|||
'url' => '/admin/weixinpay',
|
||||
'name' => '微信商户设置',
|
||||
],
|
||||
[
|
||||
'url' => '/admin/alipay',
|
||||
'name' => '支付宝商户设置',
|
||||
],
|
||||
[
|
||||
'url' => '/admin/miniprogram',
|
||||
'name' => '小程序设置',
|
||||
],
|
||||
[
|
||||
'url' => '/admin/h5',
|
||||
'name' => 'H5设置',
|
||||
],
|
||||
[
|
||||
'url' => '/admin/systemconfig',
|
||||
'name' => '系统配置',
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user