mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-20 19:07:03 +08:00
疫情期间更新
This commit is contained in:
parent
7a4aa88218
commit
1d40766a2a
@ -20,7 +20,7 @@ class CleanLogTask extends Task
|
||||
$this->cleanVodLog();
|
||||
$this->cleanStorageLog();
|
||||
$this->cleanAlipayLog();
|
||||
$this->cleanWechatLog();
|
||||
$this->cleanWxpayLog();
|
||||
$this->cleanRefundLog();
|
||||
}
|
||||
|
||||
@ -115,9 +115,9 @@ class CleanLogTask extends Task
|
||||
/**
|
||||
* 清理微信支付服务日志
|
||||
*/
|
||||
protected function cleanWechatLog()
|
||||
protected function cleanWxpayLog()
|
||||
{
|
||||
$this->cleanLog('wechat', 30);
|
||||
$this->cleanLog('wxpay', 30);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,8 +3,8 @@
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Services\Alipay as AlipayService;
|
||||
use App\Services\Wechat as WechatService;
|
||||
use App\Services\Payment\Alipay as AlipayService;
|
||||
use App\Services\Payment\Wxpay as WxpayService;
|
||||
use Phalcon\Cli\Task;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
@ -23,8 +23,8 @@ class CloseTradeTask extends Task
|
||||
foreach ($trades as $trade) {
|
||||
if ($trade->channel == TradeModel::CHANNEL_ALIPAY) {
|
||||
$this->closeAlipayTrade($trade);
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WECHAT) {
|
||||
$this->closeWechatTrade($trade);
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) {
|
||||
$this->closeWxpayTrade($trade);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,48 +36,38 @@ class CloseTradeTask extends Task
|
||||
*/
|
||||
protected function closeAlipayTrade($trade)
|
||||
{
|
||||
$service = new AlipayService();
|
||||
$alipay = new AlipayService();
|
||||
|
||||
$alyOrder = $service->findOrder($trade->sn);
|
||||
|
||||
if ($alyOrder) {
|
||||
if ($alyOrder->trade_status == 'WAIT_BUYER_PAY') {
|
||||
$service->closeOrder($trade->sn);
|
||||
}
|
||||
}
|
||||
$success = $alipay->close($trade->sn);
|
||||
|
||||
if ($success) {
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
|
||||
$trade->update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭微信交易
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
*/
|
||||
protected function closeWechatTrade($trade)
|
||||
protected function closeWxpayTrade($trade)
|
||||
{
|
||||
$service = new WechatService();
|
||||
$wxpay = new WxpayService();
|
||||
|
||||
$wxOrder = $service->findOrder($trade->sn);
|
||||
|
||||
if ($wxOrder) {
|
||||
if ($wxOrder->trade_state == 'NOTPAY') {
|
||||
$service->closeOrder($trade->sn);
|
||||
}
|
||||
}
|
||||
$success = $wxpay->close($trade->sn);
|
||||
|
||||
if ($success) {
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
|
||||
$trade->update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找待关闭交易
|
||||
*
|
||||
* @param int $limit
|
||||
* @return Resultset|ResultsetInterface
|
||||
* @return ResultsetInterface|Resultset|TradeModel[]
|
||||
*/
|
||||
protected function findTrades($limit = 5)
|
||||
{
|
||||
|
@ -41,11 +41,13 @@ class LearningTask extends Task
|
||||
if (!$requestIds) return;
|
||||
|
||||
foreach ($requestIds as $requestId) {
|
||||
$itemKey = $syncer->getItemKey($requestId);
|
||||
$this->handleLearning($itemKey);
|
||||
}
|
||||
|
||||
$this->redis->sRem($syncKey, ...$requestIds);
|
||||
$itemKey = $syncer->getItemKey($requestId);
|
||||
|
||||
$this->handleLearning($itemKey);
|
||||
|
||||
$this->redis->sRem($syncKey, $requestId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
70
app/Console/Tasks/LiveNoticeConsumerTask.php
Normal file
70
app/Console/Tasks/LiveNoticeConsumerTask.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Library\Cache\Backend\Redis as RedisCache;
|
||||
use App\Services\Smser\Live as LiveSmser;
|
||||
use Phalcon\Cli\Task;
|
||||
|
||||
class LiveNoticeConsumerTask extends Task
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RedisCache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @var \Redis
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
$hour = date('h');
|
||||
|
||||
/**
|
||||
* 限定合理的时间范围
|
||||
*/
|
||||
if ($hour < 7 || $hour > 23) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cache = $this->getDI()->get('cache');
|
||||
|
||||
$this->redis = $this->cache->getRedis();
|
||||
|
||||
$providerTask = new LiveNoticeProviderTask();
|
||||
|
||||
$cacheKey = $providerTask->getCacheKey();
|
||||
|
||||
$members = $this->redis->sMembers($cacheKey);
|
||||
|
||||
if (!$members) return;
|
||||
|
||||
$smser = new LiveSmser();
|
||||
|
||||
$now = time();
|
||||
|
||||
foreach ($members as $member) {
|
||||
|
||||
list($chapterId, $userId, $startTime) = explode(':', $member);
|
||||
|
||||
$remove = false;
|
||||
|
||||
if ($now - $startTime < 3600) {
|
||||
$smser->handle($chapterId, $userId, $startTime);
|
||||
$remove = true;
|
||||
}
|
||||
|
||||
if ($now > $startTime) {
|
||||
$remove = true;
|
||||
}
|
||||
|
||||
if ($remove) {
|
||||
$this->redis->sRem($cacheKey, $member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
96
app/Console/Tasks/LiveNoticeProviderTask.php
Normal file
96
app/Console/Tasks/LiveNoticeProviderTask.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Tasks;
|
||||
|
||||
use App\Library\Cache\Backend\Redis as RedisCache;
|
||||
use App\Models\ChapterLive as ChapterLiveModel;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use Phalcon\Cli\Task;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class LiveNoticeProviderTask extends Task
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RedisCache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* @var \Redis
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
public function mainAction()
|
||||
{
|
||||
|
||||
$this->cache = $this->getDI()->get('cache');
|
||||
|
||||
$this->redis = $this->cache->getRedis();
|
||||
|
||||
$tasks = $this->findTasks();
|
||||
|
||||
if ($tasks->count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$values = [];
|
||||
|
||||
foreach ($tasks as $task) {
|
||||
$items = [$task->chapter_id, $task->user_id, $task->start_time];
|
||||
$values[] = implode(':', $items);
|
||||
}
|
||||
|
||||
$key = $this->getCacheKey();
|
||||
|
||||
$lifetime = $this->getLifetime();
|
||||
|
||||
$this->redis->sAdd($key, ...$values);
|
||||
|
||||
$this->redis->expire($key, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ResultsetInterface|Resultset
|
||||
*/
|
||||
protected function findTasks()
|
||||
{
|
||||
$beginTime = strtotime('today');
|
||||
|
||||
$endTime = strtotime('tomorrow');
|
||||
|
||||
/**
|
||||
* 过滤付费和导入用户,减少发送量
|
||||
*/
|
||||
$sourceTypes = [
|
||||
CourseUserModel::SOURCE_CHARGE,
|
||||
CourseUserModel::SOURCE_IMPORT,
|
||||
];
|
||||
|
||||
$rows = $this->modelsManager->createBuilder()
|
||||
->columns(['cu.course_id', 'cu.user_id', 'cl.chapter_id', 'cl.start_time'])
|
||||
->addFrom(ChapterLiveModel::class, 'cl')
|
||||
->join(CourseUserModel::class, 'cl.course_id = cu.course_id', 'cu')
|
||||
->inWhere('cu.source_type', $sourceTypes)
|
||||
->betweenWhere('start_time', $beginTime, $endTime)
|
||||
->getQuery()->execute();
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function getLifetime()
|
||||
{
|
||||
$tomorrow = strtotime('tomorrow');
|
||||
|
||||
$lifetime = $tomorrow - time();
|
||||
|
||||
return $lifetime;
|
||||
}
|
||||
|
||||
public function getCacheKey()
|
||||
{
|
||||
return 'live_notice';
|
||||
}
|
||||
|
||||
}
|
@ -4,16 +4,20 @@ namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Models\Task as TaskModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Services\Smser\Order as OrderSmser;
|
||||
use Phalcon\Cli\Task;
|
||||
use Phalcon\Mvc\Model;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
class ProcessOrderTask extends Task
|
||||
class OrderTask extends Task
|
||||
{
|
||||
|
||||
const TRY_COUNT = 3;
|
||||
@ -30,8 +34,6 @@ class ProcessOrderTask extends Task
|
||||
|
||||
foreach ($tasks as $task) {
|
||||
|
||||
try {
|
||||
|
||||
/**
|
||||
* @var array $itemInfo
|
||||
*/
|
||||
@ -39,6 +41,10 @@ class ProcessOrderTask extends Task
|
||||
|
||||
$order = $orderRepo->findById($itemInfo['order']['id']);
|
||||
|
||||
if (!$order) continue;
|
||||
|
||||
try {
|
||||
|
||||
switch ($order->item_type) {
|
||||
case OrderModel::ITEM_COURSE:
|
||||
$this->handleCourseOrder($order);
|
||||
@ -51,6 +57,12 @@ class ProcessOrderTask extends Task
|
||||
break;
|
||||
}
|
||||
|
||||
$task->status = TaskModel::STATUS_FINISHED;
|
||||
|
||||
$task->update();
|
||||
|
||||
$this->handleOrderNotice($order);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$task->try_count += 1;
|
||||
@ -62,6 +74,13 @@ class ProcessOrderTask extends Task
|
||||
|
||||
$task->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务失败,申请退款
|
||||
*/
|
||||
if ($task->status == TaskModel::STATUS_FAILED) {
|
||||
$this->handleOrderRefund($order);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,6 +162,38 @@ class ProcessOrderTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handleOrderNotice(OrderModel $order)
|
||||
{
|
||||
$smser = new OrderSmser();
|
||||
|
||||
$smser->handle($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderModel $order
|
||||
*/
|
||||
protected function handleOrderRefund(OrderModel $order)
|
||||
{
|
||||
$trade = $this->findFinishedTrade($order->id);
|
||||
|
||||
if (!$trade) return;
|
||||
|
||||
$refund = new RefundModel();
|
||||
|
||||
$refund->subject = $order->subject;
|
||||
$refund->amount = $order->amount;
|
||||
$refund->apply_note = '开通失败,自动退款';
|
||||
$refund->review_note = '自动操作';
|
||||
$refund->user_id = $order->user_id;
|
||||
$refund->order_id = $order->id;
|
||||
$refund->trade_id = $trade->id;
|
||||
|
||||
$refund->create();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $courseId
|
||||
* @param int $userId
|
||||
@ -166,13 +217,30 @@ class ProcessOrderTask extends Task
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $orderId
|
||||
* @return Model|TradeModel
|
||||
*/
|
||||
protected function findFinishedTrade($orderId)
|
||||
{
|
||||
$status = TradeModel::STATUS_FINISHED;
|
||||
|
||||
$result = TradeModel::findFirst([
|
||||
'conditions' => ['order_id = :order_id: AND status = :status:'],
|
||||
'bind' => ['order_id' => $orderId, 'status' => $status],
|
||||
'order' => 'id DESC',
|
||||
]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|TaskModel[]
|
||||
*/
|
||||
protected function findTasks($limit = 100)
|
||||
{
|
||||
$itemType = TaskModel::TYPE_PROCESS_ORDER;
|
||||
$itemType = TaskModel::TYPE_ORDER;
|
||||
$status = TaskModel::STATUS_PENDING;
|
||||
$tryCount = self::TRY_COUNT;
|
||||
|
@ -11,8 +11,9 @@ use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Refund as RefundRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Services\Alipay as AlipayService;
|
||||
use App\Services\Wechat as WechatService;
|
||||
use App\Services\Payment\Alipay as AlipayService;
|
||||
use App\Services\Payment\Wxpay as WxpayService;
|
||||
use App\Services\Smser\Refund as RefundSmser;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
|
||||
@ -49,6 +50,10 @@ class RefundTask extends Task
|
||||
$trade = $tradeRepo->findById($itemInfo['refund']['trade_id']);
|
||||
$order = $orderRepo->findById($itemInfo['refund']['order_id']);
|
||||
|
||||
if (!$refund || !$trade || !$order) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$this->db->begin();
|
||||
@ -83,6 +88,8 @@ class RefundTask extends Task
|
||||
|
||||
$this->db->commit();
|
||||
|
||||
$this->handleRefundNotice($refund);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->db->rollback();
|
||||
@ -92,8 +99,6 @@ class RefundTask extends Task
|
||||
|
||||
if ($task->try_count > self::TRY_COUNT) {
|
||||
$task->status = TaskModel::STATUS_FAILED;
|
||||
$refund->status = RefundModel::STATUS_FAILED;
|
||||
$refund->update();
|
||||
}
|
||||
|
||||
$task->update();
|
||||
@ -103,6 +108,11 @@ class RefundTask extends Task
|
||||
'task' => $task->toArray(),
|
||||
]));
|
||||
}
|
||||
|
||||
if ($task->status == TaskModel::STATUS_FAILED) {
|
||||
$refund->status = RefundModel::STATUS_FAILED;
|
||||
$refund->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,22 +130,13 @@ class RefundTask extends Task
|
||||
|
||||
$alipay = new AlipayService();
|
||||
|
||||
$response = $alipay->refundOrder([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'out_request_no' => $refund->sn,
|
||||
'refund_amount' => $refund->amount,
|
||||
]);
|
||||
$response = $alipay->refund($refund);
|
||||
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WECHAT) {
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) {
|
||||
|
||||
$wechat = new WechatService();
|
||||
$wxpay = new WxpayService();
|
||||
|
||||
$response = $wechat->refundOrder([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'out_refund_no' => $refund->sn,
|
||||
'total_fee' => 100 * $trade->amount,
|
||||
'refund_fee' => 100 * $refund->amount,
|
||||
]);
|
||||
$response = $wxpay->refund($refund);
|
||||
}
|
||||
|
||||
if (!$response) {
|
||||
@ -252,6 +253,16 @@ class RefundTask extends Task
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RefundModel $refund
|
||||
*/
|
||||
protected function handleRefundNotice(RefundModel $refund)
|
||||
{
|
||||
$smser = new RefundSmser();
|
||||
|
||||
$smser->handle($refund);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $limit
|
||||
* @return ResultsetInterface|Resultset|TaskModel[]
|
||||
|
@ -28,7 +28,7 @@ class RevokeVipTask extends Task
|
||||
* 查找待解锁用户
|
||||
*
|
||||
* @param int $limit
|
||||
* @return UserModel[]|Resultset|ResultsetInterface
|
||||
* @return ResultsetInterface|Resultset|UserModel[]
|
||||
*/
|
||||
protected function findUsers($limit = 1000)
|
||||
{
|
||||
|
@ -22,13 +22,17 @@ class VodEventTask extends Task
|
||||
$count = 0;
|
||||
|
||||
foreach ($events as $event) {
|
||||
|
||||
$handles[] = $event['EventHandle'];
|
||||
|
||||
if ($event['EventType'] == 'NewFileUpload') {
|
||||
$this->handleNewFileUploadEvent($event);
|
||||
} elseif ($event['EventType'] == 'ProcedureStateChanged') {
|
||||
$this->handleProcedureStateChangedEvent($event);
|
||||
}
|
||||
|
||||
$count++;
|
||||
|
||||
if ($count >= 12) {
|
||||
break;
|
||||
}
|
||||
@ -61,8 +65,10 @@ class VodEventTask extends Task
|
||||
* @var array $attrs
|
||||
*/
|
||||
$attrs = $chapter->attrs;
|
||||
|
||||
$attrs['file_status'] = ChapterModel::FS_TRANSLATING;
|
||||
$attrs['duration'] = (int)$duration;
|
||||
|
||||
$chapter->update(['attrs' => $attrs]);
|
||||
|
||||
$this->updateVodAttrs($chapter->course_id);
|
||||
@ -71,6 +77,7 @@ class VodEventTask extends Task
|
||||
protected function handleProcedureStateChangedEvent($event)
|
||||
{
|
||||
$fileId = $event['ProcedureStateChangeEvent']['FileId'];
|
||||
|
||||
$processResult = $event['ProcedureStateChangeEvent']['MediaProcessResultSet'];
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
@ -110,7 +117,9 @@ class VodEventTask extends Task
|
||||
* @var array $attrs
|
||||
*/
|
||||
$attrs = $chapter->attrs;
|
||||
|
||||
$attrs['file_status'] = $fileStatus;
|
||||
|
||||
$chapter->update(['attrs' => $attrs]);
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,7 @@ class ConfigController extends Controller
|
||||
if ($this->request->isPost()) {
|
||||
|
||||
$section = $this->request->getPost('section');
|
||||
|
||||
$data = $this->request->getPost();
|
||||
|
||||
$configService->updateSectionConfig($section, $data);
|
||||
@ -157,10 +158,10 @@ class ConfigController extends Controller
|
||||
} else {
|
||||
|
||||
$alipay = $configService->getSectionConfig('payment.alipay');
|
||||
$wechat = $configService->getSectionConfig('payment.wechat');
|
||||
$wxpay = $configService->getSectionConfig('payment.wxpay');
|
||||
|
||||
$this->view->setVar('alipay', $alipay);
|
||||
$this->view->setVar('wechat', $wechat);
|
||||
$this->view->setVar('wxpay', $wxpay);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Admin\Controllers;
|
||||
|
||||
use App\Http\Admin\Services\AlipayTest as AlipayTestService;
|
||||
use App\Http\Admin\Services\Config as ConfigService;
|
||||
use App\Http\Admin\Services\WxpayTest as WxpayTestService;
|
||||
use App\Services\Captcha as CaptchaService;
|
||||
use App\Services\Live as LiveService;
|
||||
use App\Services\Mailer as MailerService;
|
||||
use App\Services\Smser as SmserService;
|
||||
use App\Services\Mailer\Test as TestMailerService;
|
||||
use App\Services\Smser\Test as TestSmserService;
|
||||
use App\Services\Storage as StorageService;
|
||||
use App\Services\Vod as VodService;
|
||||
use Phalcon\Mvc\View;
|
||||
@ -21,7 +22,7 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Post("/storage", name="admin.test.storage")
|
||||
*/
|
||||
public function storageTestAction()
|
||||
public function storageAction()
|
||||
{
|
||||
$storageService = new StorageService();
|
||||
|
||||
@ -37,7 +38,7 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Post("/vod", name="admin.test.vod")
|
||||
*/
|
||||
public function vodTestAction()
|
||||
public function vodAction()
|
||||
{
|
||||
$vodService = new VodService();
|
||||
|
||||
@ -53,12 +54,17 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Get("/live/push", name="admin.test.live.push")
|
||||
*/
|
||||
public function livePushTestAction()
|
||||
public function livePushAction()
|
||||
{
|
||||
$liveService = new LiveService();
|
||||
|
||||
$pushUrl = $liveService->getPushUrl('test');
|
||||
|
||||
$codeUrl = $this->url->get(
|
||||
['for' => 'home.qr.img'],
|
||||
['text' => urlencode($pushUrl)]
|
||||
);
|
||||
|
||||
$obs = new \stdClass();
|
||||
|
||||
$position = strrpos($pushUrl, '/');
|
||||
@ -66,14 +72,15 @@ class TestController extends Controller
|
||||
$obs->stream_code = substr($pushUrl, $position + 1);
|
||||
|
||||
$this->view->pick('config/live_push_test');
|
||||
$this->view->setVar('push_url', $pushUrl);
|
||||
|
||||
$this->view->setVar('code_url', $codeUrl);
|
||||
$this->view->setVar('obs', $obs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/live/pull", name="admin.test.live.pull")
|
||||
*/
|
||||
public function livePullTestAction()
|
||||
public function livePullAction()
|
||||
{
|
||||
$liveService = new LiveService();
|
||||
|
||||
@ -81,7 +88,9 @@ class TestController extends Controller
|
||||
$flvPullUrls = $liveService->getPullUrls('test', 'flv');
|
||||
|
||||
$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
|
||||
|
||||
$this->view->pick('public/live_player');
|
||||
|
||||
$this->view->setVar('m3u8_pull_urls', $m3u8PullUrls);
|
||||
$this->view->setVar('flv_pull_urls', $flvPullUrls);
|
||||
}
|
||||
@ -89,13 +98,13 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Post("/smser", name="admin.test.smser")
|
||||
*/
|
||||
public function smserTestAction()
|
||||
public function smserAction()
|
||||
{
|
||||
$phone = $this->request->getPost('phone');
|
||||
|
||||
$smserService = new SmserService();
|
||||
$smserService = new TestSmserService();
|
||||
|
||||
$response = $smserService->sendTestMessage($phone);
|
||||
$response = $smserService->handle($phone);
|
||||
|
||||
if ($response) {
|
||||
return $this->ajaxSuccess(['msg' => '发送短信成功,请到收件箱确认']);
|
||||
@ -107,13 +116,13 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Post("/mailer", name="admin.test.mailer")
|
||||
*/
|
||||
public function mailerTestAction()
|
||||
public function mailerAction()
|
||||
{
|
||||
$email = $this->request->getPost('email');
|
||||
|
||||
$mailerService = new MailerService();
|
||||
$mailerService = new TestMailerService();
|
||||
|
||||
$result = $mailerService->sendTestMail($email);
|
||||
$result = $mailerService->handle($email);
|
||||
|
||||
if ($result) {
|
||||
return $this->ajaxSuccess(['msg' => '发送邮件成功,请到收件箱确认']);
|
||||
@ -125,7 +134,7 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Post("/captcha", name="admin.test.captcha")
|
||||
*/
|
||||
public function captchaTestAction()
|
||||
public function captchaAction()
|
||||
{
|
||||
$post = $this->request->getPost();
|
||||
|
||||
@ -149,37 +158,47 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Get("/alipay", name="admin.test.alipay")
|
||||
*/
|
||||
public function alipayTestAction()
|
||||
public function alipayAction()
|
||||
{
|
||||
$alipayTestService = new AlipayTestService();
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$order = $alipayTestService->createTestOrder();
|
||||
$trade = $alipayTestService->createTestTrade($order);
|
||||
$qrcode = $alipayTestService->getTestQrCode($trade);
|
||||
$order = $alipayTestService->createOrder();
|
||||
$trade = $alipayTestService->createTrade($order);
|
||||
$code = $alipayTestService->scan($trade);
|
||||
|
||||
if ($order->id > 0 && $trade->id > 0 && $qrcode) {
|
||||
if ($order && $trade && $code) {
|
||||
$this->db->commit();
|
||||
} else {
|
||||
$this->db->rollback();
|
||||
}
|
||||
|
||||
$codeUrl = null;
|
||||
|
||||
if ($code) {
|
||||
$codeUrl = $this->url->get(
|
||||
['for' => 'home.qr.img'],
|
||||
['text' => urlencode($code)]
|
||||
);
|
||||
}
|
||||
|
||||
$this->view->pick('config/payment_alipay_test');
|
||||
$this->view->setVar('trade', $trade);
|
||||
$this->view->setVar('qrcode', $qrcode);
|
||||
|
||||
$this->view->setVar('trade_sn', $trade->sn);
|
||||
$this->view->setVar('code_url', $codeUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/alipay/status", name="admin.test.alipay.status")
|
||||
*/
|
||||
public function alipayTestStatusAction()
|
||||
public function alipayStatusAction()
|
||||
{
|
||||
$sn = $this->request->getPost('sn');
|
||||
$tradeSn = $this->request->getPost('trade_sn');
|
||||
|
||||
$alipayTestService = new AlipayTestService();
|
||||
|
||||
$status = $alipayTestService->getTestStatus($sn);
|
||||
$status = $alipayTestService->status($tradeSn);
|
||||
|
||||
return $this->ajaxSuccess(['status' => $status]);
|
||||
}
|
||||
@ -187,13 +206,66 @@ class TestController extends Controller
|
||||
/**
|
||||
* @Post("/alipay/cancel", name="admin.test.alipay.cancel")
|
||||
*/
|
||||
public function alipayTestCancelAction()
|
||||
public function alipayCancelAction()
|
||||
{
|
||||
$sn = $this->request->getPost('sn');
|
||||
$tradeSn = $this->request->getPost('trade_sn');
|
||||
|
||||
$alipayTestService = new AlipayTestService();
|
||||
|
||||
$alipayTestService->cancelTestOrder($sn);
|
||||
$alipayTestService->cancel($tradeSn);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '取消订单成功']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/wxpay", name="admin.test.wxpay")
|
||||
*/
|
||||
public function wxpayAction()
|
||||
{
|
||||
$wxpayTestService = new WxpayTestService();
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$order = $wxpayTestService->createOrder();
|
||||
$trade = $wxpayTestService->createTrade($order);
|
||||
$codeUrl = $wxpayTestService->scan($trade);
|
||||
|
||||
if ($order && $trade && $codeUrl) {
|
||||
$this->db->commit();
|
||||
} else {
|
||||
$this->db->rollback();
|
||||
}
|
||||
|
||||
$this->view->pick('config/payment_wxpay_test');
|
||||
|
||||
$this->view->setVar('trade_sn', $trade->sn);
|
||||
$this->view->setVar('code_url', $codeUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/wxpay/status", name="admin.test.wxpay.status")
|
||||
*/
|
||||
public function wxpayStatusAction()
|
||||
{
|
||||
$tradeSn = $this->request->getPost('trade_sn');
|
||||
|
||||
$wxpayTestService = new WxpayTestService();
|
||||
|
||||
$status = $wxpayTestService->status($tradeSn);
|
||||
|
||||
return $this->ajaxSuccess(['status' => $status]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/wxpay/cancel", name="admin.test.wxpay.cancel")
|
||||
*/
|
||||
public function wxpayCancelAction()
|
||||
{
|
||||
$tradeSn = $this->request->getPost('trade_sn');
|
||||
|
||||
$wxpayTestService = new WxpayTestService();
|
||||
|
||||
$wxpayTestService->cancel($tradeSn);
|
||||
|
||||
return $this->ajaxSuccess(['msg' => '取消订单成功']);
|
||||
}
|
||||
|
@ -6,44 +6,38 @@ use App\Models\Order as OrderModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Services\Alipay as AlipayService;
|
||||
use App\Services\Payment\Alipay as AlipayService;
|
||||
|
||||
class AlipayTest extends PaymentTest
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取测试二维码
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTestQrCode($trade)
|
||||
{
|
||||
$outOrder = [
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_amount' => $trade->amount,
|
||||
'subject' => $trade->subject,
|
||||
];
|
||||
protected $channel = TradeModel::CHANNEL_ALIPAY;
|
||||
|
||||
public function scan(TradeModel $trade)
|
||||
{
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$qrcode = $alipayService->getQrCode($outOrder);
|
||||
$qrcode = $alipayService->scan($trade);
|
||||
|
||||
$result = $qrcode ?: false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消测试订单
|
||||
*
|
||||
* @param string $sn
|
||||
*/
|
||||
public function cancelTestOrder($sn)
|
||||
public function status($tradeNo)
|
||||
{
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$result = $alipayService->status($tradeNo);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function cancel($tradeNo)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findBySn($sn);
|
||||
$trade = $tradeRepo->findBySn($tradeNo);
|
||||
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
@ -51,11 +45,13 @@ class AlipayTest extends PaymentTest
|
||||
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$response = $alipayService->cancelOrder($trade->sn);
|
||||
$response = $alipayService->cancel($trade->sn);
|
||||
|
||||
if ($response) {
|
||||
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
$trade->update();
|
||||
|
||||
if ($order->status != OrderModel::STATUS_PENDING) {
|
||||
$order->status = OrderModel::STATUS_PENDING;
|
||||
$order->update();
|
||||
|
@ -4,18 +4,25 @@ namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
|
||||
abstract class PaymentTest extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* 创建测试订单
|
||||
* @var string 支付平台
|
||||
*/
|
||||
protected $channel;
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*
|
||||
* @return OrderModel
|
||||
*/
|
||||
public function createTestOrder()
|
||||
public function createOrder()
|
||||
{
|
||||
/**
|
||||
* @var object $authUser
|
||||
*/
|
||||
$authUser = $this->getDI()->get('auth')->getAuthInfo();
|
||||
|
||||
$order = new OrderModel();
|
||||
@ -36,7 +43,7 @@ abstract class PaymentTest extends Service
|
||||
* @param OrderModel $order
|
||||
* @return TradeModel $trade
|
||||
*/
|
||||
public function createTestTrade($order)
|
||||
public function createTrade(OrderModel $order)
|
||||
{
|
||||
$trade = new TradeModel();
|
||||
|
||||
@ -44,7 +51,7 @@ abstract class PaymentTest extends Service
|
||||
$trade->order_id = $order->id;
|
||||
$trade->subject = $order->subject;
|
||||
$trade->amount = $order->amount;
|
||||
$trade->channel = TradeModel::CHANNEL_ALIPAY;
|
||||
$trade->channel = $this->channel;
|
||||
|
||||
$trade->create();
|
||||
|
||||
@ -52,33 +59,27 @@ abstract class PaymentTest extends Service
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单状态
|
||||
* 交易状态
|
||||
*
|
||||
* @param string $sn
|
||||
* @param string $tradeNo
|
||||
* @return string
|
||||
*/
|
||||
public function getTestStatus($sn)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findBySn($sn);
|
||||
|
||||
return $trade->status;
|
||||
}
|
||||
abstract public function status($tradeNo);
|
||||
|
||||
/**
|
||||
* 获取测试二维码
|
||||
* 扫码下单
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
* @return mixed
|
||||
* @return string|bool
|
||||
*/
|
||||
abstract public function getTestQrCode($trade);
|
||||
abstract public function scan(TradeModel $trade);
|
||||
|
||||
/**
|
||||
* 取消测试订单
|
||||
* 取消交易
|
||||
*
|
||||
* @param string $sn
|
||||
* @param string $tradeNo
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function cancelTestOrder($sn);
|
||||
abstract public function cancel($tradeNo);
|
||||
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ class Refund extends Service
|
||||
|
||||
$data = [];
|
||||
|
||||
$validator->checkIfAllowReview($refund);
|
||||
$validator->checkReviewAction($refund);
|
||||
|
||||
$data['status'] = $validator->checkReviewStatus($post['status']);
|
||||
$data['review_note'] = $validator->checkReviewNote($post['review_note']);
|
||||
|
@ -95,6 +95,7 @@ class Trade extends Service
|
||||
$validator->checkIfAllowClose($trade);
|
||||
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
|
||||
$trade->update();
|
||||
|
||||
return $trade;
|
||||
@ -114,7 +115,7 @@ class Trade extends Service
|
||||
$refund->amount = $trade->amount;
|
||||
$refund->user_id = $trade->user_id;
|
||||
$refund->order_id = $trade->order_id;
|
||||
$refund->trade_id = $trade->sn;
|
||||
$refund->trade_id = $trade->id;
|
||||
$refund->apply_note = '后台人工申请退款';
|
||||
|
||||
$refund->create();
|
||||
|
@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Order as OrderRepo;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Services\Wechat as WechatService;
|
||||
|
||||
class WechatTest extends PaymentTest
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取测试二维码
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTestQrcode($trade)
|
||||
{
|
||||
$outOrder = [
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_fee' => 100 * $trade->amount,
|
||||
'body' => $trade->subject,
|
||||
];
|
||||
|
||||
$wechatService = new WechatService();
|
||||
|
||||
$qrcode = $wechatService->getQrCode($outOrder);
|
||||
|
||||
$result = $qrcode ?: false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消测试订单
|
||||
*
|
||||
* @param string $sn
|
||||
*/
|
||||
public function cancelTestOrder($sn)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findBySn($sn);
|
||||
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
$order = $orderRepo->findById($trade->order_id);
|
||||
|
||||
$wechatService = new WechatService();
|
||||
|
||||
$response = $wechatService->closeOrder($trade->sn);
|
||||
|
||||
if ($response) {
|
||||
$trade->status = TradeModel::STATUS_CLOSED;
|
||||
$trade->update();
|
||||
if ($order->status != OrderModel::STATUS_PENDING) {
|
||||
$order->status = OrderModel::STATUS_PENDING;
|
||||
$order->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
42
app/Http/Admin/Services/WxpayTest.php
Normal file
42
app/Http/Admin/Services/WxpayTest.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Admin\Services;
|
||||
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Services\Payment\Wxpay as WxpayService;
|
||||
|
||||
class WxpayTest extends PaymentTest
|
||||
{
|
||||
|
||||
protected $channel = TradeModel::CHANNEL_WXPAY;
|
||||
|
||||
public function scan(TradeModel $trade)
|
||||
{
|
||||
$wxpayService = new WxpayService();
|
||||
|
||||
$qrcode = $wxpayService->scan($trade);
|
||||
|
||||
$result = $qrcode ?: false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function status($tradeNo)
|
||||
{
|
||||
$wxpayService = new WxpayService();
|
||||
|
||||
$result = $wxpayService->status($tradeNo);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function cancel($tradeNo)
|
||||
{
|
||||
$wxpayService = new WxpayService();
|
||||
|
||||
$response = $wxpayService->close($tradeNo);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-inline" style="width:150px;margin-left:110px;">
|
||||
<img src="/qrcode/img?text={{ push_url|url_encode }}">
|
||||
<img class="kg-qrcode" src="{{ code_url }}" alt="二维码图片">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<ul class="layui-tab-title kg-tab-title">
|
||||
<li class="layui-this">支付宝支付</li>
|
||||
<li class="layui-this">支付宝</li>
|
||||
<li>微信支付</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
@ -8,7 +8,7 @@
|
||||
{{ partial('config/payment_alipay') }}
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
{{ partial('config/payment_wechat') }}
|
||||
{{ partial('config/payment_wxpay') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,33 +1,32 @@
|
||||
<div class="kg-qrcode-block">
|
||||
|
||||
{% if qrcode %}
|
||||
{% if code_url %}
|
||||
|
||||
<div id="qrcode" class="qrcode" qrcode-text="{{ qrcode }}"></div>
|
||||
|
||||
<input type="hidden" name="sn" value="{{ trade.sn }}">
|
||||
|
||||
<div id="success-tips" class="success-tips layui-hide">
|
||||
<span><i class="layui-icon layui-icon-ok-circle"></i> 支付成功</span>
|
||||
<div id="qrcode">
|
||||
<img class="kg-qrcode" src="{{ code_url }}" alt="二维码图片">
|
||||
</div>
|
||||
|
||||
<div id="error-tips" class="error-tips layui-hide">
|
||||
<span><i class="layui-icon layui-icon-close-fill"></i> 支付失败</span>
|
||||
<input type="hidden" name="trade_sn" value="{{ trade_sn }}">
|
||||
|
||||
<div id="success-tips" class="kg-success-tips layui-hide">
|
||||
<span>支付成功</span>
|
||||
</div>
|
||||
|
||||
<div id="error-tips" class="kg-error-tips layui-hide">
|
||||
<span>支付失败</span>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="error-tips">
|
||||
<span><i class="layui-icon layui-icon-close-fill"></i> 生成二维码失败</span>
|
||||
<div class="kg-error-tips">
|
||||
<span>生成二维码失败</span>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% if qrcode %}
|
||||
|
||||
{{ javascript_include('lib/jquery.min.js') }}
|
||||
{{ javascript_include('lib/jquery.qrcode.min.js') }}
|
||||
{% if code_url %}
|
||||
|
||||
<script>
|
||||
|
||||
@ -35,21 +34,15 @@
|
||||
|
||||
var $ = layui.jquery;
|
||||
|
||||
$('#qrcode').qrcode({
|
||||
text: $('#qrcode').attr('qrcode-text'),
|
||||
width: 150,
|
||||
height: 150
|
||||
});
|
||||
|
||||
var loopTime = 0;
|
||||
var sn = $('input[name=sn]').val();
|
||||
var tradeSn = $('input[name=trade_sn]').val();
|
||||
var interval = setInterval(function () {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/test/alipay/status',
|
||||
data: {sn: sn},
|
||||
data: {trade_sn: tradeSn},
|
||||
success: function (res) {
|
||||
if (res.status == 'finished') {
|
||||
if (res.status === 'finished') {
|
||||
$('#success-tips').removeClass('layui-hide');
|
||||
$('#qrcode').addClass('layui-hide');
|
||||
clearInterval(interval);
|
||||
@ -66,7 +59,7 @@
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/test/alipay/cancel',
|
||||
data: {sn: sn},
|
||||
data: {trade_sn: tradeSn},
|
||||
success: function (res) {
|
||||
},
|
||||
error: function (xhr) {
|
||||
|
@ -3,37 +3,36 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开启支付</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="enabled" value="1" title="是" {% if wechat.enabled == "1" %}checked{% endif %}>
|
||||
<input type="radio" name="enabled" value="0" title="否" {% if wechat.enabled == "0" %}checked{% endif %}>
|
||||
<input type="radio" name="enabled" value="1" title="是" {% if wxpay.enabled == "1" %}checked{% endif %}>
|
||||
<input type="radio" name="enabled" value="0" title="否" {% if wxpay.enabled == "0" %}checked{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">App ID</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="app_id" value="{{ wechat.app_id }}" lay-verify="required">
|
||||
<input class="layui-input" type="text" name="app_id" value="{{ wxpay.app_id }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Mch ID</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="mch_id" value="{{ wechat.mch_id }}" lay-verify="required">
|
||||
<input class="layui-input" type="text" name="mch_id" value="{{ wxpay.mch_id }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Private Key</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="key" value="{{ wechat.key }}" lay-verify="required">
|
||||
<input class="layui-input" type="text" name="key" value="{{ wxpay.key }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">Notify Url</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="notify_url" value="{{ wechat.notify_url }}"
|
||||
lay-verify="required">
|
||||
<input class="layui-input" type="text" name="notify_url" value="{{ wxpay.notify_url }}" lay-verify="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -42,7 +41,7 @@
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="true" lay-filter="go">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
<input type="hidden" name="section" value="payment.wechat">
|
||||
<input type="hidden" name="section" value="payment.wxpay">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -71,7 +70,7 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"></label>
|
||||
<div class="layui-input-block">
|
||||
<button type="button" class="layui-btn" id="show-wechat-test">提交</button>
|
||||
<button type="button" class="layui-btn" id="show-wxpay-test">提交</button>
|
||||
<button type="button" class="kg-back layui-btn layui-btn-primary">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -85,8 +84,8 @@
|
||||
var $ = layui.jquery;
|
||||
var layer = layui.layer;
|
||||
|
||||
$('#show-wechat-test').on('click', function () {
|
||||
var url = '/admin/test/wechat';
|
||||
$('#show-wxpay-test').on('click', function () {
|
||||
var url = '/admin/test/wxpay';
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: '微信 - 支付测试',
|
@ -1,33 +1,32 @@
|
||||
<div class="kg-qrcode-block">
|
||||
|
||||
{% if qrcode %}
|
||||
{% if code_url %}
|
||||
|
||||
<div id="qrcode" class="qrcode" qrcode-text="{{ qrcode }}"></div>
|
||||
|
||||
<input type="hidden" name="sn" value="{{ trade.sn }}">
|
||||
|
||||
<div id="success-tips" class="success-tips layui-hide">
|
||||
<span><i class="layui-icon layui-icon-ok-circle"></i> 支付成功</span>
|
||||
<div id="qrcode">
|
||||
<img class="kg-qrcode" src="{{ code_url }}" alt="二维码图片">
|
||||
</div>
|
||||
|
||||
<div id="error-tips" class="error-tips layui-hide">
|
||||
<span><i class="layui-icon layui-icon-close-fill"></i> 支付失败</span>
|
||||
<input type="hidden" name="trade_sn" value="{{ trade_sn }}">
|
||||
|
||||
<div id="success-tips" class="kg-success-tips layui-hide">
|
||||
<span>支付成功</span>
|
||||
</div>
|
||||
|
||||
<div id="error-tips" class="kg-error-tips layui-hide">
|
||||
<span>支付失败</span>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="error-tips">
|
||||
<span><i class="layui-icon layui-icon-close-fill"></i> 生成二维码失败</span>
|
||||
<div class="kg-error-tips">
|
||||
<span>生成二维码失败</span>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
{% if qrcode %}
|
||||
|
||||
{{ javascript_include('lib/jquery.min.js') }}
|
||||
{{ javascript_include('lib/jquery.qrcode.min.js') }}
|
||||
{% if code_url %}
|
||||
|
||||
<script>
|
||||
|
||||
@ -35,21 +34,15 @@
|
||||
|
||||
var $ = layui.jquery;
|
||||
|
||||
$('#qrcode').qrcode({
|
||||
text: $('#qrcode').attr('qrcode-text'),
|
||||
width: 150,
|
||||
height: 150
|
||||
});
|
||||
|
||||
var loopTime = 0;
|
||||
var sn = $('input[name=sn]').val();
|
||||
var tradeSn = $('input[name=trade_sn]').val();
|
||||
var interval = setInterval(function () {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/test/alipay/status',
|
||||
data: {sn: sn},
|
||||
url: '/admin/test/wxpay/status',
|
||||
data: {trade_sn: tradeSn},
|
||||
success: function (res) {
|
||||
if (res.status == 2) {
|
||||
if (res.status === 'finished') {
|
||||
$('#success-tips').removeClass('layui-hide');
|
||||
$('#qrcode').addClass('layui-hide');
|
||||
clearInterval(interval);
|
||||
@ -65,8 +58,8 @@
|
||||
if (loopTime >= 300) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/admin/config/wechat/test/cancel',
|
||||
data: {sn: sn},
|
||||
url: '/admin/test/wxpay/cancel',
|
||||
data: {trade_sn: tradeSn},
|
||||
success: function (res) {
|
||||
},
|
||||
error: function (xhr) {
|
@ -32,15 +32,13 @@
|
||||
<table class="kg-table layui-table layui-form">
|
||||
<colgroup>
|
||||
<col width="12%">
|
||||
<col width="10%">
|
||||
<col width="12%">
|
||||
<col width="15%">
|
||||
<col>
|
||||
<col width="10%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>类型</th>
|
||||
<th>模板编号</th>
|
||||
<th>模板内容</th>
|
||||
<th>操作</th>
|
||||
@ -48,32 +46,28 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>注册帐号</td>
|
||||
<td><span class="layui-badge">验证码</span></td>
|
||||
<td><input class="layui-input" type="text" name="template[id][register]" value="{{ template.register.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc1" class="layui-input" type="text" name="template[content][register]" value="{{ template.register.content }}" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc1">复制</span></td>
|
||||
<td>身份验证</td>
|
||||
<td><input class="layui-input" type="text" name="template[id][verify]" value="{{ template.verify.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc-verify" class="layui-input" type="text" name="template[content][verify]" value="{{ template.verify.content }}" readonly="readonly" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc-verify">复制</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>重置密码</td>
|
||||
<td><span class="layui-badge">验证码</span></td>
|
||||
<td><input class="layui-input" type="text" name="template[id][reset_password]" value="{{ template.reset_password.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc2" class="layui-input" type="text" name="template[content][reset_password]" value="{{ template.reset_password.content }}" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc2">复制</span></td>
|
||||
<td>订单通知</td>
|
||||
<td><input class="layui-input" type="text" name="template[id][order]" value="{{ template.order.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc-order" class="layui-input" type="text" name="template[content][order]" value="{{ template.order.content }}" readonly="readonly" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc-order">复制</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>购买课程</td>
|
||||
<td><span class="layui-badge layui-bg-blue">通知</span></td>
|
||||
<td><input class="layui-input" type="text" name="template[id][buy_course]" value="{{ template.buy_course.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc3" class="layui-input" type="text" name="template[content][buy_course]" value="{{ template.buy_course.content }}" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc3">复制</span></td>
|
||||
<td>退款通知</td>
|
||||
<td><input class="layui-input" type="text" name="template[id][refund]" value="{{ template.refund.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc-refund" class="layui-input" type="text" name="template[content][refund]" value="{{ template.refund.content }}" readonly="readonly" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc-refund">复制</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>购买会员</td>
|
||||
<td><span class="layui-badge layui-bg-blue">通知</span></td>
|
||||
<td><input class="layui-input" type="text" name="template[id][buy_member]" value="{{ template.buy_member.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc4" class="layui-input" type="text" name="template[content][buy_member]" value="{{ template.buy_member.content }}" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc4">复制</span></td>
|
||||
<td>直播通知</td>
|
||||
<td><input class="layui-input" type="text" name="template[id][live]" value="{{ template.live.id }}" lay-verify="required"></td>
|
||||
<td><input id="tc-live" class="layui-input" type="text" name="template[content][live]" value="{{ template.live.content }}" readonly="readonly" lay-verify="required"></td>
|
||||
<td><span class="kg-copy layui-btn" data-clipboard-target="#tc-live">复制</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
{%- macro category_info(items) %}
|
||||
{% for item in items %}
|
||||
<span class="layui-badge layui-bg-green">{{ item.name }}</span>
|
||||
<a class="layui-badge layui-bg-green" href="{{ url({'for':'admin.course.list'},{'category_id':item.id}) }}">{{ item.name }}</a>
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
|
@ -11,13 +11,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户编号</label>
|
||||
<div class="layui-input-block">
|
||||
<input class="layui-input" type="text" name="user_id" placeholder="用户编号精确匹配">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">标题</label>
|
||||
<div class="layui-input-block">
|
||||
@ -37,7 +30,7 @@
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="model" value="vod" title="点播">
|
||||
<input type="radio" name="model" value="live" title="直播">
|
||||
<input type="radio" name="model" value="article" title="图文">
|
||||
<input type="radio" name="model" value="read" title="图文">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
{%- macro channel_type(value) %}
|
||||
{% if value == 'alipay' %}
|
||||
<span class="layui-badge layui-bg-blue">支付宝</span>
|
||||
{% elseif value == 'wechat' %}
|
||||
{% elseif value == 'wxpay' %}
|
||||
<span class="layui-badge layui-bg-green">微信</span>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
@ -22,7 +22,7 @@
|
||||
<label class="layui-form-label">交易平台</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="channel" value="alipay" title="支付宝">
|
||||
<input type="radio" name="channel" value="wechat" title="微信">
|
||||
<input type="radio" name="channel" value="wxpay" title="微信">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,59 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Services\Alipay as AlipayService;
|
||||
|
||||
|
||||
class NotifyController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Post("/alipay/notify", name="home.alipay.notify")
|
||||
*/
|
||||
public function alipayNotifyAction()
|
||||
{
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$response = $alipayService->handleNotify();
|
||||
|
||||
if (!$response) exit;
|
||||
|
||||
$response->send();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/wechat/notify", name="home.wechat.notify")
|
||||
*/
|
||||
public function wechatNotifyAction()
|
||||
{
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$response = $alipayService->handleNotify();
|
||||
|
||||
if (!$response) exit;
|
||||
|
||||
$response->send();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/vod/notify", name="home.vod.notify")
|
||||
*/
|
||||
public function vodNotifyAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/live/notify", name="home.live.notify")
|
||||
*/
|
||||
public function liveNotifyAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
74
app/Http/Home/Controllers/PaymentController.php
Normal file
74
app/Http/Home/Controllers/PaymentController.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Home\Controllers;
|
||||
|
||||
use App\Services\Payment\Alipay as AlipayService;
|
||||
use App\Services\Payment\Wxpay as WxpayService;
|
||||
use App\Traits\Ajax as AjaxTrait;
|
||||
|
||||
class PaymentController extends \Phalcon\Mvc\Controller
|
||||
{
|
||||
|
||||
use AjaxTrait;
|
||||
|
||||
/**
|
||||
* @Post("/alipay/notify", name="home.alipay.notify")
|
||||
*/
|
||||
public function alipayNotifyAction()
|
||||
{
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$response = $alipayService->notify();
|
||||
|
||||
if (!$response) exit;
|
||||
|
||||
$response->send();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/wxpay/notify", name="home.wxpay.notify")
|
||||
*/
|
||||
public function wxpayNotifyAction()
|
||||
{
|
||||
$wxpayService = new WxpayService();
|
||||
|
||||
$response = $wxpayService->notify();
|
||||
|
||||
if (!$response) exit;
|
||||
|
||||
$response->send();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/alipay/status", name="home.alipay.status")
|
||||
*/
|
||||
public function alipayStatusAction()
|
||||
{
|
||||
$sn = $this->request->getPost('sn');
|
||||
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$status = $alipayService->status($sn);
|
||||
|
||||
return $this->ajaxSuccess(['status' => $status]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Post("/wxpay/status", name="home.wxpay.status")
|
||||
*/
|
||||
public function wxpayStatusAction()
|
||||
{
|
||||
$sn = $this->request->getPost('sn');
|
||||
|
||||
$wxpayService = new WxpayService();
|
||||
|
||||
$status = $wxpayService->status($sn);
|
||||
|
||||
return $this->ajaxSuccess(['status' => $status]);
|
||||
}
|
||||
|
||||
}
|
@ -66,9 +66,9 @@ class PublicController extends \Phalcon\Mvc\Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/qrcode/img", name="home.qrcode.img")
|
||||
* @Get("/qr/img", name="home.qr.img")
|
||||
*/
|
||||
public function qrcodeImageAction()
|
||||
public function qrImageAction()
|
||||
{
|
||||
$text = $this->request->getQuery('text');
|
||||
$level = $this->request->getQuery('level', 'int', 0);
|
||||
@ -76,7 +76,9 @@ class PublicController extends \Phalcon\Mvc\Controller
|
||||
|
||||
$url = urldecode($text);
|
||||
|
||||
echo QRcode::png($url, false, $level, $size);
|
||||
QRcode::png($url, false, $level, $size);
|
||||
|
||||
$this->response->send();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class Payment extends Listener
|
||||
|
||||
$task->item_id = $order->id;
|
||||
$task->item_info = $itemInfo;
|
||||
$task->item_type = TaskModel::TYPE_PROCESS_ORDER;
|
||||
$task->item_type = TaskModel::TYPE_ORDER;
|
||||
|
||||
if ($task->create() === false) {
|
||||
throw new \RuntimeException('Create Order Process Task Failed');
|
||||
|
@ -12,6 +12,7 @@ class Order extends Model
|
||||
*/
|
||||
const ITEM_COURSE = 'course'; // 课程
|
||||
const ITEM_PACKAGE = 'package'; // 套餐
|
||||
const ITEM_REWARD = 'reward'; // 赞赏
|
||||
const ITEM_VIP = 'vip'; // 会员
|
||||
const ITEM_TEST = 'test'; // 测试
|
||||
|
||||
@ -183,6 +184,7 @@ class Order extends Model
|
||||
$list = [
|
||||
self::ITEM_COURSE => '课程',
|
||||
self::ITEM_PACKAGE => '套餐',
|
||||
self::ITEM_REWARD => '赞赏',
|
||||
self::ITEM_VIP => '会员',
|
||||
self::ITEM_TEST => '测试',
|
||||
];
|
||||
|
@ -9,8 +9,7 @@ class Task extends Model
|
||||
* 任务类型
|
||||
*/
|
||||
const TYPE_REFUND = 'refund'; // 退款
|
||||
const TYPE_PROCESS_ORDER = 'process_order'; // 处理订单
|
||||
const TYPE_LIVE_NOTIFY = 'live_notify'; // 直播通知
|
||||
const TYPE_ORDER = 'order'; // 下单
|
||||
|
||||
/**
|
||||
* 优先级
|
||||
|
@ -11,7 +11,7 @@ class Trade extends Model
|
||||
* 平台类型
|
||||
*/
|
||||
const CHANNEL_ALIPAY = 'alipay'; // 支付宝
|
||||
const CHANNEL_WECHAT = 'wechat'; // 微信
|
||||
const CHANNEL_WXPAY = 'wxpay'; // 微信
|
||||
|
||||
/**
|
||||
* 状态类型
|
||||
@ -145,7 +145,7 @@ class Trade extends Model
|
||||
{
|
||||
$list = [
|
||||
self::CHANNEL_ALIPAY => '支付宝',
|
||||
self::CHANNEL_WECHAT => '微信',
|
||||
self::CHANNEL_WXPAY => '微信',
|
||||
];
|
||||
|
||||
return $list;
|
||||
|
@ -125,7 +125,7 @@ class Order extends Repository
|
||||
* @param string $itemType
|
||||
* @return OrderModel|Model|bool
|
||||
*/
|
||||
public function findLastUserOrder($userId, $itemId, $itemType)
|
||||
public function findLastUserItem($userId, $itemId, $itemType)
|
||||
{
|
||||
$result = OrderModel::findFirst([
|
||||
'conditions' => 'user_id = ?1 AND item_id = ?2 AND item_type = ?3',
|
||||
|
@ -37,7 +37,7 @@ class Vip extends Repository
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $where
|
||||
* @param array $where
|
||||
* @return ResultsetInterface|Resultset|VipModel[]
|
||||
*/
|
||||
public function findAll($where = [])
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Phalcon\Logger\Adapter\File as FileLogger;
|
||||
use TencentCloud\Captcha\V20190722\CaptchaClient;
|
||||
use TencentCloud\Captcha\V20190722\Models\DescribeCaptchaResultRequest;
|
||||
use TencentCloud\Common\Credential;
|
||||
@ -14,14 +15,27 @@ class Captcha extends Service
|
||||
|
||||
const END_POINT = 'captcha.tencentcloudapi.com';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var FileLogger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var CaptchaClient
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = $this->getSectionConfig('captcha');
|
||||
|
||||
$this->logger = $this->getLogger('captcha');
|
||||
|
||||
$this->client = $this->getCaptchaClient();
|
||||
}
|
||||
|
||||
@ -44,6 +58,9 @@ class Captcha extends Service
|
||||
|
||||
$request = new DescribeCaptchaResultRequest();
|
||||
|
||||
/**
|
||||
* 注意:CaptchaType 和 CaptchaAppId 强类型要求
|
||||
*/
|
||||
$params = json_encode([
|
||||
'Ticket' => $ticket,
|
||||
'Randstr' => $rand,
|
||||
@ -61,9 +78,9 @@ class Captcha extends Service
|
||||
|
||||
$this->logger->debug('Describe Captcha Result Response ' . $response->toJsonString());
|
||||
|
||||
$result = json_decode($response->toJsonString(), true);
|
||||
$data = json_decode($response->toJsonString(), true);
|
||||
|
||||
return $result['CaptchaCode'] == 1 ? true : false;
|
||||
$result = $data['CaptchaCode'] == 1;
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
@ -73,8 +90,10 @@ class Captcha extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ class ChapterComment extends Service
|
||||
|
||||
$validator = new UserDailyLimitValidator();
|
||||
|
||||
$validator->checkCommentLimit($user->id);
|
||||
$validator->checkCommentLimit($user);
|
||||
|
||||
$validator = new CommentValidator();
|
||||
|
||||
@ -62,6 +62,11 @@ class ChapterComment extends Service
|
||||
$this->incrUserDailyCommentCount($user);
|
||||
}
|
||||
|
||||
protected function handleMentions($mentions)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function incrUserDailyCommentCount(UserModel $user)
|
||||
{
|
||||
$this->eventsManager->fire('userDailyCounter:incrCommentCount', $this, $user);
|
||||
|
@ -9,7 +9,6 @@ use App\Models\CommentVote as CommentVoteModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Comment as CommentRepo;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
|
||||
class ChapterCommentList extends Service
|
||||
{
|
||||
@ -104,9 +103,6 @@ class ChapterCommentList extends Service
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
/**
|
||||
* @var Resultset $votes
|
||||
*/
|
||||
$votes = $chapterRepo->findUserCommentVotes($chapterId, $userId);
|
||||
|
||||
if ($votes->count() == 0) {
|
||||
|
@ -19,21 +19,26 @@ class Comment extends Service
|
||||
|
||||
$validator = new CommentValidator();
|
||||
|
||||
$validator->checkOwnerPriv($user->id, $comment->user_id);
|
||||
$validator->checkOwner($user->id, $comment->user_id);
|
||||
|
||||
$comment->deleted = 1;
|
||||
|
||||
$comment->update();
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($comment->chapter_id);
|
||||
|
||||
$chapter->comment_count -= 1;
|
||||
|
||||
$chapter->update();
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($comment->course_id);
|
||||
|
||||
$course->comment_count -= 1;
|
||||
|
||||
$course->update();
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@ class CourseUser extends Service
|
||||
|
||||
$validator = new CourseUserValidator();
|
||||
|
||||
$validator->checkIfAllowApply($course, $user);
|
||||
|
||||
$validator->checkIfJoined($course->id, $user->id);
|
||||
|
||||
$courseUser = new CourseUserModel();
|
||||
|
30
app/Services/Frontend/OrderCancel.php
Normal file
30
app/Services/Frontend/OrderCancel.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Validators\Order as OrderValidator;
|
||||
|
||||
class OrderCancel extends Service
|
||||
{
|
||||
|
||||
use OrderTrait;
|
||||
|
||||
public function cancelOrder($sn)
|
||||
{
|
||||
$order = $this->checkOrder($sn);
|
||||
|
||||
$user = $this->getLoginUser();
|
||||
|
||||
$validator = new OrderValidator();
|
||||
|
||||
$validator->checkOwner($user->id, $order->user_id);
|
||||
|
||||
$validator->checkIfAllowCancel($order);
|
||||
|
||||
$order->status = OrderModel::STATUS_CLOSED;
|
||||
|
||||
$order->update();
|
||||
}
|
||||
|
||||
}
|
@ -30,42 +30,46 @@ class OrderCreate extends Service
|
||||
|
||||
$validator = new OrderValidator();
|
||||
|
||||
/**
|
||||
* @var CourseModel|PackageModel|VipModel $item
|
||||
*/
|
||||
$item = $validator->checkItem($post['item_id'], $post['item_type']);
|
||||
|
||||
$validator->checkIfBought($user->id, $post['item_id'], $post['item_type']);
|
||||
|
||||
$validator->checkDailyLimit($user->id);
|
||||
$validator->checkItemType($post['item_type']);
|
||||
|
||||
$orderRepo = new OrderRepo();
|
||||
|
||||
$order = $orderRepo->findLastUserOrder($user->id, $post['item_id'], $post['item_type']);
|
||||
$order = $orderRepo->findLastUserItem($user->id, $post['item_id'], $post['item_type']);
|
||||
|
||||
/**
|
||||
* 存在新鲜的未支付订单直接返回(减少订单记录)
|
||||
*/
|
||||
if ($order) {
|
||||
|
||||
$caseA = $order->status == OrderModel::STATUS_PENDING;
|
||||
$caseB = time() - $order->created_at < 6 * 3600;
|
||||
|
||||
if ($caseA && $caseB) {
|
||||
return $order;
|
||||
}
|
||||
}
|
||||
|
||||
$order = new OrderModel();
|
||||
if ($post['item_type'] == OrderModel::ITEM_COURSE) {
|
||||
|
||||
switch ($post['item_type']) {
|
||||
case OrderModel::ITEM_COURSE:
|
||||
$order = $this->createCourseOrder($item, $user);
|
||||
break;
|
||||
case OrderModel::ITEM_PACKAGE:
|
||||
$order = $this->createPackageOrder($item, $user);
|
||||
break;
|
||||
case OrderModel::ITEM_VIP:
|
||||
$order = $this->createVipOrder($item, $user);
|
||||
break;
|
||||
$course = $validator->checkItemCourse($post['item_id']);
|
||||
|
||||
$validator->checkIfBoughtCourse($user->id, $course->id);
|
||||
|
||||
$order = $this->createCourseOrder($course, $user);
|
||||
|
||||
} elseif ($post['item_type'] == OrderModel::ITEM_PACKAGE) {
|
||||
|
||||
$package = $validator->checkItemPackage($post['item_id']);
|
||||
|
||||
$validator->checkIfBoughtPackage($user->id, $package->id);
|
||||
|
||||
$order = $this->createPackageOrder($package, $user);
|
||||
|
||||
} elseif ($post['item_type'] == OrderModel::ITEM_VIP) {
|
||||
|
||||
$vip = $validator->checkItemVip($post['item_id']);
|
||||
|
||||
$order = $this->createVipOrder($vip, $user);
|
||||
}
|
||||
|
||||
$this->incrUserDailyOrderCount($user);
|
||||
@ -78,7 +82,7 @@ class OrderCreate extends Service
|
||||
* @param UserModel $user
|
||||
* @return OrderModel $order
|
||||
*/
|
||||
public function createCourseOrder($course, $user)
|
||||
public function createCourseOrder(CourseModel $course, UserModel $user)
|
||||
{
|
||||
$studyExpiryTime = strtotime("+{$course->study_expiry} months");
|
||||
$refundExpiryTime = strtotime("+{$course->refund_expiry} days");
|
||||
@ -118,7 +122,7 @@ class OrderCreate extends Service
|
||||
* @param UserModel $user
|
||||
* @return OrderModel $order
|
||||
*/
|
||||
public function createPackageOrder($package, $user)
|
||||
public function createPackageOrder(PackageModel $package, UserModel $user)
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
@ -175,7 +179,7 @@ class OrderCreate extends Service
|
||||
* @param UserModel $user
|
||||
* @return OrderModel
|
||||
*/
|
||||
public function createVipOrder($vip, $user)
|
||||
public function createVipOrder(VipModel $vip, UserModel $user)
|
||||
{
|
||||
$baseTime = $user->vip_expiry_time > time() ? $user->vip_expiry_time : time();
|
||||
$expiryTime = strtotime("+{$vip->expiry} months", $baseTime);
|
||||
@ -184,8 +188,8 @@ class OrderCreate extends Service
|
||||
'vip' => [
|
||||
'id' => $vip->id,
|
||||
'title' => $vip->title,
|
||||
'expiry' => $vip->expiry,
|
||||
'price' => $vip->price,
|
||||
'expiry' => $vip->expiry,
|
||||
'expiry_time' => $expiryTime,
|
||||
]
|
||||
];
|
||||
@ -204,6 +208,9 @@ class OrderCreate extends Service
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserModel $user
|
||||
*/
|
||||
protected function incrUserDailyOrderCount(UserModel $user)
|
||||
{
|
||||
$this->eventsManager->fire('userDailyCounter:incrOrderCount', $this, $user);
|
||||
|
@ -3,8 +3,8 @@
|
||||
namespace App\Services\Frontend;
|
||||
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Services\Alipay as AlipayService;
|
||||
use App\Services\Wechat as WxPayService;
|
||||
use App\Services\Payment\Alipay as AlipayService;
|
||||
use App\Services\Payment\Wxpay as WxPayService;
|
||||
use App\Validators\Trade as TradeValidator;
|
||||
|
||||
class OrderTrade extends Service
|
||||
@ -68,21 +68,13 @@ class OrderTrade extends Service
|
||||
|
||||
$alipayService = new AlipayService();
|
||||
|
||||
$qrCode = $alipayService->getQrCode([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_amount' => $trade->amount,
|
||||
'subject' => $trade->subject,
|
||||
]);
|
||||
$qrCode = $alipayService->scan($trade);
|
||||
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WECHAT) {
|
||||
} elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) {
|
||||
|
||||
$wechatService = new WxPayService();
|
||||
$wxpayService = new WxPayService();
|
||||
|
||||
$qrCode = $wechatService->getQrCode([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_fee' => 100 * $trade->amount,
|
||||
'body' => $trade->subject,
|
||||
]);
|
||||
$qrCode = $wxpayService->scan($trade);
|
||||
}
|
||||
|
||||
return $qrCode;
|
||||
|
@ -3,52 +3,46 @@
|
||||
namespace App\Services\Frontend;
|
||||
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\User as UserRepo;
|
||||
use App\Validators\Validator as AppValidator;
|
||||
use Phalcon\Mvc\Model;
|
||||
use Phalcon\Mvc\User\Component;
|
||||
|
||||
class Service extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @return UserModel|Model
|
||||
*/
|
||||
public function getCurrentUser()
|
||||
{
|
||||
$user = UserModel::findFirst(100015);
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById(100015);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserModel|Model
|
||||
*/
|
||||
public function getCurrentUser2()
|
||||
{
|
||||
$authUser = $this->getAuthUser();
|
||||
|
||||
if ($authUser) {
|
||||
$user = UserModel::findFirst($authUser->id);
|
||||
} else {
|
||||
$user = $this->getGuestUser();
|
||||
if (!$authUser) {
|
||||
return $this->getGuestUser();
|
||||
}
|
||||
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById($authUser->id);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserModel|Model
|
||||
*/
|
||||
public function getLoginUser()
|
||||
{
|
||||
$user = UserModel::findFirst(100015);
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById(100015);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserModel|Model
|
||||
*/
|
||||
public function getLoginUser2()
|
||||
{
|
||||
$authUser = $this->getAuthUser();
|
||||
@ -57,7 +51,9 @@ class Service extends Component
|
||||
|
||||
$validator->checkAuthUser($authUser);
|
||||
|
||||
$user = UserModel::findFirst($authUser->id);
|
||||
$userRepo = new UserRepo();
|
||||
|
||||
$user = $userRepo->findById($authUser->id);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
55
app/Services/Frontend/TeacherCourseList.php
Normal file
55
app/Services/Frontend/TeacherCourseList.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend;
|
||||
|
||||
use App\Builders\CourseUserList as CourseUserListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
|
||||
class TeacherCourseList extends Service
|
||||
{
|
||||
|
||||
use UserTrait;
|
||||
|
||||
public function getCourses($id)
|
||||
{
|
||||
$user = $this->checkUser($id);
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['user_id'] = $user->id;
|
||||
$params['role_type'] = CourseUserModel::ROLE_TEACHER;
|
||||
$params['deleted'] = 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
$pager = $courseUserRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleCourses($pager);
|
||||
}
|
||||
|
||||
protected function handleCourses($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new CourseUserListBuilder();
|
||||
|
||||
$relations = $pager->items->toArray();
|
||||
|
||||
$courses = $builder->getCourses($relations);
|
||||
|
||||
$pager->items = $courses;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
68
app/Services/Frontend/UserCourseList.php
Normal file
68
app/Services/Frontend/UserCourseList.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend;
|
||||
|
||||
use App\Builders\CourseUserList as CourseUserListBuilder;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Models\CourseUser as CourseUserModel;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
|
||||
class UserCourseList extends Service
|
||||
{
|
||||
|
||||
use UserTrait;
|
||||
|
||||
public function getCourses($id)
|
||||
{
|
||||
$user = $this->checkUser($id);
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
|
||||
$params['user_id'] = $user->id;
|
||||
$params['role_type'] = CourseUserModel::ROLE_STUDENT;
|
||||
$params['deleted'] = 0;
|
||||
|
||||
$sort = $pagerQuery->getSort();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$courseUserRepo = new CourseUserRepo();
|
||||
|
||||
$pager = $courseUserRepo->paginate($params, $sort, $page, $limit);
|
||||
|
||||
return $this->handleCourses($pager);
|
||||
}
|
||||
|
||||
protected function handleCourses($pager)
|
||||
{
|
||||
if ($pager->total_items == 0) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
$builder = new CourseUserListBuilder();
|
||||
|
||||
$relations = $pager->items->toArray();
|
||||
|
||||
$courses = $builder->getCourses($relations);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
|
||||
$course = $courses[$relation['course_id']] ?? [];
|
||||
|
||||
$items = [
|
||||
'course' => $course,
|
||||
'progress' => $relation['progress'],
|
||||
'duration' => $relation['duration'],
|
||||
];
|
||||
}
|
||||
|
||||
$pager->items = $items;
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
}
|
@ -41,7 +41,9 @@ class LearningSyncer extends Service
|
||||
*/
|
||||
public function addItem(LearningModel $learning, $timeout = 10)
|
||||
{
|
||||
// 兼容秒和毫秒
|
||||
/**
|
||||
* 兼容秒和毫秒
|
||||
*/
|
||||
if ($timeout > 1000) {
|
||||
$timeout = intval($timeout / 1000);
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ namespace App\Services;
|
||||
class Live extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
public function __construct()
|
||||
@ -63,17 +66,26 @@ class Live extends Service
|
||||
$urls = [];
|
||||
|
||||
if ($transEnabled) {
|
||||
|
||||
foreach (['fd', 'sd', 'hd', 'od'] as $rateName) {
|
||||
|
||||
$realStreamName = ($rateName == 'od') ? $streamName : "{$streamName}_{$rateName}";
|
||||
|
||||
$authParams = $this->getAuthParams($realStreamName, $authKey, $expireTime);
|
||||
|
||||
$url = "{$protocol}://{$domain}/{$appName}/{$realStreamName}.{$extension}";
|
||||
$url .= $authEnabled ? "?{$authParams}" : '';
|
||||
|
||||
$urls[$rateName] = $url;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$authParams = $this->getAuthParams($streamName, $authKey, $expireTime);
|
||||
|
||||
$url = "{$protocol}://{$domain}/{$appName}/{$streamName}.{$extension}";
|
||||
$url .= $authEnabled ? "?{$authParams}" : '';
|
||||
|
||||
$urls['od'] = $url;
|
||||
}
|
||||
|
||||
|
@ -2,34 +2,27 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Phalcon\Logger\Adapter\File as FileLogger;
|
||||
use Phalcon\Mailer\Manager as MailerManager;
|
||||
|
||||
class Mailer extends Service
|
||||
abstract class Mailer extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* @var MailerManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* @var FileLogger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->manager = $this->getManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送测试邮件
|
||||
*
|
||||
* @param string $email
|
||||
* @return mixed
|
||||
*/
|
||||
public function sendTestMail($email)
|
||||
{
|
||||
$message = $this->manager->createMessage();
|
||||
|
||||
$result = $message->to($email)
|
||||
->subject('这是一封测试邮件')
|
||||
->content('这是一封测试邮件')
|
||||
->send();
|
||||
|
||||
return $result;
|
||||
$this->logger = $this->getLogger('mailer');
|
||||
}
|
||||
|
||||
/**
|
||||
|
36
app/Services/Mailer/Test.php
Normal file
36
app/Services/Mailer/Test.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Mailer;
|
||||
|
||||
use App\Services\Mailer;
|
||||
|
||||
class Test extends Mailer
|
||||
{
|
||||
|
||||
public function handle($email)
|
||||
{
|
||||
try {
|
||||
|
||||
$message = $this->manager->createMessage();
|
||||
|
||||
$count = $message->to($email)
|
||||
->subject('测试邮件')
|
||||
->content('东风快递,使命必达')
|
||||
->send();
|
||||
|
||||
$result = $count > 0;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->logger->error('Send Test Mail Exception ' . kg_json_encode([
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]));
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
52
app/Services/Mailer/Verify.php
Normal file
52
app/Services/Mailer/Verify.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Mailer;
|
||||
|
||||
use App\Library\Util\Verification;
|
||||
use App\Services\Mailer;
|
||||
|
||||
class Verify extends Mailer
|
||||
{
|
||||
|
||||
public function handle($email)
|
||||
{
|
||||
try {
|
||||
|
||||
$message = $this->manager->createMessage();
|
||||
|
||||
$subject = '邮件验证码';
|
||||
|
||||
$minutes = 5;
|
||||
|
||||
$code = Verification::code($email, 60 * $minutes);
|
||||
|
||||
$content = $this->formatContent($code, $minutes);
|
||||
|
||||
$count = $message->to($email)
|
||||
->subject($subject)
|
||||
->content($content)
|
||||
->send();
|
||||
|
||||
$result = $count > 0;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->logger->error('Send Verify Mail Exception ' . kg_json_encode([
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]));
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function formatContent($code, $minutes)
|
||||
{
|
||||
$content = sprintf('验证码:%s,%s 分钟内有效,如非本人操作请忽略。', $code, $minutes);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
67
app/Services/Payment.php
Normal file
67
app/Services/Payment.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
|
||||
abstract class Payment extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* 交易状态
|
||||
*
|
||||
* @param string $tradeNo
|
||||
* @return string
|
||||
*/
|
||||
public function status($tradeNo)
|
||||
{
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findBySn($tradeNo);
|
||||
|
||||
return $trade->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫码下单
|
||||
*
|
||||
* @param TradeModel $trade
|
||||
*/
|
||||
abstract public function scan(TradeModel $trade);
|
||||
|
||||
/**
|
||||
* 异步通知
|
||||
*/
|
||||
abstract public function notify();
|
||||
|
||||
/**
|
||||
* 查找交易
|
||||
*
|
||||
* @param string $tradeNo
|
||||
*/
|
||||
abstract public function find($tradeNo);
|
||||
|
||||
/**
|
||||
* 关闭交易
|
||||
*
|
||||
* @param string $tradeNo
|
||||
*/
|
||||
abstract public function close($tradeNo);
|
||||
|
||||
/**
|
||||
* 取消交易
|
||||
*
|
||||
* @param string $tradeNo
|
||||
*/
|
||||
abstract public function cancel($tradeNo);
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*
|
||||
* @param RefundModel $refund
|
||||
*/
|
||||
abstract public function refund(RefundModel $refund);
|
||||
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
namespace App\Services\Payment;
|
||||
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Services\Payment;
|
||||
use Yansongda\Pay\Log;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
class Alipay extends Service
|
||||
class Alipay extends Payment
|
||||
{
|
||||
|
||||
/**
|
||||
@ -29,142 +31,23 @@ class Alipay extends Service
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单(扫码生成订单后可执行)
|
||||
* 扫码下单
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function findOrder($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$order = ['out_trade_no' => $outTradeNo];
|
||||
|
||||
$result = $this->gateway->find($order);
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Find Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销订单(未生成订单也可执行)
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function cancelOrder($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$order = ['out_trade_no' => $outTradeNo];
|
||||
|
||||
$result = $this->gateway->cancel($order);
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Cancel Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭订单(扫码生成订单后可执行)
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function closeOrder($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$order = ['out_trade_no' => $outTradeNo];
|
||||
|
||||
$result = $this->gateway->close($order);
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Close Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
*
|
||||
* <code>
|
||||
* $order = [
|
||||
* 'out_trade_no' => '1514027114',
|
||||
* 'refund_amount' => 0.01,
|
||||
* ];
|
||||
* </code>
|
||||
*
|
||||
* @param array $order
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function refundOrder($order)
|
||||
{
|
||||
try {
|
||||
|
||||
$result = $this->gateway->refund($order);
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Refund Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取二维码内容
|
||||
*
|
||||
* <code>
|
||||
* $order = [
|
||||
* 'out_trade_no' =>'1514027114',
|
||||
* 'total_amount' => 0.01,
|
||||
* 'subject' => 'foo',
|
||||
* ];
|
||||
*</code>
|
||||
*
|
||||
* @param array $order
|
||||
* @param TradeModel $trade
|
||||
* @return bool|string
|
||||
*/
|
||||
public function getQrCode($order)
|
||||
public function scan(TradeModel $trade)
|
||||
{
|
||||
try {
|
||||
|
||||
$response = $this->gateway->scan($order);
|
||||
$response = $this->gateway->scan([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_amount' => $trade->amount,
|
||||
'subject' => $trade->subject,
|
||||
]);
|
||||
|
||||
$result = $response->qr_code ?? false;
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Qrcode Exception', [
|
||||
@ -172,14 +55,16 @@ class Alipay extends Service
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理异步通知
|
||||
**/
|
||||
public function handleNotify()
|
||||
* 异步通知
|
||||
*/
|
||||
public function notify()
|
||||
{
|
||||
try {
|
||||
|
||||
@ -229,7 +114,127 @@ class Alipay extends Service
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Alipay Gateway
|
||||
* 查询交易(扫码生成订单后可执行)
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function find($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$result = $this->gateway->find([
|
||||
'out_trade_no' => $outTradeNo,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Find Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭交易(扫码生成订单后可执行)
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return bool
|
||||
*/
|
||||
public function close($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$response = $this->gateway->close([
|
||||
'out_trade_no' => $outTradeNo,
|
||||
]);
|
||||
|
||||
$result = $response->code == '10000';
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Close Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销交易(未生成订单也可执行)
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return bool
|
||||
*/
|
||||
public function cancel($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$response = $this->gateway->cancel([
|
||||
'out_trade_no' => $outTradeNo,
|
||||
]);
|
||||
|
||||
$result = $response->code == '10000';
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Cancel Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*
|
||||
* @param RefundModel $refund
|
||||
* @return bool
|
||||
*/
|
||||
public function refund(RefundModel $refund)
|
||||
{
|
||||
try {
|
||||
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findById($refund->trade_id);
|
||||
|
||||
$response = $this->gateway->refund([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'out_request_no' => $refund->sn,
|
||||
'refund_amount' => $refund->amount,
|
||||
]);
|
||||
|
||||
$result = $response->code == '10000';
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Refund Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Gateway
|
||||
*
|
||||
* @return \Yansongda\Pay\Gateways\Alipay
|
||||
*/
|
@ -1,14 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
namespace App\Services\Payment;
|
||||
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Models\Trade as TradeModel;
|
||||
use App\Repos\Trade as TradeRepo;
|
||||
use App\Services\Payment;
|
||||
use Yansongda\Pay\Gateways\Wechat;
|
||||
use Yansongda\Pay\Log;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
class Wechat extends Service
|
||||
class Wxpay extends Payment
|
||||
{
|
||||
|
||||
/**
|
||||
@ -17,115 +20,50 @@ class Wechat extends Service
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var \Yansongda\Pay\Gateways\Wechat
|
||||
* @var Wechat
|
||||
*/
|
||||
protected $gateway;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = $this->getSectionConfig('payment.wechat');
|
||||
$this->config = $this->getSectionConfig('payment.wxpay');
|
||||
|
||||
$this->gateway = $this->getGateway();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭订单(扫码生成订单后可执行)
|
||||
* 扫码下单
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function closeOrder($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$order = ['out_trade_no' => $outTradeNo];
|
||||
|
||||
$result = $this->gateway->close($order);
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Wechat Close Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
*
|
||||
* <code>
|
||||
* $order = [
|
||||
* 'out_trade_no' => '1514027114',
|
||||
* 'out_refund_no' => '1734027115',
|
||||
* 'total_fee' => 1,
|
||||
* 'refund_fee' => 1,
|
||||
* ];
|
||||
* </code>
|
||||
*
|
||||
* @param array $order
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function refundOrder($order)
|
||||
{
|
||||
try {
|
||||
|
||||
$result = $this->gateway->refund($order);
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Wechat Refund Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取二维码内容
|
||||
*
|
||||
* <code>
|
||||
* $order = [
|
||||
* 'out_trade_no' =>'1514027114',
|
||||
* 'total_fee' => 1,
|
||||
* 'body' => 'foo',
|
||||
* ];
|
||||
*</code>
|
||||
*
|
||||
* @param array $order
|
||||
* @param TradeModel $trade
|
||||
* @return bool|string
|
||||
*/
|
||||
public function getQrCode($order)
|
||||
public function scan(TradeModel $trade)
|
||||
{
|
||||
try {
|
||||
|
||||
$response = $this->gateway->scan($order);
|
||||
$response = $this->gateway->scan([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'total_fee' => 100 * $trade->amount,
|
||||
'body' => $trade->subject,
|
||||
]);
|
||||
|
||||
$result = $response->code_url ?? false;
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Wechat Scan Error', [
|
||||
Log::error('Wxpay Scan Error', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理异步通知
|
||||
* 异步通知
|
||||
*/
|
||||
public function notify()
|
||||
{
|
||||
@ -133,11 +71,11 @@ class Wechat extends Service
|
||||
|
||||
$data = $this->gateway->verify();
|
||||
|
||||
Log::debug('Wechat Verify Data', $data->all());
|
||||
Log::debug('Wxpay Verify Data', $data->all());
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Wechat Verify Error', [
|
||||
Log::error('Wxpay Verify Error', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
@ -175,9 +113,114 @@ class Wechat extends Service
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Wechat Gateway
|
||||
* 查询交易(扫码生成订单后可执行)
|
||||
*
|
||||
* @return \Yansongda\Pay\Gateways\Wechat
|
||||
* @param string $outTradeNo
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function find($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$result = $this->gateway->find([
|
||||
'out_trade_no' => $outTradeNo,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Alipay Find Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭交易(扫码生成订单后可执行)
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return bool
|
||||
*/
|
||||
public function close($outTradeNo)
|
||||
{
|
||||
try {
|
||||
|
||||
$response = $this->gateway->close([
|
||||
'out_trade_no' => $outTradeNo,
|
||||
]);
|
||||
|
||||
$result = $response->result_code == 'SUCCESS';
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Wxpay Close Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消交易
|
||||
*
|
||||
* @param string $outTradeNo
|
||||
* @return bool
|
||||
*/
|
||||
public function cancel($outTradeNo)
|
||||
{
|
||||
$result = $this->close($outTradeNo);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*
|
||||
* @param RefundModel $refund
|
||||
* @return Collection|bool
|
||||
*/
|
||||
public function refund(RefundModel $refund)
|
||||
{
|
||||
try {
|
||||
|
||||
$tradeRepo = new TradeRepo();
|
||||
|
||||
$trade = $tradeRepo->findById($refund->trade_id);
|
||||
|
||||
$response = $this->gateway->refund([
|
||||
'out_trade_no' => $trade->sn,
|
||||
'out_refund_no' => $refund->sn,
|
||||
'total_fee' => 100 * $trade->amount,
|
||||
'refund_fee' => 100 * $refund->amount,
|
||||
]);
|
||||
|
||||
$result = $response->result_code == 'SUCCESS';
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Log::error('Wxpay Refund Order Exception', [
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Gateway
|
||||
*
|
||||
* @return Wechat
|
||||
*/
|
||||
public function getGateway()
|
||||
{
|
||||
@ -191,7 +234,7 @@ class Wechat extends Service
|
||||
'key' => $this->config['key'],
|
||||
'notify_url' => $this->config['notify_url'],
|
||||
'log' => [
|
||||
'file' => log_path('wechat.log'),
|
||||
'file' => log_path('wxpay.log'),
|
||||
'level' => $level,
|
||||
'type' => 'daily',
|
||||
'max_file' => 30,
|
@ -2,74 +2,64 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Qcloud\Sms\SmsMultiSender;
|
||||
use Phalcon\Logger\Adapter\File as FileLogger;
|
||||
use Qcloud\Sms\SmsSingleSender;
|
||||
|
||||
class Smser extends Service
|
||||
Abstract class Smser extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var FileLogger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = $this->getSectionConfig('smser');
|
||||
|
||||
$this->logger = $this->getLogger('smser');
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function resetPassword()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function buyCourse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function buyMember()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送测试短信
|
||||
* 发送短信
|
||||
*
|
||||
* @param string $phone
|
||||
* @param string $phoneNumber
|
||||
* @param string $templateId
|
||||
* @param array $params
|
||||
* @return bool
|
||||
*/
|
||||
public function sendTestMessage($phone)
|
||||
public function send($phoneNumber, $templateId, $params)
|
||||
{
|
||||
$sender = $this->createSingleSender();
|
||||
$templateId = $this->getTemplateId('register');
|
||||
$signature = $this->getSignature();
|
||||
|
||||
$params = [888888, 5];
|
||||
$signature = $this->getSignature();
|
||||
|
||||
try {
|
||||
|
||||
$response = $sender->sendWithParam('86', $phone, $templateId, $params, $signature);
|
||||
$response = $sender->sendWithParam('86', $phoneNumber, $templateId, $params, $signature);
|
||||
|
||||
$this->logger->debug('Send Test Message Response ' . $response);
|
||||
$this->logger->debug('Send Message Response ' . $response);
|
||||
|
||||
$content = json_decode($response, true);
|
||||
|
||||
return $content['result'] == 0 ? true : false;
|
||||
$result = $content['result'] == 0;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->logger->error('Send Test Message Exception ' . kg_json_encode([
|
||||
$this->logger->error('Send Message Exception ' . kg_json_encode([
|
||||
'code' => $e->getCode(),
|
||||
'message' => $e->getMessage(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function createSingleSender()
|
||||
@ -79,20 +69,6 @@ class Smser extends Service
|
||||
return $sender;
|
||||
}
|
||||
|
||||
protected function createMultiSender()
|
||||
{
|
||||
$sender = new SmsMultiSender($this->config['app_id'], $this->config['app_key']);
|
||||
|
||||
return $sender;
|
||||
}
|
||||
|
||||
protected function getRandNumber()
|
||||
{
|
||||
$result = rand(100, 999) . rand(100, 999);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getTemplateId($code)
|
||||
{
|
||||
$template = json_decode($this->config['template'], true);
|
||||
|
50
app/Services/Smser/Live.php
Normal file
50
app/Services/Smser/Live.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Smser;
|
||||
|
||||
use App\Repos\Account as AccountRepo;
|
||||
use App\Repos\Chapter as ChapterRepo;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Services\Smser;
|
||||
|
||||
class Live extends Smser
|
||||
{
|
||||
|
||||
protected $templateCode = 'live';
|
||||
|
||||
/**
|
||||
* @param int $chapterId
|
||||
* @param int $userId
|
||||
* @param int $startTime
|
||||
* @return bool|null
|
||||
*/
|
||||
public function handle($chapterId, $userId, $startTime)
|
||||
{
|
||||
$accountRepo = new AccountRepo();
|
||||
|
||||
$account = $accountRepo->findById($userId);
|
||||
|
||||
if (!$account->phone) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$chapterRepo = new ChapterRepo();
|
||||
|
||||
$chapter = $chapterRepo->findById($chapterId);
|
||||
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$course = $courseRepo->findById($chapter->course_id);
|
||||
|
||||
$params = [
|
||||
$course->title,
|
||||
$chapter->title,
|
||||
$startTime,
|
||||
];
|
||||
|
||||
$templateId = $this->getTemplateId($this->templateCode);
|
||||
|
||||
return $this->send($account->phone, $templateId, $params);
|
||||
}
|
||||
|
||||
}
|
35
app/Services/Smser/Order.php
Normal file
35
app/Services/Smser/Order.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Smser;
|
||||
|
||||
use App\Models\Order as OrderModel;
|
||||
use App\Repos\Account as AccountRepo;
|
||||
use App\Services\Smser;
|
||||
|
||||
class Order extends Smser
|
||||
{
|
||||
|
||||
protected $templateCode = 'order';
|
||||
|
||||
public function handle(OrderModel $order)
|
||||
{
|
||||
$accountRepo = new AccountRepo();
|
||||
|
||||
$account = $accountRepo->findById($order->user_id);
|
||||
|
||||
if (!$account->phone) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$templateId = $this->getTemplateId($this->templateCode);
|
||||
|
||||
$params = [
|
||||
$order->subject,
|
||||
$order->sn,
|
||||
$order->amount,
|
||||
];
|
||||
|
||||
return $this->send($account->phone, $templateId, $params);
|
||||
}
|
||||
|
||||
}
|
35
app/Services/Smser/Refund.php
Normal file
35
app/Services/Smser/Refund.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Smser;
|
||||
|
||||
use App\Models\Refund as RefundModel;
|
||||
use App\Repos\Account as AccountRepo;
|
||||
use App\Services\Smser;
|
||||
|
||||
class Refund extends Smser
|
||||
{
|
||||
|
||||
protected $templateCode = 'refund';
|
||||
|
||||
public function handle(RefundModel $refund)
|
||||
{
|
||||
$accountRepo = new AccountRepo();
|
||||
|
||||
$account = $accountRepo->findById($refund->user_id);
|
||||
|
||||
if (!$account->phone) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$templateId = $this->getTemplateId($this->templateCode);
|
||||
|
||||
$params = [
|
||||
$refund->subject,
|
||||
$refund->sn,
|
||||
$refund->amount,
|
||||
];
|
||||
|
||||
return $this->send($account->phone, $templateId, $params);
|
||||
}
|
||||
|
||||
}
|
19
app/Services/Smser/Test.php
Normal file
19
app/Services/Smser/Test.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Smser;
|
||||
|
||||
use App\Services\Smser;
|
||||
|
||||
class Test extends Smser
|
||||
{
|
||||
|
||||
public function handle($phoneNumber)
|
||||
{
|
||||
$identity = new Verify();
|
||||
|
||||
$result = $identity->handle($phoneNumber);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
26
app/Services/Smser/Verify.php
Normal file
26
app/Services/Smser/Verify.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Smser;
|
||||
|
||||
use App\Library\Util\Verification;
|
||||
use App\Services\Smser;
|
||||
|
||||
class Verify extends Smser
|
||||
{
|
||||
|
||||
protected $templateCode = 'verify';
|
||||
|
||||
public function handle($phone)
|
||||
{
|
||||
$minutes = 5;
|
||||
|
||||
$code = Verification::code($phone, 60 * $minutes);
|
||||
|
||||
$templateId = $this->getTemplateId($this->templateCode);
|
||||
|
||||
$params = [$code, $minutes];
|
||||
|
||||
return $this->send($phone, $templateId, $params);
|
||||
}
|
||||
|
||||
}
|
@ -3,19 +3,33 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\ContentImage as ContentImageModel;
|
||||
use Phalcon\Logger\Adapter\File as FileLogger;
|
||||
use Qcloud\Cos\Client as CosClient;
|
||||
|
||||
class Storage extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var FileLogger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var CosClient
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = $this->getSectionConfig('storage');
|
||||
|
||||
$this->logger = $this->getLogger('storage');
|
||||
|
||||
$this->client = $this->getCosClient();
|
||||
}
|
||||
|
||||
@ -49,7 +63,7 @@ class Storage extends Service
|
||||
/**
|
||||
* 上传内容图片
|
||||
*
|
||||
* @return mixed
|
||||
* @return string|bool
|
||||
*/
|
||||
public function uploadContentImage()
|
||||
{
|
||||
@ -74,7 +88,7 @@ class Storage extends Service
|
||||
/**
|
||||
* 上传头像图片
|
||||
*
|
||||
* @return mixed
|
||||
* @return string|bool
|
||||
*/
|
||||
public function uploadAvatarImage()
|
||||
{
|
||||
@ -87,7 +101,7 @@ class Storage extends Service
|
||||
* 上传图片
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return mixed
|
||||
* @return string|bool
|
||||
*/
|
||||
public function uploadImage($prefix = '')
|
||||
{
|
||||
@ -117,7 +131,7 @@ class Storage extends Service
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $body
|
||||
* @return mixed string|bool
|
||||
* @return string|bool
|
||||
*/
|
||||
public function putString($key, $body)
|
||||
{
|
||||
@ -129,8 +143,6 @@ class Storage extends Service
|
||||
|
||||
$result = $response['Location'] ? $key : false;
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->logger->error('Put String Exception ' . kg_json_encode([
|
||||
@ -138,8 +150,10 @@ class Storage extends Service
|
||||
'message' => $e->getMessage(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,8 +175,6 @@ class Storage extends Service
|
||||
|
||||
$result = $response['Location'] ? $key : false;
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
$this->logger->error('Put File Exception ' . kg_json_encode([
|
||||
@ -170,8 +182,10 @@ class Storage extends Service
|
||||
'message' => $e->getMessage(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,7 +285,7 @@ class Storage extends Service
|
||||
|
||||
$client = new CosClient([
|
||||
'region' => $this->config['bucket_region'],
|
||||
'schema' => 'https',
|
||||
'schema' => $this->config['bucket_protocol'],
|
||||
'credentials' => [
|
||||
'secretId' => $secret['secret_id'],
|
||||
'secretKey' => $secret['secret_key'],
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Phalcon\Logger\Adapter\File as FileLogger;
|
||||
use TencentCloud\Common\Credential;
|
||||
use TencentCloud\Common\Exception\TencentCloudSDKException;
|
||||
use TencentCloud\Common\Profile\ClientProfile;
|
||||
@ -19,14 +20,27 @@ class Vod extends Service
|
||||
|
||||
const END_POINT = 'vod.tencentcloudapi.com';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var VodClient
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var FileLogger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = $this->getSectionConfig('vod');
|
||||
|
||||
$this->logger = $this->getLogger('vod');
|
||||
|
||||
$this->client = $this->getVodClient();
|
||||
}
|
||||
|
||||
@ -49,9 +63,7 @@ class Vod extends Service
|
||||
|
||||
$this->logger->debug('Describe Audio Track Templates Response ' . $response->toJsonString());
|
||||
|
||||
$result = $response->TotalCount > 0 ? true : false;
|
||||
|
||||
return $result;
|
||||
$result = $response->TotalCount > 0;
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
@ -61,8 +73,10 @@ class Vod extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,9 +219,9 @@ class Vod extends Service
|
||||
|
||||
$this->logger->debug('Pull Events Response ' . $response->toJsonString());
|
||||
|
||||
$result = json_decode($response->toJsonString(), true);
|
||||
$data = json_decode($response->toJsonString(), true);
|
||||
|
||||
return $result['EventSet'] ?? [];
|
||||
$result = $data['EventSet'] ?? [];
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
@ -217,8 +231,10 @@ class Vod extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -245,8 +261,6 @@ class Vod extends Service
|
||||
|
||||
$result = json_decode($response->toJsonString(), true);
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
$this->logger->error('Confirm Events Exception ' . kg_json_encode([
|
||||
@ -255,8 +269,10 @@ class Vod extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -289,8 +305,6 @@ class Vod extends Service
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
$this->logger->error('Describe Media Info Exception ' . kg_json_encode([
|
||||
@ -299,8 +313,10 @@ class Vod extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,8 +347,6 @@ class Vod extends Service
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
$this->logger->error('Describe Task Detail Exception ' . kg_json_encode([
|
||||
@ -341,8 +355,10 @@ class Vod extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,13 +380,18 @@ class Vod extends Service
|
||||
$transCodeTaskSet = [];
|
||||
|
||||
foreach ($videoTransTemplates as $key => $template) {
|
||||
|
||||
$caseA = $originVideoInfo['width'] >= $template['width'];
|
||||
$caseB = $originVideoInfo['bit_rate'] >= 1000 * $template['bit_rate'];
|
||||
|
||||
if ($caseA || $caseB) {
|
||||
|
||||
$item = ['Definition' => $key];
|
||||
|
||||
if ($watermarkTemplate) {
|
||||
$item['WatermarkSet'][] = ['Definition' => $watermarkTemplate];
|
||||
}
|
||||
|
||||
$transCodeTaskSet[] = $item;
|
||||
}
|
||||
}
|
||||
@ -379,11 +400,15 @@ class Vod extends Service
|
||||
* 无匹配转码模板,取第一项转码
|
||||
*/
|
||||
if (empty($transCodeTaskSet)) {
|
||||
|
||||
$keys = array_keys($videoTransTemplates);
|
||||
|
||||
$item = ['Definition' => $keys[0]];
|
||||
|
||||
if ($watermarkTemplate) {
|
||||
$item['WatermarkSet'][] = ['Definition' => $watermarkTemplate];
|
||||
}
|
||||
|
||||
$transCodeTaskSet[] = $item;
|
||||
}
|
||||
|
||||
@ -408,8 +433,6 @@ class Vod extends Service
|
||||
|
||||
$result = $response->TaskId ?: false;
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
$this->logger->error('Process Media Exception ' . kg_json_encode([
|
||||
@ -418,8 +441,10 @@ class Vod extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -439,8 +464,11 @@ class Vod extends Service
|
||||
$transCodeTaskSet = [];
|
||||
|
||||
foreach ($audioTransTemplates as $key => $template) {
|
||||
|
||||
if ($originAudioInfo['bit_rate'] >= 1000 * $template['bit_rate']) {
|
||||
|
||||
$item = ['Definition' => $key];
|
||||
|
||||
$transCodeTaskSet[] = $item;
|
||||
}
|
||||
}
|
||||
@ -449,8 +477,11 @@ class Vod extends Service
|
||||
* 无匹配转码模板,取第一项转码
|
||||
*/
|
||||
if (empty($transCodeTaskSet)) {
|
||||
|
||||
$keys = array_keys($audioTransTemplates);
|
||||
|
||||
$item = ['Definition' => $keys[0]];
|
||||
|
||||
$transCodeTaskSet[] = $item;
|
||||
}
|
||||
|
||||
@ -475,8 +506,6 @@ class Vod extends Service
|
||||
|
||||
$result = $response->TaskId ?: false;
|
||||
|
||||
return $result;
|
||||
|
||||
} catch (TencentCloudSDKException $e) {
|
||||
|
||||
$this->logger->error('Process Media Exception ' . kg_json_encode([
|
||||
@ -485,8 +514,10 @@ class Vod extends Service
|
||||
'requestId' => $e->getRequestId(),
|
||||
]));
|
||||
|
||||
return false;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,8 @@ namespace App\Validators;
|
||||
|
||||
use App\Exceptions\BadRequest as BadRequestException;
|
||||
use App\Library\Validator\Common as CommonValidator;
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Models\User as UserModel;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Repos\CourseUser as CourseUserRepo;
|
||||
use App\Repos\User as UserRepo;
|
||||
@ -65,6 +67,16 @@ class CourseUser extends Validator
|
||||
return strtotime($value);
|
||||
}
|
||||
|
||||
public function checkIfAllowApply(CourseModel $course, UserModel $user)
|
||||
{
|
||||
$caseA = $course->market_price > 0;
|
||||
$caseB = $user->vip == 0 && $course->vip_price > 0;
|
||||
|
||||
if ($caseA || $caseB) {
|
||||
throw new BadRequestException('course_user.apply_not_allowed');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkIfJoined($courseId, $userId)
|
||||
{
|
||||
$repo = new CourseUserRepo();
|
||||
@ -72,7 +84,7 @@ class CourseUser extends Validator
|
||||
$courseUser = $repo->findCourseStudent($courseId, $userId);
|
||||
|
||||
if ($courseUser) {
|
||||
throw new BadRequestException('course_user.user_has_joined');
|
||||
throw new BadRequestException('course_user.has_joined_course');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,33 +38,55 @@ class Order extends Validator
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function checkItem($itemId, $itemType)
|
||||
public function checkItemType($itemType)
|
||||
{
|
||||
$list = OrderModel::itemTypes();
|
||||
|
||||
if (!isset($list[$itemType])) {
|
||||
throw new BadRequestException('order.invalid_item_type');
|
||||
}
|
||||
|
||||
return $itemType;
|
||||
}
|
||||
|
||||
public function checkItemCourse($itemId)
|
||||
{
|
||||
if ($itemType == OrderModel::ITEM_COURSE) {
|
||||
$courseRepo = new CourseRepo();
|
||||
|
||||
$item = $courseRepo->findById($itemId);
|
||||
|
||||
if (!$item) {
|
||||
throw new BadRequestException('order.item_not_found');
|
||||
}
|
||||
} elseif ($itemType == OrderModel::ITEM_PACKAGE) {
|
||||
$packageRepo = new PackageRepo();
|
||||
$item = $packageRepo->findById($itemId);
|
||||
if (!$item) {
|
||||
throw new BadRequestException('order.item_not_found');
|
||||
}
|
||||
} elseif ($itemType == OrderModel::ITEM_VIP) {
|
||||
$vipRepo = new VipRepo();
|
||||
$item = $vipRepo->findById($itemId);
|
||||
if (!$item) {
|
||||
throw new BadRequestException('order.item_not_found');
|
||||
}
|
||||
} else {
|
||||
throw new BadRequestException('order.item_not_found');
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function checkItemPackage($itemId)
|
||||
{
|
||||
$packageRepo = new PackageRepo();
|
||||
|
||||
$item = $packageRepo->findById($itemId);
|
||||
|
||||
if (!$item) {
|
||||
throw new BadRequestException('order.item_not_found');
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function checkItemVip($itemId)
|
||||
{
|
||||
$vipRepo = new VipRepo();
|
||||
|
||||
$item = $vipRepo->findById($itemId);
|
||||
|
||||
if (!$item) {
|
||||
throw new BadRequestException('order.item_not_found');
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function checkAmount($amount)
|
||||
{
|
||||
$value = $this->filter->sanitize($amount, ['trim', 'float']);
|
||||
@ -83,18 +105,6 @@ class Order extends Validator
|
||||
}
|
||||
}
|
||||
|
||||
public function checkIfBought($userId, $itemId, $itemType)
|
||||
{
|
||||
switch ($itemType) {
|
||||
case OrderModel::ITEM_COURSE:
|
||||
$this->checkIfBoughtCourse($userId, $itemId);
|
||||
break;
|
||||
case OrderModel::ITEM_PACKAGE:
|
||||
$this->checkIfBoughtPackage($userId, $itemId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function checkIfBoughtCourse($userId, $courseId)
|
||||
{
|
||||
$orderRepo = new OrderRepo();
|
||||
|
@ -27,7 +27,7 @@ class Validator extends Component
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function checkOwnerPriv($userId, $ownerId)
|
||||
public function checkOwner($userId, $ownerId)
|
||||
{
|
||||
if ($userId != $ownerId) {
|
||||
throw new ForbiddenException('sys.access_denied');
|
||||
|
@ -91,10 +91,6 @@ $error['course.invalid_publish_status'] = '无效的发布状态';
|
||||
$error['course.pub_chapter_not_found'] = '尚未发现已发布的课时';
|
||||
$error['course.pub_chapter_not_enough'] = '已发布的课时太少(未过三分之一)';
|
||||
|
||||
$error['course.has_applied'] = '已经参加过该课程了';
|
||||
$error['course.has_not_applied'] = '尚未参加该课程';
|
||||
$error['course.has_reviewed'] = '已经评价过该课程了';
|
||||
|
||||
/**
|
||||
* 话题相关
|
||||
*/
|
||||
@ -121,7 +117,8 @@ $error['package.invalid_publish_status'] = '无效的发布状态';
|
||||
$error['course_user.not_found'] = '课程学员不存在';
|
||||
$error['course_user.course_not_found'] = '课程不存在';
|
||||
$error['course_user.user_not_found'] = '用户不存在';
|
||||
$error['course_user.user_has_joined'] = '课程学员已存在';
|
||||
$error['course_user.apply_not_allowed'] = '当前不允许申请课程';
|
||||
$error['course_user.has_joined_course'] = '已经加入当前课程';
|
||||
$error['course_user.invalid_expiry_time'] = '无效的过期时间';
|
||||
|
||||
/**
|
||||
@ -240,7 +237,6 @@ $error['slide.invalid_publish_status'] = '无效的发布状态';
|
||||
*/
|
||||
$error['order.not_found'] = '订单不存在';
|
||||
$error['order.item_not_found'] = '商品不存在';
|
||||
$error['order.reach_daily_limit'] = '超出每日订单限额';
|
||||
$error['order.close_not_allowed'] = '当前不允许关闭订单';
|
||||
$error['order.has_bought_course'] = '已经够买过该课程';
|
||||
$error['order.has_bought_package'] = '已经够买过该套餐';
|
||||
|
@ -161,14 +161,19 @@ img.kg-cover {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.kg-qrcode-block .layui-icon-close-fill {
|
||||
.kg-error-tips {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.kg-qrcode-block .layui-icon-ok-circle {
|
||||
.kg-success-tips {
|
||||
color: green;
|
||||
}
|
||||
|
||||
img.kg-qrcode {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.kg-order-date {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
@ -17,11 +17,14 @@ $scheduler->php($script, $bin, ['--task' => 'process_order', '--action' => 'main
|
||||
->at('*/5 * * * *');
|
||||
|
||||
$scheduler->php($script, $bin, ['--task' => 'vod_event', '--action' => 'main'])
|
||||
->at('*/7 * * * *');
|
||||
->at('*/5 * * * *');
|
||||
|
||||
$scheduler->php($script, $bin, ['--task' => 'close_trade', '--action' => 'main'])
|
||||
->at('*/10 * * * *');
|
||||
|
||||
$scheduler->php($script, $bin, ['--task' => 'live_notice_consumer', '--action' => 'main'])
|
||||
->at('*/15 * * * *');
|
||||
|
||||
$scheduler->php($script, $bin, ['--task' => 'close_order', '--action' => 'main'])
|
||||
->hourly(3);
|
||||
|
||||
@ -43,4 +46,7 @@ $scheduler->php($script, $bin, ['--task' => 'revoke_vip', '--action' => 'main'])
|
||||
$scheduler->php($script, $bin, ['--task' => 'count_course', '--action' => 'main'])
|
||||
->daily(3, 17);
|
||||
|
||||
$scheduler->php($script, $bin, ['--task' => 'live_notice_provider', '--action' => 'main'])
|
||||
->daily(3, 23);
|
||||
|
||||
$scheduler->run();
|
Loading…
x
Reference in New Issue
Block a user