Commit 2efb0ef2 by 宋毅

tj

parent 206e07b0
......@@ -32,7 +32,6 @@ class PaymentAPI extends APIBase {
// sy
case "getQrCode"://pc端订单支付二维码生成
url = this.centerAppUrl + "payment/paymentApi/getQrCode";
break;
case "queryOrder"://通联支付查询
url = this.centerAppUrl + "payment/paymentApi/queryOrder";
......
......@@ -33,7 +33,7 @@ class ProductAPI extends APIBase {
break;
}
return opResult;
}
}
}
module.exports = ProductAPI;
\ No newline at end of file
......@@ -4,8 +4,10 @@ var settings = require("../../../../config/settings");
class PaymentAPI extends APIBase {
constructor() {
super();
this.execlient = system.getObject("util.execClient");
this.centerAppUrl = settings.centerAppUrl();
// this.execlient = system.getObject("util.execClient");
// this.centerAppUrl = settings.centerAppUrl();
this.utilsOrderSve = system.getObject("service.utilsSve.utilsOrderSve");
}
/**
......@@ -26,28 +28,27 @@ class PaymentAPI extends APIBase {
}
async opActionProcess(pobj, action_type, action_body, req) {
var opResult = null;
var url = "";
switch (action_type) {
// sy
case "getH5PayUrl"://H5端订单支付二维码生成
opResult = await this.utilsOrderSve.getH5PayUrl(pobj, pobj.actionBody);
break;
case "getOrderQrCode"://pc端订单支付二维码生成
opResult = await this.utilsOrderSve.getQrCodeInfo(pobj, pobj.actionBody);
break;
case "queryOrderStatus"://通联支付查询
opResult = await this.utilsOrderSve.queryOrderStatus(pobj, pobj.actionBody);
break;
case "getQrCode"://pc端订单支付二维码生成
url = this.centerAppUrl + "payment/paymentApi/getQrCode";
opResult = await this.utilsOrderSve.getQrCode(pobj, pobj.actionBody);
break;
case "queryOrder"://通联支付查询
url = this.centerAppUrl + "payment/paymentApi/queryOrder";
break;
case "receiveCallBackNotify"://通联支付查询
url = this.centerAppUrl + "payment/paymentApi/receiveCallBackNotify";
opResult = await this.utilsOrderSve.queryOrder(pobj, pobj.actionBody);
break;
default:
opResult = system.getResult(null, "action_type参数错误");
break;
}
if (url) {
opResult = system.getResultSuccess(null, "action_type参数错误");
}
var opResultstr = await this.execlient.execPost(pobj, url);
opResult = JSON.parse(opResultstr.stdout)
return opResult;
}
}
......
const CacheBase = require("../cache.base");
const system = require("../../system");
const settings = require("../../../config/settings");
class TlPayLocker extends CacheBase {
constructor() {
super();
this.prefix = settings.cacheprefix + "_tlPayLocker:";
}
desc() {
return "支付业务锁";
}
prefix() {
return settings.cacheprefix + "_uiconfig:";
}
async init(tradekey) {
const key = this.prefix + tradekey;
return this.redisClient.rpushWithEx(key, "1", 1800);
}
async enter(tradekey) {
const key = this.prefix + tradekey;
return this.redisClient.rpop(key);
}
async release(tradekey) {
const key = this.prefix + tradekey;
return this.redisClient.rpushWithEx(key, "1", 1800);
}
}
module.exports = TlPayLocker;
const System = require("../../../system");
const system = require("../../../system");
var settings = require("../../../../config/settings");
const querystring = require('querystring');
const AppServiceBase = require("../../app.base");
......@@ -6,7 +6,28 @@ class UtilsOrderService extends AppServiceBase {
constructor() {
super();
this.centerOrderUrl = settings.centerOrderUrl();
this.tlPayNotifyUrl = settings.tlPayNotifyUrl();
this.centerAppPayUrl = settings.centerAppUrl() + "payment/paymentApi/springBoard";
};
/*
* 订单验证
*/
async isOrderVerify(pobj, actionBody) {
var price_list = actionBody.product_info.price_list;
if (!price_list) {
return system.getResult(null, "产品价格列表信息有误,10080");
}
var product_price = price_list.filter(f => f.id == actionBody.id);
if (!product_price || product_price.length == 0) {
return system.getResult(null, "产品定价id信息有误,10110");
}
var totalSum = Number(product_price[0].price) * Number(actionBody.quantity);
if (Number(actionBody.totalSum) < totalSum) {
return system.getResult(null, "订单金额有误,10130");
}
pobj.actionBody.product_info.price_item = product_price[0];
return system.getResultSuccess();
}
/**
* 创建订单
* @param {*} pobj
......@@ -28,6 +49,12 @@ class UtilsOrderService extends AppServiceBase {
if (productItemResult.status != 0) {
return productItemResult;
}
pobj.actionBody.product_info = productItemResult.data;
var verifyResult = await this.isOrderVerify(pobj, pobj.actionBody);
if (verifyResult.status != 0) {
return verifyResult;
}
pobj.actionType = "getProductInterface";
pobj.actionBody.productId = productItemResult.data.id;
var productItemInterfaceResult = await this.restPostUrl(pobj, url);
......@@ -35,7 +62,6 @@ class UtilsOrderService extends AppServiceBase {
return productItemInterfaceResult;
}
productItemResult.data.interface_info = productItemInterfaceResult.data;
pobj.actionBody.product_info = productItemResult.data;
pobj.actionType = "addOrder";
var reqUrl = this.centerOrderUrl + "action/order/springBoard";
......@@ -43,5 +69,197 @@ class UtilsOrderService extends AppServiceBase {
var result = await this.restPostUrl(pobj, reqUrl);
return result;
}
/**
* 获取H5支付地址
* @param {*} pobj
* @param {*} actionBody {orderNo:XXXX}
*/
async getH5PayUrl(pobj, actionBody) {
if (!actionBody.orderNo) {
return system.getResult(null, "actionBody.orderNo can not be empty");
}
pobj.actionType = "getPayOrderInfo";
var orderUrl = settings.centerOrderUrl() + "action/order/springBoard";
var orderResult = await this.restPostUrl(pobj, orderUrl);
if (orderResult.status != 0) {
return orderResult;
}
// pobj.actionBody.body_desc, pobj.actionBody.total_fee, pobj.actionBody.order_num, pobj.actionBody.returl
pobj.actionBody.body_desc = orderResult.data.orderProduct.channelItemName;
pobj.actionBody.total_fee = Number(orderResult.data.receiptVoucher.totalSum) * 100;
pobj.actionBody.order_num = orderResult.data.receiptVoucher.sourceOrderNo;
pobj.actionBody.returl = this.tlPayNotifyUrl;
pobj.actionType = "getH5PayUrl";
var url = this.centerAppPayUrl;
var result = await this.restPostUrl(pobj, url);
if (result.status != 0) {
return result;
}
await this.cacheManager["TlPayLocker"].init(orderResult.data.receiptVoucher.sourceOrderNo);
return result;
}
/**
* 获取二维码
* @param {*} pobj
* @param {*} actionBody {orderNo:XXXX,opType:"wx"}---"wx":"微信","alipay":"支付宝"
*/
async getOrderQrCode(pobj, actionBody) {
if (!actionBody.orderNo) {
return system.getResult(null, "actionBody.orderNo can not be empty");
}
pobj.actionType = "getPayOrderInfo";
var orderUrl = settings.centerOrderUrl() + "action/order/springBoard";
var orderResult = await this.restPostUrl(pobj, orderUrl);
if (orderResult.status != 0) {
return orderResult;
}
//查询支付流水号是否已经支付
var receiptVoucher = orderResult.data.receiptVoucher;
pobj.actionType = "queryOrderStatus";
var url = this.centerAppUrl + "payment/paymentApi/queryOrder";
if (receiptVoucher.busPayOrderCode != receiptVoucher.wxPayOrderCode) {
pobj.actionBody.trxid = wxPayOrderCode;
var wxPayStatus = await this.restPostUrl(pobj, url);
if (wxPayStatus && wxPayStatus.code == 1 && wxPayStatus.data.trxstatus == "0000") {
return system.getResultFail(-140, "订单已支付,请勿重复付款");
}
}
if (receiptVoucher.busPayOrderCode != receiptVoucher.aliPayOrderCode) {
pobj.actionBody.trxid = aliPayOrderCode;
var aliPayStatus = await this.restPostUrl(pobj, url);
if (aliPayStatus && aliPayStatus.code == 1 && aliPayStatus.data.trxstatus == "0000") {
return system.getResultFail(-150, "订单已支付,请勿重复付款");
}
}
// pobj.actionBody.body_desc, pobj.actionBody.total_fee, pobj.actionBody.order_num, pobj.actionBody.op_type
pobj.actionBody.body_desc = orderResult.data.orderProduct.channelItemName;
pobj.actionBody.total_fee = Number(receiptVoucher.totalSum) * 100;
pobj.actionBody.order_num = receiptVoucher.sourceOrderNo;
pobj.actionBody.op_type = actionBody.opType;
pobj.actionType = "getOrderQrCode";
var getQrCodeUrl = this.centerAppUrl + "payment/paymentApi/getQrCode";
var result = await this.restPostUrl(pobj, getQrCodeUrl);
if (result.status != 0) {
return result;
}
//更新DB付款信息
var isPut = 0;
var setField = {};
if (opType == "wx") {
if (actionBody.trxid != receiptVoucher.wxPayOrderCode) {
setField.wxPayOrderCode = tResult.data.trxid;
receiptVoucher.wxPayOrderCode = tResult.data.trxid;
isPut = 1;
}
} else {
//支付宝
if (actionBody.trxid != receiptVoucher.aliPayOrderCode) {
setField.aliPayOrderCode = tResult.data.trxid;
receiptVoucher.aliPayOrderCode = tResult.data.trxid;
isPut = 1;
}
}
pobj.actionBody.isPut;
pobj.actionBody.setField = setField;
pobj.actionBody.receiptVoucherId = receiptVoucher.id;
pobj.actionBody.trxid = result.data.trxid;
pobj.actionType = "putReceiptVoucherInfo";
var putOrderResult = await this.restPostUrl(pobj, orderUrl);
if (putOrderResult.status != 0) {
return putOrderResult;
}
if (isPut > 0) {
await this.cacheManager["TlPayLocker"].init(receiptVoucher.sourceOrderNo);
}
result.wxPayOrderCode = receiptVoucher.wxPayOrderCode;
result.aliPayOrderCode = receiptVoucher.aliPayOrderCode;
return result;
}
/**
* 查询订单状态
* @param {*} pobj
* @param {*} actionBody {orderNo:XXXX,opType:"wx"}---"wx":"微信","alipay":"支付宝"
*/
async queryOrderStatus(pobj, actionBody) {
if (!actionBody.orderNo) {
return system.getResult(null, "actionBody.orderNo can not be empty");
}
if (!actionBody.opType) {
return system.getResult(null, "actionBody.opType can not be empty");
}
pobj.actionType = "getPayOrderInfo";
var orderUrl = settings.centerOrderUrl() + "action/order/springBoard";
var orderResult = await this.restPostUrl(pobj, url);
if (orderResult.status != 0) {
return orderResult;
}
//检查流水号是否已经支付
var receiptVoucher = orderResult.data.receiptVoucher;
var payTrxid = opType == "wx" ? receiptVoucher.wxPayOrderCode : receiptVoucher.aliPayOrderCode;
pobj.actionBody.trxid = payTrxid;
pobj.actionType = "queryOrderStatus";
var url = this.centerAppUrl + "payment/paymentApi/queryOrder";
var payStatus = await this.restPostUrl(pobj, url);
if (payStatus.data && payStatus.data.trxstatus == "0000") {
//TODO:处理支付成功的业务逻辑
// payStatus.data.client_ip = obj.client_ip || "";
// let attachList = [];
// if (payStatus.data.reqsn.indexOf("_") >= 0) {
// attachList = payStatus.data.reqsn.split("_");
// }
// else {
// attachList.push(payStatus.data.reqsn);
// }
// if (attachList.length != 2) {
// return { -120, msg: "reqsn参数错误,没有_标识" };
// }
// payStatus.data.out_trade_no = attachList[0];
// payStatus.data.company_id = attachList[1];
// return await this.utilstlbankSve.opBackNotify(payStatus.data, "页面回调");
}
else if (payStatus.data && payStatus.data.trxstatus == "3045") {
return system.getResultFail(-330, "超时未支付,请刷新页面");
}
return system.getResultFail(-130, "请及时支付");
}
/**
* 只是获取二维码--不跟订单关联
* @param {*} pobj
* @param {*} actionBody
* "actionBody": {
"order_num": order.orderNo,
"total_fee": Number(order.totalSum) * 100,
"body_desc": order.itemName,
"op_type": obj.opType
}
*/
async getQrCode(pobj, actionBody) {
if (!actionBody.orderNo) {
return system.getResult(null, "actionBody.orderNo can not be empty");
}
var url = this.centerAppUrl + "payment/paymentApi/getQrCode";
return await this.restPostUrl(pobj, url);
}
/**
* 只是检查支付状态--不跟订单关联
* @param {*} pobj
* @param {*} actionBody { "trxid": payTrxid 支付流水号}
*/
async queryOrder(pobj, actionBody) {
if (!actionBody.trxid) {
return system.getResult(null, "actionBody.trxid can not be empty");
}
var url = this.centerAppUrl + "payment/paymentApi/queryOrder";
return await this.restPostUrl(pobj, url);
}
async receiveCallBackNotify(pobj, actionBody) {//---暂时没有用到
var url = this.centerAppUrl + "payment/paymentApi/receiveCallBackNotify";
return await this.restPostUrl(pobj, url);
}
}
module.exports = UtilsOrderService;
......@@ -3,6 +3,15 @@ var system = require("../../base/system");
var utilsAuthSve = system.getObject("service.utilsSve.utilsAuthSve");
module.exports = function (app) {
//-----------------------新的模式------------------开始
app.use('/tlpay/notify', function (req, res) {
// var client_ip = system.get_client_ip(req);
// // req.body["client_ip"]=client_ip;
// var orderSve = system.getObject("service.dborder.orderSve");
// var p = orderSve.receiveTlCallBackNotify(req.body);
// p.then(r => {
// res.end(JSON.stringify(r));
// });
});
app.all("/web/*", async function (req, res, next) {
var result = system.getResult(null, "req method must is post");
......@@ -40,8 +49,7 @@ module.exports = function (app) {
req.body.appInfo = result.data;
req.body.actionProcess = result.data.app_code;
var lst = [
"addOrder", "getTmOrderList",
"getTmOrderInfo", "getTmApplyInfo",
"addOrder", "getH5PayUrl","getOrderQrCode", "queryOrderStatus",
"getTmNclList", "getNeedInfo",
"tmConfirm", "updateTmInfo",
"updateNclInfo", "updateContacts",
......
......@@ -20,6 +20,13 @@ var settings = {
usertimeout: 3600,//单位秒
basepath: path.normalize(path.join(__dirname, '../..')),
port: process.env.NODE_PORT || 4012,
tlPayNotifyUrl: function () {
if (this.env == "dev") {
return "http://gsb.qifu.gongsibao.com:4012/tlpay/notify";
} else {
return "http://gsb.qifu.gongsibao.com/tlpay/notify";
}
},
paasUrl: function () {
if (this.env == "dev") {
return "http://p.apps.com:4001/";
......@@ -110,7 +117,7 @@ var settings = {
user: ENVINPUT.DB_USER,
password: ENVINPUT.DB_PWD,
config: {
host: ENVINPUT.DB_HOST,
host: ENVINPUT.DB_HOST,
dialect: 'mysql',
operatorsAliases: false,
pool: {
......
<a name="menu" href="/doc">返回主目录</a>
1. [产品列表-根据产品大类获取](#getCAProductListByTypeOneCode)
1. [产品列表-根据产品二类获取](#getCAProductListByTypeCode)
1. [产品详情](#getCAProductDetail)
1. [下商标订单](#addOrder)
1. [下其他订单](#addOtherOrder)
1. [获取H5支付链接](#getH5PayUrl)
## **<a name="getCAProductListByTypeOneCode"> 产品列表-根据产品大类获取</a>**
## **<a name="addOrder"> 下商标订单</a>**
[返回到目录](#menu)
##### URL
[/action/product/springBoard]
[/web/opaction/order/springBoard]
#### 参数格式 `JSON`
#### HTTP请求方式 `POST`
#### 渠道执行的类型 actionType:getCAProductListByTypeOneCode
#### 请求头中需要增加userpin(用户登录后的凭证)的值
#### 渠道执行的类型 actionType:addOrder
``` javascript
{
......@@ -148,17 +149,24 @@
}
```
## **<a name="getCAProductListByTypeCode"> 产品列表-根据产品二类获取</a>**
## **<a name="addOtherOrder"> 下其他订单</a>getH5PayUrl
[返回到目录](#menu)
##### URL
[/action/product/springBoard]
[/web/opaction/order/springBoard]
#### 参数格式 `JSON`
#### HTTP请求方式 `POST`
#### 渠道执行的类型 actionType:getCAProductListByTypeCode
#### 请求头中需要增加userpin(用户登录后的凭证)的值
#### 渠道执行的类型 actionType:addOrder
``` javascript
{
"typeCode":"sbzc"
"channelItemCode":"fzsbzc",// Y 产品的渠道编码
"id":2,// Y 定价id
"quantity":1,// Y 购买数量
"totalSum":699,// Y 订单总金额
"payTotalSum":699, // Y 订单付款总金额
"channelOrder":{},// Y 渠道订单信息,没有则填写{}
"deliveryData":null//Y 交付单信息,没有则填写null
}
```
......@@ -166,142 +174,29 @@
#### 返回结果
```javascript
{
"status":0,
"msg":"success",
"data":[
{
"id":1,
"uapp_id":16,
"path_code":"sbfu/sbzc",
"path_name":"商标服务/商标注册",
"item_code":"zzsbzc",
"item_name":"商标注册【自助申请】",
"pic_url":null,
"product_desc":"{"logo":"","desc":["自己检索商标,准备官方所需注册材料","提交迅速,及时反馈","全流程跟踪,掌握申请进度"]}",
"channel_item_code":"FW_GOODS-581976-1",
"channel_item_name":"商标注册【自助申请】",
"sort":0,
"productType_id":2,
"created_at":"2020-01-07T15:29:57.000Z",
"product_id":1,
"price":300,
"supply_price":0,
"service_charge":0,
"public_expense":0,
"channel_profit_rate":0,
"price_type":"mj",
"price_type_name":"每件",
"price_desc":null,
"min_qty":1,
"max_qty":100,
"type_id":2,
"p_id":1,
"type_code":"sbzc",
"type_name":"商标注册",
"type_pic":null,
"type_desc":null,
"type_icon":null,
"p_type_id":1,
"p_type_code":"sbfu",
"p_type_name":"商标服务",
"p_type_pic":null,
"p_type_desc":null,
"p_type_icon":null
},
{
"id":2,
"uapp_id":16,
"path_code":"sbfu/sbzc",
"path_name":"商标服务/商标注册",
"item_code":"fzsbzc",
"item_name":"商标注册【专家辅助申请】",
"pic_url":null,
"product_desc":"{"logo":"","desc":["由专业代理人帮您检索分析,成功率高","为您优化注册方案,全方位保护","代理人全流程服务,24小时拿到官方申请号"]}",
"channel_item_code":"FW_GOODS-580010-1",
"channel_item_name":"商标注册【专家辅助申请】",
"sort":0,
"productType_id":2,
"created_at":"2020-01-07T15:30:34.000Z",
"product_id":2,
"price":699,
"supply_price":0,
"service_charge":0,
"public_expense":0,
"channel_profit_rate":0,
"price_type":"mj",
"price_type_name":"每件",
"price_desc":null,
"min_qty":1,
"max_qty":100,
"type_id":2,
"p_id":1,
"type_code":"sbzc",
"type_name":"商标注册",
"type_pic":null,
"type_desc":null,
"type_icon":null,
"p_type_id":1,
"p_type_code":"sbfu",
"p_type_name":"商标服务",
"p_type_pic":null,
"p_type_desc":null,
"p_type_icon":null
},
{
"id":3,
"uapp_id":16,
"path_code":"sbfu/sbzc",
"path_name":"商标服务/商标注册",
"item_code":"dbsbzc",
"item_name":"商标注册【担保申请】",
"pic_url":"",
"product_desc":"{"logo":"","desc":["专业代理人精准评估,风险共担","注册不成功,全额退款","24小时拿到官方申请号"]}",
"channel_item_code":"FW_GOODS-581978-1",
"channel_item_name":"商标注册【担保申请】",
"sort":0,
"productType_id":2,
"created_at":"2020-01-07T15:30:34.000Z",
"product_id":3,
"price":1380,
"supply_price":0,
"service_charge":0,
"public_expense":0,
"channel_profit_rate":0,
"price_type":"mj",
"price_type_name":"每件",
"price_desc":"",
"min_qty":1,
"max_qty":100,
"type_id":2,
"p_id":1,
"type_code":"sbzc",
"type_name":"商标注册",
"type_pic":null,
"type_desc":null,
"type_icon":null,
"p_type_id":1,
"p_type_code":"sbfu",
"p_type_name":"商标服务",
"p_type_pic":null,
"p_type_desc":null,
"p_type_icon":null
}
],
"requestId":"3708d266442a45edbfedaf87d26f6400"
"status": 0,// 0为成功,否则失败
"msg": "success",
"data": {
"orderNo": "OT26202002151649kPgs",//订单号
"channelServiceNo": "OT26202002151649kPgs",//渠道单号
"channelParams": ""//渠道参数
},
"requestId": "2f90fad8108b4933bb97c3d978b0fe10"
}
```
## **<a name="getCAProductDetail"> 产品详情</a>**
## **<a name="getH5PayUrl"> 获取H5支付链接</a>**
[返回到目录](#menu)
##### URL
[/action/product/springBoard]
[/web/payment/paymentApi/springBoard]
#### 参数格式 `JSON`
#### HTTP请求方式 `POST`
#### 渠道执行的类型 actionType:getCAProductDetail
#### 请求头中需要增加userpin(用户登录后的凭证)的值
#### 渠道执行的类型 actionType:getH5PayUrl
``` javascript
{
"channelItemCode":"FW_GOODS-581976-1"
"orderNo":"OT26202002151649kPgs"
}
```
......@@ -309,65 +204,9 @@
#### 返回结果
```javascript
{
"status":0,
"msg":"success",
"data":[
{
"id":1,
"uapp_id":16,
"path_code":"sbfu/sbzc",
"path_name":"商标服务/商标注册",
"item_code":"zzsbzc",
"item_name":"商标注册【自助申请】",
"pic_url":null,
"product_desc":"{"logo":"","desc":["自己检索商标,准备官方所需注册材料","提交迅速,及时反馈","全流程跟踪,掌握申请进度"]}",
"channel_item_code":"FW_GOODS-581976-1",
"channel_item_name":"商标注册【自助申请】",
"sort":0,
"productType_id":2,
"created_at":"2020-01-07T15:29:57.000Z",
"product_id":1,
"price":300,
"supply_price":0,
"service_charge":0,
"public_expense":0,
"channel_profit_rate":0,
"price_type":"mj",
"price_type_name":"每件",
"price_desc":null,
"min_qty":1,
"max_qty":100,
"type_id":2,
"p_id":1,
"type_code":"sbzc",
"type_name":"商标注册",
"type_pic":null,
"type_desc":null,
"type_icon":null,
"p_type_id":1,
"p_type_code":"sbfu",
"p_type_name":"商标服务",
"p_type_pic":null,
"p_type_desc":null,
"p_type_icon":null,
"productPriceList":[
{
"price":300,
"supply_price":0,
"service_charge":0,
"public_expense":0,
"is_default":1,
"price_type":"mj",
"price_type_name":"每件",
"sort":1,
"price_desc":null,
"min_qty":1,
"max_qty":100
}
]
}
],
"requestId":"0f2cad6ead8f4788b61bdd619f45732e"
"status": 0,// 0为成功,否则失败
"payUrl": "https://syb.allinpay.com/apiweb/h5unionpay/unionorder?appid=00172286&body=%E5%95%86%E6%A0%87%E6%B3%A8%E5%86%8C%E3%80%90%E4%B8%93%E5%AE%B6%E8%BE%85%E5%8A%A9%E7%94%B3%E8%AF%B7%E3%80%91&charset=UTF-8&cusid=560595073992Z6G&notify_url=http%3A%2F%2Fgsb.qifu.gongsibao.com%3A4012%2Ftlpay%2Fnotify&randomstr=1581758584924&remark=h5paypagesywdy&reqsn=OT26202002151649kPgs&returl=http%3A%2F%2Fgsb.qifu.gongsibao.com%3A4012%2Ftlpay%2Fnotify&sign=439FA9F49D365DC32FE1CA712F5AD848&trxamt=69900&version=12", // H5支付链接
"requestId": "ac22e84d8ebc4df09629c0aff2bb1fe9"
}
```
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment