| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- <?php
- namespace services\common;
- use common\enums\PayTypeEnum;
- use common\events\addons\PaymentTypeEvent;
- use Yii;
- use yii\helpers\Json;
- use common\models\common\PaymentTrade;
- use common\models\user\UserWallet;
- use Exception;
- /**
- * 组合支付服务类
- * @package services\common
- */
- final class MixedPayService extends BaseService
- {
- /**
- * @var array
- */
- protected $setting;
- /**
- * 钱包支付方式
- */
- const WALLET_TYPES = [
- PayTypeEnum::BALANCE,
- PayTypeEnum::SCORE,
- PayTypeEnum::CONSUMER_CARD,
- ];
- /**
- * 目前支持进行组合支付的在线支付方式
- */
- const ONLINE_TYPES = [
- PayTypeEnum::WECHAT,
- PayTypeEnum::ALI,
- PayTypeEnum::JOINPAY,
- PayTypeEnum::HUIFUPAY,
- // PayTypeEnum::JOINPAY_FAST_PAY
- ];
- public function __construct($config)
- {
- parent::__construct($config);
- $this->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);
- }
- }
|