1. Toss payments Paypal 연동
npm install @tosspayments/payment-sdk --save
import { loadTossPayments } from '@tosspayments/payment-sdk';
.
.
.
// PAY NOW 버튼 클릭 시 결제창으로 이동
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const orderId = nanoid();
loadTossPayments(clientKey).then((tossPayments) => {
tossPayments
.requestPayment('해외간편결제', {
// 결제 정보 파라미터
amount: totalPrice,
orderId,
customerName: name,
orderName: serviceId.toString(),
successUrl: `${window.location.origin}/successPayments`,
failUrl: `${window.location.origin}/failPayments`,
provider: 'PAYPAL',
currency: 'USD',
country: 'US',
})
.then(() => {
setResvStorage({
orderId,
serviceId,
headcount,
tourDate,
tourTime,
name,
email,
phone,
sns,
snsId,
detailRequest: request,
totalPrice,
paymentMethod: 'paypal',
});
})
.catch(function (error) {
// 결제 고객이 결제창을 닫았을 때 에러 처리
if (
error.code === 'USER_CANCEL' ||
error.code === 'PAY_PROCESS_CANCELED'
) {
alert('Payment has been canceled by the customer.');
console.log('error', error);
// 그 외의 경우 에러 처리
} else {
console.log('error:', error);
}
})
.finally(() => {
setPaymentRequested(false); // 결제 요청 상태 초기화
});
setPaymentRequested(true); // 결제 요청 상태 업데이트
});
};
successUrl: `${window.location.origin}/successPayments`
window.location.origin
결제 신청 금액과 URL로 받은 amount가 같은지 확인하기
useEffect(() => {
// 결제 금액과 successUrl로 받은 금액 일치하지 않으면 실패 페이지로 이동
if (amountNum !== resvStorage.totalPrice) {
router.push('/failPayments');
} else {
confirmPayments();
}
// eslint-disable-next-line
}, []);
// 토스 결제 승인 함수
const confirmPayments = async () => {
let options = {
method: 'POST',
url: 'https://api.tosspayments.com/v1/payments/confirm',
headers: {
Authorization:
'인코딩 된 인증 header 입력',
'Content-Type': 'application/json',
},
data: { paymentKey, amount, orderId },
};
axios
.request(options)
.then(function (response: any) {
console.log(response.data);
postReservation();
})
.catch(function (error: any) {
console.error(error);
router.push('/failPayments'); // 승인 실패 시 실패 페이지로 이동
});
};
Authorization
에는 toss에서 발급받은 secretKey
로 인증 헤더 값을 만들어 입력하기
echo -n '발급받은secretKey:' | base64
터미널에 명령어 입력 후 인코딩 된 값을 입력postReservation()
// 결제 승인 시 db에 결제 내용 post
const postReservation = async () => {
try {
const response = await axios.post('/api/reservation', {
serviceId: resvStorage.serviceId,
orderId: resvStorage.orderId,
headcount: resvStorage.headcount,
tourDate: resvStorage.tourDate,
tourTime: resvStorage.tourTime,
name: resvStorage.name,
email: resvStorage.email,
phone: resvStorage.phone,
sns: resvStorage.sns,
snsId: resvStorage.snsId,
detailRequest: resvStorage.detailRequest,
totalPrice: resvStorage.totalPrice,
paymentMethod: resvStorage.paymentMethod,
});
console.log('DB post 완료 => ', response);
// 결제 승인 및 DB 추가 완료했을 시 spinner 사라짐
setIsApproved(true);
resetScheduleTime(); // 시간 선택 초기화
resetHeadcount(); // headcount 초기화
resetSns(); // sns 초기화
resetSnsId(); // snsId 초기화
resetRequest(); // request 초기화
resetSessionStorage(); // sessionStorage 초기화
} catch (error) {
console.error(error);
}
};
failUrl: `${window.location.origin}/failPayments`
const FailPayments = () => {
.
.
.
const searchParams = useSearchParams();
const errorCode = searchParams.get('code');
const errorMessage: { [key: string]: string } = {
PAY_PROCESS_CANCELED: 'Payment has been canceled by the customer.',
PAY_PROCESS_ABORTED: 'Payment has been canceled or has not been processed.',
REJECT_CARD_COMPANY: 'Payment was rejected.',
COMMON_ERROR: 'An unexpected error has occurred.',
};
.
.
.
return (
<h1>
{errorCode
? errorMessage[errorCode]
: 'The payment was not successful.'}
</h1>
);
};
Agreements
컴포넌트 생성import Link from 'next/link';
const Agreements = () => {
const termsList = [
{
title:
'General Terms and Conditions for Electronic Financial Transactions.',
href: 'https://pages.tosspayments.com/terms/en/paypal/general_terms_and_conditions',
},
{
title: 'Consent to Collection and Use of Personal Information.',
href: 'https://pages.tosspayments.com/terms/en/paypal/collection_use_consent',
},
{
title:
'Consent to Providing Personal Information and Transmitting Personal Information Overseas.',
href: 'https://pages.tosspayments.com/terms/en/paypal/providing_transmitting_consent',
},
];
return (
<div className="flex flex-col items-center text-[1.4rem] pb-[3rem]">
{termsList.map((term, i) => (
<div className="flex max-md:flex-col" key={i}>
<div className="pr-[1.5rem] max-md:pr-0">{term.title}</div>
<Link
legacyBehavior // Link 태그 안에 a 태그를 사용하기 위해 추가
href={term.href}
>
<a
target="_blank"
className="underline max-md:text-right max-md:mb-[1rem] max-md:mt-[-0.7rem]"
>
View More
</a>
</Link>
</div>
))}
{/* Agreements checkbox */}
<div className="flex justify-center gap-5 pt-[1.5rem]">
<input
required
type="checkbox"
id="termsCheckbox"
className="checkboxColor"
/>
<label
htmlFor="termsCheckbox"
className="text-[1.8rem] font-semibold max-md:text-[1.5rem]"
>
I agree to the terms and conditions.
</label>
</div>
</div>
);
};
export default Agreements;
완성
반응형