인프런 커뮤니티 질문&답변

현정님의 프로필 이미지

작성한 질문수

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

28-01-payment

Section 50 퀴즈 관련 질문입니다.

해결된 질문

23.08.11 12:46 작성

·

249

1

backend playground를 보고 작업하고 있으나 추가로 질문 드려야만 해결할 수 있는 부분이 있어 여쭤봅니다.

loading 페이지에서 createPointTransactionOfLoading을 사용하여 이것을 complete 페이지에서 fetch해서 가져와야할 거 같은데 fetch 할 때 필요한 api를 모르겠어서 임시로 fetchPointTransactionsOfSelling로 했습니다.

createPointTransactionOfLoading 부분에서 id는 사용자 아이디인데 impUid는 뭘 의미하나요? 회원가입 하면 id가 발급되는 것처럼 해당 api에서 자체적으로 발급되는 걸까요?

amount가 포인트 양인 것 같아서 기존의 포인트에 포인트를 중첩하려면 loading과 complete에 동일한 api를 fetch해서 Selected를 더하는 게 맞나요?

createPoint와 fetchPoint할 때 필요한 요소는 뭐가 더 있는지 궁금합니다.

complete 페이지에서 'IPointTransaction[]' 형식에 'amount' 속성이 없습니다. 라고 뜨는데 어떻게 해결하나요?

 

작성한 코드입니다.

complete ({data?.fetchPointTransactionsOfSelling.amount}에 amount 속성이 없다는 빨간 줄)

 

import { gql, useQuery } from "@apollo/client"
import type { IQuery, IQueryFetchPointTransactionsOfSellingArgs } from "../../../../src/commons/types/generated/types"
const FETCH_POINT = gql`
  query {
    fetchPointTransactionsOfSelling {
      _id
      impUid
      amount
    }
  }
`
export default function CompletePage():JSX.Element {
  const { data } = useQuery<Pick<IQuery,"fetchPointTransactionsOfSelling">,IQueryFetchPointTransactionsOfSellingArgs>(FETCH_POINT)
  return <>충전한 포인트는 {data?.fetchPointTransactionsOfSelling.amount}원</>
}

loading (Number(amount)에 이름 찾을 수 없다는 빨간 줄)

import { gql, useQuery, useMutation } from "@apollo/client"
import type { IQuery } from "../../../../src/commons/types/generated/types"
import { loginCheck } from "../../../../src/components/commons/hocs/withAuth"
import { useRouter } from "next/router"
import type { ChangeEvent } from "react"
import { useState } from "react"
const FETCH_USER_LOGGED_IN = gql`
  query {
    fetchUserLoggedIn {
      email
      name
    }
  }
`
const CREATE_POINT = gql`
  mutation createPointTransactionOfLoading($impUid:ID!){
    createPointTransactionOfLoading(impUid:$impUid){
      _id
      impUid
      amount
    }
  }
`
declare const window: typeof globalThis & {
  IMP: any
}
function LoadingPage():JSX.Element {
  const router = useRouter()
  const { data } = useQuery<Pick<IQuery,"fetchUserLoggedIn">>(FETCH_USER_LOGGED_IN)
  const [ myFunction ] = useMutation(CREATE_POINT)
  const selectList = [0,500,1000,2000,5000];
  const [Selected, setSelected] = useState(0);

  const handleSelect = (e:ChangeEvent<HTMLSelectElement>):void => {setSelected(Number(e.target.value));};
  
  const onClickPayment = ():void => {
    if (Selected === 0) { alert("금액을 선택해주세요."); return; }

    const IMP = window.IMP;
    IMP.init("imp27255777");

    IMP.request_pay({ // param
      pg: "kakaopay",
      pay_method: "card",
      // merchant_uid: "ORD20180131-0000011",
      name: `Section 50-${Selected}원 결제`,
      amount: Selected,
      buyer_email: data?.fetchUserLoggedIn.email,
      buyer_name: data?.fetchUserLoggedIn.name,
      buyer_tel: "",
      buyer_addr: "",
      buyer_postcode: "",
      m_redirect_url:""
    }, async (rsp:any) => {
      if (rsp.success === true) {
        await myFunction({
          variables:{ 
            impUid : data?.fetchUserLoggedIn._id,
            amount: Number(amount) + Selected
          }
        })
        const {Modal} = await import("antd")
        Modal.success({content:"등록 성공"})
        void router.push("/z_quiz/section50/complete")
      } else {
        alert("결제 실패")
      }
    });
  }
  
  return (<>
  <div>{data?.fetchUserLoggedIn.name}님 환영합니다.</div>
  <select onChange={handleSelect} value={Selected}>
    {selectList.map((item) => (
      <option value={item} key={item}>{item}</option>
    ))}
  </select>
  <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js" />
	<script src="https://cdn.iamport.kr/v1/iamport.js" />
  <button onClick={onClickPayment}>충전하기</button>
  </>)
}
export default loginCheck(LoadingPage);

