Example #1
0
 /**
  * @brief 获取关联的交易记录
  *
  * @return  public function 
  * @retval   
  * @see 
  * @note 
  * @author 吕宝贵
  * @date 2015/12/17 20:31:11
  **/
 public function getTrans()
 {
     return $this->hasOne(Trans::className(), ['id' => 'trans_id']);
 }
 /**
  * @brief 充值成功处理,第三方的只有充值成功通知,在支持成功之后的业务逻辑处理,支付宝和微信的所有回告都应该是充值接口
  *
  * @param string $callback 回调函数,仅仅对需要对订单进行逻辑处理的操作有效,需要添加订单id为参数
  * @return Trans object 返回充值支付的交易记录 
  * @see 
  * @note 
  * @author 吕宝贵
  * @date 2015/12/06 21:14:32
  **/
 public function processChargePaySuccess($receivable)
 {
     $receivable->status = Receivable::PAY_STATUS_FINISHED;
     if (!$receivable->save()) {
         return false;
     }
     //获取交易记录
     $trans = Trans::findOne($receivable->trans_id);
     if (!$trans) {
         return false;
     }
     //充值型trans,直接成功,设置交易信息
     $trans->status = Trans::PAY_STATUS_FINISHED;
     if (!$trans->save()) {
         return false;
     }
     //为用户账户充值,充值成功即为一个事物,后续的购买判断在controller里面完成
     $userAccount = $this->getUserAccount($trans->to_uid);
     if (!$userAccount->plus($trans->total_money, $trans->id, $trans->trans_type_id, '充值', '账户充值')) {
         return false;
     }
     return $trans;
 }
Example #3
0
 /**
  * @brief 用户帐户变动的核心函数,所有的变动都需要通过此函数来记录
  *
  * @return  public function 
  * @retval   
  * @see 
  * @note 
  * @author 吕宝贵
  * @date 2015/12/30 14:39:00
  **/
 protected function balance($uid, $balanceType, $money, $transId, $description, $currency)
 {
     $freezeCat = false;
     $freeze = null;
     $trans = null;
     Yii::warning('进入balance页面', __METHOD__);
     Yii::warning('uid and balanceType:' . $uid . '---' . $balanceType, __METHOD__);
     if (in_array($balanceType, [UserAccount::BALANCE_TYPE_FREEZE, UserAccount::BALANCE_TYPE_UNFREEZE, UserAccount::BALANCE_TYPE_FINISH_FREEZE])) {
         $freezeCat = true;
         $freeze = Freeze::findOne($transId);
         if (!$freeze) {
             $this->addError('trans', '不存在该交易订单');
             return false;
         }
     } else {
         //根据交易号查找对应的交易
         $trans = Trans::findOne($transId);
         if (!$trans) {
             $this->addError('trans', '不存在该交易订单');
             return false;
         }
     }
     Yii::warning('获取用户帐户', __METHOD__);
     $userAccount = $this->getUserAccount($uid);
     Yii::warning('判断账户变更类型', __METHOD__);
     switch ($balanceType) {
         case UserAccount::BALANCE_TYPE_PLUS:
             $userAccount->plus($money);
             break;
         case UserAccount::BALANCE_TYPE_MINUS:
             $userAccount->minus($money);
             break;
         case UserAccount::BALANCE_TYPE_FREEZE:
             Yii::warning('进入帐号金额冻结');
             $userAccount->freeze($money);
             break;
         case UserAccount::BALANCE_TYPE_UNFREEZE:
             $userAccount->unFreeze($money);
             break;
         case UserAccount::BALANCE_TYPE_FINISH_FREEZE:
             $userAccount->finishFreeze($money);
             break;
         default:
             $this->addError(__METHOD__, '不支持提交的账户操作类型');
             return false;
     }
     if ($userAccount->save()) {
         //记录账单
         Yii::warning('产生用户账单', __METHOD__);
         $bill = new Bill();
         $bill->uid = $userAccount->uid;
         if (!$freezeCat) {
             $bill->trans_id = $trans->id;
             $bill->trans_type_id = $trans->trans_type_id;
             $bill->trans_type_name = $trans->transType->name;
         } else {
             $bill->trans_id = $freeze->id;
         }
         $bill->money = $money;
         $bill->balance_type = $balanceType;
         $bill->currency = $currency;
         $bill->description = $description;
         if (!$bill->save()) {
             $this->addErrors($bill->getErrors());
             return false;
         }
         Yii::warning('产生账户快照', __METHOD__);
         //账户快照产生
         $accountLog = new UserAccountLog();
         $accountLog->uid = $userAccount->uid;
         $accountLog->account_type = $userAccount->type;
         $accountLog->currency = $currency;
         if (!$freezeCat) {
             $accountLog->trans_id = $trans->id;
         } else {
             $accountLog->trans_id = $freeze->id;
         }
         $accountLog->balance = $userAccount->balance;
         $accountLog->deposit = $userAccount->deposit;
         $accountLog->frozen_money = $userAccount->frozen_money;
         $accountLog->balance_type = $balanceType;
         $accountLog->trans_money = $money;
         $accountLog->trans_desc = $description;
         Yii::warning('保存账户信息', __METHOD__);
         if (!$accountLog->save()) {
             //$this->addErrors($accountLog->getErrors());
             Yii::warning('保存账户快照失败', __METHOD__);
             Yii::warning($accountLog->getErrors(), __METHOD__);
             return false;
         } else {
             Yii::warning('保存账户快照成功', __METHOD__);
             return true;
         }
     } else {
         return false;
     }
 }
