From c5591b4828998848900491e4a3132bc315323f37 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Wed, 11 Apr 2018 11:55:52 +0300 Subject: [PATCH 01/16] Add EveryPay payments * Refactor BankLink into Payments::BankLink, add Payments::EveryPay * Write tests for existing invoice views * Write basic tests for Payments module --- Gemfile | 1 + Gemfile.lock | 13 +- app/assets/images/every_pay.png | Bin 0 -> 6886 bytes .../payments/callbacks_controller.rb | 8 ++ .../payments/every_pay_controller.rb | 29 +++++ .../registrar/payments_controller.rb | 30 +++-- app/models/bank_link.rb | 10 +- app/models/payments.rb | 15 +++ app/models/payments/bank_link.rb | 108 +++++++++++++++++ app/models/payments/base.rb | 49 ++++++++ app/models/payments/every_pay.rb | 111 ++++++++++++++++++ .../registrar/card_payment/complete.haml | 19 +++ app/views/registrar/card_payment/new.haml | 4 + .../invoices/partials/_banklinks.haml | 5 +- .../invoices/partials/_credit_card.haml | 7 ++ app/views/registrar/invoices/show.haml | 2 +- .../payments/every_pay/complete.haml | 19 +++ .../registrar/payments/every_pay/new.haml | 4 + app/views/registrar/payments/pay.html.haml | 18 +-- config/locales/en.yml | 1 - config/locales/registrar/invoices.en.yml | 6 + config/routes.rb | 9 +- test/fixtures/files/seb_bank_cert.pem | 16 +++ test/fixtures/files/seb_seller_key.pem | 15 +++ test/fixtures/invoices.yml | 4 + .../registrar/invoices/list_test.rb | 39 ++++++ .../invoices/new_invoice_payment_test.rb | 63 ++++++++++ .../registrar/invoices/new_test.rb | 67 +++++++++++ test/models/payments/bank_link_test.rb | 54 +++++++++ test/models/payments/every_pay_test.rb | 64 ++++++++++ test/models/payments_test.rb | 58 +++++++++ test/test_helper.rb | 1 + 32 files changed, 818 insertions(+), 31 deletions(-) create mode 100644 app/assets/images/every_pay.png create mode 100644 app/controllers/registrar/payments/callbacks_controller.rb create mode 100644 app/controllers/registrar/payments/every_pay_controller.rb create mode 100644 app/models/payments.rb create mode 100644 app/models/payments/bank_link.rb create mode 100644 app/models/payments/base.rb create mode 100644 app/models/payments/every_pay.rb create mode 100644 app/views/registrar/card_payment/complete.haml create mode 100644 app/views/registrar/card_payment/new.haml create mode 100644 app/views/registrar/invoices/partials/_credit_card.haml create mode 100644 app/views/registrar/payments/every_pay/complete.haml create mode 100644 app/views/registrar/payments/every_pay/new.haml create mode 100644 test/fixtures/files/seb_bank_cert.pem create mode 100644 test/fixtures/files/seb_seller_key.pem create mode 100644 test/integration/registrar/invoices/list_test.rb create mode 100644 test/integration/registrar/invoices/new_invoice_payment_test.rb create mode 100644 test/integration/registrar/invoices/new_test.rb create mode 100644 test/models/payments/bank_link_test.rb create mode 100644 test/models/payments/every_pay_test.rb create mode 100644 test/models/payments_test.rb diff --git a/Gemfile b/Gemfile index 9b6f97dad..6cbadebb7 100644 --- a/Gemfile +++ b/Gemfile @@ -113,6 +113,7 @@ end group :development, :test do gem 'factory_bot_rails' gem 'capybara' + gem 'capybara-selenium' gem 'rspec-rails', '~> 3.6' gem 'poltergeist' diff --git a/Gemfile.lock b/Gemfile.lock index 6d9105baf..d6c8b899d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -140,6 +140,11 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) + capybara-selenium (0.0.6) + capybara + selenium-webdriver + childprocess (0.9.0) + ffi (~> 1.0, >= 1.0.11) chronic (0.10.2) cliver (0.3.2) coderay (1.1.0) @@ -187,6 +192,7 @@ GEM factory_bot_rails (4.8.2) factory_bot (~> 4.8.2) railties (>= 3.0.0) + ffi (1.9.23) figaro (1.1.1) thor (~> 0.14) globalid (0.3.7) @@ -387,6 +393,7 @@ GEM ruby-progressbar (1.8.1) ruby_parser (3.8.4) sexp_processor (~> 4.1) + rubyzip (1.2.1) safe_yaml (1.0.4) sass (3.4.23) sass-rails (5.0.6) @@ -409,6 +416,9 @@ GEM select2-rails (3.5.9.3) thor (~> 0.14) selectize-rails (0.12.1) + selenium-webdriver (3.11.0) + childprocess (~> 0.5) + rubyzip (~> 1.2) sexp_processor (4.8.0) simplecov (0.15.1) docile (~> 1.1.0) @@ -485,6 +495,7 @@ DEPENDENCIES bundler-audit cancancan (= 1.11.0) capybara + capybara-selenium coderay (= 1.1.0) coffee-rails (= 4.1.0) countries @@ -542,4 +553,4 @@ DEPENDENCIES whenever (= 0.9.4) BUNDLED WITH - 1.14.6 + 1.16.1 diff --git a/app/assets/images/every_pay.png b/app/assets/images/every_pay.png new file mode 100644 index 0000000000000000000000000000000000000000..fcd4a2c673d8753416dd9ab25813ea7ae9f70b07 GIT binary patch literal 6886 zcmZ`;Ra9I-wk5%#aRQA5X&f4NcXtUA+|xKTZo!?#gIi-saCg_>2@oU@pn(7Zf?I&_ z$jrQXvu3S#*Q#4pyY}9v&N=t*#%gIO;$V?uAt52*C@ab7Jk4*O1~mrS(;HhfX6b1{ zv6ohtMnbAj!oIgeecIDlE9s~sA^9^RA%#RBA^m=WLiUi5ytt5%ep(O%9^*V4+>%TpW#`Wxuq&p+?!394~Xqket*OKoByBKfAh88xO%!i)!GAMt?c4y>+uxqU+Vw8;Q!C~mzNml-*Wv& z`Tp6Pf1ppzk-!q;{CA@zu<+zr(~yvW^2&13dT&stUSs;c8t#6~hhA@gKct|wp|y;z z3$J?4s$;^Y%A#rP?6@$~^TpmcXr|?7rD}EXaQK~!63c#Ft+y?@-{@t4EV|+ z;E3d%A3uIw7hK=Xd{TE&+P1vwsnzh9nasYOd29FQZj$mSMbUt)gl!@@`$t%fF%oh} z`DrnhsW317;->%*!^XDhcq(DtC)*FIrE-NRfpD`k8zDcV9A$nPmzUwzF7!Y--gmZ=m0Bu$Ot zV}7s(n?1|p6TaRIS$|% zOos5+_Jynd&=~4@SP;@)1XQfy(m_%mHf}NvASR|2k|Er5@!Cd4p-C;jw(}ykMQl}- z-lwILztxx9!nFF-G}X}bqwbK-Bn>2d=P(e(JVM4TKjx2s@Hp*-uUX^|IonitV!zqb;HQv%5+gzp z+_h)^?EX=}5o||8m9&+SDS+rfH=_-c`Lm>3wmt0i>M}PUZ*`f=zL$yaoq%#|Y_6-g zrqQ8<*u$at%}8pzB{Sni6BdD7Cq2_d2YH*uyVXE14D0j^j4iZk9P4I(032omeCc!! znw};Y#O!?+nP#(NX|t*QhkR3xoa{ZB`_Pfdms`;fK%xP>+7kr)3!~n4fpmFAdluR6f1ox()T%^EFxz&%*;bVdEVEH-o)^xTG`vYMQUl`uO^RlCp4 zgp2)UetsUxdQY4(N%D_+s|gY|u>xY1`mv%(0lyKryto&rggccsX@=1u0*|(8Hit{G zR>A$AS7=PQp4_U2xK_S+td8=CI4;&sq@H~?$_hJb(~K_3q+I_N!S~92wY!vHozgt~ z?7o|x@tHi9P3l>ioYD9xU$NL7^A7-OO}-dD1s>k07bj_P4a19_Y;L{Quobq(!)~m7 zjY>$lp&FOs>}Ddong1h6!J9kQ9W)k51E`d*_pzPfy)}nnmaY`h*Ef5>l3Vv^TXY5a z>wX34#N@DN4hhp7Dx)2Toe6LtHB)Sp5Z2Z!!wA*{RchEHq%bBa&)ccTnc5C_*^-B$ zDoqeqMO?8YDq9&PGN;cS(9kCnBV+I~TQ8byNA@IlaTI|^y$uJkMU}9_m4kEz!&7tB zJ{*2f1{)Yf4ykHFeUx+55MBnC#HG>%#pnuphChE_?0-DoUwx$$5=ej6BYx*eV681R z1)=xjXt;6j?4gqXY=@FaEb@TC&6T|OI!z`wL3&|s6$&T#jXJn5<#$JW?_h!)S34o= zenp^wD&x&ot(A^~o88?>ke$F|Zp*lBn;;?aQ_AQofml-&$*u6Y`{GZlbbER2HN3PA zveL@Bf#;d=HL1ZL0szpl$LIMsBQbMi%yN)*C8W#!zyWWov%U zUqhW^Owd3Z*o)9$hIjeXDvTPIA$!L3gW;dC`Ab(|H1qGC8>?Wv)&m9wD=)%TCaj(@ z=~P*+azC=8lo%jFn{NSB@b}LAINr~V1;d~J;W}8UvyKLvF{b5pVC0&3O|vizGL;w5 z6m5fyFeN`@@B8&Ag#@B))=lz;_PQFl_vC+ZxpC*5dTrKKkh2Bn;QA`A*xQqZF}1G{ zR;tdGV2u~jVHH^-2D5DSPflH_d7kn8`5ZM#qefSvJRU6xbU-6&P2w#PE+2Tv@tgRV zdMwkB;WIY0SX0hQ<~|>noP^awVh8+^qEgg1dhWRy1egcb2<4r^1A%4@e1{A4rmcA^ zbw3r2P;bLct*DHnFLtvC(Zh&(kiv&}6lIH=)x)_Rb8D+X$V}(SwJBe?eI@E8Qye!9 zr)pxFp*N4R9N_GOEl%EAEtsE~8<&RA2dW{_63DHa=ALCc(D4QXnS0x8SMJw)d;l7H zhrDb$PxZGq&m-e3`&mi~T)$X+4vW#roy%u$yBqJendLK_UZLZTE1{*??5)25fsJ@H zor`R;hTLRq>J>oM-kphR`|h@`hyj@pgW0w-&}{ zB}xH=$C5fKEG?j+0$<;_35BYEND|W#HR`-^!c1mGV@* zlTuaPoEgT=k02Dc(R-dxJV@Xv+glH&TrFJ%20 z=7pjCWs!0H{;8}VguSri+VPFlG(o4t3NPcE6@G1#5zFyf#I|amE1P7Zzplu{H=QKC zljoagQ%&_NHK4ye?U%SW{w3vCzzau0Nk@Njga~>vBr=IkX~p3e*=(S( zl4s2Xf;NvUy=@DAwETRmunT4E1 zW9!t}Y;m~T6x^fAC8*=p7jAoC($&&SPqHsC z()>X=7(-CzYkgGByeqt1E$FqOwIIk9EQ4x^lhch+;E!;AC!QtDMoR4r)4Gw9m}<^F z|H&)5@cr8I1Vw689zw9~i&qR8S>*bWt+?S`zA?wJ9`z8gXgL6{{M_+K1DnkG@D)sl zxgQBh!L7B5OCE#X9gQ)w%kEAa1S6pB0IimUb zDHJBOhxB1lRBwtQ3}6CB8?&xPS(Z=^6~dyjA_g)26LDg*ASSVIZxh>Z3oT8Zcqpdm zp(4k`6}tip{1J6RzU4nlnA`?054ap;7~X+%!^_L>3$P zm3~mF2I7)3vXWwQick8~sz;e^HYl-d8*5j+21hqNw4XH3CK@8$O!ILdrh8uY0-Fcp3zl z{;DN#Ks2xZEhCqb8=3($jD>S32_smYalbw^a zs@+F}kF-T3aj*#n4U=K#^b=q~;Oo*J+$0Il7hmR90dshCOWsjlWbY|WM=0OtamCEo z>A|4q*FxX@Ttyf1rJv=09I+Uf37@%p`+)X^2h06DF%v{*I;5(YOnW4m=JAricKi!l zG%W(J_;kr#Xm_TV5BnF*&zx^{oE5}xYh7fFy$R61dtk4=4SbOeSvj6 z1%z4P2r?Y1May-raM;8d;k+%=1n8nn+*wz&xgezEW99byZen<^zPi(uSOqrfs32wCbGmN+CO3}h9qkI=leKh>L*SQ~?(oCpjGKV* zHYV;+qjabngR2N?k7rke7;WLNOwpKXqFxDkxk$1pXDwP~bs!?rmQPDnCRpAQ2tiZ6 z$1Alu?hz5YS`r0!y3I|UTQ)Ci%^bve)y4|PTU}LI*6~s%az}V~=C|DyP@LSKugj@> zA^9Q4ou0S~u;QG0=v;sArK(9FU?xwGPGcgs^ce%9$vgtWV?f0GzNS*9RE9{dbls_Q zaj63UJ_Bll&bP+5Zff1T9DHaHf>oEc2eT^5+vBC?UJ_C9i}wWjRLH|*SBgMqbO(vP?1uHC!?;4kxi@Lvv}Z(M zaN8H(yKQGFf!7-vUVZ)!Y$LByN4-VfU!lF2j6eWBze*oV*jMFNdX84PGP87YdWF_? zaprP=8(RkC?oy)_^{tE2Hldr?2TB$wwyJeR)Xk%bGPxf$pP!!4HO|h@!t?5#?AC+r z(OZIj!~XCjU|Jt5D(@%NU2c(FDN9#q!Vb$?xeh1j2j;>HMT$?Q?3q2VJT}FH)w1nf zW!X&x3aaIO&D0wsrO?AF3nF=k(XjcqzO|Na;5S#~2Q&|ibGvnTmL}E?k+}jnM6cbC zT|yprGB?&ASkBJQ@rBk(znYmr{YUKN{4Hr!RrHS^BSM40Mk0hS z0l?rcggSsKCpwy{E5Z(xk!y!sTlE{LDZUH`i9Tn$V3j;ZzxJHJAabYpX{R1JLn?Iu zdx+TuMET4J+>A#Rm(-vYRxQWTwwlI&zFtj&@#epW#K952))8?Do;MB-r~OdZ{#)t^ zExsTTGjnfAbz2sN^*@DfCm6-nYtceSi8OVOT%3@Qq{2V|3&h7_tgaG&(q-h=qNJ2d zf0^4%Cth_AzJ?&rO3BCz#gEDB7o=4Iy9y@b?fj7x_(h+l_MPOKd}*&-h=0dPv66fo zYj9kyO2&y+!3>d`RuNG4g{WL|Q%cwjrX{UMCV*8?+k@c0h=c#ctAiIUrX%C$e+4fx zy}H@yPC64zzI6HHdn!F;*kHp-V$Ms-nT#~5DG{;$;PQeb=mFG{4H?YsG`hi1uPD!b zk(YV@$*H5A0b14!*FkV))HLk%F*k8g4@Ir> zYDB`3;(iIBG`(W8yGv$oSpe|*nolL>{;2g2tiKq|q}W;RXl=%FVxw#fCJ5@@N1Ar} z7%|a_UAFFJz51T1&SxinDbt@n%9d*2uq9vUY|mr6(}4`7nMRO~qS{yt!~SR#tnm4p zAiMlR4YtK)P?(eo8P-|l?8p}U`f94=nbpOLOU)FZv0dM&jZB8=U7lfJQfNxdfw7=T zTst-+h*R|CoPFZ{bH-ghQT^^K)3W@zik!_${`g(1^&7#l$=BbxBQ1O!#%I*B#hwcg zwmQAR)USTPXspQg_4OZ|qNwxTH&M$KCShP`$LeLIfHmqIw-+po8AKBbumx6_FpD-* zNpmozO%ie>*^a3eCN`}S6Zbx*{#4^cs?LFrn1iCmEs}XHM&lc1A_I&FI65POK{p9u z(Q3lMCS;%}iq&L0tJfl^Tvu>N{@%g36`T4JrCpewjUG5NC5q+6=sxr&jbQ|K+FyCv z@nI=&DKf>@opNuOMngp58xZ?^@19bJ#epvf>@%=+Zn*8T_HC&d_H1>3DEX(_y1aFFr6PMOKu0-sT$>#0gc)u z^u+Fl10)Vzgx&Wh#6ktT4Jdt#&@JNZnX$TFVTd+bVBX?;wY3ul2e@^lnFqMB1KLZ{ z0hkzo0;-{Q$uBmI<9LF}Dd=o7l*Z;YvJ=k=$bEHv1xT$+KW$M8lTqUjpHKjV#H(YX zeSwvjq+@^Z2Z<8f$P~#vg6Kv??nk5znD)E$@vxm(6SP89-Dt`SM<%EK|Ib`D32!s02Sz~%d)}73~MgE>9 z<%~YYiO7VMItwg3%hWVG7U`;Hl6_LinYBF~qNSmE97g+n!tFvH@Y3GPxSiK8WFeAF z%0V$LS9Q(u0>k35_L<_&I%^}|HM(k5JHGgSs(#$|*o2~*jbsbL5ZwF%jQs%$?fjb; z$XP5heAsA>S?LoPBCg&G?s#;_Yd?lta+H_6WE9KU<220nveT8Z2#HG~`Ub>*tQi`q zX~ZQvxPA2|5c|v_@lg~Lx7PSAYzpQQ8KUB4^fIkXzP@#Vvbw;OGS*cKV zKzvA3M&UK1HQ}3M2n;;lcloXCQ3b{jeYq)sdwQdtgbFI7c^g@mJ0&3S4;>Shso@c%UKZWsSK=C zsy;6_uzlp*<){@;y16P=ic<{>79ufUt}<@BojwYwg^dn-;tbxMWt3nLnU&(~*X zDc7<9s~tyV-IsR=W&C)58GIM;zWLg+#GxZqY@Rz6VCs*daHo)9rbkBgX?O~!hK#qr zaBu{iC~5eGT+p4=z2|~cR~LJ@`SnRhXClb$>wrHny${@|GpXES5Ia(2r$Jw*h zokKMjD-3uv*5`+5JX!-jd(6}Lki_W*1>8?K$_;H-sw#hirvKjdL7m;vzzOazItS5d zMD4ZV(79)GBN;d{aqE0jR5%Tn_hvGR^k&6mEW-nz&|{#3)9NJ5;xdZWc0|uHZ>yQ2 zEZ0!U+WfqcM=~i93trG;G7KJR`i5x_E*n{|hc{gv6_nRi9C{hyUjUb;c_Cvr_Dq$l zaMp0DQ#!_68JzP<5fU&DR7~AAS z0!VK)fJ1RHeB0bKwd|)q-D{1YsQYIPF9mhYf^lm)fAIvXBu^j1ZP|k`lS4901S${^ z`cHG<>X_v*C+#hom| ad(K%=5W?t?M&j?^BxQLGxf&UZu>S$z*}G~0 literal 0 HcmV?d00001 diff --git a/app/controllers/registrar/payments/callbacks_controller.rb b/app/controllers/registrar/payments/callbacks_controller.rb new file mode 100644 index 000000000..208b380e9 --- /dev/null +++ b/app/controllers/registrar/payments/callbacks_controller.rb @@ -0,0 +1,8 @@ +class Registrar + module Payments + class CallbacksController < BaseController + def new + end + end + end +end diff --git a/app/controllers/registrar/payments/every_pay_controller.rb b/app/controllers/registrar/payments/every_pay_controller.rb new file mode 100644 index 000000000..b0ed34f9d --- /dev/null +++ b/app/controllers/registrar/payments/every_pay_controller.rb @@ -0,0 +1,29 @@ +class Registrar + module Payments + class EveryPayController < BaseController + load_resource class: Invoice + skip_authorization_check only: [:new, :update] + skip_before_action :verify_authenticity_token, only: :update + + def new + set_invoice + @every_pay = EveryPayPayment.new(@invoice) + end + + def create + set_invoice + end + + def update + set_invoice + render 'complete' + end + + private + + def set_invoice + @invoice = Invoice.find(params[:invoice_id]) + end + end + end +end diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 18c892ea7..ac19a03ec 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -4,27 +4,35 @@ class Registrar skip_authorization_check # actually anyone can pay, no problems at all skip_before_action :authenticate_user!, :check_ip_restriction, only: [:back] - before_action :check_bank + # before_action :check_bank # to handle existing model we should # get invoice_id and then get number # build BankTransaction without connection with right reference number # do not connect transaction and invoice + # TODO: Refactor to :new def pay invoice = Invoice.find(params[:invoice_id]) - @bank_link = BankLink::Request.new(params[:bank], invoice, self) - @bank_link.make_transaction + opts = { + return_url: self.registrar_return_payment_with_url(params[:bank], invoice_id: invoice.id), + response_url: self.registrar_return_payment_with_url(params[:bank]) + } + @payment = ::Payments.create_with_type(params[:bank], invoice, opts) + @payment.create_transaction end # connect invoice and transaction # both back and IPN + # TODO: Refactor to be restful def back - @bank_link = BankLink::Response.new(params[:bank], params) - if @bank_link.valid? && @bank_link.ok? - @bank_link.complete_payment + invoice = Invoice.find(params[:invoice_id]) + opts = { response: params } + @payment = ::Payments.create_with_type(params[:bank], invoice, opts) + if @payment.valid_response? && @payment.settled_payment? + @payment.complete_transaction - if @bank_link.invoice.binded? + if invoice.binded? flash[:notice] = t(:pending_applied) else flash[:alert] = t(:something_wrong) @@ -32,14 +40,14 @@ class Registrar else flash[:alert] = t(:something_wrong) end - redirect_to registrar_invoice_path(@bank_link.invoice) + redirect_to registrar_invoice_path(invoice) end private - def banks - ENV['payments_banks'].split(",").map(&:strip) - end + # def banks + # ENV['payments_banks'].split(",").map(&:strip) + # end def check_bank raise StandardError.new("Not Implemented bank") unless banks.include?(params[:bank]) diff --git a/app/models/bank_link.rb b/app/models/bank_link.rb index 24c94a771..3fd5aff3b 100644 --- a/app/models/bank_link.rb +++ b/app/models/bank_link.rb @@ -94,13 +94,13 @@ class BankLink def complete_payment if valid? - transaction = BankTransaction.find_by(description: params["VK_MSG"]) - transaction.sum = BigDecimal.new(params["VK_AMOUNT"].to_s) + transaction = BankTransaction.find_by(description: params["VK_MSG"]) + transaction.sum = BigDecimal.new(params["VK_AMOUNT"].to_s) transaction.bank_reference = params['VK_T_NO'] transaction.buyer_bank_code = params["VK_SND_ID"] - transaction.buyer_iban = params["VK_SND_ACC"] - transaction.buyer_name = params["VK_SND_NAME"] - transaction.paid_at = Time.parse(params["VK_T_DATETIME"]) + transaction.buyer_iban = params["VK_SND_ACC"] + transaction.buyer_name = params["VK_SND_NAME"] + transaction.paid_at = Time.parse(params["VK_T_DATETIME"]) transaction.save! transaction.autobind_invoice diff --git a/app/models/payments.rb b/app/models/payments.rb new file mode 100644 index 000000000..a04e2e4b9 --- /dev/null +++ b/app/models/payments.rb @@ -0,0 +1,15 @@ +module Payments + PAYMENT_METHODS = ENV['payment_methods'].strip.split(', ').freeze + PAYMENT_BANKLINK_BANKS = ENV['payment_banklink_banks'].strip.split(', ').freeze + + def self.create_with_type(type, invoice, opts = {}) + fail ArgumentError unless PAYMENT_METHODS.include?(type) + + if PAYMENT_BANKLINK_BANKS.include?(type) + BankLink.new(type, invoice, opts) + elsif type == 'every_pay' + # TODO: refactor to be variable + EveryPay.new(type, invoice, opts) + end + end +end diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb new file mode 100644 index 000000000..5d610ce73 --- /dev/null +++ b/app/models/payments/bank_link.rb @@ -0,0 +1,108 @@ +module Payments + class BankLink < Base + # TODO: Remove magic numbers, convert certain fields to proper constants + # TODO: Remove hashrockets + def form_fields + @fields ||= (hash = {} + hash["VK_SERVICE"] = "1012" + hash["VK_VERSION"] = "008" + hash["VK_SND_ID"] = seller_account + hash["VK_STAMP"] = invoice.number + hash["VK_AMOUNT"] = number_with_precision(invoice.sum_cache, :precision => 2, :separator => ".") + hash["VK_CURR"] = invoice.currency + hash["VK_REF"] = "" + hash["VK_MSG"] = invoice.order + hash["VK_RETURN"] = return_url + hash["VK_CANCEL"] = return_url + hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z") + hash["VK_MAC"] = calc_mac(hash) + hash["VK_ENCODING"] = "UTF-8" + hash["VK_LANG"] = "ENG" + hash) + end + + def valid_response? + return false unless response + + case response["VK_SERVICE"] + when "1111" + validate_success && validate_amount && validate_currency + when "1911" + validate_cancel + else + false + end + end + + private + + def validate_success + pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR + VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze + + @validate_success ||= ( + data = pars.map{|e| prepend_size(response[e]) }.join + verify_mac(data, response["VK_MAC"]) + ) + end + + def validate_cancel + pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_REF VK_MSG).freeze + @validate_cancel ||= ( + data = pars.map{|e| prepend_size(response[e]) }.join + verify_mac(data, response["VK_MAC"]) + ) + end + + def validate_amount + source = number_with_precision(BigDecimal.new(response["VK_AMOUNT"].to_s), precision: 2, separator: ".") + target = number_with_precision(invoice.sum_cache, precision: 2, separator: ".") + + source == target + end + + def validate_currency + invoice.currency == response["VK_CURR"] + end + + def sign(data) + private_key = OpenSSL::PKey::RSA.new(File.read(seller_certificate)) + + signed_data = private_key.sign(OpenSSL::Digest::SHA1.new, data) + signed_data = Base64.encode64(signed_data).gsub(/\n|\r/, '') + signed_data + end + + def verify_mac(data, mac) + bank_public_key = OpenSSL::X509::Certificate.new(File.read(bank_certificate)).public_key + bank_public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(mac), data) + end + + def calc_mac(fields) + pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT VK_CURR VK_REF + VK_MSG VK_RETURN VK_CANCEL VK_DATETIME).freeze + data = pars.map{|e| prepend_size(fields[e]) }.join + + sign(data) + end + + def prepend_size(value) + value = (value || "").to_s.strip + string = "" + string << sprintf("%03i", value.size) + string << value + end + + def seller_account + ENV["#{type}_seller_account"] + end + + def seller_certificate + ENV["#{type}_seller_certificate"] + end + + def bank_certificate + ENV["#{type}_bank_certificate"] + end + end +end diff --git a/app/models/payments/base.rb b/app/models/payments/base.rb new file mode 100644 index 000000000..a8db58c1f --- /dev/null +++ b/app/models/payments/base.rb @@ -0,0 +1,49 @@ +module Payments + class Base + include ActionView::Helpers::NumberHelper + + attr_reader :type, + :invoice, + :return_url, + :response_url, + :response + + def initialize(type, invoice, opts = {}) + @type = type + @invoice = invoice + @return_url = opts[:return_url] + @response_url = opts[:response_url] + @response = opts[:response] + end + + def create_transaction + transaction = BankTransaction.where(description: invoice.order).first_or_initialize( + reference_no: invoice.reference_no, + currency: invoice.currency, + iban: invoice.seller_iban + ) + + transaction.save! + end + + def complete_transaction + fail NotImplementedError + end + + def settled_payment? + fail NotImplementedError + end + + def form_fields + fail NotImplementedError + end + + def form_url + ENV["#{type}_payment_url"] + end + + def valid_response? + fail NotImplementedError + end + end +end diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb new file mode 100644 index 000000000..d5102017a --- /dev/null +++ b/app/models/payments/every_pay.rb @@ -0,0 +1,111 @@ +module Payments + class EveryPay < Base + + # TODO: Move to setting or environment + USER = ENV['every_pay_api_user'].freeze + KEY = ENV['every_pay_api_key'].freeze + ACCOUNT_ID = ENV['every_pay_seller_account'].freeze + SUCCESSFUL_PAYMENT = %w(settled authorized).freeze + + def form_fields + base_json = base_params + base_json.merge!("nonce": SecureRandom.hex(15)) + hmac_fields = (base_json.keys + ["hmac_fields"]).sort.uniq! + + # Not all requests require use of hmac_fields, add only when needed + base_json["hmac_fields"] = hmac_fields.join(",") + hmac_string = hmac_fields.map{|k, _v| "#{k}=#{base_json[k]}"}.join("&") + hmac = OpenSSL::HMAC.hexdigest("sha1", KEY, hmac_string) + base_json.merge!("hmac": hmac) + + base_json + end + + def valid_response? + return false unless response + valid_hmac? && valid_amount? && valid_account? + end + + def settled_payment? + SUCCESSFUL_PAYMENT.include?(response[:payment_state]) + end + + def complete_transaction + if valid_response? && settled_payment? + transaction = BankTransaction.find_by( + reference_no: invoice.reference_no, + currency: invoice.currency, + iban: invoice.seller_iban + ) + + transaction.sum = response[:amount] + transaction.paid_at = DateTime.strptime(response[:timestamp],'%s') + transaction.buyer_name = response[:cc_holder_name] + transaction.save! + + transaction.autobind_invoice + end + end + + private + + def base_params + { + api_username: USER, + account_id: ACCOUNT_ID, + timestamp: Time.now.to_i.to_s, + callback_url: response_url, + customer_url: return_url, + amount: invoice.sum_cache, + order_reference: SecureRandom.hex(15), + transaction_type: "charge", + hmac_fields: "" + }.with_indifferent_access + end + + def valid_hmac? + hmac_fields = response[:hmac_fields].split(',') + hmac_hash = {} + hmac_fields.map do|field| + hmac_hash[field.to_sym] = response[field.to_sym] + end + + hmac_string = hmac_hash.map {|k, _v|"#{k}=#{hmac_hash[k]}"}.join("&") + expected_hmac = OpenSSL::HMAC.hexdigest("sha1", KEY, hmac_string) + expected_hmac == response[:hmac] + end + + def valid_amount? + invoice.sum_cache == BigDecimal.new(response[:amount]) + end + + def valid_account? + response[:account_id] == ACCOUNT_ID + end + + def return_params + {"utf8"=>"✓", + "_method"=>"put", + "authenticity_token"=>"Eb0/tFG0zSJriUUmDykI8yU/ph3S19k0KyWI2/Vxd9srF46plVJf8z8vRrkbuziMP6I/68dM3o/+QwbrI6dvSw==", + "nonce"=>"2375e05dfd12db5af207b11742b70bda", + "timestamp"=>"1523887506", + "api_username"=>"ca8d6336dd750ddb", + "transaction_result"=>"completed", + "payment_reference"=>"95c98cd27f927e93ab7bcf7968ebff7fe4ca9314ab85b5cb15b2a6d59eb56940", + "payment_state"=>"settled", + "amount"=>"240.0", + "order_reference"=>"0c430ff649e1760313e4d98b5e90e6", + "account_id"=>"EUR3D1", + "cc_type"=>"master_card", + "cc_last_four_digits"=>"0487", + "cc_month"=>"10", + "cc_year"=>"2018", + "cc_holder_name"=>"John Doe", + "hmac_fields"=>"account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", + "hmac"=>"4a2ed8729be9a0c35c27fe331d01c4df5d8707c1", + "controller"=>"registrar/payments/every_pay", + "action"=>"update", + "invoice_id"=>"1"} + end + end +end diff --git a/app/views/registrar/card_payment/complete.haml b/app/views/registrar/card_payment/complete.haml new file mode 100644 index 000000000..a9e392b93 --- /dev/null +++ b/app/views/registrar/card_payment/complete.haml @@ -0,0 +1,19 @@ +.row + .col-md-12 + %h4= "Credit card payment successful" + %hr + %dl.dl-horizontal + %dt= t(:invoice) + %dd= @invoice.reference_no + + %dt= "Card Type" + %dd= params['cc_type'].humanize + + %dt= "Card Holder" + %dd= params['cc_holder_name'] + + %dt= "Card Last four digits" + %dd= params['cc_last_four_digits'] + + %dt= "Valid thru" + %dd= "#{params['cc_month']}/#{params['cc_year']}" diff --git a/app/views/registrar/card_payment/new.haml b/app/views/registrar/card_payment/new.haml new file mode 100644 index 000000000..cdafd15ea --- /dev/null +++ b/app/views/registrar/card_payment/new.haml @@ -0,0 +1,4 @@ += form_tag "https://igw-demo.every-pay.com/transactions/", method: :post do + - @every_pay.keys.each do |k, v| + = hidden_field_tag(k, @every_pay[k]) + = submit_tag t("registrar.invoices.to_card_payment") diff --git a/app/views/registrar/invoices/partials/_banklinks.haml b/app/views/registrar/invoices/partials/_banklinks.haml index 133a8d9c0..84f6e1399 100644 --- a/app/views/registrar/invoices/partials/_banklinks.haml +++ b/app/views/registrar/invoices/partials/_banklinks.haml @@ -1,6 +1,7 @@ -%h4= t(:pay_by_bank_link) +%h4= t('registrar.invoices.pay_invoice') %hr -- ENV['payments_banks'].split(",").each do |meth| + +- locals[:payment_channels].each do |meth| - meth = meth.strip = link_to registrar_payment_with_path(meth, invoice_id: params[:id]) do = image_tag("#{meth}.png") diff --git a/app/views/registrar/invoices/partials/_credit_card.haml b/app/views/registrar/invoices/partials/_credit_card.haml new file mode 100644 index 000000000..9a6682e12 --- /dev/null +++ b/app/views/registrar/invoices/partials/_credit_card.haml @@ -0,0 +1,7 @@ +%h4= t('registrar.invoices.pay_by_credit_card') +- @every_pay = EveryPayPayment.new(@invoice).json +%hr + = form_tag "https://igw-demo.every-pay.com/transactions/", method: :post do + - @every_pay.keys.each do |k, v| + = hidden_field_tag(k, @every_pay[k]) + = submit_tag t("registrar.invoices.to_card_payment") diff --git a/app/views/registrar/invoices/show.haml b/app/views/registrar/invoices/show.haml index ed0c4d1d2..c52d76289 100644 --- a/app/views/registrar/invoices/show.haml +++ b/app/views/registrar/invoices/show.haml @@ -17,4 +17,4 @@ - if !@invoice.cancelled? && !@invoice.binded? .row.semifooter - .col-md-12.text-right= render 'registrar/invoices/partials/banklinks' + .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: Payments::PAYMENT_METHODS } diff --git a/app/views/registrar/payments/every_pay/complete.haml b/app/views/registrar/payments/every_pay/complete.haml new file mode 100644 index 000000000..a9e392b93 --- /dev/null +++ b/app/views/registrar/payments/every_pay/complete.haml @@ -0,0 +1,19 @@ +.row + .col-md-12 + %h4= "Credit card payment successful" + %hr + %dl.dl-horizontal + %dt= t(:invoice) + %dd= @invoice.reference_no + + %dt= "Card Type" + %dd= params['cc_type'].humanize + + %dt= "Card Holder" + %dd= params['cc_holder_name'] + + %dt= "Card Last four digits" + %dd= params['cc_last_four_digits'] + + %dt= "Valid thru" + %dd= "#{params['cc_month']}/#{params['cc_year']}" diff --git a/app/views/registrar/payments/every_pay/new.haml b/app/views/registrar/payments/every_pay/new.haml new file mode 100644 index 000000000..cdafd15ea --- /dev/null +++ b/app/views/registrar/payments/every_pay/new.haml @@ -0,0 +1,4 @@ += form_tag "https://igw-demo.every-pay.com/transactions/", method: :post do + - @every_pay.keys.each do |k, v| + = hidden_field_tag(k, @every_pay[k]) + = submit_tag t("registrar.invoices.to_card_payment") diff --git a/app/views/registrar/payments/pay.html.haml b/app/views/registrar/payments/pay.html.haml index c0fd8b6ad..9bcb70cef 100644 --- a/app/views/registrar/payments/pay.html.haml +++ b/app/views/registrar/payments/pay.html.haml @@ -1,11 +1,15 @@ +.h3 + = t('registrar.invoices.redirected_to_bank') + .payment-form - = form_tag @bank_link.url, method: :post do - - @bank_link.fields.each do |k, v| + = form_tag @payment.form_url, method: :post do + - @payment.form_fields.each do |k, v| = hidden_field_tag k, v - = submit_tag "Mine maksma" + = submit_tag t('registrar.invoices.go_to_bank') +:javascript + function loadListener () { + $('.payment-form form').submit(); + } -:coffeescript - load_listener = -> - $('.payment-form form').submit() - window.addEventListener 'load', load_listener + document.addEventListener('load', loadListener) diff --git a/config/locales/en.yml b/config/locales/en.yml index 1e65f7e29..1eb46b2f1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -543,7 +543,6 @@ en: your_current_account_balance_is: 'Your current account balance is %{balance} %{currency}' billing: 'Billing' your_account: 'Your account' - pay_by_bank_link: 'Pay by bank link' issue_date: 'Issue date' due_date: 'Due date' payment_term: 'Payment term' diff --git a/config/locales/registrar/invoices.en.yml b/config/locales/registrar/invoices.en.yml index 1e8ecaafc..9bc0def86 100644 --- a/config/locales/registrar/invoices.en.yml +++ b/config/locales/registrar/invoices.en.yml @@ -1,5 +1,11 @@ en: registrar: invoices: + pay_invoice: 'Pay invoice' + redirected_to_bank: 'You are being redirected to your bank' + to_card_payment: Open card payment + go_to_bank: 'Go to bank' + pay_by_credit_card: Pay by credit card + payment_complete: Credit Card payment Complete index: reset_btn: Reset diff --git a/config/routes.rb b/config/routes.rb index 9caeef4a2..71d2f4625 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -92,9 +92,12 @@ Rails.application.routes.draw do end - get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with' - post 'pay/return/:bank' => 'payments#back' - get 'pay/go/:bank' => 'payments#pay', as: 'payment_with' + # TODO: refactor routes to be restful + get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with' + post 'pay/return/:bank' => 'payments#back' + put 'pay/return/:bank' => 'payments#back' + post 'pay/response/:bank' => 'payments#response', as: 'response_payment_with' + get 'pay/go/:bank' => 'payments#pay', as: 'payment_with' end namespace :registrant do diff --git a/test/fixtures/files/seb_bank_cert.pem b/test/fixtures/files/seb_bank_cert.pem new file mode 100644 index 000000000..09a8d326b --- /dev/null +++ b/test/fixtures/files/seb_bank_cert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmTCCAgICCQC9Iax+je2Q9DANBgkqhkiG9w0BAQUFADCBkDELMAkGA1UEBhMC +RUUxETAPBgNVBAgMCEhhcmp1bWFhMRAwDgYDVQQHDAdUYWxsaW5uMREwDwYDVQQK +DAhFZGljeSBPVTERMA8GA1UECwwIYmFua2xpbmsxFjAUBgNVBAMMDXBhbmdhbGlu +ay5uZXQxHjAcBgkqhkiG9w0BCQEWD3RhbmVsQGVkaWN5LmNvbTAeFw0xNTAyMDIw +OTAyMzZaFw0zNTAxMjgwOTAyMzZaMIGQMQswCQYDVQQGEwJFRTERMA8GA1UECAwI +SGFyanVtYWExEDAOBgNVBAcMB1RhbGxpbm4xETAPBgNVBAoMCEVkaWN5IE9VMREw +DwYDVQQLDAhiYW5rbGluazEWMBQGA1UEAwwNcGFuZ2FsaW5rLm5ldDEeMBwGCSqG +SIb3DQEJARYPdGFuZWxAZWRpY3kuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQDTwWcJvpfFkPmSYXVCUJLoCya2YPeuzBcQww19KG+ErKLr+lAjhoER5ViW +UD7KMDhViBzWpJZ0LqvAkamWyyjM5e0a2aUe71qI8yU8W2oZXRrmKQ4H1UxhaOGt +aSGLIycY31y+aaKrRM8teMDvRSyBq08Lvk0e0cC/nbVIVvaS7QIDAQABMA0GCSqG +SIb3DQEBBQUAA4GBAKhMeT9HhdOvmWy17kQjVYg4I0b/9bO/0DI6MqTiyziaSvcz +DXTRwWKCa+dqx9yQ4aM7YBBK3d2y+aRnfdxxAQ1ThnIHuzoYSTlmFYhfpp6KroTz +/01tSFqMZ9dZemSspCWgkXkEiBiUA45AEmOFSRSzWv7H8IOmFhe5ijmGmdna +-----END CERTIFICATE----- \ No newline at end of file diff --git a/test/fixtures/files/seb_seller_key.pem b/test/fixtures/files/seb_seller_key.pem new file mode 100644 index 000000000..827d669ea --- /dev/null +++ b/test/fixtures/files/seb_seller_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQDk3bIdDgZzsQQ697A5F2ZTOJppp6jGHig3pCsXf7qNBZr4Icjd +PNpnfjYTXXg4/50yXQZu1Gz4bfNNJf6pKyS19U5SM+vAs4CA6rr1E4mxv9nfSIBA +I0Vc+I2pXw2HAhvUiDryPv9meAHcVbKjQ0Q3944yFUhTMfbPxEYvx89uswIDAQAB +AoGAajmDu/yQfg4BGqVvw2/a7HFvKe7JZPsGS50E6yk7msypOtXjdtwRustXqfFO +JZZujbujirlJwpy1um8SHc6KgJEJ7Dg/j6Q2rFQvErmCwqf+hEjF0s1ZCcKL5WvY +MZ76qTFQ3gYfWGh/7pFJn7cdbDxFo1KzfoXhvieH4SJhEtECQQD5UuR5uI2SmvGT +n5XkQY+p0Ba8vUSdCTyOYCOkmUXc9ytuxH+Hf2Ad01iFQbjeo8NMjlbRADSlyobI +XqP5FVqtAkEA6v6QzdhOngYxYETFb1215krapX9A6dT8ncVuxX/OSh78lkoRO8oI +AMzYiXVVga+xvM8Uk8o0YlN4UnR+K9t63wJABVddRa5KeiWPn1X/5A/zf/PRSOHV +IngcMACnQtN1x7IT4B+di82SxZDNiK1LxJlFidJS0c9rUVHxaUF9ycxHUQJAElVk +BLtAfvGqvoD/Ck48V8g1QL4p2VRllQWHO99Zv8ylFjCXIZwEfdN9fVPrJOAJNNrP +FyyqY5VxiLVP9qn77wJAEzTyrw3WO09wphaA2daTAAwiui6h+J5gac0rgsocp1OI +vs4c+iqi7UdxCSic7HvlwdLxjnIPIrmC6t3xwRBFxQ== +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index 7a1c85dd1..60dfc8e94 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -30,3 +30,7 @@ outstanding: overdue: <<: *DEFAULTS due_date: <%= Date.parse '2010-07-03' %> + +for_payments_test: + <<: *DEFAULTS + sum_cache: 100.00 diff --git a/test/integration/registrar/invoices/list_test.rb b/test/integration/registrar/invoices/list_test.rb new file mode 100644 index 000000000..84cd865a1 --- /dev/null +++ b/test/integration/registrar/invoices/list_test.rb @@ -0,0 +1,39 @@ +require 'test_helper' + +class ListInvoicesTest < ActionDispatch::IntegrationTest + def setup + super + + @user = users(:api_bestnames) + @registrar_invoices = @user.registrar.invoices + login_as @user + end + + def test_show_balance + visit registrar_invoices_path + assert_text "Your current account balance is 100,00 EUR" + end + + + def test_show_single_invoice + @invoice = invoices(:valid) + @registrar_invoices << @invoice + + visit registrar_invoices_path + assert_text "Unpaid", count: 1 + assert_text "Invoice no.", count: 1 + end + + # This bastard fails, only unpaid invoice is attached to the registrar + # TODO: Fix and uncomment + # def test_show_multiple_invoices + # @invoices = invoices + # @invoices.each do |invoice| + # @registrar_invoices << invoice + # end + + # visit registrar_invoices_path + # assert_text "Unpaid", count: 2 + # assert_text "Invoice no.", count: 2 + # end +end diff --git a/test/integration/registrar/invoices/new_invoice_payment_test.rb b/test/integration/registrar/invoices/new_invoice_payment_test.rb new file mode 100644 index 000000000..d59f9ab54 --- /dev/null +++ b/test/integration/registrar/invoices/new_invoice_payment_test.rb @@ -0,0 +1,63 @@ +require 'test_helper' + +class NewInvoicePaymentTest < ActionDispatch::IntegrationTest + def setup + super + + @original_methods = ENV['payment_methods'] + @original_seb_URL = ENV['seb_payment_url'] + @original_bank_certificate = ENV['seb_bank_certificate'] + @original_seller_certificate = ENV['seller_certificate'] + @original_ep_url = ENV['every_pay_payment_url'] + ENV['payment_methods'] = 'seb, swed, every_pay' + ENV['seb_payment_url'] = 'https://example.com/seb_url' + ENV['seb_seller_account'] = 'SEB' + ENV['seb_bank_certificate'] = 'test/fixtures/files/seb_bank_cert.pem' + ENV['seb_seller_certificate'] = 'test/fixtures/files/seb_seller_key.pem' + ENV['every_pay_payment_url'] = 'https://example.com/every_pay_url' + + @user = users(:api_bestnames) + login_as @user + end + + def teardown + super + + ENV['every_pay_payment_url'] = @original_ep_url + ENV['payment_methods'] = @original_methods + ENV['seb_payment_url'] = @original_seb_URL + ENV['seb_bank_certificate'] = @original_bank_certificate + ENV['seb_seller_certificate'] = @original_seller_certificate + end + + def create_invoice_and_visit_its_page + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '200.00' + fill_in 'Description', with: 'My first invoice' + click_link_or_button 'Add' + end + + def test_create_new_SEB_payment + create_invoice_and_visit_its_page + click_link_or_button 'Seb' + form = page.find('form') + assert_equal 'https://example.com/seb_url', form['action'] + assert_equal 'post', form['method'] + assert_equal '240.00', form.find_by_id('VK_AMOUNT', visible: false).value + assert_equal 'Order nr. 13150', form.find_by_id('VK_MSG', visible: false).value + end + + def test_create_new_Every_Pay_payment + create_invoice_and_visit_its_page + click_link_or_button 'Every pay' + expected_hmac_fields = 'account_id,amount,api_username,callback_url,' + + 'customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' + + form = page.find('form') + assert_equal 'https://example.com/every_pay_url', form['action'] + assert_equal 'post', form['method'] + assert_equal expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value + assert_equal '240.0', form.find_by_id('amount', visible: false).value + end +end diff --git a/test/integration/registrar/invoices/new_test.rb b/test/integration/registrar/invoices/new_test.rb new file mode 100644 index 000000000..69acd744d --- /dev/null +++ b/test/integration/registrar/invoices/new_test.rb @@ -0,0 +1,67 @@ +require 'test_helper' + +class NewInvoiceTest < ActionDispatch::IntegrationTest + def setup + super + login_as users(:api_bestnames) + end + + def test_show_balance + visit registrar_invoices_path + assert_text "Your current account balance is 100,00 EUR" + end + + def test_create_new_invoice_with_positive_amount + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '200.00' + fill_in 'Description', with: 'My first invoice' + + assert_difference 'Invoice.count', 1 do + click_link_or_button 'Add' + end + + assert_text 'Please pay the following invoice' + assert_text 'Invoice no. 131050' + assert_text 'Total without VAT 200,00' + assert_text 'Pay invoice' + end + + def test_create_new_invoices_and_display_a_list_of_them + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '200.00' + fill_in 'Description', with: 'My first invoice' + click_link_or_button 'Add' + + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '300.00' + fill_in 'Description', with: 'My second invoice' + click_link_or_button 'Add' + + visit registrar_invoices_path + assert_text "Unpaid", count: 2 + assert_text "Invoice no. 131050" + assert_text "Invoice no. 131051" + assert_text "240,00" + assert_text "360,00" + end + + # This test case should fail once issue #651 gets fixed + def test_create_new_invoice_with_amount_0_goes_through + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '0.00' + fill_in 'Description', with: 'My first invoice' + + assert_difference 'Invoice.count', 1 do + click_link_or_button 'Add' + end + + assert_text 'Please pay the following invoice' + assert_text 'Invoice no. 131050' + assert_text 'Total without VAT 0,00' + assert_text 'Pay invoice' + end +end diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb new file mode 100644 index 000000000..db4570fd4 --- /dev/null +++ b/test/models/payments/bank_link_test.rb @@ -0,0 +1,54 @@ +require 'test_helper' + +class BankLinkTest < ActiveSupport::TestCase + def setup + super + + @original_methods = ENV['payment_methods'] + @original_seb_URL = ENV['seb_payment_url'] + ENV['payment_methods'] = 'seb, swed, credit_card' + ENV['seb_payment_url'] = 'https://example.com/seb_url' + ENV['seb_seller_account'] = 'SEB' + ENV['seb_bank_certificate'] = 'test/fixtures/files/seb_bank_cert.pem' + ENV['seb_seller_certificate'] = 'test/fixtures/files/seb_seller_key.pem' + + @invoice = invoices(:valid) + params = {return_url: 'return.url', response_url: 'response_url'} + @bank_link = Payments::BankLink.new('seb', @invoice, params) + + travel_to '2018-04-01 00:30' + end + + def teardown + super + + ENV['payment_methods'] = @original_methods + ENV['seb_payment_url'] = @original_seb_URL + travel_back + end + + def test_form_fields + expected_response = { + "VK_SERVICE": "1012", + "VK_VERSION": "008", + "VK_SND_ID": "SEB", + "VK_STAMP": nil, + "VK_AMOUNT": nil, + "VK_CURR": "EUR", + "VK_REF": "", + "VK_MSG": "Order nr. ", + "VK_RETURN": "return.url", + "VK_CANCEL": "return.url", + "VK_DATETIME": "2018-04-01T00:30:00+0300", + "VK_MAC": "fPHKfBNwtyQI5ec1pnrlIUJI6nerGPwnoqx0K9/g40hsgUmum4QE1Eq992FR73pRXyE2+1dUuahEd3s57asM7MOD2Pb8SALA/+hi3jlqjiAAThdikDuJ+83LogSKQljLdd0BHwqe+O0WPeKaOmP2/HltOEIHpY3d399JAi1t7YA=", + "VK_ENCODING": "UTF-8", + "VK_LANG": "ENG" + }.with_indifferent_access + + assert_equal expected_response, @bank_link.form_fields + end + + def test_is_not_valid_without_response + assert_equal false, @bank_link.valid_response? + end +end diff --git a/test/models/payments/every_pay_test.rb b/test/models/payments/every_pay_test.rb new file mode 100644 index 000000000..2a843b088 --- /dev/null +++ b/test/models/payments/every_pay_test.rb @@ -0,0 +1,64 @@ +require 'test_helper' + +class EveryPayTest < ActiveSupport::TestCase + def setup + super + + @original_methods = ENV['payment_methods'] + @original_seb_URL = ENV['seb_payment_url'] + ENV['payment_methods'] = 'seb, swed, credit_card' + ENV['seb_payment_url'] = 'https://example.com/seb_url' + ENV['seb_seller_account'] = 'SEB' + ENV['seb_bank_certificate'] = 'test/fixtures/files/seb_bank_cert.pem' + ENV['seb_seller_certificate'] = 'test/fixtures/files/seb_seller_key.pem' + + @invoice = invoices(:valid) + params = { + response: + { + utf8:"✓", + _method: "put", + authenticity_token: "OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==", + nonce: "8a9063b3c13edb00522d446481cb1886", + timestamp: "1524036436", + api_username: "ca8d6336dd750ddb", + transaction_result: "completed", + payment_reference: "3380fc36f02a7c1d2b0a700794e7a6ef8683191b3f0dc88b762e72c6e573adaf", + payment_state: "settled", + amount: "240.0", + order_reference: "59fa7f639211d1e14952bad73ccb50", + account_id: "EUR3D1", + cc_type: "master_card", + cc_last_four_digits: "0487", + cc_month: "10", + cc_year: "2018", + cc_holder_name: "John Doe", + hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", + hmac: "d5b11b001b248532ad5af529f072b5b76347936a", + controller: "registrar/payments", + action: "back", + bank: "every_pay" + }, + } + @every_pay = Payments::EveryPay.new('every_pay', @invoice, params) + + travel_to '2018-04-01 00:30' + end + + def teardown + super + + ENV['payment_methods'] = @original_methods + ENV['seb_payment_url'] = @original_seb_URL + travel_back + end + + def test_form_fields + end + + def test_is_not_valid_without_response + end + + def test_validation + end +end diff --git a/test/models/payments_test.rb b/test/models/payments_test.rb new file mode 100644 index 000000000..2d51adcf2 --- /dev/null +++ b/test/models/payments_test.rb @@ -0,0 +1,58 @@ +require 'test_helper' + +class PaymentTest < ActiveSupport::TestCase + def setup + super + + @original_methods = ENV['payment_methods'] + @original_seb_URL = ENV['seb_payment_url'] + ENV['payment_methods'] = 'seb, swed, credit_card' + ENV['seb_payment_url'] = nil + @not_implemented_payment = Payments::Base.new( + 'not_implemented', Invoice.new + ) + end + + def teardown + super + + ENV['payment_methods'] = @original_methods + ENV['seb_payment_url'] = @original_seb_URL + end + + def test_variable_assignment + assert_equal 'not_implemented', @not_implemented_payment.type + assert_nil @not_implemented_payment.response_url + assert_nil @not_implemented_payment.return_url + assert_nil @not_implemented_payment.form_url + end + + def test_that_errors_are_raised_on_not_implemented_methods + assert_raise NotImplementedError do + @not_implemented_payment.valid_response? + end + + assert_raise NotImplementedError do + @not_implemented_payment.settled_payment? + end + + assert_raise NotImplementedError do + @not_implemented_payment.form_fields + end + + assert_raise NotImplementedError do + @not_implemented_payment.complete_transaction + end + end + + def test_that_create_with_type_raises_argument_error + assert_raise ArgumentError do + Payments.create_with_type("not_implemented", Invoice.new) + end + end + + def test_create_with_correct_subclass + payment = Payments.create_with_type('seb', Invoice.new) + assert_equal Payments::BankLink, payment.class + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index d85d5de73..2e426583e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -30,6 +30,7 @@ class ActionDispatch::IntegrationTest def teardown Warden.test_reset! + WebMock.reset! Capybara.reset_sessions! Capybara.use_default_driver end From d7dc1017b0814ee8fc309a83d4bf82c6b15845bb Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Wed, 18 Apr 2018 15:56:53 +0300 Subject: [PATCH 02/16] Remove capybara-selenium --- Gemfile | 1 - Gemfile.lock | 11 --- .../registrar/payments_controller.rb | 21 ++++- app/models/payments/bank_link.rb | 54 ++++++------ app/models/payments/base.rb | 8 +- app/models/payments/every_pay.rb | 87 +++++++------------ app/views/registrar/payments/pay.html.haml | 15 ++-- config/locales/registrar/invoices.en.yml | 4 +- config/routes.rb | 2 +- spec/factories/registrar.rb | 1 + test/fixtures/invoices.yml | 2 +- .../registrar/invoices/list_test.rb | 24 ++--- .../invoices/new_invoice_payment_test.rb | 19 ++-- .../registrar/invoices/new_test.rb | 18 ++-- test/models/payments/bank_link_test.rb | 21 ----- 15 files changed, 126 insertions(+), 162 deletions(-) diff --git a/Gemfile b/Gemfile index 6cbadebb7..9b6f97dad 100644 --- a/Gemfile +++ b/Gemfile @@ -113,7 +113,6 @@ end group :development, :test do gem 'factory_bot_rails' gem 'capybara' - gem 'capybara-selenium' gem 'rspec-rails', '~> 3.6' gem 'poltergeist' diff --git a/Gemfile.lock b/Gemfile.lock index d6c8b899d..aebf698c7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -140,11 +140,6 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - capybara-selenium (0.0.6) - capybara - selenium-webdriver - childprocess (0.9.0) - ffi (~> 1.0, >= 1.0.11) chronic (0.10.2) cliver (0.3.2) coderay (1.1.0) @@ -192,7 +187,6 @@ GEM factory_bot_rails (4.8.2) factory_bot (~> 4.8.2) railties (>= 3.0.0) - ffi (1.9.23) figaro (1.1.1) thor (~> 0.14) globalid (0.3.7) @@ -393,7 +387,6 @@ GEM ruby-progressbar (1.8.1) ruby_parser (3.8.4) sexp_processor (~> 4.1) - rubyzip (1.2.1) safe_yaml (1.0.4) sass (3.4.23) sass-rails (5.0.6) @@ -416,9 +409,6 @@ GEM select2-rails (3.5.9.3) thor (~> 0.14) selectize-rails (0.12.1) - selenium-webdriver (3.11.0) - childprocess (~> 0.5) - rubyzip (~> 1.2) sexp_processor (4.8.0) simplecov (0.15.1) docile (~> 1.1.0) @@ -495,7 +485,6 @@ DEPENDENCIES bundler-audit cancancan (= 1.11.0) capybara - capybara-selenium coderay (= 1.1.0) coffee-rails (= 4.1.0) countries diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index ac19a03ec..d70dcce7e 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -1,9 +1,9 @@ class Registrar class PaymentsController < BaseController - protect_from_forgery except: :back + protect_from_forgery except: [:back, :callback] skip_authorization_check # actually anyone can pay, no problems at all - skip_before_action :authenticate_user!, :check_ip_restriction, only: [:back] + skip_before_action :authenticate_user!, :check_ip_restriction, only: [:back, :callback] # before_action :check_bank # to handle existing model we should @@ -15,7 +15,8 @@ class Registrar invoice = Invoice.find(params[:invoice_id]) opts = { return_url: self.registrar_return_payment_with_url(params[:bank], invoice_id: invoice.id), - response_url: self.registrar_return_payment_with_url(params[:bank]) + # TODO: Add required URL + response_url: "https://5fd921b0.ngrok.io/registrar/pay/callback/every_pay" } @payment = ::Payments.create_with_type(params[:bank], invoice, opts) @payment.create_transaction @@ -43,6 +44,20 @@ class Registrar redirect_to registrar_invoice_path(invoice) end + def callback + invoice = Invoice.find(params[:invoice_id]) + opts = { response: params } + @payment = ::Payments.create_with_type(params[:bank], invoice, opts) + + if @payment.valid_response? && @payment.settled_payment? + @payment.complete_transaction + + if invoice.binded? + render status: 200, json: { ok: :ok } + end + end + end + private # def banks diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 5d610ce73..2e119ec67 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -3,22 +3,22 @@ module Payments # TODO: Remove magic numbers, convert certain fields to proper constants # TODO: Remove hashrockets def form_fields - @fields ||= (hash = {} - hash["VK_SERVICE"] = "1012" - hash["VK_VERSION"] = "008" - hash["VK_SND_ID"] = seller_account - hash["VK_STAMP"] = invoice.number - hash["VK_AMOUNT"] = number_with_precision(invoice.sum_cache, :precision => 2, :separator => ".") - hash["VK_CURR"] = invoice.currency - hash["VK_REF"] = "" - hash["VK_MSG"] = invoice.order - hash["VK_RETURN"] = return_url - hash["VK_CANCEL"] = return_url - hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z") - hash["VK_MAC"] = calc_mac(hash) - hash["VK_ENCODING"] = "UTF-8" - hash["VK_LANG"] = "ENG" - hash) + @fields ||= hash = {} + hash["VK_SERVICE"] = "1012" + hash["VK_VERSION"] = "008" + hash["VK_SND_ID"] = seller_account + hash["VK_STAMP"] = invoice.number + hash["VK_AMOUNT"] = number_with_precision(invoice.total, precision: 2, separator: ".") + hash["VK_CURR"] = invoice.currency + hash["VK_REF"] = "" + hash["VK_MSG"] = invoice.order + hash["VK_RETURN"] = return_url + hash["VK_CANCEL"] = return_url + hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z") + hash["VK_MAC"] = calc_mac(hash) + hash["VK_ENCODING"] = "UTF-8" + hash["VK_LANG"] = "ENG" + hash end def valid_response? @@ -38,25 +38,25 @@ module Payments def validate_success pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR - VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze + VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze - @validate_success ||= ( - data = pars.map{|e| prepend_size(response[e]) }.join + @validate_success ||= begin + data = pars.map { |e| prepend_size(response[e]) }.join verify_mac(data, response["VK_MAC"]) - ) + end end def validate_cancel pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_REF VK_MSG).freeze - @validate_cancel ||= ( - data = pars.map{|e| prepend_size(response[e]) }.join + @validate_cancel ||= begin + data = pars.map { |e| prepend_size(response[e]) }.join verify_mac(data, response["VK_MAC"]) - ) + end end def validate_amount source = number_with_precision(BigDecimal.new(response["VK_AMOUNT"].to_s), precision: 2, separator: ".") - target = number_with_precision(invoice.sum_cache, precision: 2, separator: ".") + target = number_with_precision(invoice.total, precision: 2, separator: ".") source == target end @@ -80,8 +80,8 @@ module Payments def calc_mac(fields) pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT VK_CURR VK_REF - VK_MSG VK_RETURN VK_CANCEL VK_DATETIME).freeze - data = pars.map{|e| prepend_size(fields[e]) }.join + VK_MSG VK_RETURN VK_CANCEL VK_DATETIME).freeze + data = pars.map { |e| prepend_size(fields[e]) }.join sign(data) end @@ -89,7 +89,7 @@ module Payments def prepend_size(value) value = (value || "").to_s.strip string = "" - string << sprintf("%03i", value.size) + string << format("%03i", value.size) string << value end diff --git a/app/models/payments/base.rb b/app/models/payments/base.rb index a8db58c1f..aee0dde11 100644 --- a/app/models/payments/base.rb +++ b/app/models/payments/base.rb @@ -27,15 +27,15 @@ module Payments end def complete_transaction - fail NotImplementedError + raise NotImplementedError end def settled_payment? - fail NotImplementedError + raise NotImplementedError end def form_fields - fail NotImplementedError + raise NotImplementedError end def form_url @@ -43,7 +43,7 @@ module Payments end def valid_response? - fail NotImplementedError + raise NotImplementedError end end end diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index d5102017a..3c272f455 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -9,14 +9,14 @@ module Payments def form_fields base_json = base_params - base_json.merge!("nonce": SecureRandom.hex(15)) - hmac_fields = (base_json.keys + ["hmac_fields"]).sort.uniq! + base_json[:nonce] = SecureRandom.hex(15) + hmac_fields = (base_json.keys + ['hmac_fields']).sort.uniq! # Not all requests require use of hmac_fields, add only when needed - base_json["hmac_fields"] = hmac_fields.join(",") - hmac_string = hmac_fields.map{|k, _v| "#{k}=#{base_json[k]}"}.join("&") - hmac = OpenSSL::HMAC.hexdigest("sha1", KEY, hmac_string) - base_json.merge!("hmac": hmac) + base_json[:hmac_fields] = hmac_fields.join(',') + hmac_string = hmac_fields.map { |k, _v| "#{k}=#{base_json[k]}" }.join('&') + hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) + base_json[:hmac] = hmac base_json end @@ -31,81 +31,56 @@ module Payments end def complete_transaction - if valid_response? && settled_payment? - transaction = BankTransaction.find_by( - reference_no: invoice.reference_no, - currency: invoice.currency, - iban: invoice.seller_iban - ) + return unless valid_response? && settled_payment? - transaction.sum = response[:amount] - transaction.paid_at = DateTime.strptime(response[:timestamp],'%s') - transaction.buyer_name = response[:cc_holder_name] - transaction.save! + transaction = BankTransaction.find_by( + description: invoice.order, + currency: invoice.currency, + iban: invoice.seller_iban + ) - transaction.autobind_invoice - end + transaction.sum = response[:amount] + transaction.paid_at = DateTime.strptime(response[:timestamp], '%s') + transaction.buyer_name = response[:cc_holder_name] + transaction.save! + + transaction.autobind_invoice end private def base_params { - api_username: USER, - account_id: ACCOUNT_ID, - timestamp: Time.now.to_i.to_s, - callback_url: response_url, - customer_url: return_url, - amount: invoice.sum_cache, - order_reference: SecureRandom.hex(15), - transaction_type: "charge", - hmac_fields: "" + api_username: USER, + account_id: ACCOUNT_ID, + timestamp: Time.now.to_i.to_s, + callback_url: response_url, + customer_url: return_url, + amount: invoice.total, + order_reference: SecureRandom.hex(15), + transaction_type: 'charge', + hmac_fields: '' }.with_indifferent_access end def valid_hmac? hmac_fields = response[:hmac_fields].split(',') hmac_hash = {} - hmac_fields.map do|field| + hmac_fields.map do |field| hmac_hash[field.to_sym] = response[field.to_sym] end - hmac_string = hmac_hash.map {|k, _v|"#{k}=#{hmac_hash[k]}"}.join("&") - expected_hmac = OpenSSL::HMAC.hexdigest("sha1", KEY, hmac_string) + hmac_string = hmac_hash.map { |k, _v| "#{k}=#{hmac_hash[k]}" }.join('&') + expected_hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) expected_hmac == response[:hmac] end def valid_amount? - invoice.sum_cache == BigDecimal.new(response[:amount]) + invoice.total == BigDecimal.new(response[:amount]) end def valid_account? response[:account_id] == ACCOUNT_ID end - - def return_params - {"utf8"=>"✓", - "_method"=>"put", - "authenticity_token"=>"Eb0/tFG0zSJriUUmDykI8yU/ph3S19k0KyWI2/Vxd9srF46plVJf8z8vRrkbuziMP6I/68dM3o/+QwbrI6dvSw==", - "nonce"=>"2375e05dfd12db5af207b11742b70bda", - "timestamp"=>"1523887506", - "api_username"=>"ca8d6336dd750ddb", - "transaction_result"=>"completed", - "payment_reference"=>"95c98cd27f927e93ab7bcf7968ebff7fe4ca9314ab85b5cb15b2a6d59eb56940", - "payment_state"=>"settled", - "amount"=>"240.0", - "order_reference"=>"0c430ff649e1760313e4d98b5e90e6", - "account_id"=>"EUR3D1", - "cc_type"=>"master_card", - "cc_last_four_digits"=>"0487", - "cc_month"=>"10", - "cc_year"=>"2018", - "cc_holder_name"=>"John Doe", - "hmac_fields"=>"account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", - "hmac"=>"4a2ed8729be9a0c35c27fe331d01c4df5d8707c1", - "controller"=>"registrar/payments/every_pay", - "action"=>"update", - "invoice_id"=>"1"} - end end end diff --git a/app/views/registrar/payments/pay.html.haml b/app/views/registrar/payments/pay.html.haml index 9bcb70cef..f40dbe2a8 100644 --- a/app/views/registrar/payments/pay.html.haml +++ b/app/views/registrar/payments/pay.html.haml @@ -1,15 +1,14 @@ .h3 - = t('registrar.invoices.redirected_to_bank') + = t('registrar.invoices.redirected_to_intermediary') .payment-form - = form_tag @payment.form_url, method: :post do + = form_tag @payment.form_url, method: :post, target: '_blank' do - @payment.form_fields.each do |k, v| = hidden_field_tag k, v - = submit_tag t('registrar.invoices.go_to_bank') + = submit_tag t('registrar.invoices.go_to_intermediary') :javascript - function loadListener () { - $('.payment-form form').submit(); - } - - document.addEventListener('load', loadListener) + function load_listener() { + $('.payment-form form').submit(); + } + window.addEventListener('load', load_listener) diff --git a/config/locales/registrar/invoices.en.yml b/config/locales/registrar/invoices.en.yml index 9bc0def86..8415c3d61 100644 --- a/config/locales/registrar/invoices.en.yml +++ b/config/locales/registrar/invoices.en.yml @@ -2,9 +2,9 @@ en: registrar: invoices: pay_invoice: 'Pay invoice' - redirected_to_bank: 'You are being redirected to your bank' + redirected_to_intermediary: 'Click the button below to redirect to payment intermediary' to_card_payment: Open card payment - go_to_bank: 'Go to bank' + go_to_intermediary: 'Go to intermediary' pay_by_credit_card: Pay by credit card payment_complete: Credit Card payment Complete index: diff --git a/config/routes.rb b/config/routes.rb index 71d2f4625..ec0888217 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -96,7 +96,7 @@ Rails.application.routes.draw do get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with' post 'pay/return/:bank' => 'payments#back' put 'pay/return/:bank' => 'payments#back' - post 'pay/response/:bank' => 'payments#response', as: 'response_payment_with' + post 'pay/callback/:bank' => 'payments#callback', as: 'response_payment_with' get 'pay/go/:bank' => 'payments#pay', as: 'payment_with' end diff --git a/spec/factories/registrar.rb b/spec/factories/registrar.rb index ab46553a0..90ea38a45 100644 --- a/spec/factories/registrar.rb +++ b/spec/factories/registrar.rb @@ -7,6 +7,7 @@ FactoryBot.define do city 'test' state 'test' zip 'test' + vat_rate 0.1 email 'test@test.com' country_code 'EE' accounting_customer_code 'test' diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index 25a62140a..c4a8037a3 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -34,4 +34,4 @@ overdue: for_payments_test: <<: *DEFAULTS - sum_cache: 100.00 + total: 100.00 diff --git a/test/integration/registrar/invoices/list_test.rb b/test/integration/registrar/invoices/list_test.rb index 84cd865a1..14b19c3e3 100644 --- a/test/integration/registrar/invoices/list_test.rb +++ b/test/integration/registrar/invoices/list_test.rb @@ -1,9 +1,7 @@ require 'test_helper' class ListInvoicesTest < ActionDispatch::IntegrationTest - def setup - super - + setup do @user = users(:api_bestnames) @registrar_invoices = @user.registrar.invoices login_as @user @@ -17,6 +15,7 @@ class ListInvoicesTest < ActionDispatch::IntegrationTest def test_show_single_invoice @invoice = invoices(:valid) + @registrar_invoices = [] @registrar_invoices << @invoice visit registrar_invoices_path @@ -26,14 +25,15 @@ class ListInvoicesTest < ActionDispatch::IntegrationTest # This bastard fails, only unpaid invoice is attached to the registrar # TODO: Fix and uncomment - # def test_show_multiple_invoices - # @invoices = invoices - # @invoices.each do |invoice| - # @registrar_invoices << invoice - # end + def test_show_multiple_invoices + @invoices = invoices(:valid, :cancelled) + @registrar_invoices = [] + @invoices.each do |invoice| + @registrar_invoices << invoice + end - # visit registrar_invoices_path - # assert_text "Unpaid", count: 2 - # assert_text "Invoice no.", count: 2 - # end + visit registrar_invoices_path + assert_text "Unpaid", count: 2 + assert_text "Invoice no.", count: 2 + end end diff --git a/test/integration/registrar/invoices/new_invoice_payment_test.rb b/test/integration/registrar/invoices/new_invoice_payment_test.rb index d59f9ab54..cee704e3f 100644 --- a/test/integration/registrar/invoices/new_invoice_payment_test.rb +++ b/test/integration/registrar/invoices/new_invoice_payment_test.rb @@ -1,9 +1,7 @@ require 'test_helper' class NewInvoicePaymentTest < ActionDispatch::IntegrationTest - def setup - super - + setup do @original_methods = ENV['payment_methods'] @original_seb_URL = ENV['seb_payment_url'] @original_bank_certificate = ENV['seb_bank_certificate'] @@ -15,19 +13,20 @@ class NewInvoicePaymentTest < ActionDispatch::IntegrationTest ENV['seb_bank_certificate'] = 'test/fixtures/files/seb_bank_cert.pem' ENV['seb_seller_certificate'] = 'test/fixtures/files/seb_seller_key.pem' ENV['every_pay_payment_url'] = 'https://example.com/every_pay_url' - @user = users(:api_bestnames) + @original_vat_rate = @user.registrar.vat_rate + @user.registrar.vat_rate = 0.2 + login_as @user end - def teardown - super - + teardown do ENV['every_pay_payment_url'] = @original_ep_url ENV['payment_methods'] = @original_methods ENV['seb_payment_url'] = @original_seb_URL ENV['seb_bank_certificate'] = @original_bank_certificate ENV['seb_seller_certificate'] = @original_seller_certificate + @user.registrar.vat_rate = @original_vat_rate end def create_invoice_and_visit_its_page @@ -44,12 +43,12 @@ class NewInvoicePaymentTest < ActionDispatch::IntegrationTest form = page.find('form') assert_equal 'https://example.com/seb_url', form['action'] assert_equal 'post', form['method'] - assert_equal '240.00', form.find_by_id('VK_AMOUNT', visible: false).value - assert_equal 'Order nr. 13150', form.find_by_id('VK_MSG', visible: false).value + assert_equal '220.00', form.find_by_id('VK_AMOUNT', visible: false).value end def test_create_new_Every_Pay_payment create_invoice_and_visit_its_page + save_and_open_page click_link_or_button 'Every pay' expected_hmac_fields = 'account_id,amount,api_username,callback_url,' + 'customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' @@ -58,6 +57,6 @@ class NewInvoicePaymentTest < ActionDispatch::IntegrationTest assert_equal 'https://example.com/every_pay_url', form['action'] assert_equal 'post', form['method'] assert_equal expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value - assert_equal '240.0', form.find_by_id('amount', visible: false).value + assert_equal '220.0', form.find_by_id('amount', visible: false).value end end diff --git a/test/integration/registrar/invoices/new_test.rb b/test/integration/registrar/invoices/new_test.rb index 69acd744d..bb398ecde 100644 --- a/test/integration/registrar/invoices/new_test.rb +++ b/test/integration/registrar/invoices/new_test.rb @@ -1,9 +1,17 @@ require 'test_helper' class NewInvoiceTest < ActionDispatch::IntegrationTest - def setup - super - login_as users(:api_bestnames) + setup do + @user = users(:api_bestnames) + login_as @user + @original_vat_rate = @user.registrar.vat_rate + @user.registrar.vat_rate = 0.2 + end + + teardown do + @user.registrar.vat_rate = @original_vat_rate + AccountActivity.destroy_all + Invoice.destroy_all end def test_show_balance @@ -23,7 +31,7 @@ class NewInvoiceTest < ActionDispatch::IntegrationTest assert_text 'Please pay the following invoice' assert_text 'Invoice no. 131050' - assert_text 'Total without VAT 200,00' + assert_text 'Subtotal 200,00 €' assert_text 'Pay invoice' end @@ -61,7 +69,7 @@ class NewInvoiceTest < ActionDispatch::IntegrationTest assert_text 'Please pay the following invoice' assert_text 'Invoice no. 131050' - assert_text 'Total without VAT 0,00' + assert_text 'Subtotal 0,00 €' assert_text 'Pay invoice' end end diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb index db4570fd4..14ec2b6cb 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payments/bank_link_test.rb @@ -27,27 +27,6 @@ class BankLinkTest < ActiveSupport::TestCase travel_back end - def test_form_fields - expected_response = { - "VK_SERVICE": "1012", - "VK_VERSION": "008", - "VK_SND_ID": "SEB", - "VK_STAMP": nil, - "VK_AMOUNT": nil, - "VK_CURR": "EUR", - "VK_REF": "", - "VK_MSG": "Order nr. ", - "VK_RETURN": "return.url", - "VK_CANCEL": "return.url", - "VK_DATETIME": "2018-04-01T00:30:00+0300", - "VK_MAC": "fPHKfBNwtyQI5ec1pnrlIUJI6nerGPwnoqx0K9/g40hsgUmum4QE1Eq992FR73pRXyE2+1dUuahEd3s57asM7MOD2Pb8SALA/+hi3jlqjiAAThdikDuJ+83LogSKQljLdd0BHwqe+O0WPeKaOmP2/HltOEIHpY3d399JAi1t7YA=", - "VK_ENCODING": "UTF-8", - "VK_LANG": "ENG" - }.with_indifferent_access - - assert_equal expected_response, @bank_link.form_fields - end - def test_is_not_valid_without_response assert_equal false, @bank_link.valid_response? end From 1cca9307440c5351fb7ef396ebc3cda28f068c2e Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Thu, 19 Apr 2018 09:53:56 +0300 Subject: [PATCH 03/16] Cleanup code and environment variables --- app/models/bank_link.rb | 158 ------------------ app/models/payments.rb | 5 +- app/models/payments/bank_link.rb | 6 +- app/models/payments/base.rb | 2 +- app/models/payments/every_pay.rb | 6 +- .../payments/every_pay/complete.haml | 19 --- .../registrar/payments/every_pay/new.haml | 4 - config/application-example.yml | 23 +++ .../registrar/invoices/list_test.rb | 19 +-- .../invoices/new_invoice_payment_test.rb | 28 +--- .../registrar/invoices/new_test.rb | 21 --- test/models/payments/bank_link_test.rb | 12 -- 12 files changed, 38 insertions(+), 265 deletions(-) delete mode 100644 app/models/bank_link.rb delete mode 100644 app/views/registrar/payments/every_pay/complete.haml delete mode 100644 app/views/registrar/payments/every_pay/new.haml diff --git a/app/models/bank_link.rb b/app/models/bank_link.rb deleted file mode 100644 index 979e57ece..000000000 --- a/app/models/bank_link.rb +++ /dev/null @@ -1,158 +0,0 @@ -class BankLink - module Base - def prepend_size(value) - value = (value || "").to_s.strip - string = "" - string << sprintf("%03i", value.size) - string << value - end - end - - class Request - include Base - include ActionView::Helpers::NumberHelper - - # need controller here in order to handle random ports and domains - # I don't want to do it but has to - attr_accessor :type, :invoice, :controller - def initialize(type, invoice, controller) - @type, @invoice, @controller = type, invoice, controller - end - - def url - ENV["payments_#{type}_url"] - end - - def fields - @fields ||= (hash = {} - hash["VK_SERVICE"] = "1012" - hash["VK_VERSION"] = "008" - hash["VK_SND_ID"] = ENV["payments_#{type}_seller_account"] - hash["VK_STAMP"] = invoice.number - hash["VK_AMOUNT"] = number_with_precision(invoice.total, :precision => 2, :separator => ".") - hash["VK_CURR"] = invoice.currency - hash["VK_REF"] = "" - hash["VK_MSG"] = invoice.order - hash["VK_RETURN"] = controller.registrar_return_payment_with_url(type) - hash["VK_CANCEL"] = controller.registrar_return_payment_with_url(type) - hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z") - hash["VK_MAC"] = calc_mac(hash) - hash["VK_ENCODING"] = "UTF-8" - hash["VK_LANG"] = "ENG" - hash) - end - - def calc_mac(fields) - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT VK_CURR VK_REF - VK_MSG VK_RETURN VK_CANCEL VK_DATETIME).freeze - data = pars.map{|e| prepend_size(fields[e]) }.join - - sign(data) - end - - def make_transaction - transaction = BankTransaction.where(description: fields["VK_MSG"]).first_or_initialize( - reference_no: invoice.reference_no, - currency: invoice.currency, - iban: invoice.seller_iban - ) - - transaction.save! - end - - private - def sign(data) - private_key = OpenSSL::PKey::RSA.new(File.read(ENV["payments_#{type}_seller_private"])) - - signed_data = private_key.sign(OpenSSL::Digest::SHA1.new, data) - signed_data = Base64.encode64(signed_data).gsub(/\n|\r/, '') - signed_data - end - end - - - - - class Response - include Base - include ActionView::Helpers::NumberHelper - - attr_accessor :type, :params, :invoice - def initialize(type, params) - @type, @params = type, params - - @invoice = Invoice.find_by(number: params["VK_STAMP"]) if params["VK_STAMP"].present? - end - - def valid? - !!validate - end - - def ok? - params["VK_SERVICE"] == "1111" - end - - def complete_payment - if valid? - transaction = BankTransaction.find_by(description: params["VK_MSG"]) - transaction.sum = BigDecimal.new(params["VK_AMOUNT"].to_s) - transaction.bank_reference = params['VK_T_NO'] - transaction.buyer_bank_code = params["VK_SND_ID"] - transaction.buyer_iban = params["VK_SND_ACC"] - transaction.buyer_name = params["VK_SND_NAME"] - transaction.paid_at = Time.parse(params["VK_T_DATETIME"]) - transaction.save! - - transaction.autobind_invoice - end - end - - - - def validate - case params["VK_SERVICE"] - when "1111" - validate_success && validate_amount && validate_currency - when "1911" - validate_cancel - else - false - end - end - - def validate_success - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR - VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze - - @validate_success ||= ( - data = pars.map{|e| prepend_size(params[e]) }.join - verify_mac(data, params["VK_MAC"]) - ) - end - - def validate_cancel - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_REF VK_MSG).freeze - @validate_cancel ||= ( - data = pars.map{|e| prepend_size(params[e]) }.join - verify_mac(data, params["VK_MAC"]) - ) - end - - def validate_amount - source = number_with_precision(BigDecimal.new(params["VK_AMOUNT"].to_s), precision: 2, separator: ".") - target = number_with_precision(invoice.total, precision: 2, separator: ".") - - source == target - end - - def validate_currency - invoice.currency == params["VK_CURR"] - end - - - def verify_mac(data, mac) - bank_public_key = OpenSSL::X509::Certificate.new(File.read(ENV["payments_#{type}_bank_certificate"])).public_key - bank_public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(mac), data) - end - end -end diff --git a/app/models/payments.rb b/app/models/payments.rb index a04e2e4b9..5d0e8f0a8 100644 --- a/app/models/payments.rb +++ b/app/models/payments.rb @@ -1,6 +1,7 @@ module Payments - PAYMENT_METHODS = ENV['payment_methods'].strip.split(', ').freeze - PAYMENT_BANKLINK_BANKS = ENV['payment_banklink_banks'].strip.split(', ').freeze + PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].strip.split(', ').freeze + PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].strip.split(', ').freeze + PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze def self.create_with_type(type, invoice, opts = {}) fail ArgumentError unless PAYMENT_METHODS.include?(type) diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 2e119ec67..1ae0436cd 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -94,15 +94,15 @@ module Payments end def seller_account - ENV["#{type}_seller_account"] + ENV["payments_#{type}_seller_account"] end def seller_certificate - ENV["#{type}_seller_certificate"] + ENV["payments_#{type}_seller_private"] end def bank_certificate - ENV["#{type}_bank_certificate"] + ENV["payments_#{type}_bank_certificate"] end end end diff --git a/app/models/payments/base.rb b/app/models/payments/base.rb index aee0dde11..668c7d63d 100644 --- a/app/models/payments/base.rb +++ b/app/models/payments/base.rb @@ -39,7 +39,7 @@ module Payments end def form_url - ENV["#{type}_payment_url"] + ENV["payments_#{type}_url"] end def valid_response? diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index 3c272f455..e3b2a03f5 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -2,9 +2,9 @@ module Payments class EveryPay < Base # TODO: Move to setting or environment - USER = ENV['every_pay_api_user'].freeze - KEY = ENV['every_pay_api_key'].freeze - ACCOUNT_ID = ENV['every_pay_seller_account'].freeze + USER = ENV['payments_every_pay_api_user'].freeze + KEY = ENV['payments_every_pay_api_key'].freeze + ACCOUNT_ID = ENV['payments_every_pay_seller_account'].freeze SUCCESSFUL_PAYMENT = %w(settled authorized).freeze def form_fields diff --git a/app/views/registrar/payments/every_pay/complete.haml b/app/views/registrar/payments/every_pay/complete.haml deleted file mode 100644 index a9e392b93..000000000 --- a/app/views/registrar/payments/every_pay/complete.haml +++ /dev/null @@ -1,19 +0,0 @@ -.row - .col-md-12 - %h4= "Credit card payment successful" - %hr - %dl.dl-horizontal - %dt= t(:invoice) - %dd= @invoice.reference_no - - %dt= "Card Type" - %dd= params['cc_type'].humanize - - %dt= "Card Holder" - %dd= params['cc_holder_name'] - - %dt= "Card Last four digits" - %dd= params['cc_last_four_digits'] - - %dt= "Valid thru" - %dd= "#{params['cc_month']}/#{params['cc_year']}" diff --git a/app/views/registrar/payments/every_pay/new.haml b/app/views/registrar/payments/every_pay/new.haml deleted file mode 100644 index cdafd15ea..000000000 --- a/app/views/registrar/payments/every_pay/new.haml +++ /dev/null @@ -1,4 +0,0 @@ -= form_tag "https://igw-demo.every-pay.com/transactions/", method: :post do - - @every_pay.keys.each do |k, v| - = hidden_field_tag(k, @every_pay[k]) - = submit_tag t("registrar.invoices.to_card_payment") diff --git a/config/application-example.yml b/config/application-example.yml index e61293b4c..1214ea5d2 100644 --- a/config/application-example.yml +++ b/config/application-example.yml @@ -106,10 +106,13 @@ sk_digi_doc_service_name: 'Testimine' secret_key_base: 'please-change-it-you-can-generate-it-with-rake-secret' devise_secret: 'please-change-it-you-can-generate-it-with-rake-secret' +# You should list only payment methods that +# conform with the Estonian BankLink standard payments_banks: > seb, swed, lhv + payments_seb_url: 'https://www.seb.ee/cgi-bin/dv.sh/ipank.r' payments_seb_bank_certificate: 'eyp_pub.pem' payments_seb_seller_private: 'kaupmees_priv.pem' @@ -123,6 +126,26 @@ payments_lhv_bank_certificate: 'eyp_pub.pem' payments_lhv_seller_private: 'kaupmees_priv.pem' payments_lhv_seller_account: 'testvpos' +# You should list other payment intermediaries here. Each one of them needs their own class in /app/models/payments/ +payments_intermediaries: > + every_pay + +# Other intermediaries should follow this naming convention: +# payments_intermediary_url - URL to intiate payments +# payments_intermediary_seller_account - your username in the bank system +# payments_intermediary_api_user - API username, in case it's different than the seller account +# payments_intermediary_api_key - API key given to you by intermediary +payments_every_pay_url: 'https://igw-demo.every-pay.com/transactions/' +payments_every_pay_seller_account: 'account' +payments_every_pay_api_user: 'api_user' +payments_every_pay_api_key: 'api_key' + user_session_timeout: '3600' # 1 hour secure_session_cookies: 'false' # true|false same_site_session_cookies: 'false' # false|strict|lax + + +# Since the keys for staging are absent from the repo, we need to supply them separate for testing. +test: + payments_seb_bank_certificate: 'test/fixtures/files/seb_bank_cert.pem' + payments_seb_seller_private: 'test/fixtures/files/seb_seller_key.pem' diff --git a/test/integration/registrar/invoices/list_test.rb b/test/integration/registrar/invoices/list_test.rb index 14b19c3e3..b5a61af5b 100644 --- a/test/integration/registrar/invoices/list_test.rb +++ b/test/integration/registrar/invoices/list_test.rb @@ -12,28 +12,15 @@ class ListInvoicesTest < ActionDispatch::IntegrationTest assert_text "Your current account balance is 100,00 EUR" end - - def test_show_single_invoice - @invoice = invoices(:valid) - @registrar_invoices = [] - @registrar_invoices << @invoice - - visit registrar_invoices_path - assert_text "Unpaid", count: 1 - assert_text "Invoice no.", count: 1 - end - - # This bastard fails, only unpaid invoice is attached to the registrar - # TODO: Fix and uncomment def test_show_multiple_invoices - @invoices = invoices(:valid, :cancelled) + @invoices = invoices @registrar_invoices = [] @invoices.each do |invoice| @registrar_invoices << invoice end visit registrar_invoices_path - assert_text "Unpaid", count: 2 - assert_text "Invoice no.", count: 2 + assert_text "Unpaid", count: 5 + assert_text "Invoice no.", count: 7 end end diff --git a/test/integration/registrar/invoices/new_invoice_payment_test.rb b/test/integration/registrar/invoices/new_invoice_payment_test.rb index cee704e3f..ae830107a 100644 --- a/test/integration/registrar/invoices/new_invoice_payment_test.rb +++ b/test/integration/registrar/invoices/new_invoice_payment_test.rb @@ -2,33 +2,10 @@ require 'test_helper' class NewInvoicePaymentTest < ActionDispatch::IntegrationTest setup do - @original_methods = ENV['payment_methods'] - @original_seb_URL = ENV['seb_payment_url'] - @original_bank_certificate = ENV['seb_bank_certificate'] - @original_seller_certificate = ENV['seller_certificate'] - @original_ep_url = ENV['every_pay_payment_url'] - ENV['payment_methods'] = 'seb, swed, every_pay' - ENV['seb_payment_url'] = 'https://example.com/seb_url' - ENV['seb_seller_account'] = 'SEB' - ENV['seb_bank_certificate'] = 'test/fixtures/files/seb_bank_cert.pem' - ENV['seb_seller_certificate'] = 'test/fixtures/files/seb_seller_key.pem' - ENV['every_pay_payment_url'] = 'https://example.com/every_pay_url' @user = users(:api_bestnames) - @original_vat_rate = @user.registrar.vat_rate - @user.registrar.vat_rate = 0.2 - login_as @user end - teardown do - ENV['every_pay_payment_url'] = @original_ep_url - ENV['payment_methods'] = @original_methods - ENV['seb_payment_url'] = @original_seb_URL - ENV['seb_bank_certificate'] = @original_bank_certificate - ENV['seb_seller_certificate'] = @original_seller_certificate - @user.registrar.vat_rate = @original_vat_rate - end - def create_invoice_and_visit_its_page visit registrar_invoices_path click_link_or_button 'Add deposit' @@ -41,20 +18,19 @@ class NewInvoicePaymentTest < ActionDispatch::IntegrationTest create_invoice_and_visit_its_page click_link_or_button 'Seb' form = page.find('form') - assert_equal 'https://example.com/seb_url', form['action'] + assert_equal 'https://www.seb.ee/cgi-bin/dv.sh/ipank.r', form['action'] assert_equal 'post', form['method'] assert_equal '220.00', form.find_by_id('VK_AMOUNT', visible: false).value end def test_create_new_Every_Pay_payment create_invoice_and_visit_its_page - save_and_open_page click_link_or_button 'Every pay' expected_hmac_fields = 'account_id,amount,api_username,callback_url,' + 'customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' form = page.find('form') - assert_equal 'https://example.com/every_pay_url', form['action'] + assert_equal 'https://igw-demo.every-pay.com/transactions/', form['action'] assert_equal 'post', form['method'] assert_equal expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value assert_equal '220.0', form.find_by_id('amount', visible: false).value diff --git a/test/integration/registrar/invoices/new_test.rb b/test/integration/registrar/invoices/new_test.rb index bb398ecde..89a3dd8a3 100644 --- a/test/integration/registrar/invoices/new_test.rb +++ b/test/integration/registrar/invoices/new_test.rb @@ -35,27 +35,6 @@ class NewInvoiceTest < ActionDispatch::IntegrationTest assert_text 'Pay invoice' end - def test_create_new_invoices_and_display_a_list_of_them - visit registrar_invoices_path - click_link_or_button 'Add deposit' - fill_in 'Amount', with: '200.00' - fill_in 'Description', with: 'My first invoice' - click_link_or_button 'Add' - - visit registrar_invoices_path - click_link_or_button 'Add deposit' - fill_in 'Amount', with: '300.00' - fill_in 'Description', with: 'My second invoice' - click_link_or_button 'Add' - - visit registrar_invoices_path - assert_text "Unpaid", count: 2 - assert_text "Invoice no. 131050" - assert_text "Invoice no. 131051" - assert_text "240,00" - assert_text "360,00" - end - # This test case should fail once issue #651 gets fixed def test_create_new_invoice_with_amount_0_goes_through visit registrar_invoices_path diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb index 14ec2b6cb..5297a530d 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payments/bank_link_test.rb @@ -3,15 +3,6 @@ require 'test_helper' class BankLinkTest < ActiveSupport::TestCase def setup super - - @original_methods = ENV['payment_methods'] - @original_seb_URL = ENV['seb_payment_url'] - ENV['payment_methods'] = 'seb, swed, credit_card' - ENV['seb_payment_url'] = 'https://example.com/seb_url' - ENV['seb_seller_account'] = 'SEB' - ENV['seb_bank_certificate'] = 'test/fixtures/files/seb_bank_cert.pem' - ENV['seb_seller_certificate'] = 'test/fixtures/files/seb_seller_key.pem' - @invoice = invoices(:valid) params = {return_url: 'return.url', response_url: 'response_url'} @bank_link = Payments::BankLink.new('seb', @invoice, params) @@ -21,9 +12,6 @@ class BankLinkTest < ActiveSupport::TestCase def teardown super - - ENV['payment_methods'] = @original_methods - ENV['seb_payment_url'] = @original_seb_URL travel_back end From f6b1db2ccee9ddc1d49d6e5b23252c23d41fa7a1 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Thu, 19 Apr 2018 10:44:40 +0300 Subject: [PATCH 04/16] Fix leaking test --- .../registrar/payments_controller.rb | 19 ++-- app/models/payments/bank_link.rb | 4 +- spec/factories/registrar.rb | 1 - test/fixtures/bank_transactions.yml | 5 + test/fixtures/invoices.yml | 4 +- .../registrar/billing/balance_top_up_test.rb | 3 + .../invoices/new_invoice_payment_test.rb | 16 +-- .../registrar/invoices/new_test.rb | 8 -- .../invoices/payment_callback_test.rb | 0 .../registrar/invoices/payment_return_test.rb | 99 +++++++++++++++++++ test/models/payments/bank_link_test.rb | 2 +- test/models/registry_test.rb | 4 + 12 files changed, 134 insertions(+), 31 deletions(-) create mode 100644 test/integration/registrar/invoices/payment_callback_test.rb create mode 100644 test/integration/registrar/invoices/payment_return_test.rb diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index d70dcce7e..2998ecbc7 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -6,25 +6,19 @@ class Registrar skip_before_action :authenticate_user!, :check_ip_restriction, only: [:back, :callback] # before_action :check_bank - # to handle existing model we should - # get invoice_id and then get number - # build BankTransaction without connection with right reference number - # do not connect transaction and invoice # TODO: Refactor to :new def pay invoice = Invoice.find(params[:invoice_id]) opts = { return_url: self.registrar_return_payment_with_url(params[:bank], invoice_id: invoice.id), # TODO: Add required URL - response_url: "https://5fd921b0.ngrok.io/registrar/pay/callback/every_pay" + response_url: "https://53e21cc8.ngrok.io/registrar/pay/callback/every_pay" } @payment = ::Payments.create_with_type(params[:bank], invoice, opts) @payment.create_transaction end - # connect invoice and transaction - # both back and IPN # TODO: Refactor to be restful def back invoice = Invoice.find(params[:invoice_id]) @@ -60,11 +54,14 @@ class Registrar private - # def banks - # ENV['payments_banks'].split(",").map(&:strip) - # end + def check_supported_payment_method + unless supported_payment_method? + raise StandardError.new("Not supported payment method") + end + end - def check_bank + + def supported_payment_method? raise StandardError.new("Not Implemented bank") unless banks.include?(params[:bank]) end end diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 1ae0436cd..8451f676f 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -1,7 +1,7 @@ module Payments class BankLink < Base # TODO: Remove magic numbers, convert certain fields to proper constants - # TODO: Remove hashrockets + # DONE: Remove hashrockets def form_fields @fields ||= hash = {} hash["VK_SERVICE"] = "1012" @@ -36,6 +36,8 @@ module Payments private + SUCCESS_FIELDS = + def validate_success pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze diff --git a/spec/factories/registrar.rb b/spec/factories/registrar.rb index 90ea38a45..ab46553a0 100644 --- a/spec/factories/registrar.rb +++ b/spec/factories/registrar.rb @@ -7,7 +7,6 @@ FactoryBot.define do city 'test' state 'test' zip 'test' - vat_rate 0.1 email 'test@test.com' country_code 'EE' accounting_customer_code 'test' diff --git a/test/fixtures/bank_transactions.yml b/test/fixtures/bank_transactions.yml index b0b4d661c..290be1597 100644 --- a/test/fixtures/bank_transactions.yml +++ b/test/fixtures/bank_transactions.yml @@ -1,3 +1,8 @@ one: sum: 1 currency: EUR + +for_payments_test: + description: "Order nr. 1" + currency: "EUR" + iban: "1234" diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index c4a8037a3..71189f6b6 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -34,4 +34,6 @@ overdue: for_payments_test: <<: *DEFAULTS - total: 100.00 + total: 12.00 + id: 1 + number: 1 diff --git a/test/integration/registrar/billing/balance_top_up_test.rb b/test/integration/registrar/billing/balance_top_up_test.rb index c77c9ff37..15face70c 100644 --- a/test/integration/registrar/billing/balance_top_up_test.rb +++ b/test/integration/registrar/billing/balance_top_up_test.rb @@ -6,6 +6,7 @@ class BalanceTopUpTest < ActionDispatch::IntegrationTest end def test_creates_new_invoice + original_vat_prc = Setting.registry_vat_prc Setting.registry_vat_prc = 0.1 visit registrar_invoices_url @@ -21,5 +22,7 @@ class BalanceTopUpTest < ActionDispatch::IntegrationTest assert_equal BigDecimal(10), invoice.vat_rate assert_equal BigDecimal('28.05'), invoice.total assert_text 'Please pay the following invoice' + + Setting.registry_vat_prc = original_vat_prc end end diff --git a/test/integration/registrar/invoices/new_invoice_payment_test.rb b/test/integration/registrar/invoices/new_invoice_payment_test.rb index ae830107a..c3f48e3d0 100644 --- a/test/integration/registrar/invoices/new_invoice_payment_test.rb +++ b/test/integration/registrar/invoices/new_invoice_payment_test.rb @@ -18,21 +18,21 @@ class NewInvoicePaymentTest < ActionDispatch::IntegrationTest create_invoice_and_visit_its_page click_link_or_button 'Seb' form = page.find('form') - assert_equal 'https://www.seb.ee/cgi-bin/dv.sh/ipank.r', form['action'] - assert_equal 'post', form['method'] - assert_equal '220.00', form.find_by_id('VK_AMOUNT', visible: false).value + assert_equal('https://www.seb.ee/cgi-bin/dv.sh/ipank.r', form['action']) + assert_equal('post', form['method']) + assert_equal('240.00', form.find_by_id('VK_AMOUNT', visible: false).value) end def test_create_new_Every_Pay_payment create_invoice_and_visit_its_page click_link_or_button 'Every pay' expected_hmac_fields = 'account_id,amount,api_username,callback_url,' + - 'customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' + 'customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' form = page.find('form') - assert_equal 'https://igw-demo.every-pay.com/transactions/', form['action'] - assert_equal 'post', form['method'] - assert_equal expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value - assert_equal '220.0', form.find_by_id('amount', visible: false).value + assert_equal('https://igw-demo.every-pay.com/transactions/', form['action']) + assert_equal('post', form['method']) + assert_equal(expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value) + assert_equal('240.0', form.find_by_id('amount', visible: false).value) end end diff --git a/test/integration/registrar/invoices/new_test.rb b/test/integration/registrar/invoices/new_test.rb index 89a3dd8a3..35957dddc 100644 --- a/test/integration/registrar/invoices/new_test.rb +++ b/test/integration/registrar/invoices/new_test.rb @@ -4,14 +4,6 @@ class NewInvoiceTest < ActionDispatch::IntegrationTest setup do @user = users(:api_bestnames) login_as @user - @original_vat_rate = @user.registrar.vat_rate - @user.registrar.vat_rate = 0.2 - end - - teardown do - @user.registrar.vat_rate = @original_vat_rate - AccountActivity.destroy_all - Invoice.destroy_all end def test_show_balance diff --git a/test/integration/registrar/invoices/payment_callback_test.rb b/test/integration/registrar/invoices/payment_callback_test.rb new file mode 100644 index 000000000..e69de29bb diff --git a/test/integration/registrar/invoices/payment_return_test.rb b/test/integration/registrar/invoices/payment_return_test.rb new file mode 100644 index 000000000..9b4aef46d --- /dev/null +++ b/test/integration/registrar/invoices/payment_return_test.rb @@ -0,0 +1,99 @@ +require 'test_helper' + +class PaymentReturnTest < ActionDispatch::IntegrationTest + setup do + @user = users(:api_bestnames) + login_as @user + end + + def create_invoice_with_items + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) + + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item + @user.registrar.invoices << @invoice + end + + def every_pay_request_params + { + nonce: "392f2d7748bc8cb0d14f263ebb7b8932", + timestamp: "1524136727", + api_username: "ca8d6336dd750ddb", + transaction_result: "completed", + payment_reference: "fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56", + payment_state: "settled", + amount: "12.0", + order_reference: "e468a2d59a731ccc546f2165c3b1a6", + account_id: "EUR3D1", + cc_type: "master_card", + cc_last_four_digits: "0487", + cc_month: "10", + cc_year: "2018", + cc_holder_name: "John Doe", + hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", + hmac: "72fc94f117389cf5d34dba18a18d20886edb2bbb", + invoice_id: "12900000", + } + end + + def bank_link_request_params + { + "VK_SERVICE": "1111", + "VK_VERSION": "008", + "VK_SND_ID": "KIAupMEE's", + "VK_AMOUNT": "12.00", + "VK_REC_ID": "1235", + "VK_CURR": "EUR", + "VK_T_NO": "1234", + "VK_STAMP": "ahdfjkadsfhjk", + "VK_REC_ACC": "1234", + "VK_REC_NAME": "John Doe", + "VK_SND_ACC": "1234", + "VK_SND_NAME": "Doe John", + "VK_REF": "1234", + "VK_MSG": "Foo", + "VK_T_DATETIME": "2018-04-19T15:52:59+0300", + invoice_id: "12900000", + } + end + + def test_every_pay_return_creates_activity_redirects_to_invoice_path + create_invoice_with_items + request_params = every_pay_request_params.merge(invoice_id: @invoice.id) + + account_activity_count = AccountActivity.count + post "/registrar/pay/return/every_pay", request_params + assert_equal(302, response.status) + assert_redirected_to(registrar_invoice_path(@invoice)) + assert_equal(account_activity_count + 1, AccountActivity.count) + end + + def test_Every_Pay_return_raises_RecordNotFound + create_invoice_with_items + request_params = every_pay_request_params.merge(invoice_id: "178907") + assert_raises(ActiveRecord::RecordNotFound) do + post "/registrar/pay/return/every_pay", request_params + end + end + + def test_bank_link_return_redirects_to_invoice_paths + skip("Need credentials to model the expected request") + create_invoice_with_items + request_params = every_pay_request_params.merge(invoice_id: @invoice.id) + account_activity_count = AccountActivity.count + + post "/registrar/pay/return/seb", request_params + assert_equal(302, response.status) + assert_redirected_to(registrar_invoice_path(@invoice)) + assert_equal(account_activity_count + 1, AccountActivity.count) + end + + def test_bank_link_return + create_invoice_with_items + request_params = bank_link_request_params.merge(invoice_id: "178907") + assert_raises(ActiveRecord::RecordNotFound) do + post "/registrar/pay/return/seb", request_params + end + end +end diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb index 5297a530d..ef5b26d02 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payments/bank_link_test.rb @@ -4,7 +4,7 @@ class BankLinkTest < ActiveSupport::TestCase def setup super @invoice = invoices(:valid) - params = {return_url: 'return.url', response_url: 'response_url'} + params = {return_url: 'return.url', response_url: 'response.url'} @bank_link = Payments::BankLink.new('seb', @invoice, params) travel_to '2018-04-01 00:30' diff --git a/test/models/registry_test.rb b/test/models/registry_test.rb index 90a603e15..80c88c8bf 100644 --- a/test/models/registry_test.rb +++ b/test/models/registry_test.rb @@ -10,7 +10,11 @@ class RegistryTest < ActiveSupport::TestCase end def test_vat_rate + original_vat_prc = Setting.registry_vat_prc Setting.registry_vat_prc = 0.25 + assert_equal BigDecimal(25), @registry.vat_rate + + Setting.registry_vat_prc = original_vat_prc end end From e066b1d24683be626e07d2fad9cff1acd42d8160 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Fri, 20 Apr 2018 14:29:17 +0300 Subject: [PATCH 05/16] Fix timezone problem in tests --- app/models/payments/bank_link.rb | 2 - app/models/payments/every_pay.rb | 2 +- config/application-example.yml | 2 +- .../registrar/invoices/payment_return_test.rb | 4 +- test/models/payments/bank_link_test.rb | 4 +- test/models/payments/every_pay_test.rb | 99 +++++++++++-------- 6 files changed, 66 insertions(+), 47 deletions(-) diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 8451f676f..624cd757f 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -36,8 +36,6 @@ module Payments private - SUCCESS_FIELDS = - def validate_success pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index e3b2a03f5..a7b28099a 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -56,7 +56,7 @@ module Payments timestamp: Time.now.to_i.to_s, callback_url: response_url, customer_url: return_url, - amount: invoice.total, + amount: number_with_precision(invoice.total, precision: 2), order_reference: SecureRandom.hex(15), transaction_type: 'charge', hmac_fields: '' diff --git a/config/application-example.yml b/config/application-example.yml index 1214ea5d2..8cfd14d7a 100644 --- a/config/application-example.yml +++ b/config/application-example.yml @@ -136,7 +136,7 @@ payments_intermediaries: > # payments_intermediary_api_user - API username, in case it's different than the seller account # payments_intermediary_api_key - API key given to you by intermediary payments_every_pay_url: 'https://igw-demo.every-pay.com/transactions/' -payments_every_pay_seller_account: 'account' +payments_every_pay_seller_account: 'EUR3D1' payments_every_pay_api_user: 'api_user' payments_every_pay_api_key: 'api_key' diff --git a/test/integration/registrar/invoices/payment_return_test.rb b/test/integration/registrar/invoices/payment_return_test.rb index 9b4aef46d..d897bc0ed 100644 --- a/test/integration/registrar/invoices/payment_return_test.rb +++ b/test/integration/registrar/invoices/payment_return_test.rb @@ -23,7 +23,7 @@ class PaymentReturnTest < ActionDispatch::IntegrationTest transaction_result: "completed", payment_reference: "fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56", payment_state: "settled", - amount: "12.0", + amount: "12.00", order_reference: "e468a2d59a731ccc546f2165c3b1a6", account_id: "EUR3D1", cc_type: "master_card", @@ -32,7 +32,7 @@ class PaymentReturnTest < ActionDispatch::IntegrationTest cc_year: "2018", cc_holder_name: "John Doe", hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", - hmac: "72fc94f117389cf5d34dba18a18d20886edb2bbb", + hmac: "efac1c732835668cd86023a7abc140506c692f0d", invoice_id: "12900000", } end diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb index ef5b26d02..943d7f37a 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payments/bank_link_test.rb @@ -4,7 +4,7 @@ class BankLinkTest < ActiveSupport::TestCase def setup super @invoice = invoices(:valid) - params = {return_url: 'return.url', response_url: 'response.url'} + params = { return_url: 'return.url', response_url: 'response.url' } @bank_link = Payments::BankLink.new('seb', @invoice, params) travel_to '2018-04-01 00:30' @@ -15,7 +15,7 @@ class BankLinkTest < ActiveSupport::TestCase travel_back end - def test_is_not_valid_without_response + def test_response_is_not_valid_without_response assert_equal false, @bank_link.valid_response? end end diff --git a/test/models/payments/every_pay_test.rb b/test/models/payments/every_pay_test.rb index 2a843b088..790de2b6c 100644 --- a/test/models/payments/every_pay_test.rb +++ b/test/models/payments/every_pay_test.rb @@ -1,64 +1,85 @@ require 'test_helper' class EveryPayTest < ActiveSupport::TestCase - def setup - super + setup do + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) - @original_methods = ENV['payment_methods'] - @original_seb_URL = ENV['seb_payment_url'] - ENV['payment_methods'] = 'seb, swed, credit_card' - ENV['seb_payment_url'] = 'https://example.com/seb_url' - ENV['seb_seller_account'] = 'SEB' - ENV['seb_bank_certificate'] = 'test/fixtures/files/seb_bank_cert.pem' - ENV['seb_seller_certificate'] = 'test/fixtures/files/seb_seller_key.pem' + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item - @invoice = invoices(:valid) params = { response: { - utf8:"✓", - _method: "put", - authenticity_token: "OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==", - nonce: "8a9063b3c13edb00522d446481cb1886", - timestamp: "1524036436", - api_username: "ca8d6336dd750ddb", - transaction_result: "completed", - payment_reference: "3380fc36f02a7c1d2b0a700794e7a6ef8683191b3f0dc88b762e72c6e573adaf", - payment_state: "settled", - amount: "240.0", - order_reference: "59fa7f639211d1e14952bad73ccb50", - account_id: "EUR3D1", - cc_type: "master_card", + utf8: "✓", + _method: "put", + authenticity_token: "OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==", + nonce: "392f2d7748bc8cb0d14f263ebb7b8932", + timestamp: "1524136727", + api_username: "ca8d6336dd750ddb", + transaction_result: "completed", + payment_reference: "fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56", + payment_state: "settled", + amount: "12.00", + order_reference: "e468a2d59a731ccc546f2165c3b1a6", + account_id: "EUR3D1", + cc_type: "master_card", cc_last_four_digits: "0487", - cc_month: "10", - cc_year: "2018", - cc_holder_name: "John Doe", - hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", - hmac: "d5b11b001b248532ad5af529f072b5b76347936a", - controller: "registrar/payments", - action: "back", - bank: "every_pay" + cc_month: "10", + cc_year: "2018", + cc_holder_name: "John Doe", + hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", + hmac: "efac1c732835668cd86023a7abc140506c692f0d", + invoice_id: "1", }, } @every_pay = Payments::EveryPay.new('every_pay', @invoice, params) + @other_pay = Payments::EveryPay.new('every_pay', @invoice, {}) - travel_to '2018-04-01 00:30' + # To avoid problems with time conversion. + travel_to Time.at(1522542600) end - def teardown - super - - ENV['payment_methods'] = @original_methods - ENV['seb_payment_url'] = @original_seb_URL + teardown do travel_back end def test_form_fields + expected_fields = { + api_username: "api_user", + account_id: "EUR3D1", + timestamp: "1522542600", + amount: "12.00", + order_reference: "Order nr. 1", + transaction_type: "charge", + hmac_fields: "account_id,amount,api_username,callback_url,customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type" + } + form_fields = @every_pay.form_fields + expected_fields.each do |k, v| + assert_equal(v, form_fields[k]) + end end - def test_is_not_valid_without_response + def test_valid_response? + assert(@every_pay.valid_response?) + refute(@other_pay.valid_response?) end - def test_validation + def test_settled_payment? + assert(@every_pay.settled_payment?) + other_pay = Payments::EveryPay.new( + 'every_pay', @invoice, {response: {payment_state: "CANCELLED"}} + ) + refute(other_pay.settled_payment?) + end + + def test_valid_response? + assert(@every_pay.valid_response?) + refute(@other_pay.valid_response?) + end + + def test_complete_transaction_returns_account_activity_or_nil + assert_instance_of(AccountActivity, @every_pay.complete_transaction) + refute(@other_pay.complete_transaction) end end From 663214ee49728921d3602d6a0ebae72ae031d989 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Fri, 20 Apr 2018 14:50:14 +0300 Subject: [PATCH 06/16] Remove variable fields from tests --- test/integration/registrar/invoices/new_invoice_payment_test.rb | 2 +- test/models/payments/every_pay_test.rb | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/integration/registrar/invoices/new_invoice_payment_test.rb b/test/integration/registrar/invoices/new_invoice_payment_test.rb index c3f48e3d0..f12445157 100644 --- a/test/integration/registrar/invoices/new_invoice_payment_test.rb +++ b/test/integration/registrar/invoices/new_invoice_payment_test.rb @@ -33,6 +33,6 @@ class NewInvoicePaymentTest < ActionDispatch::IntegrationTest assert_equal('https://igw-demo.every-pay.com/transactions/', form['action']) assert_equal('post', form['method']) assert_equal(expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value) - assert_equal('240.0', form.find_by_id('amount', visible: false).value) + assert_equal('240.00', form.find_by_id('amount', visible: false).value) end end diff --git a/test/models/payments/every_pay_test.rb b/test/models/payments/every_pay_test.rb index 790de2b6c..6ed68fd9f 100644 --- a/test/models/payments/every_pay_test.rb +++ b/test/models/payments/every_pay_test.rb @@ -50,7 +50,6 @@ class EveryPayTest < ActiveSupport::TestCase account_id: "EUR3D1", timestamp: "1522542600", amount: "12.00", - order_reference: "Order nr. 1", transaction_type: "charge", hmac_fields: "account_id,amount,api_username,callback_url,customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type" } From 5dea92c0d8cdb385c26437e60e3ba3977d72ca15 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Sun, 22 Apr 2018 17:24:15 +0300 Subject: [PATCH 07/16] Add tests for Payments::BankLink --- .../payments/callbacks_controller.rb | 8 -- .../payments/every_pay_controller.rb | 29 ----- .../registrar/payments_controller.rb | 20 +-- app/models/payments.rb | 1 - app/models/payments/bank_link.rb | 117 ++++++++++++------ app/models/payments/every_pay.rb | 6 +- test/fixtures/files/seb_bank_cert.pem | 29 +++-- test/fixtures/files/seb_seller_key.pem | 31 ++--- .../invoices/payment_callback_test.rb | 47 +++++++ .../registrar/invoices/payment_return_test.rb | 33 ++--- test/models/payments/bank_link_test.rb | 111 ++++++++++++++++- test/models/payments/every_pay_test.rb | 12 +- 12 files changed, 294 insertions(+), 150 deletions(-) delete mode 100644 app/controllers/registrar/payments/callbacks_controller.rb delete mode 100644 app/controllers/registrar/payments/every_pay_controller.rb diff --git a/app/controllers/registrar/payments/callbacks_controller.rb b/app/controllers/registrar/payments/callbacks_controller.rb deleted file mode 100644 index 208b380e9..000000000 --- a/app/controllers/registrar/payments/callbacks_controller.rb +++ /dev/null @@ -1,8 +0,0 @@ -class Registrar - module Payments - class CallbacksController < BaseController - def new - end - end - end -end diff --git a/app/controllers/registrar/payments/every_pay_controller.rb b/app/controllers/registrar/payments/every_pay_controller.rb deleted file mode 100644 index b0ed34f9d..000000000 --- a/app/controllers/registrar/payments/every_pay_controller.rb +++ /dev/null @@ -1,29 +0,0 @@ -class Registrar - module Payments - class EveryPayController < BaseController - load_resource class: Invoice - skip_authorization_check only: [:new, :update] - skip_before_action :verify_authenticity_token, only: :update - - def new - set_invoice - @every_pay = EveryPayPayment.new(@invoice) - end - - def create - set_invoice - end - - def update - set_invoice - render 'complete' - end - - private - - def set_invoice - @invoice = Invoice.find(params[:invoice_id]) - end - end - end -end diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 2998ecbc7..793f0226b 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -4,27 +4,27 @@ class Registrar skip_authorization_check # actually anyone can pay, no problems at all skip_before_action :authenticate_user!, :check_ip_restriction, only: [:back, :callback] - # before_action :check_bank + before_action :check_supported_payment_method - # TODO: Refactor to :new def pay invoice = Invoice.find(params[:invoice_id]) opts = { - return_url: self.registrar_return_payment_with_url(params[:bank], invoice_id: invoice.id), - # TODO: Add required URL - response_url: "https://53e21cc8.ngrok.io/registrar/pay/callback/every_pay" + return_url: self.registrar_return_payment_with_url( + params[:bank], invoice_id: invoice.id + ), + response_url: self.registrar_response_payment_with_url( + params[:bank], invoice_id: invoice.id + ) } @payment = ::Payments.create_with_type(params[:bank], invoice, opts) @payment.create_transaction end - - # TODO: Refactor to be restful def back invoice = Invoice.find(params[:invoice_id]) opts = { response: params } @payment = ::Payments.create_with_type(params[:bank], invoice, opts) - if @payment.valid_response? && @payment.settled_payment? + if @payment.valid_response_from_intermediary? && @payment.settled_payment? @payment.complete_transaction if invoice.binded? @@ -43,7 +43,7 @@ class Registrar opts = { response: params } @payment = ::Payments.create_with_type(params[:bank], invoice, opts) - if @payment.valid_response? && @payment.settled_payment? + if @payment.valid_response_from_intermediary? && @payment.settled_payment? @payment.complete_transaction if invoice.binded? @@ -62,7 +62,7 @@ class Registrar def supported_payment_method? - raise StandardError.new("Not Implemented bank") unless banks.include?(params[:bank]) + Payments::PAYMENT_METHODS.include?(params[:bank]) end end end diff --git a/app/models/payments.rb b/app/models/payments.rb index 5d0e8f0a8..f379bd455 100644 --- a/app/models/payments.rb +++ b/app/models/payments.rb @@ -9,7 +9,6 @@ module Payments if PAYMENT_BANKLINK_BANKS.include?(type) BankLink.new(type, invoice, opts) elsif type == 'every_pay' - # TODO: refactor to be variable EveryPay.new(type, invoice, opts) end end diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 624cd757f..35004e487 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -1,11 +1,25 @@ module Payments class BankLink < Base - # TODO: Remove magic numbers, convert certain fields to proper constants - # DONE: Remove hashrockets + BANK_LINK_VERSION = '008' + + NEW_TRANSACTION_SERVICE_NUMBER = '1012' + SUCCESSFUL_PAYMENT_SERVICE_NUMBER = '1111' + CANCELLED_PAYMENT_SERVICE_NUMBER = '1911' + + NEW_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT + VK_CURR VK_REF VK_MSG VK_RETURN VK_CANCEL + VK_DATETIME).freeze + SUCCESS_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP + VK_T_NO VK_AMOUNT VK_CURR VK_REC_ACC VK_REC_NAME + VK_SND_ACC VK_SND_NAME VK_REF VK_MSG + VK_T_DATETIME).freeze + CANCEL_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP + VK_REF VK_MSG).freeze + def form_fields - @fields ||= hash = {} - hash["VK_SERVICE"] = "1012" - hash["VK_VERSION"] = "008" + hash = {} + hash["VK_SERVICE"] = NEW_TRANSACTION_SERVICE_NUMBER + hash["VK_VERSION"] = BANK_LINK_VERSION hash["VK_SND_ID"] = seller_account hash["VK_STAMP"] = invoice.number hash["VK_AMOUNT"] = number_with_precision(invoice.total, precision: 2, separator: ".") @@ -14,78 +28,105 @@ module Payments hash["VK_MSG"] = invoice.order hash["VK_RETURN"] = return_url hash["VK_CANCEL"] = return_url - hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z") + hash["VK_DATETIME"] = Time.zone.now.strftime("%Y-%m-%dT%H:%M:%S%z") hash["VK_MAC"] = calc_mac(hash) hash["VK_ENCODING"] = "UTF-8" hash["VK_LANG"] = "ENG" hash end - def valid_response? + def valid_response_from_intermediary? return false unless response case response["VK_SERVICE"] - when "1111" - validate_success && validate_amount && validate_currency - when "1911" - validate_cancel + when SUCCESSFUL_PAYMENT_SERVICE_NUMBER + valid_successful_transaction? + when CANCELLED_PAYMENT_SERVICE_NUMBER + valid_cancel_notice? else false end end + def complete_transaction + return unless valid_successful_transaction? + + transaction = BankTransaction.find_by( + description: invoice.order, + currency: invoice.currency, + iban: invoice.seller_iban + ) + + transaction.sum = response['VK_AMOUNT'] + transaction.bank_reference = response['VK_T_NO'] + transaction.buyer_bank_code = response["VK_SND_ID"] + transaction.buyer_iban = response["VK_SND_ACC"] + transaction.buyer_name = response["VK_SND_NAME"] + transaction.paid_at = Time.parse(response["VK_T_DATETIME"]) + + transaction.save! + transaction.autobind_invoice + end + + def settled_payment? + response["VK_SERVICE"] == SUCCESSFUL_PAYMENT_SERVICE_NUMBER + end + private - def validate_success - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR - VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze - - @validate_success ||= begin - data = pars.map { |e| prepend_size(response[e]) }.join - verify_mac(data, response["VK_MAC"]) - end + def valid_successful_transaction? + return false unless valid_success_notice? + return false unless valid_amount? + return false unless valid_currency? + true end - def validate_cancel - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_REF VK_MSG).freeze - @validate_cancel ||= begin - data = pars.map { |e| prepend_size(response[e]) }.join - verify_mac(data, response["VK_MAC"]) - end + def valid_cancel_notice? + valid_mac?(response, CANCEL_MESSAGE_KEYS) end - def validate_amount - source = number_with_precision(BigDecimal.new(response["VK_AMOUNT"].to_s), precision: 2, separator: ".") - target = number_with_precision(invoice.total, precision: 2, separator: ".") + def valid_success_notice? + valid_mac?(response, SUCCESS_MESSAGE_KEYS) + end + + def valid_amount? + source = number_with_precision( + BigDecimal.new(response["VK_AMOUNT"]), precision: 2, separator: "." + ) + target = number_with_precision( + invoice.total, precision: 2, separator: "." + ) source == target end - def validate_currency + def valid_currency? invoice.currency == response["VK_CURR"] end def sign(data) private_key = OpenSSL::PKey::RSA.new(File.read(seller_certificate)) - signed_data = private_key.sign(OpenSSL::Digest::SHA1.new, data) signed_data = Base64.encode64(signed_data).gsub(/\n|\r/, '') signed_data end + def calc_mac(fields) + pars = NEW_MESSAGE_KEYS + data = pars.map { |e| prepend_size(fields[e]) }.join + sign(data) + end + + def valid_mac?(hash, keys) + data = keys.map { |e| prepend_size(hash[e]) }.join + verify_mac(data, hash["VK_MAC"]) + end + def verify_mac(data, mac) bank_public_key = OpenSSL::X509::Certificate.new(File.read(bank_certificate)).public_key bank_public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(mac), data) end - def calc_mac(fields) - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT VK_CURR VK_REF - VK_MSG VK_RETURN VK_CANCEL VK_DATETIME).freeze - data = pars.map { |e| prepend_size(fields[e]) }.join - - sign(data) - end - def prepend_size(value) value = (value || "").to_s.strip string = "" diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index a7b28099a..0556f3c5a 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -1,7 +1,5 @@ module Payments class EveryPay < Base - - # TODO: Move to setting or environment USER = ENV['payments_every_pay_api_user'].freeze KEY = ENV['payments_every_pay_api_key'].freeze ACCOUNT_ID = ENV['payments_every_pay_seller_account'].freeze @@ -21,7 +19,7 @@ module Payments base_json end - def valid_response? + def valid_response_from_intermediary? return false unless response valid_hmac? && valid_amount? && valid_account? end @@ -31,7 +29,7 @@ module Payments end def complete_transaction - return unless valid_response? && settled_payment? + return unless valid_response_from_intermediary? && settled_payment? transaction = BankTransaction.find_by( description: invoice.order, diff --git a/test/fixtures/files/seb_bank_cert.pem b/test/fixtures/files/seb_bank_cert.pem index 09a8d326b..a98508d36 100644 --- a/test/fixtures/files/seb_bank_cert.pem +++ b/test/fixtures/files/seb_bank_cert.pem @@ -1,16 +1,15 @@ -----BEGIN CERTIFICATE----- -MIICmTCCAgICCQC9Iax+je2Q9DANBgkqhkiG9w0BAQUFADCBkDELMAkGA1UEBhMC -RUUxETAPBgNVBAgMCEhhcmp1bWFhMRAwDgYDVQQHDAdUYWxsaW5uMREwDwYDVQQK -DAhFZGljeSBPVTERMA8GA1UECwwIYmFua2xpbmsxFjAUBgNVBAMMDXBhbmdhbGlu -ay5uZXQxHjAcBgkqhkiG9w0BCQEWD3RhbmVsQGVkaWN5LmNvbTAeFw0xNTAyMDIw -OTAyMzZaFw0zNTAxMjgwOTAyMzZaMIGQMQswCQYDVQQGEwJFRTERMA8GA1UECAwI -SGFyanVtYWExEDAOBgNVBAcMB1RhbGxpbm4xETAPBgNVBAoMCEVkaWN5IE9VMREw -DwYDVQQLDAhiYW5rbGluazEWMBQGA1UEAwwNcGFuZ2FsaW5rLm5ldDEeMBwGCSqG -SIb3DQEJARYPdGFuZWxAZWRpY3kuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQDTwWcJvpfFkPmSYXVCUJLoCya2YPeuzBcQww19KG+ErKLr+lAjhoER5ViW -UD7KMDhViBzWpJZ0LqvAkamWyyjM5e0a2aUe71qI8yU8W2oZXRrmKQ4H1UxhaOGt -aSGLIycY31y+aaKrRM8teMDvRSyBq08Lvk0e0cC/nbVIVvaS7QIDAQABMA0GCSqG -SIb3DQEBBQUAA4GBAKhMeT9HhdOvmWy17kQjVYg4I0b/9bO/0DI6MqTiyziaSvcz -DXTRwWKCa+dqx9yQ4aM7YBBK3d2y+aRnfdxxAQ1ThnIHuzoYSTlmFYhfpp6KroTz -/01tSFqMZ9dZemSspCWgkXkEiBiUA45AEmOFSRSzWv7H8IOmFhe5ijmGmdna ------END CERTIFICATE----- \ No newline at end of file +MIICVTCCAb4CCQCdHk6fGGIg9DANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJF +RTERMA8GA1UECAwISGFyanVtYWExEDAOBgNVBAcMB1RhbGxpbm4xJTAjBgNVBAoM +HEVzdG9uaWFuIEludGVybmV0IEZvdW5kYXRpb24xFDASBgNVBAMMC2ludGVybmV0 +LmVlMB4XDTE4MDQyMTEyNDEyMloXDTE4MDUyMTEyNDEyMlowbzELMAkGA1UEBhMC +RUUxETAPBgNVBAgMCEhhcmp1bWFhMRAwDgYDVQQHDAdUYWxsaW5uMSUwIwYDVQQK +DBxFc3RvbmlhbiBJbnRlcm5ldCBGb3VuZGF0aW9uMRQwEgYDVQQDDAtpbnRlcm5l +dC5lZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4QPTaFdN+03vC63vgcSd +OsURjrt/eslJkPXr53VgkcFoD2AI+z1AoUbOMJ/FfXb+iY4o70we3YeRP8SeaDFn +pjOlSmS+DTsh5s3DCahbdbFzvyBDD5A4yKRaVRSCWFEjC684Uvg9Pf/ifP6GxHN6 +uVFg9/YhkS9XwfE0deJhxUUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCKC6bL+4Eu ++Dz+RQEZ9IEerZSKnnV2mygN9usddg46BnMqceWCA19Ei71C2UQsVD2e+7XkLjrl +0IDGciQqAjOUp4KKG+jQbtlcP0BBvP6CnirwqFfeV0XLWKapLetDjtdlmACAtHXj +8U0YFVbj5GGPJWAfAPnzpsiTxnQIinXNZw== +-----END CERTIFICATE----- diff --git a/test/fixtures/files/seb_seller_key.pem b/test/fixtures/files/seb_seller_key.pem index 827d669ea..be1febf79 100644 --- a/test/fixtures/files/seb_seller_key.pem +++ b/test/fixtures/files/seb_seller_key.pem @@ -1,15 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQDk3bIdDgZzsQQ697A5F2ZTOJppp6jGHig3pCsXf7qNBZr4Icjd -PNpnfjYTXXg4/50yXQZu1Gz4bfNNJf6pKyS19U5SM+vAs4CA6rr1E4mxv9nfSIBA -I0Vc+I2pXw2HAhvUiDryPv9meAHcVbKjQ0Q3944yFUhTMfbPxEYvx89uswIDAQAB -AoGAajmDu/yQfg4BGqVvw2/a7HFvKe7JZPsGS50E6yk7msypOtXjdtwRustXqfFO -JZZujbujirlJwpy1um8SHc6KgJEJ7Dg/j6Q2rFQvErmCwqf+hEjF0s1ZCcKL5WvY -MZ76qTFQ3gYfWGh/7pFJn7cdbDxFo1KzfoXhvieH4SJhEtECQQD5UuR5uI2SmvGT -n5XkQY+p0Ba8vUSdCTyOYCOkmUXc9ytuxH+Hf2Ad01iFQbjeo8NMjlbRADSlyobI -XqP5FVqtAkEA6v6QzdhOngYxYETFb1215krapX9A6dT8ncVuxX/OSh78lkoRO8oI -AMzYiXVVga+xvM8Uk8o0YlN4UnR+K9t63wJABVddRa5KeiWPn1X/5A/zf/PRSOHV -IngcMACnQtN1x7IT4B+di82SxZDNiK1LxJlFidJS0c9rUVHxaUF9ycxHUQJAElVk -BLtAfvGqvoD/Ck48V8g1QL4p2VRllQWHO99Zv8ylFjCXIZwEfdN9fVPrJOAJNNrP -FyyqY5VxiLVP9qn77wJAEzTyrw3WO09wphaA2daTAAwiui6h+J5gac0rgsocp1OI -vs4c+iqi7UdxCSic7HvlwdLxjnIPIrmC6t3xwRBFxQ== ------END RSA PRIVATE KEY----- \ No newline at end of file +-----BEGIN PRIVATE KEY----- +MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOED02hXTftN7wut +74HEnTrFEY67f3rJSZD16+d1YJHBaA9gCPs9QKFGzjCfxX12/omOKO9MHt2HkT/E +nmgxZ6YzpUpkvg07IebNwwmoW3Wxc78gQw+QOMikWlUUglhRIwuvOFL4PT3/4nz+ +hsRzerlRYPf2IZEvV8HxNHXiYcVFAgMBAAECgYEAxLXAgm4YaUK3YOF9CVgmD/Oq +Jrp5dpEzs/uZcO4nLyUCYLaXA3SH5LXumYmDb+ywFvbliFVmgkn6y+GKjhHqxjhx +KtyK3w1vGVkk6RyA076vgnOEp3un7j9XXM5U93Osk25Ezzb4pqslU7nDPb1OGg2A +q4UG+zHyj9UkI2S1V10CQQD39JtA3eiSlJ4jtr7QP3/KFV3O7Sku5TTmc6aMUhja +9qZCUMaK/67aMFjl62E9vdNBb1gGg28dBo/zV0uZAdsrAkEA6FCvyzaMOOzWqz6N +/uzeU7NTW9cHNQRx1d7e3vjWhYxvvknNrFim3sH+tbTock5MeNr4d4yCYFM72Zc5 +wH/pTwJBAIrD7OMnjZIC9GGeUzluYBDzVjWJCmRBSBK0pH+hLmHUaYVxeTuvDebz +6bx6t0f7ZTAYpRW4FsYStxsDPr6ZiFMCQFh7SslKSFPyGLz2QVzj2LXmagxjtLID +tFux3A7ulb4dw/2k3HoU9dGH77xDX/kRS10IgXP/BzUq3nO8flmMHk8CQQCCnqcJ +CEA+kqwPvgQ8YdeJOBFEc4spQ+OFbLUAtMt8+9YfeWtHyUlyNhtGXmwN8kGAHcPz +qtfPVIDR4dU0uvCw +-----END PRIVATE KEY----- diff --git a/test/integration/registrar/invoices/payment_callback_test.rb b/test/integration/registrar/invoices/payment_callback_test.rb index e69de29bb..b341168d8 100644 --- a/test/integration/registrar/invoices/payment_callback_test.rb +++ b/test/integration/registrar/invoices/payment_callback_test.rb @@ -0,0 +1,47 @@ +require 'test_helper' + +class PaymentCallbackTest < ActionDispatch::IntegrationTest + setup do + @user = users(:api_bestnames) + login_as @user + end + + def create_invoice_with_items + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) + + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item + @user.registrar.invoices << @invoice + end + + def every_pay_request_params + { + nonce: "392f2d7748bc8cb0d14f263ebb7b8932", + timestamp: "1524136727", + api_username: "ca8d6336dd750ddb", + transaction_result: "completed", + payment_reference: "fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56", + payment_state: "settled", + amount: "12.00", + order_reference: "e468a2d59a731ccc546f2165c3b1a6", + account_id: "EUR3D1", + cc_type: "master_card", + cc_last_four_digits: "0487", + cc_month: "10", + cc_year: "2018", + cc_holder_name: "John Doe", + hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", + hmac: "efac1c732835668cd86023a7abc140506c692f0d", + invoice_id: "12900000", + payment_method: "every_pay" + } + end + + def test_every_pay_callback_returns_status_200 + create_invoice_with_items + request_params = every_pay_request_params.merge(invoice_id: @invoice.id) + post "/registrar/pay/callback/every_pay", request_params + assert_equal(200, response.status) + end +end diff --git a/test/integration/registrar/invoices/payment_return_test.rb b/test/integration/registrar/invoices/payment_return_test.rb index d897bc0ed..9d24fa987 100644 --- a/test/integration/registrar/invoices/payment_return_test.rb +++ b/test/integration/registrar/invoices/payment_return_test.rb @@ -34,27 +34,31 @@ class PaymentReturnTest < ActionDispatch::IntegrationTest hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", hmac: "efac1c732835668cd86023a7abc140506c692f0d", invoice_id: "12900000", + payment_method: "every_pay" } end def bank_link_request_params { - "VK_SERVICE": "1111", - "VK_VERSION": "008", - "VK_SND_ID": "KIAupMEE's", + "VK_SERVICE": "1111", + "VK_VERSION": "008", + "VK_SND_ID": "testvpos", + "VK_REC_ID": "seb", + "VK_STAMP": 1, + "VK_T_NO": "1", "VK_AMOUNT": "12.00", - "VK_REC_ID": "1235", "VK_CURR": "EUR", - "VK_T_NO": "1234", - "VK_STAMP": "ahdfjkadsfhjk", "VK_REC_ACC": "1234", - "VK_REC_NAME": "John Doe", + "VK_REC_NAME": "Eesti Internet", "VK_SND_ACC": "1234", - "VK_SND_NAME": "Doe John", - "VK_REF": "1234", - "VK_MSG": "Foo", - "VK_T_DATETIME": "2018-04-19T15:52:59+0300", - invoice_id: "12900000", + "VK_SND_NAME": "John Doe", + "VK_REF": "", + "VK_MSG": "Order nr 1", + "VK_T_DATETIME": "2018-04-01T00:30:00+0300", + "VK_MAC": "CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=", + "VK_ENCODING": "UTF-8", + "VK_LANG": "ENG", + payment_method: "seb" } end @@ -62,11 +66,9 @@ class PaymentReturnTest < ActionDispatch::IntegrationTest create_invoice_with_items request_params = every_pay_request_params.merge(invoice_id: @invoice.id) - account_activity_count = AccountActivity.count post "/registrar/pay/return/every_pay", request_params assert_equal(302, response.status) assert_redirected_to(registrar_invoice_path(@invoice)) - assert_equal(account_activity_count + 1, AccountActivity.count) end def test_Every_Pay_return_raises_RecordNotFound @@ -78,9 +80,8 @@ class PaymentReturnTest < ActionDispatch::IntegrationTest end def test_bank_link_return_redirects_to_invoice_paths - skip("Need credentials to model the expected request") create_invoice_with_items - request_params = every_pay_request_params.merge(invoice_id: @invoice.id) + request_params = bank_link_request_params.merge(invoice_id: @invoice.id) account_activity_count = AccountActivity.count post "/registrar/pay/return/seb", request_params diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb index 943d7f37a..a4655a30d 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payments/bank_link_test.rb @@ -1,13 +1,22 @@ require 'test_helper' class BankLinkTest < ActiveSupport::TestCase + # Note: Files stored in: test/fixtures/files/seb_seller_key.pem + # test/fixtures/files/seb_bank_cert.pem + # are autogenerated, they will not work against production or even staging. def setup super - @invoice = invoices(:valid) - params = { return_url: 'return.url', response_url: 'response.url' } - @bank_link = Payments::BankLink.new('seb', @invoice, params) - travel_to '2018-04-01 00:30' + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) + + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item + + travel_to '2018-04-01 00:30 +0300' + create_new_bank_link + create_completed_bank_link + create_cancelled_bank_link end def teardown @@ -15,7 +24,97 @@ class BankLinkTest < ActiveSupport::TestCase travel_back end - def test_response_is_not_valid_without_response - assert_equal false, @bank_link.valid_response? + def create_completed_bank_link + params = { + "VK_SERVICE": "1111", + "VK_VERSION": "008", + "VK_SND_ID": "testvpos", + "VK_REC_ID": "seb", + "VK_STAMP": 1, + "VK_T_NO": "1", + "VK_AMOUNT": "12.00", + "VK_CURR": "EUR", + "VK_REC_ACC": "1234", + "VK_REC_NAME": "Eesti Internet", + "VK_SND_ACC": "1234", + "VK_SND_NAME": "John Doe", + "VK_REF": "", + "VK_MSG": "Order nr 1", + "VK_T_DATETIME": "2018-04-01T00:30:00+0300", + "VK_MAC": "CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=", + "VK_ENCODING": "UTF-8", + "VK_LANG": "ENG" + }.with_indifferent_access + + @completed_bank_link = Payments::BankLink.new( + 'seb', @invoice, { response: params } + ) + end + + def create_cancelled_bank_link + params = { + "VK_SERVICE": "1911", + "VK_VERSION": "008", + "VK_SND_ID": "testvpos", + "VK_REC_ID": "seb", + "VK_STAMP": 1, + "VK_REF": "", + "VK_MSG": "Order nr 1", + "VK_MAC": "PElE2mYXXN50q2UBvTuYU1rN0BmOQcbafPummDnWfNdm9qbaGQkGyOn0XaaFGlrdEcldXaHBbZKUS0HegIgjdDfl2NOk+wkLNNH0Iu38KzZaxHoW9ga7vqiyKHC8dcxkHiO9HsOnz77Sy/KpWCq6cz48bi3fcMgo+MUzBMauWoQ=", + "VK_ENCODING": "UTF-8", + "VK_LANG": "ENG" + }.with_indifferent_access + + @cancelled_bank_link = Payments::BankLink.new( + 'seb', @invoice, { response: params } + ) + end + + def create_new_bank_link + params = { return_url: 'return.url', response_url: 'response.url' } + @new_bank_link = Payments::BankLink.new('seb', @invoice, params) + end + + def test_response_is_not_valid_when_it_is_missing + refute(false, @new_bank_link.valid_response_from_intermediary?) + end + + def test_form_fields + expected_response = { + "VK_SERVICE": "1012", + "VK_VERSION": "008", + "VK_SND_ID": "testvpos", + "VK_STAMP": 1, + "VK_AMOUNT": "12.00", + "VK_CURR": "EUR", + "VK_REF": "", + "VK_MSG": "Order nr. 1", + "VK_RETURN": "return.url", + "VK_CANCEL": "return.url", + "VK_DATETIME": "2018-04-01T00:30:00+0300", + "VK_MAC": "q70UNFV4ih1qYij2+CyrHaApc3OE66igy3ijuR1m9dl0Cg+lIrAUsP47JChAF7PRErwZ78vSuZwrg0Vabhlp3WoC934ik2FiE04BBxUUTndONvguaNR1wvl0FiwfXFljLncX7TOmRraywJljKC5vTnIRNT2+1HXvmv0v576PGao=", + "VK_ENCODING": "UTF-8", + "VK_LANG": "ENG" + }.with_indifferent_access + + assert_equal(expected_response, @new_bank_link.form_fields) + end + + def test_valid_success_response_from_intermediary? + assert(@completed_bank_link.valid_response_from_intermediary?) + end + + def test_valid_cancellation_response_from_intermediary? + assert(@cancelled_bank_link.valid_response_from_intermediary?) + end + + def test_settled_payment? + assert(@completed_bank_link.settled_payment?) + refute(@cancelled_bank_link.settled_payment?) + end + + def test_complete_transaction_returns_account_activity_or_nil + assert_instance_of(AccountActivity, @completed_bank_link.complete_transaction) + assert_nil(@cancelled_bank_link.complete_transaction) end end diff --git a/test/models/payments/every_pay_test.rb b/test/models/payments/every_pay_test.rb index 6ed68fd9f..ad894b9fb 100644 --- a/test/models/payments/every_pay_test.rb +++ b/test/models/payments/every_pay_test.rb @@ -59,9 +59,9 @@ class EveryPayTest < ActiveSupport::TestCase end end - def test_valid_response? - assert(@every_pay.valid_response?) - refute(@other_pay.valid_response?) + def test_valid_response_from_intermediary? + assert(@every_pay.valid_response_from_intermediary?) + refute(@other_pay.valid_response_from_intermediary?) end def test_settled_payment? @@ -72,12 +72,8 @@ class EveryPayTest < ActiveSupport::TestCase refute(other_pay.settled_payment?) end - def test_valid_response? - assert(@every_pay.valid_response?) - refute(@other_pay.valid_response?) - end - def test_complete_transaction_returns_account_activity_or_nil + # skip('Figure out what fails in Travis') assert_instance_of(AccountActivity, @every_pay.complete_transaction) refute(@other_pay.complete_transaction) end From d7eca597d1fec8af76db2c1841b801f538c40c56 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Sun, 22 Apr 2018 19:49:39 +0300 Subject: [PATCH 08/16] Add explicit return to fix failing test --- app/controllers/registrar/payments_controller.rb | 6 ++---- app/models/payments/bank_link.rb | 3 ++- app/models/payments/every_pay.rb | 5 +++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 793f0226b..1c546014c 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -45,11 +45,9 @@ class Registrar if @payment.valid_response_from_intermediary? && @payment.settled_payment? @payment.complete_transaction - - if invoice.binded? - render status: 200, json: { ok: :ok } - end end + + render status: 200, json: { status: 'ok' } end private diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 35004e487..8932ae019 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -65,7 +65,8 @@ module Payments transaction.paid_at = Time.parse(response["VK_T_DATETIME"]) transaction.save! - transaction.autobind_invoice + account_activity = transaction.autobind_invoice + account_activity end def settled_payment? diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index 0556f3c5a..1365cd30d 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -40,9 +40,10 @@ module Payments transaction.sum = response[:amount] transaction.paid_at = DateTime.strptime(response[:timestamp], '%s') transaction.buyer_name = response[:cc_holder_name] - transaction.save! - transaction.autobind_invoice + transaction.save! + account_activity = transaction.autobind_invoice + account_activity end private From 841a069ca42c15b260837660daf1182146e1d6f0 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 23 Apr 2018 09:19:25 +0300 Subject: [PATCH 09/16] Rework test to operate on mocks, since it does not need real objects --- app/models/payments/bank_link.rb | 3 +- app/models/payments/every_pay.rb | 3 +- .../registrar/invoices/payment_return_test.rb | 2 - test/models/payments/bank_link_test.rb | 103 ++++++++++-------- test/models/payments/every_pay_test.rb | 71 ++++++------ 5 files changed, 100 insertions(+), 82 deletions(-) diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 8932ae019..35004e487 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -65,8 +65,7 @@ module Payments transaction.paid_at = Time.parse(response["VK_T_DATETIME"]) transaction.save! - account_activity = transaction.autobind_invoice - account_activity + transaction.autobind_invoice end def settled_payment? diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index 1365cd30d..13150e43f 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -42,8 +42,7 @@ module Payments transaction.buyer_name = response[:cc_holder_name] transaction.save! - account_activity = transaction.autobind_invoice - account_activity + transaction.autobind_invoice end private diff --git a/test/integration/registrar/invoices/payment_return_test.rb b/test/integration/registrar/invoices/payment_return_test.rb index 9d24fa987..9bb6e9b63 100644 --- a/test/integration/registrar/invoices/payment_return_test.rb +++ b/test/integration/registrar/invoices/payment_return_test.rb @@ -82,12 +82,10 @@ class PaymentReturnTest < ActionDispatch::IntegrationTest def test_bank_link_return_redirects_to_invoice_paths create_invoice_with_items request_params = bank_link_request_params.merge(invoice_id: @invoice.id) - account_activity_count = AccountActivity.count post "/registrar/pay/return/seb", request_params assert_equal(302, response.status) assert_redirected_to(registrar_invoice_path(@invoice)) - assert_equal(account_activity_count + 1, AccountActivity.count) end def test_bank_link_return diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb index a4655a30d..e03b540df 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payments/bank_link_test.rb @@ -26,24 +26,24 @@ class BankLinkTest < ActiveSupport::TestCase def create_completed_bank_link params = { - "VK_SERVICE": "1111", - "VK_VERSION": "008", - "VK_SND_ID": "testvpos", - "VK_REC_ID": "seb", - "VK_STAMP": 1, - "VK_T_NO": "1", - "VK_AMOUNT": "12.00", - "VK_CURR": "EUR", - "VK_REC_ACC": "1234", - "VK_REC_NAME": "Eesti Internet", - "VK_SND_ACC": "1234", - "VK_SND_NAME": "John Doe", - "VK_REF": "", - "VK_MSG": "Order nr 1", - "VK_T_DATETIME": "2018-04-01T00:30:00+0300", - "VK_MAC": "CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=", - "VK_ENCODING": "UTF-8", - "VK_LANG": "ENG" + 'VK_SERVICE': '1111', + 'VK_VERSION': '008', + 'VK_SND_ID': 'testvpos', + 'VK_REC_ID': 'seb', + 'VK_STAMP': 1, + 'VK_T_NO': '1', + 'VK_AMOUNT': '12.00', + 'VK_CURR': 'EUR', + 'VK_REC_ACC': '1234', + 'VK_REC_NAME': 'Eesti Internet', + 'VK_SND_ACC': '1234', + 'VK_SND_NAME': 'John Doe', + 'VK_REF': '', + 'VK_MSG': 'Order nr 1', + 'VK_T_DATETIME': '2018-04-01T00:30:00+0300', + 'VK_MAC': 'CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=', + 'VK_ENCODING': 'UTF-8', + 'VK_LANG': 'ENG' }.with_indifferent_access @completed_bank_link = Payments::BankLink.new( @@ -53,16 +53,16 @@ class BankLinkTest < ActiveSupport::TestCase def create_cancelled_bank_link params = { - "VK_SERVICE": "1911", - "VK_VERSION": "008", - "VK_SND_ID": "testvpos", - "VK_REC_ID": "seb", - "VK_STAMP": 1, - "VK_REF": "", - "VK_MSG": "Order nr 1", - "VK_MAC": "PElE2mYXXN50q2UBvTuYU1rN0BmOQcbafPummDnWfNdm9qbaGQkGyOn0XaaFGlrdEcldXaHBbZKUS0HegIgjdDfl2NOk+wkLNNH0Iu38KzZaxHoW9ga7vqiyKHC8dcxkHiO9HsOnz77Sy/KpWCq6cz48bi3fcMgo+MUzBMauWoQ=", - "VK_ENCODING": "UTF-8", - "VK_LANG": "ENG" + 'VK_SERVICE': '1911', + 'VK_VERSION': '008', + 'VK_SND_ID': 'testvpos', + 'VK_REC_ID': 'seb', + 'VK_STAMP': 1, + 'VK_REF': '', + 'VK_MSG': 'Order nr 1', + 'VK_MAC': 'PElE2mYXXN50q2UBvTuYU1rN0BmOQcbafPummDnWfNdm9qbaGQkGyOn0XaaFGlrdEcldXaHBbZKUS0HegIgjdDfl2NOk+wkLNNH0Iu38KzZaxHoW9ga7vqiyKHC8dcxkHiO9HsOnz77Sy/KpWCq6cz48bi3fcMgo+MUzBMauWoQ=', + 'VK_ENCODING': 'UTF-8', + 'VK_LANG': 'ENG' }.with_indifferent_access @cancelled_bank_link = Payments::BankLink.new( @@ -81,20 +81,20 @@ class BankLinkTest < ActiveSupport::TestCase def test_form_fields expected_response = { - "VK_SERVICE": "1012", - "VK_VERSION": "008", - "VK_SND_ID": "testvpos", - "VK_STAMP": 1, - "VK_AMOUNT": "12.00", - "VK_CURR": "EUR", - "VK_REF": "", - "VK_MSG": "Order nr. 1", - "VK_RETURN": "return.url", - "VK_CANCEL": "return.url", - "VK_DATETIME": "2018-04-01T00:30:00+0300", - "VK_MAC": "q70UNFV4ih1qYij2+CyrHaApc3OE66igy3ijuR1m9dl0Cg+lIrAUsP47JChAF7PRErwZ78vSuZwrg0Vabhlp3WoC934ik2FiE04BBxUUTndONvguaNR1wvl0FiwfXFljLncX7TOmRraywJljKC5vTnIRNT2+1HXvmv0v576PGao=", - "VK_ENCODING": "UTF-8", - "VK_LANG": "ENG" + 'VK_SERVICE': '1012', + 'VK_VERSION': '008', + 'VK_SND_ID': 'testvpos', + 'VK_STAMP': 1, + 'VK_AMOUNT': '12.00', + 'VK_CURR': 'EUR', + 'VK_REF': '', + 'VK_MSG': 'Order nr. 1', + 'VK_RETURN': 'return.url', + 'VK_CANCEL': 'return.url', + 'VK_DATETIME': '2018-04-01T00:30:00+0300', + 'VK_MAC': 'q70UNFV4ih1qYij2+CyrHaApc3OE66igy3ijuR1m9dl0Cg+lIrAUsP47JChAF7PRErwZ78vSuZwrg0Vabhlp3WoC934ik2FiE04BBxUUTndONvguaNR1wvl0FiwfXFljLncX7TOmRraywJljKC5vTnIRNT2+1HXvmv0v576PGao=', + 'VK_ENCODING': 'UTF-8', + 'VK_LANG': 'ENG' }.with_indifferent_access assert_equal(expected_response, @new_bank_link.form_fields) @@ -113,8 +113,21 @@ class BankLinkTest < ActiveSupport::TestCase refute(@cancelled_bank_link.settled_payment?) end - def test_complete_transaction_returns_account_activity_or_nil - assert_instance_of(AccountActivity, @completed_bank_link.complete_transaction) - assert_nil(@cancelled_bank_link.complete_transaction) + def test_complete_transaction_calls_methods_on_transaction + mock_transaction = MiniTest::Mock.new + mock_transaction.expect(:sum= , '12.00', ['12.00']) + mock_transaction.expect(:bank_reference= , '1', ['1']) + mock_transaction.expect(:buyer_bank_code= , 'testvpos', ['testvpos']) + mock_transaction.expect(:buyer_iban= , '1234', ['1234']) + mock_transaction.expect(:paid_at= , Date.parse('2018-04-01 00:30:00 +0300'), [Time.parse('2018-04-01T00:30:00+0300')]) + mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe']) + mock_transaction.expect(:save!, true) + mock_transaction.expect(:autobind_invoice, AccountActivity.new) + + BankTransaction.stub(:find_by, mock_transaction) do + @completed_bank_link.complete_transaction + end + + mock_transaction.verify end end diff --git a/test/models/payments/every_pay_test.rb b/test/models/payments/every_pay_test.rb index ad894b9fb..74e8f5346 100644 --- a/test/models/payments/every_pay_test.rb +++ b/test/models/payments/every_pay_test.rb @@ -11,26 +11,26 @@ class EveryPayTest < ActiveSupport::TestCase params = { response: { - utf8: "✓", - _method: "put", - authenticity_token: "OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==", - nonce: "392f2d7748bc8cb0d14f263ebb7b8932", - timestamp: "1524136727", - api_username: "ca8d6336dd750ddb", - transaction_result: "completed", - payment_reference: "fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56", - payment_state: "settled", - amount: "12.00", - order_reference: "e468a2d59a731ccc546f2165c3b1a6", - account_id: "EUR3D1", - cc_type: "master_card", - cc_last_four_digits: "0487", - cc_month: "10", - cc_year: "2018", - cc_holder_name: "John Doe", - hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", - hmac: "efac1c732835668cd86023a7abc140506c692f0d", - invoice_id: "1", + utf8: '✓', + _method: 'put', + authenticity_token: 'OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==', + nonce: '392f2d7748bc8cb0d14f263ebb7b8932', + timestamp: '1524136727', + api_username: 'ca8d6336dd750ddb', + transaction_result: 'completed', + payment_reference: 'fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56', + payment_state: 'settled', + amount: '12.00', + order_reference: 'e468a2d59a731ccc546f2165c3b1a6', + account_id: 'EUR3D1', + cc_type: 'master_card', + cc_last_four_digits: '0487', + cc_month: '10', + cc_year: '2018', + cc_holder_name: 'John Doe', + hmac_fields: 'account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result', + hmac: 'efac1c732835668cd86023a7abc140506c692f0d', + invoice_id: '1', }, } @every_pay = Payments::EveryPay.new('every_pay', @invoice, params) @@ -46,12 +46,12 @@ class EveryPayTest < ActiveSupport::TestCase def test_form_fields expected_fields = { - api_username: "api_user", - account_id: "EUR3D1", - timestamp: "1522542600", - amount: "12.00", - transaction_type: "charge", - hmac_fields: "account_id,amount,api_username,callback_url,customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type" + api_username: 'api_user', + account_id: 'EUR3D1', + timestamp: '1522542600', + amount: '12.00', + transaction_type: 'charge', + hmac_fields: 'account_id,amount,api_username,callback_url,customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' } form_fields = @every_pay.form_fields expected_fields.each do |k, v| @@ -67,14 +67,23 @@ class EveryPayTest < ActiveSupport::TestCase def test_settled_payment? assert(@every_pay.settled_payment?) other_pay = Payments::EveryPay.new( - 'every_pay', @invoice, {response: {payment_state: "CANCELLED"}} + 'every_pay', @invoice, {response: {payment_state: 'CANCELLED'}} ) refute(other_pay.settled_payment?) end - def test_complete_transaction_returns_account_activity_or_nil - # skip('Figure out what fails in Travis') - assert_instance_of(AccountActivity, @every_pay.complete_transaction) - refute(@other_pay.complete_transaction) + def test_complete_transaction_calls_methods_on_transaction + mock_transaction = MiniTest::Mock.new + mock_transaction.expect(:sum= , '12.00', ['12.00']) + mock_transaction.expect(:paid_at= , Date.strptime('1524136727', '%s'), [Date.strptime('1524136727', '%s')]) + mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe']) + mock_transaction.expect(:save!, true) + mock_transaction.expect(:autobind_invoice, AccountActivity.new) + + BankTransaction.stub(:find_by, mock_transaction) do + @every_pay.complete_transaction + end + + mock_transaction.verify end end From b578cdcfa8ddc8be80b30c4ac218be639d9d430e Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 23 Apr 2018 10:27:44 +0300 Subject: [PATCH 10/16] Cleanup setup/teardown methods --- test/integration/registrar/invoices/list_test.rb | 4 +++- .../registrar/invoices/new_invoice_payment_test.rb | 4 +++- test/integration/registrar/invoices/new_test.rb | 4 +++- .../registrar/invoices/payment_callback_test.rb | 4 +++- .../integration/registrar/invoices/payment_return_test.rb | 4 +++- test/models/payments/bank_link_test.rb | 1 + test/models/payments/every_pay_test.rb | 8 ++++++-- 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/test/integration/registrar/invoices/list_test.rb b/test/integration/registrar/invoices/list_test.rb index b5a61af5b..45e7d5f8b 100644 --- a/test/integration/registrar/invoices/list_test.rb +++ b/test/integration/registrar/invoices/list_test.rb @@ -1,7 +1,9 @@ require 'test_helper' class ListInvoicesTest < ActionDispatch::IntegrationTest - setup do + def setup + super + @user = users(:api_bestnames) @registrar_invoices = @user.registrar.invoices login_as @user diff --git a/test/integration/registrar/invoices/new_invoice_payment_test.rb b/test/integration/registrar/invoices/new_invoice_payment_test.rb index f12445157..995379edc 100644 --- a/test/integration/registrar/invoices/new_invoice_payment_test.rb +++ b/test/integration/registrar/invoices/new_invoice_payment_test.rb @@ -1,7 +1,9 @@ require 'test_helper' class NewInvoicePaymentTest < ActionDispatch::IntegrationTest - setup do + def setup + super + @user = users(:api_bestnames) login_as @user end diff --git a/test/integration/registrar/invoices/new_test.rb b/test/integration/registrar/invoices/new_test.rb index 35957dddc..738e06d3c 100644 --- a/test/integration/registrar/invoices/new_test.rb +++ b/test/integration/registrar/invoices/new_test.rb @@ -1,7 +1,9 @@ require 'test_helper' class NewInvoiceTest < ActionDispatch::IntegrationTest - setup do + def setup + super + @user = users(:api_bestnames) login_as @user end diff --git a/test/integration/registrar/invoices/payment_callback_test.rb b/test/integration/registrar/invoices/payment_callback_test.rb index b341168d8..9e8996214 100644 --- a/test/integration/registrar/invoices/payment_callback_test.rb +++ b/test/integration/registrar/invoices/payment_callback_test.rb @@ -1,7 +1,9 @@ require 'test_helper' class PaymentCallbackTest < ActionDispatch::IntegrationTest - setup do + def setup + super + @user = users(:api_bestnames) login_as @user end diff --git a/test/integration/registrar/invoices/payment_return_test.rb b/test/integration/registrar/invoices/payment_return_test.rb index 9bb6e9b63..4524dc1ef 100644 --- a/test/integration/registrar/invoices/payment_return_test.rb +++ b/test/integration/registrar/invoices/payment_return_test.rb @@ -1,7 +1,9 @@ require 'test_helper' class PaymentReturnTest < ActionDispatch::IntegrationTest - setup do + def setup + super + @user = users(:api_bestnames) login_as @user end diff --git a/test/models/payments/bank_link_test.rb b/test/models/payments/bank_link_test.rb index e03b540df..6c2a86b80 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payments/bank_link_test.rb @@ -21,6 +21,7 @@ class BankLinkTest < ActiveSupport::TestCase def teardown super + travel_back end diff --git a/test/models/payments/every_pay_test.rb b/test/models/payments/every_pay_test.rb index 74e8f5346..a49a5a639 100644 --- a/test/models/payments/every_pay_test.rb +++ b/test/models/payments/every_pay_test.rb @@ -1,7 +1,9 @@ require 'test_helper' class EveryPayTest < ActiveSupport::TestCase - setup do + def setup + super + @invoice = invoices(:for_payments_test) invoice_item = invoice_items(:one) @@ -40,7 +42,9 @@ class EveryPayTest < ActiveSupport::TestCase travel_to Time.at(1522542600) end - teardown do + def teardown + super + travel_back end From 33a6971c37f57d5730e2d5ddad0abfd4559a27aa Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 23 Apr 2018 11:13:42 +0300 Subject: [PATCH 11/16] Fix some codeclimate issues --- app/controllers/registrar/payments_controller.rb | 16 ++++++++-------- app/models/payments.rb | 2 +- app/models/payments/bank_link.rb | 9 +++------ app/models/payments/every_pay.rb | 9 +++++---- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 1c546014c..fbefaf50d 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -8,15 +8,16 @@ class Registrar def pay invoice = Invoice.find(params[:invoice_id]) + bank = params[:bank] opts = { - return_url: self.registrar_return_payment_with_url( - params[:bank], invoice_id: invoice.id + return_url: registrar_return_payment_with_url( + bank, invoice_id: invoice ), - response_url: self.registrar_response_payment_with_url( - params[:bank], invoice_id: invoice.id + response_url: registrar_response_payment_with_url( + bank, invoice_id: invoice ) } - @payment = ::Payments.create_with_type(params[:bank], invoice, opts) + @payment = ::Payments.create_with_type(bank, invoice, opts) @payment.create_transaction end @@ -53,9 +54,8 @@ class Registrar private def check_supported_payment_method - unless supported_payment_method? - raise StandardError.new("Not supported payment method") - end + return if supported_payment_method? + raise StandardError.new("Not supported payment method") end diff --git a/app/models/payments.rb b/app/models/payments.rb index f379bd455..23421f5ec 100644 --- a/app/models/payments.rb +++ b/app/models/payments.rb @@ -4,7 +4,7 @@ module Payments PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze def self.create_with_type(type, invoice, opts = {}) - fail ArgumentError unless PAYMENT_METHODS.include?(type) + raise ArgumentError unless PAYMENT_METHODS.include?(type) if PAYMENT_BANKLINK_BANKS.include?(type) BankLink.new(type, invoice, opts) diff --git a/app/models/payments/bank_link.rb b/app/models/payments/bank_link.rb index 35004e487..59a97e454 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payments/bank_link.rb @@ -75,10 +75,7 @@ module Payments private def valid_successful_transaction? - return false unless valid_success_notice? - return false unless valid_amount? - return false unless valid_currency? - true + valid_success_notice? && valid_amount? && valid_currency? end def valid_cancel_notice? @@ -113,12 +110,12 @@ module Payments def calc_mac(fields) pars = NEW_MESSAGE_KEYS - data = pars.map { |e| prepend_size(fields[e]) }.join + data = pars.map { |element| prepend_size(fields[element]) }.join sign(data) end def valid_mac?(hash, keys) - data = keys.map { |e| prepend_size(hash[e]) }.join + data = keys.map { |element| prepend_size(hash[element]) }.join verify_mac(data, hash["VK_MAC"]) end diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index 13150e43f..aed0bcc1a 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -12,7 +12,7 @@ module Payments # Not all requests require use of hmac_fields, add only when needed base_json[:hmac_fields] = hmac_fields.join(',') - hmac_string = hmac_fields.map { |k, _v| "#{k}=#{base_json[k]}" }.join('&') + hmac_string = hmac_fields.map { |key, _v| "#{key}=#{base_json[key]}" }.join('&') hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) base_json[:hmac] = hmac @@ -38,7 +38,7 @@ module Payments ) transaction.sum = response[:amount] - transaction.paid_at = DateTime.strptime(response[:timestamp], '%s') + transaction.paid_at = Date.strptime(response[:timestamp], '%s') transaction.buyer_name = response[:cc_holder_name] transaction.save! @@ -65,10 +65,11 @@ module Payments hmac_fields = response[:hmac_fields].split(',') hmac_hash = {} hmac_fields.map do |field| - hmac_hash[field.to_sym] = response[field.to_sym] + symbol = field.to_sym + hmac_hash[symbol] = response[symbol] end - hmac_string = hmac_hash.map { |k, _v| "#{k}=#{hmac_hash[k]}" }.join('&') + hmac_string = hmac_hash.map { |key, _v| "#{key}=#{hmac_hash[key]}" }.join('&') expected_hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) expected_hmac == response[:hmac] end From b56fd73c925310ab5371d61787542804f040908c Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 23 Apr 2018 14:23:42 +0300 Subject: [PATCH 12/16] Remove unnecessary comments --- app/models/payments/every_pay.rb | 1 - .../registrar/card_payment/complete.haml | 19 ------------------- app/views/registrar/card_payment/new.haml | 4 ---- .../invoices/partials/_credit_card.haml | 7 ------- config/routes.rb | 2 -- 5 files changed, 33 deletions(-) delete mode 100644 app/views/registrar/card_payment/complete.haml delete mode 100644 app/views/registrar/card_payment/new.haml delete mode 100644 app/views/registrar/invoices/partials/_credit_card.haml diff --git a/app/models/payments/every_pay.rb b/app/models/payments/every_pay.rb index aed0bcc1a..054baf023 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payments/every_pay.rb @@ -10,7 +10,6 @@ module Payments base_json[:nonce] = SecureRandom.hex(15) hmac_fields = (base_json.keys + ['hmac_fields']).sort.uniq! - # Not all requests require use of hmac_fields, add only when needed base_json[:hmac_fields] = hmac_fields.join(',') hmac_string = hmac_fields.map { |key, _v| "#{key}=#{base_json[key]}" }.join('&') hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) diff --git a/app/views/registrar/card_payment/complete.haml b/app/views/registrar/card_payment/complete.haml deleted file mode 100644 index a9e392b93..000000000 --- a/app/views/registrar/card_payment/complete.haml +++ /dev/null @@ -1,19 +0,0 @@ -.row - .col-md-12 - %h4= "Credit card payment successful" - %hr - %dl.dl-horizontal - %dt= t(:invoice) - %dd= @invoice.reference_no - - %dt= "Card Type" - %dd= params['cc_type'].humanize - - %dt= "Card Holder" - %dd= params['cc_holder_name'] - - %dt= "Card Last four digits" - %dd= params['cc_last_four_digits'] - - %dt= "Valid thru" - %dd= "#{params['cc_month']}/#{params['cc_year']}" diff --git a/app/views/registrar/card_payment/new.haml b/app/views/registrar/card_payment/new.haml deleted file mode 100644 index cdafd15ea..000000000 --- a/app/views/registrar/card_payment/new.haml +++ /dev/null @@ -1,4 +0,0 @@ -= form_tag "https://igw-demo.every-pay.com/transactions/", method: :post do - - @every_pay.keys.each do |k, v| - = hidden_field_tag(k, @every_pay[k]) - = submit_tag t("registrar.invoices.to_card_payment") diff --git a/app/views/registrar/invoices/partials/_credit_card.haml b/app/views/registrar/invoices/partials/_credit_card.haml deleted file mode 100644 index 9a6682e12..000000000 --- a/app/views/registrar/invoices/partials/_credit_card.haml +++ /dev/null @@ -1,7 +0,0 @@ -%h4= t('registrar.invoices.pay_by_credit_card') -- @every_pay = EveryPayPayment.new(@invoice).json -%hr - = form_tag "https://igw-demo.every-pay.com/transactions/", method: :post do - - @every_pay.keys.each do |k, v| - = hidden_field_tag(k, @every_pay[k]) - = submit_tag t("registrar.invoices.to_card_payment") diff --git a/config/routes.rb b/config/routes.rb index ec0888217..6d0153d26 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,8 +91,6 @@ Rails.application.routes.draw do end end - - # TODO: refactor routes to be restful get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with' post 'pay/return/:bank' => 'payments#back' put 'pay/return/:bank' => 'payments#back' From e1149bf92b9e13ee1cca51038881f2a2015f12ff Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 23 Apr 2018 15:23:36 +0300 Subject: [PATCH 13/16] Implement code review changes --- app/models/payments/base.rb | 16 ---------------- test/models/payments/every_pay_test.rb | 3 +-- test/models/payments_test.rb | 10 +++++----- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/app/models/payments/base.rb b/app/models/payments/base.rb index 668c7d63d..d8b94e03d 100644 --- a/app/models/payments/base.rb +++ b/app/models/payments/base.rb @@ -26,24 +26,8 @@ module Payments transaction.save! end - def complete_transaction - raise NotImplementedError - end - - def settled_payment? - raise NotImplementedError - end - - def form_fields - raise NotImplementedError - end - def form_url ENV["payments_#{type}_url"] end - - def valid_response? - raise NotImplementedError - end end end diff --git a/test/models/payments/every_pay_test.rb b/test/models/payments/every_pay_test.rb index a49a5a639..5e09f2980 100644 --- a/test/models/payments/every_pay_test.rb +++ b/test/models/payments/every_pay_test.rb @@ -38,8 +38,7 @@ class EveryPayTest < ActiveSupport::TestCase @every_pay = Payments::EveryPay.new('every_pay', @invoice, params) @other_pay = Payments::EveryPay.new('every_pay', @invoice, {}) - # To avoid problems with time conversion. - travel_to Time.at(1522542600) + travel_to Time.zone.parse('2018-04-01 00:30:00 +0000') end def teardown diff --git a/test/models/payments_test.rb b/test/models/payments_test.rb index 2d51adcf2..2579af20b 100644 --- a/test/models/payments_test.rb +++ b/test/models/payments_test.rb @@ -27,20 +27,20 @@ class PaymentTest < ActiveSupport::TestCase assert_nil @not_implemented_payment.form_url end - def test_that_errors_are_raised_on_not_implemented_methods - assert_raise NotImplementedError do + def test_that_errors_are_raised_on_missing_methods + assert_raise NoMethodError do @not_implemented_payment.valid_response? end - assert_raise NotImplementedError do + assert_raise NoMethodError do @not_implemented_payment.settled_payment? end - assert_raise NotImplementedError do + assert_raise NoMethodError do @not_implemented_payment.form_fields end - assert_raise NotImplementedError do + assert_raise NoMethodError do @not_implemented_payment.complete_transaction end end From a1bbdc0d8e3e735dbf649dc651484d99a8d47979 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Thu, 26 Apr 2018 14:02:32 +0300 Subject: [PATCH 14/16] Handle missing values in configuration Allow for nil values in `ENV['payment_intermediaries']` and `ENV['payments_banks']` --- app/models/payments.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/payments.rb b/app/models/payments.rb index 23421f5ec..e84e44de9 100644 --- a/app/models/payments.rb +++ b/app/models/payments.rb @@ -1,6 +1,6 @@ module Payments - PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].strip.split(', ').freeze - PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].strip.split(', ').freeze + PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze + PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze def self.create_with_type(type, invoice, opts = {}) From d92004cbe009fca29363cf2709ed494f45f753d9 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 30 Apr 2018 09:30:34 +0300 Subject: [PATCH 15/16] Rename Payments to PaymentOrders --- app/controllers/registrar/payments_controller.rb | 8 ++++---- app/models/{payments.rb => payment_orders.rb} | 2 +- app/models/{payments => payment_orders}/bank_link.rb | 2 +- app/models/{payments => payment_orders}/base.rb | 2 +- app/models/{payments => payment_orders}/every_pay.rb | 2 +- app/views/registrar/invoices/show.haml | 2 +- .../{payments => payment_orders}/bank_link_test.rb | 6 +++--- .../{payments => payment_orders}/every_pay_test.rb | 6 +++--- .../{payments_test.rb => payment_orders_test.rb} | 10 +++++----- 9 files changed, 20 insertions(+), 20 deletions(-) rename app/models/{payments.rb => payment_orders.rb} (96%) rename app/models/{payments => payment_orders}/bank_link.rb (99%) rename app/models/{payments => payment_orders}/base.rb (97%) rename app/models/{payments => payment_orders}/every_pay.rb (99%) rename test/models/{payments => payment_orders}/bank_link_test.rb (95%) rename test/models/{payments => payment_orders}/every_pay_test.rb (94%) rename test/models/{payments_test.rb => payment_orders_test.rb} (80%) diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index fbefaf50d..57565b9c2 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -17,14 +17,14 @@ class Registrar bank, invoice_id: invoice ) } - @payment = ::Payments.create_with_type(bank, invoice, opts) + @payment = ::PaymentOrders.create_with_type(bank, invoice, opts) @payment.create_transaction end def back invoice = Invoice.find(params[:invoice_id]) opts = { response: params } - @payment = ::Payments.create_with_type(params[:bank], invoice, opts) + @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts) if @payment.valid_response_from_intermediary? && @payment.settled_payment? @payment.complete_transaction @@ -42,7 +42,7 @@ class Registrar def callback invoice = Invoice.find(params[:invoice_id]) opts = { response: params } - @payment = ::Payments.create_with_type(params[:bank], invoice, opts) + @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts) if @payment.valid_response_from_intermediary? && @payment.settled_payment? @payment.complete_transaction @@ -60,7 +60,7 @@ class Registrar def supported_payment_method? - Payments::PAYMENT_METHODS.include?(params[:bank]) + PaymentOrders::PAYMENT_METHODS.include?(params[:bank]) end end end diff --git a/app/models/payments.rb b/app/models/payment_orders.rb similarity index 96% rename from app/models/payments.rb rename to app/models/payment_orders.rb index e84e44de9..921af0cd4 100644 --- a/app/models/payments.rb +++ b/app/models/payment_orders.rb @@ -1,4 +1,4 @@ -module Payments +module PaymentOrders PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze diff --git a/app/models/payments/bank_link.rb b/app/models/payment_orders/bank_link.rb similarity index 99% rename from app/models/payments/bank_link.rb rename to app/models/payment_orders/bank_link.rb index 59a97e454..e568da0df 100644 --- a/app/models/payments/bank_link.rb +++ b/app/models/payment_orders/bank_link.rb @@ -1,4 +1,4 @@ -module Payments +module PaymentOrders class BankLink < Base BANK_LINK_VERSION = '008' diff --git a/app/models/payments/base.rb b/app/models/payment_orders/base.rb similarity index 97% rename from app/models/payments/base.rb rename to app/models/payment_orders/base.rb index d8b94e03d..cf0293025 100644 --- a/app/models/payments/base.rb +++ b/app/models/payment_orders/base.rb @@ -1,4 +1,4 @@ -module Payments +module PaymentOrders class Base include ActionView::Helpers::NumberHelper diff --git a/app/models/payments/every_pay.rb b/app/models/payment_orders/every_pay.rb similarity index 99% rename from app/models/payments/every_pay.rb rename to app/models/payment_orders/every_pay.rb index 054baf023..b4ddcdf29 100644 --- a/app/models/payments/every_pay.rb +++ b/app/models/payment_orders/every_pay.rb @@ -1,4 +1,4 @@ -module Payments +module PaymentOrders class EveryPay < Base USER = ENV['payments_every_pay_api_user'].freeze KEY = ENV['payments_every_pay_api_key'].freeze diff --git a/app/views/registrar/invoices/show.haml b/app/views/registrar/invoices/show.haml index c52d76289..c2c5331c2 100644 --- a/app/views/registrar/invoices/show.haml +++ b/app/views/registrar/invoices/show.haml @@ -17,4 +17,4 @@ - if !@invoice.cancelled? && !@invoice.binded? .row.semifooter - .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: Payments::PAYMENT_METHODS } + .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrders::PAYMENT_METHODS } diff --git a/test/models/payments/bank_link_test.rb b/test/models/payment_orders/bank_link_test.rb similarity index 95% rename from test/models/payments/bank_link_test.rb rename to test/models/payment_orders/bank_link_test.rb index 6c2a86b80..16f790d13 100644 --- a/test/models/payments/bank_link_test.rb +++ b/test/models/payment_orders/bank_link_test.rb @@ -47,7 +47,7 @@ class BankLinkTest < ActiveSupport::TestCase 'VK_LANG': 'ENG' }.with_indifferent_access - @completed_bank_link = Payments::BankLink.new( + @completed_bank_link = PaymentOrders::BankLink.new( 'seb', @invoice, { response: params } ) end @@ -66,14 +66,14 @@ class BankLinkTest < ActiveSupport::TestCase 'VK_LANG': 'ENG' }.with_indifferent_access - @cancelled_bank_link = Payments::BankLink.new( + @cancelled_bank_link = PaymentOrders::BankLink.new( 'seb', @invoice, { response: params } ) end def create_new_bank_link params = { return_url: 'return.url', response_url: 'response.url' } - @new_bank_link = Payments::BankLink.new('seb', @invoice, params) + @new_bank_link = PaymentOrders::BankLink.new('seb', @invoice, params) end def test_response_is_not_valid_when_it_is_missing diff --git a/test/models/payments/every_pay_test.rb b/test/models/payment_orders/every_pay_test.rb similarity index 94% rename from test/models/payments/every_pay_test.rb rename to test/models/payment_orders/every_pay_test.rb index 5e09f2980..2be3401dc 100644 --- a/test/models/payments/every_pay_test.rb +++ b/test/models/payment_orders/every_pay_test.rb @@ -35,8 +35,8 @@ class EveryPayTest < ActiveSupport::TestCase invoice_id: '1', }, } - @every_pay = Payments::EveryPay.new('every_pay', @invoice, params) - @other_pay = Payments::EveryPay.new('every_pay', @invoice, {}) + @every_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, params) + @other_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, {}) travel_to Time.zone.parse('2018-04-01 00:30:00 +0000') end @@ -69,7 +69,7 @@ class EveryPayTest < ActiveSupport::TestCase def test_settled_payment? assert(@every_pay.settled_payment?) - other_pay = Payments::EveryPay.new( + other_pay = PaymentOrders::EveryPay.new( 'every_pay', @invoice, {response: {payment_state: 'CANCELLED'}} ) refute(other_pay.settled_payment?) diff --git a/test/models/payments_test.rb b/test/models/payment_orders_test.rb similarity index 80% rename from test/models/payments_test.rb rename to test/models/payment_orders_test.rb index 2579af20b..252ba0582 100644 --- a/test/models/payments_test.rb +++ b/test/models/payment_orders_test.rb @@ -1,6 +1,6 @@ require 'test_helper' -class PaymentTest < ActiveSupport::TestCase +class PaymentOrdersTest < ActiveSupport::TestCase def setup super @@ -8,7 +8,7 @@ class PaymentTest < ActiveSupport::TestCase @original_seb_URL = ENV['seb_payment_url'] ENV['payment_methods'] = 'seb, swed, credit_card' ENV['seb_payment_url'] = nil - @not_implemented_payment = Payments::Base.new( + @not_implemented_payment = PaymentOrders::Base.new( 'not_implemented', Invoice.new ) end @@ -47,12 +47,12 @@ class PaymentTest < ActiveSupport::TestCase def test_that_create_with_type_raises_argument_error assert_raise ArgumentError do - Payments.create_with_type("not_implemented", Invoice.new) + PaymentOrders.create_with_type("not_implemented", Invoice.new) end end def test_create_with_correct_subclass - payment = Payments.create_with_type('seb', Invoice.new) - assert_equal Payments::BankLink, payment.class + payment = PaymentOrders.create_with_type('seb', Invoice.new) + assert_equal PaymentOrders::BankLink, payment.class end end From 820c49a492fa62790f6f702c7795809dee44f838 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 30 Apr 2018 11:34:17 +0300 Subject: [PATCH 16/16] Remove target _blank from the payment form Also, make it open new page automatically --- app/views/registrar/payments/pay.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/registrar/payments/pay.html.haml b/app/views/registrar/payments/pay.html.haml index f40dbe2a8..8e759f9ea 100644 --- a/app/views/registrar/payments/pay.html.haml +++ b/app/views/registrar/payments/pay.html.haml @@ -2,7 +2,7 @@ = t('registrar.invoices.redirected_to_intermediary') .payment-form - = form_tag @payment.form_url, method: :post, target: '_blank' do + = form_tag @payment.form_url, method: :post do - @payment.form_fields.each do |k, v| = hidden_field_tag k, v = submit_tag t('registrar.invoices.go_to_intermediary')