login

import { gql, useMutation } from "@apollo/client"
import { type ChangeEvent, useState } from "react"
import type { IMutation, IMutationLoginUserArgs } from "../../../../src/commons/types/generated/types"
import { useRecoilState } from "recoil"
import { accessTokenState } from "../../../../src/commons/stores"
import { useRouter } from "next/router"
import { wrapFormAsync } from "../../../../src/commons/libraries/asyncFunc"
const LOGIN_USER =gql`
  mutation loginUser($email:String!, $password:String!){
    loginUser(email:$email,password:$password){
      accessToken
    }
  }
`
export default function LoginPage():JSX.Element {
  const router = useRouter()
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [loginUser] = useMutation<Pick<IMutation,"loginUser">,IMutationLoginUserArgs>(LOGIN_USER)
  const [, setAccessToken] = useRecoilState(accessTokenState)
  const onChangeEmail = (event: ChangeEvent<HTMLInputElement>):void => {
    setEmail(event.currentTarget.value)
  }
  const onChangePassword = (event: ChangeEvent<HTMLInputElement>):void => {
    setPassword(event.currentTarget.value)
  }
  const onClickLogin = async ():Promise<void> => {
    try {
      const result = await loginUser({variables: { email, password }}) 
      const accessToken = result.data?.loginUser.accessToken

      if (accessToken=== undefined) {
        alert("로그인 실패")
        return ;}
      setAccessToken(accessToken)
      localStorage.setItem("accessToken", accessToken)
      void router.push("/z_quiz/section50/loading")
    } catch(error) {
      if (error instanceof Error ) alert(error.message)
    }
  }
  return (
    <form  onSubmit={wrapFormAsync(onClickLogin)}>
    이메일: <input type="text" onChange={onChangeEmail} />
    비밀번호: <input type="password" onChange={onChangePassword} />
    <button>로그인</button>
    </form>
  )
}

답변 1

0

노원두님의 프로필 이미지
노원두
지식공유자

2023. 08. 12. 15:22

안녕하세요! 현정님!

해당 질문을 자세히 읽어보니, 아직 결제 수업에 대한 이론 학습이 조금 더 필요할 것 같아요!
해당 수업에서는 약 1시간가량의 결제 이론 수업을 진행하고 있는데, 이 부분을 한 번 더 보완해 주실 것을 부탁드려요!

이유는, 해당 수업은 자체 서비스만으로는 해결할 수 없으며 포트원(전 아임포트) 서비스에대한 이해도를 필요로 하기 때문에 그렇답니다!

먼저, 간단히만 결론을 말씀드리면, impUid는 해당 포트원(전 아임포트)에 결제를 진행한 후에 발급받은 포트원ID를 말합니다. 이 ID는 코드캠프 백엔드와 연동될 필요가 있으므로 해당 ID를 graphql을 통해 다시 한 번 넘겨주게 되는 것이지요!^^

현정님의 프로필 이미지

작성한 질문수

질문하기