Example #4
0
 /**
  * @brief 充值成功处理,第三方的只有充值成功通知,在支持成功之后的业务逻辑处理,支付宝和微信的所有回告都应该是充值接口
  *
  * @param string $callback 回调函数,仅仅对需要对订单进行逻辑处理的操作有效,需要添加订单id为参数
  * @return Trans object 返回充值支付的交易记录 
  * @see 
  * @note 
  * @author 吕宝贵
  * @date 2015/12/06 21:14:32
  **/
 public function processChargePaySuccess($transId)
 {
     //获取交易记录
     $trans = Trans::findOne($transId);
     if (!$trans) {
         $this->addError(__METHOD__, '对应的交易记录不存在');
         return false;
     }
     //充值型trans,直接成功,设置交易信息
     $trans->status = Trans::PAY_STATUS_FINISHED;
     if (!$trans->save()) {
         return false;
     }
     //为用户账户充值,充值成功即为一个事物,后续的购买判断在controller里面完成
     $userAccount = $this->getUserAccount($trans->from_uid);
     if (!$this->plus($userAccount->uid, $trans->total_money, $trans->id, '用户账户充值')) {
         $this->addError(__METHOD__, '为账户充值时发生错误');
         return false;
     }
     return $trans;
 }
Example #5
0
 /**
  * based on the pay form ,generate Trans, this method can be rewrite by the child class
  *
  * @return Trans 返回trans实例
  */
 public function getTrans()
 {
     $this->booking = Booking::findOne(['bid' => $this->booking_id, 'q_uid' => Yii::$app->user->identity['uid']]);
     if (empty($this->booking)) {
         $this->addError('booking_id', '指定的订单不存在');
         return false;
     }
     //如果预定已经成功支付,则不允许用户进行第二次支付
     if ($this->booking->status > BookingStatus::PAYSUCCESS) {
         $this->addError('booking_id', '订单已支付!');
         return false;
     }
     if (empty($this->booking->trans_id)) {
         $this->trans = $this->generateTrans();
     } else {
         $this->trans = Trans::findOne($this->booking->trans_id);
     }
     return $this->trans;
 }
 /**
  * @brief 处理充值消息通知的action,对于notify来讲,不需要做页面跳转,只需要针对不同的支付方式返回对应的状态
  *
  * @return  public function
  * @retval
  * @see
  * @note
  * @author 吕宝贵
  * @date 2015/12/09 23:30:24
  **/
 protected function processPayNotify($payChannelId)
 {
     $channels = PayChannel::find()->select(['id', 'name', 'alias'])->indexBy('id')->all();
     //回调的时候,appId根据返回的参数来确定
     $payment = new Payment($channels[$payChannelId]['alias']);
     //判断订单是否支付成功, 如果成功则进入成功处理逻辑
     if ($payment->checkPayStatus() === false) {
         Yii::error('支付结果检查失败!');
         $payment->replyFailureToServer();
         exit;
     }
     $receivable = $payment->getReceivable();
     if (!$receivable) {
         Yii::error('找不到对应的收款单!');
         $payment->replyFailureToServer();
         exit;
     } else {
         //如果收款单的付款成功事件已被处理,则直接返回服务器成功
         if ($receivable->hasPaySucceeded()) {
             Yii::info('收款单已处理!');
             $payment->replySuccessToServer();
             exit;
         }
     }
     //如果checkPayStatus返回成功,代表支付成功,此时进行实际的业务处理
     $transaction = Yii::$app->db->beginTransaction();
     //设置支付的成功和失败回调函数,此处处理的主要是账户体系的逻辑
     $handlers = ['paySuccessHandler' => [Yii::$app->account, 'processChargePaySuccess'], 'payFailHandler' => [Yii::$app->account, 'processPayFailure']];
     $trans = null;
     //业务逻辑处理,此处应当判断订单是否成功
     if ($transId = $payment->processNotify($handlers)) {
         //充值交易完成,在commit之后,需要回告给服务器
         $transaction->commit();
         $trans = Trans::findOne($transId);
         Yii::info('交易id为:' . $transId, 'account-pay-notify');
         Yii::info('成功处理用户充值逻辑', 'account-pay-notify');
         //如果交易存在关联的交易,则查询关联交易的信息,并尝试支付相应的关联订单,需要提供订单的回调函数
         if ($trans->trans_id_ext) {
             //如果存在关联订单,需要开启新事务处理相关订单
             Yii::info('存在关联交易,处理关联交易逻辑', 'account-pay-notify');
             $transaction = Yii::$app->db->beginTransaction();
             $transOrder = Trans::findOne($trans->trans_id_ext);
             if (!$transOrder) {
                 $transaction->rollback();
                 Yii::warning('关联交易查询失败,并不存在该关联交易订单, 退出购买逻辑', 'account-pay-notify');
                 exit;
             }
             if (Yii::$app->account->pay($transOrder)) {
                 //如果关联交易为产品购买
                 if ($transOrder->trans_type_id == Trans::TRANS_TYPE_TRADE) {
                     $booking = Booking::findOne(['bid' => $transOrder->trans_id_ext]);
                     if (!$booking) {
                         $transaction->rollback();
                         Yii::warning('查询关联预订失败', 'account-pay-notify');
                         throw new LBUserException('查询关联订单信息失败', 2);
                         exit;
                     }
                     Yii::info('关联预订信息获取成功', 'account-pay-notify');
                     $callbackData = ['bid' => $booking->bid, 'trans_id' => $booking->trans_id];
                     //此处的回调为业务上的订单处理回调
                     if (!Booking::processPaySuccess($callbackData)) {
                         $transaction->rollback();
                         Yii::warning('关联预订处理操作失败', 'account-pay-notify');
                         throw new LBUserException('订单支付成功回调处理失败', 3);
                         exit;
                     }
                     Yii::info('关联预订相关回调处理成功', 'account-pay-notify');
                 }
                 $transaction->commit();
                 Yii::info('提交事务...', 'account-pay-notify');
                 //页面跳转逻辑
             } else {
                 $transaction->rollback();
                 Yii::error('用户付款失败', 'account-pay-notify');
                 exit;
             }
         } else {
             Yii::info('交易没有关联订单:', 'account-pay-notify');
             Yii::info($trans);
         }
     } else {
         $transaction->rollback();
         Yii::warning('处理支付成功失败...', 'account-pay-notify');
         $payment->replyFailureToServer();
         exit;
     }
     Yii::info('交易成功处理...', 'account-pay-notify');
     $payment->replySuccessToServer();
     exit;
 }