<?php /** * Created by IntelliJ IDEA. * 奖品兑换 * User: zhoutao * Date: 2016/12/07 * Time: 上午14:27 */ namespace Api\Controller\Mall; use Com\PackageValidate; use Common\Model\ConvertModel; use Common\Model\PrizeModel; use Common\Service\ConvertProcessService; use Common\Service\ConvertService; use Common\Service\PrizeService; use VcySDK\Integral; use VcySDK\Message; use VcySDK\Service; class PrizeConvertController extends AbstractController { /** 单个兑换库存操作数 */ const SINGLE_EXC_NUMBE = -1; /** @var array 奖品数据 */ protected $prizeData = []; public function before_action($action = '') { // 开启自动获取 $this->autoGetData = true; $this->field = [ 'ia_id' => [ 'require' => true, 'verify' => 'intval', 'cn' => '奖品ID', ], 'applicant_phone' => [ 'require' => true, 'verify' => 'intval', 'cn' => '手机号', 'regexp' => '/(^0?1[2,3,4,5,6,7,8,9]\d{9}$)|(^(\d{3,4})-(\d{7,8})$)|(^(\d{7,8})$) |(^(\d{3,4})-(\d{7,8})-(\d{1,4})$)|(^(\d{7,8})-(\d{1,4})$)/' ], 'applicant_email' => [ 'require' => false, 'verify' => 'strval', 'cn' => '邮箱', 'regexp' => '/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/' ], 'applicant_mark' => [ 'require' => false, 'verify' => 'strval', 'cn' => '备注', 'maxLength' => 60 ], ]; return parent::before_action($action); } public function Index() { // 业务逻辑验证 $this->verifyBusinessLogic(); $prizeServ = new PrizeService(); $convertServ = new ConvertService(); $convertProcessServ = new ConvertProcessService(); $integralSdk = new Integral(Service::instance()); // 兑换编号 $number = $this->makeNumber(); // 申请表ID $ic_id = 0; // 开启事务 $prizeServ->start_trans(); $convertServ->start_trans(); $convertProcessServ->start_trans(); try { // 更改库存 $changeReserve = $prizeServ->changeReserve($this->data['ia_id'], self::SINGLE_EXC_NUMBE); // 没有库存了 if ($changeReserve === 0) { E('_ERR_PRIZE_CONVERT_HAVENT_RESERVE'); return false; } // 写入申请表 $ic_id = $convertServ->insert([ 'uid' => $this->uid, 'ia_id' => $this->data['ia_id'], 'number' => $number, 'integral' => $this->prizeData['integral'], 'applicant_phone' => $this->data['applicant_phone'], 'applicant_email' => empty($this->data['applicant_email']) ? '' : $this->data['applicant_email'], 'applicant_mark' => empty($this->data['applicant_mark']) ? '' : $this->data['applicant_mark'], ]); // 发送消息 $smgSdk = new Message(Service::instance()); $msgParam = [ 'toUser' => $this->uid, 'articles' => [ [ 'title' => '您已成功发起奖品兑换申请,请等待后台管理员审核', 'description' => "奖品名称:" . $this->prizeData['name'] . "\n兑换编号:" . $number . "\n申请时间:" . rgmdate(NOW_TIME, 'Y-m-d H:i'), 'url' => frontUrl('/app/page/integral/apply-detail', ['ic_id' => $ic_id]), ] ], ]; $smgSdk->sendNews($msgParam); // 积分修改 $ucOperate = $integralSdk->integralExchange([ 'memUid' => $this->uid, 'integral' => $this->prizeData['integral'], 'milOptType' => Integral::MANUAL_EXCHAGE_INTEGRAL, 'businessId' => $ic_id, 'prizeName' => $this->prizeData['name'], 'remark' => '【申请兑换】' . $this->prizeData['name'], 'milCreateMemUid' => $this->uid, 'milCreateMemUsername' => $this->_login->user['memUsername'], 'msgIdentifier' => APP_IDENTIFIER, // 动作标识 积分中心 根据 UC 配置的 'businessKey' => 'integral_center', 'businessAct' => 'convert', ]); // 更新申请表数据 $convertServ->update($ic_id, [ 'ucintegral_id' => $ucOperate['milId'], // 在末尾加上主键ID 为了唯一 'number' => $number . settype($ic_id, 'string') ]); // 写入申请进度表 $convertProcessServ->insert([ 'ic_id' => $ic_id, 'uid' => $this->uid, 'operating_time' => MILLI_TIME, // 扣减积分 'integral' => $this->prizeData['integral'] * -1, 'mark' => empty($this->data['applicant_mark']) ? '' : $this->data['applicant_mark'], ]); // 提交事务 $prizeServ->commit(); $convertServ->commit(); $convertProcessServ->commit(); } catch (\Exception $e) { \Think\Log::record( '兑换奖品失败!' . var_export($e, true) . '提交信息:' . var_export($this->data, true) . '奖品信息:' . var_export($this->prizeData, true)); // 数据库回滚 $prizeServ->rollback(); $convertServ->rollback(); $convertProcessServ->rollback(); // 积分冲正 if (isset($ucOperate['milId'])) { $integralSdk->integralExchange([ 'memUid' => $this->uid, 'integral' => $this->prizeData['integral'], 'milOptType' => Integral::MANUAL_EXCHAGE_BACK_INTEGRAL, 'isAdmin' => Integral::IS_ADMIN_FALSE, 'businessId' => $ic_id, 'prizeName' => $this->prizeData['name'], 'remark' => '【兑换出错】' . $this->prizeData['name'], 'milCreateMemUid' => $this->uid, 'milCreateMemUsername' => $this->_login->user['memUsername'], 'msgIdentifier' => APP_IDENTIFIER, // 动作标识 积分中心 根据 UC 配置的 'businessKey' => 'integral_center', 'businessAct' => 'convert_back', ]); } E($e->getMessage()); return false; } // 返回成功后的申请ID $this->_result = [ 'ic_id' => $ic_id ]; return true; } /** * 业务逻辑 判断 * @return bool */ protected function verifyBusinessLogic() { // 获取奖品数据 $prizeServ = new PrizeService(); $this->prizeData = $prizeServ->get($this->data['ia_id']); // 已删除 if (empty($this->prizeData)) { E('_ERR_PRIZE_CONVERT_IS_DELETED'); return false; } // 已下架 if ($this->prizeData['on_sale'] == PrizeModel::OFF_SALE) { E('_ERR_PRIZE_CONVERT_IS_OFFSALE'); return false; } // 没库存 if ($this->prizeData['reserve'] <= 0) { E('_ERR_PRIZE_CONVERT_HAVENT_RESERVE'); return false; } // 兑换范围 if (!$this->verifyArea($this->prizeData)) { E('_ERR_PRIZE_CONVERT_NOT_IN_AREA'); return false; }; // 如果有次数限制 if ($this->prizeData['times'] != PrizeModel::MEAN_TIMES_NO_LIMIT) { // 获取已经兑换的数据 $convertServ = new ConvertService(); $excTotal = $convertServ->count_by_conds([ 'ia_id' => $this->data['ia_id'], 'uid' => $this->uid, 'convert_status' => [ ConvertModel::CONVERT_STATUS_ING, ConvertModel::CONVERT_STATUS_AGREE, ] ]); // 超出次数限制 if ($excTotal >= $this->prizeData['times']) { E('_ERR_OVER_PER_EXC_TIMES'); return false; } } // 判断积分 $integralSdk = new Integral(Service::instance()); $userIntegral = $integralSdk->detail(['memUid' => $this->uid]); if (empty($userIntegral['available']) || $userIntegral['available'] < $this->prizeData['integral']) { E('_ERR_PRIZE_CONVERT_INTEGRAL_NOT_ENOUGH'); return false; } return true; } /** * 生成兑换编号 * @return mixed */ protected function makeNumber() { $number = rgmdate(NOW_TIME, 'YmdHis') . $this->randNumber(); return $number; } /** * 随机生成数字串 * @param int $length 长度 * @return int|string */ protected function randNumber($length = 5) { $numberStr = ''; for ($i = 0; $i < $length; $i ++) { $numberStr += rand(0, 9); } return $numberStr; } }