spree_conekta 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +59 -0
  4. data/Rakefile +24 -0
  5. data/app/assets/javascripts/admin/spree_conekta.js +0 -0
  6. data/app/assets/javascripts/spree_conekta.js +0 -0
  7. data/app/assets/javascripts/store/easyXDM.min.js +25 -0
  8. data/app/assets/javascripts/store/printThis.js +146 -0
  9. data/app/assets/javascripts/store/spree_conekta.js +2 -0
  10. data/app/assets/javascripts/store/utils.js.erb +35 -0
  11. data/app/assets/stylesheets/admin/print.css.sass +12 -0
  12. data/app/assets/stylesheets/admin/spree_conekta.css +3 -0
  13. data/app/assets/stylesheets/spree_conekta.css +3 -0
  14. data/app/assets/stylesheets/store/conekta.css.sass +40 -0
  15. data/app/assets/stylesheets/store/spree_conekta.css +3 -0
  16. data/app/controllers/spree/checkout_controller_decorator.rb +14 -0
  17. data/app/controllers/spree/conekta/payments_controller.rb +20 -0
  18. data/app/models/spree.rb +5 -0
  19. data/app/models/spree/billing_integration/conekta.rb +23 -0
  20. data/app/models/spree/conekta_payment.rb +11 -0
  21. data/app/models/spree/order_decorator.rb +19 -0
  22. data/app/models/spree/payment_decorator.rb +18 -0
  23. data/app/views/spree/admin/payments/_bank.html.erb +32 -0
  24. data/app/views/spree/admin/payments/_cash.html.erb +29 -0
  25. data/app/views/spree/admin/payments/source_forms/_conekta.html.erb +3 -0
  26. data/app/views/spree/admin/payments/source_views/_conekta.html.erb +1 -0
  27. data/app/views/spree/checkout/payment/_conekta.html.erb +3 -0
  28. data/app/views/spree/conekta/payments/_bank.html.erb +30 -0
  29. data/app/views/spree/conekta/payments/_card.html.erb +0 -0
  30. data/app/views/spree/conekta/payments/_cash.html.erb +32 -0
  31. data/app/views/spree/conekta/payments/show.html.erb +14 -0
  32. data/config/locales/en.yml +20 -0
  33. data/config/locales/es-MX.yml +20 -0
  34. data/config/routes.rb +5 -0
  35. data/db/migrate/20130904161251_create_spree_conekta_payments.rb +9 -0
  36. data/db/migrate/20130904172418_rename_type_column_to_conekta_payment.rb +7 -0
  37. data/lib/generators/spree_conekta/install/install_generator.rb +32 -0
  38. data/lib/spree/conekta/client.rb +39 -0
  39. data/lib/spree/conekta/payment_source/bank.rb +11 -0
  40. data/lib/spree/conekta/payment_source/card.rb +23 -0
  41. data/lib/spree/conekta/payment_source/cash.rb +11 -0
  42. data/lib/spree/conekta/provider.rb +40 -0
  43. data/lib/spree/conekta/response.rb +13 -0
  44. data/lib/spree_conekta.rb +8 -0
  45. data/lib/spree_conekta/engine.rb +32 -0
  46. data/lib/spree_conekta/version.rb +3 -0
  47. data/lib/tasks/spree_conekta_tasks.rake +4 -0
  48. metadata +175 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 451684edde4ec353fcda1d5a95510fa0298e17cd
