diff --git a/src/backend/handler.js b/src/backend/handler.js index 2cb34ad..c13af5b 100644 --- a/src/backend/handler.js +++ b/src/backend/handler.js @@ -127,9 +127,15 @@ module.exports.itemDetail = async (event) => { } }; -module.exports.qrcodeTest = async (event) => { - const re = await authenticator.generateQrcode("userId=awefoiewbuafwehweabu&itemId=eifbaif7382bvhdj&token=euhsnvjqifjekvne"); - return builder.buildAWSResponse(re); +module.exports.itemSellerContract = async (event) => { + if (await checkAuth(event) == true) { + const response = await itemHandler.sellerContract(event); + console.log(response); + return response; + } else { + console.log("Auth fail"); + return getAuthFailResponse(); + } }; module.exports.test = async (event) => { diff --git a/src/backend/handlers/item.js b/src/backend/handlers/item.js index 3d51935..7333fb2 100644 --- a/src/backend/handlers/item.js +++ b/src/backend/handlers/item.js @@ -2,6 +2,7 @@ const parser = require("../utils/parser"); const database = require("../utils/database"); +const authenticator = require("../utils/authenticator"); const responseTemplate = require("../responses/template"); const registration = async (event) => { @@ -23,6 +24,7 @@ const registration = async (event) => { const list = async (event) => { const userId = parser.getUserId(event); + const mode = parser.getExtras(event)["mode"]; const result = await database.getUserItem(userId); if (result == null) { @@ -30,7 +32,7 @@ const list = async (event) => { } else if (result.length == 0) { return responseTemplate.itemListFail("등록된 상품이 없습니다."); } else { - return responseTemplate.itemListSuccess(result, "list"); + return responseTemplate.itemListSuccess(result, mode); } }; @@ -71,7 +73,7 @@ const detail = async (event) => { const item = await database.getItem(itemId); if (item != null) { const user = (mode == "search" ? await database.getUser(userId) : null); - if (user != null) { + if (user != null || mode == "list") { return responseTemplate.itemDetail(item, mode, user); } else { return responseTemplate.itemListFail("상품 조회에 실패했습니다."); @@ -81,10 +83,32 @@ const detail = async (event) => { } }; +const sellerContract = async (event) => { + const userId = parser.getUserId(event); + const extras = parser.getExtras(event); + const itemId = extras["itemId"]; + + const qrcode = authenticator.getContractQrcode(userId, itemId); + const token = qrcode.token; + const qrcodePaths = await database.uploadImages("contract/" + token + "/", [qrcode.qrcodePath]); + + if (qrcodePaths == null) { + return responseTemplate.processFail("상품 판매 실패", "상품 판매 등록에 실패했습니다."); + } else { + const result = await database.registTempDeal(userId, itemId, token); + if (result.success == true) { + return responseTemplate.itemSellerContractSuccess(qrcodePaths[0], itemId); + } else { + return responseTemplate.processFail("상품 판매 실패", "상품 판매 등록에 실패했습니다."); + } + } +}; + module.exports = { registration, list, searchCategory, searchKeyword, - detail + detail, + sellerContract }; diff --git a/src/backend/responses/common.js b/src/backend/responses/common.js index 3c1d592..6c08e88 100644 --- a/src/backend/responses/common.js +++ b/src/backend/responses/common.js @@ -14,8 +14,8 @@ module.exports.welcome = () => { // Construct seller card const sellerThumbnail = builder.getThumbnail(resource.sellerThumbnailUrl); const sellerItemRegistButton = builder.getButton("상품 등록", "block", "상품 등록", resource.sellerItemRegistBlockId); - const sellerItemListButton = builder.getButton("상품 목록", "block", "상품 목록", resource.sellerItemListBlockId); - const sellerContractButton = builder.getButton("판매자 거래 체결", "block", "판매자 거래 체결", resource.sellerContractBlockId); + const sellerItemListButton = builder.getButton("상품 목록", "block", "상품 목록", resource.sellerItemListBlockId, {mode: "list"}); + const sellerContractButton = builder.getButton("판매자 거래 체결", "block", "판매자 거래 체결", resource.sellerItemListBlockId, {mode: "contract"}); const sellerCardBody = builder.getBasicCardBody("판매", "상품을 판매합니다.", sellerThumbnail, [sellerItemRegistButton, sellerItemListButton, sellerContractButton]); // Construct user information card @@ -28,3 +28,14 @@ module.exports.welcome = () => { // Build response return builder.buildResponse([builder.getCarousel("basicCard", [buyerCardBody, sellerCardBody, userInfoCardBody])], false); }; + +module.exports.processFail = (errorTitle, errorMessage) => { + // Construct result card + const resultThumbnail = builder.getThumbnail(resource.itemRegistrationFailThumbnailUrl); + const resultTitle = errorTitle; + const resultDescription = errorMessage; + const resultCard = builder.getBasicCard(resultTitle, resultDescription, resultThumbnail); + + // Build response + return builder.buildResponse([resultCard]); +}; diff --git a/src/backend/responses/item.js b/src/backend/responses/item.js index 4dac456..2aa6763 100644 --- a/src/backend/responses/item.js +++ b/src/backend/responses/item.js @@ -9,8 +9,7 @@ module.exports.itemRegistrationSuccess = (itemName, itemDetail, itemPrice, image const resultTitle = itemName; const resultDescription = itemDetail; const resultPrice = itemPrice; - const resultMainMenuButton = builder.getButton("처음으로", "block", "처음으로", resource.welcomeBlockId); - const resultCard = builder.getCommerceCard(resultTitle, resultDescription, resultPrice, resultThumbnail, null, [resultMainMenuButton]); + const resultCard = builder.getCommerceCard(resultTitle, resultDescription, resultPrice, resultThumbnail, null); // Build response return builder.buildResponse([resultCard]); @@ -21,15 +20,14 @@ module.exports.itemRegistrationFail = (errorMessage) => { const resultThumbnail = builder.getThumbnail(resource.itemRegistrationFailThumbnailUrl); const resultTitle = "상품 등록 실패"; const resultDescription = errorMessage; - const resultMainMenuButton = builder.getButton("처음으로", "block", "처음으로", resource.welcomeBlockId); - const resultCard = builder.getBasicCard(resultTitle, resultDescription, resultThumbnail, [resultMainMenuButton]); + const resultCard = builder.getBasicCard(resultTitle, resultDescription, resultThumbnail); // Build response return builder.buildResponse([resultCard]); }; module.exports.itemListSuccess = (itemList, mode="search") => { - const modes = ["list", "search"]; + const modes = ["list", "search", "contract"]; if (modes.includes(mode)) { // Construct commerce cards @@ -53,9 +51,8 @@ module.exports.itemListSuccess = (itemList, mode="search") => { } else if (mode == "search") { buttons.push(builder.getButton("구매", "block", "구매", resource.itemBuyBlockId, {userId: resultUserId, itemId: resultItemId})); buttons.push(builder.getButton("상세정보", "block", "상세정보", resource.itemDetailBlockId, {userId: resultUserId, itemId: resultItemId, mode: "search"})); - // buttons.push(builder.getButton("신고", "block", "신고", resource.itemReportBlockId, {userId: resultUserId, itemId: resultItemId})); - } else if (mode == "transaction") { - buttons.push(builder.getButton("판매", "block", "판매", resource.itemSellBlockId, {itemId: resultItemId})); + } else if (mode == "contract") { + buttons.push(builder.getButton("판매", "block", "판매", resource.itemSellerContractBlockId, {itemId: resultItemId})); } bodys.push(builder.getCommerceCardBody(resultTitle, resultDescription, resultPrice, resultThumbnail, resultNickname, buttons)); } @@ -72,8 +69,7 @@ module.exports.itemListFail = (errorMessage) => { const resultThumbnail = builder.getThumbnail(resource.itemRegistrationFailThumbnailUrl); const resultTitle = "상품 조회 실패"; const resultDescription = errorMessage; - const resultMainMenuButton = builder.getButton("처음으로", "block", "처음으로", resource.welcomeBlockId); - const resultCard = builder.getBasicCard(resultTitle, resultDescription, resultThumbnail, [resultMainMenuButton]); + const resultCard = builder.getBasicCard(resultTitle, resultDescription, resultThumbnail); // Build response return builder.buildResponse([resultCard]); @@ -81,15 +77,23 @@ module.exports.itemListFail = (errorMessage) => { module.exports.itemDetail = (item, mode="list", user=null) => { // Construct registration guide - const resultThumbnail = builder.getThumbnail(item.item_image[0]); - const resultUserId = (user.userId != undefined ? user.userId : null); + const resultThumbnail = builder.getThumbnail(item.item_image[0], true, 500, 500); + const resultUserId = (user != null ? user.userId : null); const resultItemId = item.itemId; const resultTitle = item.item_name + "(" + item.item_price + "원)"; - const resultDescription = item.item_detail + "\n";// + item.item_date; + const resultDescription = item.item_detail + "\n"+ item.item_date; const resultMainMenuButton = (mode == "list" ? builder.getButton("삭제", "block", "삭제", resource.itemDeleteBlockId) : builder.getButton("구매", "block", "구매", resource.itemBuyBlockId, {userId: resultUserId, itemId: resultItemId})); const resultCard1 = builder.getBasicCardBody(resultTitle, resultDescription, "", [resultMainMenuButton, resultMainMenuButton]); - const resultCard2 = builder.getBasicCardBody("", "uiiyfiyiyfi", resultThumbnail); + const resultCard2 = builder.getBasicCardBody("", "", resultThumbnail); // Build response return builder.buildResponse([builder.getCarousel("basicCard", [resultCard1, resultCard2, resultCard2])]); }; + +module.exports.itemSellerContractSuccess = (qrcodePath, itemId) => { + const resultThumbnail = builder.getThumbnail(qrcodePath, true, 200, 200); + const resultText = "구매자에게 '구매자 거래 체결' 메뉴를 이용해 QR코드를 스캔하도록 안내해 주세요."; + const resultOkButton = builder.getButton("스캔완료", "block", "스캔완료", resource.itemSellerContractVerifyBlockId, {itemId: itemId}); + const basicCard = builder.getBasicCard("", resultText, resultThumbnail, [resultOkButton]); + return builder.buildResponse([basicCard]); +}; diff --git a/src/backend/responses/template.js b/src/backend/responses/template.js index 15077c8..0b0c98d 100644 --- a/src/backend/responses/template.js +++ b/src/backend/responses/template.js @@ -6,6 +6,7 @@ const itemResponse = require("./item"); module.exports = { welcome: commonResponse.welcome, + processFail: commonResponse.processFail, userRegistration: userResponse.userRegistration, userRegistrationSuccess: userResponse.userRegistrationSuccess, userRegistrationFail: userResponse.userRegistrationFail, @@ -16,5 +17,6 @@ module.exports = { itemRegistrationFail: itemResponse.itemRegistrationFail, itemListSuccess: itemResponse.itemListSuccess, itemListFail: itemResponse.itemListFail, - itemDetail: itemResponse.itemDetail + itemDetail: itemResponse.itemDetail, + itemSellerContractSuccess: itemResponse.itemSellerContractSuccess }; diff --git a/src/backend/responses/user.js b/src/backend/responses/user.js index 4cde1d4..940e3a0 100644 --- a/src/backend/responses/user.js +++ b/src/backend/responses/user.js @@ -48,11 +48,10 @@ module.exports.userInformation = (nickname, school_name, school_mail, openprofil const infoSchoolMailList = builder.getListItem(school_mail, "학교 이메일"); const infoOpenProfileList = builder.getListItem(openprofile, "오픈프로필 주소"); const infoReliabilityScoreList = builder.getListItem(reliability_score, "신뢰도"); - const infoOpenProfileButton = builder.getButton("오픈프로필로", "webLink", openprofile); - const infoMainMenuButton = builder.getButton("처음으로", "block", "처음으로", resource.welcomeBlockId); - const infoCard = builder.getListCard(infoTitle, "", [infoNicknameList, infoSchoolNameList, infoSchoolMailList, - infoOpenProfileList, infoReliabilityScoreList], - [infoOpenProfileButton, infoMainMenuButton]); + const infoOpenProfileButton = builder.getButton("오픈프로필로 가기", "webLink", openprofile); + const infoWithdrawButton = builder.getButton("회원 탈퇴", "block", "회원 탈퇴", resource.userWithdrawBlockId); + const infoCard = builder.getListCard(infoTitle, "", [infoNicknameList, infoSchoolNameList, infoSchoolMailList, infoOpenProfileList, infoReliabilityScoreList], + [infoOpenProfileButton, infoWithdrawButton]); // Build response return builder.buildResponse([infoCard]); diff --git a/src/backend/serverless.yml b/src/backend/serverless.yml index f3f71c6..0e1bd35 100644 --- a/src/backend/serverless.yml +++ b/src/backend/serverless.yml @@ -67,11 +67,11 @@ functions: - http: path: item/detail method: post - qrcodeTest: - handler: handler.qrcodeTest + itemSellerContract: + handler: handler.itemSellerContract events: - http: - path: qrcode + path: item/contract/seller method: post test: handler: handler.test diff --git a/src/backend/utils/authenticator.js b/src/backend/utils/authenticator.js index afb17e5..4835f69 100755 --- a/src/backend/utils/authenticator.js +++ b/src/backend/utils/authenticator.js @@ -14,9 +14,9 @@ const transporter = nodemailer.createTransport({ } }); -const generateQrcode = (url) => { +const generateQrcode = (string) => { const path = "/tmp/qrcode.png"; - qrcode.toFile(path, url); + qrcode.toFile(path, string); return path; }; @@ -34,6 +34,16 @@ const generateToken = (seed="") => { return token; }; +const getContractQrcode = (userId, itemId) => { + const token = generateToken(); + const info = "userId=" + userId + "&itemId=" + itemId + "&token=" + token; + const qrcodePath = generateQrcode(info); + return { + token: token, + qrcodePath: qrcodePath + }; +}; + const generateMailAuthenticationUrl = (userId, token) => { return resource.mailAuthenticateEndpoint + "?userId=" + userId + "&token=" + token; } @@ -83,8 +93,8 @@ const sendAuthenticateMail = async (userId, userMail) => { }; module.exports = { - generateQrcode, authenticateUser, authenticateMail, - sendAuthenticateMail + sendAuthenticateMail, + getContractQrcode } diff --git a/src/backend/utils/builder.js b/src/backend/utils/builder.js index 0236d69..b87cb20 100644 --- a/src/backend/utils/builder.js +++ b/src/backend/utils/builder.js @@ -64,9 +64,12 @@ const getButton = (label, action, data, blockId=undefined, extra=undefined) => { } } -const getThumbnail = (imageUrl) => { +const getThumbnail = (imageUrl, fixedRatio=false, width=100, height=100) => { return { - imageUrl: imageUrl + imageUrl: imageUrl, + fixedRatio: fixedRatio, + width: width, + height: height }; } diff --git a/src/backend/utils/resource.js b/src/backend/utils/resource.js index 18dac01..d08b760 100644 --- a/src/backend/utils/resource.js +++ b/src/backend/utils/resource.js @@ -31,5 +31,7 @@ module.exports = { itemDeleteBlockId: "5decfa26ffa74800014b098e", // Temp itemBuyBlockId: "5decfa26ffa74800014b098e", // Temp itemReportBlockId: "5decfa26ffa74800014b098e", // Temp - itemSellBlockId: "5decfa26ffa74800014b098e", // Temp + itemSellerContractBlockId: "5de3d4eaffa7480001988104", + userWithdrawBlockId: "5de3d56d8192ac0001d65d18", // Temp + itemSellerContractVerifyBlockId: "5de3d56d8192ac0001d65d18", // Temp };