728x90
반응형
빌링키 발급에 성공했을 경우 아임포트가 보안상의 이유로 빌링키에 직접 접근할 수 없기 때문에 customer_uid를 이용해
( https://api.iamport.kr/subscribe/payments/again ) REST API 를 호출해 빌링키로 결제를 요청하도록 한다.
1. 빌링키 발급이 성공했을 경우에 axios로 백엔드에 직접 만든 라우터로 경로를 설정해준다.
(구독 신청이 성공할 경우 로그아웃해서 쿠키 정보를 갱신해준다.)
참고로 빌링키와 결제요청은 merchant_uid를 다르게 해야함
const subscribeItemClickHandler = (e: any) => {
var IMP = window.IMP;
IMP.init(process.env.NEXT_PUBLIC_IMP_CODE); // iamport 가맹점 식별코드
IMP.request_pay({
pg: 'kcp_billing',
pay_method: 'card', // 'card'만 지원됩니다.
merchant_uid: "order_monthly_0001", // 상점에서 관리하는 주문 번호 (날짜를 붙이면 중복되지않아 좋습니다.)
name: '최초인증결제',
amount: 500, // 결제창에 표시될 금액. 실제 승인이 이뤄지지는 않습니다. (PC에서는 가격이 표시되지 않음)
customer_uid: 'your-customer-unique-id', // 필수 입력.
buyer_email: 'iamport@siot.do',
buyer_name: '아임포트',
buyer_tel: '02-1234-1234',
m_redirect_url: '{모바일에서 결제 완료 후 리디렉션 될 URL}' // 예: https://www.my-service.com/payments/complete/mobile
}, function (rsp: any) {
if (rsp.success) {
axios.post('/api/subscribe/payments',{
muser_id: loginData.userId, // 로그인 아이디
radioItem: radioItem, // 구독 개월 수 라디오 버튼
merchant_uid: "위에 적은 merchant_uid",
customer_uid : "위에 적은 customer_uid",
name: "위에 적은 name",
amount: "위에 적은 amount"
}).then(({ data }) => {
if (data.success) {
// 성공할 경우
axios.get('/api/auth/logout')
.then(({ data }) => {
if (data.success) {
alert('구독신청이 완료되었습니다. 다시 로그인해주세요.')
router.push('/');
}
})
}
else {
// 실패할 경우
alert('내용을 다시확인해주세요.')
}
})
} else {
alert('내용을 다시확인해주세요.')
console.log(rsp.error_msg);
}
});
}
2. 백엔드에 클라이언트가 요청할 라우터를 만들어준다. 인증 토큰을 받고 결제 요청을 해야한다.
router.post("/payments", async function (req, res, next) {
const body = req.body;
console.log("body : ", body)
try {
// 인증 토큰 발급 받기
const getToken = await axios({
url: "https://api.iamport.kr/users/getToken",
method: "post", // POST method
headers: { "Content-Type": "application/json" }, // "Content-Type": "application/json"
data: {
imp_key: process.env.IMP_API_KEY, // REST API 키
imp_secret: process.env.IMP_API_SECRET_KEY // REST API Secret
}
});
const { access_token } = getToken.data.response; // 인증 토큰
// 결제(재결제) 요청
const paymentResult = await axios({
url: 'https://api.iamport.kr/subscribe/payments/again',
method: "post",
headers: { "Authorization": access_token }, // 인증 토큰을 Authorization header에 추가
data: {
customer_uid: body.customer_uid,
merchant_uid: body.merchant_uid, // 새로 생성한 결제(재결제)용 주문 번호
amount: body.amount,
name: body.name
}
});
const { code, message } = paymentResult.data;
if (code === 0) { // 카드사 통신에 성공(실제 승인 성공 여부는 추가 판단이 필요함)
if (paymentResult.data.response.status === "paid") { //카드 정상 승인
res.send({ success: true });
} else { //카드 승인 실패 (예: 고객 카드 한도초과, 거래정지카드, 잔액부족 등)
//paymentResult.status : failed 로 수신됨
res.send({ success: false });
}
} else { // 카드사 요청에 실패 (paymentResult is null)
res.send({ success: false });
}
}
catch (Err) {
console.log("err : ", Err)
res.send({ success: false })
}
});
3. 구독에 대한 DB를 사용하는 서비스에 따라 설계하고 결제 요청 성공 시에 추가해주도록 한다.
( 저는 구독 남은 개월 수를 표시하고 나중에 아임포트 웹훅으로 카운팅 해주도록 설계했습니다. )
( 또한 쿠키를 삭제하고 로그인 유저의 구독에 관한 데이터를 변경하여 로그아웃 시킨 다음 로그인 했을 시에 서비스를 이용 가능하게 했습니다. )
if (code === 0) { // 카드사 통신에 성공(실제 승인 성공 여부는 추가 판단이 필요함)
if (paymentResult.data.response.status === "paid") { //카드 정상 승인
Subscribe.create({
subscribe_muser_id: body.muser_id,
subscribe_type: body.radioItem + "개월 구독",
subscribe_customer_uid: body.customer_uid,
subscribe_merchant_uid: body.merchant_uid,
subscribe_count: body.radioItem,
subscribe_amount: body.amount,
subscribe_createdAt: new Date(),
subscribe_updatedAt: new Date()
})
// 사옹자의 구독에 관한 데이터를 가진 컬럼을 수정해준다. (로그아웃하고 로그인하면 쿠키에 등록되어 서비스 이용 가능)
MUserInfo.update({
muser_subscribe_type: body.name
}, {
where: {
muser_id: body.muser_id
}
})
res.clearCookie('사용했던 쿠키');
res.send({ success: true });
} else { //카드 승인 실패 (예: 고객 카드 한도초과, 거래정지카드, 잔액부족 등)
//paymentResult.status : failed 로 수신됨
res.send({ success: false });
}
} else { // 카드사 요청에 실패 (paymentResult is null)
res.send({ success: false });
}
혹시나 금액을 500 이하로 설정했을 경우 '[8105] 포맷에러(지불|신용카드|금액)' 이 에러구문을 볼 수 있다. 금액을 500원 이상으로 설정해주자.
728x90
반응형
'Front-End > Next.js' 카테고리의 다른 글
Next.js | 아임포트 정기 결제(4) ( with TypeScript ) | 구독 취소하기 (0) | 2022.05.18 |
---|---|
Next.js | 아임포트 정기 결제(3) ( with TypeScript ) | 아임포트 웹훅 사용하기 (0) | 2022.05.17 |
Next.js | 아임포트 정기 결제(1) ( with TypeScript ) | 클라이언트에서 빌링키 받기 (0) | 2022.05.16 |
Next.js | 사용자 접속 IP 확인하기 (0) | 2022.03.11 |
Next.js | 세션(express-session)과 토큰(jwt)을 사용한 중복 로그인 방지 ( 기존 사용자 로그아웃 여부 확인) (0) | 2022.03.07 |