4
+ data.tar.gz: e905ba096e13f41a7159def6806654b4ab414af2
5
+ SHA512:
6
+ metadata.gz: ea6531e0e33c95a4c76fbd870b7b7a28385df4e999076b246847851dfbfa6706953fa22d16e650c5e27f9283a7c34d4edda5cbe76073fe1268b77149dcee6e08
7
+ data.tar.gz: 4afc3472a6ba1ebdcbb83df952ac66caa79315df0dc68042c17de21f73157c0326ce7ba81c9c7af1f0c57db10230377b478e01b87db96d2f47592562d4b90879
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Crowd Interactive
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ # Spree Conekta
2
+ [![Code Climate](https://codeclimate.com/github/crowdint/spree_conekta.png)](https://codeclimate.com/github/crowdint/spree_conekta)
3
+ [![Build Status](https://travis-ci.org/crowdint/spree_conekta.png?branch=conekta-apiv2)](https://travis-ci.org/crowdint/spree_conekta)
4
+
5
+ Setup
6
+ -----
7
+
8
+ Add this extension to your Gemfile:
9
+
10
+ ```ruby
11
+ gem 'spree_conekta', git: 'git://github.com/crowdint/spree_conekta.git'
12
+ ```
13
+
14
+ Then run:
15
+
16
+ ```
17
+ bundle
18
+ rails g spree_conekta:install
19
+ ```
20
+
21
+ ##Setup Conekta Payments
22
+
23
+ 1. You need to go to [Conekta](https://www.conekta.io/), create an account and retrieve your public api key.
24
+
25
+ 2. On the spree application admin side go to:
26
+ ```
27
+ /admin/payment_methods/new
28
+ ```
29
+
30
+ 3. In the provider box, choose:
31
+ ```
32
+ Spree::BillingIntegration::Conekta
33
+ ```
34
+
35
+ 4. On the source method field, add the value of one of the following:
36
+ * card
37
+ * cash
38
+ * bank
39
+
40
+ ###Source Methods
41
+
42
+ Conekta currently supports three different methods:
43
+
44
+ ####Card
45
+ >Card method will let you pay using your credit or debit card. More info: [Conekta Card](https://www.conekta.io/docs/crear_cargo#tarjetas)
46
+
47
+ ####Cash
48
+ >Cash method will generate a bar code with the order information so you'll be able to take it to your nearest OXXO store to pay it. More info: [Conekta Cash](https://www.conekta.io/docs/crear_cargo#oxxo)
49
+
50
+ ####Bank
51
+ >Bank method will let you generate a deposit or transfer reference. More info: [Conekta Bank](https://www.conekta.io/docs/crear_cargo#bancos)
52
+
53
+
54
+ **Important Note:** If you want to support all source methods, you'll need to create a payment method for each one.
55
+
56
+ # About the Author
57
+
58
+ [Crowd Interactive](http://www.crowdint.com) is an American web design and development company that happens to work in Colima, Mexico.
59
+ We specialize in building and growing online retail stores. We don’t work with everyone – just companies we believe in. Call us today to see if there’s a fit.
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ require 'spree/testing_support/common_rake'
10
+
11
+ rescue LoadError
12
+ require 'rdoc/rdoc'
13
+ require 'rake/rdoctask'
14
+ RDoc::Task = Rake::RDocTask
15
+ end
16
+
17
+ Bundler::GemHelper.install_tasks
18
+
19
+ require 'rspec/core'
20
+ require 'rspec/core/rake_task'
21
+
22
+ desc "Run all specs in spec directory (excluding plugin specs)"
23
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
24
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license
3
+ * easyXDM
4
+ * http://easyxdm.net/
5
+ * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+ (function(N,d,p,K,k,H){var b=this;var n=Math.floor(Math.random()*10000);var q=Function.prototype;var Q=/^((http.?:)\/\/([^:\/\s]+)(:\d+)*)/;var R=/[\-\w]+\/\.\.\//;var F=/([^:])\/\//g;var I="";var o={};var M=N.easyXDM;var U="easyXDM_";var E;var y=false;var i;var h;function C(X,Z){var Y=typeof X[Z];return Y=="function"||(!!(Y=="object"&&X[Z]))||Y=="unknown"}function u(X,Y){return !!(typeof(X[Y])=="object"&&X[Y])}function r(X){return Object.prototype.toString.call(X)==="[object Array]"}function c(){var Z="Shockwave Flash",ad="application/x-shockwave-flash";if(!t(navigator.plugins)&&typeof navigator.plugins[Z]=="object"){var ab=navigator.plugins[Z].description;if(ab&&!t(navigator.mimeTypes)&&navigator.mimeTypes[ad]&&navigator.mimeTypes[ad].enabledPlugin){i=ab.match(/\d+/g)}}if(!i){var Y;try{Y=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");i=Array.prototype.slice.call(Y.GetVariable("$version").match(/(\d+),(\d+),(\d+),(\d+)/),1);Y=null}catch(ac){}}if(!i){return false}var X=parseInt(i[0],10),aa=parseInt(i[1],10);h=X>9&&aa>0;return true}var v,x;if(C(N,"addEventListener")){v=function(Z,X,Y){Z.addEventListener(X,Y,false)};x=function(Z,X,Y){Z.removeEventListener(X,Y,false)}}else{if(C(N,"attachEvent")){v=function(X,Z,Y){X.attachEvent("on"+Z,Y)};x=function(X,Z,Y){X.detachEvent("on"+Z,Y)}}else{throw new Error("Browser not supported")}}var W=false,J=[],L;if("readyState" in d){L=d.readyState;W=L=="complete"||(~navigator.userAgent.indexOf("AppleWebKit/")&&(L=="loaded"||L=="interactive"))}else{W=!!d.body}function s(){if(W){return}W=true;for(var X=0;X<J.length;X++){J[X]()}J.length=0}if(!W){if(C(N,"addEventListener")){v(d,"DOMContentLoaded",s)}else{v(d,"readystatechange",function(){if(d.readyState=="complete"){s()}});if(d.documentElement.doScroll&&N===top){var g=function(){if(W){return}try{d.documentElement.doScroll("left")}catch(X){K(g,1);return}s()};g()}}v(N,"load",s)}function G(Y,X){if(W){Y.call(X);return}J.push(function(){Y.call(X)})}function m(){var Z=parent;if(I!==""){for(var X=0,Y=I.split(".");X<Y.length;X++){Z=Z[Y[X]]}}return Z.easyXDM}function e(X){N.easyXDM=M;I=X;if(I){U="easyXDM_"+I.replace(".","_")+"_"}return o}function z(X){return X.match(Q)[3]}function f(X){return X.match(Q)[4]||""}function j(Z){var X=Z.toLowerCase().match(Q);var aa=X[2],ab=X[3],Y=X[4]||"";if((aa=="http:"&&Y==":80")||(aa=="https:"&&Y==":443")){Y=""}return aa+"//"+ab+Y}function B(X){X=X.replace(F,"$1/");if(!X.match(/^(http||https):\/\//)){var Y=(X.substring(0,1)==="/")?"":p.pathname;if(Y.substring(Y.length-1)!=="/"){Y=Y.substring(0,Y.lastIndexOf("/")+1)}X=p.protocol+"//"+p.host+Y+X}while(R.test(X)){X=X.replace(R,"")}return X}function P(X,aa){var ac="",Z=X.indexOf("#");if(Z!==-1){ac=X.substring(Z);X=X.substring(0,Z)}var ab=[];for(var Y in aa){if(aa.hasOwnProperty(Y)){ab.push(Y+"="+H(aa[Y]))}}return X+(y?"#":(X.indexOf("?")==-1?"?":"&"))+ab.join("&")+ac}var S=(function(X){X=X.substring(1).split("&");var Z={},aa,Y=X.length;while(Y--){aa=X[Y].split("=");Z[aa[0]]=k(aa[1])}return Z}(/xdm_e=/.test(p.search)?p.search:p.hash));function t(X){return typeof X==="undefined"}var O=function(){var Y={};var Z={a:[1,2,3]},X='{"a":[1,2,3]}';if(typeof JSON!="undefined"&&typeof JSON.stringify==="function"&&JSON.stringify(Z).replace((/\s/g),"")===X){return JSON}if(Object.toJSON){if(Object.toJSON(Z).replace((/\s/g),"")===X){Y.stringify=Object.toJSON}}if(typeof String.prototype.evalJSON==="function"){Z=X.evalJSON();if(Z.a&&Z.a.length===3&&Z.a[2]===3){Y.parse=function(aa){return aa.evalJSON()}}}if(Y.stringify&&Y.parse){O=function(){return Y};return Y}return null};function T(X,Y,Z){var ab;for(var aa in Y){if(Y.hasOwnProperty(aa)){if(aa in X){ab=Y[aa];if(typeof ab==="object"){T(X[aa],ab,Z)}else{if(!Z){X[aa]=Y[aa]}}}else{X[aa]=Y[aa]}}}return X}function a(){var Y=d.body.appendChild(d.createElement("form")),X=Y.appendChild(d.createElement("input"));X.name=U+"TEST"+n;E=X!==Y.elements[X.name];d.body.removeChild(Y)}function A(Y){if(t(E)){a()}var ac;if(E){ac=d.createElement('<iframe name="'+Y.props.name+'"/>')}else{ac=d.createElement("IFRAME");ac.name=Y.props.name}ac.id=ac.name=Y.props.name;delete Y.props.name;if(typeof Y.container=="string"){Y.container=d.getElementById(Y.container)}if(!Y.container){T(ac.style,{position:"absolute",top:"-2000px",left:"0px"});Y.container=d.body}var ab=Y.props.src;Y.props.src="javascript:false";T(ac,Y.props);ac.border=ac.frameBorder=0;ac.allowTransparency=true;Y.container.appendChild(ac);if(Y.onLoad){v(ac,"load",Y.onLoad)}if(Y.usePost){var aa=Y.container.appendChild(d.createElement("form")),X;aa.target=ac.name;aa.action=ab;aa.method="POST";if(typeof(Y.usePost)==="object"){for(var Z in Y.usePost){if(Y.usePost.hasOwnProperty(Z)){if(E){X=d.createElement('<input name="'+Z+'"/>')}else{X=d.createElement("INPUT");X.name=Z}X.value=Y.usePost[Z];aa.appendChild(X)}}}aa.submit();aa.parentNode.removeChild(aa)}else{ac.src=ab}Y.props.src=ab;return ac}function V(aa,Z){if(typeof aa=="string"){aa=[aa]}var Y,X=aa.length;while(X--){Y=aa[X];Y=new RegExp(Y.substr(0,1)=="^"?Y:("^"+Y.replace(/(\*)/g,".$1").replace(/\?/g,".")+"$"));if(Y.test(Z)){return true}}return false}function l(Z){var ae=Z.protocol,Y;Z.isHost=Z.isHost||t(S.xdm_p);y=Z.hash||false;if(!Z.props){Z.props={}}if(!Z.isHost){Z.channel=S.xdm_c.replace(/["'<>\\]/g,"");Z.secret=S.xdm_s;Z.remote=S.xdm_e.replace(/["'<>\\]/g,"");ae=S.xdm_p;if(Z.acl&&!V(Z.acl,Z.remote)){throw new Error("Access denied for "+Z.remote)}}else{Z.remote=B(Z.remote);Z.channel=Z.channel||"default"+n++;Z.secret=Math.random().toString(16).substring(2);if(t(ae)){if(j(p.href)==j(Z.remote)){ae="4"}else{if(C(N,"postMessage")||C(d,"postMessage")){ae="1"}else{if(Z.swf&&C(N,"ActiveXObject")&&c()){ae="6"}else{if(navigator.product==="Gecko"&&"frameElement" in N&&navigator.userAgent.indexOf("WebKit")==-1){ae="5"}else{if(Z.remoteHelper){ae="2"}else{ae="0"}}}}}}}Z.protocol=ae;switch(ae){case"0":T(Z,{interval:100,delay:2000,useResize:true,useParent:false,usePolling:false},true);if(Z.isHost){if(!Z.local){var ac=p.protocol+"//"+p.host,X=d.body.getElementsByTagName("img"),ad;var aa=X.length;while(aa--){ad=X[aa];if(ad.src.substring(0,ac.length)===ac){Z.local=ad.src;break}}if(!Z.local){Z.local=N}}var ab={xdm_c:Z.channel,xdm_p:0};if(Z.local===N){Z.usePolling=true;Z.useParent=true;Z.local=p.protocol+"//"+p.host+p.pathname+p.search;ab.xdm_e=Z.local;ab.xdm_pa=1}else{ab.xdm_e=B(Z.local)}if(Z.container){Z.useResize=false;ab.xdm_po=1}Z.remote=P(Z.remote,ab)}else{T(Z,{channel:S.xdm_c,remote:S.xdm_e,useParent:!t(S.xdm_pa),usePolling:!t(S.xdm_po),useResize:Z.useParent?false:Z.useResize})}Y=[new o.stack.HashTransport(Z),new o.stack.ReliableBehavior({}),new o.stack.QueueBehavior({encode:true,maxLength:4000-Z.remote.length}),new o.stack.VerifyBehavior({initiate:Z.isHost})];break;case"1":Y=[new o.stack.PostMessageTransport(Z)];break;case"2":Z.remoteHelper=B(Z.remoteHelper);Y=[new o.stack.NameTransport(Z),new o.stack.QueueBehavior(),new o.stack.VerifyBehavior({initiate:Z.isHost})];break;case"3":Y=[new o.stack.NixTransport(Z)];break;case"4":Y=[new o.stack.SameOriginTransport(Z)];break;case"5":Y=[new o.stack.FrameElementTransport(Z)];break;case"6":if(!i){c()}Y=[new o.stack.FlashTransport(Z)];break}Y.push(new o.stack.QueueBehavior({lazy:Z.lazy,remove:true}));return Y}function D(aa){var ab,Z={incoming:function(ad,ac){this.up.incoming(ad,ac)},outgoing:function(ac,ad){this.down.outgoing(ac,ad)},callback:function(ac){this.up.callback(ac)},init:function(){this.down.init()},destroy:function(){this.down.destroy()}};for(var Y=0,X=aa.length;Y<X;Y++){ab=aa[Y];T(ab,Z,true);if(Y!==0){ab.down=aa[Y-1]}if(Y!==X-1){ab.up=aa[Y+1]}}return ab}function w(X){X.up.down=X.down;X.down.up=X.up;X.up=X.down=null}T(o,{version:"2.4.17.1",query:S,stack:{},apply:T,getJSONObject:O,whenReady:G,noConflict:e});o.DomHelper={on:v,un:x,requiresJSON:function(X){if(!u(N,"JSON")){d.write('<script type="text/javascript" src="'+X+'"><\/script>')}}};(function(){var X={};o.Fn={set:function(Y,Z){X[Y]=Z},get:function(Z,Y){var aa=X[Z];if(Y){delete X[Z]}return aa}}}());o.Socket=function(Y){var X=D(l(Y).concat([{incoming:function(ab,aa){Y.onMessage(ab,aa)},callback:function(aa){if(Y.onReady){Y.onReady(aa)}}}])),Z=j(Y.remote);this.origin=j(Y.remote);this.destroy=function(){X.destroy()};this.postMessage=function(aa){X.outgoing(aa,Z)};X.init()};o.Rpc=function(Z,Y){if(Y.local){for(var ab in Y.local){if(Y.local.hasOwnProperty(ab)){var aa=Y.local[ab];if(typeof aa==="function"){Y.local[ab]={method:aa}}}}}var X=D(l(Z).concat([new o.stack.RpcBehavior(this,Y),{callback:function(ac){if(Z.onReady){Z.onReady(ac)}}}]));this.origin=j(Z.remote);this.destroy=function(){X.destroy()};X.init()};o.stack.SameOriginTransport=function(Y){var Z,ab,aa,X;return(Z={outgoing:function(ad,ae,ac){aa(ad);if(ac){ac()}},destroy:function(){if(ab){ab.parentNode.removeChild(ab);ab=null}},onDOMReady:function(){X=j(Y.remote);if(Y.isHost){T(Y.props,{src:P(Y.remote,{xdm_e:p.protocol+"//"+p.host+p.pathname,xdm_c:Y.channel,xdm_p:4}),name:U+Y.channel+"_provider"});ab=A(Y);o.Fn.set(Y.channel,function(ac){aa=ac;K(function(){Z.up.callback(true)},0);return function(ad){Z.up.incoming(ad,X)}})}else{aa=m().Fn.get(Y.channel,true)(function(ac){Z.up.incoming(ac,X)});K(function(){Z.up.callback(true)},0)}},init:function(){G(Z.onDOMReady,Z)}})};o.stack.FlashTransport=function(aa){var ac,X,ab,ad,Y,ae;function af(ah,ag){K(function(){ac.up.incoming(ah,ad)},0)}function Z(ah){var ag=aa.swf+"?host="+aa.isHost;var aj="easyXDM_swf_"+Math.floor(Math.random()*10000);o.Fn.set("flash_loaded"+ah.replace(/[\-.]/g,"_"),function(){o.stack.FlashTransport[ah].swf=Y=ae.firstChild;var ak=o.stack.FlashTransport[ah].queue;for(var al=0;al<ak.length;al++){ak[al]()}ak.length=0});if(aa.swfContainer){ae=(typeof aa.swfContainer=="string")?d.getElementById(aa.swfContainer):aa.swfContainer}else{ae=d.createElement("div");T(ae.style,h&&aa.swfNoThrottle?{height:"20px",width:"20px",position:"fixed",right:0,top:0}:{height:"1px",width:"1px",position:"absolute",overflow:"hidden",right:0,top:0});d.body.appendChild(ae)}var ai="callback=flash_loaded"+ah.replace(/[\-.]/g,"_")+"&proto="+b.location.protocol+"&domain="+z(b.location.href)+"&port="+f(b.location.href)+"&ns="+I;ae.innerHTML="<object height='20' width='20' type='application/x-shockwave-flash' id='"+aj+"' data='"+ag+"'><param name='allowScriptAccess' value='always'></param><param name='wmode' value='transparent'><param name='movie' value='"+ag+"'></param><param name='flashvars' value='"+ai+"'></param><embed type='application/x-shockwave-flash' FlashVars='"+ai+"' allowScriptAccess='always' wmode='transparent' src='"+ag+"' height='1' width='1'></embed></object>"}return(ac={outgoing:function(ah,ai,ag){Y.postMessage(aa.channel,ah.toString());if(ag){ag()}},destroy:function(){try{Y.destroyChannel(aa.channel)}catch(ag){}Y=null;if(X){X.parentNode.removeChild(X);X=null}},onDOMReady:function(){ad=aa.remote;o.Fn.set("flash_"+aa.channel+"_init",function(){K(function(){ac.up.callback(true)})});o.Fn.set("flash_"+aa.channel+"_onMessage",af);aa.swf=B(aa.swf);var ah=z(aa.swf);var ag=function(){o.stack.FlashTransport[ah].init=true;Y=o.stack.FlashTransport[ah].swf;Y.createChannel(aa.channel,aa.secret,j(aa.remote),aa.isHost);if(aa.isHost){if(h&&aa.swfNoThrottle){T(aa.props,{position:"fixed",right:0,top:0,height:"20px",width:"20px"})}T(aa.props,{src:P(aa.remote,{xdm_e:j(p.href),xdm_c:aa.channel,xdm_p:6,xdm_s:aa.secret}),name:U+aa.channel+"_provider"});X=A(aa)}};if(o.stack.FlashTransport[ah]&&o.stack.FlashTransport[ah].init){ag()}else{if(!o.stack.FlashTransport[ah]){o.stack.FlashTransport[ah]={queue:[ag]};Z(ah)}else{o.stack.FlashTransport[ah].queue.push(ag)}}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.PostMessageTransport=function(aa){var ac,ad,Y,Z;function X(ae){if(ae.origin){return j(ae.origin)}if(ae.uri){return j(ae.uri)}if(ae.domain){return p.protocol+"//"+ae.domain}throw"Unable to retrieve the origin of the event"}function ab(af){var ae=X(af);if(ae==Z&&af.data.substring(0,aa.channel.length+1)==aa.channel+" "){ac.up.incoming(af.data.substring(aa.channel.length+1),ae)}}return(ac={outgoing:function(af,ag,ae){Y.postMessage(aa.channel+" "+af,ag||Z);if(ae){ae()}},destroy:function(){x(N,"message",ab);if(ad){Y=null;ad.parentNode.removeChild(ad);ad=null}},onDOMReady:function(){Z=j(aa.remote);if(aa.isHost){var ae=function(af){if(af.data==aa.channel+"-ready"){Y=("postMessage" in ad.contentWindow)?ad.contentWindow:ad.contentWindow.document;x(N,"message",ae);v(N,"message",ab);K(function(){ac.up.callback(true)},0)}};v(N,"message",ae);T(aa.props,{src:P(aa.remote,{xdm_e:j(p.href),xdm_c:aa.channel,xdm_p:1}),name:U+aa.channel+"_provider"});ad=A(aa)}else{v(N,"message",ab);Y=("postMessage" in N.parent)?N.parent:N.parent.document;Y.postMessage(aa.channel+"-ready",Z);K(function(){ac.up.callback(true)},0)}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.FrameElementTransport=function(Y){var Z,ab,aa,X;return(Z={outgoing:function(ad,ae,ac){aa.call(this,ad);if(ac){ac()}},destroy:function(){if(ab){ab.parentNode.removeChild(ab);ab=null}},onDOMReady:function(){X=j(Y.remote);if(Y.isHost){T(Y.props,{src:P(Y.remote,{xdm_e:j(p.href),xdm_c:Y.channel,xdm_p:5}),name:U+Y.channel+"_provider"});ab=A(Y);ab.fn=function(ac){delete ab.fn;aa=ac;K(function(){Z.up.callback(true)},0);return function(ad){Z.up.incoming(ad,X)}}}else{if(d.referrer&&j(d.referrer)!=S.xdm_e){N.top.location=S.xdm_e}aa=N.frameElement.fn(function(ac){Z.up.incoming(ac,X)});Z.up.callback(true)}},init:function(){G(Z.onDOMReady,Z)}})};o.stack.NameTransport=function(ab){var ac;var ae,ai,aa,ag,ah,Y,X;function af(al){var ak=ab.remoteHelper+(ae?"#_3":"#_2")+ab.channel;ai.contentWindow.sendMessage(al,ak)}function ad(){if(ae){if(++ag===2||!ae){ac.up.callback(true)}}else{af("ready");ac.up.callback(true)}}function aj(ak){ac.up.incoming(ak,Y)}function Z(){if(ah){K(function(){ah(true)},0)}}return(ac={outgoing:function(al,am,ak){ah=ak;af(al)},destroy:function(){ai.parentNode.removeChild(ai);ai=null;if(ae){aa.parentNode.removeChild(aa);aa=null}},onDOMReady:function(){ae=ab.isHost;ag=0;Y=j(ab.remote);ab.local=B(ab.local);if(ae){o.Fn.set(ab.channel,function(al){if(ae&&al==="ready"){o.Fn.set(ab.channel,aj);ad()}});X=P(ab.remote,{xdm_e:ab.local,xdm_c:ab.channel,xdm_p:2});T(ab.props,{src:X+"#"+ab.channel,name:U+ab.channel+"_provider"});aa=A(ab)}else{ab.remoteHelper=ab.remote;o.Fn.set(ab.channel,aj)}var ak=function(){var al=ai||this;x(al,"load",ak);o.Fn.set(ab.channel+"_load",Z);(function am(){if(typeof al.contentWindow.sendMessage=="function"){ad()}else{K(am,50)}}())};ai=A({props:{src:ab.local+"#_4"+ab.channel},onLoad:ak})},init:function(){G(ac.onDOMReady,ac)}})};o.stack.HashTransport=function(Z){var ac;var ah=this,af,aa,X,ad,am,ab,al;var ag,Y;function ak(ao){if(!al){return}var an=Z.remote+"#"+(am++)+"_"+ao;((af||!ag)?al.contentWindow:al).location=an}function ae(an){ad=an;ac.up.incoming(ad.substring(ad.indexOf("_")+1),Y)}function aj(){if(!ab){return}var an=ab.location.href,ap="",ao=an.indexOf("#");if(ao!=-1){ap=an.substring(ao)}if(ap&&ap!=ad){ae(ap)}}function ai(){aa=setInterval(aj,X)}return(ac={outgoing:function(an,ao){ak(an)},destroy:function(){N.clearInterval(aa);if(af||!ag){al.parentNode.removeChild(al)}al=null},onDOMReady:function(){af=Z.isHost;X=Z.interval;ad="#"+Z.channel;am=0;ag=Z.useParent;Y=j(Z.remote);if(af){T(Z.props,{src:Z.remote,name:U+Z.channel+"_provider"});if(ag){Z.onLoad=function(){ab=N;ai();ac.up.callback(true)}}else{var ap=0,an=Z.delay/50;(function ao(){if(++ap>an){throw new Error("Unable to reference listenerwindow")}try{ab=al.contentWindow.frames[U+Z.channel+"_consumer"]}catch(aq){}if(ab){ai();ac.up.callback(true)}else{K(ao,50)}}())}al=A(Z)}else{ab=N;ai();if(ag){al=parent;ac.up.callback(true)}else{T(Z,{props:{src:Z.remote+"#"+Z.channel+new Date(),name:U+Z.channel+"_consumer"},onLoad:function(){ac.up.callback(true)}});al=A(Z)}}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.ReliableBehavior=function(Y){var aa,ac;var ab=0,X=0,Z="";return(aa={incoming:function(af,ad){var ae=af.indexOf("_"),ag=af.substring(0,ae).split(",");af=af.substring(ae+1);if(ag[0]==ab){Z="";if(ac){ac(true);ac=null}}if(af.length>0){aa.down.outgoing(ag[1]+","+ab+"_"+Z,ad);if(X!=ag[1]){X=ag[1];aa.up.incoming(af,ad)}}},outgoing:function(af,ad,ae){Z=af;ac=ae;aa.down.outgoing(X+","+(++ab)+"_"+af,ad)}})};o.stack.QueueBehavior=function(Z){var ac,ad=[],ag=true,aa="",af,X=0,Y=false,ab=false;function ae(){if(Z.remove&&ad.length===0){w(ac);return}if(ag||ad.length===0||af){return}ag=true;var ah=ad.shift();ac.down.outgoing(ah.data,ah.origin,function(ai){ag=false;if(ah.callback){K(function(){ah.callback(ai)},0)}ae()})}return(ac={init:function(){if(t(Z)){Z={}}if(Z.maxLength){X=Z.maxLength;ab=true}if(Z.lazy){Y=true}else{ac.down.init()}},callback:function(ai){ag=false;var ah=ac.up;ae();ah.callback(ai)},incoming:function(ak,ai){if(ab){var aj=ak.indexOf("_"),ah=parseInt(ak.substring(0,aj),10);aa+=ak.substring(aj+1);if(ah===0){if(Z.encode){aa=k(aa)}ac.up.incoming(aa,ai);aa=""}}else{ac.up.incoming(ak,ai)}},outgoing:function(al,ai,ak){if(Z.encode){al=H(al)}var ah=[],aj;if(ab){while(al.length!==0){aj=al.substring(0,X);al=al.substring(aj.length);ah.push(aj)}while((aj=ah.shift())){ad.push({data:ah.length+"_"+aj,origin:ai,callback:ah.length===0?ak:null})}}else{ad.push({data:al,origin:ai,callback:ak})}if(Y){ac.down.init()}else{ae()}},destroy:function(){af=true;ac.down.destroy()}})};o.stack.VerifyBehavior=function(ab){var ac,aa,Y,Z=false;function X(){aa=Math.random().toString(16).substring(2);ac.down.outgoing(aa)}return(ac={incoming:function(af,ad){var ae=af.indexOf("_");if(ae===-1){if(af===aa){ac.up.callback(true)}else{if(!Y){Y=af;if(!ab.initiate){X()}ac.down.outgoing(af)}}}else{if(af.substring(0,ae)===Y){ac.up.incoming(af.substring(ae+1),ad)}}},outgoing:function(af,ad,ae){ac.down.outgoing(aa+"_"+af,ad,ae)},callback:function(ad){if(ab.initiate){X()}}})};o.stack.RpcBehavior=function(ad,Y){var aa,af=Y.serializer||O();var ae=0,ac={};function X(ag){ag.jsonrpc="2.0";aa.down.outgoing(af.stringify(ag))}function ab(ag,ai){var ah=Array.prototype.slice;return function(){var aj=arguments.length,al,ak={method:ai};if(aj>0&&typeof arguments[aj-1]==="function"){if(aj>1&&typeof arguments[aj-2]==="function"){al={success:arguments[aj-2],error:arguments[aj-1]};ak.params=ah.call(arguments,0,aj-2)}else{al={success:arguments[aj-1]};ak.params=ah.call(arguments,0,aj-1)}ac[""+(++ae)]=al;ak.id=ae}else{ak.params=ah.call(arguments,0)}if(ag.namedParams&&ak.params.length===1){ak.params=ak.params[0]}X(ak)}}function Z(an,am,ai,al){if(!ai){if(am){X({id:am,error:{code:-32601,message:"Procedure not found."}})}return}var ak,ah;if(am){ak=function(ao){ak=q;X({id:am,result:ao})};ah=function(ao,ap){ah=q;var aq={id:am,error:{code:-32099,message:ao}};if(ap){aq.error.data=ap}X(aq)}}else{ak=ah=q}if(!r(al)){al=[al]}try{var ag=ai.method.apply(ai.scope,al.concat([ak,ah]));if(!t(ag)){ak(ag)}}catch(aj){ah(aj.message)}}return(aa={incoming:function(ah,ag){var ai=af.parse(ah);if(ai.method){if(Y.handle){Y.handle(ai,X)}else{Z(ai.method,ai.id,Y.local[ai.method],ai.params)}}else{var aj=ac[ai.id];if(ai.error){if(aj.error){aj.error(ai.error)}}else{if(aj.success){aj.success(ai.result)}}delete ac[ai.id]}},init:function(){if(Y.remote){for(var ag in Y.remote){if(Y.remote.hasOwnProperty(ag)){ad[ag]=ab(Y.remote[ag],ag)}}}aa.down.init()},destroy:function(){for(var ag in Y.remote){if(Y.remote.hasOwnProperty(ag)&&ad.hasOwnProperty(ag)){delete ad[ag]}}aa.down.destroy()}})};b.easyXDM=o})(window,document,location,window.setTimeout,decodeURIComponent,encodeURIComponent);
@@ -0,0 +1,146 @@
1
+ /*
2
+ * printThis v1.2
3
+ * @desc Printing plug-in for jQuery
4
+ * @author Jason Day
5
+ *
6
+ * Resources (based on) :
7
+ * jPrintArea: http://plugins.jquery.com/project/jPrintArea
8
+ * jqPrint: https://github.com/permanenttourist/jquery.jqprint
9
+ * Ben Nadal: http://www.bennadel.com/blog/1591-Ask-Ben-Print-Part-Of-A-Web-Page-With-jQuery.htm
10
+ *
11
+ * Dual licensed under the MIT and GPL licenses:
12
+ * http://www.opensource.org/licenses/mit-license.php
13
+ * http://www.gnu.org/licenses/gpl.html
14
+ *
15
+ * (c) Jason Day 2013
16
+ *
17
+ * Usage:
18
+ *
19
+ * $("#mySelector").printThis({
20
+ * debug: false, * show the iframe for debugging
21
+ * importCSS: true, * import page CSS
22
+ * printContainer: true, * grab outer container as well as the contents of the selector
23
+ * loadCSS: "path/to/my.css", * path to additional css file
24
+ * pageTitle: "", * add title to print page
25
+ * removeInline: false * remove all inline styles from print elements
26
+ * });
27
+ *
28
+ * Notes:
29
+ * - the loadCSS will load additional css (with or without @media print) into the iframe, adjusting layout
30
+ */
31
+ ;(function ($) {
32
+ var opt;
33
+ $.fn.printThis = function (options) {
34
+ opt = $.extend({}, $.fn.printThis.defaults, options);
35
+ var $element = this instanceof jQuery ? this : $(this);
36
+
37
+ var strFrameName = "printThis-" + (new Date()).getTime();
38
+
39
+ if(window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)){
40
+ // Ugly IE hacks due to IE not inheriting document.domain from parent
41
+ // checks if document.domain is set by comparing the host name against document.domain
42
+ var iframeSrc = "javascript:document.write(\"<head><script>document.domain=\\\"" + document.domain + "\\\";</script></head><body></body>\")";
43
+ var printI= document.createElement('iframe');
44
+ printI.name = "printIframe";
45
+ printI.id = strFrameName;
46
+ printI.className = "MSIE";
47
+ document.body.appendChild(printI);
48
+ printI.src = iframeSrc;
49
+
50
+ } else {
51
+ // other browsers inherit document.domain, and IE works if document.domain is not explicitly set
52
+ var $frame = $("<iframe id='" + strFrameName +"' name='printIframe' />");
53
+ $frame.appendTo("body");
54
+ }
55
+
56
+
57
+ var $iframe = $("#" + strFrameName);
58
+
59
+ // show frame if in debug mode
60
+ if (!opt.debug) $iframe.css({
61
+ position: "absolute",
62
+ width: "0px",
63
+ height: "0px",
64
+ left: "-600px",
65
+ top: "-600px"
66
+ });
67
+
68
+
69
+ // $iframe.ready() and $iframe.load were inconsistent between browsers
70
+ setTimeout ( function () {
71
+
72
+ var $doc = $iframe.contents();
73
+
74
+ // import page stylesheets
75
+ if (opt.importCSS) $("link[rel=stylesheet]").each(function () {
76
+ var href = $(this).attr("href");
77
+ if (href) {
78
+ var media = $(this).attr("media") || "all";
79
+ $doc.find("head").append("<link type='text/css' rel='stylesheet' href='" + href + "' media='" + media + "'>")
80
+ }
81
+ });
82
+
83
+ //add title of the page
84
+ if (opt.pageTitle) $doc.find("head").append("<title>" + opt.pageTitle + "</title>");
85
+
86
+ // import additional stylesheet
87
+ if (opt.loadCSS) $doc.find("head").append("<link type='text/css' rel='stylesheet' href='" + opt.loadCSS + "'>");
88
+
89
+ // grab $.selector as container
90
+ if (opt.printContainer) $doc.find("body").append($element.outer());
91
+
92
+ // otherwise just print interior elements of container
93
+ else $element.each(function () {
94
+ $doc.find("body").append($(this).html())
95
+ });
96
+
97
+ // remove inline styles
98
+ if (opt.removeInline) {
99
+ // $.removeAttr available jQuery 1.7+
100
+ if ($.isFunction($.removeAttr)) {
101
+ $doc.find("body *").removeAttr("style");
102
+ } else {
103
+ $doc.find("body *").attr("style", "");
104
+ }
105
+ }
106
+
107
+ setTimeout(function () {
108
+ if($iframe.hasClass("MSIE")){
109
+ // check if the iframe was created with the ugly hack
110
+ // and perform another ugly hack out of neccessity
111
+ window.frames["printIframe"].focus();
112
+ $doc.find("head").append("<script> window.print(); </script>");
113
+ } else {
114
+ // proper method
115
+ $iframe[0].contentWindow.focus();
116
+ $iframe[0].contentWindow.print();
117
+ }
118
+
119
+ //remove iframe after print
120
+ if (!opt.debug) {
121
+ setTimeout(function () {
122
+ $iframe.remove();
123
+ }, 1000);
124
+ }
125
+
126
+ }, 333);
127
+
128
+ }, 333 );
129
+
130
+ };
131
+
132
+ // defaults
133
+ $.fn.printThis.defaults = {
134
+ debug: false, // show the iframe for debugging
135
+ importCSS: true, // import parent page css
136
+ printContainer: true, // print outer container/$.selector
137
+ loadCSS: "", // load an additional css file
138
+ pageTitle: "", // add title to print page
139
+ removeInline: false // remove all inline styles
140
+ };
141
+
142
+ // $.selector container
143
+ jQuery.fn.outer = function () {
144
+ return $($("<div></div>").html(this.clone())).html()
145
+ }
146
+ })(jQuery);
@@ -0,0 +1,2 @@
1
+ //
2
+ //= require_tree .
@@ -0,0 +1,35 @@
1
+ window.spreeConekta || (window.spreeConekta = {})
2
+
3
+ spreeConekta.Utils = (function(){
4
+ function Utils(args) {
5
+ this.printable = args.printable;
6
+ this.options = args.options;
7
+ if (args.trigger) {
8
+ this.setup(args.trigger)
9
+ };
10
+ };
11
+
12
+ Utils.prototype.print = function (){
13
+ this.printable.printThis(this.options);
14
+ };
15
+
16
+ Utils.prototype.setup = function(trigger) {
17
+ _this_ = this;
18
+ trigger.on('click', function(event){
19
+ event.preventDefault();
20
+ _this_.print();
21
+ })
22
+ };
23
+
24
+
25
+ return Utils;
26
+ })();
27
+
28
+
29
+ function printDoc(printable) {
30
+ printer = new spreeConekta.Utils({
31
+ printable: $(printable),
32
+ options: { loadCSS: "<%= asset_path('admin/print.css.sass') %>" }
33
+ });
34
+ printer.print();
35
+ };
@@ -0,0 +1,12 @@
1
+ @media print
2
+ .conekta-oxxo
3
+ width: 100px
4
+
5
+ .order-title, .order-footer
6
+ display: none
7
+
8
+ .print
9
+ border: 1px solid black
10
+
11
+ .title
12
+ border-bottom: 1px solid black
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree .
3
+ */
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree .
3
+ */
@@ -0,0 +1,40 @@
1
+ .align-right
2
+ text-align: right
3
+
4
+ .align-center
5
+ text-align: center
6
+
7
+ .conekta-brand
8
+ float: left
9
+
10
+ .conekta-oxxo
11
+ width: 100px
12
+ display: inline
13
+
14
+ .order-footer
15
+ border-top: 1px solid #cee1f4
16
+ margin-top: 20px
17
+ padding-top: 10px
18
+
19
+ .order-title
20
+ margin-bottom: 20px
21
+ border-bottom: 1px solid #cee1f4
22
+
23
+ .payment-title
24
+ padding: 10px 0
25
+ clear: both
26
+
27
+ table.payment-information
28
+ width: 100%
29
+ thead
30
+ background-color: #cee1f4
31
+
32
+ #barcode
33
+ padding: 20px
34
+
35
+ #order_payment
36
+ padding: 20px
37
+
38
+ #oxxo-title
39
+ display: inline
40
+
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree .
3
+ */
@@ -0,0 +1,14 @@
1
+ module Spree
2
+ CheckoutController.class_eval do
3
+ def completion_route
4
+ payment_method = @order.payments.last.payment_method
5
+
6
+ if payment_method.class == Spree::BillingIntegration::Conekta || !payment_method.preferred_source_method == 'card'
7
+ conekta_payment_path(@order)
8
+ else
9
+ @order.payments.last.complete if payment_method.preferred_source_method == 'card'
10
+ spree.order_path(@order)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ module Spree::Conekta
2
+ class PaymentsController < Spree::StoreController
3
+ ssl_required
4
+
5
+ def show
6
+ @order = Spree::Order.find_by_number(params[:id])
7
+ @order_details = @order.last_payment_details.params
8
+ end
9
+
10
+ def create
11
+ update_order_payment if params['type'].eql? 'charge.paid'
12
+ render nothing: true
13
+ end
14
+
15
+ private
16
+ def update_order_payment
17
+ Spree::Payment.capture_by_order_id params['data']['object']['reference_id']
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module Spree
2
+ def self.table_name_prefix
3
+ 'spree_'
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ module Spree
2
+ class BillingIntegration::Conekta < Gateway
3
+ preference :auth_token, :string
4
+ preference :source_method, :string, default: ['card, cash, bank']
5
+
6
+ def provider_class
7
+ Spree::Conekta::Provider
8
+ end
9
+
10
+ def payment_source_class
11
+ card? ? CreditCard : Spree::ConektaPayment
12
+ end
13
+
14
+ def method_type
15
+ card? ? 'gateway' : 'conekta'
16
+ end
17
+
18
+ def card?
19
+ preferred_source_method.eql?('card')
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ class Spree::ConektaPayment < ActiveRecord::Base
2
+ has_many :payments, as: :source
3
+
4
+ def actions
5
+ %w{capture}
6
+ end
7
+
8
+ def can_capture?(payment)
9
+ ['checkout', 'pending'].include?(payment.state)
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ Order.class_eval do
3
+ #HACK
4
+ Spree::Conekta
5
+ Spree::Conekta::Response
6
+ Spree::Conekta::PaymentSource
7
+ Spree::Conekta::PaymentSource::Card
8
+ Spree::Conekta::PaymentSource::Bank
9
+ Spree::Conekta::PaymentSource::Cash
10
+
11
+ def last_payment_details
12
+ YAML.load payments.last.log_entries.last.details
13
+ end
14
+
15
+ def last_payment_source
16
+ payments.last.payment_method_source
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ Payment.class_eval do
3
+ def payment_method_source
4
+ payment_method.options[:source_method]
5
+ end
6
+
7
+ def self.find_by_order_id(order_id)
8
+ Spree::Payment.joins(:order)
9
+ .where(state: 'pending', spree_orders: {
10
+ number: order_id
11
+ }).readonly(false).first
12
+ end
13
+
14
+ def self.capture_by_order_id(order_id)
15
+ Spree::Payment.find_by_order_id(order_id.split('-')[0]).try(:capture!)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ <%- @order_details = @order.last_payment_details.params %>
2
+
3
+ <table class='print' id='conekta_bank'>
4
+ <thead>
5
+ <tr>
6
+ <th class='title' colspan='2'> <%= t('conekta.order_number', number: @order.number) %> </th>
7
+ </tr>
8
+ <tr>
9
+ <th> <%= t('conekta.bank.service_number') %> </th>
10
+ <th> <%= t('conekta.bank.reference') %> </th>
11
+ </tr>
12
+ </thead>
13
+ <tfoot>
14
+ <tr>
15
+ <td colspan='2'> <%= raw t('conekta.bank.payment_message') %> </td>
16
+ </tr>
17
+ </tfoot>
18
+ <tbody>
19
+ <tr>
20
+ <td class='align-center'> <%= @order_details['bank']['service_number'] %> </td>
21
+ <td class='align-center'> <%= @order_details['bank']['reference'] %> </td>
22
+ </tr>
23
+ <tr>
24
+ <td class='align-right'> <%= t('conekta.total') %> </td>
25
+ <td class='align-center'><%= money(@order.total) %></td>
26
+ </tr>
27
+ </tbody>
28
+ </table>
29
+
30
+ <a id='pbutton' href='#' class='icon-print' onclick='printDoc("#conekta_bank")'>
31
+ <%= t('conekta.cash.print_payment_form') %>
32
+ </a>
@@ -0,0 +1,29 @@
1
+ <%- @order_details = @order.last_payment_details.params %>
2
+
3
+ <table class='print' id='conekta_cash'>
4
+ <thead>
5
+ <tr>
6
+ <th class='title' colspan='2'> <%= t('conekta.order_number', number: @order.number) %> </th>
7
+ </tr>
8
+ <tr>
9
+ <th> <%= t('conekta.cash.bar_code') %> </th>
10
+ </tr>
11
+ </thead>
12
+ <tfoot>
13
+ <tr>
14
+ <td colspan='2'> <%= raw t('conekta.cash.payment_message') %> </td>
15
+ </tr>
16
+ </tfoot>
17
+ <tbody>
18
+ <tr>
19
+ <td class='align-center'>
20
+ <%= image_tag(@order_details['cash']['barcode_url']) %>
21
+ <div><%= @order_details['cash']['barcode'] %></div>
22
+ </td>
23
+ </tr>
24
+ </tbody>
25
+ </table>
26
+
27
+ <a id='pbutton' href='#' class='icon-print' onclick='printDoc("#conekta_cash")'>
28
+ <%= t('conekta.cash.print_payment_form') %>
29
+ </a>
@@ -0,0 +1,3 @@
1
+ <% param_prefix = "payment_source[#{payment_method.id}]" %>
2
+ <%= hidden_field param_prefix, 'first_name', :value => @order.billing_firstname %>
3
+ <%= hidden_field param_prefix, 'last_name', :value => @order.billing_lastname %>
@@ -0,0 +1 @@
1
+ <%= render partial: @order.last_payment_source %>
@@ -0,0 +1,3 @@
1
+ <% param_prefix = "payment_source[#{payment_method.id}]" %>
2
+ <%= hidden_field param_prefix, 'first_name', :value => @order.billing_firstname %>
3
+ <%= hidden_field param_prefix, 'last_name', :value => @order.billing_lastname %>
@@ -0,0 +1,30 @@
1
+ <h1><%= t('conekta.bank.payment_title') %></h1>
2
+
3
+ <table id='conekta_bank' class='payment-information'>
4
+ <thead>
5
+ <tr>
6
+ <th colspan='2'> <%= t('conekta.order_number', number: @order.number) %> </th>
7
+ </tr>
8
+ <tr>
9
+ <th> <%= t('conekta.bank.service_number') %> </th>
10
+ <th> <%= t('conekta.bank.reference') %> </th>
11
+ </tr>
12
+ </thead>
13
+ <tfoot>
14
+ <tr>
15
+ <td colspan='2'> <%= raw t('conekta.bank.payment_message') %> </td>
16
+ </tr>
17
+ </tfoot>
18
+ <tbody>
19
+ <tr>
20
+ <td class='align-center'> <%= @order_details['payment_method']['service_number'] %> </td>
21
+ <td class='align-center'> <%= @order_details['payment_method']['reference'] %> </td>
22
+ </tr>
23
+ <tr>
24
+ <td class='align-right' colspan='2'>
25
+ <b><%= t('conekta.total') %></b>
26
+ <%= @order.display_total.to_html %>
27
+ </td>
28
+ </tr>
29
+ </tbody>
30
+ </table>
@@ -0,0 +1,32 @@
1
+ <img class='conekta-oxxo' src='https://s3.amazonaws.com/pagalo/oxxo_logo.png'></img>
2
+ <h1 id='oxxo-title'><%= t("conekta.cash.payment_title") %></h1>
3
+
4
+ <table id='conekta_cash' class='payment-information'>
5
+ <thead>
6
+ <tr>
7
+ <th colspan='2'> <%= t('conekta.order_number', number: @order.number) %> </th>
8
+ </tr>
9
+ <tr>
10
+ <th colspan='2'> <%= t('conekta.cash.bar_code') %> </th>
11
+ </tr>
12
+ </thead>
13
+ <tfoot>
14
+ <tr>
15
+ <td colspan='2'> <%= raw t('conekta.cash.payment_message') %> </td>
16
+ </tr>
17
+ </tfoot>
18
+ <tbody>
19
+ <tr>
20
+ <td class='align-center' id='barcode'>
21
+ <%= image_tag(@order_details['payment_method']['barcode_url']) %>
22
+ <div><%= @order_details['payment_method']['barcode'] %></div>
23
+ </td>
24
+ </tr>
25
+ <tr>
26
+ <td class='align-right'>
27
+ <b><%= t('conekta.total') %></b>
28
+ <%= @order.display_total.to_html %>
29
+ </td>
30
+ </tr>
31
+ </tbody>
32
+ </table>
@@ -0,0 +1,14 @@
1
+ <section id='order-payment'>
2
+ <header class='order-title'>
3
+ <div class='logos'>
4
+ <img class='conekta-brand' src='https://s3.amazonaws.com/conekta/v5/img/conekta-brand.png' alt='Conekta'></img>
5
+ </div>
6
+ <h2 class='payment-title'><%= t('conekta.title') %></h2>
7
+ </header>
8
+ <div class='order-body'>
9
+ <%= render partial: @order.last_payment_source %>
10
+ </div>
11
+ <footer class='order-footer'>
12
+ <%= button_tag t('conekta.print_payment_form'), class: 'right', onclick: 'printDoc("#order-payment")' %>
13
+ </footer>
14
+ </section>
@@ -0,0 +1,20 @@
1
+ en:
2
+ conekta:
3
+ additional_steps_warning: Additional steps to complete your payment
4
+ card:
5
+ processing_order: Processing order please wait
6
+ cash:
7
+ bar_code: Barcode
8
+ next_step: Next step
9
+ payment_message: Print this form and take it to the nearest OXXO to make your payment.
10
+ payment_title: Payment through OXXO
11
+ print_payment_form: Print payment form
12
+ title: Payment information
13
+ total: Total
14
+ bank:
15
+ payment_title: Banorte deposit
16
+ service_number: Service Number
17
+ reference: Reference
18
+ payment_message: Give this reference number at any Banorte bank.
19
+ order_number: 'Order Number: %{number}'
20
+ total: 'Total:'
@@ -0,0 +1,20 @@
1
+ es-MX:
2
+ conekta:
3
+ additional_steps_warning: Pasos adicionales para completar su pago
4
+ card:
5
+ processing_order: Procesando su pago espere un momento
6
+ cash:
7
+ bar_code: Código de barras
8
+ payment_message: Imprime este formulario y preséntalo en el Oxxo mas cercano para realizar tu pago.
9
+ payment_title: Pago a través de Oxxo
10
+ total: Total
11
+ bank:
12
+ payment_title: Depósito en ventanilla Banorte
13
+ service_number: Número de servicio
14
+ reference: Referencia
15
+ payment_message: 'Presente este número de referencia en cualquier sucursal: <strong> Banorte </strong>'
16
+ title: Información de pago
17
+ next_step: Siguiente paso
18
+ order_number: 'Número de orden: %{number}'
19
+ print_payment_form: Imprimir ficha de pago
20
+ total: 'Total a pagar:'
@@ -0,0 +1,5 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ namespace :conekta do
3
+ resources :payments, only: [:create, :show]
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class CreateSpreeConektaPayments < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_conekta_payments do |t|
4
+ t.string :type
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ class RenameTypeColumnToConektaPayment < ActiveRecord::Migration
2
+ def change
3
+ rename_column :spree_conekta_payments, :type, :payment_type
4
+ add_column :spree_conekta_payments, :first_name, :string
5
+ add_column :spree_conekta_payments, :last_name, :string
6
+ end
7
+ end
@@ -0,0 +1,32 @@
1
+ module SpreeConekta
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+
5
+ class_option :auto_run_migrations, :type => :boolean, :default => false
6
+
7
+ def add_javascripts
8
+ append_file 'app/assets/javascripts/store/all.js', "\n//= require spree_conekta\n"
9
+ append_file 'app/assets/javascripts/admin/all.js', "\n//= require spree_conekta\n"
10
+ end
11
+
12
+ def add_stylesheets
13
+ inject_into_file 'app/assets/stylesheets/store/all.css', "\n *= require spree_conekta\n", :before => /\*\//, :verbose => true
14
+ inject_into_file 'app/assets/stylesheets/admin/all.css', "\n *= require spree_conekta\n", :before => /\*\//, :verbose => true
15
+ end
16
+
17
+ def add_migrations
18
+ run 'bundle exec rake railties:install:migrations'
19
+ end
20
+
21
+ def run_migrations
22
+ res = ask 'Would you like to run the migrations now? [Y/n]'
23
+ if res == '' || res.downcase == 'y'
24
+ run 'bundle exec rake db:migrate'
25
+ else
26
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ module Spree::Conekta
2
+ class Client
3
+ CONEKTA_API = 'https://api.conekta.io/'
4
+ CHARGE_ENDPOINT = 'charges'
5
+
6
+ attr_accessor :auth_token
7
+
8
+ PAYMENT_SOURCES = {
9
+ 'card' => Spree::Conekta::PaymentSource::Card,
10
+ 'bank' => Spree::Conekta::PaymentSource::Bank,
11
+ 'cash' => Spree::Conekta::PaymentSource::Cash
12
+ }
13
+
14
+ def post(params)
15
+ Oj.load connection.post(CHARGE_ENDPOINT, Oj.dump(params)).body
16
+ end
17
+
18
+ def payment_processor(source_name)
19
+ PAYMENT_SOURCES[source_name]
20
+ end
21
+
22
+ def connection
23
+ Faraday.new(:url => CONEKTA_API) do |faraday|
24
+ faraday.request :url_encoded
25
+
26
+ faraday.headers = headers
27
+ faraday.adapter :typhoeus
28
+ faraday.basic_auth(auth_token, nil)
29
+ end
30
+ end
31
+
32
+ def headers
33
+ {
34
+ 'Accept' => ' application/vnd.conekta-v0.2.0+json',
35
+ 'Content-type' => ' application/json'
36
+ }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ module Spree::Conekta::PaymentSource
2
+ module Bank
3
+ def request(common, method, gateway_options)
4
+ common['bank'] = {
5
+ 'type' => 'banorte'
6
+ }
7
+ end
8
+
9
+ module_function :request
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ module Spree::Conekta::PaymentSource
2
+ module Card
3
+ def request(common, method, gateway_options)
4
+ common['card'] = {
5
+ 'name' => "#{method.first_name} #{method.last_name}",
6
+ 'cvc' => method.verification_value,
7
+ 'number' => method.number,
8
+ 'exp_year' => method.year.to_s[-2,2],
9
+ 'exp_month' => sprintf('%02d', method.month),
10
+ 'address' => customer_address(gateway_options)
11
+ }
12
+ end
13
+
14
+ def self.customer_address(gateway_options)
15
+ customer = gateway_options[:billing_address]
16
+ customer['street1'] = customer.delete(:address1)
17
+ customer['street2'] = customer.delete(:address2)
18
+ customer
19
+ end
20
+
21
+ module_function :request
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module Spree::Conekta::PaymentSource
2
+ module Cash
3
+ def request(common, method, gateway_options)
4
+ common['cash'] = {
5
+ 'type' => 'oxxo'
6
+ }
7
+ end
8
+
9
+ module_function :request
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ module Spree::Conekta
2
+ class Provider < Client
3
+ attr_accessor :auth_token, :source_method
4
+
5
+ def initialize(options = {})
6
+ self.auth_token = options[:auth_token]
7
+ self.source_method = payment_processor(options[:source_method])
8
+ end
9
+
10
+ def authorize(amount, method_params, gateway_options = {})
11
+ common = build_common(amount, gateway_options)
12
+ commit common, method_params, gateway_options
13
+ end
14
+
15
+ def capture(amount, method_params, gateway_options = {})
16
+ Response.new({}, gateway_options)
17
+ end
18
+
19
+ private
20
+ def commit(common, method_params, gateway_options)
21
+ source_method.request(common, method_params, gateway_options)
22
+ response = Spree::Conekta::Response.new post(common), source_method
23
+
24
+ if response.status.eql? 'paid'
25
+ Spree::Payment.capture_by_order_id gateway_options[:order_id]
26
+ end
27
+
28
+ response
29
+ end
30
+
31
+ def build_common(amount, gateway_params)
32
+ {
33
+ 'amount' => amount,
34
+ 'reference_id' => gateway_params[:order_id],
35
+ 'currency' => gateway_params[:currency],
36
+ 'description' => gateway_params[:order_id]
37
+ }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ module Spree::Conekta
2
+ class Response < ActiveMerchant::Billing::Response
3
+ attr_accessor :response, :source_method, :status
4
+
5
+ def initialize(response, source_method)
6
+ @success = !(response.eql?('null') || response.include?('type')) if response
7
+ @message = @success ? 'Ok' : response['message']
8
+ @params = response
9
+ @status = response['status']
10
+ @source_method = source_method
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'spree_core'
2
+ require 'spree_backend'
3
+ require 'spree_frontend'
4
+ require 'nokogiri'
5
+ require 'typhoeus/adapters/faraday'
6
+ require 'faraday'
7
+ require 'faraday_middleware'
8
+ require 'spree_conekta/engine'
@@ -0,0 +1,32 @@
1
+ module SpreeConekta
2
+ class Engine < ::Rails::Engine
3
+ require 'spree'
4
+
5
+ engine_name 'spree_gateway'
6
+
7
+ config.autoload_paths += %W(#{config.root}/lib)
8
+
9
+ # use rspec for tests
10
+ config.generators do |g|
11
+ g.test_framework :rspec
12
+ end
13
+
14
+ if Rails.version >= '3.1'
15
+ initializer :assets do |config|
16
+ Rails.application.config.assets.precompile += %w( spree_conekta.js )
17
+ end
18
+ end
19
+
20
+ def self.activate
21
+ Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
22
+ Rails.env.production? ? require(c) : load(c)
23
+ end
24
+ end
25
+
26
+ initializer "spree.gateway.payment_methods", :after => "spree.register.payment_methods" do |app|
27
+ app.config.spree.payment_methods << Spree::BillingIntegration::Conekta
28
+ end
29
+
30
+ config.to_prepare &method(:activate).to_proc
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ module SpreeConekta
2
+ VERSION = "0.5.9"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :spree_conekta do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_conekta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.9
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan Garay
8
+ - Fernando Barajas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: oj
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: faraday
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: typhoeus
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: faraday_middleware
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: activemerchant
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: spree
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ version: '2.1'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ~>
96
+ - !ruby/object:Gem::Version
97
+ version: '2.1'
98
+ description: Spree Engine for Conekta Mexican Payment gateway
99
+ email:
100
+ - jonathan.garay@crowdint.com
101
+ - fernando.barajas@crowdint.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - app/assets/javascripts/admin/spree_conekta.js
107
+ - app/assets/javascripts/spree_conekta.js
108
+ - app/assets/javascripts/store/easyXDM.min.js
109
+ - app/assets/javascripts/store/printThis.js
110
+ - app/assets/javascripts/store/spree_conekta.js
111
+ - app/assets/javascripts/store/utils.js.erb
112
+ - app/assets/stylesheets/admin/print.css.sass
113
+ - app/assets/stylesheets/admin/spree_conekta.css
114
+ - app/assets/stylesheets/spree_conekta.css
115
+ - app/assets/stylesheets/store/conekta.css.sass
116
+ - app/assets/stylesheets/store/spree_conekta.css
117
+ - app/controllers/spree/checkout_controller_decorator.rb
118
+ - app/controllers/spree/conekta/payments_controller.rb
119
+ - app/models/spree/billing_integration/conekta.rb
120
+ - app/models/spree/conekta_payment.rb
121
+ - app/models/spree/order_decorator.rb
122
+ - app/models/spree/payment_decorator.rb
123
+ - app/models/spree.rb
124
+ - app/views/spree/admin/payments/_bank.html.erb
125
+ - app/views/spree/admin/payments/_cash.html.erb
126
+ - app/views/spree/admin/payments/source_forms/_conekta.html.erb
127
+ - app/views/spree/admin/payments/source_views/_conekta.html.erb
128
+ - app/views/spree/checkout/payment/_conekta.html.erb
129
+ - app/views/spree/conekta/payments/_bank.html.erb
130
+ - app/views/spree/conekta/payments/_card.html.erb
131
+ - app/views/spree/conekta/payments/_cash.html.erb
132
+ - app/views/spree/conekta/payments/show.html.erb
133
+ - config/locales/en.yml
134
+ - config/locales/es-MX.yml
135
+ - config/routes.rb
136
+ - db/migrate/20130904161251_create_spree_conekta_payments.rb
137
+ - db/migrate/20130904172418_rename_type_column_to_conekta_payment.rb
138
+ - lib/generators/spree_conekta/install/install_generator.rb
139
+ - lib/spree/conekta/client.rb
140
+ - lib/spree/conekta/payment_source/bank.rb
141
+ - lib/spree/conekta/payment_source/card.rb
142
+ - lib/spree/conekta/payment_source/cash.rb
143
+ - lib/spree/conekta/provider.rb
144
+ - lib/spree/conekta/response.rb
145
+ - lib/spree_conekta/engine.rb
146
+ - lib/spree_conekta/version.rb
147
+ - lib/spree_conekta.rb
148
+ - lib/tasks/spree_conekta_tasks.rake
149
+ - MIT-LICENSE
150
+ - Rakefile
151
+ - README.md
152
+ homepage: http://github.com/crowdint/spree_conekta
153
+ licenses: []
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - '>='
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.1.10
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Spree Engine for Conekta Mexican Payment gateway
175
+ test_files: []