Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
students
butter-studio
Commits
c4a8991d
Commit
c4a8991d
authored
Jul 28, 2021
by
Jiwon Yoon
Browse files
gmail 연동
parent
619844f9
Changes
20
Hide whitespace changes
Inline
Side-by-side
client/public/images/naverpay_button.png
0 → 100644
View file @
c4a8991d
1.47 KB
client/public/images/payment_icon_yellow_medium.png
0 → 100644
View file @
c4a8991d
1.79 KB
client/public/images/photothumb.db
0 → 100644
View file @
c4a8991d
File added
client/public/photothumb.db
View file @
c4a8991d
No preview for this file type
client/src/App.js
View file @
c4a8991d
...
...
@@ -14,6 +14,7 @@ import AdminPage from "./pages/AdminPage/AdminPage";
import
TicketingPage
from
"
./pages/TicketingPage
"
;
import
TicketingSeatPage
from
'
./pages/TicketingSeatPage
'
import
SearchPage
from
"
./pages/SearchPage
"
;
import
Payment
from
"
./pages/PaymentPage
"
;
const
AppContext
=
React
.
createContext
();
...
...
@@ -36,6 +37,7 @@ function App() {
<
Route
path
=
"
/movie/:movieId
"
component
=
{
MoviePage
}
/
>
<
Route
path
=
"
/ticket/seat
"
component
=
{
TicketingSeatPage
}
/
>
<
Route
path
=
"
/ticket
"
component
=
{
TicketingPage
}
/
>
<
Route
path
=
"
/payment
"
component
=
{
Payment
}
/
>
<
Route
path
=
"
/search
"
component
=
{
SearchPage
}
/
>
<
Route
path
=
"
/admin
"
component
=
{
AdminPage
}
/
>
<
/Switch
>
...
...
client/src/components/CountButton.js
View file @
c4a8991d
...
...
@@ -12,7 +12,7 @@ const CountButton = (props) => {
}
}
return
(
<
span
className
=
""
>
<
div
className
=
""
>
<
button
type
=
"
button
"
name
=
"
backbutton
"
style
=
{{
backgroundColor
:
"
black
"
,
border
:
"
0
"
}}
onClick
=
{
handleCount
}
>
<
img
src
=
"
/images/icons8-back-24.png
"
name
=
"
backbutton
"
alt
=
"
<
"
/>
<
/button
>
...
...
@@ -20,7 +20,7 @@ const CountButton = (props) => {
<
button
type
=
"
button
"
name
=
"
forwardbutton
"
min
=
"
0
"
style
=
{{
backgroundColor
:
"
black
"
,
border
:
"
0
"
}}
onClick
=
{
handleCount
}
>
<
img
src
=
"
/images/icons8-forward-24.png
"
name
=
"
forwardbutton
"
alt
=
"
>
"
/>
<
/button
>
<
/
span
>
<
/
div
>
)
}
...
...
client/src/components/Kakaopay.js
0 → 100644
View file @
c4a8991d
import
axios
from
'
axios
'
const
Kakaopay
=
(
props
)
=>
{
async
function
handleClick
()
{
try
{
const
response
=
await
axios
.
post
(
'
/api/kakaopay/test/single
'
,
{
cid
:
'
TC0ONETIME
'
,
partner_order_id
:
'
orderNum
'
,
partner_user_id
:
'
userName
'
,
item_name
:
props
.
ticketInfo
.
title
,
quantity
:
props
.
ticketInfo
.
teenager
+
props
.
ticketInfo
.
adult
+
props
.
ticketInfo
.
elderly
,
total_amount
:
props
.
ticketInfo
.
teenager
*
7000
+
props
.
ticketInfo
.
adult
*
8000
+
props
.
ticketInfo
.
elderly
*
6000
,
vat_amount
:
0
,
tax_free_amount
:
0
,
approval_url
:
'
http://localhost:3000/
'
,
fail_url
:
'
http://localhost:3000/
'
,
cancel_url
:
'
http://localhost:3000/
'
,
})
console
.
log
(
response
.
data
)
if
(
response
.
data
)
{
window
.
location
.
href
=
response
.
data
.
redirect_url
}
}
catch
(
error
)
{
console
.
log
(
error
)
}
}
return
(
<>
<
button
onClick
=
{
handleClick
}
style
=
{{
backgroundColor
:
"
black
"
,
border
:
'
0
'
}}
>
<
img
src
=
"
/images/payment_icon_yellow_medium.png
"
/>
<
/button
>
<
/
>
)
}
export
default
Kakaopay
\ No newline at end of file
client/src/pages/MoviePage.js
View file @
c4a8991d
...
...
@@ -9,7 +9,7 @@ const MoviePage = ({ location }) => {
stillCuts
:
[],
cast
:
""
,
director
:
""
,
genres
:
[],
//
genres: [],
attendance
:
""
})
const
[
state
,
setState
]
=
useState
(
0
)
...
...
@@ -27,15 +27,15 @@ const MoviePage = ({ location }) => {
const
casts
=
castsInfo
.
reduce
((
acc
,
cur
,
idx
)
=>
{
if
(
idx
!==
0
)
return
acc
+
'
,
'
+
cur
else
return
acc
+
cur
},
""
)
},
""
)
console
.
log
(
castsInfo
)
const
directorsInfo
=
await
credits
.
crew
.
filter
(
element
=>
element
.
job
===
"
Director
"
)
const
directors
=
directorsInfo
.
reduce
((
acc
,
cur
,
idx
)
=>
{
if
(
idx
!==
0
)
return
acc
+
'
,
'
+
cur
.
name
else
return
acc
+
cur
.
name
},
""
)
},
""
)
console
.
log
(
"
directorInfo=
"
,
directorsInfo
)
console
.
log
(
"
directorInfo=
"
,
directorsInfo
)
setMovieInfo
({
...
movieInfo
,
stillCuts
:
still
,
...
...
@@ -81,7 +81,10 @@ const MoviePage = ({ location }) => {
<
p
>
예매율
:
0
%
누적관객수
:
{
movieInfo
.
attendance
}
명
<
/p
>
<
p
>
감독
:
{
movieInfo
.
director
}
<
/p
>
<
p
>
출연
:
{
movieInfo
.
cast
}
<
/p
>
<
p
>
장르
:
{
movieInfo
.
genres
.
map
(
e
=>
e
)}
<
/p
>
<
p
>
장르
:
{
movieInfo
.
genres
.
reduce
((
acc
,
cur
,
idx
)
=>
{
if
(
idx
!==
0
)
return
acc
+
'
,
'
+
cur
.
name
else
return
acc
+
cur
.
name
},
""
)}
<
/p
>
<
p
>
개봉일
:{
movieInfo
.
release_date
}
<
/p
>
<
div
className
=
"
text-end
"
>
<
Link
to
=
{{
...
...
client/src/pages/PaymentPage.js
0 → 100644
View file @
c4a8991d
import
axios
from
'
axios
'
import
{
useState
}
from
'
react
'
import
Kakaopay
from
'
../components/Kakaopay
'
const
Payment
=
({
location
})
=>
{
const
[
ticketInfo
,
setTicketInfo
]
=
useState
({
...
location
.
state
})
async
function
SendMail
(
e
)
{
try
{
const
response
=
await
axios
.
post
(
'
/api/email/send
'
,{
email
:
e
.
target
.
name
})
console
.
log
(
response
.
data
)
}
catch
(
error
)
{
console
.
log
(
error
)
}
}
return
(
<
div
className
=
"
container
"
style
=
{{
color
:
"
white
"
}}
>
{
console
.
log
(
ticketInfo
)}
<
div
className
=
"
row justify-content-center my-5
"
>
<
div
className
=
"
col-sm-4 mb-3
"
>
<
h3
className
=
"
py-2 text-white text-center
"
style
=
{{
border
:
"
3px solid #000000
"
,
borderBottom
:
"
3px solid #FEDC00
"
}}
>
결제하기
<
/h3
>
<
/div
>
<
/div
>
<
div
className
=
"
row justify-content-center
"
>
<
div
className
=
"
col-sm-8 text-center
"
>
<
h5
className
=
"
mb-3
"
>
결제방법
<
/h5
>
<
img
src
=
"
/images/naverpay_button.png
"
/>
<
Kakaopay
ticketInfo
=
{
ticketInfo
}
setTicketInfo
=
{
setTicketInfo
}
/
>
<
/div
>
<
div
className
=
"
col-sm-4 p-3 text-center rounded-3
"
style
=
{{
backgroundColor
:
"
#252525
"
}}
>
<
img
style
=
{{
maxHeight
:
"
10rem
"
}}
src
=
{
`https://image.tmdb.org/t/p/original
${
ticketInfo
.
poster_path
}
`
}
alt
=
"
영화포스터
"
/>
<
h5
className
=
"
my-3
"
>
{
ticketInfo
.
title
}
<
/h5
>
<
div
>
{
ticketInfo
.
theater
}
<
/div
>
<
div
>
{
ticketInfo
.
time
}
<
/div
>
<
div
className
=
"
mb-3
"
>
{
ticketInfo
.
selectedCinemaNum
}
관
{
ticketInfo
.
selectedSeats
}
<
/div
>
<
div
className
=
"
rounded-3 p-3
"
style
=
{{
backgroundColor
:
'
#404040
'
}}
>
<
div
>
청소년
:
{
ticketInfo
.
teenager
}
명
<
/div
>
<
div
>
성인
:
{
ticketInfo
.
adult
}
명
<
/div
>
<
div
>
경로우대
:
{
ticketInfo
.
elderly
}
명
<
/div
>
<
div
>
총
결제금액
:
{
ticketInfo
.
teenager
*
7000
+
ticketInfo
.
adult
*
8000
+
ticketInfo
.
elderly
*
6000
}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
>
<
button
type
=
"
button
"
name
=
"
jiwon5393@naver.com
"
onClick
=
{
SendMail
}
>
메일발송
<
/button
>
<
/div
>
<
/div
>
)
}
export
default
Payment
\ No newline at end of file
client/src/pages/TicketingPage.js
View file @
c4a8991d
...
...
@@ -9,8 +9,8 @@ const TicketingPage = ({ location }) => {
const
[
ticketInfo
,
setTicketInfo
]
=
useState
({
...
location
.
state
,
theater
:
""
,
selectedCinemaNum
:
0
,
time
:
{}
selectedCinemaNum
:
3
,
time
:
"
2021/07/21 10:00
"
})
const
[
theaterInfo
,
setTheaterInfo
]
=
useState
({
theater
:
[
"
Butter Studio 조치원
"
],
...
...
@@ -62,8 +62,8 @@ const TicketingPage = ({ location }) => {
?
<
ul
>
<
li
>
영화
:
{
movieInfo
.
title
}
<
/li
>
<
li
>
극장
:
{
ticketInfo
.
theater
}
<
/li
>
<
li
>
일시
:
<
/li
>
<
li
>
상영관
:
<
/li
>
<
li
>
일시
:
{
ticketInfo
.
time
}
<
/li
>
<
li
>
상영관
:
{
ticketInfo
.
selectedCinemaNum
}
<
/li
>
<
/ul
>
:
<
div
><
/div>
}
<
/div
>
...
...
client/src/pages/TicketingSeatPage.js
View file @
c4a8991d
...
...
@@ -22,25 +22,33 @@ const TicketingSeatPage = ({ location }) => {
<
/div
>
<
div
className
=
"
row justify-content-center my-3
"
>
<
div
className
=
"
col-sm-6 mb-4 text-center
"
>
<
ul
className
=
"
mr-2
"
style
=
{{
listStyle
:
'
none
'
}}
>
<
li
>
<
span
className
=
""
>
일반
<
/span
>
<
CountButton
name
=
"
adult
"
count
=
{
count
}
setCount
=
{
setCount
}
/
>
<
/li
>
<
li
>
<
span
className
=
""
>
청소년
<
/span
>
<
CountButton
name
=
"
teenager
"
count
=
{
count
}
setCount
=
{
setCount
}
/
>
<
/li
>
<
li
>
<
span
className
=
""
>
경로우대
<
/span
>
<
CountButton
name
=
"
elderly
"
count
=
{
count
}
setCount
=
{
setCount
}
/
>
<
/li
>
<
/ul
>
<
div
className
=
"
row
"
>
<
div
className
=
"
col-sm-6 text-end
"
>
<
div
className
=
"
my-1
"
>
일반
<
/div
>
<
div
className
=
"
my-1
"
>
청소년
<
/div
>
<
div
className
=
"
my-1
"
>
경로우대
<
/div
>
<
/div
>
<
div
className
=
"
col-sm-6 text-start
"
>
<
CountButton
name
=
"
adult
"
count
=
{
count
}
setCount
=
{
setCount
}
/
>
<
CountButton
name
=
"
teenager
"
count
=
{
count
}
setCount
=
{
setCount
}
/
>
<
CountButton
name
=
"
elderly
"
count
=
{
count
}
setCount
=
{
setCount
}
/
>
<
/div
>
<
/div
>
{
/* <span className="">일반</span>
<CountButton name="adult" count={count} setCount={setCount} />
<span className="">청소년</span>
<CountButton name="teenager" count={count} setCount={setCount} />
<span className="">경로우대</span>
<CountButton name="elderly" count={count} setCount={setCount} /> */
}
<
/div
>
<
div
className
=
"
col-sm-6 mb-4 p-2 text-center
"
style
=
{{
backgroundColor
:
'
#252525
'
}}
>
<
div
>
{
ticketInfo
.
theater
}
|
3
관
<
/div
>
<
div
>
{
ticketInfo
.
theater
}
|
{
ticketInfo
.
selectedCinemaNum
}
관
<
/div
>
<
div
>
{
ticketInfo
.
title
}
<
/div
>
<
div
>
2021
/
07
/
21
10
:
00
~
11
:
30
<
/div
>
<
div
>
{
ticketInfo
.
time
}
<
/div
>
<
/div
>
<
/div
>
<
div
className
=
"
row justify-content-center border p-5
"
>
...
...
@@ -52,7 +60,7 @@ const TicketingSeatPage = ({ location }) => {
<
p
>
선택불가
<
/p
>
<
/div
>
<
/div
>
<
div
className
=
"
row p-3 m
y
-5
"
style
=
{{
backgroundColor
:
"
#252525
"
}}
>
<
div
className
=
"
row p-3 m
t
-5
"
style
=
{{
backgroundColor
:
"
#252525
"
}}
>
<
div
className
=
"
col-sm-3 border-end text-center
"
>
{
ticketInfo
?
<
img
style
=
{{
maxHeight
:
"
10rem
"
}}
src
=
{
`https://image.tmdb.org/t/p/original
${
ticketInfo
.
poster_path
}
`
}
alt
=
"
영화포스터
"
/>
...
...
@@ -76,7 +84,7 @@ const TicketingSeatPage = ({ location }) => {
?
<
Link
to
=
{{
pathname
:
`/payment`
,
state
:
{
}
state
:
{
...
ticketInfo
,
selectedSeats
:
selectedSeats
,
...
count
}
}}
>
<
img
className
=
"
border border-3 rounded-3
"
src
=
"
/images/icons8-arrow-white.png
"
alt
=
"
예매하기
"
/>
<
/Link
>
...
...
package-lock.json
View file @
c4a8991d
...
...
@@ -1087,6 +1087,11 @@
"resolved"
:
"https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz"
,
"integrity"
:
"sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"nodemailer"
:
{
"version"
:
"6.6.3"
,
"resolved"
:
"https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.3.tgz"
,
"integrity"
:
"sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew=="
},
"nodemon"
:
{
"version"
:
"2.0.12"
,
"resolved"
:
"https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz"
,
...
...
package.json
View file @
c4a8991d
...
...
@@ -23,6 +23,7 @@
"
express
"
:
"
^4.17.1
"
,
"
jsonwebtoken
"
:
"
^8.5.1
"
,
"
multer
"
:
"
^1.4.2
"
,
"
nodemailer
"
:
"
^6.6.3
"
,
"
pg
"
:
"
^8.6.0
"
,
"
pg-hstore
"
:
"
^2.3.4
"
,
"
sequelize
"
:
"
^6.6.4
"
...
...
server/config/app.config.js
View file @
c4a8991d
...
...
@@ -5,6 +5,7 @@ const config = {
jwtExpires
:
'
7d
'
,
cookieName
:
'
butterStudio
'
,
cookieMaxAge
:
60
*
60
*
24
*
7
*
1000
,
kakaoAdminKey
:
'
e3ce7106688a35e072e2630daa9d7250
'
,
}
export
default
config
\ No newline at end of file
server/controllers/email.controller.js
0 → 100644
View file @
c4a8991d
import
nodemailer
from
"
nodemailer
"
const
SendMail
=
async
(
req
,
res
)
=>
{
// console.log(req.body)
const
{
email
}
=
req
.
body
console
.
log
(
email
)
const
sendMail
=
async
(
email
)
=>
{
// 메일을 전달해줄 객체
const
transporter
=
nodemailer
.
createTransport
({
// service: "gmail",
host
:
'
smtp.gmail.com
'
,
port
:
465
,
secure
:
true
,
auth
:
{
type
:
"
OAuth2
"
,
user
:
"
angelayoon99@gmail.com
"
,
clientId
:
process
.
env
.
GMAIL_CLIENTID
,
clientSecret
:
process
.
env
.
GMAIL_CLIENTSECRET
,
accessToken
:
process
.
env
.
GMAIL_ACCESS_TOKEN
,
refreshToken
:
process
.
env
.
GMAIL_REFRESH_TOKEN
,
},
tls
:
{
rejectUnauthorized
:
false
,
},
});
// 메일 옵션
const
mailOptions
=
{
from
:
`윤지원 <angelayoon99@gmail.com>`
,
to
:
"
jiwon5393@naver.com
"
,
subject
:
"
사용자 계정 확인용 메일.
"
,
text
:
"
Test Mail from Test Server.
"
,
};
// 메일 전송
try
{
const
mailResult
=
await
transporter
.
sendMail
(
mailOptions
);
console
.
log
(
`Mail sent - ID :
${
mailResult
.
messageId
}
`
);
}
catch
(
err
)
{
console
.
log
(
"
Mail Sending Failuer.
"
);
console
.
log
(
err
);
}
}
sendMail
(
email
);
}
export
default
{
SendMail
}
\ No newline at end of file
server/controllers/kakaopay.controller.js
0 → 100644
View file @
c4a8991d
import
axios
from
'
axios
'
import
config
from
"
../config/app.config.js
"
;
const
success
=
(
req
,
res
)
=>
{
return
res
.
json
({
message
:
'
Success
'
})
}
const
fail
=
(
req
,
res
)
=>
{
return
res
.
json
({
message
:
'
Failed
'
})
}
const
cancel
=
(
req
,
res
)
=>
{
return
res
.
json
({
message
:
'
Canceled
'
})
}
const
singleTest
=
async
(
req
,
res
)
=>
{
try
{
const
item
=
req
.
body
const
data
=
[]
for
(
let
property
in
item
)
{
let
encodedKey
=
encodeURIComponent
(
property
);
let
encodedValue
=
encodeURIComponent
(
item
[
property
]);
data
.
push
(
encodedKey
+
"
=
"
+
encodedValue
);
}
const
bodyData
=
data
.
join
(
'
&
'
)
const
response
=
await
axios
.
post
(
'
https://kapi.kakao.com/v1/payment/ready
'
,
bodyData
,
{
headers
:
{
'
Authorization
'
:
`KakaoAK
${
config
.
kakaoAdminKey
}
`
,
'
Content-Type
'
:
'
application/x-www-form-urlencoded;charset=UTF-8
'
,
},
})
const
resp
=
response
.
data
console
.
log
(
'
resp
'
,
resp
)
res
.
json
({
redirect_url
:
resp
.
next_redirect_pc_url
})
}
catch
(
error
)
{
console
.
log
(
error
)
}
}
export
default
{
success
,
fail
,
cancel
,
singleTest
}
\ No newline at end of file
server/db/index.js
View file @
c4a8991d
...
...
@@ -35,9 +35,6 @@ const Reservation = ReservationModel(sequelize)
User
.
belongsTo
(
Role
);
Role
.
hasOne
(
User
);
User
.
belongsTo
(
Role
);
Role
.
hasOne
(
User
);
export
{
sequelize
,
User
,
...
...
server/routes/email.route.js
0 → 100644
View file @
c4a8991d
import
express
from
"
express
"
;
import
EmailCtrl
from
'
../controllers/email.controller.js
'
const
router
=
express
.
Router
();
router
.
route
(
"
/send
"
)
.
post
(
EmailCtrl
.
SendMail
)
export
default
router
\ No newline at end of file
server/routes/index.js
View file @
c4a8991d
...
...
@@ -2,11 +2,15 @@ import express from "express";
import
userRouter
from
'
./user.route.js
'
import
movieRouter
from
'
./movie.route.js
'
import
cinemaRouter
from
"
./cinema.route.js
"
;
import
kakaopayRouter
from
"
./kakaopay.route.js
"
;
import
emailRouter
from
'
./email.route.js
'
const
router
=
express
.
Router
();
router
.
use
(
'
/movie
'
,
movieRouter
)
router
.
use
(
'
/auth
'
,
userRouter
)
router
.
use
(
'
/cinema
'
,
cinemaRouter
)
router
.
use
(
'
/kakaopay
'
,
kakaopayRouter
)
router
.
use
(
'
/email
'
,
emailRouter
)
export
default
router
;
\ No newline at end of file
server/routes/kakaopay.route.js
0 → 100644
View file @
c4a8991d
import
express
from
'
express
'
import
kakaopayCtrl
from
'
../controllers/kakaopay.controller.js
'
const
router
=
express
.
Router
()
router
.
route
(
'
/success
'
)
.
get
(
kakaopayCtrl
.
success
)
router
.
route
(
'
/fail
'
)
.
get
(
kakaopayCtrl
.
fail
)
router
.
route
(
'
/cancel
'
)
.
get
(
kakaopayCtrl
.
cancel
)
router
.
route
(
'
/test/single
'
)
.
post
(
kakaopayCtrl
.
singleTest
)
export
default
router
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment