207 lines
7.4 KiB
PHP
Executable File
207 lines
7.4 KiB
PHP
Executable File
<?php
|
||
|
||
namespace app\common\helper;
|
||
|
||
class WxPayHelper
|
||
{
|
||
/**
|
||
* 根据权重随机获取一个商户
|
||
*
|
||
* @param array $merchants 商户数组
|
||
* @return array|null 随机选择的商户信息
|
||
*/
|
||
public static function getRandomMerchant(array $merchants)
|
||
{
|
||
if (empty($merchants)) {
|
||
return null;
|
||
}
|
||
|
||
// 只有一个商户,直接返回
|
||
if (count($merchants) === 1) {
|
||
return $merchants[0];
|
||
}
|
||
|
||
// 计算总权重
|
||
$totalWeight = 0;
|
||
foreach ($merchants as $merchant) {
|
||
$totalWeight += isset($merchant['weight']) ? (int)$merchant['weight'] : 1;
|
||
}
|
||
|
||
// 生成随机数
|
||
$randomWeight = mt_rand(1, $totalWeight);
|
||
|
||
// 根据权重选择商户
|
||
$currentWeight = 0;
|
||
foreach ($merchants as $merchant) {
|
||
$weight = isset($merchant['weight']) ? (int)$merchant['weight'] : 1;
|
||
$currentWeight += $weight;
|
||
|
||
if ($randomWeight <= $currentWeight) {
|
||
return $merchant;
|
||
}
|
||
}
|
||
|
||
// 默认返回第一个商户
|
||
return $merchants[0];
|
||
}
|
||
|
||
/**
|
||
* 获取微信支付配置
|
||
*
|
||
* @return array 包含随机选择的商户信息和appid
|
||
*/
|
||
public static function getWxPayConfig()
|
||
{
|
||
// 获取当前域名对应的小程序配置
|
||
$miniprogram = \app\common\helper\MiniprogramHelper::getMiniprogramConfig();
|
||
|
||
// 选择一个商户
|
||
$merchant = null;
|
||
|
||
// 如果小程序配置了关联商户,从关联商户中随机选择一个
|
||
if (!empty($miniprogram) && !empty($miniprogram['merchants']) && is_array($miniprogram['merchants']) && count($miniprogram['merchants']) > 0) {
|
||
$weixinpay_setting = getConfig('weixinpay_setting');
|
||
if (!empty($weixinpay_setting) && !empty($weixinpay_setting['merchants'])) {
|
||
// 过滤出关联的商户
|
||
$associatedMerchants = [];
|
||
foreach ($weixinpay_setting['merchants'] as $m) {
|
||
if (in_array($m['id'] ?? '', $miniprogram['merchants'])) {
|
||
$associatedMerchants[] = $m;
|
||
}
|
||
}
|
||
|
||
// 如果有关联商户,从中随机选择一个
|
||
if (!empty($associatedMerchants)) {
|
||
$merchant = self::getRandomMerchant($associatedMerchants);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有关联商户或无法获取关联商户,则使用默认商户选择逻辑
|
||
if (empty($merchant)) {
|
||
$weixinpay_setting = getConfig('weixinpay_setting');
|
||
|
||
if (!empty($weixinpay_setting) && !empty($weixinpay_setting['merchants'])) {
|
||
$merchant = self::getRandomMerchant($weixinpay_setting['merchants']);
|
||
} else {
|
||
// 兼容旧配置
|
||
$old_config = getConfig('weixinpay');
|
||
if (!empty($old_config)) {
|
||
$merchant = [
|
||
'name' => '默认商户',
|
||
'mch_id' => $old_config['mch_id'],
|
||
'keys' => $old_config['keys'],
|
||
'order_prefix' => $old_config['order_prefix'] ?? 'MYH',
|
||
'weight' => 1
|
||
];
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取微信AppID - 优先使用小程序配置中的AppID
|
||
$appid = '';
|
||
if (!empty($miniprogram) && !empty($miniprogram['appid'])) {
|
||
$appid = $miniprogram['appid'];
|
||
} else {
|
||
// 兼容旧配置
|
||
$wechat_setting = getConfig('wechat_setting');
|
||
if (!empty($wechat_setting) && !empty($wechat_setting['appid'])) {
|
||
$appid = $wechat_setting['appid'];
|
||
} else if (!empty($old_config) && !empty($old_config['appid'])) {
|
||
$appid = $old_config['appid'];
|
||
}
|
||
}
|
||
|
||
return [
|
||
'merchant' => $merchant,
|
||
'appid' => $appid
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 获取固定的微信支付配置(基于订单前缀)
|
||
*
|
||
* @param string $order_prefix 订单前缀,如果提供则返回对应前缀的商户信息
|
||
* @return array 包含固定商户信息和appid
|
||
*/
|
||
public static function getFixedWxPayConfig($order_prefix = '')
|
||
{
|
||
// 获取当前域名对应的小程序配置
|
||
$miniprogram = \app\common\helper\MiniprogramHelper::getMiniprogramConfig();
|
||
$weixinpay_setting = getConfig('weixinpay_setting');
|
||
|
||
// 尝试查找与订单前缀匹配的商户
|
||
$merchant = null;
|
||
if (!empty($order_prefix) && !empty($weixinpay_setting) && !empty($weixinpay_setting['merchants'])) {
|
||
foreach ($weixinpay_setting['merchants'] as $m) {
|
||
if (!empty($m['order_prefix']) && $m['order_prefix'] === $order_prefix) {
|
||
$merchant = $m;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有找到匹配的商户,则使用随机选择
|
||
if (empty($merchant)) {
|
||
return self::getWxPayConfig();
|
||
}
|
||
|
||
// 获取微信AppID - 优先使用小程序配置中的AppID
|
||
$appid = '';
|
||
if (!empty($miniprogram) && !empty($miniprogram['appid'])) {
|
||
$appid = $miniprogram['appid'];
|
||
} else {
|
||
// 兼容旧配置
|
||
$wechat_setting = getConfig('wechat_setting');
|
||
if (!empty($wechat_setting) && !empty($wechat_setting['appid'])) {
|
||
$appid = $wechat_setting['appid'];
|
||
} else {
|
||
$old_config = getConfig('weixinpay');
|
||
if (!empty($old_config) && !empty($old_config['appid'])) {
|
||
$appid = $old_config['appid'];
|
||
}
|
||
}
|
||
}
|
||
|
||
return [
|
||
'merchant' => $merchant,
|
||
'appid' => $appid
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 从订单号中提取商户前缀
|
||
*
|
||
* @param string $order_no 订单号(格式如 MH_ABC20240529...)
|
||
* @return string|null 商户前缀,如果无法提取则返回null
|
||
*/
|
||
public static function extractOrderPrefix($order_no)
|
||
{
|
||
if (strpos($order_no, 'MH_') === 0) {
|
||
// 尝试提取MH_后的字符作为商户前缀
|
||
// 商户前缀长度为3,如果有小程序前缀则总长度为5(3+2)
|
||
$totalPrefix = substr($order_no, 3, 5);
|
||
|
||
// 提取商户前缀(前3位)
|
||
$merchantPrefix = substr($totalPrefix, 0, 3);
|
||
|
||
// 如果有足够长度,可能包含小程序前缀
|
||
if (strlen($totalPrefix) >= 5) {
|
||
// 提取小程序前缀(后2位)
|
||
$miniprogramPrefix = substr($totalPrefix, 3, 2);
|
||
|
||
// 使用数组返回,包含商户前缀和小程序前缀
|
||
return [
|
||
'merchant_prefix' => $merchantPrefix,
|
||
'miniprogram_prefix' => $miniprogramPrefix
|
||
];
|
||
}
|
||
|
||
// 只有商户前缀,没有小程序前缀
|
||
if (!empty($merchantPrefix) && strlen($merchantPrefix) === 3) {
|
||
return ['merchant_prefix' => $merchantPrefix];
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
}
|