1. 아임포트 스크립트 추가
2. 결제모듈 생성
//결제모듈
const IMP = window.IMP;
IMP.init('imp~가맹점식별코드'); /* imp~ : 가맹점 식별코드*/
//일반결제
const payKg = () => {
console.log('일반 결제 시작');
// IMP 객체를 사용하여 결제를 요청
IMP.request_pay(
{
pg: 'html5_inicis',
pay_method: 'card',
merchant_uid: new Date().getTime(), //임의 번호 부여
name: 'ArtiQ 포인트 충전 / ' + point + 'p',
amount: 100, //100원으로 고정 진행(선택한 값 받아와도 됨, 테스트라서 100으로 진행)
buyer_email: userEmail,
buyer_name: userName,
},
function (rsp) {
// 결제 성공 시
if (rsp.success) {
console.log('결제 성공, 백앤드 검증 시작');
console.log('rsp.imp_uid' + rsp.imp_uid);
const merchant_uid = rsp.imp_uid; //주문번호
const imp_uid = rsp.imp_uid; //고유번호
//백엔드 검증
pointCheck(imp_uid, merchant_uid);
//DB 저장
pointSubmit(rsp.imp_uid);
alert('포인트 충전 성공');
} else {
// 결제 실패 시
const msg = '결제에 실패하였습니다.';
msg += '에러내용 : ' + rsp.error_msg;
alert(msg);
}
}
);
};
//백엔드 검증 함수
const pointCheck = async (imp_uid, merchant_uid) => {
try {
console.log('백엔드 검증 실행');
const response = await axios.post('http://localhost:4000/verify/' + imp_uid);
console.log('결제 검증 완료', response.data);
//db에 저장
pointSubmit(merchant_uid);
} catch (error) {
console.error('결제 검증 실패', error);
}
};
//결제 정보 전달
const pointSubmit = async (merchant_uid) => {
try {
console.log('넘어가는 결제 번호:' + merchant_uid);
const response = await axios.post('http://localhost:4000/user/myPage/point/pay', {
pointCertify: merchant_uid.toString(),
userEmail: userEmail,
pointCharge: point,
pointPay: money,
});
// 받은 데이터
console.log(response.data);
} catch (error) {
console.error('결제 테이블 저장 실패', error);
}
};
3. 백엔드 결제 검증 서비스
iamport.api.key
와 iamport.api.secret
지정 필요@Controller
public class PaymentController {
// 결제 검증 서비스
private final IamportClient iamportClient;
public PaymentController(@Value("${iamport.api.key}") String apiKey,
@Value("${iamport.api.secret}") String apiSecret) {
this.iamportClient = new IamportClient(apiKey, apiSecret);
}
@ResponseBody
@RequestMapping("/verify/{imp_uid}")
public IamportResponse<Payment> paymentByImpUid(@PathVariable("imp_uid") String imp_uid)
throws IamportResponseException, IOException {
// 데이터와 처음 금액이 일치 확인 이후 결제 성공 실패 여부 리턴
System.out.println("결제 검증 서비스 실행");
return iamportClient.paymentByImpUid(imp_uid);
}
}
0.요청을 위해 프록시 설정(CORS 에러 방지)
1. 아이디, 시크릿 env에 추가
2. 결제 취소 함수
//결제 취소 함수
//pointCertify = imp_uid
const onPayCancel = async (pointCertify) => {
const confirm = window.confirm('결제번호:' + pointCertify + ' / 결제를 취소하시겠습니까?');
const impKey = process.env.REACT_APP_IMP_KEY;
const impSecret = process.env.REACT_APP_IMP_SECRET;
if (confirm) {
try {
//access_token 받아옴
const response = await axios({
url: '/users/getToken',
method: 'post',
headers: { 'Content-Type': 'application/json' },
data: {
imp_key: impKey,
imp_secret: impSecret,
},
});
const { access_token } = response.data.response;
console.log('받아온 access_token:', access_token);
//취소요청
getCancelData(access_token, pointCertify);
} catch (error) {
console.error('토큰 추출 에러 발생:', error);
}
}
};
//취소 요청
const getCancelData = async (access_token, pointCertify) => {
try {
const response = await axios.post(
'/payments/cancel',
{
imp_uid: pointCertify, // 주문번호 (필수)
},
{
headers: {
'Content-Type': 'application/json',
Authorization: access_token, // 엑세스 토큰 (필수)
},
}
);
console.log('결제 취소 완료' + response.data);
//DB 삭제 요청
pointTableCancel(pointCertify);
} catch (error) {
console.error('결제 취소 에러 발생:', error);
}
};
//DB 삭제
const pointTableCancel = async (pointCertify) => {
try {
console.log('넘어가는 결제 번호:' + pointCertify);
const response = await axios.post(
'http://localhost:4000/admin/userPointTable/cancel',
{
pointCertify: pointCertify,
},
{ headers: { Authorization: `Bearer ${jwt}` } }
);
// 받은 데이터
console.log(response.data);
alert('결제 취소 완료');
fetchUserPoint(); //정보 리로드
} catch (error) {
console.error('결제 테이블 삭제 실패', error);
}
};
api 문서를 보면서 하나씩 해보는 재미가 있음 ㅋㅋㅋ
다음엔 결제 취소 부분에도 검증 거쳐서 안전하게 결제 진행 예정!
그리고 리액트 js코드가 넘 더러워서 한 번 정리가 필요할 듯...
참고문서
https://portone.gitbook.io/docs/api/rest-api-access-token
https://portone.gitbook.io/docs/auth/guide-2
https://portone.gitbook.io/docs/api/api-1/api