mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-26 20:52:44 +08:00
完成前端支付逻辑
This commit is contained in:
parent
eaa593a274
commit
cf5cd3ea51
@ -21,6 +21,7 @@ class CleanLogTask extends Task
|
|||||||
$this->cleanStorageLog();
|
$this->cleanStorageLog();
|
||||||
$this->cleanAlipayLog();
|
$this->cleanAlipayLog();
|
||||||
$this->cleanWxpayLog();
|
$this->cleanWxpayLog();
|
||||||
|
$this->cleanOrderLog();
|
||||||
$this->cleanRefundLog();
|
$this->cleanRefundLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +121,14 @@ class CleanLogTask extends Task
|
|||||||
$this->cleanLog('wxpay', 30);
|
$this->cleanLog('wxpay', 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理订单日志
|
||||||
|
*/
|
||||||
|
protected function cleanOrderLog()
|
||||||
|
{
|
||||||
|
$this->cleanLog('order', 30);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理退款日志
|
* 清理退款日志
|
||||||
*/
|
*/
|
||||||
|
@ -13,7 +13,6 @@ use App\Repos\CourseUser as CourseUserRepo;
|
|||||||
use App\Repos\Order as OrderRepo;
|
use App\Repos\Order as OrderRepo;
|
||||||
use App\Repos\User as UserRepo;
|
use App\Repos\User as UserRepo;
|
||||||
use App\Services\Smser\Order as OrderSmser;
|
use App\Services\Smser\Order as OrderSmser;
|
||||||
use Phalcon\Cli\Task;
|
|
||||||
use Phalcon\Mvc\Model;
|
use Phalcon\Mvc\Model;
|
||||||
use Phalcon\Mvc\Model\Resultset;
|
use Phalcon\Mvc\Model\Resultset;
|
||||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||||
@ -25,6 +24,8 @@ class OrderTask extends Task
|
|||||||
|
|
||||||
public function mainAction()
|
public function mainAction()
|
||||||
{
|
{
|
||||||
|
$logger = $this->getLogger('order');
|
||||||
|
|
||||||
$tasks = $this->findTasks();
|
$tasks = $this->findTasks();
|
||||||
|
|
||||||
if ($tasks->count() == 0) {
|
if ($tasks->count() == 0) {
|
||||||
@ -77,6 +78,13 @@ class OrderTask extends Task
|
|||||||
}
|
}
|
||||||
|
|
||||||
$task->update();
|
$task->update();
|
||||||
|
|
||||||
|
$logger->info('Order Task Exception ' . kg_json_encode([
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'code' => $e->getCode(),
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'task' => $task->toArray(),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,7 +106,7 @@ class OrderTask extends Task
|
|||||||
$data = [
|
$data = [
|
||||||
'user_id' => $order->user_id,
|
'user_id' => $order->user_id,
|
||||||
'course_id' => $order->item_id,
|
'course_id' => $order->item_id,
|
||||||
'expiry_time' => $itemInfo['course']['expiry_time'],
|
'expiry_time' => $itemInfo['course']['study_expiry_time'],
|
||||||
'role_type' => CourseUserModel::ROLE_STUDENT,
|
'role_type' => CourseUserModel::ROLE_STUDENT,
|
||||||
'source_type' => CourseUserModel::SOURCE_CHARGE,
|
'source_type' => CourseUserModel::SOURCE_CHARGE,
|
||||||
];
|
];
|
||||||
@ -124,7 +132,7 @@ class OrderTask extends Task
|
|||||||
$data = [
|
$data = [
|
||||||
'user_id' => $order->user_id,
|
'user_id' => $order->user_id,
|
||||||
'course_id' => $course['id'],
|
'course_id' => $course['id'],
|
||||||
'expiry_time' => $course['expiry_time'],
|
'expiry_time' => $course['study_expiry_time'],
|
||||||
'role_type' => CourseUserModel::ROLE_STUDENT,
|
'role_type' => CourseUserModel::ROLE_STUDENT,
|
||||||
'source_type' => CourseUserModel::SOURCE_CHARGE,
|
'source_type' => CourseUserModel::SOURCE_CHARGE,
|
||||||
];
|
];
|
||||||
@ -179,7 +187,7 @@ class OrderTask extends Task
|
|||||||
|
|
||||||
$refund->subject = $order->subject;
|
$refund->subject = $order->subject;
|
||||||
$refund->amount = $order->amount;
|
$refund->amount = $order->amount;
|
||||||
$refund->apply_note = '开通失败,自动退款';
|
$refund->apply_note = '开通服务失败,自动退款';
|
||||||
$refund->review_note = '自动操作';
|
$refund->review_note = '自动操作';
|
||||||
$refund->user_id = $order->user_id;
|
$refund->user_id = $order->user_id;
|
||||||
$refund->order_id = $order->id;
|
$refund->order_id = $order->id;
|
||||||
@ -214,7 +222,7 @@ class OrderTask extends Task
|
|||||||
/**
|
/**
|
||||||
* @param int $courseId
|
* @param int $courseId
|
||||||
* @param int $userId
|
* @param int $userId
|
||||||
* @return ResultsetInterface|Resultset|TaskModel[]
|
* @return ResultsetInterface|Resultset|CourseUserModel[]
|
||||||
*/
|
*/
|
||||||
protected function findPlanChapterUsers($courseId, $userId)
|
protected function findPlanChapterUsers($courseId, $userId)
|
||||||
{
|
{
|
||||||
@ -228,7 +236,7 @@ class OrderTask extends Task
|
|||||||
/**
|
/**
|
||||||
* @param int $courseId
|
* @param int $courseId
|
||||||
* @param int $userId
|
* @param int $userId
|
||||||
* @return ResultsetInterface|Resultset|TaskModel[]
|
* @return ResultsetInterface|Resultset|CourseUserModel[]
|
||||||
*/
|
*/
|
||||||
protected function findPlanLearnings($courseId, $userId)
|
protected function findPlanLearnings($courseId, $userId)
|
||||||
{
|
{
|
||||||
@ -267,7 +275,7 @@ class OrderTask extends Task
|
|||||||
return TaskModel::query()
|
return TaskModel::query()
|
||||||
->where('item_type = :item_type:', ['item_type' => $itemType])
|
->where('item_type = :item_type:', ['item_type' => $itemType])
|
||||||
->andWhere('status = :status:', ['status' => $status])
|
->andWhere('status = :status:', ['status' => $status])
|
||||||
->andWhere('try_count < :try_count:', ['try_count' => $tryCount])
|
->andWhere('try_count < :try_count:', ['try_count' => $tryCount + 1])
|
||||||
->orderBy('priority ASC')
|
->orderBy('priority ASC')
|
||||||
->limit($limit)
|
->limit($limit)
|
||||||
->execute();
|
->execute();
|
||||||
|
@ -97,13 +97,15 @@ class RefundTask extends Task
|
|||||||
$task->try_count += 1;
|
$task->try_count += 1;
|
||||||
$task->priority += 1;
|
$task->priority += 1;
|
||||||
|
|
||||||
if ($task->try_count >= self::TRY_COUNT) {
|
if ($task->try_count > self::TRY_COUNT) {
|
||||||
$task->status = TaskModel::STATUS_FAILED;
|
$task->status = TaskModel::STATUS_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$task->update();
|
$task->update();
|
||||||
|
|
||||||
$logger->info('Refund Task Exception ' . kg_json_encode([
|
$logger->info('Refund Task Exception ' . kg_json_encode([
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'code' => $e->getCode(),
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
'task' => $task->toArray(),
|
'task' => $task->toArray(),
|
||||||
]));
|
]));
|
||||||
@ -186,7 +188,7 @@ class RefundTask extends Task
|
|||||||
$courseUser->deleted = 1;
|
$courseUser->deleted = 1;
|
||||||
|
|
||||||
if ($courseUser->update() === false) {
|
if ($courseUser->update() === false) {
|
||||||
throw new \RuntimeException('Delete CourseQuery User Failed');
|
throw new \RuntimeException('Delete Course User Failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +216,7 @@ class RefundTask extends Task
|
|||||||
$courseUser->deleted = 1;
|
$courseUser->deleted = 1;
|
||||||
|
|
||||||
if ($courseUser->update() === false) {
|
if ($courseUser->update() === false) {
|
||||||
throw new \RuntimeException('Delete CourseQuery User Failed');
|
throw new \RuntimeException('Delete Course User Failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,7 +295,7 @@ class RefundTask extends Task
|
|||||||
return TaskModel::query()
|
return TaskModel::query()
|
||||||
->where('item_type = :item_type:', ['item_type' => $itemType])
|
->where('item_type = :item_type:', ['item_type' => $itemType])
|
||||||
->andWhere('status = :status:', ['status' => $status])
|
->andWhere('status = :status:', ['status' => $status])
|
||||||
->andWhere('try_count < :try_count:', ['try_count' => $tryCount])
|
->andWhere('try_count < :try_count:', ['try_count' => $tryCount + 1])
|
||||||
->orderBy('priority ASC')
|
->orderBy('priority ASC')
|
||||||
->limit($limit)
|
->limit($limit)
|
||||||
->execute();
|
->execute();
|
||||||
|
@ -77,11 +77,11 @@ class TestController extends Controller
|
|||||||
['text' => urlencode($pushUrl)]
|
['text' => urlencode($pushUrl)]
|
||||||
);
|
);
|
||||||
|
|
||||||
$obs = new \stdClass();
|
$obs = [];
|
||||||
|
|
||||||
$position = strrpos($pushUrl, '/');
|
$pos = strrpos($pushUrl, '/');
|
||||||
$obs->fms_url = substr($pushUrl, 0, $position + 1);
|
$obs['fms_url'] = substr($pushUrl, 0, $pos + 1);
|
||||||
$obs->stream_code = substr($pushUrl, $position + 1);
|
$obs['stream_code'] = substr($pushUrl, $pos + 1);
|
||||||
|
|
||||||
$this->view->pick('setting/live_push_test');
|
$this->view->pick('setting/live_push_test');
|
||||||
$this->view->setVar('code_url', $codeUrl);
|
$this->view->setVar('code_url', $codeUrl);
|
||||||
@ -176,29 +176,29 @@ class TestController extends Controller
|
|||||||
|
|
||||||
$order = $alipayTestService->createOrder();
|
$order = $alipayTestService->createOrder();
|
||||||
$trade = $alipayTestService->createTrade($order);
|
$trade = $alipayTestService->createTrade($order);
|
||||||
$codeUrl = $alipayTestService->scan($trade);
|
$qrcodeUrl = $alipayTestService->scan($trade);
|
||||||
|
|
||||||
if ($order && $trade && $codeUrl) {
|
if ($order && $trade && $qrcodeUrl) {
|
||||||
$this->db->commit();
|
$this->db->commit();
|
||||||
} else {
|
} else {
|
||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->pick('setting/pay_alipay_test');
|
$this->view->pick('setting/pay_alipay_test');
|
||||||
$this->view->setVar('trade_sn', $trade->sn);
|
$this->view->setVar('sn', $trade->sn);
|
||||||
$this->view->setVar('code_url', $codeUrl);
|
$this->view->setVar('qrcode_url', $qrcodeUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Post("/alipay/status", name="admin.test.alipay_status")
|
* @Get("/alipay/status", name="admin.test.alipay_status")
|
||||||
*/
|
*/
|
||||||
public function alipayStatusAction()
|
public function alipayStatusAction()
|
||||||
{
|
{
|
||||||
$tradeSn = $this->request->getPost('trade_sn');
|
$sn = $this->request->getQuery('sn');
|
||||||
|
|
||||||
$alipayTestService = new AlipayTestService();
|
$alipayTestService = new AlipayTestService();
|
||||||
|
|
||||||
$status = $alipayTestService->status($tradeSn);
|
$status = $alipayTestService->status($sn);
|
||||||
|
|
||||||
return $this->jsonSuccess(['status' => $status]);
|
return $this->jsonSuccess(['status' => $status]);
|
||||||
}
|
}
|
||||||
@ -208,11 +208,11 @@ class TestController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function alipayCancelAction()
|
public function alipayCancelAction()
|
||||||
{
|
{
|
||||||
$tradeSn = $this->request->getPost('trade_sn');
|
$sn = $this->request->getPost('sn');
|
||||||
|
|
||||||
$alipayTestService = new AlipayTestService();
|
$alipayTestService = new AlipayTestService();
|
||||||
|
|
||||||
$alipayTestService->cancel($tradeSn);
|
$alipayTestService->cancel($sn);
|
||||||
|
|
||||||
return $this->jsonSuccess(['msg' => '取消订单成功']);
|
return $this->jsonSuccess(['msg' => '取消订单成功']);
|
||||||
}
|
}
|
||||||
@ -228,29 +228,29 @@ class TestController extends Controller
|
|||||||
|
|
||||||
$order = $wxpayTestService->createOrder();
|
$order = $wxpayTestService->createOrder();
|
||||||
$trade = $wxpayTestService->createTrade($order);
|
$trade = $wxpayTestService->createTrade($order);
|
||||||
$codeUrl = $wxpayTestService->scan($trade);
|
$qrcodeUrl = $wxpayTestService->scan($trade);
|
||||||
|
|
||||||
if ($order && $trade && $codeUrl) {
|
if ($order && $trade && $qrcodeUrl) {
|
||||||
$this->db->commit();
|
$this->db->commit();
|
||||||
} else {
|
} else {
|
||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->pick('setting/pay_wxpay_test');
|
$this->view->pick('setting/pay_wxpay_test');
|
||||||
$this->view->setVar('trade_sn', $trade->sn);
|
$this->view->setVar('sn', $trade->sn);
|
||||||
$this->view->setVar('code_url', $codeUrl);
|
$this->view->setVar('qrcode_url', $qrcodeUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Post("/wxpay/status", name="admin.test.wxpay_status")
|
* @Get("/wxpay/status", name="admin.test.wxpay_status")
|
||||||
*/
|
*/
|
||||||
public function wxpayStatusAction()
|
public function wxpayStatusAction()
|
||||||
{
|
{
|
||||||
$tradeSn = $this->request->getPost('trade_sn');
|
$sn = $this->request->getQuery('sn');
|
||||||
|
|
||||||
$wxpayTestService = new WxpayTestService();
|
$wxpayTestService = new WxpayTestService();
|
||||||
|
|
||||||
$status = $wxpayTestService->status($tradeSn);
|
$status = $wxpayTestService->status($sn);
|
||||||
|
|
||||||
return $this->jsonSuccess(['status' => $status]);
|
return $this->jsonSuccess(['status' => $status]);
|
||||||
}
|
}
|
||||||
@ -260,11 +260,11 @@ class TestController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function wxpayCancelAction()
|
public function wxpayCancelAction()
|
||||||
{
|
{
|
||||||
$tradeSn = $this->request->getPost('trade_sn');
|
$sn = $this->request->getPost('sn');
|
||||||
|
|
||||||
$wxpayTestService = new WxpayTestService();
|
$wxpayTestService = new WxpayTestService();
|
||||||
|
|
||||||
$wxpayTestService->cancel($tradeSn);
|
$wxpayTestService->cancel($sn);
|
||||||
|
|
||||||
return $this->jsonSuccess(['msg' => '取消订单成功']);
|
return $this->jsonSuccess(['msg' => '取消订单成功']);
|
||||||
}
|
}
|
||||||
|
@ -104,12 +104,7 @@ class UserController extends Controller
|
|||||||
$userService->updateAccount($id);
|
$userService->updateAccount($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$location = $this->url->get(['for' => 'admin.user.list']);
|
$content = ['msg' => '更新用户成功'];
|
||||||
|
|
||||||
$content = [
|
|
||||||
'location' => $location,
|
|
||||||
'msg' => '更新用户成功',
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->jsonSuccess($content);
|
return $this->jsonSuccess($content);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
type: 2,
|
type: 2,
|
||||||
title: '支付宝 - 支付测试',
|
title: '支付宝 - 支付测试',
|
||||||
resize: false,
|
resize: false,
|
||||||
area: ['480px', '300px'],
|
area: ['640px', '300px'],
|
||||||
content: [url, 'no']
|
content: [url, 'no']
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<div class="kg-qrcode-block">
|
<div class="kg-qrcode-block">
|
||||||
|
|
||||||
{% if code_url %}
|
{% if qrcode_url %}
|
||||||
|
|
||||||
<div id="qrcode">
|
<div id="qrcode">
|
||||||
<img class="kg-qrcode" src="{{ code_url }}" alt="二维码图片">
|
<img class="kg-qrcode" src="{{ qrcode_url }}" alt="二维码图片">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="trade_sn" value="{{ trade_sn }}">
|
<input type="hidden" name="sn" value="{{ sn }}">
|
||||||
|
|
||||||
<div id="success-tips" class="kg-success-tips layui-hide">
|
<div id="success-tips" class="kg-success-tips layui-hide">
|
||||||
<span>支付成功</span>
|
<span>支付成功</span>
|
||||||
@ -26,19 +26,19 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if code_url %}
|
{% if qrcode_url %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
layui.use(['jquery'], function () {
|
layui.use(['jquery'], function () {
|
||||||
|
|
||||||
var $ = layui.jquery;
|
var $ = layui.jquery;
|
||||||
var tradeSn = $('input[name=trade_sn]').val();
|
var sn = $('input[name=sn]').val();
|
||||||
var interval = setInterval(function () {
|
var interval = setInterval(function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'GET',
|
||||||
url: '/admin/test/alipay/status',
|
url: '/admin/test/alipay/status',
|
||||||
data: {trade_sn: tradeSn},
|
data: {sn: sn},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
if (res.status === 'finished') {
|
if (res.status === 'finished') {
|
||||||
$('#success-tips').removeClass('layui-hide');
|
$('#success-tips').removeClass('layui-hide');
|
||||||
|
@ -90,7 +90,7 @@
|
|||||||
type: 2,
|
type: 2,
|
||||||
title: '微信 - 支付测试',
|
title: '微信 - 支付测试',
|
||||||
resize: false,
|
resize: false,
|
||||||
area: ['480px', '270px'],
|
area: ['640px', '300px'],
|
||||||
content: [url, 'no']
|
content: [url, 'no']
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<div class="kg-qrcode-block">
|
<div class="kg-qrcode-block">
|
||||||
|
|
||||||
{% if code_url %}
|
{% if qrcode_url %}
|
||||||
|
|
||||||
<div id="qrcode">
|
<div id="qrcode">
|
||||||
<img class="kg-qrcode" src="{{ code_url }}" alt="二维码图片">
|
<img class="kg-qrcode" src="{{ qrcode_url }}" alt="二维码图片">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="trade_sn" value="{{ trade_sn }}">
|
<input type="hidden" name="sn" value="{{ sn }}">
|
||||||
|
|
||||||
<div id="success-tips" class="kg-success-tips layui-hide">
|
<div id="success-tips" class="kg-success-tips layui-hide">
|
||||||
<span>支付成功</span>
|
<span>支付成功</span>
|
||||||
@ -26,19 +26,19 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if code_url %}
|
{% if qrcode_url %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
layui.use(['jquery'], function () {
|
layui.use(['jquery'], function () {
|
||||||
|
|
||||||
var $ = layui.jquery;
|
var $ = layui.jquery;
|
||||||
var tradeSn = $('input[name=trade_sn]').val();
|
var sn = $('input[name=sn]').val();
|
||||||
var interval = setInterval(function () {
|
var interval = setInterval(function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'GET',
|
||||||
url: '/admin/test/wxpay/status',
|
url: '/admin/test/wxpay/status',
|
||||||
data: {trade_sn: tradeSn},
|
data: {sn: sn},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
if (res.status === 'finished') {
|
if (res.status === 'finished') {
|
||||||
$('#success-tips').removeClass('layui-hide');
|
$('#success-tips').removeClass('layui-hide');
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">加入方式</label>
|
<label class="layui-form-label">加入方式</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<input type="radio" name="source" value="1" title="免费课程">
|
<input type="radio" name="source_type" value="1" title="免费课程">
|
||||||
<input type="radio" name="source" value="2" title="付费课程">
|
<input type="radio" name="source_type" value="2" title="付费课程">
|
||||||
<input type="radio" name="source" value="3" title="后台导入">
|
<input type="radio" name="source_type" value="3" title="后台导入">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">教学角色</label>
|
<label class="layui-form-label">教学角色</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<input type="radio" name="edu_role" value="student" title="学员" {% if user.edu_role == 'student' %}checked{% endif %}>
|
<input type="radio" name="edu_role" value="1" title="学员" {% if user.edu_role == '1' %}checked{% endif %}>
|
||||||
<input type="radio" name="edu_role" value="teacher" title="讲师" {% if user.edu_role == 'teacher' %}checked{% endif %}>
|
<input type="radio" name="edu_role" value="2" title="讲师" {% if user.edu_role == '2' %}checked{% endif %}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@ class CourseController extends Controller
|
|||||||
|
|
||||||
$service = new RewardOptionList();
|
$service = new RewardOptionList();
|
||||||
|
|
||||||
$rewardOptions = $service->handle();
|
$rewards = $service->handle();
|
||||||
|
|
||||||
$this->view->setVar('course', $course);
|
$this->view->setVar('course', $course);
|
||||||
$this->view->setVar('chapters', $chapters);
|
$this->view->setVar('chapters', $chapters);
|
||||||
$this->view->setVar('teachers', $teachers);
|
$this->view->setVar('teachers', $teachers);
|
||||||
$this->view->setVar('reward_options', $rewardOptions);
|
$this->view->setVar('rewards', $rewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Web\Controllers;
|
namespace App\Http\Web\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Order as OrderModel;
|
||||||
use App\Services\Frontend\Order\OrderCancel as OrderCancelService;
|
use App\Services\Frontend\Order\OrderCancel as OrderCancelService;
|
||||||
use App\Services\Frontend\Order\OrderConfirm as OrderConfirmService;
|
use App\Services\Frontend\Order\OrderConfirm as OrderConfirmService;
|
||||||
use App\Services\Frontend\Order\OrderCreate as OrderCreateService;
|
use App\Services\Frontend\Order\OrderCreate as OrderCreateService;
|
||||||
@ -37,28 +38,36 @@ class OrderController extends Controller
|
|||||||
|
|
||||||
$order = $service->handle();
|
$order = $service->handle();
|
||||||
|
|
||||||
$location = $this->url->get(['for' => 'web.order.pay', 'sn' => $order->sn]);
|
$location = $this->url->get(['for' => 'web.order.pay'], ['sn' => $order->sn]);
|
||||||
|
|
||||||
return $this->jsonSuccess(['location' => $location]);
|
return $this->jsonSuccess(['location' => $location]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Get("/{sn:[0-9]+}/pay", name="web.order.pay")
|
* @Get("/pay", name="web.order.pay")
|
||||||
*/
|
*/
|
||||||
public function payAction($sn)
|
public function payAction()
|
||||||
{
|
{
|
||||||
|
$sn = $this->request->getQuery('sn');
|
||||||
|
|
||||||
$service = new OrderInfoService();
|
$service = new OrderInfoService();
|
||||||
|
|
||||||
$order = $service->handle($sn);
|
$order = $service->handle($sn);
|
||||||
|
|
||||||
|
if ($order['status'] != OrderModel::STATUS_PENDING) {
|
||||||
|
$this->response->redirect(['for' => 'web.my.orders']);
|
||||||
|
}
|
||||||
|
|
||||||
$this->view->setVar('order', $order);
|
$this->view->setVar('order', $order);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Get("/{sn:[0-9]+}/info", name="web.order.info")
|
* @Get("/info", name="web.order.info")
|
||||||
*/
|
*/
|
||||||
public function infoAction($sn)
|
public function infoAction()
|
||||||
{
|
{
|
||||||
|
$sn = $this->request->getQuery('sn');
|
||||||
|
|
||||||
$service = new OrderInfoService();
|
$service = new OrderInfoService();
|
||||||
|
|
||||||
$order = $service->handle($sn);
|
$order = $service->handle($sn);
|
||||||
@ -67,10 +76,12 @@ class OrderController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Post("/{sn:[0-9]+}/cancel", name="web.order.cancel")
|
* @Post("/cancel", name="web.order.cancel")
|
||||||
*/
|
*/
|
||||||
public function cancelAction($sn)
|
public function cancelAction()
|
||||||
{
|
{
|
||||||
|
$sn = $this->request->getPost('sn');
|
||||||
|
|
||||||
$service = new OrderCancelService();
|
$service = new OrderCancelService();
|
||||||
|
|
||||||
$order = $service->handle($sn);
|
$order = $service->handle($sn);
|
||||||
|
@ -24,15 +24,17 @@ class TradeController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Get("/{sn:[0-9]+}/status", name="web.trade.status")
|
* @Get("/status", name="web.trade.status")
|
||||||
*/
|
*/
|
||||||
public function statusAction($sn)
|
public function statusAction()
|
||||||
{
|
{
|
||||||
|
$sn = $this->request->getQuery('sn');
|
||||||
|
|
||||||
$service = new TradeInfoService();
|
$service = new TradeInfoService();
|
||||||
|
|
||||||
$trade = $service->handle($sn);
|
$trade = $service->handle($sn);
|
||||||
|
|
||||||
return $this->jsonSuccess(['status' => $trade->status]);
|
return $this->jsonSuccess(['status' => $trade['status']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ use App\Exceptions\BadRequest as BadRequestException;
|
|||||||
use App\Models\Trade as TradeModel;
|
use App\Models\Trade as TradeModel;
|
||||||
use App\Services\Frontend\Trade\TradeCreate as TradeCreateService;
|
use App\Services\Frontend\Trade\TradeCreate as TradeCreateService;
|
||||||
use App\Services\Pay\Alipay as AlipayService;
|
use App\Services\Pay\Alipay as AlipayService;
|
||||||
|
use App\Services\Pay\Wxpay as WxpayService;
|
||||||
|
|
||||||
class Trade extends Service
|
class Trade extends Service
|
||||||
{
|
{
|
||||||
@ -39,12 +40,25 @@ class Trade extends Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function getQrCodeUrl(TradeModel $trade)
|
protected function getQrCodeUrl(TradeModel $trade)
|
||||||
|
{
|
||||||
|
$qrcodeUrl = null;
|
||||||
|
|
||||||
|
if ($trade->channel == TradeModel::CHANNEL_ALIPAY) {
|
||||||
|
$qrcodeUrl = $this->getAlipayQrCodeUrl($trade);
|
||||||
|
} elseif ($trade->channel == TradeModel::CHANNEL_WXPAY) {
|
||||||
|
$qrcodeUrl = $this->getWxpayQrCodeUrl($trade);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $qrcodeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getAlipayQrCodeUrl(TradeModel $trade)
|
||||||
{
|
{
|
||||||
$qrCodeUrl = null;
|
$qrCodeUrl = null;
|
||||||
|
|
||||||
$alipayService = new AlipayService();
|
$service = new AlipayService();
|
||||||
|
|
||||||
$text = $alipayService->scan($trade);
|
$text = $service->scan($trade);
|
||||||
|
|
||||||
if ($text) {
|
if ($text) {
|
||||||
$qrCodeUrl = $this->url->get(
|
$qrCodeUrl = $this->url->get(
|
||||||
@ -56,4 +70,11 @@ class Trade extends Service
|
|||||||
return $qrCodeUrl;
|
return $qrCodeUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getWxpayQrCodeUrl(TradeModel $trade)
|
||||||
|
{
|
||||||
|
$service = new WxpayService();
|
||||||
|
|
||||||
|
return $service->scan($trade);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
<div class="layui-card-header">赞赏支持</div>
|
<div class="layui-card-header">赞赏支持</div>
|
||||||
<div class="layui-card-body">
|
<div class="layui-card-body">
|
||||||
<div class="sidebar-order">
|
<div class="sidebar-order">
|
||||||
{% for option in reward_options %}
|
{% for reward in rewards %}
|
||||||
{% set item_id = [course.id,option.id]|join('-') %}
|
{% set item_id = [course.id,reward.id]|join('-') %}
|
||||||
{% set order_url = url({'for':'web.order.confirm'},{'item_id':item_id,'item_type':'reward'}) %}
|
{% set order_url = url({'for':'web.order.confirm'},{'item_id':item_id,'item_type':'reward'}) %}
|
||||||
<a class="layui-btn layui-btn-xs reward-btn" href="{{ order_url }}">{{ option.title }}</a>
|
<a class="layui-btn layui-btn-xs reward-btn" href="{{ order_url }}">{{ reward.title }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,14 +2,6 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{%- macro reward_course_card(reward) %}
|
|
||||||
<div>I am reward</div>
|
|
||||||
{%- endmacro %}
|
|
||||||
|
|
||||||
{%- macro vip_course_card(vip) %}
|
|
||||||
<div>I am vip</div>
|
|
||||||
{%- endmacro %}
|
|
||||||
|
|
||||||
<div class="layui-breadcrumb breadcrumb">
|
<div class="layui-breadcrumb breadcrumb">
|
||||||
<a href="/">首页</a>
|
<a href="/">首页</a>
|
||||||
<a><cite>支付订单</cite></a>
|
<a><cite>支付订单</cite></a>
|
||||||
@ -22,12 +14,79 @@
|
|||||||
支付金额:<span class="amount">¥{{ order.amount }}</span>
|
支付金额:<span class="amount">¥{{ order.amount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="channel">
|
<div class="channel">
|
||||||
<a class="alipay" href="javascript:"></a>
|
{% set create_url = url({'for':'web.trade.create'}) %}
|
||||||
<a class="wxpay" href="javascript:"></a>
|
{% set status_url = url({'for':'web.trade.status'}) %}
|
||||||
|
<a class="alipay pay-btn" href="javascript:" data-channel="alipay"></a>
|
||||||
|
<a class="wxpay pay-btn" href="javascript:" data-channel="wxpay"></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<span class="tips">友情提示:请在12小时内完成支付,有问题请联系客服</span>
|
<span class="tips">友情提示:请在12小时内完成支付,有问题请联系客服</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="alipay-qr-box" class="layui-hide"></div>
|
||||||
|
<div id="wxpay-qr-box" class="layui-hide"></div>
|
||||||
|
|
||||||
|
<div class="layui-hide">
|
||||||
|
<input type="hidden" name="trade_create_url" value="{{ url({'for':'web.trade.create'}) }}">
|
||||||
|
<input type="hidden" name="trade_status_url" value="{{ url({'for':'web.trade.status'}) }}">
|
||||||
|
<input type="hidden" name="forward_url" value="{{ url({'for':'web.course.list'}) }}">
|
||||||
|
<input type="hidden" name="order_sn" value="{{ order.sn }}">
|
||||||
|
<input type="hidden" name="alipay_trade_sn" value="">
|
||||||
|
<input type="hidden" name="wxpay_trade_sn" value="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block inline_js %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var $ = layui.jquery;
|
||||||
|
var layer = layui.layer;
|
||||||
|
var showQrLayer = function (title, content) {
|
||||||
|
layer.open({
|
||||||
|
type: 1,
|
||||||
|
id: 'pay-layer',
|
||||||
|
title: title,
|
||||||
|
content: content,
|
||||||
|
area: ['640px', '320px']
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$('.pay-btn').on('click', function () {
|
||||||
|
var channel = $(this).attr('data-channel');
|
||||||
|
var createUrl = $('input[name=trade_create_url]').val();
|
||||||
|
var statusUrl = $('input[name=trade_status_url]').val();
|
||||||
|
var forwardUrl = $('input[name=forward_url]').val();
|
||||||
|
var orderSn = $('input[name=order_sn]').val();
|
||||||
|
var $qrBox = $('#' + channel + '-qr-box');
|
||||||
|
var $snInput = $('input[name=' + channel + '_trade_sn]');
|
||||||
|
var qrTitle = channel === 'alipay' ? '支付宝扫码支付' : '微信扫码支付';
|
||||||
|
var qrHtml = $qrBox.html();
|
||||||
|
if (qrHtml.length === 0) {
|
||||||
|
var postData = {order_sn: orderSn, channel: channel};
|
||||||
|
$.post(createUrl, postData, function (res) {
|
||||||
|
qrHtml = '<div class="qrcode"><img src="' + res.qrcode_url + '" alt="支付二维码"></div>';
|
||||||
|
showQrLayer(qrTitle, qrHtml);
|
||||||
|
$qrBox.html(qrHtml);
|
||||||
|
$snInput.html(res.sn);
|
||||||
|
var interval = setInterval(function () {
|
||||||
|
var queryData = {sn: res.sn};
|
||||||
|
$.get(statusUrl, queryData, function (res) {
|
||||||
|
if (res.status === 'finished') {
|
||||||
|
clearInterval(interval);
|
||||||
|
var html = '<div class="success-tips">支付成功</div>';
|
||||||
|
$('#pay-layer').html(html);
|
||||||
|
setTimeout(function () {
|
||||||
|
window.location.href = forwardUrl;
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 3000)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showQrLayer(qrTitle, qrHtml);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -14,6 +14,13 @@ class ChapterUser extends Model
|
|||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计划编号(course_user主键)
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $plan_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 课程编号
|
* 课程编号
|
||||||
*
|
*
|
||||||
|
@ -27,6 +27,13 @@ class Learning extends Model
|
|||||||
*/
|
*/
|
||||||
public $request_id;
|
public $request_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计划编号(course_user主键)
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public $plan_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 课程编号
|
* 课程编号
|
||||||
*
|
*
|
||||||
|
@ -59,7 +59,6 @@ class OrderList extends FrontendService
|
|||||||
'item_id' => $order['item_id'],
|
'item_id' => $order['item_id'],
|
||||||
'item_type' => $order['item_type'],
|
'item_type' => $order['item_type'],
|
||||||
'item_info' => $order['item_info'],
|
'item_info' => $order['item_info'],
|
||||||
'source_type' => $order['source_type'],
|
|
||||||
'create_time' => $order['create_time'],
|
'create_time' => $order['create_time'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -38,13 +38,7 @@ class OrderCreate extends FrontendService
|
|||||||
/**
|
/**
|
||||||
* 存在新鲜的未支付订单直接返回(减少订单记录)
|
* 存在新鲜的未支付订单直接返回(减少订单记录)
|
||||||
*/
|
*/
|
||||||
if ($order) {
|
if ($order) return $order;
|
||||||
$caseA = $order->status == OrderModel::STATUS_PENDING;
|
|
||||||
$caseB = time() - $order->create_time < 12 * 3600;
|
|
||||||
if ($caseA && $caseB) {
|
|
||||||
return $order;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($post['item_type'] == OrderModel::ITEM_COURSE) {
|
if ($post['item_type'] == OrderModel::ITEM_COURSE) {
|
||||||
|
|
||||||
@ -83,7 +77,7 @@ class OrderCreate extends FrontendService
|
|||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createCourseOrder(CourseModel $course, UserModel $user)
|
protected function createCourseOrder(CourseModel $course, UserModel $user)
|
||||||
{
|
{
|
||||||
$itemInfo = [];
|
$itemInfo = [];
|
||||||
|
|
||||||
@ -105,7 +99,7 @@ class OrderCreate extends FrontendService
|
|||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createPackageOrder(PackageModel $package, UserModel $user)
|
protected function createPackageOrder(PackageModel $package, UserModel $user)
|
||||||
{
|
{
|
||||||
$packageRepo = new PackageRepo();
|
$packageRepo = new PackageRepo();
|
||||||
|
|
||||||
@ -140,7 +134,7 @@ class OrderCreate extends FrontendService
|
|||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createVipOrder(VipModel $vip, UserModel $user)
|
protected function createVipOrder(VipModel $vip, UserModel $user)
|
||||||
{
|
{
|
||||||
$baseTime = $user->vip_expiry_time > time() ? $user->vip_expiry_time : time();
|
$baseTime = $user->vip_expiry_time > time() ? $user->vip_expiry_time : time();
|
||||||
$expiryTime = strtotime("+{$vip->expiry} months", $baseTime);
|
$expiryTime = strtotime("+{$vip->expiry} months", $baseTime);
|
||||||
@ -169,7 +163,7 @@ class OrderCreate extends FrontendService
|
|||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createRewardOrder(CourseModel $course, RewardModel $reward, UserModel $user)
|
protected function createRewardOrder(CourseModel $course, RewardModel $reward, UserModel $user)
|
||||||
{
|
{
|
||||||
$itemInfo = [
|
$itemInfo = [
|
||||||
'course' => $this->handleCourseInfo($course),
|
'course' => $this->handleCourseInfo($course),
|
||||||
|
@ -145,7 +145,7 @@ class Order extends Validator
|
|||||||
{
|
{
|
||||||
$orderRepo = new OrderRepo();
|
$orderRepo = new OrderRepo();
|
||||||
|
|
||||||
$itemType = OrderModel::ITEM_PACKAGE;
|
$itemType = OrderModel::ITEM_COURSE;
|
||||||
|
|
||||||
$order = $orderRepo->findUserLastFinishedOrder($userId, $courseId, $itemType);
|
$order = $orderRepo->findUserLastFinishedOrder($userId, $courseId, $itemType);
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ class Order extends Validator
|
|||||||
*/
|
*/
|
||||||
$itemInfo = $order->item_info;
|
$itemInfo = $order->item_info;
|
||||||
|
|
||||||
if ($itemInfo['course']['expiry_time'] > time()) {
|
if ($itemInfo['course']['study_expiry_time'] > time()) {
|
||||||
throw new BadRequestException('order.has_bought_course');
|
throw new BadRequestException('order.has_bought_course');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,8 @@ class Trade extends Validator
|
|||||||
if (!isset($list[$channel])) {
|
if (!isset($list[$channel])) {
|
||||||
throw new BadRequestException('trade.invalid_channel');
|
throw new BadRequestException('trade.invalid_channel');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkIfAllowClose(TradeModel $trade)
|
public function checkIfAllowClose(TradeModel $trade)
|
||||||
|
@ -158,6 +158,7 @@ img.kg-cover {
|
|||||||
img.kg-qrcode {
|
img.kg-qrcode {
|
||||||
width: 140px;
|
width: 140px;
|
||||||
height: 140px;
|
height: 140px;
|
||||||
|
border: 3px dashed #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kg-order-date {
|
.kg-order-date {
|
||||||
|
@ -692,7 +692,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cart-stats .pay-amount {
|
.cart-stats .pay-amount {
|
||||||
color: red;
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@ -726,7 +725,7 @@ body {
|
|||||||
|
|
||||||
.payment .channel {
|
.payment .channel {
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
margin-bottom: 40px;
|
margin-bottom: 80px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,7 +749,6 @@ body {
|
|||||||
background-position: center center;
|
background-position: center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.payment .footer {
|
.payment .footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@ -760,6 +758,25 @@ body {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pay-layer {
|
||||||
|
padding-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pay-layer .qrcode {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pay-layer .qrcode img {
|
||||||
|
width: 160px;
|
||||||
|
height: 160px;
|
||||||
|
border: 3px dashed #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pay-layer .success-tips {
|
||||||
|
color: green;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.verify-tips-btn {
|
.verify-tips-btn {
|
||||||
color: green;
|
color: green;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user