๋ถํธํ์ด ๊ณต์ Ruby ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋๋ค (์๋ฒ์ฌ์ด๋ ์ฉ)
Ruby ์ธ์ด๋ก ์์ฑ๋ ์ดํ๋ฆฌ์ผ์ด์ , ํ๋ ์์ํฌ ๋ฑ์์ ์ฌ์ฉ๊ฐ๋ฅํฉ๋๋ค.
- PG ๊ฒฐ์ ์ฐฝ ์ฐ๋์ ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ํ๋ฉ๋๋ค. (Javascript, Android, iOS, React Native, Flutter ๋ฑ)
- ๊ฒฐ์ ๊ฒ์ฆ ๋ฐ ์ทจ์, ๋น๋งํค ๋ฐ๊ธ, ๋ณธ์ธ์ธ์ฆ ๋ฑ์ ์ํ์ ์๋ฒ์ฌ์ด๋์์ ์งํ๋ฉ๋๋ค. (Java, PHP, Python, Ruby, Node.js, Go, ASP.NET ๋ฑ)
-
(๋ถํธํ์ด ํต์ ์ ์ํ) ํ ํฐ ๋ฐ๊ธ ์์ฒญ
-
๊ฒฐ์ ๊ฒ์ฆ
-
๊ฒฐ์ ์ทจ์ (์ ์ก ์ทจ์ / ๋ถ๋ถ ์ทจ์)
-
๋น๋งํค ๋ฐ๊ธ
4-1. ๋ฐ๊ธ๋ ๋น๋งํค๋ก ๊ฒฐ์ ์น์ธ ์์ฒญ
4-2. ๋ฐ๊ธ๋ ๋น๋งํค๋ก ๊ฒฐ์ ์น์ธ ์์ฝ ์์ฒญ
4-2-1. ๋ฐ๊ธ๋ ๋น๋งํค๋ก ๊ฒฐ์ ์น์ธ ์์ฝ - ์ทจ์ ์์ฒญ
4-3. ๋น๋งํค ์ญ์
-
(๋ถํธํ์ด ๋จ๋ ) ์ฌ์ฉ์ ํ ํฐ ๋ฐ๊ธ
-
(๋ถํธํ์ด ๋จ๋ ) ๊ฒฐ์ ๋งํฌ ์์ฑ
-
์๋ฒ ์น์ธ ์์ฒญ
-
๋ณธ์ธ ์ธ์ฆ ๊ฒฐ๊ณผ ์กฐํ
gem 'bootpay'Gemfile์ ์ ๋ผ์ธ์ ์ถ๊ฐํ๊ณ , ์๋ ๋ผ์ธ์ผ๋ก ์ธ์คํจ ํฉ๋๋ค.
$ bundle install
๋๋ ์๋ ๋ฌธ์ฅ์ ํตํด ๋ฐ๋ก ์ค์นํ ์ ์์ต๋๋ค:
$ gem install backend-ruby
์์ ์ ํ
์คํธ๋ ๊ฐ SDK ๋ฃจํธ์ .env ํ์ผ์ ์ฐ์ ์ฝ์ต๋๋ค. ๋จผ์ .env.example์ ๋ณต์ฌํ ๋ค ํ์ํ ํค๋ง ๋ณ๊ฒฝํ์ธ์. .env๋ gitignore ์ฒ๋ฆฌ๋์ด ์ปค๋ฐ๋์ง ์์ต๋๋ค.
cp .env.example .env
# BOOTPAY_ENV=production ๋๋ development์ฃผ์ ๋ณ์:
BOOTPAY_ENV=production
BOOTPAY_PG_CLIENT_KEY_PROD=...
BOOTPAY_PG_SECRET_KEY_PROD=...
BOOTPAY_PG_CLIENT_KEY_DEV=...
BOOTPAY_PG_SECRET_KEY_DEV=...
BOOTPAY_COMMERCE_CLIENT_KEY_PROD=...
BOOTPAY_COMMERCE_SECRET_KEY_PROD=...
BOOTPAY_COMMERCE_CLIENT_KEY_DEV=...
BOOTPAY_COMMERCE_SECRET_KEY_DEV=...๋ณ์๊ฐ ์์ผ๋ฉด SDK ํ ์คํธ์ฉ ๊ธฐ๋ณธ๊ฐ(NodeJS ๊ธฐ์ค ck/sk)์ผ๋ก fallback ํฉ๋๋ค.
require 'bootpay'
@api = Bootpay::Api.new(
client_key: ENV.fetch('BOOTPAY_PG_CLIENT_KEY_PROD'),
secret_key: ENV.fetch('BOOTPAY_PG_SECRET_KEY_PROD'),
)
# Legacy application_id/private_key ๋ฐฉ์๋ ๊ณ์ ์ง์๋ฉ๋๋ค.
response = @api.request_access_token
if response.success?
puts response.data.to_json
endํจ์ ๋จ์์ ์ํ ์ฝ๋๋ ์ด๊ณณ์ ์ฐธ์กฐํ์ธ์.
๋ถํธํ์ด์ ์๋ฒ๊ฐ ํต์ ์ ํ๊ธฐ ์ํด์๋ ๋ถํธํ์ด ์๋ฒ๋ก๋ถํฐ ํ ํฐ์ ๋ฐ๊ธ๋ฐ์์ผ ํฉ๋๋ค.
๋ฐ๊ธ๋ ํ ํฐ์ 30๋ถ๊ฐ ์ ํจํ๋ฉฐ, ์ต์ด ๋ฐ๊ธ์ผ๋ก๋ถํฐ 30๋ถ์ด ์ง๋ ๊ฒฝ์ฐ ํ ํฐ ๋ฐ๊ธ ํจ์๋ฅผ ์ฌํธ์ถ ํด์ฃผ์
์ผ ํฉ๋๋ค.
def get_token
response = @api.request_access_token
if response.success?
puts response.data.to_json
end
end๊ฒฐ์ ์ฐฝ ๋ฐ ์ ๊ธฐ๊ฒฐ์ ์์ ์น์ธ/์ทจ์๋ ๊ฒฐ์ ๊ฑด์ ๋ํ์ฌ ์ฌ๋ฐ๋ฅธ ๊ฒฐ์ ๊ฑด์ธ์ง ์๋ฒ๊ฐ ํต์ ์ผ๋ก ๊ฒฐ์ ๊ฒ์ฆ์ ํฉ๋๋ค.
def verification
receipt_id = '612df0250d681b001de61de6'
if @api.request_access_token.success?
response = @api.verify(receipt_id)
puts response.data.to_json
end
endprice๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด ์ ์ก์ทจ์ ๋ฉ๋๋ค.
- ํด๋ํฐ ๊ฒฐ์ ์ ๊ฒฝ์ฐ ์ด์๋ ๊ฒฝ์ฐ ์ดํต์ฌ ์ ์ฑ ์ ์ทจ์๋์ง ์์ต๋๋ค
- ์ ์ฐ๋ฐ์ผ์ค ๊ธ์ก๋ณด๋ค ์ทจ์๊ธ์ก์ด ํด ๊ฒฝ์ฐ PG์ฌ ์ ์ฑ ์ ์ทจ์๋์ง ์์ ์ ์์ต๋๋ค. ์ด๋ PG์ฌ์ ๋ฌธ์ํ์๋ฉด ๋๊ฒ ์ต๋๋ค.
- ๊ฐ์๊ณ์ข์ ๊ฒฝ์ฐ CMS ํน์ฝ์ด ๋์ด์์ง ์์ผ๋ฉด ์ทจ์๋์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ๊ฒฐ์ ํ ์คํธ์์๋ ๊ฐ์๊ณ์ข๋ก ํ ์คํธ ํ์ง ์๊ธธ ์ถ์ฒํฉ๋๋ค.
๋ถ๋ถ์ทจ๋ ์นด๋๋ก ๊ฒฐ์ ๋ ๊ฑด๋ง ๊ฐ๋ฅํ๋ฉฐ, ์ผ๋ถ PG์ฌ๋ง ์ง์ํฉ๋๋ค. ์์ฒญ์ price์ ๊ธ์ก์ ์ง์ ํ์๋ฉด ๋๊ฒ ์ต๋๋ค.
- (์ง์๊ฐ๋ฅ PG์ฌ: ์ด๋์์ค, kcp, ๋ค๋ , ํ์ด๋ ํฐ, ๋์ด์คํ์ด, ์นด์นด์คํ์ด, ํ์ด์ฝ)
๊ฐํน ๊ฐ๋ฐ์ฌ์์ ์ค์๋ก ์ฌ๋ฌ๋ฒ ๋ถ๋ถ์ทจ์๋ฅผ ๋ณด๋ด์ ์ฌ๋ฌ๋ฒ ์ทจ์๋๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ๋๋ฌธ์, ๋ถํธํ์ด์์๋ ๋ถ๋ถ์ทจ์ ์ค๋ณต ์์ฒญ์ ๋ง๊ธฐ ์ํด cancel_id ๋ผ๋ ํ๋๋ฅผ ์ถ๊ฐํ์ต๋๋ค. cancel_id๋ฅผ ์ง์ ํ์๋ฉด, ํด๋น ๊ฑด์ ๋ํด ์ค๋ณต ์์ฒญ๋ฐฉ์ง๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
def cancel
if @api.request_access_token.success?
response = @api.cancel_payment(
receipt_id: "612df0250d681b001de61de6",
cancel_username: 'test',
cancel_message: 'test',
cancel_price: 1000, # ๋ถ๋ถ์ทจ์ ์์ฒญ์
refund: { # ๊ฐ์๊ณ์ข ํ๋ถ ์์ฒญ์, ๋จ CMS ํน์ฝ์ด ๋์ด์์ด์ผ๋ง ํ๋ถ์์ฒญ์ด ๊ฐ๋ฅํ๋ค.
account: '675601010124', # ํ๋ถ๊ณ์ข
accountholder: 'ํ๊ธธ๋', # ํ๋ถ๊ณ์ข์ฃผ
bankcode: Bootpay::BANKCODE["๊ตญ๋ฏผ์ํ"] # ์ํ์ฝ๋
}
)
puts response.data.to_json
end
endREST API ๋ฐฉ์์ผ๋ก ๊ณ ๊ฐ์ผ๋ก๋ถํฐ ์นด๋ ์ ๋ณด๋ฅผ ์ ๋ฌํ์ฌ, PG์ฌ์๊ฒ ๋น๋งํค๋ฅผ ๋ฐ๊ธ๋ฐ์ ์ ์์ต๋๋ค. ๋ฐ๊ธ๋ฐ์ ๋น๋งํค๋ฅผ ์ ์ฅํ๊ณ ์๋ค๊ฐ, ์ํ๋ ์์ , ์ํ๋ ๊ธ์ก์ ๊ฒฐ์ ์น์ธ ์์ฒญํ์ฌ ์ข ๋ ์์ ๋ก์ด ๊ฒฐ์ ์๋๋ฆฌ์ค์ ์ ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
- ๋น์ธ์ฆ ์ ๊ธฐ๊ฒฐ์ (REST API) ๋ฐฉ์์ ์ง์ํ๋ PG์ฌ๋ง ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
def get_billing_key
if @api.request_access_token.success?
response = @api.get_billing_key(
order_id: '1234',
pg: 'nicepay',
item_name: 'ํ
์คํธ ๊ฒฐ์ ',
card_no: '', # ๊ฐ ํ ๋น ํ์
card_pw: '', # ๊ฐ ํ ๋น ํ์
expire_year: '', # ๊ฐ ํ ๋น ํ์
expire_month: '', # ๊ฐ ํ ๋น ํ์
identify_number: '' # ๊ฐ ํ ๋น ํ์
)
puts response.data.to_json
end
end๋ฐ๊ธ๋ ๋น๋งํค๋ก ์ํ๋ ์์ ์ ์ํ๋ ๊ธ์ก์ผ๋ก ๊ฒฐ์ ์น์ธ ์์ฒญ์ ํ ์ ์์ต๋๋ค. ์์ก์ด ๋ถ์กฑํ๊ฑฐ๋ ๋๋ ์นด๋ ๋ฑ์ ํน๋ณํ ๊ฑด์ด ์๋๋ฉด PG์ฌ์์ ๊ฒฐ์ ๋ฅผ ๋ฐ๋ก ์น์ธํฉ๋๋ค.
def subscribe_billing
billing_key = '612deb53019943001fb52312'
if @api.request_access_token.success?
response = @api.subscribe_billing(
billing_key: billing_key,
item_name: 'ํ
์คํธ ๊ฒฐ์ ',
price: 1000,
tax_free: 1000,
order_id: '1234'
)
puts response.data.to_json
end
end์ํ๋ ์์ ์ 4-1๋ก ๊ฒฐ์ ์น์ธ ์์ฒญ์ ๋ณด๋ด๋ ๋์ง๋ง, ๋น๋งํค ๋ฐ๊ธ ์ดํ์ ๋ฐ๋ก ๊ฒฐ์ ์์ฝ ํ ์ ์์ต๋๋ค. (๋น๋งํค๋น ์ต๋ 5๊ฑด)
def subscribe_reserve_billing
billing_key = '612deb53019943001fb52312'
if @api.request_access_token.success?
response = @api.subscribe_reserve_billing(
billing_key: billing_key,
item_name: 'ํ
์คํธ ๊ฒฐ์ ',
price: 1000,
tax_free: 1000,
order_id: '1234',
execute_at: (Time.now + 10.seconds).to_i # 10์ด ๋ค ๊ฒฐ์
)
puts response.data.to_json
end
end๋น๋งํค๋ก ์์ฝ๋ ๊ฒฐ์ ๊ฑด์ ์ทจ์ํฉ๋๋ค.
def subscribe_reserve_cancel
reserve_id = '612deb53019943001fb52312'
if @api.request_access_token.success?
response = @api.subscribe_reserve_cancel(reserve_id)
puts response.data.to_json
end
end๋ฐ๊ธ๋ ๋น๋งํค๋ก ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋๋ก, ์ญ์ ์์ฒญํฉ๋๋ค.
def destroy_billing_key
if @api.request_access_token.success?
response = @api.destroy_billing_key('6100e7ea0d681b001fd4de69')
puts response.data.to_json
end
end(๋ถํธํ์ด ๋จ๋ ) ๋ถํธํ์ด์์ ์ ๊ณตํ๋ ๊ฐํธ๊ฒฐ์ ์ฐฝ, ์์ฒด์ธ์ฆ ๊ธฐ๋ฐ์ ๊ฒฐ์ ์ฌ์ฉ์ ์ํด์๋ ๊ฐ๋ฐ์ฌ์์ ํ์ ๊ณ ์ ๋ฒํธ๋ฅผ ๊ด๋ฆฌํด์ผํ๋ฉฐ, ํด๋น ํ์์ ๋ํ ์ฌ์ฉ์ ํ ํฐ์ ๋ฐ๊ธํฉ๋๋ค. ์ด ํ ํฐ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ํด๋ผ์ด์ธํธ์์ ๊ฒฐ์ ์์ฒญ ํ์๋ฉด ๋๊ฒ ์ต๋๋ค.
def destroy_billing_key
if @api.request_access_token.success?
billing_key = '612debc70d681b0039e6133d'
response = @api.destroy_billing_key(billing_key)
puts response.data.to_json
end
end(๋ถํธํ์ด ๋จ๋ ) ์์ฒญ ํ์๋ฉด ๊ฒฐ์ ๋งํฌ๊ฐ ๋ฆฌํด๋๋ฉฐ, ํด๋น url์ ๊ณ ๊ฐ์๊ฒ ์๋ด, ๊ฒฐ์ ์ ๋ํ์ฌ ๊ฒฐ์ ๋ฅผ ์งํํ ์ ์์ต๋๋ค.
def request_link
if @api.request_access_token.success?
response = @api.request_link(
pg: 'nicepay',
price: 1000,
tax_free: 1000,
order_id: '1234',
name: '๊ฒฐ์ ํ
์คํธ'
)
puts response.data.to_json
end
end๊ฒฐ์ ์น์ธ ๋ฐฉ์์ ํด๋ผ์ด์ธํธ ์น์ธ ๋ฐฉ์๊ณผ, ์๋ฒ ์น์ธ ๋ฐฉ์์ผ๋ก ์ด 2๊ฐ์ง๊ฐ ์์ต๋๋ค.
ํด๋ผ์ด์ธํธ ์น์ธ ๋ฐฉ์์ javascript๋ native ๋ฑ์์ confirm ํจ์์์ ์งํํ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค๋ง, ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์๋ฒ ์น์ธ ๋ฐฉ์์ด ํ์ํ ์ ์์ต๋๋ค.
ํ์ํ ์ด์
- 100% ์์ ์ ์ธ ๊ฒฐ์ ํ ๊ณ ๊ฐ ์๋ด๋ฅผ ์ํด - ํด๋ผ์ด์ธํธ์์ PG๊ฒฐ์ ์งํ ํ ์น์ธ ์๋ฃ๋ ๋ onDone์ด ์ํ๋์ง ์์ (์ธํฐ๋ท ํ๊ฒฝ ๋ฑ), ๊ฒฐ์ ์ดํ ๊ณ ๊ฐ์๊ฒ ์๋ดํ์ง ๋ชปํ ์ ์์ต๋๋ค
- ๋จ์ผ ํธ๋์ญ์ ์ ๊ฐ๋ ์ด ํ์ํ ๊ฒฝ์ฐ - ์ฌ๊ณ ํ์ ์ด ์ค์ํ ์ปค๋จธ์ค๋ฅผ ์ด์ํ ๊ฒฝ์ฐ ํธ๋์ญ์ ๊ฐ๋ ์ด ํ์ํ ์ ์๊ฒ ์ผ๋ฉฐ, ์ด๋ฅผ ์ํด์๋ ์๋ฒ ์น์ธ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
def submit
receipt_id = '612e09260d681b0021e61ab9'
if @api.request_access_token.success?
response = @api.server_submit(receipt_id)
puts response.data.to_json
end
end๋ค๋ ๋ณธ์ธ์ธ์ฆ ํ ๊ฒฐ๊ณผ๊ฐ์ ์กฐํํฉ๋๋ค. ๋ค๋ ๋ณธ์ธ์ธ์ฆ์์ ํต์ ์ฌ, ์ธ๊ตญ์ธ์ฌ๋ถ, ์ ํ๋ฒํธ ์ด 3๊ฐ์ง ์ ๋ณด๋ ๋ค๋ ์ ์ถ๊ฐ๋ก ์์ฒญํ์ ์ผ ๋ฐ์ผ์ค ์ ์์ต๋๋ค.
def certificate
receipt_id = '612e09260d681b0021e61ab9'
if @api.request_access_token.success?
response = @api.certificate(receipt_id)
puts response.data.to_json
end
end์ ์ฉํ ์ํ ํ๋ก์ ํธ์ ์ฐธ์กฐํด์ฃผ์ธ์
๋ถํธํ์ด ๊ฐ๋ฐ๋งค๋ด์ผ์ ์ฐธ์กฐํด์ฃผ์ธ์
๋ถํธํ์ด ํํ์ด์ง ์ฐ์ธก ํ๋จ ์ฑํ ์ ํตํด ๊ธฐ์ ๋ฌธ์ ์ฃผ์ธ์!