├── .browserslistrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── manuals ├── CERTIFICATION.md └── PAYMENT.md ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── constants.js ├── main.js ├── router │ └── index.js ├── store │ └── index.js ├── utils.js └── views │ ├── Certification.vue │ ├── Home.vue │ ├── Payment.vue │ └── Result.vue └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | end_of_line = lf 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | max_line_length = 100 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | extends: [ 7 | 'plugin:vue/essential', 8 | '@vue/airbnb', 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint', 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iamport-vue-example 2 | 3 | [ ![alt text](https://img.shields.io/badge/vue-v2.6.11-orange.svg?longCache=true&style=flat-square) ](https://github.com/vuejs/vue) 4 | [ ![alt text](https://img.shields.io/badge/ant--design--vue-v1.5.3-yellow.svg?longCache=true&style=flat-square) ](https://github.com/vueComponent/ant-design-vue) 5 | [ ![alt text](https://img.shields.io/badge/styled--components-v4.3.2-green.svg?longCache=true&style=flat-square) ](https://github.com/styled-components/styled-components) 6 | 7 | 뷰 환경에서 아임포트 결제 및 본인인증 연동을 위한 예제입니다. 뷰 네이티브용 예제 프로젝트는 [여기](https://github.com/iamport/iamport-vue-native)를 참조해주세요. 8 | 9 | ## 다운받기 10 | 11 | ``` 12 | $ git clone https://github.com/iamport/iamport-vue-example 13 | ``` 14 | 15 | ## 실행하기 16 | 17 | ``` 18 | $ cd ./iamport-vue-example 19 | $ yarn install 20 | $ yarn run serve 21 | ``` 22 | 23 | ## 아임포트 라이브러리 추가하기 24 | 25 | 최상단 HTML(public/index.html)에 아래의 ` 30 | 31 | 32 | ``` 33 | 34 | ## 결제 연동하기 35 | 36 | 결제 연동 방법은 [뷰에서 아임포트 결제 연동하기](manuals/PAYMENT.md) 문서를 참고하세요. 37 | 38 | ## 본인인증 연동하기 39 | 40 | 본인인증 연동 방법은 [뷰에서 아임포트 휴대폰 본인인증 연동하기](manuals/CERTIFICATION.md) 문서를 참고하세요. 41 | 42 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset', 4 | ], 5 | // plugins: [ 6 | // [ 7 | // 'import', 8 | // { 9 | // libraryName: 'ant-design-vue', 10 | // libraryDirectory: 'es', 11 | // style: 'css', 12 | // }, 13 | // ], 14 | // ], 15 | }; 16 | -------------------------------------------------------------------------------- /manuals/CERTIFICATION.md: -------------------------------------------------------------------------------- 1 | 2 | # 뷰에서 아임포트 본인인증 연동하기 3 | 4 | 뷰 환경에서 아임포트 본인인증 연동을 위한 안내입니다. 5 | 6 | ## 1. 가맹점 식별하기 7 | 8 | `IMP` 객체의 `init` 함수 첫번째 인자에 `가맹점 식별코드`를 추가합니다. 9 | 10 | ```javascript 11 | const { IMP } = window; 12 | IMP.init('imp00000000'); // 'imp00000000' 대신 발급받은 가맹점 식별코드를 사용합니다. 13 | ``` 14 | 15 | 가맹점 식별코드는 아임포트 관리자 페이지 로그인 후, 시스템 설정 > 내정보에서 확인하실 수 있습니다. 16 | 17 | ## 2. 본인인증 데이터 정의하기 18 | 19 | 본인인증에 필요한 데이터를 아래와 같이 정의합니다. 이때 정의한 데이터는 `IMP.certification` 함수 호출시, 첫번째 인자로 전달됩니다. 본인인증 데이터에 대한 보다 자세한 내용은 아임포트 공식 문서를 참고하세요. 20 | 21 | ```javascript 22 | const data = { 23 | merchant_uid: `mid_${new Date().getTime()}` // 주문번호 24 | company: '아임포트', // 회사명 또는 URL 25 | carrier: 'SKT', // 통신사 26 | name: '홍길동', // 이름 27 | phone: '01012341234', // 전화번호 28 | ... 29 | }; 30 | ``` 31 | 32 | ## 3. 콜백 함수 정의하기 33 | 34 | 본인인증 후 실행될 로직을 콜백 함수로 정의합니다. 이때 정의한 함수는 `IMP.certification` 함수 호출시, 두번째 인자로 전달됩니다. 콜백 함수의 첫번째 인자로 본인인증 결과가 객체의 형태로 전달됩니다. 35 | 36 | ```javascript 37 | callback(response) { 38 | const { 39 | success, 40 | merchant_uid, 41 | error_msg, 42 | ... 43 | } = response; 44 | 45 | if (success) { 46 | alert('본인인증 성공'); 47 | } else { 48 | alert(`본인인증 실패: ${error_msg}`); 49 | } 50 | } 51 | ``` 52 | 53 | ## 4. 본인인증 창 호출하기 54 | 55 | 본인인증 하기 버튼을 눌렀을때 `IMP` 객체의 `certification` 함수를 호출해 본인인증 창을 호출합니다. `certification` 함수의 첫번째 인자로는 2에서 정의한 `본인인증 데이터`를, 두번째 인자로는 3에서 정의한 `콜백 함수`를 전달합니다. 56 | 57 | ```html 58 | 65 | 66 | 105 | ``` -------------------------------------------------------------------------------- /manuals/PAYMENT.md: -------------------------------------------------------------------------------- 1 | 2 | # 뷰에서 아임포트 결제 연동하기 3 | 4 | 뷰 환경에서 아임포트 결제 연동을 위한 안내입니다. 5 | 6 | ## 1. 가맹점 식별하기 7 | 8 | `IMP` 객체의 `init` 함수 첫번째 인자에 `가맹점 식별코드`를 추가합니다. 9 | 10 | ```javascript 11 | const { IMP } = window; 12 | IMP.init('imp00000000'); // 'imp00000000' 대신 발급받은 가맹점 식별코드를 사용합니다. 13 | ``` 14 | 15 | 가맹점 식별코드는 아임포트 관리자 페이지 로그인 후, 시스템 설정 > 내정보에서 확인하실 수 있습니다. 16 | 17 | ## 2. 결제 데이터 정의하기 18 | 19 | 결제에 필요한 데이터를 아래와 같이 정의합니다. 이때 정의한 데이터는 `IMP.request_pay` 함수 호출시, 첫번째 인자로 전달됩니다. 결제 데이터에 대한 보다 자세한 내용은 아임포트 공식 문서를 참고하세요. 20 | 21 | ```javascript 22 | const data = { 23 | pg: 'html5_inicis', // PG사 24 | pay_method: 'card', // 결제수단 25 | merchant_uid: `mid_${new Date().getTime()}`, // 주문번호 26 | amount: 1000, // 결제금액 27 | name: '아임포트 결제 데이터 분석', // 주문명 28 | buyer_name: '홍길동', // 구매자 이름 29 | buyer_tel: '01012341234', // 구매자 전화번호 30 | buyer_email: 'example@example', // 구매자 이메일 31 | buyer_addr: '신사동 661-16', // 구매자 주소 32 | buyer_postcode: '06018', // 구매자 우편번호 33 | ... 34 | }; 35 | ``` 36 | 37 | ## 3. 콜백 함수 정의하기 38 | 39 | 결제 후 실행될 로직을 콜백 함수로 정의합니다. 이때 정의한 함수는 `IMP.request_pay` 함수 호출시, 두번째 인자로 전달됩니다. 콜백 함수의 첫번째 인자로 결제 결과가 객체의 형태로 전달됩니다. 결제 결과에 대한 보다 자세한 내용은 아임포트 공식 문서를 참고하세요. 40 | 41 | ```javascript 42 | callback(response) { 43 | const { 44 | success, 45 | merchant_uid, 46 | error_msg, 47 | ... 48 | } = response; 49 | 50 | if (success) { 51 | alert('결제 성공'); 52 | } else { 53 | alert(`결제 실패: ${error_msg}`); 54 | } 55 | } 56 | ``` 57 | 58 | ## 4. 결제 창 호출하기 59 | 60 | 결제하기 버튼을 눌렀을때 `IMP` 객체의 `request_pay` 함수를 호출해 결제 창을 호출합니다. `request_pay` 함수의 첫번째 인자로는 2에서 정의한 `결제 데이터`를, 두번째 인자로는 3에서 정의한 `콜백 함수`를 전달합니다. 61 | 62 | ```html 63 | 70 | 71 | 115 | ``` 116 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iamport-vue-example", 3 | "version": "0.1.0", 4 | "private": false, 5 | "description": "뷰용 아임포트 결제/본인인증 연동 예제 프로젝트", 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint" 10 | }, 11 | "keywords": [ 12 | "iamport", 13 | "vue", 14 | "vuejs" 15 | ], 16 | "author": "Solee Choi (https://github.com/SoleeChoi)", 17 | "homepage": "https://github.com/iamport/iamport-vue-example", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/iamport/iamport-vue-example" 21 | }, 22 | "license": "MIT", 23 | "dependencies": { 24 | "ant-design-vue": "^1.5.3", 25 | "core-js": "^3.6.4", 26 | "vue": "^2.6.11", 27 | "vue-router": "^3.1.6", 28 | "vuex": "^3.1.3" 29 | }, 30 | "devDependencies": { 31 | "@vue/cli-plugin-babel": "^4.3.0", 32 | "@vue/cli-plugin-eslint": "^4.3.0", 33 | "@vue/cli-service": "^4.3.0", 34 | "@vue/eslint-config-airbnb": "^5.0.2", 35 | "babel-eslint": "^10.1.0", 36 | "babel-plugin-import": "^1.13.0", 37 | "eslint": "^6.7.2", 38 | "eslint-plugin-import": "^2.20.2", 39 | "eslint-plugin-vue": "^6.2.2", 40 | "less": "^3.0.4", 41 | "less-loader": "^5.0.0", 42 | "vue-template-compiler": "^2.6.11" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iamport/iamport-vue-example/1ab4c292ea681cb6cdcf9318bb3d926def144c59/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 48 | -------------------------------------------------------------------------------- /src/constants.js: -------------------------------------------------------------------------------- 1 | export const PGS = [ 2 | { 3 | value: 'html5_inicis', 4 | label: '웹 표준 이니시스', 5 | }, 6 | { 7 | value: 'kcp', 8 | label: 'NHN KCP', 9 | }, 10 | { 11 | value: 'kcp_billing', 12 | label: 'NHN KCP 정기결제', 13 | }, 14 | { 15 | value: 'uplus', 16 | label: 'LG 유플러스', 17 | }, 18 | { 19 | value: 'jtnet', 20 | label: 'JTNET', 21 | }, 22 | { 23 | value: 'nice', 24 | label: '나이스 정보통신', 25 | }, 26 | { 27 | value: 'kakaopay', 28 | label: '신 - 카카오페이', 29 | }, 30 | { 31 | value: 'kakao', 32 | label: '구 - LG CNS 카카오페이', 33 | }, 34 | { 35 | value: 'danal', 36 | label: '다날 휴대폰 소액결제', 37 | }, 38 | { 39 | value: 'danal_tpay', 40 | label: '다날 일반결제', 41 | }, 42 | { 43 | value: 'kicc', 44 | label: '한국정보통신', 45 | }, 46 | { 47 | value: 'paypal', 48 | label: '페이팔', 49 | }, 50 | { 51 | value: 'mobilians', 52 | label: '모빌리언스', 53 | }, 54 | { 55 | value: 'payco', 56 | label: '페이코', 57 | }, 58 | { 59 | value: 'settle', 60 | label: '세틀뱅크 가상계좌', 61 | }, 62 | { 63 | value: 'naverco', 64 | label: '네이버 체크아웃', 65 | }, 66 | { 67 | value: 'naverpay', 68 | label: '네이버페이', 69 | }, 70 | { 71 | value: 'smilepay', 72 | label: '스마일페이', 73 | }, 74 | ]; 75 | 76 | export const METHODS = [ 77 | { 78 | value: 'card', 79 | label: '신용카드', 80 | }, 81 | { 82 | value: 'trans', 83 | label: '실시간 계좌이체', 84 | }, 85 | { 86 | value: 'vbank', 87 | label: '가상계좌', 88 | }, 89 | { 90 | value: 'phone', 91 | label: '휴대폰 소액결제', 92 | }, 93 | ]; 94 | 95 | export const METHODS_FOR_INICIS = METHODS.concat([ 96 | { 97 | value: 'samsung', 98 | label: '삼성페이', 99 | }, 100 | { 101 | value: 'kapy', 102 | label: 'KPAY', 103 | }, 104 | { 105 | value: 'cultureland', 106 | label: '문화상품권', 107 | }, 108 | { 109 | value: 'smartculture', 110 | label: '스마트문상', 111 | }, 112 | { 113 | value: 'happymoney', 114 | label: '해피머니', 115 | }, 116 | ]); 117 | 118 | export const METHODS_FOR_UPLUS = METHODS.concat([ 119 | { 120 | value: 'cultureland', 121 | label: '문화상품권', 122 | }, 123 | { 124 | value: 'smartculture', 125 | label: '스마트문상', 126 | }, 127 | { 128 | value: 'booknlife', 129 | label: '도서문화상품권', 130 | }, 131 | ]); 132 | 133 | export const METHODS_FOR_KCP = METHODS.concat([{ value: 'samsung', label: '삼성페이' }]); 134 | 135 | export const METHOD_FOR_CARD = [{ value: 'card', label: '신용카드' }]; 136 | export const METHOD_FOR_PHONE = [{ value: 'phone', label: '휴대폰 소액결제' }]; 137 | export const METHOD_FOR_VBANK = [{ value: 'vbank', label: '가상계좌' }]; 138 | 139 | export const METHODS_FOR_MOBILIANS = METHOD_FOR_CARD.concat(METHOD_FOR_PHONE); 140 | 141 | export const QUOTAS = ['0', '1']; 142 | 143 | export default {}; 144 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Antd from 'ant-design-vue'; 3 | import App from './App.vue'; 4 | import router from './router'; 5 | import store from './store'; 6 | 7 | import 'ant-design-vue/dist/antd.css'; 8 | 9 | Vue.config.productionTip = false; 10 | 11 | Vue.use(Antd); 12 | 13 | new Vue({ 14 | router, 15 | store, 16 | render: (h) => h(App), 17 | }).$mount('#app'); 18 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter from 'vue-router'; 3 | import Home from '../views/Home.vue'; 4 | 5 | Vue.use(VueRouter); 6 | 7 | const routes = [ 8 | { 9 | path: '/', 10 | name: 'Home', 11 | component: Home, 12 | }, 13 | { 14 | path: '/payment', 15 | name: 'Payment', 16 | component: () => import(/* webpackChunkName: "payment" */ '../views/Payment.vue'), 17 | }, 18 | { 19 | path: '/certification', 20 | name: 'Certification', 21 | component: () => import(/* webpackChunkName: "certification" */ '../views/Certification.vue'), 22 | }, 23 | { 24 | path: '/result', 25 | name: 'Result', 26 | component: () => import(/* webpackChunkName: "result" */ '../views/Result.vue'), 27 | }, 28 | ]; 29 | 30 | const router = new VueRouter({ 31 | routes, 32 | }); 33 | 34 | export default router; 35 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | 4 | Vue.use(Vuex); 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | }, 9 | mutations: { 10 | }, 11 | actions: { 12 | }, 13 | modules: { 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | import { 2 | METHODS_FOR_INICIS, 3 | METHODS_FOR_KCP, 4 | METHOD_FOR_CARD, 5 | METHODS_FOR_UPLUS, 6 | METHOD_FOR_PHONE, 7 | METHODS_FOR_MOBILIANS, 8 | METHOD_FOR_VBANK, 9 | QUOTAS, 10 | } from './constants'; 11 | 12 | function getUserCodeByPg(pg) { 13 | switch (pg) { 14 | case 'kakao': 15 | return 'imp10391932'; 16 | case 'paypal': 17 | return 'imp09350031'; 18 | case 'mobilians': 19 | return 'imp60029475'; 20 | case 'naverco': 21 | case 'naverpay': 22 | return 'imp41073887'; 23 | default: 24 | return 'imp19424728'; 25 | } 26 | } 27 | 28 | function getMethodsByPg(pg = 'html5_inicis') { 29 | switch (pg) { 30 | case 'html5_inicis': 31 | return METHODS_FOR_INICIS; 32 | case 'kcp': 33 | return METHODS_FOR_KCP; 34 | case 'kcp_billing': 35 | case 'kakaopay': 36 | case 'kakao': 37 | case 'paypal': 38 | case 'payco': 39 | case 'smilepay': 40 | return METHOD_FOR_CARD; 41 | case 'uplus': 42 | return METHODS_FOR_UPLUS; 43 | case 'danal': 44 | return METHOD_FOR_PHONE; 45 | case 'mobilians': 46 | return METHODS_FOR_MOBILIANS; 47 | case 'settle': 48 | return METHOD_FOR_VBANK; 49 | default: 50 | return METHODS_FOR_INICIS; 51 | } 52 | } 53 | 54 | function getQuotaByPg(pg = 'html5_inicis') { 55 | switch (pg) { 56 | case 'html5_inicis': 57 | case 'kcp': 58 | return QUOTAS.concat(['2', '3', '4', '5', '6']); 59 | default: 60 | return QUOTAS; 61 | } 62 | } 63 | 64 | export default { 65 | getUserCodeByPg, 66 | getMethodsByPg, 67 | getQuotaByPg, 68 | }; 69 | -------------------------------------------------------------------------------- /src/views/Certification.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 121 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 77 | -------------------------------------------------------------------------------- /src/views/Payment.vue: -------------------------------------------------------------------------------- 1 | 147 | 148 | 260 | -------------------------------------------------------------------------------- /src/views/Result.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 68 | 69 | 101 | --------------------------------------------------------------------------------