[결제] 초간단 Stripe 결제 구현 방법

Stripe를 사용하여 매우 간단하게 결제 기능을 구현하는 방법을 소개합니다.

STRIPE

인터넷 결제 모듈로 비슷한 종류 서비스로 페이팔이 있습니다.
따로 계정이 필요 없으며, 카드번호, 카드 유효기간, cvc만 입력하면 결제가 가능합니다.
그리고 무엇보다 중요한..
구현이 매우 간단합니다! 
물론 한국 서비스를 대상으로는 사용할 수 없지만 혹시나 쓰실 일이 있을까 하여 작성해봅니다..! 
(이미 https://stripe.com/docs/stripe-js/elements/quickstart 에 잘 정리가 되어 있긴 하나.. 그래도 한글이 편하신 분들을 위하여 적습니다.)

사이트( https://stripe.com/ ) 에 가면 이미 코드를 언어별로 바로 복붙할 수 있도록 구성해 놓았습니다.

우선 카드 정보 입력 페이지의 html.erb 코드 입니다.

<script src="https://js.stripe.com/v3/"></script>
<form action="<%= pay_payments_path %>" method="post" id="payment-form">
    <div class="form-row">
        <div class="col-md-12">
        <div class="col-md-6">
            <label for="card-element">
            Credit or debit card
            </label>
            <div id="card-element">
            <!-- A Stripe Element will be inserted here. -->
            </div>
            <!-- Used to display form errors. -->
            <div id="card-errors" role="alert"></div>
        </div>
        <%= hidden_field_tag "payment_id", payment.id %>
        <div class="col-md-3">
            <button>Submit Payment</button>
        </div>
        </div>
    </div>
</form>

카드 정보 입력 페이지의 js코드입니다.

<script>
  var stripe = Stripe('secret_key');
  var elements = stripe.elements();
  var style = {
    base: {
      color: '#32325d',
      lineHeight: '18px',
      fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
      fontSmoothing: 'antialiased',
      fontSize: '16px',
      '::placeholder': {
        color: '#aab7c4'
      }
    },
    invalid: {
      color: '#fa755a',
      iconColor: '#fa755a'
    }
  };
  // Create an instance of the card Element.
  var card = elements.create('card', {style: style});
  // Add an instance of the card Element into the `card-element` <div>.
  card.mount('#card-element');
  card.addEventListener('change', function(event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
      displayError.textContent = event.error.message;
    } else {
      displayError.textContent = '';
    }
  });
  var form = document.getElementById('payment-form');
  form.addEventListener('submit', function(event) {
    event.preventDefault();
    stripe.createToken(card).then(function(result) {
      if (result.error) {
        // Inform the customer that there was an error.
        var errorElement = document.getElementById('card-errors');
        errorElement.textContent = result.error.message;
      } else {
        // Send the token to your server.
        stripeTokenHandler(result.token);
      }
    });
  });
  function stripeTokenHandler(token) {
  // Insert the token ID into the form so it gets submitted to the server
    var form = document.getElementById('payment-form');
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'stripeToken');
    hiddenInput.setAttribute('value', token.id);
    form.appendChild(hiddenInput);
    // Submit the form
    form.submit();
  }
</script>

 

별다른 기능을 추가하실 예정이 없으시다면 위의 코드에서 payment_path, path로 넘길 값들, js부분의 secret 키만 수정해주시면 바로 복사 붙여넣기로 이용이 가능합니다!

이렇게 하면 확인된 카드 관련 정보를 서버 사이드의 payment_path로 보내게 됩니다. 

서버 사이드의 payment_path 에서도 별 작업 없이 결제를 완료할 수 있습니다. 


서버사이드 코드입니다. 

def pay

    Stripe.api_key = "secret_key"

    @payment = Payment.find params[:payment_id]

    token = params[:stripeToken]

    begin
      charge = Stripe::Charge.create({
          amount: (Rails.env.development? ? 999 : ((@payment.amount*100).to_i)),
          currency: 'usd',
          description: 'payment for #{@payment.detail}',
          source: token,
        })
    rescue Stripe::CardError => e

    end

    if charge.present? && (charge["paid"] == true) && (charge["status"] == "succeeded") && (charge["amount"] == @course.price)
       ...
    end
end

 

이 역시 secret_key와 변수만 조금 수정하시면 바로 복붙하여 사용하셔도 됩니다. 

주의할 사항이라면, 2가지가 있는데, 
 

금액에 소수점을 붙이면 오류가 나게 됩니다!

그래서 100을 곱해서 보내면 알아서 잘 처리를 해줍니다! (ex> $9.99를 보내고 싶다면, 100을 곱하여 999를 보내면 stripe 대시보드에서 $9.99로 인식함)

 

토큰오류가 납니다!

이렇게 해도 문제가 없을지는 모르겠으나, 전 skip_before_action :verify_authenticity_token 를 결제를 하는 컨트롤러에 붙여주어서 넘어갔습니다.. 
 

우선 외국 서비스 결제를 대상으로 할 경우, 매우 편하게 이용할 수 있을 것 같습니다. 이외에도 많은 기능들이 있으나, 사용해보지않아서 다음에 한번 사용할 기회가 되면 내용을 더 추가해보겠습니다.


이것도 읽어보세요