본문 바로가기
IT 초보코딩의 세계/Go 언어

Go 언어 Front End 제작해보기(모달 윈도) 2장

by 조이럭키7 2023. 5. 10.
반응형

상품 주문 모달 윈도

모달을 위한 패키지 설치: npm install -–save reactstrap

상품 주문 모달 윈도modalwindow.js 파일을 src 디렉토리에 생성하고 작성

export function BuyModalWindow(props) {
    return (
        <Modal id="buy" tabIndex="-1" role="dialog" isOpen={props.showModal} toggle={props.toggle}>
        <div role="document">
                <ModalHeader toggle={props.toggle} className="bg-success text-white">
                    Buy Item
                </ModalHeader>
                <ModalBody>
                    <CreditCardInformation user={props.user} seperator={false} show={true} productid={props.productid} price={props.price} operation="Charge" toggle={props.toggle} />
                </ModalBody>
            </div>
        </Modal>
    );
}

신용카드 결제 처리

    ▶ 신용카드 정보 입력 폼 구현은 간단해 보일 수 있지만 텍스트 입력 창이 전부가 아니며 실제 운영 중인 서비스라면 신용카드 유효성을 검사하고 입력받은 정보를 안전하게 처리해야 하는데 신용카드 정보는 매우 민감한 정보이기 때문에 일반 데이터처럼 취급할 수 없음

    ▶ 프론트 엔드에서 사용할 수 있는 다양한 신용카드 결제 서비스가 있는데 그 중 가장 많이 쓰이는 스트라이프 (https://stripe.com/) 사용

    ▶ 다른 유사한 서비스와 마찬가지로 웹 사이트에 접속해서 스트라이프 계정을 생성하고 API 키를 발급 받아야 하며 이 단계에서 결제액을 입금받을 은행 계좌도 입력해야 함

    ▶ 개발과 테스트 용도로 제공하는 테스트 API 사용

    ▶ 스트라이프는 애플리케이션 내의 신용카드 결제에 필요한 모든 단계를 지원

    ▶ 신용카드 번호의 유효성을 검사하고 입력된 승인 금액으로 결제를 요청한 후 최종적으로 결제액을 계좌로 입금

 

    ▶ 리액트 스트라이프 엘리먼트: https://github.com/stripe-archive/react-stripe-elements

         ● UI 엘리먼트는 신용카드 번호와 유효기간, CVC 번호, 우편번호 등의 신용카드 정보를 입력받음

         ● 입력된 카드번호가 Master 또는 Visa인지 확인하는 등의 추가 데이터를 검증

         ● 입력된 데이터를 검증하고 신용카드 정보를 나타내는 토큰 ID 값을 발급받고 해당 ID 백엔드에 저장하고 사용

    ▶ 신용카드 결제 폼 작성 순서

         ● 신용카드 결제 폼을 감싸는 컴포넌트를 생성 - 이 컴포넌트의 이름은 child

         ● child 컴포넌트 안에 신용카드 정보를 입력하는 필드들을 포함하는 스트라이프 엘리먼트를 추가하는데 각 필드는 신용카드 번호와 유효기간 등을 입력 받는 일반적인 텍스트 입력 창

         ● child 컴포넌트에 신용카드 토큰 ID 백엔드로 전송하는 코드를 추가

         ● 스트라이프 엘리먼트를 감싸는 컴포넌트의 부모 클래스를 정의

            → 스트라이프 API 키를 처리하는 StripeProvider 컴포넌트를 호스트

            StripeProvider 컴포넌트 안에 child 컴포넌트를 추가

            스트라이프 props와 함수를 child 컴포넌트에 전달하는데 injectStripe 메서드를 사용

    ▶ 패키지 설치

         ● npm install @stripe/react-stripe-js @stripe/stripe-js

         ● npm install --save react-stripe-elements

            

    ▶ 신용카드 결제 처리 폼을 작성 src/CreditCards.js 파일

import React from 'react';
import { injectStripe, StripeProvider, Elements, CardElement } from 'react-stripe-elements';

const INITIALSTATE = "INITIAL", SUCCESSSTATE = "COMPLETE", FAILEDSTATE = "FAILED";

class CreditCardForm extends React.Component {
    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleInputChange = this.handleInputChange.bind(this);
        this.state = {
            value: '',
            status: INITIALSTATE
        };
    }
    renderCreditCardInformation() {
        const style = {
            base: {
                'fontSize': '20px',
                'color': '#495057',
                'fontFamily': 'apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'
            }
        };
        const usersavedcard = <div>
            <div className="form-row text-center">
                <button type="button" className="btn  btn-outline-success text-center mx-auto">Use saved card?</button>
            </div>
            <hr />
        </div>
        const remembercardcheck = <div className="form-row form-check text-center">
            <input className="form-check-input" type="checkbox" value="" id="remembercardcheck" />
            <label className="form-check-label" htmlFor="remembercardcheck">
                Remember Card?
            </label>
        </div>;
        return (
            <div>
                {usersavedcard}
                <h5 className="mb-4">Payment Info</h5>
                <form onSubmit={this.handleSubmit}>
                    <div className="form-row">
                        <div className="col-lg-12 form-group">
                            <label htmlFor="cc-name">Name On Card:</label>
                            <input id="cc-name" name='cc-name' className="form-control" placeholder='Name on Card' onChange={this.handleInputChange} type='text' />
                        </div>
                    </div>
                    <div className="form-row">
                        <div className="col-lg-12 form-group">
                            <label htmlFor="card">Card Information:</label>
                            <CardElement id="card" className="form-control" style={style} />
                        </div>
                    </div>
                    {remembercardcheck}
                    <hr className="mb-4" />
                    <button type="submit" className="btn btn-success btn-large" >{this.props.operation}</button>
                </form>
            </div>
        );
    }
        return (
            <div>
                <h5 className="mb-4 text-success">Credit card payment processed.....</h5>
                <button type="submit" className="btn btn-success btn-large" onClick={() => { this.props.toggle() }}>Ok</button>
            </div>
        );
    }
    renderFailure() {
        return (
            <div>
                <h5 className="mb-4 text-danger"> Credit card information invalid, try again or exit</h5>
                {this.renderCreditCardInformation()}
            </div>
        );
    }
    async handleSubmit(event) {
        event.preventDefault();
        console.log("Handle submit called, with name: " + this.state.value);
        let { token } = await this.props.stripe.createToken({ name: this.state.value });
        if (token == null) {
            console.log("invalid token");
            this.setState({ status: FAILEDSTATE });
            return;
        }

        let response = await fetch("/charge", {
            method: "POST",
            headers: { "Content-Type": "text/plain" },
            body: JSON.stringify({
                token: token.id,
                operation: this.props.operation,
            })
        });
        console.log(response.ok);
        if (response.ok) {
            console.log("Purchase Complete!");
            this.setState({ status: SUCCESSSTATE });
        }
        //  document.getElementsByClassName('#modal').modal('hide');
    }

    handleInputChange(event) {
        this.setState({
            value: event.target.value
        });
    }
    render() {

        let body = null;
        switch (this.state.status) {
            case SUCCESSSTATE:
                body = this.renderSuccess();
                break;
            case FAILEDSTATE:
                body = this.renderFailure();
                break;
            default:
                body = this.renderCreditCardInformation();
        }

        return (
            <div>
                {body}
            </div>
        );
    }
}
export default function CreditCardInformation(props) {
    if (!props.show) {
        return null;
    }
    const CCFormWithStripe = injectStripe(CreditCardForm);
    return (
        <div>
            {props.separator ? <hr /> : null}
            <StripeProvider apiKey="pk_test_LwL4RUtinpP3PXzYirX2jNfR">
                <Elements>
                    <CCFormWithStripe operation={props.operation} />
                </Elements>
            </StripeProvider>
        </div>
    );
}
반응형

댓글