Last active
July 19, 2023 20:35
-
-
Save ccjmne/a25fe512be9c3f5633a05992d65576fc to your computer and use it in GitHub Desktop.
EVO Mock Redirect TamperMonkey Script for Unite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(()=>{"use strict";const e={ECB:0,CBC:1},a={PKCS5:0,ONE_AND_ZEROS:1,LAST_BYTE:2,NULL:3,SPACES:4},c={STRING:0,UINT8_ARRAY:1};function d(e){return e>>>0}function f(e,a){return d(e^a)}function b(e,a){return d(e+a|0)}function t(e,a,c,f){return d(e<<24|a<<16|c<<8|f)}function r(e){return[e>>>24&255,e>>>16&255,e>>>8&255,255&e]}function n(e){return"string"==typeof e}function s(e){return"object"==typeof e&&"byteLength"in e}function o(e){return n(e)||s(e)}function i(e,a){let c=!1;return Object.keys(e).forEach((d=>{e[d]===a&&(c=!0)})),c}function l(e){if(n(e))return(new TextEncoder).encode(e);if(s(e))return new Uint8Array(e);throw new Error("Unsupported type")}const u="243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d01377be5466cf34e90c6cc0ac29b7c97c50dd3f84d5b5b54709179216d5d98979fb1bd1310ba698dfb5ac2ffd72dbd01adfb7b8e1afed6a267e96ba7c9045f12c7f9924a19947b3916cf70801f2e2858efc16636920d871574e69a458fea3f4933d7e0d95748f728eb658718bcd5882154aee7b54a41dc25a59b59c30d5392af26013c5d1b023286085f0ca417918b8db38ef8e79dcb0603a180e6c9e0e8bb01e8a3ed71577c1bd314b2778af2fda55605c60e65525f3aa55ab945748986263e8144055ca396a2aab10b6b4cc5c341141e8cea15486af7c72e993b3ee1411636fbc2a2ba9c55d741831f6ce5c3e169b87931eafd6ba336c24cf5c7a325381289586773b8f48986b4bb9afc4bfe81b6628219361d809ccfb21a991487cac605dec8032ef845d5de98575b1dc262302eb651b8823893e81d396acc50f6d6ff383f442392e0b4482a484200469c8f04a9e1f9b5e21c66842f6e96c9a670c9c61abd388f06a51a0d2d8542f68960fa728ab5133a36eef0b6c137a3be4ba3bf0507efb2a98a1f1651d39af017666ca593e82430e888cee8619456f9fb47d84a5c33b8b5ebee06f75d885c12073401a449f56c16aa64ed3aa62363f77061bfedf72429b023d37d0d724d00a1248db0fead349f1c09b075372c980991b7b25d479d8f6e8def7e3fe501ab6794c3b976ce0bd04c006bac1a94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5ebd09bee3d004de334afd660f2807192e4bb3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c6402c7279679f25fefb1fa3cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd23876053317b483e00df829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbca58c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb9790e1ddf2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae909198eaad8e716b93d5a0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df01c4fad5ea0688fc31cd1cff191b3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74e818acf3d6ce89e299b4a84fe0fd13e0b77cc43b81d2ada8d9165fa2668095770593cc7314211a1477e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e89a0d6411bd3ae1e7e4900250e2d2071b35e226800bb57b8e0af2464369bf009b91e5563911d59dfa6aa78c14389d95a537f207d5ba202e5b9c5832603766295cfa911c819684e734a41b3472dca7b14a94a1b5100529a532915d60f573fbc9bc6e42b60a47681e6740008ba6fb5571be91ff296ec6b2a0dd915b6636521e7b9f9b6ff34052ec585566453b02d5da99f8fa108ba47996e85076a4b7a70e9b5b32944db75092ec4192623ad6ea6b049a7df7d9cee60b88fedb266ecaa8c71699a17ff5664526cc2b19ee1193602a575094c29a0591340e4183a3e3f54989a5b429d656b8fe4d699f73fd6a1d29c07efe830f54d2d38e6f0255dc14cdd20868470eb266382e9c6021ecc5e09686b3f3ebaefc93c9718146b6a70a1687f358452a0e286b79c5305aa5007373e07841c7fdeae5c8e7d44ec5716f2b8b03ada37f0500c0df01c1f040200b3ffae0cf51a3cb574b225837a58dc0921bdd19113f97ca92ff69432477322f547013ae5e58137c2dadcc8b576349af3dda7a94461460fd0030eecc8c73ea4751e41e238cd993bea0e2f3280bba1183eb3314e548b384f6db9086f420d03f60a04bf2cb8129024977c795679b072bcaf89afde9a771fd9930810b38bae12dccf3f2e5512721f2e6b7124501adde69f84cd877a5847187408da17bc9f9abce94b7d8cec7aec3adb851dfa63094366c464c3d2ef1c18473215d908dd433b3724c2ba1612a14d432a65c45150940002133ae4dd71dff89e10314e5581ac77d65f11199b043556f1d7a3c76b3c11183b5924a509f28fe6ed97f1fbfa9ebabf2c1e153c6e86e34570eae96fb1860e5e0a5a3e2ab3771fe71c4e3d06fa2965dcb999e71d0f803e89d65266c8252e4cc9789c10b36ac6150eba94e2ea78a5fc3c531e0a2df4f2f74ea7361d2b3d1939260f19c279605223a708f71312b6ebadfe6eeac31f66e3bc4595a67bc883b17f37d1018cff28c332ddefbe6c5aa56558218568ab9802eecea50fdb2f953b2aef7dad5b6e2f841521b62829076170ecdd4775619f151013cca830eb61bd960334fe1eaa0363cfb5735c904c70a239d59e9e0bcbaade14eecc86bc60622ca79cab5cabb2f3846e648b1eaf19bdf0caa02369b9655abb5040685a323c2ab4b3319ee9d5c021b8f79b540b19875fa09995f7997e623d7da8f837889a97e32d7711ed935f166812810e358829c7e61fd696dedfa17858ba9957f584a51b2272639b83c3ff1ac24696cdb30aeb532e30548fd948e46dbc312858ebf2ef34c6ffeafe28ed61ee7c3c735d4a14d9e864b7e342105d14203e13e045eee2b6a3aaabeadb6c4f15facb4fd0c742f442ef6abbb5654f3b1d41cd2105d81e799e86854dc7e44b476a3d816250cf62a1f25b8d2646fc8883a0c1c7b6a37f1524c369cb749247848a0b5692b285095bbf00ad19489d1462b17423820e0058428d2a0c55f5ea1dadf43e233f70613372f0928d937e41d65fecf16c223bdb7cde3759cbee74604085f2a7ce77326ea607808419f8509ee8efd85561d99735a969a7aac50c06c25a04abfc800bcadc9e447a2ec3453484fdd567050e1e9ec9db73dbd3105588cd675fda79e3674340c5c43465713e38d83d28f89ef16dff20153e21e78fb03d4ae6e39f2bdb83adf7e93d5a68948140f7f64c261c94692934411520f77602d4f7bcf46b2ed4a20068d40824713320f46a43b7d4b7500061af1e39f62e9724454614214f74bf8b88404d95fc1d96b591af70f4ddd366a02f45bfbc09ec03bd97857fac6dd031cb850496eb27b355fd3941da2547e6abca0a9a28507825530429f40a2c86dae9b66dfb68dc1462d7486900680ec0a427a18dee4f3ffea2e887ad8cb58ce0067af4d6b6aace1e7cd3375fecce78a399406b2a4220fe9e35d9f385b9ee39d7ab3b124e8b1dc9faf74b6d185626a36631eae397b23a6efa74dd5b43326841e7f7ca7820fbfb0af54ed8feb397454056acba48952755533a3a20838d87fe6ba9b7d096954b55a867bca1159a58cca9296399e1db33a62a4a563f3125f95ef47e1c9029317cfdf8e80204272f7080bb155c05282ce395c11548e4c66d2248c1133fc70f86dc07f9c9ee41041f0f404779a45d886e17325f51ebd59bc0d1f2bcc18f41113564257b7834602a9c60dff8e8a31f636c1b0e12b4c202e1329eaf664fd1cad181156b2395e0333e92e13b240b62eebeb92285b2a20ee6ba0d99de720c8c2da2f728d012784595b794fd647d0862e7ccf5f05449a36f877d48fac39dfd27f33e8d1e0a476341992eff743a6f6eabf4f8fd37a812dc60a1ebddf8991be14cdb6e6b0dc67b55106d672c372765d43bdcd0e804f1290dc7cc00ffa3b5390f92690fed0b667b9ffbcedb7d9ca091cf0bd9155ea3bb132f88515bad247b9479bf763bd6eb37392eb3cc1159798026e297f42e312d6842ada7c66a2b3b12754ccc782ef11c6a124237b79251e706a1bbe64bfb63501a6b101811caedfa3d25bdd8e2e1c3c9444216590a121386d90cec6ed5abea2a64af674eda86a85fbebfe98864e4c3fe9dbc8057f0f7c08660787bf86003604dd1fd8346f6381fb07745ae04d736fccc83426b33f01eab71b08041873c005e5f77a057bebde8ae2455464299bf582e614e58f48ff2ddfda2f474ef388789bdc25366f9c3c8b38e74b475f25546fcd9b97aeb26618b1ddf84846a0e79915f95e2466e598e20b457708cd55591c902de4cb90bace1bb8205d011a862487574a99eb77f19b6e0a9dc09662d09a1c4324633e85a1f0209f0be8c4a99a0251d6efe101ab93d1d0ba5a4dfa186f20f2868f169dcb7da83573906fea1e2ce9b4fcd7f5250115e01a70683faa002b5c40de6d0279af88c27773f8641c3604c0661a806b5f0177a28c0f586e0006058aa30dc7d6211e69ed72338ea6353c2dd94c2c21634bbcbee5690bcb6deebfc7da1ce591d766f05e4094b7c018839720a3d7c927c2486e3725f724d9db91ac15bb4d39eb8fced54557808fca5b5d83d7cd34dad0fc41e50ef5eb161e6f8a28514d96c51133c6fd5c7e756e14ec4362abfceddc6c837d79a323492638212670efa8e406000e03a39ce37d3faf5cfabc277375ac52d1b5cb0679e4fa33742d382274099bc9bbed5118e9dbf0f7315d62d1c7ec700c47bb78c1b6b21a19045b26eb1be6a366eb45748ab2fbc946e79c6a376d26549c2c8530ff8ee468dde7dd5730a1d4cd04dc62939bbdba9ba4650ac9526e8be5ee304a1fad5f06a2d519a63ef8ce29a86ee22c089c2b843242ef6a51e03aa9cf2d0a483c061ba9be96a4d8fe51550ba645bd62826a2f9a73a3ae14ba99586ef5562e9c72fefd3f752f7da3f046f6977fa0a5980e4a91587b086019b09e6ad3b3ee593e990fd5a9e34d7972cf0b7d9022b8b5196d5ac3a017da67dd1cf3ed67c7d2d281f9f25cfadf2b89b5ad6b4725a88f54ce029ac71e019a5e647b0acfded93fa9be8d3c48d283b57ccf8d5662979132e28785f0191ed756055f7960e44e3d35e8c15056dd488f46dba03a161250564f0bdc3eb9e153c9057a297271aeca93a072a1b3f6d9b1e6321f5f59c66fb26dcf3197533d928b155fdf5035634828aba3cbb28517711c20ad9f8abcc5167ccad925f4de817513830dc8e379d58629320f991ea7a90c2fb3e7bce5121ce64774fbe32a8b6e37ec3293d4648de53696413e680a2ae0810dd6db22469852dfd09072166b39a460a6445c0dd586cdecf1c20c8ae5bbef7dd1b588d40ccd2017f6bb4e3bbdda26a7e3a59ff453e350a44bcb4cdd572eacea8fa6484bb8d6612aebf3c6f47d29be463542f5d9eaec2771bf64e6370740e0d8de75b1357f8721671af537d5d4040cb084eb4e2cc34d2466a0115af84e1b0042895983a1d06b89fb4ce6ea0486f3f3b823520ab82011a1d4b277227f8611560b1e7933fdcbb3a792b344525bda08839e151ce794b2f32c9b7a01fbac9e01cc87ebcc7d1f6cf0111c3a1e8aac71a908749d44fbd9ad0dadecbd50ada380339c32ac69136678df9317ce0b12b4ff79e59b743f5bb3af2d519ff27d9459cbf97222c15e6fc2a0f91fc719b941525fae59361ceb69cebc2a8645912baa8d1b6c1075ee3056a0c10d25065cb03a442e0ec6e0e1698db3b4c98a0be3278e9649f1f9532e0d392dfd3a0342b8971f21e1b0a74414ba3348cc5be7120c37632d8df359f8d9b992f2ee60b6f470fe3f11de54cda541edad891ce6279cfcd3e7e6f1618b166fd2c1d05848fd2c5f6fb2299f523f357a632762393a8353156cccd02acf081625a75ebb56e16369788d273ccde96629281b949d04c50901b71c65614e6c6c7bd327a140a45e1d006c3f27b9ac9aa53fd62a80f00bb25bfe235bdd2f671126905b2040222b6cbcf7ccd769c2b53113ec01640e3d338abbd602547adf0ba38209cf746ce7677afa1c52075606085cbfe4e8ae88dd87aaaf9b04cf9aa7e1948c25c02fb8a8c01c36ae4d6ebe1f990d4f869a65cdea03f09252dc208e69fb74e6132ce77e25b578fdfe33ac372e6";class h{static get MODE(){return e}static get PADDING(){return a}static get TYPE(){return c}constructor(c,d=e.ECB,b=a.PKCS5){if(!o(c))throw new Error("Key should be a string or an ArrayBuffer / Buffer");if(c.length<1||c.byteLength<1)throw new Error("Key should not be empty");if(!i(e,d))throw new Error("Unsupported mode");if(!i(a,b))throw new Error("Unsupported padding");this.mode=d,this.padding=b,this.iv=null;const r=function(){const e={p:[],s:[[],[],[],[]]};let a=0;for(let c=0;c<18;c++){const c=u.substring(a,a+8);a+=8,e.p.push(Number(`0x${c}`))}for(let c=0;c<4;c++)for(let d=0;d<256;d++){const d=u.substring(a,a+8);a+=8,e.s[c].push(Number(`0x${d}`))}return e}();this.p=r.p,this.s=r.s,c=function(e){if(e.length>=72)return e;const a=[];for(;a.length<72;)for(let c=0;c<e.length;c++)a.push(e[c]);return new Uint8Array(a)}(l(c));for(let e=0,a=0;e<18;e++,a+=4){const d=t(c[a],c[a+1],c[a+2],c[a+3]);this.p[e]=f(this.p[e],d)}let n=0,s=0;for(let e=0;e<18;e+=2)[n,s]=this._encryptBlock(n,s),this.p[e]=n,this.p[e+1]=s;for(let e=0;e<4;e++)for(let a=0;a<256;a+=2)[n,s]=this._encryptBlock(n,s),this.s[e][a]=n,this.s[e][a+1]=s}setIv(e){if(!o(e))throw new Error("IV should be a string or an ArrayBuffer / Buffer");if(8!==(e=l(e)).length)throw new Error("IV should be 8 byte length");this.iv=e}encode(c){if(!o(c))throw new Error("Encode data should be a string or an ArrayBuffer / Buffer");if(this.mode!==e.ECB&&!this.iv)throw new Error("IV is not set");return c=function(e,c){const d=8-e.length%8;if(8===d&&e.length>0&&c!==a.PKCS5)return e;const f=new Uint8Array(e.length+d),b=[];let t=d,r=0;switch(c){case a.PKCS5:r=d;break;case a.ONE_AND_ZEROS:b.push(128),t--;break;case a.SPACES:r=32}for(;t>0;){if(c===a.LAST_BYTE&&1===t){b.push(d);break}b.push(r),t--}return f.set(e),f.set(b,e.length),f}(l(c),this.padding),this.mode===e.ECB?this._encodeECB(c):this.mode===e.CBC?this._encodeCBC(c):void 0}decode(d,f=c.STRING){if(!o(d))throw new Error("Decode data should be a string or an ArrayBuffer / Buffer");if(this.mode!==e.ECB&&!this.iv)throw new Error("IV is not set");if((d=l(d)).length%8!=0)throw new Error("Decoded data should be multiple of 8 bytes");switch(this.mode){case e.ECB:d=this._decodeECB(d);break;case e.CBC:d=this._decodeCBC(d)}switch(d=function(e,c){let d=0;switch(c){case a.LAST_BYTE:case a.PKCS5:{const a=e[e.length-1];a<=8&&(d=a);break}case a.ONE_AND_ZEROS:{let a=1;for(;a<=8;){const c=e[e.length-a];if(128===c){d=a;break}if(0!==c)break;a++}break}case a.NULL:case a.SPACES:{const f=c===a.SPACES?32:0;let b=1;for(;b<=8;){if(e[e.length-b]!==f){d=b-1;break}b++}break}}return e.subarray(0,e.length-d)}(d,this.padding),f){case c.UINT8_ARRAY:return d;case c.STRING:return(new TextDecoder).decode(d);default:throw new Error("Unsupported return type")}}_encryptBlock(e,a){for(let c=0;c<16;c++)e=f(e,this.p[c]),a=f(a,this._f(e)),[e,a]=[a,e];return[e,a]=[a,e],a=f(a,this.p[16]),[e=f(e,this.p[17]),a]}_decryptBlock(e,a){for(let c=17;c>1;c--)e=f(e,this.p[c]),a=f(a,this._f(e)),[e,a]=[a,e];return[e,a]=[a,e],a=f(a,this.p[1]),[e=f(e,this.p[0]),a]}_f(e){const a=e>>>24&255,c=e>>>16&255,d=e>>>8&255,t=255&e;let r=b(this.s[0][a],this.s[1][c]);return r=f(r,this.s[2][d]),b(r,this.s[3][t])}_encodeECB(e){const a=new Uint8Array(e.length);for(let c=0;c<e.length;c+=8){let d=t(e[c],e[c+1],e[c+2],e[c+3]),f=t(e[c+4],e[c+5],e[c+6],e[c+7]);[d,f]=this._encryptBlock(d,f),a.set(r(d),c),a.set(r(f),c+4)}return a}_encodeCBC(e){const a=new Uint8Array(e.length);let c=t(this.iv[0],this.iv[1],this.iv[2],this.iv[3]),d=t(this.iv[4],this.iv[5],this.iv[6],this.iv[7]);for(let b=0;b<e.length;b+=8){let n=t(e[b],e[b+1],e[b+2],e[b+3]),s=t(e[b+4],e[b+5],e[b+6],e[b+7]);[n,s]=[f(c,n),f(d,s)],[n,s]=this._encryptBlock(n,s),[c,d]=[n,s],a.set(r(n),b),a.set(r(s),b+4)}return a}_decodeECB(e){const a=new Uint8Array(e.length);for(let c=0;c<e.length;c+=8){let d=t(e[c],e[c+1],e[c+2],e[c+3]),f=t(e[c+4],e[c+5],e[c+6],e[c+7]);[d,f]=this._decryptBlock(d,f),a.set(r(d),c),a.set(r(f),c+4)}return a}_decodeCBC(e){const a=new Uint8Array(e.length);let c,d,b=t(this.iv[0],this.iv[1],this.iv[2],this.iv[3]),n=t(this.iv[4],this.iv[5],this.iv[6],this.iv[7]);for(let s=0;s<e.length;s+=8){let o=t(e[s],e[s+1],e[s+2],e[s+3]),i=t(e[s+4],e[s+5],e[s+6],e[s+7]);[c,d]=[o,i],[o,i]=this._decryptBlock(o,i),[o,i]=[f(b,o),f(n,i)],[b,n]=[c,d],a.set(r(o),s),a.set(r(i),s+4)}return a}}class p{}p.transId="TransID",p.refNr="RefNr",p.userData="UserData",p.mac="MAC",p.amount="Amount",p.currency="Currency",p.orderDesc="OrderDesc",p.urlSuccess="URLSuccess",p.urlFailure="URLFailure",p.response="Response",p.urlNotify="URLNotify",p.capture="Capture",p.mid="mid",p.payId="PayID",p.xid="XID",p.type="Type",p.pcnr="PCNr",p.ccEpiry="CCExpiry",p.ccBrand="CCBrand",p.status="Status",p.description="Description",p.code="Code";class y{}function g(e,a,c,d){var f;const b=new URLSearchParams(e),t=[...function(e,a,c){var d,f,b,t;return[p.amount,p.currency,p.response,p.orderDesc,p.urlFailure,p.urlSuccess,p.urlNotify,p.capture].forEach((a=>e.delete(a))),e.set(p.mid,null!==(d=a.get("MerchantID"))&&void 0!==d?d:"mid_not_exist"),e.set(p.pcnr,"0022589500163111"),e.set(p.payId,"cef0006a2d54467d84174b08704e6314"),e.set(p.xid,"69f842ba459c48c188f25c2245d33585"),e.set(p.type,"SSL"),e.set(p.ccEpiry,"202912"),e.set(p.ccBrand,"VISA"),e.set(p.status,null!==(f=c.get(p.status))&&void 0!==f?f:"failure"),e.set(p.description,null!==(b=c.get(p.description))&&void 0!==b?b:"description"),e.set(p.code,null!==(t=c.get(p.code))&&void 0!==t?t:"321321"),e}((n=null!==(f=b.get("Data"))&&void 0!==f?f:"no_data",r=new h(a,h.MODE.ECB,h.PADDING.SPACES).decode(new Uint8Array(function(e){var a,c;return null!==(c=null===(a=e.match(/.{2}/g))||void 0===a?void 0:a.map((e=>parseInt(e,16))))&&void 0!==c?c:[]}(n)).buffer,h.TYPE.STRING),new Map(r.split("&").map((e=>e.split("="))))),b,c).entries()].map((([e,a])=>`${e}=${a}`)).join("&");var r,n;const s=(o=t,i=new h(a,h.MODE.ECB,h.PADDING.SPACES).encode(o),[...i].map((e=>Number(e).toString(16).toUpperCase().padStart(2,"0"))).join(""));var o,i;return`http://dev-stage.mercateo.${d}/basket/deucsredirect?Len=${t.length}&Data=${s}`}y.gb="T...",y.de="B...",function(){var e,a;const c=document.createElement("label");c.textContent="Hostname:",c.style.textAlign="end",c.setAttribute("for","hostname");const d=document.createElement("input");d.type="text",d.id="hostname",d.name="hostname",d.required=!0,d.value=null!==(e=localStorage.getItem("hostnameInput"))&&void 0!==e?e:"local.mercateo.co.uk:8081",d.addEventListener("change",(()=>localStorage.setItem("hostnameInput",d.value)));const f=document.createElement("label");f.textContent="Blowfish Key:",f.style.textAlign="end",f.setAttribute("for","blowfishKey");const b=document.createElement("input");b.type="text",b.id="blowfishKey",b.name="blowfishKey",b.required=!0,b.value=null!==(a=localStorage.getItem("blowfishInput"))&&void 0!==a?a:"",b.addEventListener("change",(()=>localStorage.setItem("blowfishInput",b.value)));const t=document.createElement("button");t.type="button",t.textContent="Redirect to Failure",t.onclick=()=>window.location.href=function(e,a,c){const d=new Map;return d.set(p.status,"FAILED"),d.set(p.description,"FAILED"),d.set(p.code,"21200200"),g(e,a,d,"co.uk")}(window.location.search.substring(1),b.value).replace(/(?<=https?:\/\/)[^/]+/,d.value);const r=document.createElement("button");r.type="button",r.textContent="Redirect to Success",r.onclick=()=>window.location.href=function(e,a,c){const d=new Map;return d.set(p.status,"AUTHORIZED"),d.set(p.description,"success"),d.set(p.code,"00000000"),g(e,a,d,"co.uk")}(window.location.search.substring(1),b.value).replace(/(?<=https?:\/\/)[^/]+/,d.value);const n=document.createElement("div");n.style.gridColumn="1 / 3",n.style.display="grid",n.style.gap="10px",n.style.gridTemplate="auto / 1fr 1fr",n.appendChild(t),n.appendChild(r);const s=document.createElement("form");s.id="redirectForm",s.style.display="grid",s.style.background="whitesmoke",s.style.color="grey",s.style.border="1px solid lightgrey",s.style.gridTemplate="1fr 1fr 1fr / auto 1fr",s.style.gap="10px",s.style.padding="10px",s.style.borderRadius="3px",s.style.boxShadow="rgba(0, 0, 0, 0.35) 0px 5px 15px",s.appendChild(c),s.appendChild(d),s.appendChild(f),s.appendChild(b),s.appendChild(n);const o=document.createElement("div");o.style.position="fixed",o.style.top="10px",o.style.left="50%",o.style.transform="translate(-50%) perspective(0)",o.style.zIndex="9999";const i=o.attachShadow({mode:"closed"}),l=document.createElement("style");l.textContent="\n :host * {\n font-family: sans-serif\n font-size: 1rem\n white-space: nowrap\n }",i.appendChild(l),i.appendChild(s),document.body.appendChild(o)}()})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Blowfish } from 'egoroof-blowfish' | |
class ParamName { | |
static transId: string = 'TransID' | |
static refNr: string = 'RefNr' | |
static userData: string = 'UserData' | |
static mac: string = 'MAC' | |
static amount: string = 'Amount' | |
static currency: string = 'Currency' | |
static orderDesc: string = 'OrderDesc' | |
static urlSuccess: string = 'URLSuccess' | |
static urlFailure: string = 'URLFailure' | |
static response: string = 'Response' | |
static urlNotify: string = 'URLNotify' | |
static capture: string = 'Capture' | |
static mid: string = 'mid' | |
static payId: string = 'PayID' | |
static xid: string = 'XID' | |
static type: string = 'Type' | |
static pcnr: string = 'PCNr' | |
static ccEpiry: string = 'CCExpiry' | |
static ccBrand: string = 'CCBrand' | |
static status: string = 'Status' | |
static description: string = 'Description' | |
static code: string = 'Code' | |
} | |
export class GeoAreaBlowFishKey { | |
static gb: string = 'T...' | |
static de: string = 'B...' | |
} | |
export function redirectToSuccess(queryString: string, geoAreaKey: GeoAreaBlowFishKey, devStageDomain: string) { | |
const responseMapData = new Map<string, string>() | |
responseMapData.set(ParamName.status, 'AUTHORIZED') | |
responseMapData.set(ParamName.description, 'success') | |
responseMapData.set(ParamName.code, '00000000') | |
return getRedirectResult(queryString, geoAreaKey, responseMapData, devStageDomain) | |
} | |
export function redirectToFailure(queryString: string, geoAreaKey: GeoAreaBlowFishKey, devStageDomain: string) { | |
const responseMapData = new Map<string, string>() | |
responseMapData.set(ParamName.status, 'FAILED') | |
responseMapData.set(ParamName.description, 'FAILED') | |
responseMapData.set(ParamName.code, '21200200') | |
return getRedirectResult(queryString, geoAreaKey, responseMapData, devStageDomain) | |
} | |
function getRedirectResult( | |
queryString: string, | |
geoAreaKey: GeoAreaBlowFishKey, | |
responseMapData: Map<string, string>, | |
devStageDomain: string, | |
) { | |
const urlParams = new URLSearchParams(queryString) | |
const dataToEncrypt = getDataToEncrypt(manipulateData( | |
getDataAsMap(decodeData(urlParams.get('Data') ?? 'no_data', geoAreaKey)), urlParams, | |
responseMapData | |
)) | |
const encryptedData = convertDecToHex(encryptData(dataToEncrypt, geoAreaKey)) | |
return `http://dev-stage.mercateo.${devStageDomain}/basket/deucsredirect?Len=${dataToEncrypt.length}&Data=${encryptedData}` | |
} | |
function getDataToEncrypt(manipulatedData: Map<string, string>) { | |
return [...manipulatedData.entries()].map(([key, value]) => `${key}=${value}`).join('&') | |
} | |
function encryptData(encodeStr: string, geoArea: GeoAreaBlowFishKey) { | |
return new Blowfish(geoArea, Blowfish.MODE.ECB, Blowfish.PADDING.SPACES).encode(encodeStr) | |
} | |
function manipulateData( | |
mappedData: Map<string, string>, | |
urlParams: URLSearchParams, | |
responseParams: Map<string, string>, | |
) { | |
[ | |
ParamName.amount, | |
ParamName.currency, | |
ParamName.response, | |
ParamName.orderDesc, | |
ParamName.urlFailure, | |
ParamName.urlSuccess, | |
ParamName.urlNotify, | |
ParamName.capture, | |
].forEach(entry => mappedData.delete(entry)) | |
mappedData.set(ParamName.mid, urlParams.get('MerchantID') ?? 'mid_not_exist') | |
mappedData.set(ParamName.pcnr, '0022589500163111') | |
mappedData.set(ParamName.payId, 'cef0006a2d54467d84174b08704e6314') | |
mappedData.set(ParamName.xid, '69f842ba459c48c188f25c2245d33585') | |
mappedData.set(ParamName.type, 'SSL') | |
mappedData.set(ParamName.ccEpiry, '202912') | |
mappedData.set(ParamName.ccBrand, 'VISA') | |
mappedData.set(ParamName.status, responseParams.get(ParamName.status) ?? 'failure') | |
mappedData.set(ParamName.description, responseParams.get(ParamName.description) ?? 'description') | |
mappedData.set(ParamName.code, responseParams.get(ParamName.code) ?? '321321') | |
return mappedData | |
} | |
function decodeData(hexData: string, geoArea: GeoAreaBlowFishKey) { | |
return new Blowfish(geoArea, Blowfish.MODE.ECB, Blowfish.PADDING.SPACES) | |
.decode(new Uint8Array(convertHexToDec(hexData)).buffer as Uint8Array, Blowfish.TYPE.STRING) | |
} | |
function getDataAsMap(decodedData: string) { | |
return new Map(decodedData.split('&').map(param => param.split('=') as [string, string])) | |
} | |
function convertHexToDec(hex: string) { | |
return hex.match(/.{2}/g)?.map(chunk => parseInt(chunk, 16)) ?? [] | |
} | |
function convertDecToHex(dec: Uint8Array) { | |
return [...dec].map(num => Number(num).toString(16).toUpperCase().padStart(2, '0')).join('') | |
} | |
(function setupRedirectForm() { | |
const hostnameLabel = document.createElement('label') | |
hostnameLabel.textContent = 'Hostname:' | |
hostnameLabel.style.textAlign = 'end' | |
hostnameLabel.setAttribute('for', 'hostname') | |
const hostnameInput = document.createElement('input') | |
hostnameInput.type = 'text' | |
hostnameInput.id = 'hostname' | |
hostnameInput.name = 'hostname' | |
hostnameInput.required = true | |
hostnameInput.value = localStorage.getItem('hostnameInput') ?? 'local.mercateo.co.uk:8081' | |
hostnameInput.addEventListener('change', () => localStorage.setItem('hostnameInput', hostnameInput.value)) | |
const blowfishLabel = document.createElement('label') | |
blowfishLabel.textContent = 'Blowfish Key:' | |
blowfishLabel.style.textAlign = 'end' | |
blowfishLabel.setAttribute('for', 'blowfishKey') | |
const blowfishInput = document.createElement('input') | |
blowfishInput.type = 'text' | |
blowfishInput.id = 'blowfishKey' | |
blowfishInput.name = 'blowfishKey' | |
blowfishInput.required = true | |
blowfishInput.value = localStorage.getItem('blowfishInput') ?? '' | |
blowfishInput.addEventListener('change', () => localStorage.setItem('blowfishInput', blowfishInput.value)) | |
const failureButton = document.createElement('button') | |
failureButton.type = 'button' | |
failureButton.textContent = 'Redirect to Failure' | |
failureButton.onclick = () => window.location.href = redirectToFailure(window.location.search.substring(1), blowfishInput.value, 'co.uk') | |
.replace(/(?<=https?:\/\/)[^/]+/, hostnameInput.value) | |
const successButton = document.createElement('button') | |
successButton.type = 'button' | |
successButton.textContent = 'Redirect to Success' | |
successButton.onclick = () => window.location.href = redirectToSuccess(window.location.search.substring(1), blowfishInput.value, 'co.uk') | |
.replace(/(?<=https?:\/\/)[^/]+/, hostnameInput.value) | |
const buttons = document.createElement('div') | |
buttons.style.gridColumn = '1 / 3' | |
buttons.style.display = 'grid' | |
buttons.style.gap = '10px' | |
buttons.style.gridTemplate = 'auto / 1fr 1fr' | |
buttons.appendChild(failureButton) | |
buttons.appendChild(successButton) | |
const form = document.createElement('form') | |
form.id = 'redirectForm' | |
form.style.display = 'grid' | |
form.style.background = 'whitesmoke' | |
form.style.color = 'grey' | |
form.style.border = '1px solid lightgrey' | |
form.style.gridTemplate = '1fr 1fr 1fr / auto 1fr' | |
form.style.gap = '10px' | |
form.style.padding = '10px' | |
form.style.borderRadius = '3px' | |
form.style.boxShadow = 'rgba(0, 0, 0, 0.35) 0px 5px 15px' | |
form.appendChild(hostnameLabel) | |
form.appendChild(hostnameInput) | |
form.appendChild(blowfishLabel) | |
form.appendChild(blowfishInput) | |
form.appendChild(buttons) | |
const shadowContainer = document.createElement('div') | |
shadowContainer.style.position = 'fixed' | |
shadowContainer.style.top = '10px' | |
shadowContainer.style.left = '50%' | |
shadowContainer.style.transform = 'translate(-50%) perspective(0)' | |
shadowContainer.style.zIndex = '9999' | |
const shadowRoot = shadowContainer.attachShadow({ mode: 'closed' }) | |
const style = document.createElement('style') | |
style.textContent = ` | |
:host * { | |
font-family: sans-serif | |
font-size: 1rem | |
white-space: nowrap | |
}` | |
shadowRoot.appendChild(style) | |
shadowRoot.appendChild(form) | |
document.body.appendChild(shadowContainer) | |
})() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "nodejs-typescript", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.ts", | |
"scripts": { | |
"start": "webpack watch --mode development", | |
"build": "webpack --mode production" | |
}, | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"egoroof-blowfish": "^4.0.1", | |
"esbuild": "^0.18.14", | |
"node-fetch": "^3.3.1", | |
"ts-loader": "^9.4.4", | |
"webpack": "^5.88.2" | |
}, | |
"devDependencies": { | |
"@types/node": "^20.4.2", | |
"webpack-cli": "^5.1.4" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
{ | |
"compilerOptions": { | |
"target": "ESNext", | |
"lib": ["ESNext", "DOM"], | |
"types": ["node", "@types/node"], | |
"strict": true, | |
"moduleResolution": "Node" | |
}, | |
"include": ["*.ts"] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = (_, argv) => ({ | |
devtool: argv.mode !== 'production' && 'inline-source-map', | |
entry: './index.ts', | |
module: { | |
rules: [{ | |
test: /\.ts$/, | |
use: { | |
loader: 'ts-loader', | |
options: { | |
transpileOnly: true, | |
} | |
}, | |
exclude: /node_modules/, | |
}] | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment