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
6e0e826d
Commit
6e0e826d
authored
Aug 10, 2021
by
Jiwon Yoon
Browse files
카카오페이 결제실패 및 예매내역삭제
parent
432e3eb3
Changes
15
Hide whitespace changes
Inline
Side-by-side
client/src/App.js
View file @
6e0e826d
...
...
@@ -15,8 +15,9 @@ 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/PaymentPage
"
;
import
Payment
Page
from
"
./pages/PaymentPage/PaymentPage
"
;
import
PaymentCompletePage
from
"
./pages/PaymentCompletePage
"
;
import
PaymentFailPage
from
"
./pages/PaymentFailPage
"
;
function
App
()
{
...
...
@@ -39,8 +40,9 @@ function App() {
<
Route
path
=
"
/guest
"
component
=
{
GuestPage
}
/
>
<
Route
path
=
"
/ticket/seat
"
component
=
{
TicketingSeatPage
}
/
>
<
Route
path
=
"
/ticket
"
component
=
{
TicketingPage
}
/
>
<
Route
path
=
"
/payment
"
component
=
{
Payment
}
/
>
<
Route
path
=
"
/payment
"
component
=
{
Payment
Page
}
/
>
<
Route
path
=
"
/paymentcomplete
"
component
=
{
PaymentCompletePage
}
/
>
<
Route
path
=
"
/paymentfail
"
component
=
{
PaymentFailPage
}
/
>
<
Route
path
=
"
/theater
"
component
=
{
TheaterPage
}
/
>
<
Route
path
=
"
/search
"
component
=
{
SearchPage
}
/
>
<
/Switch
>
...
...
client/src/apis/kakaopay.api.js
0 → 100644
View file @
6e0e826d
import
axios
from
"
axios
"
;
import
{
baseUrl
}
from
"
../utils/baseUrl.js
"
;
const
approveReq
=
async
(
info
)
=>
{
const
url
=
`
${
baseUrl
}
/api/kakaopay/test/single`
;
const
{
data
}
=
await
axios
.
post
(
url
,
info
);
return
data
}
const
approveSuccess
=
async
(
info
)
=>
{
const
url
=
`
${
baseUrl
}
/api/kakaopay/success`
;
const
{
data
}
=
await
axios
.
post
(
url
,
info
);
return
data
}
const
paymentCancel
=
async
(
info
)
=>
{
const
url
=
`
${
baseUrl
}
/api/kakaopay/cancel`
;
const
{
data
}
=
await
axios
.
post
(
url
,
info
);
return
data
}
const
kakaopayApi
=
{
approveReq
,
approveSuccess
,
paymentCancel
}
export
default
kakaopayApi
\ No newline at end of file
client/src/apis/reservation.api.js
View file @
6e0e826d
...
...
@@ -4,7 +4,7 @@ import { baseUrl } from "../utils/baseUrl.js";
const
findReservedSeats
=
async
(
timeTable
)
=>
{
console
.
log
(
timeTable
)
const
url
=
`
${
baseUrl
}
/api/reservation/findreservation`
;
const
{
data
}
=
await
axios
.
post
(
url
,
{
timeTable
:
timeTable
});
const
{
data
}
=
await
axios
.
post
(
url
,
{
timeTable
:
timeTable
});
return
data
}
...
...
@@ -25,12 +25,26 @@ const save = async (save) => {
const
url
=
`
${
baseUrl
}
/api/reservation/save`
;
const
{
data
}
=
await
axios
.
post
(
url
,
save
);
return
data
}
const
saveTid
=
async
(
tid
)
=>
{
const
url
=
`
${
baseUrl
}
/api/reservation/savetid`
;
const
{
data
}
=
await
axios
.
post
(
url
,
tid
);
return
data
}
const
reservationApi
=
{
const
deleteReservation
=
async
()
=>
{
const
url
=
`
${
baseUrl
}
/api/reservation/delete`
;
const
{
data
}
=
await
axios
.
get
(
url
);
return
data
}
const
reservationApi
=
{
findReservation
,
findReservedSeats
,
findOneReservation
,
save
save
,
saveTid
,
deleteReservation
}
export
default
reservationApi
\ No newline at end of file
client/src/components/KakaopaymentCancelBtn.js
0 → 100644
View file @
6e0e826d
import
kakaopayApi
from
"
../apis/kakaopay.api
"
import
catchErrors
from
"
../utils/catchErrors
"
const
KakaopaymentCancelBtn
=
()
=>
{
const
[
error
,
setError
]
=
useState
()
async
function
paymentCancel
()
{
try
{
setError
(
""
)
//실행하기 전에 먼저 reservation에서 해당하는 예매건에 대한 tid가져오기
const
response
=
await
kakaopayApi
.
paymentCancel
({
cid
:
'
TC0ONETIME
'
,
tid
:
''
,
cancel_amount
:
''
,
cancel_tax_free_amount
:
0
,
})
}
catch
(
error
)
{
catchErrors
(
error
,
setError
)
}
}
return
(
<
button
className
=
"
btn btn-warning
"
onClick
=
{
paymentCancel
}
>
결제취소
<
/button
>
)
}
\ No newline at end of file
client/src/components/TheaterInfo.js
View file @
6e0e826d
...
...
@@ -60,7 +60,7 @@ const TheaterInfo = () => {
information
:
response
.
transportation
})
}
catch
(
error
)
{
catchErrors
(
error
,
setError
)
//
catchErrors(error, setError)
console
.
log
(
error
)
}
}
...
...
client/src/pages/MoviePage.js
View file @
6e0e826d
...
...
@@ -66,7 +66,7 @@ const MoviePage = ({ location }) => {
<
/div
>
<
div
className
=
"
col-sm-6
"
style
=
{{
color
:
"
white
"
}}
>
<
h1
className
=
"
pb-3
"
>
{
movieInfo
.
title
}
<
/h1
>
<
p
>
예매율
:{
Math
.
round
((
movieInfo
.
ticket_sales
/
(
movieInfo
.
totalReservationRate
.
totalReservationRate
||
1
))
*
100
)}
%
누적관객수
:
{
movieInfo
.
ticket_sales
}
명
<
/p
>
<
p
>
예매율
:
{
Math
.
round
((
movieInfo
.
ticket_sales
/
(
movieInfo
.
totalReservationRate
.
totalReservationRate
||
1
))
*
100
)}
%
누적관객수
:
{
movieInfo
.
ticket_sales
}
명
<
/p
>
{
movieInfo
.
director
||
movieInfo
.
cast
?
<>
...
...
@@ -80,7 +80,7 @@ const MoviePage = ({ location }) => {
if
(
idx
!==
0
)
return
acc
+
'
,
'
+
cur
.
name
else
return
acc
+
cur
.
name
},
""
)}
<
/p
>
<
p
>
개봉일
:{
movieInfo
.
release_date
}
<
/p
>
<
p
>
개봉일
:
{
movieInfo
.
release_date
}
<
/p
>
<
div
className
=
"
text-end
"
>
<
Link
to
=
{{
pathname
:
`/ticket`
,
...
...
client/src/pages/PaymentCompletePage.js
View file @
6e0e826d
...
...
@@ -4,6 +4,7 @@ import moment from 'moment';
import
{
useAuth
}
from
'
../context/auth_context
'
import
catchErrors
from
'
../utils/catchErrors
'
import
reservationApi
from
'
../apis/reservation.api
'
import
kakaopayApi
from
'
../apis/kakaopay.api
'
;
const
PaymentCompletePage
=
()
=>
{
const
{
user
}
=
useAuth
()
...
...
@@ -25,9 +26,10 @@ const PaymentCompletePage = () => {
async
function
saveGuestReservation
()
{
try
{
setError
(
""
)
const
response
=
await
axios
.
get
(
`/api/auth/guestinfo/
${
user
.
id
}
`
);
const
response2
=
await
reservationApi
.
findOneReservation
()
cons
ole
.
log
(
"
예매내역=====
"
,
response2
)
cons
t
response3
=
await
reservationApi
.
saveTid
({
tid
:
localStorage
.
getItem
(
'
tid
'
)}
)
if
(
response
.
data
||
response2
)
{
const
responseEmail
=
await
axios
.
post
(
'
/api/email/send
'
,
{
reservationData
:
response2
.
map
(
el
=>
{
return
{
"
row
"
:
el
.
row
,
"
col
"
:
el
.
col
}
}),
...
...
@@ -37,7 +39,7 @@ const PaymentCompletePage = () => {
theater
:
response2
[
0
].
theater
.
theaterName
,
time
:
response2
[
0
].
timetable
.
date
.
split
(
'
T
'
)[
0
]
+
'
'
+
moment
(
response2
[
0
].
timetable
.
start_time
).
format
(
'
HH:mm
'
)
})
console
.
log
(
responseEmail
.
data
)
localStorage
.
removeItem
(
'
tid
'
)
}
}
catch
(
error
)
{
catchErrors
(
error
,
setError
)
...
...
@@ -46,18 +48,23 @@ const PaymentCompletePage = () => {
async
function
saveUserReservation
()
{
try
{
setError
(
""
)
const
response
=
await
axios
.
post
(
`/api/auth/getuserinfo`
,
{
id
:
user
.
id
})
// if (response.data) {
// const responseEmail = await axios.post('/api/email/send', {
// ...response2.data,
// ...response.data,
// })
// console.log(responseEmail.data)
// }
const
response2
=
await
reservationApi
.
findOneReservation
()
const
response3
=
await
reservationApi
.
saveTid
({
tid
:
localStorage
.
getItem
(
'
tid
'
)})
if
(
response
.
data
||
response2
)
{
const
responseEmail
=
await
axios
.
post
(
'
/api/email/send
'
,
{
reservationData
:
response2
.
map
(
el
=>
{
return
{
"
row
"
:
el
.
row
,
"
col
"
:
el
.
col
}
}),
userData
:
{
...
response
.
data
},
cinema
:
"
Butter Studio 조치원
"
,
title
:
response2
[
0
].
title
,
theater
:
response2
[
0
].
theater
.
theaterName
,
time
:
response2
[
0
].
timetable
.
date
.
split
(
'
T
'
)[
0
]
+
'
'
+
moment
(
response2
[
0
].
timetable
.
start_time
).
format
(
'
HH:mm
'
)
})
localStorage
.
removeItem
(
'
tid
'
)
}
}
catch
(
error
)
{
catchErrors
(
error
,
setError
)
}
...
...
@@ -65,9 +72,10 @@ const PaymentCompletePage = () => {
async
function
approveKakaopay
(
tid
)
{
try
{
setError
(
""
)
const
urlParams
=
new
URLSearchParams
(
window
.
location
.
search
);
const
pg_token
=
urlParams
.
get
(
'
pg_token
'
);
const
response
=
await
axios
.
post
(
`/api/kakaopay/s
uccess
`
,
{
const
response
=
await
kakaopayApi
.
approveS
uccess
(
{
'
tid
'
:
tid
,
cid
:
'
TC0ONETIME
'
,
partner_order_id
:
'
butter_studio
'
,
...
...
@@ -81,10 +89,18 @@ const PaymentCompletePage = () => {
}
return
(
<
div
className
=
"
text-center
"
>
<
h3
>
예매가
정상적으로
완료되었습니다
.
<
/h3
>
<
button
>
홈으로
<
/button
>
{
user
.
role
===
"
member
"
?
<
button
>
마이페이지
<
/button> : <></
>
}
<
div
className
=
"
container text-center py-5
"
>
<
h3
className
=
"
my-3 text-white
"
>
예매가
정상적으로
완료되었습니다
.
<
/h3
>
{
user
.
role
===
"
member
"
?
<
a
href
=
"
/mypage
"
>
<
button
className
=
"
btn btn-warning mx-1
"
>
마이페이지
<
/button
>
<
/a
>
:
<
a
href
=
"
/
"
>
<
button
className
=
"
btn btn-warning mx-1
"
>
홈으로
<
/button
>
<
/a
>
}
<
/div
>
)
}
...
...
client/src/pages/PaymentFailPage.js
0 → 100644
View file @
6e0e826d
import
{
useEffect
,
useState
}
from
'
react
'
import
{
useAuth
}
from
'
../context/auth_context
'
import
catchErrors
from
'
../utils/catchErrors
'
import
reservationApi
from
'
../apis/reservation.api
'
const
PaymentCompletePage
=
()
=>
{
const
[
error
,
setError
]
=
useState
()
useEffect
(()
=>
{
deleteReservation
()
},
[])
async
function
deleteReservation
()
{
try
{
const
response
=
await
reservationApi
.
deleteReservation
()
localStorage
.
removeItem
(
'
tid
'
)
}
catch
(
error
)
{
catchErrors
(
error
,
setError
)
}
}
return
(
<
div
className
=
"
container text-center py-5
"
>
<
h3
className
=
"
my-3 text-white
"
>
결제에
실패하셨습니다
.
<
/h3
>
<
a
href
=
"
/ticket
"
>
<
button
className
=
"
btn btn-warning mx-1
"
>
다시
예매하기
<
/button
>
<
/a
>
<
a
href
=
"
/
"
>
<
button
className
=
"
btn btn-warning mx-1
"
>
홈으로
<
/button
>
<
/a
>
<
/div
>
)
}
export
default
PaymentCompletePage
\ No newline at end of file
client/src/pages/PaymentPage/PaymentPage.js
View file @
6e0e826d
import
axios
from
'
axios
'
import
{
useEffect
,
useState
}
from
'
react
'
import
authApi
from
'
../../apis/auth.api
'
import
kakaopayApi
from
'
../../apis/kakaopay.api
'
import
reservationApi
from
'
../../apis/reservation.api
'
import
{
useAuth
}
from
'
../../context/auth_context
'
import
catchErrors
from
'
../../utils/catchErrors
'
...
...
@@ -73,23 +74,25 @@ const Payment = ({ location }) => {
userType
:
"
member
"
,
user
:
userInfo
.
id
,
...
ticketInfo
,
timetable
:
1
timetable
Id
:
1
})
const
responsekakao
=
await
axios
.
post
(
'
/api/kakaopay/test/single
'
,
{
const
responsekakao
=
await
kakaopayApi
.
approveReq
(
{
cid
:
'
TC0ONETIME
'
,
partner_order_id
:
'
butter_studio
'
,
partner_user_id
:
'
000000
'
+
(
userInfo
.
id
||
guestInfo
.
id
)
,
partner_user_id
:
'
000000
'
+
guestID
,
item_name
:
ticketInfo
.
title
,
item_code
:
ticketInfo
.
movieId
,
quantity
:
ticketInfo
.
adult
+
ticketInfo
.
youth
+
ticketInfo
.
senior
,
total_amount
:
ticketInfo
.
totalFee
,
vat_amount
:
0
,
tax_free_amount
:
0
,
approval_url
:
'
http://localhost:3000/paymentcomplete
'
,
fail_url
:
'
http://localhost:3000/
ticket
'
,
cancel_url
:
'
http://localhost:3000/
ticket
'
,
fail_url
:
'
http://localhost:3000/
paymentfail
'
,
cancel_url
:
'
http://localhost:3000/
paymentfail
'
,
})
if
(
response
&&
responsekakao
)
{
window
.
location
.
href
=
responsekakao
.
data
.
redirect_url
localStorage
.
setItem
(
'
tid
'
,
responsekakao
.
tid
)
window
.
location
.
href
=
responsekakao
.
redirect_url
}
}
else
{
if
(
guestID
)
{
...
...
@@ -99,10 +102,10 @@ const Payment = ({ location }) => {
...
ticketInfo
,
timetableId
:
1
})
const
responsekakao
=
await
axios
.
post
(
'
/api/kakaopay/test/single
'
,
{
const
responsekakao
=
await
kakaopayApi
.
approveReq
(
{
cid
:
'
TC0ONETIME
'
,
partner_order_id
:
'
butter_studio
'
,
partner_user_id
:
'
000000
'
+
guestID
,
partner_user_id
:
'
000000
'
+
guestID
,
item_name
:
ticketInfo
.
title
,
item_code
:
ticketInfo
.
movieId
,
quantity
:
ticketInfo
.
adult
+
ticketInfo
.
youth
+
ticketInfo
.
senior
,
...
...
@@ -110,12 +113,12 @@ const Payment = ({ location }) => {
vat_amount
:
0
,
tax_free_amount
:
0
,
approval_url
:
'
http://localhost:3000/paymentcomplete
'
,
fail_url
:
'
http://localhost:3000/
ticket
'
,
cancel_url
:
'
http://localhost:3000/
ticket
'
,
fail_url
:
'
http://localhost:3000/
paymentfail
'
,
cancel_url
:
'
http://localhost:3000/
paymentfail
'
,
})
if
(
response
||
responsekakao
)
{
localStorage
.
setItem
(
'
tid
'
,
responsekakao
.
data
.
tid
)
window
.
location
.
href
=
responsekakao
.
data
.
redirect_url
if
(
response
&&
responsekakao
)
{
localStorage
.
setItem
(
'
tid
'
,
responsekakao
.
tid
)
window
.
location
.
href
=
responsekakao
.
redirect_url
}
}
else
{
alert
(
"
비회원 정보를 모두 입력 후 비회원 정보 저장 버튼을 눌러주세요.
"
)
...
...
client/src/pages/TheaterPage.js
View file @
6e0e826d
...
...
@@ -25,7 +25,7 @@ const TheaterPage = () => {
<
TheaterInfo
/>
<
/div
>
<
div
className
=
"
tab-pane fade
"
id
=
"
stillcut
"
role
=
"
tabpanel
"
aria
-
labelledby
=
"
stillcut-tab
"
>
<
div
>
상영시간표
<
/div
>
<
div
className
=
"
pb-5
"
>
상영시간표
<
/div
>
<
/div
>
<
div
className
=
"
tab-pane fade
"
id
=
"
review
"
role
=
"
tabpanel
"
aria
-
labelledby
=
"
review-tab
"
>
<
div
className
=
"
row justify-content-center
"
>
...
...
server/controllers/kakaopay.controller.js
View file @
6e0e826d
import
axios
from
'
axios
'
import
config
from
"
../config/app.config.js
"
;
const
success
=
async
(
req
,
res
)
=>
{
const
success
=
async
(
req
,
res
)
=>
{
try
{
// const { cid, tid, partner_order_id, partner_user_id, pg_token } = req.body
const
item
=
req
.
body
...
...
@@ -20,12 +20,10 @@ const success = async(req, res) => {
})
const
resp
=
response
.
data
console
.
log
(
'
resp
'
,
resp
)
res
.
json
({...
resp
})
res
.
json
({
...
resp
})
}
catch
(
error
)
{
console
.
log
(
error
)
}
}
const
fail
=
(
req
,
res
)
=>
{
...
...
@@ -34,10 +32,27 @@ const fail = (req, res) => {
})
}
const
cancel
=
(
req
,
res
)
=>
{
return
res
.
json
({
message
:
'
Canceled
'
})
const
cancel
=
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/cancel
'
,
bodyData
,
{
headers
:
{
'
Authorization
'
:
`KakaoAK
${
config
.
kakaoAdminKey
}
`
,
'
Content-Type
'
:
'
application/x-www-form-urlencoded;charset=UTF-8
'
,
},
})
const
resp
=
response
.
data
res
.
json
(
resp
)
}
catch
(
error
)
{
console
.
log
(
error
)
}
}
const
singleTest
=
async
(
req
,
res
)
=>
{
...
...
server/controllers/reservation.controller.js
View file @
6e0e826d
...
...
@@ -81,9 +81,46 @@ const saveReservation = async (req, res) => {
}
}
const
saveTid
=
async
(
req
,
res
)
=>
{
try
{
const
{
tid
}
=
req
.
body
const
token
=
req
.
cookies
.
butterStudio
;
const
{
id
,
role
}
=
jwt
.
verify
(
token
,
config
.
jwtSecret
);
await
Reservation
.
update
({
tid
:
tid
},
{
where
:
{
userType
:
role
,
user
:
id
}
})
res
.
json
({
message
:
'
Tid 저장 OK
'
})
}
catch
(
error
)
{
console
.
log
(
error
)
res
.
status
(
500
).
send
(
error
.
message
||
"
예매DB에 Tid 저장 실패
"
)
}
}
const
deleteReservation
=
async
(
req
,
res
)
=>
{
try
{
const
token
=
req
.
cookies
.
butterStudio
;
const
{
id
,
role
}
=
jwt
.
verify
(
token
,
config
.
jwtSecret
);
await
Reservation
.
destroy
({
where
:
{
userType
:
role
,
user
:
id
}
});
res
.
json
({
message
:
'
결제실패로 인한 예매DB삭제
'
})
}
catch
(
error
)
{
console
.
log
(
error
)
res
.
status
(
500
).
send
(
error
.
message
||
"
예매DB 삭제실패
"
)
}
}
export
default
{
findReservedSeats
,
findReservation
,
findOneReservation
,
saveReservation
saveReservation
,
saveTid
,
deleteReservation
}
\ No newline at end of file
server/index.js
View file @
6e0e826d
...
...
@@ -10,7 +10,7 @@ dotenv.config({
});
sequelize
.
sync
({
force
:
tru
e
})
.
sync
({
force
:
fals
e
})
.
then
(
async
()
=>
{
await
Promise
.
all
(
Object
.
keys
(
ROLE_NAME
).
map
((
name
)
=>
{
...
...
server/models/reservation.model.js
View file @
6e0e826d
...
...
@@ -11,9 +11,6 @@ const ReservationModel = (sequelize) => {
primaryKey
:
true
,
autoIncrement
:
true
,
},
// reservationNum: {
// type: DataTypes.INTEGER,
// },
movieId
:
{
type
:
DataTypes
.
INTEGER
,
},
...
...
server/routes/reservation.route.js
View file @
6e0e826d
...
...
@@ -15,4 +15,10 @@ router.route('/findonereservation')
router
.
route
(
'
/save
'
)
.
post
(
reservationCtrl
.
saveReservation
)
router
.
route
(
'
/savetid
'
)
.
post
(
reservationCtrl
.
saveTid
)
router
.
route
(
'
/delete
'
)
.
get
(
reservationCtrl
.
deleteReservation
)
export
default
router
;
\ No newline at end of file
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