[JAVA] [Rails] Implémentez la fonction d'enregistrement / suppression de carte de crédit dans PAY.JP

introduction

Nous avons introduit PAY.JP pour effectuer des paiements par carte de crédit avec une application personnelle. Il y avait une petite pierre d'achoppement dans l'introduction, je l'ai donc répertoriée comme mémorandum.

Conditions préalables

procédure

  1. Inscription PAY.JP
  2. Présentez / préparez PAY.JP dans l'application
  3. Créez un modèle
  4. Fichier de migration
  5. Création d'un contrôleur
  6. Introduction de gon
  7. Création d'un fichier JS

Inscription PAY.JP

Inscrivez-vous à partir de l'URL suivante. PAY.JP

41b709e395800ed89184beb6bbfee74f.png

Une fois l'enregistrement terminé, vous serez redirigé vers l'écran ci-dessus. (Parce qu'il a été utilisé, les ventes sont élevées.) Au départ, il est en mode test. Pour effectuer une transaction réelle, vous devez postuler et passer en mode direct. Cette fois, j'utilise le mode test parce que c'est pour un usage personnel et non à des fins commerciales.

Utilisez le contenu de "API" dans la barre de menu. 996ed64b5c8b7f2c66a991720dc78f83.png

Je vais utiliser cette clé privée de test et tester la clé publique pour mon application.

Présentation de PAY.JP à l'application et préparation

Ajoutez ce qui suit à Gemfile

gem 'payjp'

À partir de là, nous nous préparerons à créer un formulaire de saisie pour les informations de la carte, mais il existe deux façons de le faire.

À propos de la tokenisation des informations de la carte

  1. Découvrez
  2. Personnalisé

À la caisse

<form action="/pay" method="post">
  <script src="https://checkout.pay.jp/" class="payjp-button" data-key=""></script>
</form>

En décrivant ce qui précède, vous pouvez utiliser le formulaire préparé par PAYJP.

Cette fois, je voulais personnaliser le formulaire moi-même, alors j'ai fait ce qui suit:

Ajoutez ce qui suit à la partie principale de application.html.haml.


 %script{src: "https://js.pay.jp", type: "text/javascript"}

Officiellement, en plus de ce qui précède, la clé publique est également décrite, mais je l'ai décrite séparément (décrite plus loin).

Ensuite, écrivez la clé publique et la clé privée PAYJP dans credentials.yml.enc.

alt

Un peu de préparation est nécessaire pour éditer le fichier. Tout d'abord, configurez-le pour que VS Code puisse être lancé à partir du terminal. Dans VSCode, appuyez sur "Commande + Maj + P" en même temps pour ouvrir la palette de commandes. Entrez ensuite "shell". Dans le menu, l'item "Commande Install'code 'dans PATH" s'affiche. Cliquez dessus. En faisant cela, vous pouvez maintenant démarrer VS Code en tapant "code" depuis le terminal.

Ensuite, modifiez le contenu du fichier ci-dessous.

$ pwd
#Assurez-vous que vous êtes dans votre répertoire d'applications
$ EDITOR='code --wait' rails credentials:edit

Après un certain temps, le fichier s'ouvrira comme indiqué ci-dessous. alt

Écrivez ici comme suit. Notez qu'il est imbriqué.


payjp:
  PAYJP_SECRET_KEY: sk_test_...
  PAYJP_PUBLIC_KEY: pk_test_...

Si vous écrivez votre propre clé, enregistrez-la, puis fermez le fichier ”New credentials encrypted and saved.” Est sortie vers le terminal, donc il est complet.

Vous pouvez vérifier s'il a été enregistré avec la commande suivante.


$ rails c
$ Rails.application.credentials[:payjp][:PAYJP_SECRET_KEY]
$ Rails.application.credentials[:payjp][:PAYJP_PUBLIC_KEY]

Créer un modèle

Cette fois, nous l'appellerons le modèle de la carte. Je l'ai créé comme suit.

class Card < ApplicationRecord
  belongs_to :user
  has_one :order, dependent: :nullify

  require 'payjp'
  Payjp.api_key = Rails.application.credentials.dig(:payjp, :PAYJP_SECRET_KEY)

  def self.create_card_to_payjp(params)
    #Créer un jeton
    token = Payjp::Token.create({
      card: {
        number:     params['number'],
        cvc:        params['cvc'],
        exp_month:  params['valid_month'],
        exp_year:   params['valid_year']
      }},
      {'X-Payjp-Direct-Token-Generate': 'true'} 
    )
    #Créez des informations client en fonction du jeton créé ci-dessus
    Payjp::Customer.create(card: token.id)
  end

Puisque le site EC a été créé dans l'application personnelle, l'association est Utilisateur et Commande.

Les informations de la carte sont symbolisées ici.

Créer une table

J'ai créé un tableau avec le contenu suivant.


class CreateCards < ActiveRecord::Migration[5.2]
  def change
    create_table :cards do |t|
      t.string :customer_id, null: false
      t.string :card_id, null: false
      t.references :user, null: false, foreign_key: true
      t.timestamps
    end
  end
end

Je ne savais pas au début, mais customer_id et card_id doivent être créés en tant que colonnes dans le mât. Les enregistrements sont enregistrés dans le tableau comme suit.

Créer un contrôleur

Cette fois, j'ai configuré le contrôleur avec 4 actions comme suit.

class CardsController < ApplicationController
  before_action :set_card, only: [:new, :show, :destroy]
  before_action :set_payjpSecretKey, except: :new
  before_action :set_cart
  before_action :set_user

  require "payjp"

  def new
    redirect_to action: :show, id: current_user.id if @card.present?
    @card = Card.new 
    gon.payjpPublicKey = Rails.application.credentials[:payjp][:PAYJP_PUBLIC_KEY]
  end

  def create
    render action: :new if params['payjpToken'].blank?
    customer = Payjp::Customer.create(
      card: params['payjpToken']
    )
    @card = Card.new(
      card_id: customer.default_card,
      user_id: current_user.id,
      customer_id: customer.id
    )
    if @card.save
      flash[:notice] = 'L'enregistrement de la carte de crédit est terminé'
      redirect_to action: :show, id: current_user.id
    else
      flash[:alert] = 'L'enregistrement de la carte de crédit a échoué'
      redirect_to action: :new
    end
  end

   def show
    redirect_to action: :new if @card.blank?
    customer = Payjp::Customer.retrieve(@card.customer_id)
    default_card_information = customer.cards.retrieve(@card.card_id)
    @card_info = customer.cards.retrieve(@card.card_id)
    @exp_month = default_card_information.exp_month.to_s
    @exp_year = default_card_information.exp_year.to_s.slice(2,3)
    customer_card = customer.cards.retrieve(@card.card_id)
    @card_brand = customer_card.brand
    case @card_brand
    when "Visa"
      @card_src = "icon_visa.png "
    when "JCB"
      @card_src = "icon_jcb.png "
    when "MasterCard"
      @card_src = "icon_mastercard.png "
    when "American Express"
      @card_src = "icon_amex.png "
    when "Diners Club"
      @card_src = "icon_diners.png "
    when "Discover"
      @card_src = "icon_discover.png "
    end
  end

  def destroy
    customer = Payjp::Customer.retrieve(@card.customer_id)
    @card.destroy
    customer.delete
    flash[:notice] = 'Carte de crédit supprimée'
    redirect_to controller: :users, action: :show, id: current_user.id
  end

  private
  def set_card
    @card = Card.where(user_id: current_user.id).first
  end

  def set_payjpSecretKey
    Payjp.api_key = Rails.application.credentials[:payjp][:PAYJP_SECRET_KEY]
  end

  def set_cart
    @cart = current_cart
  end

  def set_user
    @user = current_user
  end
end

De plus, nous avons introduit un gem appelé "gon" pour éviter d'écrire la clé publique PAYJP dans un fichier JS, qui sera décrit plus loin. C'est une reconnaissance qu'il est utilisé lorsque vous souhaitez utiliser des variables ruby dans des fichiers JS.

Introduction de gon

Ajoutez ce qui suit à Gemfile

gem 'gon'

Ajoutez ce qui suit à la partie principale de application.html.haml.


= include_gon(init: true)

Maintenant, vous êtes prêt à partir.

Créer un fichier JS

À partir de là, créez un fichier JS qui fonctionne avec new.html.haml, qui est appelé par la nouvelle action du contrôleur. Tout d'abord, écrivez new.html.haml.


.cardNew
  .title 
Entrez les informations de la carte de crédit
  .cardForm
    = form_with model: @card, id: "form" do |f|
      .cardForm__number
        = f.label :numéro de carte, class: "cardForm__number__title"
        %span.must_chèque requis
      .cardForm__field
        = f.text_field :card_number, id: "card_number", placeholder: "Numéros demi-largeur uniquement", class: "form-group__input", maxlength: 16
      .cardForm__image
        = image_tag(image_path('cards/icon_visa.png'), class: 'visa', width: 58, height: 28)
        = image_tag(image_path('cards/icon_mastercard.png'), class: 'master', width: 47, height: 36)
        = image_tag(image_path('cards/icon_jcb.png'), class: 'jcb', width: 40, height: 30)
        = image_tag(image_path('cards/icon_amex.png'), class: 'amex', width: 40, height: 30)
        = image_tag(image_path('cards/icon_diners.png'), class: 'diners', width: 45, height: 32)
        = image_tag(image_path('cards/icon_discover.png'), class: 'discover', width: 47, height: 30)
      .cardForm__expirationdate
        .cardForm__expirationdate__details
          = f.label :date d'expiration
          %span.must_chèque requis
          %br
        .cardForm__expirationdate__choice
          .cardForm__expirationdate__choice__month
            = f.select :expiration_month, options_for_select(["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]), {}, {id: "exp_month", name: "exp_month", type: "text"}
            = f.label :Mois, class: "cardForm__expirationdate__choice__month__label"
          .cardForm__expirationdate__choice__year
            = f.select :expiration_year, options_for_select((2020..2030)), {}, {id: "exp_year", name: "exp_year", type: "text"}
            = f.label :Année, class: "cardForm__expirationdate__choice__year__label"
      .cardForm__securitycode
        .cardForm__securitycode__details
          .cardForm__securitycode__details__title 
            = f.label :code de sécurité, class: "label"
            %span.must_chèque requis
          .cardForm__securitycode__details__field
            = f.text_field :cvc,  id: "cvc", class: "cvc", placeholder: "Dos de la carte 3~Numéro à 4 chiffres", maxlength: "4"
          .cardForm__securitycode__details__hatena
            = link_to "Quel est le numéro au dos de la carte??", "#", class: "cardForm__securitycode__details__hatena__link"
      #card_token
        = f.submit "s'inscrire", id: "token_submit", url: cards_path, method: :post

Ensuite, créez un fichier JS correspondant au fichier de vue ci-dessus.


$(document).on('turbolinks:load', function() {
  $(function() {
    Payjp.setPublicKey(gon.payjpPublicKey);
    $("#token_submit").on('click', function(e){
      e.preventDefault();
      let card = {
          number: $('#card_number').val(),
          cvc:$('#cvc').val(),
          exp_month: $('#exp_month').val(),
          exp_year: $('#exp_year').val()
      };

      Payjp.createToken(card, function(status, response) {
        if (response.error) {
          $("#token_submit").prop('disabled', false);
          alert("Les informations de la carte sont incorrectes.");
        }
        else {
          $("#card_number").removeAttr("name");
          $("#cvc").removeAttr("name");
          $("#exp_month").removeAttr("name");
          $("#exp_year").removeAttr("name");

          let token = response.id;
          $("#form").append(`<input type="hidden" name="payjpToken" value=${token}>`);
          $("#form").get(0).submit();
          alert("L'inscription est terminée");
        }
      });
    });
  });
});

Si vous appuyez sur le bouton d'enregistrement (= f.submit "submit", id: "token_submit") dans le fichier de vue, JS se déclenchera. La création de jetons se fait avec une méthode appelée Payjp.createToken.

Avec ce qui précède, l'enregistrement de la carte est terminé.

Enfin, je décrirai brièvement la fonction de suppression. J'ai installé un bouton de suppression dans show.html.haml que j'appelle avec l'action show comme suit.


.payment
  .payment__content
    .payment__content__title
Informations sur la carte
    .payment__content__box
      .payment__content__box__cardImage
        = image_tag "cards/#{@card_src}", width: 40, height: 28
      .payment__content__box__details
        .payment__content__box__details__cardNumber
          = "numéro de carte:**** **** **** " + @card_info.last4
        .payment__content____boxdetails__cardMMYY
          = "date d'expiration:" + @exp_month + " / " + @exp_year
  .payment__cardDelete
    = button_to "effacer", card_path(@card.id), {method: :delete, id: 'charge-form', name: "inputForm", class: "payment__cardDelete__deleteBtn"}

La prochaine fois, je décrirai la fonction de paiement avec la carte enregistrée.

Recommended Posts

[Rails] Implémentez la fonction d'enregistrement / suppression de carte de crédit dans PAY.JP
Implémenter la fonction d'application dans Rails
[Rails] Implémentez la fonction d'achat de produits avec une carte de crédit enregistrée auprès de PAY.JP
Implémenter une fonction de connexion simple dans Rails
[Rails] Fonction de commentaire (enregistrement / affichage / suppression)
Implémenter la fonction de téléchargement CSV dans Rails
Implémenter la fonction d'enregistrement des utilisateurs et la fonction d'enregistrement de l'entreprise séparément dans Rails concevoir
Mettre en œuvre la fonction de classement par étoiles en utilisant Raty dans Rails 6
Markdown implémenté dans Rails
Payjp.js V2 avec Rails Implémentation de la fonction d'enregistrement de carte de crédit Application Flima
Implémenter la fonction de recherche de publication dans l'application Rails (méthode where)
Introduisons la fonction de carte de crédit en utilisant payjp (préparation)
Utilisation de l'API PAY.JP avec Rails ~ Enregistrement de la carte ~ (payjp.js v2)
[Rails] Implémenter la fonction de recherche d'utilisateurs
Implémenter l'authentification LTI dans Rails
[Rails] Implémenter la fonction de publication d'images
Implémentez la fonction de connexion dans Rails simplement avec le nom et le mot de passe (1)
Implémentez la fonction de connexion dans Rails simplement avec juste un nom et un mot de passe (2)
[Rails] Implémenter la fonction de fin d'événement (suppression logique) en utilisant la paranoïa (gem)
Implémentez la fonction de connexion simplement avec le nom et le mot de passe dans Rails (3)
[Rails] Un moyen simple d'implémenter une fonction d'auto-introduction dans votre profil
J'ai essayé d'implémenter le traitement Ajax de la fonction similaire dans Rails
Ajoutez une fonction de recherche dans Rails.
Implémenter la fonction PHP implode en Java
Implémenter un formulaire de contact dans Rails
Les rails 6 (avec Webpacker en standard) implémentent la fonction de classement par étoiles
[Rails] J'écrirai très attentivement le mécanisme et la méthode d'utilisation de payjp (API) (enregistrement Kureka)
[Rails] Restrictions de fonction dans l'appareil (connexion / déconnexion)
Comment implémenter la fonctionnalité de classement dans Rails
Implémenter des transitions de boutons à l'aide de link_to dans Rails
[Ruby on Rails] Suppression logique (fonction de retrait)
Créer une fonction d'authentification dans l'application Rails à l'aide de devise
Fonction de publication implémentée par communication asynchrone dans Rails
Comment implémenter une fonctionnalité similaire dans Rails
Implémenter des itérations dans View en rendant une collection [Rails]
[Rails] Introduction de pay.jp (de la personnalisation de la vue à l'enregistrement)
Fonction de notification simple dans Rails (uniquement lorsqu'elle est suivie)