setting = $this->getPaySetting(); } /** * @return void */ public function setIsPayGroup(PaymentTrade $trade) { $trade->is_pay_group = 1; } /** * 当前支付订单钱包是否符合进行组合支付 * * @param PaymentTrade $trade * @param array $wallet * @return boolean */ public function isConformOfWallteByTrade(PaymentTrade $trade, array $wallet) { // 没有订单直接返回 if (empty($trade)) return []; // 是否开启组合支付 if (!($this->isOpenMixedPay())) return []; // 判断余额是否足够支付 if ($this->isSufficientOfwallet($trade, $wallet)) return []; return [ 'balance' => $this->isBalanceEnable(), 'score' => $this->isScoreEnable(), ]; } /** * 重组支付方式列表,添加余额和积分是否支持组合支付的标识 * * @param PaymentTrade|null $trade 支付订单 * @param array $list 支付方式列表 * @param array $wallet 钱包 * @param integer $source 来源 1:商品订单;2:余额充值;3:佣金提现;4:余额提现 * @return array */ public function getPayTypeList($trade, array $list, array $wallet, int $source = 1): array { // 给支付方式列表添加钱包支付类型标识 $list = $this->setPayListWalletType($list); // 来源不是商品订单直接返回 if ($source != 1) return $list; // 没有订单直接返回 if (empty($trade)) return $list; // 判断是否已经扣除钱包进行在线支付 if ($trade->isMixedPay() && $trade->getWalletPayItem()->isPay()) { // return $this->getOnlinePayList($list); // 返回所有在线支付方式 return $this->getCurrOnlinePayList($list, $trade); // 返回当前在线支付方式 } // 是否开启组合支付 if (!($this->isOpenMixedPay())) return $list; // 判断余额是否足够支付 if ($this->isSufficientOfwallet($trade, $wallet)) return $list; return array_map(function($item) use ($trade, $wallet) { // 判断商品独立设置是否开启组合支付 $isGoodsMixed = true; if (!empty($trade->limit_payment)) { $limit_payment = json_decode($trade->limit_payment, true); if (empty($limit_payment['MIXED'])) $isGoodsMixed = false; } $item['is_enable_group'] = 0; if ((isset($item['pay_type']) && $item['pay_type'] == PayTypeEnum::BALANCE) && $isGoodsMixed && $this->isBalanceEnable() && $this->isPaymentInsufficientByBalance($trade, $wallet)) { $item['unpaid_money'] = $this->getUnpaidBalance($trade, $wallet); $item['is_enable_group'] = 1; } if (isset($item['pay_type']) && $item['pay_type'] == PayTypeEnum::SCORE && $isGoodsMixed && $this->isScoreEnable() && $this->isPaymentInsufficientByScore($trade, $wallet)) { $item['unpaid_money'] = $this->getUnpaidScore($trade, $wallet); $item['is_enable_group'] = 1; } //判断消费卡 if (isset($item['pay_type']) && $item['pay_type'] == PayTypeEnum::CONSUMER_CARD && $isGoodsMixed && $item['is_enable_mixed_pay'] == 1 && $this->isPaymentInsufficientByConsumerCard($trade, $wallet)) { $item['unpaid_money'] = $this->getUnpaidConsumerCard($trade, $wallet); $item['is_enable_group'] = 1; } // 判断是否支持在线支付 if (in_array($item['pay_type'], self::ONLINE_TYPES)) { $item['is_mixed_online'] = 1; } // 不支持「汇付-快捷支付」 if (($item['pay_type'] == PayTypeEnum::HUIFUPAY && ($item['trade_type'] == 'fast_pay' || $item['trade_type'] == 'fastpay'))) { $item['is_mixed_online'] = 0; } return $item; }, $list); } /** * 给支付方式列表添加钱包支付类型标识 * * @param array $list * @return array */ public function setPayListWalletType(array $list): array { return array_map(function($item) { in_array($item['pay_type'], self::WALLET_TYPES) ? $item['is_wallet'] = 1 : $item['is_wallet'] = 0; return $item; }, $list); } /** * 创建组合支付子订单项 * * @param PaymentTrade $trade * @param array $pay_types * @return boolean */ public function createTradeItem(PaymentTrade $trade, array $pay_types, array $trade_type) { if ($this->isBalancePay($pay_types)) $pay_fee = $this->createBalanceTradeItem($trade); if ($this->isScorePay($pay_types)) $pay_fee = $this->createScoreTradeItem($trade); if ($this->isConsumerCardPay($pay_types)) $pay_fee = $this->createConsumerCardTradeItem($trade); // 未返回钱包支付金额则抛出异常 if (!isset($pay_fee)) throw new Exception('组合支付子订单项创建失败'); // 在线支付方式 $online_pay_type = $this->getOnlinePayType($pay_types); // 剩余支付金额 $left_fee = bcsub($trade->pay_fee, $pay_fee, 2); $this->createOnlineTradeItem($trade, $online_pay_type, $left_fee, $trade_type[$online_pay_type] ?? ''); } /** * 获取支付 * * @param array $pay_types * @param integer $pay_type * @return string * @throws Exception */ public function getTradeType(array $pay_types, int $pay_type) { if (isset($pay_types[$pay_type])) { return $pay_types[$pay_type]; } throw new Exception('选择交易方式异常'); } /** * 获取在线支付方式(余额和积分以外的) * * @param array $pay_types * @return int * @throws Exception */ public function getOnlinePayType(array $pay_types): int { if (count($left = array_diff($pay_types, self::WALLET_TYPES)) == 1) { return current($left); } throw new Exception('剩余支付方式异常'); } /** * 获取钱包支付方式 * * @param array $pay_types * @return int * @throws Exception */ public function getWalletPayType(array $pay_types): int { if (count($right = array_intersect($pay_types, self::WALLET_TYPES)) == 1) { return current($right); } throw new Exception('钱包支付方式异常'); } /** * 创建余额支付子订单项并返回扣除的余额 * * @param PaymentTrade $trade * @return float */ public function createBalanceTradeItem(PaymentTrade $trade) { $wallet = UserWallet::getUserWallet($trade->user_id); if ($this->isSufficientOfwallet($trade, $wallet)) { throw new Exception('余额或者积分充足, 无法进行组合支付'); } // 余额支付 $balance = $wallet['balance']; if ($balance == 0) { throw new Exception('余额不足, 无法进行组合支付'); } $trade->setWalletPayItem(PayTypeEnum::BALANCE, $balance); return $balance; } /** * 创建积分支付子订单项并返回扣除的积分 * * @param PaymentTrade $trade * @return float */ public function createScoreTradeItem(PaymentTrade $trade) { $wallet = UserWallet::getUserWallet($trade->user_id); if ($this->isSufficientOfwallet($trade, $wallet)) { throw new Exception('余额或者积分充足, 无法进行组合支付'); } // 积分支付 $score = $wallet['total_score']; if ($score == 0) { throw new Exception('积分不足, 无法进行组合支付'); } $trade->setWalletPayItem(PayTypeEnum::SCORE, $score); return $score; } /** * 创建消费卡支付子订单项并返回扣除的金额 * * @param PaymentTrade $trade * @return float */ public function createConsumerCardTradeItem(PaymentTrade $trade) { // $wallet = UserWallet::getUserWallet($trade->user_id); //获取消费卡金额 $wallet = \addons\ScoreGame\common\models\ScoreGameUserWallet::getUserWalletType($trade->user_id, \addons\ScoreGame\common\enums\ScoreGameEnum::WALLET_TYPE_CONSUMER_CARD, 0); //判断余额、积分、消费卡余额是否充足 if ($this->isSufficientOfwallet($trade, $wallet) && $wallet['num'] > $trade->pay_fee) { throw new Exception('余额、积分或消费卡金额充足, 无法进行组合支付'); } // 消费卡支付 $consumer_card = $wallet['num'] ?? 0; if ($consumer_card == 0) { throw new Exception('消费卡金额不足, 无法进行组合支付'); } $trade->setWalletPayItem(PayTypeEnum::CONSUMER_CARD, $consumer_card); return $consumer_card; } /** * 创建在线支付子订单项 * * @param PaymentTrade $trade * @param integer $pay_type * @param float $pay_fee * @param string $trade_type * @return boolean */ public function createOnlineTradeItem(PaymentTrade $trade, int $pay_type, float $pay_fee, string $trade_type = '') { return $trade->setOnlinePayItem($pay_type, $pay_fee, $trade_type); } /** * @param array $pay_types * @return boolean */ public function isBalancePay(array $pay_types): bool { return in_array(PayTypeEnum::BALANCE, $pay_types); } /** * @param array $pay_types * @return boolean */ public function isScorePay(array $pay_types): bool { return in_array(PayTypeEnum::SCORE, $pay_types); } /** * @param array $pay_types * @return boolean */ public function isConsumerCardPay(array $pay_types): bool { return in_array(PayTypeEnum::CONSUMER_CARD, $pay_types); } /** * 仅返回在线支付方式 * * @return array */ public function getOnlinePayList(array $list) { return array_filter($list, function ($item) { return !in_array($item['pay_type'], self::WALLET_TYPES); }); } /** * 仅返回绑定的在线支付方式 * * @return array */ public function getCurrOnlinePayList(array $list, PaymentTrade $trade) { return array_filter($list, function ($item) use ($trade) { return in_array($item['pay_type'], [$trade->getOnlinePayItem()->pay_type]); }); } /** * @return array */ protected function getPaySetting() { $config = Yii::$app->services->setting->mall->get($this->mall_id, 'pay', true); return array_map(function($item) { return Json::decode($item); }, $config); } /** * @return boolean */ protected function isOpenMixedPay() { return isset($this->setting['mixed']['status']) && $this->setting['mixed']['status']; } /** * 钱包的积分或者余额是否足够支付 * * @param PaymentTrade $trade * @param array $wallet * @return boolean */ protected function isSufficientOfwallet(PaymentTrade $trade, array $wallet) { if (isset($wallet['consumer_card'])) { return $wallet['balance'] > $trade->pay_fee && $wallet['total_score'] > $trade->pay_fee && $wallet['consumer_card'] > $trade->pay_fee; } return $wallet['balance'] > $trade->pay_fee && $wallet['total_score'] > $trade->pay_fee; } /** * 余额是否开启组合支付 * * @return boolean */ protected function isBalanceEnable() { return isset($this->setting['balance']['is_enable_group']) && $this->setting['balance']['is_enable_group']; } /** * 积分是否开启组合支付 * * @return boolean */ protected function isScoreEnable() { return isset($this->setting['score']['is_enable_group']) && $this->setting['score']['is_enable_group']; } /** * 余额支付是否充足 * @param PaymentTrade $trade * @param array $wallet * @return boolean */ protected function isPaymentInsufficientByBalance(PaymentTrade $trade, array $wallet) { return $wallet['balance'] > 0 && bcsub($trade->pay_fee, $wallet['balance'], 2) > 0; } /** * 积分支付是否充足 * * @param PaymentTrade $trade * @param array $wallet * @return boolean */ protected function isPaymentInsufficientByScore(PaymentTrade $trade, array $wallet) { return $wallet['total_score'] > 0 && bcsub($trade->pay_fee, $wallet['total_score'], 2) > 0; } /** * 消费卡支付是否充足 * * @param PaymentTrade $trade * @param array $wallet * @return boolean */ protected function isPaymentInsufficientByConsumerCard(PaymentTrade $trade, array $wallet) { return $wallet['consumer_card'] > 0 && bcsub($trade->pay_fee, $wallet['consumer_card'], 2) > 0; } /** * 获取未支付的余额 * * @param PaymentTrade $trade * @param array $wallet * @return float */ protected function getUnpaidBalance(PaymentTrade $trade, array $wallet) { return bcsub($trade->total_fee, $wallet['balance'], 2); } /** * 获取未支付的积分 * * @param PaymentTrade $trade * @param array $wallet * @return float */ protected function getUnpaidScore(PaymentTrade $trade, array $wallet) { return bcsub($trade->total_fee, $wallet['total_score'], 2); } /** * 获取未支付的消费卡 * * @param PaymentTrade $trade * @param array $wallet * @return float */ protected function getUnpaidConsumerCard(PaymentTrade $trade, array $wallet) { return bcsub($trade->total_fee, $wallet['consumer_card'], 2); } }