diff --git a/Gemfile b/Gemfile index f4578466..6541fca2 100644 --- a/Gemfile +++ b/Gemfile @@ -35,12 +35,8 @@ gem 'draper' # 회원인증 및 권한설정을 위한 젬 gem 'cancancan' # 권한설정 -# 회원가입 및 인증 -# 21년 1월 27일 현재, devise 젬 자체적으로 릴리즈에 문제가 있어 오류가 발생합니다. -# 스택오버플로우를 참고하여 devise젬 메인테이너가 제공하는 임시 해결법을 적용했습니다. -# https://stackoverflow.com/questions/65702896/latest-omniauth-facebook-gem-breaks-devise (feat: lucas) gem 'authority' # 권한설정 -gem 'devise', github: 'heartcombo/devise', branch: 'ca-omniauth-2' +gem 'devise' gem 'devise-jwt' # jwt 사용 gem 'jwt' gem 'letter_opener', group: :development # 개발 모드에서 이메일을 보내지 않고 브라우저에서 미리보기하는 젬 diff --git a/app/models/country.rb b/app/models/country.rb index 230d5735..02622054 100644 --- a/app/models/country.rb +++ b/app/models/country.rb @@ -35,6 +35,10 @@ def self.jp @jp ||= find_by(short_name: 'jp') end + def self.cl + @cl ||= find_by(short_name: 'cl') + end + def self.undef where(short_name: nil) end @@ -62,7 +66,8 @@ def self.seed_data { name: 'vietnam', name_ko: '베트남', locale: 'vi', short_name: 'vn', iso_code: 'VND' }, { name: 'thailand', name_ko: '태국', locale: 'th', short_name: 'th', iso_code: 'THB' }, { name: 'korea', name_ko: '한국', locale: 'ko', short_name: 'kr', iso_code: 'KRW' }, - { name: 'japan', name_ko: '일본', locale: 'ja', short_name: 'jp', iso_code: 'JPY' } + { name: 'japan', name_ko: '일본', locale: 'ja', short_name: 'jp', iso_code: 'JPY' }, + { name: 'chile', name_ko: '칠레', locale: 'es', short_name: 'cl', iso_code: 'CLP' } ] end end diff --git a/app/models/external_channel/order_info.rb b/app/models/external_channel/order_info.rb index e1b1f55a..a8c48768 100644 --- a/app/models/external_channel/order_info.rb +++ b/app/models/external_channel/order_info.rb @@ -27,13 +27,11 @@ # # Indexes # -# ex_order_info_channel (channel) -# ex_order_info_ex_o_id (external_channel_order_id) -# ex_order_info_o_id_c_id (external_channel_order_id,country_id) -# ex_order_info_o_id_channel (external_channel_order_id,channel) -# index_external_channel_order_infos_on_channel (channel) -# index_external_channel_order_infos_on_country_id (country_id) -# index_external_channel_order_infos_on_external_channel_order_id (external_channel_order_id) +# ex_order_info_channel (channel) +# ex_order_info_ex_o_id (external_channel_order_id) +# ex_order_info_o_id_c_id (external_channel_order_id,country_id) +# ex_order_info_o_id_channel (external_channel_order_id,channel) +# index_external_channel_order_infos_on_country_id (country_id) # # Foreign Keys # diff --git a/app/models/nation_record.rb b/app/models/nation_record.rb index 85da1143..6ca50dc2 100644 --- a/app/models/nation_record.rb +++ b/app/models/nation_record.rb @@ -7,6 +7,7 @@ class NationRecord < ApplicationRecord scope :vn, -> { unscoped.includes(:country).where(country: Country.vn) } scope :kr, -> { unscoped.includes(:country).where(country: Country.kr) } scope :jp, -> { unscoped.includes(:country).where(country: Country.jp) } + scope :cl, -> { unscoped.includes(:country).where(country: Country.cl) } scope :undef, -> { unscoped.includes(:country).where(country: Country.undef) } scope :at, ->(key) { unscoped.includes(:country).where(country: Country.at(key)) } scope :global, -> { unscoped.includes(:country).where(country: Country.all) } diff --git a/app/models/payment.rb b/app/models/payment.rb index 8ce2a814..911043b6 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -4,7 +4,7 @@ # # id :bigint not null, primary key # amount :integer -# cancel_message :text(16777215) +# cancel_message :text(65535) # cancelled :boolean default(FALSE), not null # delivery_amount :integer # expire_at :datetime @@ -16,17 +16,20 @@ # created_at :datetime not null # updated_at :datetime not null # charge_id :string(255) +# country_id :bigint # order_info_id :bigint # # Indexes # +# index_payments_on_country_id (country_id) # index_payments_on_order_info_id (order_info_id) # # Foreign Keys # +# fk_rails_... (country_id => countries.id) # fk_rails_... (order_info_id => order_infos.id) # -class Payment < ApplicationRecord +class Payment < NationRecord STATUS = %w[ pay_wait @@ -35,11 +38,30 @@ class Payment < ApplicationRecord refund_complete refund_reject ].freeze + enum status: STATUS.to_echo act_as_status_loggable status_list: STATUS.to_echo + PAY_METHODS = %w[ + bank + cod + omise + iamport + momo_pay + vn_pay + ].freeze + enum pay_method: PAY_METHODS.to_echo + + PAY_METHODS_VIA_PG = %w[ + omise + iamport + momo_pay + vn_pay + ].freeze + extend_has_many_attached :pay_slips belongs_to :order_info has_one :user, through: :order_info + has_many :payment_charges, :class_name => 'Payment::Charge', as: :charge validates_presence_of :order_info diff --git a/app/models/payment/charge.rb b/app/models/payment/charge.rb new file mode 100644 index 00000000..46620ed0 --- /dev/null +++ b/app/models/payment/charge.rb @@ -0,0 +1,40 @@ +# == Schema Information +# +# Table name: payment_charges +# +# id :bigint not null, primary key +# pg_name :string(255) not null +# statement :text(65535) +# status :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# country_id :bigint +# external_charge_id :string(255) +# payment_id :bigint +# +# Indexes +# +# index_payment_charges_on_country_id (country_id) +# index_payment_charges_on_payment_id (payment_id) +# +# Foreign Keys +# +# fk_rails_... (country_id => countries.id) +# fk_rails_... (payment_id => payments.id) +# +class Payment::Charge < NationRecord + STATUS = %w[ + pending + paid + expired + refunded + ].freeze + enum status: STATUS.to_echo + + belongs_to :payment + + def statement + JSON.parse self[:statement] if self[:statement] + end + +end diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index dc76ba95..a110c025 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -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--lYy0X0Jm40ShaKzV--PlBJs8h3AcV8OoAGRyvG0Q== \ No newline at end of file +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--bwWDnzwexVFgVuB+--65DhipeWvNZbA/Gg5sY+Ng== \ No newline at end of file diff --git a/config/credentials/development.yml.enc b/config/credentials/development.yml.enc index 6a1f4f23..6b974aad 100644 --- a/config/credentials/development.yml.enc +++ b/config/credentials/development.yml.enc @@ -1 +1 @@ -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--gwpfxe9Z3nus1NXV--L3IbXLzQZLw3BaKIkOHTmQ== \ No newline at end of file +daeBkj4z+wQ/enaf5H6sUAlyLhYA04A9kjKYTmxjp8JCpF05YDE4iYW+o33wI9TAYDYor7RcSF/Vnm64UewEuQkQn95eUhxBg4O6uXDF3McoRwvF6bkdIiPW8qeMdYJ2betpA0GqSejdan0MKeSNGAecHt8CLno3ShWdDhRnK0XqIBK2pN5tdxlEKnkNwB1/OAyYmwcMvZ7eeOHiuc4Wsgmr6RiywEsDh5ACVd+OPdnZpSm2EwsOiP6+WIElnAwVgB80BZLmzmV54o5h0ztVluCdS7680KWmk3GwQxa7oHTvY22uLE5LHeqMz4Cfz9MmXEgSWuUqnWKDQT+X4ODqywLK/4t5jniErqjdcTnnxXnjoCQuDZ9PkedwZO9YHadMZaXvqwmFnoFGWUbCjKg4FsuNuITUhbBR8D48GxAUMhxYmdmXD2/4rcW1lM/srS642UNn2u5JnceCvbAkoZ+8vcmEWZ8EHaWwpelfFHJEvc+RRJaokeR7WFULE5Di3eYtsXUuBpXQ1xPeLpKbNNFM+KVn5z0WViw/IWOdE+npE/iXx1KvSpfccVFeU9itjJYrV9IjNb9NeC9HfDMm3+yCrYB6vhVLgNFRNKgtvTHFJew7PPONeJQEO0/DvKlTeHcPZC0DAhLFtMAPq90ZOuikRO5lVVj6vq3O9sdZtl04GhiIHQ72eBDhy6DNz+HmwF4Hnv16CfetD1/hAwwu8EuZwwyaXWaimrtHDcexBEzHsgabuhsu2n1u3Jo/P5aAbm0n0Tmjd5V9TJRaizYqHQCx+8FxT8APhQbZJ7izB942qqeY7yE+Ts4stzgPl7IRdxL5OXtey6aWXnMiCXtWHVMymyDFf9zgDKyCXOTtgUMzkTaldOvS2uNspKYcyHNoHaN97YlNnDM3dC/c6S7kILWJOk3ceW4bONIpgAmyG4VoDwQgH6FjMG6TyOfOgpkREJF3C4dlxWVd4WC8cdQ0fXMCCuJpfhKOvWmW4iQ9CqWe/1FGbilboeHM58p6pYZC2jFSSt99lBj0KnUI5gjmiDA8zKQWv69zsNJMUqeD580twTnVDatrR98TXJGL/sjJhrj9FoZzlswxLWCCi5fRY4UQNoVcH8RGxzkor53KqeQtTmDm7SZ8rSUWoGpsUP2qOGsxrp/pjm1PZAlDJNhNfaaIMgcj39nxVmkYnd8t7yjJHEiT+QCt5glNYipIoiAY+W1HEdeKM7CVrs3G+C/XOKXfzWcJqY1drqxoV9ou2MBcuyAKkr4eLM6JE3mgYpo4V5GHe+vfVwPrNRTQ6Neijawf6tb7y7qjI7WCnVlSTO3+BReMaoFcJE3aAfSHTTv0ui6RIjBBMAfKePQ8CgmQdXBSKDG9lnvS8XWXzJ8+te4pOTmXX7/ulyqMjb7x36Ot1tnlmIK901YcAJpUap0Iwiog+PfCMNPTAeSrsWBTP0/6Dg7DTRRrhUt6w3kPZwgcP435BohHoQf0Y6zrbA72B/wVDYUrqHuqmqBvvOLLPjVzbvEko3qH57LuX8i944lqyHTPJANaQ1GDqaOTlJ8MureiMWcbGvGB2WD6YxEsJ4Zb5pQuKryMTuS9RnctZ3fbyu2EyB3R7l6ihwRC1ZbEGBgxCAMFDGJopp1uXcU8ko3G2/NZ3lk49l6oZi4tptq95QqNhF2Q9IlIRgNRLqP94SdFwH55nu7Rmb61rT7wTCG31WdO9XlWPulhvM7n8XRqbi3VB6YA4tcPpwfXo+vGMjth0vXHPy8sXwkZTM6ITrQr8HU/X6yY0xUL3e6CZfv9J+CoX7Ump/fG5QH+vVmDWiCZGZkZFnZN3k0lbX9JfU8b3zQSakL2evB6iBUnkgcUfpoY5I396qUJrYqPlEbhUmLyHbgf6SWkDqyBDprXbPfGnWzo1iT6QciifvgorcU4AjEQD76F9FudcwK3NMWlL7YDdloygAqT937f7lfa/JsS1FteWaxrBE2USeJ3IoJJoikw1VarmGJuWhUFr+zky38d8rjDU8S6IiWIew1hpa7MGP4v8b5alc+6G2huxksfgR/lAgdBP9ApgpnCTBiVw/EvQM8I3t0PFTPfGx2h9lODoL3JHCdNT9LwIiP3fe5UGs1JUyVf6N5FyK5jE+T/JrGw9e3Fse5dH31f7Sr+ZkoqVJcMajlq5mM6bjABp+jicDXo75WIifOl9oN+dY2rE7qGtY9ASe/0xICaxBPAxlZwANy5lNsnCSnayKROyYgVG8+b2w+Mqc6PT6uczJdHtcDdm8Yh/C02xKx029EYxSQQ/VhmPBt4P9aUMz6BawdBtJRCvbC9a14TrUipVx0D81ag9uChoB3eRuxrps/7NqIfrCIAmKG60Csev74pJhLjiOdYUsN2iKwb0D9vr6A4BpdBfHfvs3Hb/Ne2LWkozS44xou5KrnFj9KpdxoH1iuaCGMzcrcCeOx0AXMOc6m19p43zJFuIdS+V3JyN1XHggwSdse8GbSH1bpPlpdZHSElJC4/iqjN9X3AzsAhpjuCJWAry7NM/wMonhuxzjhI5/IxKNtU9lkazdiGDSbTTDkqmDzlsBirbhg4vBawDhrY6xRQXFtKkn4dBN74mv6bGdnTvBGp0lygRpf72gNAEIjvcaGgcdqRIcJ4txSo1hRK85tC7nCCmEm6dnpL33IeB49DXU0cAV371/LygomGo3KdpcSXF5coM1M0dvoNVMu6PWqyZpdObvxWaAzcnpkFRvUwQ7OgFvALUgVa8DrmNTe1jUOCaKC5Fl9VSbpmIUpQDUa2ruSv2kuMNFz736yKEQoFkZx8IOhu5eiQ0jf8MLAFgJ+eJQd3Ojw=--PYg+PQYt02D36cA3--4eLItr01OVU/960MDFKELA== \ No newline at end of file diff --git a/config/credentials/staging.yml.enc b/config/credentials/staging.yml.enc index 739688cf..b54de16f 100644 --- a/config/credentials/staging.yml.enc +++ b/config/credentials/staging.yml.enc @@ -1 +1 @@ -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--u5kWFMp+vIiAgdTQ--7k3kF4H/XNZ1Yj+eEk/KOg== \ No newline at end of file +3/hM9wLpQPVPwi/3QqLiYYuJm+9iGlaV3Z4dkd2Qv6P/ktZk0YfT4JvzMlvwPv+8WY64Qfq5+jxjpAKAQ8XbF8cMXwiQltv7DuCJRjlKZn7ERU+J44z7TxgWQAUStAzK7VGqQM5JMEKxQ4vSvUwTXYeRYr3p0xAhn42QK2wR+vv4YsyRVp5U2jR0Yy257WdvkZcwVM4H1AjkTbW491ba28MXe72fgRFombm118/tTMEl2d3Oi/8LWCCsgBLKP5ItUYN/yN7hTB8eSbVY26pXOppC6vudBvZtwOABRYByHMO6QNBG+tNm3xxlTUlencdeSDkpIkLAtdqCYN/fqIXLxWOEgKWeVYzPcjXuFbXP1ULLyw/Elta1zVg2Yq3IUfhfaDC5fKSNlEVo7VPfJHAHmf+7t+sRx+90bahtUuH6liRNleEtRl9iu3ANrWEfmuXxhNJ1YYUV8Y02bpZ7NrQLJsocpifTKndwEYaiIbApcA6El1QHZ2ek/KVbXXwOdNk6XM5iUggLJWdE4MS2gjMmtN3XdQAAYl/A+sMe7i1l+GYQbHFnlLM5MXmc8NcJ2SmWxMY4MZy5y4PvW1t2x3lKuBMFf/6O4hz4K76MJvMe/u4ppQ3qG97IxhMarVKl3piyNQbibCBOiuWp+OUhauZzFhJ2GNUE+0uilXYIJQtu/u0An6U710MqSh6b1Ly3CCHp+THucoXNj1gNv+rZWjOawg0w1BtEP43YknOz4Sq3eRe24UvfvtZhIqU79KznPVRb+IhLoPUC2zBKzqYAzSYHjeoqbwCWOIPcqQ4rStGvcklXQqJHGPzuxmq7K0kO8XDXML/EAx9HjFUlxWGkGdyGe+KKNaoZeZE4E4+pAPgh6rxVid/Og0oEW0qVDPp6B0jE/h8+/4pln8pnp778KK1VhXAU/gWpHiUR40MorJIflMXQldmXW5pTEAp2o6tbI04MhRFK3Ss5OL+1Sz9eWBQ4037KPvQJHkUlVbuIOnUsncnFIaEKIbyUvEE2mi8Vee80upfmcoFOJd7fDtDvMBfx6U34u6Yd725KHgbfjM8n8LQKWi5+wAozy7ygYn1yRwLmCqPzFwlfUCQPzrHAc1NHyVKqtFXaX8ezS1B+YJh/PQGLWulKOC75eSiGyHxPdBwX3V8U3ByZSeYRIGZMnLDktD+BhZiArAxewG8g62QWvp5eW1b1HT877Bb5ZqMRJ5yOzyMS+Ltfd2JdAh0LK9YzZ+M3w2fCw1SCxxRoD+IkyHAmwF9iwtRGQ/omP6OYz5DWmPg8AaJjXI2V95cwB37ei8g6FnUwwDw26wGDt6CXj63kaW8sHs1lnIycv1yqIqnQmTl9YrzZNnd0iynJx1V0S0jq1EqwMGQe68WBTwFtEHSxhTm8uqY/orCWms1KvPzUfEVh3klauz3IjpzPKn13hifssGYhdIG4Fn+Nlwe5mYttJzkpDNJRLS8p9u8Ng7iXeinhRW0Nqg1W6SRIxN5c+y4AqHlflSGcYmRyGDWyChzw6WAJ2JPoGY/m5te7+blvtLO8LJxWSHh569LyshRinUktwepDTcufEZylz6D0YE7p1k8Njzm0GzP+yHblFM2l3eGqnWVWPBQ+2EdANzZbCK0zunoXypnKPYD5bAKNs2LZI4dnoWTEWDMM4yQDCEay/2+pjtyyR/KMChCqOgyZ6YGw5+O9I+IRVNN9wJAg8i4HKNHCXB9knl73UCWjNet1zp62FHJEhwoBbsM9+p95UCqAwyDvKhHoBHEzmVafD5W9OaHeTIRFyWyRdiFJQal6kv1AXZHWhwNc9dC0Y67QVFixRWCsn5b26TYYsL4EDp3ImsCnoPdUQBIdEB0yR00mUKr/e6PZlUXfBn1xD0CIuon9S5qBgY/FT+RL0fkf1vV99/SKD0IqSlSlZTTApdMFUAlNwKd7K9SjXuu/Euhpv0k7NoIMjP6KveSPnZ77cM97MoCb77cjFxVwijBounTJxxOF73H4L2ntuU2y4g3V8IXbSJbMvZ+1h/DOV0XJFb+bqSoUcKFo4Ip2TsCl7/gpasJKc3woYk7ox3WU9Ce5t3qGdI022jcky6/D09OrSRdteW+NzjNKuhAsQQMb5ktl+21q7IqPhF/Yc3SdH5rNsKnlCgvC7yIMKvuZ2mr4tohjoziKX+bzWtyqFeCwLAnM2Z4nL4QdCK2RRNCv2aBzAgDU8BFWSsF9iuwvrh2/WblXNFkKW2sUht57p/JxRESXt4ax62+lyaU1gxEBQv+UM+OZGWLKc5EvEYot5K+310bFTIudyR29zgVuI/1WaPV3BPLdPNNxvDLhfzFpbc3XtDCuYC/nXK5Sd15THSbZY0/FXSiFt6pBnS4/NJofZGxbMPXxRBJuQ8cJozaBOzdSjMS3icP35Ku9ZywAYT9NkkMD+sugGtVYf48J5DAiaqYn+bAjOcNRpxs8K9OBuIqluo7/Rx1kj09pkA+gmdDIxasxjOASANgw4CGS74bHiezMhUMQdyiFuMXZBEDuNYL8FCrDqxYJ/FuGw9bj9VIZ47H9KOFs9dZ4SakbzBXUIl5OsR2uHMVPJPe9KMjs3ma39D9opemLXoIlrG67MuMapSYSNI53VnqsnkMieXuGnQ6rMF48ImoZmY4/9tIMXTJjVmvRfMNDSxZ8L6p9DhqsJKsYo0ghSbvwdWk8wN6c7o1wtNK7a4F35LHpcfo72bxkazLU4/wVFXWkYz1CdJzUDZYgS/GYrGuowX4o8IiDKQWrrXB1ALYNIGr5dyslmw8yFKiV/c45y3RhPjW2xawErwLsVu8gc6wsfVD7EhDRIt+AZpnPahlEq8RorITZaJ0Mmn5ZpDWV5yAn7kqulTe5jMFRPHBiSgPmfvVoXkwiBt0I7TDevF6uFcjawEkNG2iM7H6hS1XpaEJ15Ly29VnlToFC1qqwSni3Cv5Ikj1I0L/usF7W4PwTIbWw9BusrEsW75787z58bA5PCdvwbJWyZOVd1e5lThXUH26xX1zOzp+DRrYexpiUqgAFxKZ327wgUsbzt49PXDP64tNv44+5Yztirto9RykCYcKjqQN1XoMn3wea/k+gfCZBXMnSz3QBDiro9FoNEepVTgsnJ8hiU1VbqVE/WezW/5MIMlo1KnkIZYbdOR4GxmvuKMNbQCDwJmLNuJGdLL4rujWTUcutkotDgZ1LP4P3RmpOt1V5t51b+3eflwTqoPQT8lBTyc2f9z/Mrx8u73P07DClBYtJZrVBK755uh7gb5n5rCWNbJJ8vl2NLRDzZoWotwLHjuwKMfRTZ12M5gL2dji1fh6ry4sZljnc2MTUd9y+8IlWUc+s6/oBHqnbg7YWh9BFYYIRGX9QFlr4JU3VXZNxuOlBdWxeEDWS3XKReOlgD+JANvJH0rKlRdB6gdVDlSBL0e7uEFzszMMURuOZPg+HHgXnaGNRwJ5EgGtAaVX7AhvD7GCpwjwsso3LVWeuqQAEF1k25oEtp+WYy7BeSyYlLU7QRCqEwaNe8x4P0V+Y6bYNX1X0McFAsBw8YwA8pqMYU0v8iJz4xxOaBfUcuyw0gDlrqgsbdJu6Yqt5r50q7RiCIPLPCt9RQ7y7TTUKczRKzU9bGr4=--kj3GDAkDhaW+9bdr--oZTd5DzkOesGQkCkWap5Lg== \ No newline at end of file diff --git a/db/data/20210610025720_set_country_for_payment.rb b/db/data/20210610025720_set_country_for_payment.rb new file mode 100644 index 00000000..b1ed1d99 --- /dev/null +++ b/db/data/20210610025720_set_country_for_payment.rb @@ -0,0 +1,20 @@ +class SetCountryForPayment < ActiveRecord::Migration[6.0] + def up + all_payment = Payment.all + count = all_payment.count + all_payment.each_with_index do |payment, index| + if payment.order_info.nil? + payment.destroy! + ap "payment(id: #{payment.id}) is deleted. [ #{index} / #{count} ]" + next + end + payment.update(country: payment.order_info.country) + print "payment(id: #{payment.id}) is updated. [ #{index} / #{count} ] \r" + end + puts '' + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/data/20210610028057_redefine_pay_method_for_payment.rb b/db/data/20210610028057_redefine_pay_method_for_payment.rb new file mode 100644 index 00000000..19a1ecff --- /dev/null +++ b/db/data/20210610028057_redefine_pay_method_for_payment.rb @@ -0,0 +1,9 @@ +class RedefinePayMethodForPayment < ActiveRecord::Migration[6.0] + def up + Payment.where(pay_method: 'card').update_all(pay_method: :omise, updated_at: DateTime.now) + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/data/20210610045910_set_charge_for_current_payment.rb b/db/data/20210610045910_set_charge_for_current_payment.rb new file mode 100644 index 00000000..9c38f6aa --- /dev/null +++ b/db/data/20210610045910_set_charge_for_current_payment.rb @@ -0,0 +1,153 @@ +class SetChargeForCurrentPayment < ActiveRecord::Migration[6.0] + # omise_payment = pay_method가 card인 payment + # charge id가 0이면 manual order info + # charge id + def up + init_omise_api + # paid가 nil인 주문이 있어서 마이그레이션이 불가한 것을 고치기 위한 코드. 프로덕션 환경에서 해당하는 레코드는 1건입니다. id: 4379 + Payment.where(paid: nil).update_all(paid: false) + + # omise로 결제된 payment들을 가지고 옵니다. + omise_payment = Payment.where(pay_method: 'omise').where.not(charge_id: [nil, '0']) + total_count = omise_payment.count + ap "#{total_count} payment will be processed." + pending_msg = ' Create the pending charge.'.to_sym + paid_msg = ' Create the paid charge.'.to_sym + refund_msg = ' Create the refunded charge.'.to_sym + expired_msg = ' Create the expired charge.'.to_sym + ApplicationRecord.transaction do + omise_payment.each_with_index do |payment, index| + ap "Payment(id: #{payment.id}) is being processed.. [#{index} / #{total_count}]" + # 필요한 데이터들을 준비합니다. + pg_name = payment.pay_method + pg_id = payment.charge_id + # 하나의 payment에 따른 모든 charge의 공동 속성 + common_charge_attributes = { + payment: payment, + pg_name: pg_name, + external_charge_id: pg_id + } + # omise에서 charge를 불러와서 소스를 만들고, 그게 안되면 다른 데이터로 소스를 만듭니다. + statement_resources = fetch_statement(payment, pg_id) + + # pending 상태의 charge가 가지는 statement를 구성합니다. + pending_statement_keys = [:amount, :pay_request_url, :request_url_expire_time, :card] + pending_statement = statement_resources.clone.keep_if { |k, _| pending_statement_keys.include?(k) }.to_json + + # 데이터들을 모아 pending 상태의 charge를 만듭니다. + Payment::Charge.create( + **common_charge_attributes, + status: Payment::Charge.statuses[:pending], + created_at: payment.created_at, + statement: pending_statement + ) + ap pending_msg + + # 결제가 완료된 payment이면, paid상태의 charge를 생성합니다. + if payment.paid + paid_statement_keys = [:amount, :card] + paid_statement = statement_resources.clone.keep_if { |k, _| paid_statement_keys.include?(k) }.to_json + Payment::Charge.create( + **common_charge_attributes, + status: Payment::Charge.statuses[:paid], + created_at: payment.paid_at, + statement: paid_statement + ) + ap paid_msg + end + + # 결제가 완료되지 않고 expire 되었으면, expired 상태의 charge를 생성합니다. + # exire_at이 없는 주문은 정상 주문이 아니므로 마찬가지로 expired시킵니다. + if !payment.paid && (payment.expire_at.nil? || payment.expire_at < DateTime.now) + Payment::Charge.create( + **common_charge_attributes, + status: Payment::Charge.statuses[:expired], + created_at: payment.expire_at + ) + ap expired_msg + end + + # 결제가 완료 되었지만 refund되었으면, refunded 상태의 charge를 생성합니다. + if payment.paid && payment.cancelled + refund_log = payment.status_logs.where(code: Payment.statuses['refund_complete']).last + if refund_log + refunded_statement_keys = [:amount] + refunded_statement = statement_resources.clone.keep_if { |k, _| refunded_statement_keys.include?(k) }.to_json + Payment::Charge.create( + **common_charge_attributes, + status: Payment::Charge.statuses[:refunded], + created_at: refund_log.created_at, + statement: refunded_statement + ) + end + ap refund_msg + end + end + end + end + + def down + raise ActiveRecord::IrreversibleMigration + end + + def fetch_statement(payment, pg_id, tried=1) + begin + omise_charge = get_omise_charge(pg_id) + build_statement_hash_from(omise_charge) + rescue Omise::Error => e + raise e if e.code != 'not_found' + { + amount: payment.amount, + pay_request_url: 'staging.test.charge.url', + request_url_expire_time: 30.minutes, + card: { + card_name: 'visa', + year: '22', + month: '11', + id: 'test_card_id', + card_number: '**** **** **** ****', + name: 'test_name' + } + } + rescue NoMethodError => e + wait_cool_down(tried) + fetch_statement(payment, pg_id, (tried + 1)) + end + end + + def build_statement_hash_from(omise_charge) + card_info = omise_charge.card.as_json + { + amount: omise_charge.amount, + pay_request_url: omise_charge.authorize_uri, + request_url_expire_time: 30.minutes, + card: { + card_name: card_info.dig('brand'), + year: card_info.dig('expiration_year'), + month: card_info.dig('expiration_month'), + id: card_info.dig('id'), + card_number: [card_info.dig('first_digits') || '****', ' **** **** ', card_info.dig('last_digits') || '****'].join, + name: card_info.dig('name') + } + } + end + + def wait_cool_down(tried) + ap "Omise api seems like tired.." + spin_particles = [ '⎮', '/', '-', '\\'] * 3 + (tried**2).times do + spin_particles.each do |particle| + print "#{particle} \r" + sleep 0.3 + end + end + end + + def get_omise_charge(charge_id) + Omise::Charge.retrieve(charge_id) + end + + def init_omise_api + Omise.secret_api_key = Rails.application.credentials.dig(:omise, :sec_key) + end +end diff --git a/db/data/20210714051517_add_country_for_chile.rb b/db/data/20210714051517_add_country_for_chile.rb new file mode 100644 index 00000000..4baa0e4e --- /dev/null +++ b/db/data/20210714051517_add_country_for_chile.rb @@ -0,0 +1,9 @@ +class AddCountryForChile < ActiveRecord::Migration[6.0] + def up + Country.find_or_create_by(name: 'chile', name_ko: '칠레', locale: 'es', short_name: 'cl', iso_code: 'CLP') + end + + def down + Country.find_by_name(name: 'chile').delete + end +end diff --git a/db/migrate/20210610030630_create_payment_charges.rb b/db/migrate/20210610030630_create_payment_charges.rb new file mode 100644 index 00000000..ff504b7f --- /dev/null +++ b/db/migrate/20210610030630_create_payment_charges.rb @@ -0,0 +1,14 @@ +class CreatePaymentCharges < ActiveRecord::Migration[6.0] + def change + create_table :payment_charges do |t| + t.string :pg_name, null: false + t.string :external_charge_id + t.string :status, null: false + t.text :statement + t.references :payment, foreign_key: true + t.references :country, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/migrate/payment/20210610025604_add_country_for_payment.rb b/db/migrate/payment/20210610025604_add_country_for_payment.rb new file mode 100644 index 00000000..e7838afb --- /dev/null +++ b/db/migrate/payment/20210610025604_add_country_for_payment.rb @@ -0,0 +1,5 @@ +class AddCountryForPayment < ActiveRecord::Migration[6.0] + def change + add_reference :payments, :country, foreign_key: true + end +end diff --git a/db/seed/country.rb b/db/seed/country.rb index 86d70633..e52cab30 100644 --- a/db/seed/country.rb +++ b/db/seed/country.rb @@ -2,3 +2,4 @@ Country.find_or_create_by(name: 'vietnam', name_ko: '베트남', locale: 'vi', short_name: 'vn', iso_code: 'VND') Country.find_or_create_by(name: 'korea', name_ko: '한국', locale: 'ko', short_name: 'kr', iso_code: 'KRW') Country.find_or_create_by(name: 'japan', name_ko: '일본', locale: 'ja', short_name: 'jp', iso_code: 'JPY') +Country.find_or_create_by(name: 'chile', name_ko: '칠레', locale: 'es', short_name: 'cl', iso_code: 'CLP') diff --git a/spec/models/payment/charge_spec.rb b/spec/models/payment/charge_spec.rb new file mode 100644 index 00000000..a1ecec99 --- /dev/null +++ b/spec/models/payment/charge_spec.rb @@ -0,0 +1,29 @@ +# == Schema Information +# +# Table name: payment_charges +# +# id :bigint not null, primary key +# pg_name :string(255) not null +# statement :text(65535) +# status :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# country_id :bigint +# external_charge_id :string(255) +# payment_id :bigint +# +# Indexes +# +# index_payment_charges_on_country_id (country_id) +# index_payment_charges_on_payment_id (payment_id) +# +# Foreign Keys +# +# fk_rails_... (country_id => countries.id) +# fk_rails_... (payment_id => payments.id) +# +require 'rails_helper' + +RSpec.describe Payment::Charge, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/test/fixtures/external_channel_order_infos.yml b/test/fixtures/external_channel_order_infos.yml index 9c8619d6..71363e93 100644 --- a/test/fixtures/external_channel_order_infos.yml +++ b/test/fixtures/external_channel_order_infos.yml @@ -27,13 +27,11 @@ # # Indexes # -# ex_order_info_channel (channel) -# ex_order_info_ex_o_id (external_channel_order_id) -# ex_order_info_o_id_c_id (external_channel_order_id,country_id) -# ex_order_info_o_id_channel (external_channel_order_id,channel) -# index_external_channel_order_infos_on_channel (channel) -# index_external_channel_order_infos_on_country_id (country_id) -# index_external_channel_order_infos_on_external_channel_order_id (external_channel_order_id) +# ex_order_info_channel (channel) +# ex_order_info_ex_o_id (external_channel_order_id) +# ex_order_info_o_id_c_id (external_channel_order_id,country_id) +# ex_order_info_o_id_channel (external_channel_order_id,channel) +# index_external_channel_order_infos_on_country_id (country_id) # # Foreign Keys # diff --git a/test/models/external_channel/order_info_test.rb b/test/models/external_channel/order_info_test.rb index 68063e33..619a309e 100644 --- a/test/models/external_channel/order_info_test.rb +++ b/test/models/external_channel/order_info_test.rb @@ -27,13 +27,11 @@ # # Indexes # -# ex_order_info_channel (channel) -# ex_order_info_ex_o_id (external_channel_order_id) -# ex_order_info_o_id_c_id (external_channel_order_id,country_id) -# ex_order_info_o_id_channel (external_channel_order_id,channel) -# index_external_channel_order_infos_on_channel (channel) -# index_external_channel_order_infos_on_country_id (country_id) -# index_external_channel_order_infos_on_external_channel_order_id (external_channel_order_id) +# ex_order_info_channel (channel) +# ex_order_info_ex_o_id (external_channel_order_id) +# ex_order_info_o_id_c_id (external_channel_order_id,country_id) +# ex_order_info_o_id_channel (external_channel_order_id,channel) +# index_external_channel_order_infos_on_country_id (country_id) # # Foreign Keys #