이 페이지에서는 주문을 처리하는 통합의 기능을 테스트하고 측정하며 오류 상태를 해결하는 데 도움이 되는 도구를 제공합니다.
Google Pay 결제 게이트웨이 테스트
JSFiddle을 사용하여 샌드박스 환경에서 Google Pay 결제 게이트웨이를 통해 테스트 결제를 진행합니다.
<html> <head> <style>body { background-color: #a3d5d3;}.googlepay { background-color: #000; background-image: url('data:image/svg+xml,%3Csvg%20width%3D%2241%22%20height%3D%2217%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M19.526%202.635v4.083h2.518c.6%200%201.096-.202%201.488-.605.403-.402.605-.882.605-1.437%200-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0%205.52v4.736h-1.504V1.198h3.99c1.013%200%201.873.337%202.582%201.012.72.675%201.08%201.497%201.08%202.466%200%20.991-.36%201.819-1.08%202.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668%202.287c0%20.392.166.718.499.98.332.26.722.391%201.168.391.633%200%201.196-.234%201.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61%200-1.12.148-1.528.442-.409.294-.613.657-.613%201.093m1.946-5.815c1.112%200%201.989.297%202.633.89.642.594.964%201.408.964%202.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45%201.372-2.486%201.372-.882%200-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96%200-.828.313-1.486.94-1.976s1.463-.735%202.51-.735c.892%200%201.629.163%202.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132%202.132%200%200%200-1.455-.547c-.84%200-1.504.353-1.995%201.062l-1.324-.834c.73-1.045%201.81-1.568%203.238-1.568m11.853.262l-5.02%2011.53H34.42l1.864-4.034-3.302-7.496h1.635l2.387%205.749h.032l2.322-5.75z%22%20fill%3D%22%23FFF%22%2F%3E%3Cpath%20d%3D%22M13.448%207.134c0-.473-.04-.93-.116-1.366H6.988v2.588h3.634a3.11%203.11%200%200%201-1.344%202.042v1.68h2.169c1.27-1.17%202.001-2.9%202.001-4.944%22%20fill%3D%22%234285F4%22%2F%3E%3Cpath%20d%3D%22M6.988%2013.7c1.816%200%203.344-.595%204.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754%200-3.244-1.182-3.776-2.774H.978v1.731a6.728%206.728%200%200%200%206.01%203.703%22%20fill%3D%22%2334A853%22%2F%3E%3Cpath%20d%3D%22M3.212%208.267a4.034%204.034%200%200%201%200-2.572V3.964H.978A6.678%206.678%200%200%200%20.261%206.98c0%201.085.26%202.11.717%203.017l2.234-1.731z%22%20fill%3D%22%23FABB05%22%2F%3E%3Cpath%20d%3D%22M6.988%202.921c.992%200%201.88.34%202.58%201.008v.001l1.92-1.918C10.324.928%208.804.262%206.989.262a6.728%206.728%200%200%200-6.01%203.702l2.234%201.731c.532-1.592%202.022-2.774%203.776-2.774%22%20fill%3D%22%23E94235%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E'); background-origin: content-box; background-position: center; background-repeat: no-repeat; background-size: contain; border: 0; border-radius: 4px; box-shadow: 0 1px 1px 0 rgba(60, 64, 67, 0.30), 0 1px 3px 1px rgba(60, 64, 67, 0.15); outline: 0; padding: 11px 24px; width: 160px; min-width: 90px; height: 40px; min-height: 40px;}.googlepay.long { background-image: url('data:image/svg+xml,%3Csvg%20width%3D%22103%22%20height%3D%2217%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M.148%202.976h3.766c.532%200%201.024.117%201.477.35.453.233.814.555%201.085.966.27.41.406.863.406%201.358%200%20.495-.124.924-.371%201.288s-.572.64-.973.826v.084c.504.177.912.471%201.225.882.313.41.469.891.469%201.442a2.6%202.6%200%200%201-.427%201.47c-.285.43-.667.763-1.148%201.001A3.5%203.5%200%200%201%204.082%2013H.148V2.976zm3.696%204.2c.448%200%20.81-.14%201.085-.42.275-.28.413-.602.413-.966s-.133-.684-.399-.959c-.266-.275-.614-.413-1.043-.413H1.716v2.758h2.128zm.238%204.368c.476%200%20.856-.15%201.141-.448.285-.299.427-.644.427-1.036%200-.401-.147-.749-.441-1.043-.294-.294-.688-.441-1.183-.441h-2.31v2.968h2.366zm5.379.903c-.453-.518-.679-1.239-.679-2.163V5.86h1.54v4.214c0%20.579.138%201.013.413%201.302.275.29.637.434%201.085.434.364%200%20.686-.096.966-.287.28-.191.495-.446.644-.763a2.37%202.37%200%200%200%20.224-1.022V5.86h1.54V13h-1.456v-.924h-.084c-.196.336-.5.611-.91.826-.41.215-.845.322-1.302.322-.868%200-1.528-.259-1.981-.777zm9.859.161L16.352%205.86h1.722l2.016%204.858h.056l1.96-4.858H23.8l-4.41%2010.164h-1.624l1.554-3.416zm8.266-6.748h1.666l1.442%205.11h.056l1.61-5.11h1.582l1.596%205.11h.056l1.442-5.11h1.638L36.392%2013h-1.624L33.13%207.876h-.042L31.464%2013h-1.596l-2.282-7.14zm12.379-1.337a1%201%200%200%201-.301-.735%201%201%200%200%201%20.301-.735%201%201%200%200%201%20.735-.301%201%201%200%200%201%20.735.301%201%201%200%200%201%20.301.735%201%201%200%200%201-.301.735%201%201%200%200%201-.735.301%201%201%200%200%201-.735-.301zM39.93%205.86h1.54V13h-1.54V5.86zm5.568%207.098a1.967%201.967%200%200%201-.686-.406c-.401-.401-.602-.947-.602-1.638V7.218h-1.246V5.86h1.246V3.844h1.54V5.86h1.736v1.358H45.75v3.36c0%20.383.075.653.224.812.14.187.383.28.728.28.159%200%20.299-.021.42-.063.121-.042.252-.11.392-.203v1.498c-.308.14-.681.21-1.12.21-.317%200-.616-.051-.896-.154zm3.678-9.982h1.54v2.73l-.07%201.092h.07c.205-.336.511-.614.917-.833.406-.22.842-.329%201.309-.329.868%200%201.53.254%201.988.763.457.509.686%201.202.686%202.079V13h-1.54V8.688c0-.541-.142-.947-.427-1.218-.285-.27-.656-.406-1.113-.406-.345%200-.656.098-.931.294a2.042%202.042%200%200%200-.651.777%202.297%202.297%200%200%200-.238%201.029V13h-1.54V2.976zm32.35-.341v4.083h2.518c.6%200%201.096-.202%201.488-.605.403-.402.605-.882.605-1.437%200-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0%205.52v4.736h-1.504V1.198h3.99c1.013%200%201.873.337%202.582%201.012.72.675%201.08%201.497%201.08%202.466%200%20.991-.36%201.819-1.08%202.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668%202.287c0%20.392.166.718.499.98.332.26.722.391%201.168.391.633%200%201.196-.234%201.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61%200-1.12.148-1.528.442-.409.294-.613.657-.613%201.093m1.946-5.815c1.112%200%201.989.297%202.633.89.642.594.964%201.408.964%202.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45%201.372-2.486%201.372-.882%200-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96%200-.828.313-1.486.94-1.976s1.463-.735%202.51-.735c.892%200%201.629.163%202.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132%202.132%200%200%200-1.455-.547c-.84%200-1.504.353-1.995%201.062l-1.324-.834c.73-1.045%201.81-1.568%203.238-1.568m11.853.262l-5.02%2011.53H96.42l1.864-4.034-3.302-7.496h1.635l2.387%205.749h.032l2.322-5.75z%22%20fill%3D%22%23FFF%22%2F%3E%3Cpath%20d%3D%22M75.448%207.134c0-.473-.04-.93-.116-1.366h-6.344v2.588h3.634a3.11%203.11%200%200%201-1.344%202.042v1.68h2.169c1.27-1.17%202.001-2.9%202.001-4.944%22%20fill%3D%22%234285F4%22%2F%3E%3Cpath%20d%3D%22M68.988%2013.7c1.816%200%203.344-.595%204.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754%200-3.244-1.182-3.776-2.774h-2.234v1.731a6.728%206.728%200%200%200%206.01%203.703%22%20fill%3D%22%2334A853%22%2F%3E%3Cpath%20d%3D%22M65.212%208.267a4.034%204.034%200%200%201%200-2.572V3.964h-2.234a6.678%206.678%200%200%200-.717%203.017c0%201.085.26%202.11.717%203.017l2.234-1.731z%22%20fill%3D%22%23FABB05%22%2F%3E%3Cpath%20d%3D%22M68.988%202.921c.992%200%201.88.34%202.58%201.008v.001l1.92-1.918c-1.165-1.084-2.685-1.75-4.5-1.75a6.728%206.728%200%200%200-6.01%203.702l2.234%201.731c.532-1.592%202.022-2.774%203.776-2.774%22%20fill%3D%22%23E94235%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E'); width: 240px; min-width: 151px;}.googlepay:hover { background-color: #3c4043;}.googlepay:focus { box-shadow: #202124;}.googlepay:active { background-color: #5f6368;}// extra padding for testingsection { padding: 1em 0;}div { margin: 0.5em 0;}button { margin-top: 0.5em; margin-right: 0.5em;}table,th,td { border: 1px solid black; font-family: Arial, Helvetica, sans-serif;}pre { white-space: pre-wrap; /* Since CSS 2.1 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ font-family: Arial, Helvetica, sans-serif;}
</style> </head> <body><section> <div> <button class="googlepay long" title="Buy with Google Pay" onclick="onGooglePaymentButtonClicked()"></button> </div> </section> <div> <table style="width:100%"> <tr> <th>Payment Gateway Response</th> </tr> <tr> <td> <pre id="gatewayResponse"></pre> </td> </tr> </table> </div>
<script>/** * Identify your gateway and your site's gateway merchant identifier * * The Google Pay API response will return an encrypted payment method capable * of being charged by a supported gateway after payer authorization * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#gateway|PaymentMethodTokenizationSpecification} */ const tokenizationSpecification = { type: 'PAYMENT_GATEWAY', parameters: { "gateway": "example", "gatewayMerchantId": "exampleGatewayMerchantId", } }; /** * Card networks supported by your site and your gateway * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters} */ const allowedCardNetworks = ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"]; /** * Define the version of the Google Pay API referenced when creating your * configuration * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|apiVersion in PaymentDataRequest} */ const baseRequest = { apiVersion: 2, apiVersionMinor: 0 }; /** * Card authentication methods supported by your site and your gateway * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters} */ const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"]; /** * Describe your site's support for the CARD payment method and its required * fields * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters} */ const baseCardPaymentMethod = { type: 'CARD', parameters: { allowedAuthMethods: allowedCardAuthMethods, allowedCardNetworks: allowedCardNetworks } }; /** * Describe your site's support for the CARD payment method including optional * fields * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters} */ const cardPaymentMethod = Object.assign({}, baseCardPaymentMethod, { tokenizationSpecification: tokenizationSpecification } ); function displayResult(result) { document.getElementById("gatewayResponse").innerHTML = JSON.stringify(JSON.parse(result.paymentMethodData.tokenizationData.token), null, 2); } /** * An initialized google.payments.api.PaymentsClient object or null if not yet set * * @see {@link getGooglePaymentsClient} */ let paymentsClient = null; /** * Configure your site's support for payment methods supported by the Google Pay * API. * * Each member of allowedPaymentMethods should contain only the required fields, * allowing reuse of this base request when determining a viewer's ability * to pay and later requesting a supported payment method * * @return {object} Google Pay API version, payment methods supported by the site */ function getGoogleIsReadyToPayRequest() { return Object.assign({}, baseRequest, { allowedPaymentMethods: [baseCardPaymentMethod] } ); } /** * Configure support for the Google Pay API * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|PaymentDataRequest} * @return {object} PaymentDataRequest fields */ function getGooglePaymentDataRequest() { const paymentDataRequest = Object.assign({}, baseRequest); paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod]; paymentDataRequest.transactionInfo = getGoogleTransactionInfo(); paymentDataRequest.merchantInfo = { // See {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist|Integration checklist} // merchantId: '01234567890123456789', merchantName: 'Example Merchant' }; return paymentDataRequest; } /** * Return an active PaymentsClient or initialize * * @see {@link https://developers.google.com/pay/api/web/reference/client#PaymentsClient|PaymentsClient constructor} * @return {google.payments.api.PaymentsClient} Google Pay API client */ function getGooglePaymentsClient() { if (paymentsClient === null) { paymentsClient = new google.payments.api.PaymentsClient({ environment: 'TEST' }); } return paymentsClient; } /** * Initialize Google PaymentsClient after Google-hosted JavaScript has loaded * * Display a Google Pay payment button after confirmation of the viewer's * ability to pay. */ function onGooglePayLoaded() { const paymentsClient = getGooglePaymentsClient(); paymentsClient.isReadyToPay(getGoogleIsReadyToPayRequest()) .then(function (response) { if (response.result) { // prefetchGooglePaymentData(); } }) .catch(function (err) { // show error in developer console for debugging console.error(err); }); } /** * Provide Google Pay API with a payment amount, currency, and amount status * * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo|TransactionInfo} * @return {object} transaction info, suitable for use as transactionInfo property of PaymentDataRequest */ function getGoogleTransactionInfo() { return { countryCode: 'US', currencyCode: 'USD', totalPriceStatus: 'FINAL', // set to cart total totalPrice: '1.00' }; } /** * Prefetch payment data to improve performance * * @see {@link https://developers.google.com/pay/api/web/reference/client#prefetchPaymentData|prefetchPaymentData()} */ function prefetchGooglePaymentData() { const paymentDataRequest = getGooglePaymentDataRequest(); // transactionInfo must be set but does not affect cache paymentDataRequest.transactionInfo = { totalPriceStatus: 'NOT_CURRENTLY_KNOWN', currencyCode: 'USD' }; const paymentsClient = getGooglePaymentsClient(); paymentsClient.prefetchPaymentData(paymentDataRequest); } /** * Show Google Pay payment sheet when Google Pay payment button is clicked */ function onGooglePaymentButtonClicked() { // Alert if sample is using example values if (tokenizationSpecification.parameters["gateway"].startsWith('example')) { alert('In the JavaScript box, replace the tokenizationSpecification parameters with your gateway\'s sandbox parameters.'); return; } const paymentDataRequest = getGooglePaymentDataRequest(); paymentDataRequest.transactionInfo = getGoogleTransactionInfo(); const paymentsClient = getGooglePaymentsClient(); paymentsClient.loadPaymentData(paymentDataRequest) .then(function (paymentData) { // handle the response processPayment(paymentData); displayResult(paymentData); }) .catch(function (err) { // show error in developer console for debugging console.error(err); }); } /** * Process payment data returned by the Google Pay API * * @param {object} paymentData response from Google Pay API after user approves payment * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData|PaymentData object reference} */ function processPayment(paymentData) { // show returned data in developer console for debugging console.log(paymentData); paymentToken = paymentData.paymentMethodData.tokenizationData.token; }
</script><script async src="https://payments.google.com/gp/p/js/pay.js"></script>
결제 매개변수를 테스트하려면 다음 단계를 따르세요.
- JSFiddle에서 열기 (< >) 버튼을 클릭하여 JSFiddle에서 위의 샘플 코드를 엽니다.
- JavaScript + No-Library 창을 찾습니다.
-
tokenizationSpecification
(9번 줄에서 시작)에서parameters
을 자체 값으로 바꿉니다. 결제 게이트웨이 매개변수에 관한 자세한 내용은 Google Pay API 게이트웨이 문서를 참고하세요. - JSFiddle 페이지의 기본 탐색 메뉴에서 Run을 클릭합니다.
- GPay로 구매 버튼을 클릭합니다.
- Google 계정 및 결제 수단을 선택합니다.
- 계속을 클릭하여 결제를 완료합니다.
테스트 결제가 성공하면 결제 게이트웨이 응답 섹션에 결제 토큰과 일반 결제 세부정보가 포함된 메시지가 표시됩니다.
통합 테스트 사례
각 테스트 사례에서 콘솔은 데이터 피드를 읽어 장바구니 유효성 검사, 주문 생성, 오류 처리 구현을 확인하는 엔드포인트의 Checkout
및 SubmitOrder
요청을 생성합니다.
통합 테스트는 Checkout
에 대해 다음 테스트 시나리오를 실행합니다.
- 사용 가능한 장바구니 - 옵션이 없는 상품: 테스트에서 간단한 메뉴 항목이 포함된 사용 가능한 장바구니를 확인합니다.
- 사용 가능한 장바구니 - 옵션이 있는 상품: 테스트에서 복잡한 메뉴 항목 맞춤설정이 적용된 사용 가능한 장바구니를 확인합니다.
- 배송지 주소가 범위를 벗어남: 서비스 지역 외부의 배송지 주소가 있는 장바구니를 테스트에서 결제하려고 시도합니다.
- 최소 주문 금액 미충족: 최소 주문 금액 미만인 장바구니를 결제하려고 시도합니다.
- 식당 폐쇄: 식당이 문을 닫은 상태에서 장바구니를 결제하려고 시도합니다.
- 구매할 수 없는 상품: 테스트에서 점심 특선과 같이 구매할 수 없는 상품이 포함된 장바구니를 결제하려고 시도합니다.
- 구매할 수 없는 상품 - 최소 주문 금액 미충족: 테스트에서 점심 특식과 같이 구매할 수 없는 상품이 포함된 장바구니를 결제하려고 시도하지만 장바구니에 있는 다른 유효한 상품이 최소 주문 금액을 충족하지 않습니다.
- 오래된 상품 가격: 인위적으로 수정된 상품 가격이 포함된 장바구니를 결제하려고 시도합니다.
- 오래된 상품 가격 - 최소 주문 금액 미충족: 테스트에서 인위적으로 수정된 상품 가격으로 장바구니를 결제하려고 시도하지만 장바구니의 실제 금액이 최소 주문 금액을 충족하지 않습니다.
- 오래된 옵션 가격: 인위적으로 수정된 옵션 가격으로 장바구니를 결제하려고 시도합니다.
- 사용하지 않는 옵션 가격 - 최소 주문 금액 미충족: 테스트에서 인위적으로 수정된 옵션 가격으로 장바구니를 결제하려고 시도하지만 장바구니의 실제 금액이 최소 주문 금액을 충족하지 않습니다.
- 결제 시 잘못된 프로모션 코드 전송: 테스트에서 잘못된 프로모션 코드로 결제하려고 시도합니다.
통합 테스트는 SubmitOrder
에 대해 다음 테스트 시나리오를 실행합니다.
- 요건을 충족하는 장바구니: 테스트에서 요건을 충족하는 장바구니가 포함된 주문을 제출합니다.
- 결제 거부됨: 테스트에서 유효하지 않은 결제 토큰으로 주문을 제출하려고 시도합니다.
- 자격 요건을 충족하지 않는 사용자: 테스트에서 불완전한 사용자 정보로 주문을 제출하려고 시도합니다.
Chrome DevTools 콘솔
주문 엔드 투 엔드 UI를 테스트할 때 Chrome DevTools Console에서 결제 및 SubmitOrder 요청 로그를 볼 수 있습니다. 로그에서 처리 엔드포인트의 요청 및 응답, 명령어 (예: 재시도 명령어)와 같은 데이터를 검사할 수 있습니다.