main #2
@ -136,8 +136,13 @@
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="text-xl font-medium text-gray-900 mb-2">服务器创建成功!</h3>
|
||||
<p class="text-gray-600 mb-2">您的 Jsite 服务器已成功开通。</p>
|
||||
<h3 class="text-xl font-medium text-gray-900 mb-2">支付成功!</h3>
|
||||
<p class="text-gray-600 mb-4">
|
||||
您的订单已支付成功,服务器正在创建中。创建并启动需要 3-5 分钟,请耐心等待。
|
||||
</p>
|
||||
<p class="text-gray-500 text-sm">
|
||||
创建完成后,您将收到通知,也可以在服务器列表中查看状态。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 微信支付状态 -->
|
||||
@ -437,9 +442,6 @@ export default {
|
||||
|
||||
this.isProcessingPayment = false;
|
||||
this.paymentSuccess = true;
|
||||
console.log('余额支付成功,更新状态:', {
|
||||
paymentSuccess: this.paymentSuccess
|
||||
});
|
||||
},
|
||||
onError(error) {
|
||||
this.error = error.message || '余额支付处理失败';
|
||||
@ -462,6 +464,7 @@ export default {
|
||||
|
||||
toast.success('支付页面已在新窗口打开');
|
||||
|
||||
// 开始轮询支付状态
|
||||
this.startPaymentCheck();
|
||||
},
|
||||
onError(error) {
|
||||
@ -483,6 +486,7 @@ export default {
|
||||
this.paymentQrCode = response.payment_url;
|
||||
this.paymentQrCodeImage = response.qr_code_image || null;
|
||||
|
||||
// 开始轮询支付状态
|
||||
this.startPaymentCheck();
|
||||
},
|
||||
onError(error) {
|
||||
@ -495,13 +499,17 @@ export default {
|
||||
checkPaymentStatus() {
|
||||
return {
|
||||
url: 'jcloud.api.billing.check_server_order_payment_status',
|
||||
params: {
|
||||
order_id: this.order?.order_id
|
||||
},
|
||||
validate() {
|
||||
if (!this.order || !this.order.order_id) {
|
||||
throw new DashboardError('缺少订单信息');
|
||||
}
|
||||
},
|
||||
onSuccess(data) {
|
||||
if (data && data.status === '交易成功') {
|
||||
if (data && data.status === '已支付') {
|
||||
// 支付成功,停止轮询
|
||||
this.stopPaymentCheck();
|
||||
|
||||
const orderData = { ...this.order, ...(data.order || {}) };
|
||||
@ -511,7 +519,11 @@ export default {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.stopPaymentCheck();
|
||||
},
|
||||
mounted() {
|
||||
console.log('组件mounted,开始获取地域列表');
|
||||
@ -558,6 +570,24 @@ export default {
|
||||
|
||||
this.isLoading = false;
|
||||
},
|
||||
startPaymentCheck() {
|
||||
this.isProcessingPayment = false;
|
||||
|
||||
this.checkInterval = setInterval(() => {
|
||||
this.$resources.checkPaymentStatus.submit();
|
||||
}, 3000);
|
||||
|
||||
// 15分钟后停止检查
|
||||
setTimeout(() => {
|
||||
this.stopPaymentCheck();
|
||||
}, 900000);
|
||||
},
|
||||
stopPaymentCheck() {
|
||||
if (this.checkInterval) {
|
||||
clearInterval(this.checkInterval);
|
||||
this.checkInterval = null;
|
||||
}
|
||||
},
|
||||
processPayment() {
|
||||
this.isProcessingPayment = true;
|
||||
this.error = null;
|
||||
@ -588,26 +618,9 @@ export default {
|
||||
});
|
||||
}
|
||||
},
|
||||
startPaymentCheck() {
|
||||
this.isProcessingPayment = false;
|
||||
|
||||
this.checkInterval = setInterval(() => {
|
||||
this.$resources.checkPaymentStatus.submit();
|
||||
}, 3000);
|
||||
|
||||
// 15分钟后停止检查
|
||||
setTimeout(() => {
|
||||
this.stopPaymentCheck();
|
||||
}, 900000);
|
||||
},
|
||||
stopPaymentCheck() {
|
||||
if (this.checkInterval) {
|
||||
clearInterval(this.checkInterval);
|
||||
this.checkInterval = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
close() {
|
||||
this.stopPaymentCheck();
|
||||
this.show = false;
|
||||
this.$emit('success');
|
||||
},
|
||||
@ -656,9 +669,7 @@ export default {
|
||||
return name;
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.stopPaymentCheck();
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@ -373,4 +373,129 @@ def get_aliyun_images(image_type='system', region_id='cn-shanghai'):
|
||||
def get_aliyun_regions():
|
||||
"""通过阿里云SDK实时获取可用地域列表"""
|
||||
manager = _get_manager()
|
||||
return manager.get_regions()
|
||||
return manager.get_regions()
|
||||
|
||||
# 服务器订单和创建相关
|
||||
|
||||
@jingrow.whitelist()
|
||||
def create_server_order(**kwargs):
|
||||
"""创建服务器订单"""
|
||||
try:
|
||||
plan_id = kwargs.get('plan_id')
|
||||
image_id = kwargs.get('image_id')
|
||||
period = kwargs.get('period', 1)
|
||||
region_id = kwargs.get('region_id', 'cn-shanghai')
|
||||
|
||||
if not plan_id or not image_id:
|
||||
jingrow.throw("缺少必要参数")
|
||||
|
||||
from jcloud.utils import get_current_team
|
||||
team = get_current_team(True)
|
||||
|
||||
# 获取套餐价格
|
||||
plans_response = get_aliyun_plans(region_id)
|
||||
selected_plan = None
|
||||
if plans_response and plans_response.get('success'):
|
||||
plans = plans_response['data'].get('plans', [])
|
||||
selected_plan = next((p for p in plans if p.get('plan_id') == plan_id), None)
|
||||
|
||||
if not selected_plan:
|
||||
jingrow.throw("套餐不存在")
|
||||
|
||||
# 计算价格
|
||||
monthly_price = float(selected_plan.get('origin_price', 0))
|
||||
total_amount = monthly_price * period
|
||||
|
||||
# 生成订单号
|
||||
from datetime import datetime
|
||||
import random
|
||||
order_id = datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3] + ''.join(random.choices('0123456789', k=6))
|
||||
|
||||
# 创建订单
|
||||
order = jingrow.get_pg({
|
||||
"pagetype": "Order",
|
||||
"order_id": order_id,
|
||||
"order_type": "新建服务器",
|
||||
"team": team.name,
|
||||
"status": "待支付",
|
||||
"total_amount": total_amount,
|
||||
"title": f"新建服务器 - {region_id}",
|
||||
"description": f"{selected_plan.get('core')}核/{selected_plan.get('memory')}GB/{selected_plan.get('disk_size')}GB, {period}个月",
|
||||
"server_config": {
|
||||
"plan_id": plan_id,
|
||||
"image_id": image_id,
|
||||
"period": period,
|
||||
"region_id": region_id,
|
||||
"monthly_price": monthly_price
|
||||
}
|
||||
})
|
||||
|
||||
order.insert(ignore_permissions=True)
|
||||
jingrow.db.commit()
|
||||
|
||||
return {"success": True, "order": order.as_dict()}
|
||||
|
||||
except Exception as e:
|
||||
jingrow.log_error("创建服务器订单失败", str(e))
|
||||
return {"success": False, "message": str(e)}
|
||||
|
||||
def create_server_async(order_name):
|
||||
"""异步创建服务器"""
|
||||
try:
|
||||
order = jingrow.get_pg("Order", order_name)
|
||||
if not order:
|
||||
raise Exception("订单不存在")
|
||||
|
||||
# 获取配置
|
||||
config = order.server_config or {}
|
||||
plan_id = config.get('plan_id')
|
||||
image_id = config.get('image_id')
|
||||
period = config.get('period', 1)
|
||||
region_id = config.get('region_id', 'cn-shanghai')
|
||||
|
||||
# 调用阿里云API创建实例
|
||||
result = create_aliyun_instance(plan_id, image_id, period, region_id)
|
||||
|
||||
if not result or not result.get('success'):
|
||||
raise Exception(f"阿里云创建失败: {result.get('message', '未知错误')}")
|
||||
|
||||
instance_id = result['data']['instance_id']
|
||||
|
||||
# 创建服务器记录
|
||||
server = jingrow.get_pg({
|
||||
"pagetype": "Jsite Server",
|
||||
"instance_id": instance_id,
|
||||
"team": order.team,
|
||||
"order": order.name,
|
||||
"status": "Running",
|
||||
"region_id": region_id,
|
||||
"plan_id": plan_id,
|
||||
"image_id": image_id,
|
||||
"period": period,
|
||||
"monthly_price": config.get('monthly_price', 0),
|
||||
"total_amount": order.total_amount,
|
||||
"payment_method": order.payment_method,
|
||||
"created_at": jingrow.utils.now(),
|
||||
"expires_at": jingrow.utils.add_months(jingrow.utils.nowdate(), period)
|
||||
})
|
||||
|
||||
server.insert(ignore_permissions=True)
|
||||
|
||||
# 更新订单状态
|
||||
order.status = "交易成功"
|
||||
order.instance_id = instance_id
|
||||
order.server_record = server.name
|
||||
order.save(ignore_permissions=True)
|
||||
|
||||
jingrow.db.commit()
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
jingrow.log_error("服务器创建失败", f"订单 {order_name}: {str(e)}")
|
||||
# 更新订单状态为失败
|
||||
try:
|
||||
jingrow.db.set_value("Order", order_name, "status", "创建失败")
|
||||
except:
|
||||
pass
|
||||
raise e
|
||||
@ -1088,6 +1088,9 @@ def handle_order_payment_complete(order_id):
|
||||
process_balance_recharge(order)
|
||||
elif order.order_type == "网站续费":
|
||||
process_site_renew(order_id)
|
||||
elif order.order_type == "Jsite Server":
|
||||
# 异步创建服务器
|
||||
jingrow.enqueue('jcloud.api.aliyun_server_light.create_server_async', order_name=order.name)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
@ -1869,3 +1872,121 @@ def get_balance_transactions(page=1, page_size=20, search=None):
|
||||
"total": 0,
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
# Jsite Server 相关功能
|
||||
|
||||
@jingrow.whitelist()
|
||||
def process_balance_payment_for_server_order(order_id):
|
||||
"""使用余额支付服务器订单"""
|
||||
try:
|
||||
team = get_current_team(True)
|
||||
order = jingrow.get_pg("Order", {"order_id": order_id})
|
||||
|
||||
if not order or order.team != team.name:
|
||||
jingrow.throw("订单不存在或无权限")
|
||||
|
||||
if order.status != "待支付":
|
||||
return {"success": False, "message": "订单已处理"}
|
||||
|
||||
balance = team.get_balance()
|
||||
if balance < order.total_amount:
|
||||
return {"success": False, "message": "余额不足"}
|
||||
|
||||
# 扣款
|
||||
balance_transaction = jingrow.get_pg({
|
||||
"pagetype": "Balance Transaction",
|
||||
"team": team.name,
|
||||
"type": "Adjustment",
|
||||
"source": "Prepaid Credits",
|
||||
"amount": -order.total_amount,
|
||||
"description": f"服务器购买: {order.title}"
|
||||
})
|
||||
balance_transaction.insert(ignore_permissions=True)
|
||||
balance_transaction.submit()
|
||||
|
||||
# 更新订单状态
|
||||
order.status = "已支付"
|
||||
order.payment_method = "余额支付"
|
||||
order.save(ignore_permissions=True)
|
||||
|
||||
# 异步创建服务器
|
||||
jingrow.enqueue('jcloud.api.aliyun_server_light.create_server_async', order_name=order.name)
|
||||
|
||||
return {"success": True, "message": "支付成功,服务器创建中"}
|
||||
|
||||
except Exception as e:
|
||||
jingrow.log_error("服务器支付失败", str(e))
|
||||
return {"success": False, "message": str(e)}
|
||||
|
||||
@jingrow.whitelist()
|
||||
def process_alipay_server_order(order_id):
|
||||
"""支付宝支付服务器订单"""
|
||||
team = get_current_team(True)
|
||||
order = jingrow.get_pg("Order", {"order_id": order_id})
|
||||
|
||||
if not order or order.team != team.name:
|
||||
jingrow.throw("订单不存在或无权限")
|
||||
|
||||
if order.status != "待支付":
|
||||
jingrow.throw("订单已处理")
|
||||
|
||||
from jcloud.api.payment.alipay import AlipayAPI
|
||||
api = AlipayAPI()
|
||||
|
||||
payment_url = api.generate_payment_url(
|
||||
order_id=order_id,
|
||||
amount=order.total_amount,
|
||||
subject=order.title,
|
||||
team_name=team.name
|
||||
)
|
||||
|
||||
order.payment_method = "支付宝"
|
||||
order.save(ignore_permissions=True)
|
||||
|
||||
return {"payment_url": payment_url, "order_id": order_id}
|
||||
|
||||
@jingrow.whitelist()
|
||||
def process_wechatpay_server_order(order_id):
|
||||
"""微信支付服务器订单"""
|
||||
team = get_current_team(True)
|
||||
order = jingrow.get_pg("Order", {"order_id": order_id})
|
||||
|
||||
if not order or order.team != team.name:
|
||||
jingrow.throw("订单不存在或无权限")
|
||||
|
||||
if order.status != "待支付":
|
||||
jingrow.throw("订单已处理")
|
||||
|
||||
wechat_pay = WeChatPayAPI()
|
||||
qr_code_url = wechat_pay.generate_payment_url(
|
||||
order_id=order_id,
|
||||
amount=order.total_amount,
|
||||
subject=order.title,
|
||||
team_name=team.name
|
||||
)
|
||||
|
||||
order.payment_method = "微信支付"
|
||||
order.save(ignore_permissions=True)
|
||||
|
||||
return {"qr_code_url": qr_code_url, "order_id": order_id}
|
||||
|
||||
@jingrow.whitelist()
|
||||
def check_server_order_payment_status(order_id):
|
||||
"""检查服务器订单支付状态"""
|
||||
try:
|
||||
order = jingrow.get_pg("Order", {"order_id": order_id})
|
||||
if not order:
|
||||
jingrow.throw(f"找不到订单: {order_id}")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"status": order.status,
|
||||
"order": order.as_dict()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
jingrow.log_error("服务器订单错误", f"检查服务器订单状态失败: {str(e)}")
|
||||
return {
|
||||
"success": False,
|
||||
"message": f"检查订单状态失败: {str(e)}"
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
"actions": [],
|
||||
"allow_rename": 1,
|
||||
"creation": "2025-03-23 21:29:54.329381",
|
||||
"pagetype": "PageType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"title",
|
||||
@ -37,7 +36,7 @@
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"options": "\u5f85\u652f\u4ed8\n\u5df2\u652f\u4ed8\n\u4ea4\u6613\u6210\u529f\n\u5df2\u53d6\u6d88\n\u5df2\u9000\u6b3e",
|
||||
"options": "待支付\n已支付\n交易成功\n已取消\n已退款",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@ -45,7 +44,7 @@
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Payment Method",
|
||||
"options": "\n\u652f\u4ed8\u5b9d\n\u5fae\u4fe1\u652f\u4ed8\n\u4f59\u989d\u652f\u4ed8\n\u94f6\u884c\u8f6c\u8d26\n\u5176\u4ed6",
|
||||
"options": "\n支付宝\n微信支付\n余额支付\n银行转账\n其他",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@ -78,18 +77,19 @@
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Order Type",
|
||||
"options": "\n\u4f59\u989d\u5145\u503c\n\u65b0\u5efa\u7f51\u7ad9\n\u7f51\u7ad9\u7eed\u8d39\n\u57df\u540d\u7eed\u8d39",
|
||||
"options": "\n余额充值\n新建网站\n网站续费\n域名续费\n新建服务器\n服务器续费",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-03-26 03:34:52.624889",
|
||||
"modified": "2025-07-27 17:29:16.088188",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Jcloud",
|
||||
"name": "Order",
|
||||
"owner": "Administrator",
|
||||
"pagetype": "PageType",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
@ -104,6 +104,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
|
||||
@ -16,7 +16,7 @@ class Order(Document):
|
||||
|
||||
description: DF.Data | None
|
||||
order_id: DF.Data | None
|
||||
order_type: DF.Literal["", "\u4f59\u989d\u5145\u503c", "\u65b0\u5efa\u7f51\u7ad9", "\u7f51\u7ad9\u7eed\u8d39", "\u57df\u540d\u7eed\u8d39"]
|
||||
order_type: DF.Literal["", "\u4f59\u989d\u5145\u503c", "\u65b0\u5efa\u7f51\u7ad9", "\u7f51\u7ad9\u7eed\u8d39", "\u57df\u540d\u7eed\u8d39", "\u65b0\u5efa\u670d\u52a1\u5668", "\u670d\u52a1\u5668\u7eed\u8d39"]
|
||||
payment_method: DF.Literal["", "\u652f\u4ed8\u5b9d", "\u5fae\u4fe1\u652f\u4ed8", "\u4f59\u989d\u652f\u4ed8", "\u94f6\u884c\u8f6c\u8d26", "\u5176\u4ed6"]
|
||||
status: DF.Literal["\u5f85\u652f\u4ed8", "\u5df2\u652f\u4ed8", "\u4ea4\u6613\u6210\u529f", "\u5df2\u53d6\u6d88", "\u5df2\u9000\u6b3e"]
|
||||
team: DF.Link | None
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user