From b2ec169dc3ca72f1c32efb605e221c2b8b451098 Mon Sep 17 00:00:00 2001 From: buckE Date: Thu, 2 Apr 2020 22:30:16 +0000 Subject: server-build initial commit; moved plugin to /plugin directory --- LICENSE | 339 -------- README.md | 3 - plugin/LICENSE | 339 ++++++++ plugin/README.md | 3 + .../class-wc-gnutaler-gateway.php | 890 +++++++++++++++++++++ .../src/GNU-taler-payment/functions/functions.php | 224 ++++++ .../GNU-taler-payment/functions/functionsTest.php | 157 ++++ plugin/src/GNU-taler-payment/js/WalletDetection.js | 43 + .../src/GNU-taler-payment/js/taler-wallet-lib.js | 270 +++++++ plugin/src/GNU-taler-payment/readme.txt | 59 ++ .../class-wc-gnutaler-gateway.php | 890 --------------------- src/GNU-taler-payment/functions/functions.php | 224 ------ src/GNU-taler-payment/functions/functionsTest.php | 157 ---- src/GNU-taler-payment/js/WalletDetection.js | 43 - src/GNU-taler-payment/js/taler-wallet-lib.js | 270 ------- src/GNU-taler-payment/readme.txt | 59 -- 16 files changed, 1985 insertions(+), 1985 deletions(-) delete mode 100644 LICENSE delete mode 100644 README.md create mode 100644 plugin/LICENSE create mode 100644 plugin/README.md create mode 100644 plugin/src/GNU-taler-payment/class-wc-gnutaler-gateway.php create mode 100644 plugin/src/GNU-taler-payment/functions/functions.php create mode 100644 plugin/src/GNU-taler-payment/functions/functionsTest.php create mode 100644 plugin/src/GNU-taler-payment/js/WalletDetection.js create mode 100644 plugin/src/GNU-taler-payment/js/taler-wallet-lib.js create mode 100644 plugin/src/GNU-taler-payment/readme.txt delete mode 100644 src/GNU-taler-payment/class-wc-gnutaler-gateway.php delete mode 100644 src/GNU-taler-payment/functions/functions.php delete mode 100644 src/GNU-taler-payment/functions/functionsTest.php delete mode 100644 src/GNU-taler-payment/js/WalletDetection.js delete mode 100644 src/GNU-taler-payment/js/taler-wallet-lib.js delete mode 100644 src/GNU-taler-payment/readme.txt diff --git a/LICENSE b/LICENSE deleted file mode 100644 index d159169..0000000 --- a/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/README.md b/README.md deleted file mode 100644 index f035bfa..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# GNU-Taler-Plugin - -GNU Taler plugin for Wordpress with Woocommerce. diff --git a/plugin/LICENSE b/plugin/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/plugin/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugin/README.md b/plugin/README.md new file mode 100644 index 0000000..f035bfa --- /dev/null +++ b/plugin/README.md @@ -0,0 +1,3 @@ +# GNU-Taler-Plugin + +GNU Taler plugin for Wordpress with Woocommerce. diff --git a/plugin/src/GNU-taler-payment/class-wc-gnutaler-gateway.php b/plugin/src/GNU-taler-payment/class-wc-gnutaler-gateway.php new file mode 100644 index 0000000..0d8100b --- /dev/null +++ b/plugin/src/GNU-taler-payment/class-wc-gnutaler-gateway.php @@ -0,0 +1,890 @@ +. + */ + + +require_once ABSPATH . 'wp-admin/includes/plugin.php'; + +//Exit if accessed directly. +if ( ! defined( 'ABSPATH' ) ) { + exit(); +} + +/* + * This action hook registers our PHP class as a WooCommerce payment gateway + */ + +/** + * Adds the GNU Taler payment method to the other payment gateways. + * + * @param $gateways - Array of all the payment gateways. + * @return array + * @since 0.6.0 + */ + + +function gnutaler_add_gateway_class( $gateways ) { + $gateways[] = 'WC_GNUTaler_Gateway'; + return $gateways; +} + +add_filter( 'woocommerce_payment_gateways', 'gnutaler_add_gateway_class' ); + +/** + * The class itself, please note that it is inside plugins_loaded action hook + */ + +add_action( 'plugins_loaded', 'gnutaler_init_gateway_class' ); + + +function gnutaler_init_gateway_class() +{ + //Check if WooCommerce is active, if not then deactivate and show error message + if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins' ) ), true ) ) { + deactivate_plugins(plugin_basename(__FILE__)); + wp_die("GNU Taler requires WooCommerce plugin to work normally. Please activate it or install it from here.

Back to the WordPress Plugins page."); + } + + /** + * GNU Taler Payment Gateway class. + * + * Handles the payments from the Woocommerce Webshop and sends the transactions to the GNU Taler Backend and the GNU Taler Wallet. + * + * @since 0.6.0 + */ + class WC_GNUTaler_Gateway extends WC_Payment_Gateway + { + /** + * Class constructor + */ + public function __construct() + { + $this->id = 'gnutaler'; // payment gateway plugin ID + $this->icon = ''; // URL of the icon that will be displayed on checkout page near the gateway name + $this->has_fields = false; // There is no need for custom checkout fields, therefore set false + $this->method_title = 'GNU Taler Gateway'; + $this->method_description = 'This plugin enables the payment via the GNU Taler payment system'; // will be displayed on the options page + + // gateways can support refunds, saved payment methods, + $this->supports = array( + 'products', 'refunds', + ); + // Method with all the options fields + $this->init_form_fields(); + + // Load the settings. + $this->init_settings(); + $this->title = $this->get_option( 'title' ); + $this->description = $this->get_option( 'description' ); + $this->enabled = $this->get_option( 'enabled' ); + $this->GNU_Taler_Backend_URL = $this->get_option( 'GNU_Taler_Backend_URL' ); + $this->GNU_Taler_Backend_API_Key = $this->get_option( 'GNU_Taler_Backend_API_Key' ); + $this->Payment_url = $this->get_option( 'Payment_url' ); + $this->Order_text = $this->get_option( 'Order_text' ); + $this->merchant_information = $this->get_option( 'merchant_information' ); + $this->merchant_name = $this->get_option( 'merchant_name' ); + + //Here we add the Javascript files to the webserver + add_action( 'woocommerce_before_checkout_form', static function () { + wp_enqueue_script( 'taler-wallet-lib', plugin_dir_url( __FILE__ ) . 'js/taler-wallet-lib.js' ); + } ); + add_action( 'woocommerce_before_checkout_form', static function () { + wp_enqueue_script( 'WalletDetection', plugin_dir_url( __FILE__ ) . 'js/WalletDetection.js' ); + } ); + + add_action( 'woocommerce_api_'. strtolower( get_class($this) ), array( $this, 'callback_handler' ) ); + + // This action hook saves the settings + add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); + } + + /** + * Plugin options + */ + public function init_form_fields() + { + $this->form_fields = array( + 'enabled' => array( + 'title' => 'Enable/Disable', + 'label' => 'Enable GNU Taler Gateway', + 'type' => 'checkbox', + 'description' => '', + 'default' => 'no', + ), + 'title' => array( + 'title' => 'Title', + 'type' => 'text', + 'description' => 'What name should the payment method have when the costumer can choose how to pay .', + 'default' => 'GNU Taler', + 'desc_tip' => true, + ), + 'description' => array( + 'title' => 'Description', + 'type' => 'textarea', + 'description' => 'This controls the description which the customer sees during checkout.', + 'default' => 'Pay with the new Payment method GNU Taler.', + ), + 'GNU_Taler_Backend_URL' => array( + 'title' => 'GNU Taler Backend URL', + 'type' => 'text', + 'description' => 'Set the URL of the GNU Taler Backend.', + 'default' => 'https://backend.demo.taler.net', + ), + 'GNU_Taler_Backend_API_Key' => array( + 'title' => 'GNU Taler Backend API Key', + 'type' => 'text', + 'description' => 'Set the API-key for the Authorization with the GNU Taler Backend.', + 'default' => 'ApiKey sandbox', + ), + 'Payment_url' => array( + 'title' => 'GNU Taler Payment url', + 'type' => 'text', + 'description' => 'Set the URL for your GNU Taler Wallet where the Coins of the costumer will be send to.', + 'default' => '', + ), + 'Order_text' => array( + 'title' => 'Summarytext of the order', + 'type' => 'text', + 'description' => 'Set the text the customer should see as a summary when he confirms the payment.', + 'default' => 'Order', + ), + 'merchant_information' => array( + 'title' => 'Enable/Disable', + 'label' => 'Enable sending your merchant information to the GNU Taler Backend', + 'type' => 'checkbox', + 'description' => 'Do you want to send your merchant information to the GNU Taler Backend via the transaction', + 'default' => 'yes', + ), + 'merchant_name' => array( + 'title' => 'Name of the webshop', + 'type' => 'text', + 'description' => 'Set the name of the webshop that the customer will see during the payment transaction.', + 'default' => '', + ), + ); + } + + /** + * Callback is called, when the payment succeeds. + * + * Is called on successful payment process. + * User is then being forwarded to the order details page. + * + * @since 0.6.0 + */ + + public function callback_handler(): void + { + + if ( is_user_logged_in() ) + { + $user_id = WC()->customer->get_id(); + } + else + { + $user_id = 'Guest'; + } + + if ( isset( $_GET['order_id'] ) ) { + + //Gets the order id from the fulfillment url + $order_id_backend = $_GET['order_id']; + $order_id_array = explode( '-', $order_id_backend ); + $order_id_name = $order_id_array[0]; + $order_id = $order_id_array[1]; + $wc_order = wc_get_order( $order_id ); + + //Completes the order + $wc_order->payment_complete(); + + //Empties the shopping cart + WC()->cart->empty_cart(); + + $this->add_log_entry('transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Payment succeeded and the user was forwarded to the order confirmed page' ); + + wp_redirect( get_home_url() . '/checkout/order-received/' . $order_id . '/?key=' . $order_id_name ); + exit; + } + wp_redirect(get_home_url() . '/my-account/orders/'); + exit; + } + + /** + * Sends a request to a url via HTTP. + * + * Sends a request to a GNU Taler Backend over HTTP and returns the result. + * The request can be sent as POST, GET, PUT or another method. + * + * @param $method - POST, GET, PUT or another method. + * @param $backend_url - URL to the GNU Taler Backend. + * @param $body - The content of the request. + * @param $purpose - What return value is to be expected. + * @return array The return array will either have the successful return value or a detailed error message. + * @since 0.6.0 + * + */ + public function call_api( $method, $backend_url, $body, $purpose ): array + { + //create_url + $url = $this->create_api_url( $backend_url, $purpose, $body ); + + //Initialize curl request + $curl = $this->curl_init( $method, $body, $url ); + + // EXECUTE: + $result = curl_exec( $curl ); + + //HTTP Status Error handling + $message_array = $this->curl_error_handling( $curl, $result ); + curl_close( $curl ); + return $message_array; + } + + /** + * Checks if the return http code is a success and if not what kind of error status it is. + * + * If the request was successful an array will be returned with the boolean value true, the http code and the result of the response. + * If the request failed an array will be returned with the boolean value false, the http code and a detailed error message. + * + * @param $curl - Created curl request for error handling. + * @param $result - The response from the backend, that will be returned if the request was successful + * @return array - Array with a boolean, a http code and a message will be returned + * @since 0.6.0 + * + */ + public function curl_error_handling( $curl, $result ): array + { + $http_code = curl_getinfo( $curl, CURLINFO_HTTP_CODE ); + if ( curl_error( $curl ) ) { + $error_msg = curl_error( $curl ); + } + curl_close( $curl ); + if ( isset( $error_msg ) ) { + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => $error_msg, + ); + } + if ( $http_code === 200 ) { + return array( + 'result' => true, + 'http_code' => $http_code, + 'message' => $result, + ); + } + if ( preg_match( '(4[0-9]{2})', $http_code ) ) { + switch ($http_code) { + case 400: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'request', + ); + break; + case 401: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Unauthorized', + ); + break; + case 403: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Forbidden', + ); + break; + case 404: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Page Not Found', + ); + break; + default: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => '4xx Client Error', + ); + break; + } + } elseif ( preg_match( '(5[0-9]{2})', $http_code ) ) { + switch ( $http_code ) { + case '500': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Internal Server Error', + ); + break; + case '502': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Bad Gateway', + ); + break; + case '503': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Service Unavailable', + ); + break; + case '504': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Gateway Timeout', + ); + break; + default: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => '5xx Client Error', + ); + break; + } + } else { + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'http status error', + ); + } + } + + /** + * Initialises the curl request and sets some necessary options depending on the method. + * + * Depending of the method chosen different options for the curl request will be set. + * Not depending on the method the settings for a return value, Authorization and Content-Type are being set. + * + * @param $method - POST, GET, PUT or another method. + * @param $body - Content of the request. + * @param $url - URL where the request will be send + * @return false|resource - Either the configured curl request will be returned or false if an error appears. + * @since 0.6.0 + */ + public function curl_init( $method, $body, $url ) + { + $curl = curl_init(); + $apikey = $this->get_option( 'GNU_Taler_Backend_API_Key' ); + + switch ( $method ) { + case 'POST': + curl_setopt( $curl, CURLOPT_POST, 1 ); + if ( $body ) { + curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); + } + break; + case 'PUT': + curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, 'PUT' ); + if ( $body ) { + curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); + } + break; + case 'GET': + curl_setopt( $curl, CURLOPT_VERBOSE, 1 ); + break; + default: + curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $method ); + break; + } + + // OPTIONS: + curl_setopt( $curl, CURLOPT_URL, $url ); + curl_setopt( $curl, CURLOPT_HTTPHEADER, array( + 'Authorization: ' . $apikey, + 'Content-Type: application/json', + ) ); + curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 ); + curl_setopt ($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ); + + return $curl; + } + + /** + * Creates the final url depending on the purpose. + * + * @param $url - URL where the request will be send. + * @param $purpose - What will be added to the url. + * @param $body - Content of the request. + * @return string - return the final url. + * @since 0.6.0 + */ + public function create_api_url ($url, $purpose, $body ): string + { + if ( $purpose === 'create_order' ) { + return $url . '/order'; + } + if ( $purpose === 'confirm_payment' ) { + return $url . '/check-payment?order_id=' . $body; + } + if ( $purpose === 'create_refund' ) { + return $url . '/refund'; + } + return $url; + } + + /** + * Verifying if the url to the backend given in the plugin options is valid or not. + * + * @param $url - URL to the backend + * @return bool - Returns if valid or not. + * @since 0.6.0 + */ + public function verify_backend_url( $url ): bool + { + $result = $this->call_api( 'GET', $url, '', '' ); + if ( $result['result'] ){ + return true; + } + return false; + } + + /** + * Processes the payment after the checkout + * + * If the payment process finished successfully the user is being redirected to its GNU Taler Wallet. + * If an error occurs it returns void and throws an error. + * + * @param $order_id - ID of the order to get the Order from the WooCommerce Webshop + * @return array|void - Array with result => success and redirection url otherwise it returns void. + * @since 0.6.0 + */ + public function process_payment( $order_id ) + { + // we need it to get any order detailes + $wc_order = wc_get_order( $order_id ); + + if ( is_user_logged_in() ) + { + $user_id = WC()->customer->get_id(); + } + else + { + $user_id = 'Guest'; + $this->add_log_entry( 'transaction', 'The customer started a transaction without login, therefore the userid is unknown.' ); + } + + // Gets the url of the backend from the WooCommerce Settings + $backend_url = $this->get_option( 'GNU_Taler_Backend_URL', 1 ); + + //Log entry that the customer started the payment process + $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - User started the payment process.' ); + + if ( ! $this->verify_backend_url( $backend_url ) ) { + wc_add_notice( 'Something went wrong please contact the system administrator of the webshop and send the following error: GNU Taler backend url invalid', 'error' ); + $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Checkout process failed - Invalid backend url.' ); + return; + } + $order_json = $this->convert_to_checkout_json( $order_id ); + + $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Transaction request send to GNU Taler backend' ); + $order_request = $this->send_order_request( $backend_url, $order_json, $user_id, $order_id ); + + if ( $order_request['boolean'] ) { + + //Returns that the payment process finished successfully and redirects the costumer to confirm the payment via GNU Taler + $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Customer is being redirected to the payment confirmation site' ); + return array( + 'result' => 'success', + // 'redirect' => '', + 'redirect' => $order_request['url'], + ); + } + wc_add_notice( 'There seems to be a problem with the payment process, please try again or send the following message to a system administrator: ' . $order_request['http_code'] . ' - ' . $order_request['error_message'] ); + $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the payment process - ' . $order_request['http_code'] . ' - ' . $order_request['error_message'] ); + $wc_order->set_status( 'cancelled' ); + return; + } + + /** + * Sends the transaction to the GNU Taler Backend + * + * If the payment process finishes successfully it returns an array with the redirection url to the GNU Taler Wallet and a boolean value for error handling. + * If an error occurs it returns an array with a boolean value for error handling, the http status code and an error message. + * + * @param $backend_url - URL where the request will be sent. + * @param $json - JSON array with the data of the order for the backend. + * @param $user_id - User id for logging. + * @param $order_id - Order id for logging. + * @return array|void - Array with boolean true|false, url or error message with http status code. + * @since 0.6.0 + */ + public function send_order_request( $backend_url, $json, $user_id, $order_id ): array + { + // Send the POST-Request via CURL to the GNU Taler Backend + $order_confirmation = $this->call_api( 'POST', $backend_url, json_encode($json, JSON_UNESCAPED_SLASHES), 'create_order' ); + + $order_message = $order_confirmation['message']; + $order_boolean = $order_confirmation['result']; + + if ( $order_boolean ) { + $order_confirmation_id = explode( '"', $order_message )[3]; + + // Send the final confirmation to execute the payment transaction to the GNU Taler Backend + $payment_confirmation = $this->call_api( 'GET', $backend_url, $order_confirmation_id, 'confirm_payment' ); + $payment_message = $payment_confirmation['message']; + $payment_boolean = $order_confirmation['result']; + + if ( $payment_boolean ) { + + //Here we check what kind of http code came back from the backend + $payment_confirmation_url = explode( '"', $payment_message )[3]; + $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Successfully received redirect url to wallet from GNU Taler Backend' ); + return array( + 'boolean' => true, + 'url' => $payment_confirmation_url, + ); + } + $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the second request to the GNU Taler backend - ' . $payment_confirmation['http_code'] . ' - ' . $payment_message ); + return array( + 'boolean' => false, + 'http_code' => $payment_confirmation['http_code'], + 'error_message' => $payment_message, + ); + } + $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the first request to the GNU Taler backend - ' . $order_confirmation['http_code'] . ' - ' . $order_message ); + return array( + 'boolean' => false, + 'http_code' => $order_confirmation['http_code'], + 'error_message' => $order_message, + ); + } + + /** + * Converts the order into a JSON format that can be send to the GNU Taler Backend. + * + * + * The amount of the refund request can, at the moment, only be refunded in the currency 'KUDOS', which is the currency that the GNU Taler Payment system uses. + * This will change in the future. + * + * @param $order_id - To get the order from the WooCommerce Webshop + * @return array - return the JSON Format. + * @since 0.6.0 + */ + public function convert_to_checkout_json( $order_id ): array + { + $wc_order = wc_get_order( $order_id ); + $wc_order_total_amount = $wc_order->get_total(); + $wc_order_currency = $wc_order->get_currency(); + $wc_cart = WC()->cart->get_cart(); + $wc_order_id = $wc_order->get_order_key() . '-' . $wc_order->get_order_number(); + $merchant_option = $this->get_option( 'merchant_information' ); + + $wc_order_products_array = $this->mutate_products_to_json_format( $wc_cart, $wc_order_currency, $wc_order); + + $wc_order_merchant = $this->mutate_merchant_information_to_json_format( $merchant_option ); + + $order_json = array( + 'order' => array( + 'amount' => $wc_order_currency . ':' . $wc_order_total_amount, + 'summary' => 'Order from the merchant ' . $this->get_option('merchant_name') . ': ', + 'fulfillment_url' => get_home_url() . '/wc-api/wc_gnutaler_gateway', + //'payment_url' => $this->get_option( 'Payment_url' ), + 'order_id' => $wc_order_id, + 'merchant' => $wc_order_merchant, + 'products' => $wc_order_products_array, + ), + ); + return $order_json; + } + + /** + * Mutates the products in the cart into a format which can be included in a JSON file. + * + * @param $wc_cart - The content of the WooCommerce Cart. + * @param $wc_order_currency - The currency the WooCommerce Webshop uses. + * @return array - Returns an array of products. + * @since 0.6.0 + */ + public function mutate_products_to_json_format( $wc_cart, $wc_order_currency, $wc_order ): array + { + $wc_order_products_array = array(); + foreach ( $wc_cart as $product ) { + $wc_order_products_array[] = array( + 'description' => 'Order of product: ' . $product['data']->get_title(), + 'quantity' => $product['quantity'], + 'price' => $wc_order_currency . ':' . $product['data']->get_price(), + 'product_id' => $product['data']->get_id(), + 'delivery_location' => $this->mutate_shipping_information_to_json_format($wc_order), + ); + } + return $wc_order_products_array; + } + + /** + * Mutates the merchant information of the webshop into a format which can be included in a JSON file. + * + * @param $merchant_option - If the webshop owner allows to send the backend their information + * @return array - Returns an array of merchant information's. + * @since 0.6.0 + */ + public function mutate_merchant_information_to_json_format( $merchant_option ): array + { + $whitechar_encounter = false; + $store_address_street = ''; + $store_address_streetNr = ''; + + // When the option is enabled the informations of the merchant will be included in the transaction + if ( $merchant_option === 'yes' ) { + // The country/state + $store_raw_country = get_option( 'woocommerce_default_country' ); + $split_country = explode( ':', $store_raw_country ); + + // Country and state separated: + $store_country = $split_country[0]; + $store_state = $split_country[1]; + + //Streetname and number + $store_address = get_option( 'woocommerce_store_address' ); + $store_address_inverted = strrev( $store_address ); + $store_address_array = str_split( $store_address_inverted ); + + //Split the address into street and street number + foreach ( $store_address_array as $char ) { + if ( ! $whitechar_encounter ) { + $store_address_streetNr .= $char; + } elseif ( ctype_space( $char ) ) { + $whitechar_encounter = true; + } else { + $store_address_street .= $char; + } + } + $wc_order_merchant_location = array( + 'country' => $store_country, + 'state' => $store_state, + 'city' => WC()->countries->get_base_city(), + 'ZIP code' => WC()->countries->get_base_postcode(), + 'street' => strrev( $store_address_street ), + 'street number' => strrev( $store_address_streetNr ), + ); + return array( + 'address' => $wc_order_merchant_location, + 'name' => $this->get_option( 'merchant_name' ), + ); + } + return array(); + } + + /** + * Processes the refund transaction if requested by the system administrator of the webshop + * + * If the refund request is finished successfully it returns an refund url, which can be send to the customer to finish the refund transaction. + * If an error it will throw a WP_Error message and inform the system administrator. + * + * @param $wc_order + * @return array + * @since 0.6.0 + */ + public function mutate_shipping_information_to_json_format($wc_order): array + { + $whitechar_encounter = false; + $shipping_address_street = ''; + $shipping_address_streetNr = ''; + + $store_address = $wc_order->get_shipping_address_1(); + $store_address_inverted = strrev( $store_address ); + $store_address_array = str_split( $store_address_inverted ); + + //Split the address into street and street number + foreach ( $store_address_array as $char ) { + if ( ! $whitechar_encounter ) { + $shipping_address_street .= $char; + } elseif ( ctype_space( $char ) ) { + $whitechar_encounter = true; + } else { + $shipping_address_street .= $char; + } + } + + return array( + 'country' => $wc_order->get_shipping_country(), + 'state' => $wc_order->get_shipping_state(), + 'city' => $wc_order->get_shipping_city(), + 'ZIP code' => $wc_order->get_shipping_postcode(), + 'street' => $shipping_address_street, + 'street number' => $shipping_address_streetNr, + ); + } + + /** + * Processes the refund transaction if requested by the system administrator of the webshop + * + * If the refund request is finished successfully it returns an refund url, which can be send to the customer to finish the refund transaction. + * If an error it will throw a WP_Error message and inform the system administrator. + * + * @param $order_id - Order id for logging. + * @param null $amount - Amount that is requested to be refunded. + * @param string $reason - Reason for the refund request. + * @return bool|WP_Error - Returns true or throws an WP_Error message in case of error. + * @since 0.6.0 + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) + { + $wc_order = wc_get_order( $order_id ); + $refund_json = $this->convert_refund_to_json( $wc_order, $amount, $reason ); + + $user_id = wc_get_order($order_id)->get_customer_id(); + if ( $user_id === 0 ){ + $user_id = 'Guest'; + } + + $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Refund process of order: ' . $order_id . ' started with the refunded amount: ' . $amount . ' ' . $wc_order->get_currency() . ' and the reason: ' . $reason ); + + // Gets the url of the backend from the WooCommerce Settings + $backend_url = $this->get_option( 'GNU_Taler_Backend_URL' ); + + //Get the current status of the order + $wc_order_status = $wc_order->get_status(); + + //Checks if current status is already set as paid + if ( $wc_order_status === 'processing' || $wc_order_status === 'on hold' || $wc_order_status === 'completed' ) { + + $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Refund request sent to the GNU Taler Backend' ); + $refund_request = $this->send_refund_request( $backend_url, $refund_json ); + + if( $refund_request['boolean'] ) { + //Set the status as refunded and post the link to confirm the refund process via the GNU Taler payment method + $wc_order->update_status( 'refunded' ); + $wc_order->add_order_note( 'The refund process finished successfully, please send the following url to the customer via an email to confirm the refund transaction.' ); + $wc_order->add_order_note( $refund_request['url'] ); + $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Successfully received refund redirect url from GNU Taler backend, customer can now refund the given amount.' ); + return true; + } + $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the refund process - ' . $refund_request['http_code'] . ' - ' . $refund_request['error_message'] ); + return new WP_Error( 'error', 'An error occurred during the refund process, please try again or send the following message to your system administrator: ' . $refund_request['http_code'] . ' - ' . $refund_request['error_message'] ); + } + $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - The status of the order does not allow a refund' ); + return new WP_Error( 'error', 'The status of the order does not allow for a refund.' ); + } + + /** + * Sends the refund transaction to the GNU Taler Backend + * + * If the refund process finishes successfully it returns a boolean value true and sends the system administrator the refund url for the customer. + * If an error occurs it returns a WP_Error which will be displayed . + * + * @param $backend_url - URL where the request will be sent. + * @param $json - JSON array with the data of the refund request for the backend. + * @return array|void - Array with boolean true|false, url or error message with http status code. + * @since 0.6.0 + */ + public function send_refund_request( $backend_url, $json ): array + { + $refund_url = ''; + $refund_confirmation = $this->call_api( 'POST', $backend_url, json_encode($json, JSON_UNESCAPED_SLASHES), 'create_refund' ); + + $message = $refund_confirmation['message']; + $refund_boolean = $refund_confirmation['result']; + + if ($refund_boolean) { + //Here we check what kind of http code came back from the backend + $refund_confirmation_array = explode(',', $message); + foreach ( $refund_confirmation_array as $value ) { + + //Looping through the return value and checking if "refund_redirect_url" can be found + if ( strpos( $value, 'refund_redirect_url' ) ) { + $refund_url = explode( '"', $value )[3]; + } + } + return array( + 'boolean' => true, + 'url' => $refund_url, + ); + } + return array( + 'boolean' => false, + 'url' => $refund_url, + 'http_code' => $refund_confirmation['http_code'], + 'error_message' => $refund_confirmation['message'], + ); + } + + /** + * Converts the information of the refund request into a JSON format that can be send to the GNU Taler Backend. + * + * The amount of the refund request can, at the moment, only be refunded in the currency 'KUDOS', which is the currency that the GNU Taler Payment system uses. + * This will change in the future. + * + * @param $order - Order where the refund request originated from. + * @param $amount - Amount to be refunded. + * @param $reason - Reason of refund. + * @return array - returns the JSON Format. + * @since 0.6.0 + */ + public function convert_refund_to_json( $order, $amount, $reason ): array + { + return array( + 'order_id' => $order->get_order_key() . '-' . $order->get_order_number(), + 'refund' => $order->get_currency() . ':' . $amount, + 'instance' => 'default', + 'reason' => $reason, + ); + } + + /** + * + * Creates or opens the log files and writes a log entry. + * + * @param $type - What kind of log it is. + * @param $message - What the message of the log entry is. + * @return void - Returns void. + * @since 0.6.0 + */ + public function add_log_entry( $type, $message ): void + { + $file = null; + $timestamp = date( 'r' ); + if ( $type === 'error' ) { + $file = fopen( __DIR__ . '/log/GNUTaler_Error.log', 'ab' ); + } + elseif ( $type === 'transaction' ) { + $file = fopen( __DIR__ . '/log/GNUTaler_User_Transactions.log', 'ab' ); + } + else + { + $file = fopen( __DIR__ . '/log/GNUTaler_' . $type . '.log', 'ab' ); + } + if ( $file !== null ){ + fwrite( $file, $timestamp . ' - ' . $message . PHP_EOL ); + fclose( $file ); + } + } + } +} diff --git a/plugin/src/GNU-taler-payment/functions/functions.php b/plugin/src/GNU-taler-payment/functions/functions.php new file mode 100644 index 0000000..1a8dd6f --- /dev/null +++ b/plugin/src/GNU-taler-payment/functions/functions.php @@ -0,0 +1,224 @@ + false, + 'http_code' => $http_code, + 'message' => $error_msg, + ); + } + if ( $http_code === 200 ) { + return array( + 'result' => true, + 'http_code' => $http_code, + 'message' => $result, + ); + } + if ( preg_match( '(4[0-9]{2})', $http_code ) ) { + switch ($http_code) { + case 400: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Bad request', + ); + break; + case 401: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Unauthorized', + ); + break; + case 403: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Forbidden', + ); + break; + case 404: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Page Not Found', + ); + break; + default: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => '4xx Client Error', + ); + break; + } + } elseif ( preg_match( '(5[0-9]{2})', $http_code ) ) { + switch ( $http_code ) { + case '500': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Internal Server Error', + ); + break; + case '502': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Bad Gateway', + ); + break; + case '503': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Service Unavailable', + ); + break; + case '504': + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'Gateway Timeout', + ); + break; + default: + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => '5xx Client Error', + ); + break; + } + } else { + return array( + 'result' => false, + 'http_code' => $http_code, + 'message' => 'http status error', + ); + } +} + +/** + * Initialises the curl request and sets some necessary options depending on the method. + * + * Depending of the method chosen different options for the curl request will be set. + * Not depending on the method the settings for a return value, Authorization and Content-Type are being set. + * + * @param $method - POST, GET, PUT or another method. + * @param $body - Content of the request. + * @param $url - URL where the request will be send + * @param $api_key + * @return false|resource - Either the configured curl request will be returned or false if an error appears. + * @since 0.6.0 + */ +function curl_init_request( $method, $body, $url, $api_key ) +{ + $curl = curl_init(); + + switch ( $method ) { + case 'POST': + curl_setopt( $curl, CURLOPT_POST, 1 ); + if ( $body ) { + curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); + } + break; + case 'PUT': + curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, 'PUT' ); + if ( $body ) { + curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); + } + break; + case 'GET': + curl_setopt( $curl, CURLOPT_VERBOSE, 1 ); + break; + default: + curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $method ); + break; + } + + // OPTIONS: + curl_setopt( $curl, CURLOPT_URL, $url ); + curl_setopt( $curl, CURLOPT_HTTPHEADER, array( + 'Authorization: ' . $api_key, + 'Content-Type: application/json', + ) ); + curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 ); + curl_setopt ($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ); + + return $curl; +} + +/** + * Creates the final url depending on the purpose. + * + * @param $url - URL where the request will be send. + * @param $purpose - What will be added to the url. + * @param $body - Content of the request. + * @return string - return the final url. + * @since 0.6.0 + */ +function create_api_url ($url, $purpose, $body ): string +{ + if ( $purpose === 'create_order' ) { + return $url . '/order'; + } + if ( $purpose === 'confirm_payment' ) { + return $url . '/check-payment?order_id=' . $body; + } + if ( $purpose === 'create_refund' ) { + return $url . '/refund'; + } + return $url; +} + + diff --git a/plugin/src/GNU-taler-payment/functions/functionsTest.php b/plugin/src/GNU-taler-payment/functions/functionsTest.php new file mode 100644 index 0000000..a18dab2 --- /dev/null +++ b/plugin/src/GNU-taler-payment/functions/functionsTest.php @@ -0,0 +1,157 @@ + array( + 'amount' => 'KUDOS:0.1', + 'fulfillment_url' => 'http://gnutaler.hofmd.ch', + 'summary' => 'Test_order', + 'order_id' => $wc_order_test_request, + ) + ); + $purpose_1 = 'create_order'; + + $body_request_2 = $wc_order_test_request; + $purpose_2 = 'confirm_payment'; + + $result_create_order = call_api( $method_post, $backend_url, json_encode($body_request_1), $purpose_1, $api_key ); + $result_confirm_payment = call_api( $method_get, $backend_url, $body_request_2, $purpose_2, $api_key ); + $result_verify_backend_url = call_api( $method_get, $backend_url, '', '', $api_key ); + $result_method_different = call_api( $method_different, $backend_url, json_encode($body_request_1), $purpose_1, $api_key ); + + Assert::assertTrue($result_create_order['result']); + Assert::assertEquals($wc_order_test_request, json_decode($result_create_order['message'], true)['order_id']); + Assert::assertTrue($result_confirm_payment['result']); + Assert::assertEquals(false, json_decode($result_confirm_payment['message'], true)['paid']); + Assert::assertTrue($result_verify_backend_url['result']); + Assert::assertEquals('Hello, I\'m a merchant\'s Taler backend. This HTTP server is not for humans.', trim($result_verify_backend_url['message'])); + Assert::assertFalse($result_method_different['result']); + Assert::assertEquals('Bad request', $result_method_different['message']); + } + + + /** + * Tests the create_api_url function + */ + public function test_create_api_url(): void + { + $url_test = 'https://backend.demo.taler.net'; + $wc_test_order = ''; + try { + $wc_test_order = 'wc_test_' . random_int(0, 1000); + } catch (Exception $e) { + } + $purpose_create_order = 'create_order'; + $purpose_confirm_payment = 'confirm_payment'; + $purpose_create_refund = 'create_refund'; + + $create_order_url = create_api_url($url_test, $purpose_create_order, ''); + $confirm_payment_url = create_api_url($url_test, $purpose_confirm_payment, $wc_test_order); + $create_refund_url = create_api_url($url_test, $purpose_create_refund, ''); + + Assert::assertEquals('https://backend.demo.taler.net/order', $create_order_url); + Assert::assertEquals('https://backend.demo.taler.net/check-payment?order_id=' . $wc_test_order, $confirm_payment_url); + Assert::assertEquals('https://backend.demo.taler.net/refund', $create_refund_url); + } + + /** + * Tests the curl_error_handling function with the http status code 200 + */ + public function test_curl_error_handling_code_200(): void + { + $api_key = 'ApiKey sandbox'; + $test_url = 'https://backend.demo.taler.net'; + + $curl_error_message_array = call_api('GET', $test_url, '', '', $api_key); + + Assert::assertTrue($curl_error_message_array['result']); + Assert::assertEquals(200, $curl_error_message_array['http_code']); + } + + /** + * Tests the curl_error_handling function with the http status code 400 + */ + public function test_curl_error_handling_code_400(): void + { + $api_key = 'ApiKey sandbox'; + $api_key_wrong = 'ApiKey ____***££££èèè'; + $test_url = 'https://backend.demo.taler.net'; + $test_url_wrong = 'https://backend.demo.taler.net/test_if_this_exits'; + $body = json_encode(array( + 'order' => array( + 'wrong_field' => 'Wrong value', + ) + )); + + $curl_error_message_array_400 = call_api('POST', $test_url, $body, 'create_order', $api_key); + $curl_error_message_array_401 = call_api('GET', $test_url, '', '', $api_key_wrong); + $curl_error_message_array_403 = call_api('GET', 'https://httpstat.us/403', '', '', ''); + $curl_error_message_array_404 = call_api('GET', $test_url_wrong, '', '', $api_key); + + Assert::assertFalse($curl_error_message_array_400['result']); + Assert::assertEquals(400, $curl_error_message_array_400['http_code']); + Assert::assertFalse($curl_error_message_array_401['result']); + Assert::assertEquals(401, $curl_error_message_array_401['http_code']); + Assert::assertFalse($curl_error_message_array_403['result']); + Assert::assertEquals(403, $curl_error_message_array_403['http_code']); + Assert::assertFalse($curl_error_message_array_404['result']); + Assert::assertEquals(404, $curl_error_message_array_404['http_code']); + + } + + + /** + * Tests the curl_error_handling function with the http status code 500 + */ + public function test_curl_error_handling_code_500(): void + { + $api_key = 'ApiKey sandbox'; + $test_url = 'https://backend.demo.taler.net'; + $test_url_500 = 'https://httpstat.us/500'; + $test_url_502 = 'https://httpstat.us/502'; + $test_url_503 = 'https://httpstat.us/503'; + $test_url_504 = 'https://httpstat.us/504'; + + $curl_error_message_array_500 = call_api('GET', $test_url_500, '', '', $api_key); + $curl_error_message_array_502 = call_api('GET', $test_url_502, '', '', $api_key); + $curl_error_message_array_503 = call_api('GET', $test_url_503, '', '', $api_key); + $curl_error_message_array_504 = call_api('GET', $test_url_504, '', '', $api_key); + + Assert::assertFalse($curl_error_message_array_500['result']); + Assert::assertEquals(500, $curl_error_message_array_500['http_code']); + Assert::assertFalse($curl_error_message_array_502['result']); + Assert::assertEquals(502, $curl_error_message_array_502['http_code']); + Assert::assertFalse($curl_error_message_array_503['result']); + Assert::assertEquals(503, $curl_error_message_array_503['http_code']); + Assert::assertFalse($curl_error_message_array_504['result']); + Assert::assertEquals(504, $curl_error_message_array_504['http_code']); + + } + +} diff --git a/plugin/src/GNU-taler-payment/js/WalletDetection.js b/plugin/src/GNU-taler-payment/js/WalletDetection.js new file mode 100644 index 0000000..d2b1df5 --- /dev/null +++ b/plugin/src/GNU-taler-payment/js/WalletDetection.js @@ -0,0 +1,43 @@ +/** + * Wallet detection script + * Detects which browser the user is using and if the GNU Taler wallet is installed + * If the wallet isn't detected or the customer uses a browser which isn't supported, then it removes the GNU Taler payment method from the possibilities. + * + * Currently only the Browser detection is working and the wallet detection isn't + * The reason is, that we couldn't figure out how to detect the wallet with the given functions of the taler-wallet-lib.js + */ + +function detectWallet() { + + sUsrAg = navigator.userAgent; + + if ((sUsrAg.indexOf("Firefox") > -1) || (sUsrAg.indexOf("Opera") > -1 || sUsrAg.indexOf("OPR") > -1) || (sUsrAg.indexOf("Chrome") > -1)) { + //Mozilla Firefox, Opera or Google Chrome + taler.onAbsent(() => { + //Does nothing + }); + } else if ((sUsrAg.indexOf("Trident") > -1) || (sUsrAg.indexOf("Edge") > -1) || (sUsrAg.indexOf("Safari") > -1)) { + //Microsoft Internet Explorer, Microsoft edge or Apple Safari + removePaymentMethod(); + } else { + //Unknown Browser + removePaymentMethod(); + } +} + +function removePaymentMethod() { + var observer = new MutationObserver(function (mutations, observer) { + mutations.forEach(() => { + document.getElementsByClassName("wc_payment_method payment_method_gnutaler").item(0).style.display = 'none'; + }); + }); + + // define what element should be observed by the observer + // and what types of mutations trigger the callback + observer.observe(document, { + subtree: true, + attributes: true + }); +} + +detectWallet(); \ No newline at end of file diff --git a/plugin/src/GNU-taler-payment/js/taler-wallet-lib.js b/plugin/src/GNU-taler-payment/js/taler-wallet-lib.js new file mode 100644 index 0000000..8b1812a --- /dev/null +++ b/plugin/src/GNU-taler-payment/js/taler-wallet-lib.js @@ -0,0 +1,270 @@ +/* + @source https://www.git.taler.net/?p=web-common.git;a=blob_plain;f=taler-wallet-lib.ts;hb=HEAD + @license magnet:?xt=urn:btih:5de60da917303dbfad4f93fb1b985ced5a89eac2&dn=lgpl-2.1.txt LGPL v21 + + @licstart The following is the entire license notice for the + JavaScript code in this page. + + Copyright (C) 2015, 2016 INRIA + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + Lesser General Public License (GNU LGPL) as published by the Free Software + Foundation, either version 2.1 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU LGPL for more details. + + As additional permission under GNU LGPL version 2.1 section 7, you + may distribute non-source (e.g., minimized or compacted) forms of + that code without the copy of the GNU LGPL normally required by + section 4, provided you include this license notice and a URL + through which recipients can access the Corresponding Source. + + @licend The above is the entire license notice + for the JavaScript code in this page. + + @author Marcello Stanisci + @author Florian Dold +*/ + +var taler; +(function (taler) { + "use strict"; + var logVerbose = false; + try { + logVerbose = !!localStorage.getItem("taler-log-verbose"); + } + catch (e) { + // can't read from local storage + } + var presentHandlers = []; + var absentHandlers = []; + // Are we running as the content script of an + // extension (and not just from a normal page)? + var runningInExtension = false; + var callSeqId = 1; + var installed = false; + var probeExecuted = false; + var pageLoaded = false; + var errorHandler = undefined; + function onError(handler) { + if (errorHandler) { + console.warn("Overriding error handler"); + } + errorHandler = handler; + } + taler.onError = onError; + /** + * Error handler for things that go wrong in the merchant + * frontend browser code. + */ + function raise_error(reason, detail) { + if (errorHandler) { + errorHandler(reason, detail); + return; + } + alert("Failure: " + reason + ". No error handler installed. Open the developer console for more information."); + console.error(reason, detail); + console.warn("No custom error handler set."); + } + function callWallet(funcName, args, onResult) { + var detail = JSON.parse(JSON.stringify(args || {})); + var callId = callSeqId++; + detail.callId = callId; + var onTimeout = function () { + console.warn("timeout for invocation of " + funcName); + }; + var timeoutHandle = setTimeout(onTimeout, 1000); + var handler = function (evt) { + if (evt.detail.callId !== callId) { + return; + } + if (onResult) { + onResult(evt.detail); + } + clearTimeout(timeoutHandle); + document.removeEventListener(funcName + "-result", handler); + }; + document.addEventListener(funcName + "-result", handler); + var evt = new CustomEvent(funcName, { detail: detail }); + document.dispatchEvent(evt); + } + /** + * Confirm that a reserve was created. + * + * Used by tightly integrated bank portals. + */ + function confirmReserve(reservePub) { + if (!installed) { + logVerbose && console.log("delaying confirmReserve"); + taler.onPresent(function () { + confirmReserve(reservePub); + }); + return; + } + callWallet("taler-confirm-reserve", { reserve_pub: reservePub }); + } + taler.confirmReserve = confirmReserve; + function createReserve(callbackUrl, amount, wtTypes, suggestedExchangeUrl) { + if (!installed) { + logVerbose && console.log("delaying createReserve"); + taler.onPresent(function () { + createReserve(callbackUrl, amount, wtTypes, suggestedExchangeUrl); + }); + return; + } + var args = { + callback_url: callbackUrl, + amount: amount, + wt_types: wtTypes, + suggested_exchange_url: suggestedExchangeUrl + }; + callWallet("taler-create-reserve", args); + } + taler.createReserve = createReserve; + function onPresent(f) { + presentHandlers.push(f); + } + taler.onPresent = onPresent; + function onAbsent(f) { + absentHandlers.push(f); + } + taler.onAbsent = onAbsent; + function pay(p) { + if (!installed) { + logVerbose && console.log("delaying call to 'pay' until GNU Taler wallet is present"); + taler.onPresent(function () { + pay(p); + }); + return; + } + callWallet("taler-pay", p); + } + taler.pay = pay; + function refund(refundUrl) { + if (!installed) { + logVerbose && console.log("delaying call to 'refund' until GNU Taler wallet is present"); + taler.onPresent(function () { + refund(refundUrl); + }); + return; + } + callWallet("taler-refund", refundUrl); + } + taler.refund = refund; + function addAuditor(d) { + if (!installed) { + logVerbose && console.log("delaying call to 'addAuditor' until GNU Taler wallet is present"); + taler.onPresent(function () { + addAuditor(d); + }); + return; + } + callWallet("taler-add-auditor", d); + } + taler.addAuditor = addAuditor; + /** + * Check if an auditor is already added to the wallet. + * + * Same-origin restrictions apply. + */ + function checkAuditor(url) { + if (!installed) { + logVerbose && console.log("delaying call to 'checkAuditor' until GNU Taler wallet is present"); + return new Promise(function (resolve, reject) { + taler.onPresent(function () { + resolve(checkAuditor(url)); + }); + }); + } + return new Promise(function (resolve, reject) { + taler.onPresent(function () { + callWallet("taler-check-auditor", url, function (x) { return resolve(x); }); + }); + }); + } + taler.checkAuditor = checkAuditor; + function initTaler() { + function handleUninstall() { + installed = false; + // not really true, but we want "uninstalled" to be shown + firstTimeoutCalled = true; + announce(); + } + function handleProbe() { + probeExecuted = true; + if (!installed) { + logVerbose && console.log("taler install detected"); + installed = true; + announce(); + } + } + function probeTaler() { + probeExecuted = false; + var eve = new Event("taler-probe"); + document.dispatchEvent(eve); + } + var firstTimeoutCalled = false; + function onProbeTimeout() { + if (!probeExecuted) { + if (installed || !firstTimeoutCalled) { + installed = false; + firstTimeoutCalled = true; + logVerbose && console.log("taler uninstall detected"); + announce(); + } + } + // try again, maybe it'll be installed ... + probeTaler(); + } + /** + * Announce presence/absence + * + * Only called after document.readyState is at least "interactive". + */ + function announce() { + if (!pageLoaded) { + logVerbose && console.log("page not loaded yet, announcing later"); + return; + } + if (installed) { + logVerbose && console.log("announcing installed"); + for (var i = 0; i < presentHandlers.length; i++) { + presentHandlers[i](); + } + } + else { + if (firstTimeoutCalled) { + logVerbose && console.log("announcing uninstalled"); + for (var i = 0; i < absentHandlers.length; i++) { + absentHandlers[i](); + } + } + else { + logVerbose && console.log("announcing nothing"); + } + } + } + function onPageLoad() { + pageLoaded = true; + // We only start the timeout after the page is interactive. + window.setInterval(onProbeTimeout, 300); + announce(); + } + probeTaler(); + document.addEventListener("taler-probe-result", handleProbe, false); + document.addEventListener("taler-uninstall", handleUninstall, false); + // Handle the case where the JavaScript is loaded after the page + // has been loaded for the first time. + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", onPageLoad, false); + } + else { + onPageLoad(); + } + } + logVerbose && console.log("running taler-wallet-lib from page"); + initTaler(); +})(taler || (taler = {})); +// @license-end \ No newline at end of file diff --git a/plugin/src/GNU-taler-payment/readme.txt b/plugin/src/GNU-taler-payment/readme.txt new file mode 100644 index 0000000..e298a0e --- /dev/null +++ b/plugin/src/GNU-taler-payment/readme.txt @@ -0,0 +1,59 @@ +=== GNU Taler Payment Gateway for Woocommerce === +Contributors: hofmd2, sakaeo +Donate link: https://donations.demo.taler.net/ +Tags: woocommerce, e-commerce, GNU Taler, Taler, Payment Gateway +Requires at least: 5.1 +Tested up to: 5.2.1 +Stable tag: 5.2 +Requires PHP: 7.2 +License: GNU General Public License v3.0 +License URI: http://www.gnu.org/licenses/gpl-3.0.html + +Online payment plugin for Woocommerce powered by GNU Taler + +== Description == + +This plugin provides a safe and secure way to pay via the GNU Taler system. The plugin sends a request to and receives a respones from the GNU Taler Backend. +After that the plugin confirms the transaction again and redirect the customer to his own wallet to confirm the transaction. +The plugin provides the possibilitiy for the admininstrator to send the costumer a refund. +For that the plugin sends a refund request to the GNU Taler backend and receives a refund-url, which will be forwarded to the customer via an email to confirm the refund. + +The GNU Taler payment system has some certificate and includes latest fraud and risk management. + +== Installation == + +1. Ensure you have latest version of WooCommerce plugin installed +2. Upload the plugin files to the `/wp-content/plugins/plugin-name` directory, or install the plugin through the WordPress plugins screen directly. +3. Activate the GNU Taler Payment for Woocommerce plugin through the 'Plugins' screen in WordPress. +4. Use WooCommerce settings-> payment tab -> GNU Taler Payment for Woocommerce Settings to configure the plugin. + +== Frequently Asked Questions == + += Do I have to have a GNU Taler account to use the plugin? = + +Yes, you need to have an account. +You can join the GNU Taler family on: https://bank.demo.taler.net/ + += Does the customer need to have the GNU Taler Wallet installed to pay with GNU Taler? = + +Yes, the customer needs the GNU Taler Wallet. +The customer can download it here: https://bank.demo.taler.net/ + + += Can the plugin work without Woocommerce = + +For the plugin to work perfectly you need to have the Woocommerce plugin installed + +== Screenshots == + +1. No screenshots + +== Changelog == + += 0.6.0 = +* First Public Release + +== Upgrade Notice == + += 0.6.0 = + diff --git a/src/GNU-taler-payment/class-wc-gnutaler-gateway.php b/src/GNU-taler-payment/class-wc-gnutaler-gateway.php deleted file mode 100644 index 0d8100b..0000000 --- a/src/GNU-taler-payment/class-wc-gnutaler-gateway.php +++ /dev/null @@ -1,890 +0,0 @@ -. - */ - - -require_once ABSPATH . 'wp-admin/includes/plugin.php'; - -//Exit if accessed directly. -if ( ! defined( 'ABSPATH' ) ) { - exit(); -} - -/* - * This action hook registers our PHP class as a WooCommerce payment gateway - */ - -/** - * Adds the GNU Taler payment method to the other payment gateways. - * - * @param $gateways - Array of all the payment gateways. - * @return array - * @since 0.6.0 - */ - - -function gnutaler_add_gateway_class( $gateways ) { - $gateways[] = 'WC_GNUTaler_Gateway'; - return $gateways; -} - -add_filter( 'woocommerce_payment_gateways', 'gnutaler_add_gateway_class' ); - -/** - * The class itself, please note that it is inside plugins_loaded action hook - */ - -add_action( 'plugins_loaded', 'gnutaler_init_gateway_class' ); - - -function gnutaler_init_gateway_class() -{ - //Check if WooCommerce is active, if not then deactivate and show error message - if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins' ) ), true ) ) { - deactivate_plugins(plugin_basename(__FILE__)); - wp_die("GNU Taler requires WooCommerce plugin to work normally. Please activate it or install it from here.

Back to the WordPress Plugins page."); - } - - /** - * GNU Taler Payment Gateway class. - * - * Handles the payments from the Woocommerce Webshop and sends the transactions to the GNU Taler Backend and the GNU Taler Wallet. - * - * @since 0.6.0 - */ - class WC_GNUTaler_Gateway extends WC_Payment_Gateway - { - /** - * Class constructor - */ - public function __construct() - { - $this->id = 'gnutaler'; // payment gateway plugin ID - $this->icon = ''; // URL of the icon that will be displayed on checkout page near the gateway name - $this->has_fields = false; // There is no need for custom checkout fields, therefore set false - $this->method_title = 'GNU Taler Gateway'; - $this->method_description = 'This plugin enables the payment via the GNU Taler payment system'; // will be displayed on the options page - - // gateways can support refunds, saved payment methods, - $this->supports = array( - 'products', 'refunds', - ); - // Method with all the options fields - $this->init_form_fields(); - - // Load the settings. - $this->init_settings(); - $this->title = $this->get_option( 'title' ); - $this->description = $this->get_option( 'description' ); - $this->enabled = $this->get_option( 'enabled' ); - $this->GNU_Taler_Backend_URL = $this->get_option( 'GNU_Taler_Backend_URL' ); - $this->GNU_Taler_Backend_API_Key = $this->get_option( 'GNU_Taler_Backend_API_Key' ); - $this->Payment_url = $this->get_option( 'Payment_url' ); - $this->Order_text = $this->get_option( 'Order_text' ); - $this->merchant_information = $this->get_option( 'merchant_information' ); - $this->merchant_name = $this->get_option( 'merchant_name' ); - - //Here we add the Javascript files to the webserver - add_action( 'woocommerce_before_checkout_form', static function () { - wp_enqueue_script( 'taler-wallet-lib', plugin_dir_url( __FILE__ ) . 'js/taler-wallet-lib.js' ); - } ); - add_action( 'woocommerce_before_checkout_form', static function () { - wp_enqueue_script( 'WalletDetection', plugin_dir_url( __FILE__ ) . 'js/WalletDetection.js' ); - } ); - - add_action( 'woocommerce_api_'. strtolower( get_class($this) ), array( $this, 'callback_handler' ) ); - - // This action hook saves the settings - add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); - } - - /** - * Plugin options - */ - public function init_form_fields() - { - $this->form_fields = array( - 'enabled' => array( - 'title' => 'Enable/Disable', - 'label' => 'Enable GNU Taler Gateway', - 'type' => 'checkbox', - 'description' => '', - 'default' => 'no', - ), - 'title' => array( - 'title' => 'Title', - 'type' => 'text', - 'description' => 'What name should the payment method have when the costumer can choose how to pay .', - 'default' => 'GNU Taler', - 'desc_tip' => true, - ), - 'description' => array( - 'title' => 'Description', - 'type' => 'textarea', - 'description' => 'This controls the description which the customer sees during checkout.', - 'default' => 'Pay with the new Payment method GNU Taler.', - ), - 'GNU_Taler_Backend_URL' => array( - 'title' => 'GNU Taler Backend URL', - 'type' => 'text', - 'description' => 'Set the URL of the GNU Taler Backend.', - 'default' => 'https://backend.demo.taler.net', - ), - 'GNU_Taler_Backend_API_Key' => array( - 'title' => 'GNU Taler Backend API Key', - 'type' => 'text', - 'description' => 'Set the API-key for the Authorization with the GNU Taler Backend.', - 'default' => 'ApiKey sandbox', - ), - 'Payment_url' => array( - 'title' => 'GNU Taler Payment url', - 'type' => 'text', - 'description' => 'Set the URL for your GNU Taler Wallet where the Coins of the costumer will be send to.', - 'default' => '', - ), - 'Order_text' => array( - 'title' => 'Summarytext of the order', - 'type' => 'text', - 'description' => 'Set the text the customer should see as a summary when he confirms the payment.', - 'default' => 'Order', - ), - 'merchant_information' => array( - 'title' => 'Enable/Disable', - 'label' => 'Enable sending your merchant information to the GNU Taler Backend', - 'type' => 'checkbox', - 'description' => 'Do you want to send your merchant information to the GNU Taler Backend via the transaction', - 'default' => 'yes', - ), - 'merchant_name' => array( - 'title' => 'Name of the webshop', - 'type' => 'text', - 'description' => 'Set the name of the webshop that the customer will see during the payment transaction.', - 'default' => '', - ), - ); - } - - /** - * Callback is called, when the payment succeeds. - * - * Is called on successful payment process. - * User is then being forwarded to the order details page. - * - * @since 0.6.0 - */ - - public function callback_handler(): void - { - - if ( is_user_logged_in() ) - { - $user_id = WC()->customer->get_id(); - } - else - { - $user_id = 'Guest'; - } - - if ( isset( $_GET['order_id'] ) ) { - - //Gets the order id from the fulfillment url - $order_id_backend = $_GET['order_id']; - $order_id_array = explode( '-', $order_id_backend ); - $order_id_name = $order_id_array[0]; - $order_id = $order_id_array[1]; - $wc_order = wc_get_order( $order_id ); - - //Completes the order - $wc_order->payment_complete(); - - //Empties the shopping cart - WC()->cart->empty_cart(); - - $this->add_log_entry('transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Payment succeeded and the user was forwarded to the order confirmed page' ); - - wp_redirect( get_home_url() . '/checkout/order-received/' . $order_id . '/?key=' . $order_id_name ); - exit; - } - wp_redirect(get_home_url() . '/my-account/orders/'); - exit; - } - - /** - * Sends a request to a url via HTTP. - * - * Sends a request to a GNU Taler Backend over HTTP and returns the result. - * The request can be sent as POST, GET, PUT or another method. - * - * @param $method - POST, GET, PUT or another method. - * @param $backend_url - URL to the GNU Taler Backend. - * @param $body - The content of the request. - * @param $purpose - What return value is to be expected. - * @return array The return array will either have the successful return value or a detailed error message. - * @since 0.6.0 - * - */ - public function call_api( $method, $backend_url, $body, $purpose ): array - { - //create_url - $url = $this->create_api_url( $backend_url, $purpose, $body ); - - //Initialize curl request - $curl = $this->curl_init( $method, $body, $url ); - - // EXECUTE: - $result = curl_exec( $curl ); - - //HTTP Status Error handling - $message_array = $this->curl_error_handling( $curl, $result ); - curl_close( $curl ); - return $message_array; - } - - /** - * Checks if the return http code is a success and if not what kind of error status it is. - * - * If the request was successful an array will be returned with the boolean value true, the http code and the result of the response. - * If the request failed an array will be returned with the boolean value false, the http code and a detailed error message. - * - * @param $curl - Created curl request for error handling. - * @param $result - The response from the backend, that will be returned if the request was successful - * @return array - Array with a boolean, a http code and a message will be returned - * @since 0.6.0 - * - */ - public function curl_error_handling( $curl, $result ): array - { - $http_code = curl_getinfo( $curl, CURLINFO_HTTP_CODE ); - if ( curl_error( $curl ) ) { - $error_msg = curl_error( $curl ); - } - curl_close( $curl ); - if ( isset( $error_msg ) ) { - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => $error_msg, - ); - } - if ( $http_code === 200 ) { - return array( - 'result' => true, - 'http_code' => $http_code, - 'message' => $result, - ); - } - if ( preg_match( '(4[0-9]{2})', $http_code ) ) { - switch ($http_code) { - case 400: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'request', - ); - break; - case 401: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Unauthorized', - ); - break; - case 403: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Forbidden', - ); - break; - case 404: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Page Not Found', - ); - break; - default: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => '4xx Client Error', - ); - break; - } - } elseif ( preg_match( '(5[0-9]{2})', $http_code ) ) { - switch ( $http_code ) { - case '500': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Internal Server Error', - ); - break; - case '502': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Bad Gateway', - ); - break; - case '503': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Service Unavailable', - ); - break; - case '504': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Gateway Timeout', - ); - break; - default: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => '5xx Client Error', - ); - break; - } - } else { - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'http status error', - ); - } - } - - /** - * Initialises the curl request and sets some necessary options depending on the method. - * - * Depending of the method chosen different options for the curl request will be set. - * Not depending on the method the settings for a return value, Authorization and Content-Type are being set. - * - * @param $method - POST, GET, PUT or another method. - * @param $body - Content of the request. - * @param $url - URL where the request will be send - * @return false|resource - Either the configured curl request will be returned or false if an error appears. - * @since 0.6.0 - */ - public function curl_init( $method, $body, $url ) - { - $curl = curl_init(); - $apikey = $this->get_option( 'GNU_Taler_Backend_API_Key' ); - - switch ( $method ) { - case 'POST': - curl_setopt( $curl, CURLOPT_POST, 1 ); - if ( $body ) { - curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); - } - break; - case 'PUT': - curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, 'PUT' ); - if ( $body ) { - curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); - } - break; - case 'GET': - curl_setopt( $curl, CURLOPT_VERBOSE, 1 ); - break; - default: - curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $method ); - break; - } - - // OPTIONS: - curl_setopt( $curl, CURLOPT_URL, $url ); - curl_setopt( $curl, CURLOPT_HTTPHEADER, array( - 'Authorization: ' . $apikey, - 'Content-Type: application/json', - ) ); - curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 ); - curl_setopt ($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ); - - return $curl; - } - - /** - * Creates the final url depending on the purpose. - * - * @param $url - URL where the request will be send. - * @param $purpose - What will be added to the url. - * @param $body - Content of the request. - * @return string - return the final url. - * @since 0.6.0 - */ - public function create_api_url ($url, $purpose, $body ): string - { - if ( $purpose === 'create_order' ) { - return $url . '/order'; - } - if ( $purpose === 'confirm_payment' ) { - return $url . '/check-payment?order_id=' . $body; - } - if ( $purpose === 'create_refund' ) { - return $url . '/refund'; - } - return $url; - } - - /** - * Verifying if the url to the backend given in the plugin options is valid or not. - * - * @param $url - URL to the backend - * @return bool - Returns if valid or not. - * @since 0.6.0 - */ - public function verify_backend_url( $url ): bool - { - $result = $this->call_api( 'GET', $url, '', '' ); - if ( $result['result'] ){ - return true; - } - return false; - } - - /** - * Processes the payment after the checkout - * - * If the payment process finished successfully the user is being redirected to its GNU Taler Wallet. - * If an error occurs it returns void and throws an error. - * - * @param $order_id - ID of the order to get the Order from the WooCommerce Webshop - * @return array|void - Array with result => success and redirection url otherwise it returns void. - * @since 0.6.0 - */ - public function process_payment( $order_id ) - { - // we need it to get any order detailes - $wc_order = wc_get_order( $order_id ); - - if ( is_user_logged_in() ) - { - $user_id = WC()->customer->get_id(); - } - else - { - $user_id = 'Guest'; - $this->add_log_entry( 'transaction', 'The customer started a transaction without login, therefore the userid is unknown.' ); - } - - // Gets the url of the backend from the WooCommerce Settings - $backend_url = $this->get_option( 'GNU_Taler_Backend_URL', 1 ); - - //Log entry that the customer started the payment process - $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - User started the payment process.' ); - - if ( ! $this->verify_backend_url( $backend_url ) ) { - wc_add_notice( 'Something went wrong please contact the system administrator of the webshop and send the following error: GNU Taler backend url invalid', 'error' ); - $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Checkout process failed - Invalid backend url.' ); - return; - } - $order_json = $this->convert_to_checkout_json( $order_id ); - - $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Transaction request send to GNU Taler backend' ); - $order_request = $this->send_order_request( $backend_url, $order_json, $user_id, $order_id ); - - if ( $order_request['boolean'] ) { - - //Returns that the payment process finished successfully and redirects the costumer to confirm the payment via GNU Taler - $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Customer is being redirected to the payment confirmation site' ); - return array( - 'result' => 'success', - // 'redirect' => '', - 'redirect' => $order_request['url'], - ); - } - wc_add_notice( 'There seems to be a problem with the payment process, please try again or send the following message to a system administrator: ' . $order_request['http_code'] . ' - ' . $order_request['error_message'] ); - $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the payment process - ' . $order_request['http_code'] . ' - ' . $order_request['error_message'] ); - $wc_order->set_status( 'cancelled' ); - return; - } - - /** - * Sends the transaction to the GNU Taler Backend - * - * If the payment process finishes successfully it returns an array with the redirection url to the GNU Taler Wallet and a boolean value for error handling. - * If an error occurs it returns an array with a boolean value for error handling, the http status code and an error message. - * - * @param $backend_url - URL where the request will be sent. - * @param $json - JSON array with the data of the order for the backend. - * @param $user_id - User id for logging. - * @param $order_id - Order id for logging. - * @return array|void - Array with boolean true|false, url or error message with http status code. - * @since 0.6.0 - */ - public function send_order_request( $backend_url, $json, $user_id, $order_id ): array - { - // Send the POST-Request via CURL to the GNU Taler Backend - $order_confirmation = $this->call_api( 'POST', $backend_url, json_encode($json, JSON_UNESCAPED_SLASHES), 'create_order' ); - - $order_message = $order_confirmation['message']; - $order_boolean = $order_confirmation['result']; - - if ( $order_boolean ) { - $order_confirmation_id = explode( '"', $order_message )[3]; - - // Send the final confirmation to execute the payment transaction to the GNU Taler Backend - $payment_confirmation = $this->call_api( 'GET', $backend_url, $order_confirmation_id, 'confirm_payment' ); - $payment_message = $payment_confirmation['message']; - $payment_boolean = $order_confirmation['result']; - - if ( $payment_boolean ) { - - //Here we check what kind of http code came back from the backend - $payment_confirmation_url = explode( '"', $payment_message )[3]; - $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Successfully received redirect url to wallet from GNU Taler Backend' ); - return array( - 'boolean' => true, - 'url' => $payment_confirmation_url, - ); - } - $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the second request to the GNU Taler backend - ' . $payment_confirmation['http_code'] . ' - ' . $payment_message ); - return array( - 'boolean' => false, - 'http_code' => $payment_confirmation['http_code'], - 'error_message' => $payment_message, - ); - } - $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the first request to the GNU Taler backend - ' . $order_confirmation['http_code'] . ' - ' . $order_message ); - return array( - 'boolean' => false, - 'http_code' => $order_confirmation['http_code'], - 'error_message' => $order_message, - ); - } - - /** - * Converts the order into a JSON format that can be send to the GNU Taler Backend. - * - * - * The amount of the refund request can, at the moment, only be refunded in the currency 'KUDOS', which is the currency that the GNU Taler Payment system uses. - * This will change in the future. - * - * @param $order_id - To get the order from the WooCommerce Webshop - * @return array - return the JSON Format. - * @since 0.6.0 - */ - public function convert_to_checkout_json( $order_id ): array - { - $wc_order = wc_get_order( $order_id ); - $wc_order_total_amount = $wc_order->get_total(); - $wc_order_currency = $wc_order->get_currency(); - $wc_cart = WC()->cart->get_cart(); - $wc_order_id = $wc_order->get_order_key() . '-' . $wc_order->get_order_number(); - $merchant_option = $this->get_option( 'merchant_information' ); - - $wc_order_products_array = $this->mutate_products_to_json_format( $wc_cart, $wc_order_currency, $wc_order); - - $wc_order_merchant = $this->mutate_merchant_information_to_json_format( $merchant_option ); - - $order_json = array( - 'order' => array( - 'amount' => $wc_order_currency . ':' . $wc_order_total_amount, - 'summary' => 'Order from the merchant ' . $this->get_option('merchant_name') . ': ', - 'fulfillment_url' => get_home_url() . '/wc-api/wc_gnutaler_gateway', - //'payment_url' => $this->get_option( 'Payment_url' ), - 'order_id' => $wc_order_id, - 'merchant' => $wc_order_merchant, - 'products' => $wc_order_products_array, - ), - ); - return $order_json; - } - - /** - * Mutates the products in the cart into a format which can be included in a JSON file. - * - * @param $wc_cart - The content of the WooCommerce Cart. - * @param $wc_order_currency - The currency the WooCommerce Webshop uses. - * @return array - Returns an array of products. - * @since 0.6.0 - */ - public function mutate_products_to_json_format( $wc_cart, $wc_order_currency, $wc_order ): array - { - $wc_order_products_array = array(); - foreach ( $wc_cart as $product ) { - $wc_order_products_array[] = array( - 'description' => 'Order of product: ' . $product['data']->get_title(), - 'quantity' => $product['quantity'], - 'price' => $wc_order_currency . ':' . $product['data']->get_price(), - 'product_id' => $product['data']->get_id(), - 'delivery_location' => $this->mutate_shipping_information_to_json_format($wc_order), - ); - } - return $wc_order_products_array; - } - - /** - * Mutates the merchant information of the webshop into a format which can be included in a JSON file. - * - * @param $merchant_option - If the webshop owner allows to send the backend their information - * @return array - Returns an array of merchant information's. - * @since 0.6.0 - */ - public function mutate_merchant_information_to_json_format( $merchant_option ): array - { - $whitechar_encounter = false; - $store_address_street = ''; - $store_address_streetNr = ''; - - // When the option is enabled the informations of the merchant will be included in the transaction - if ( $merchant_option === 'yes' ) { - // The country/state - $store_raw_country = get_option( 'woocommerce_default_country' ); - $split_country = explode( ':', $store_raw_country ); - - // Country and state separated: - $store_country = $split_country[0]; - $store_state = $split_country[1]; - - //Streetname and number - $store_address = get_option( 'woocommerce_store_address' ); - $store_address_inverted = strrev( $store_address ); - $store_address_array = str_split( $store_address_inverted ); - - //Split the address into street and street number - foreach ( $store_address_array as $char ) { - if ( ! $whitechar_encounter ) { - $store_address_streetNr .= $char; - } elseif ( ctype_space( $char ) ) { - $whitechar_encounter = true; - } else { - $store_address_street .= $char; - } - } - $wc_order_merchant_location = array( - 'country' => $store_country, - 'state' => $store_state, - 'city' => WC()->countries->get_base_city(), - 'ZIP code' => WC()->countries->get_base_postcode(), - 'street' => strrev( $store_address_street ), - 'street number' => strrev( $store_address_streetNr ), - ); - return array( - 'address' => $wc_order_merchant_location, - 'name' => $this->get_option( 'merchant_name' ), - ); - } - return array(); - } - - /** - * Processes the refund transaction if requested by the system administrator of the webshop - * - * If the refund request is finished successfully it returns an refund url, which can be send to the customer to finish the refund transaction. - * If an error it will throw a WP_Error message and inform the system administrator. - * - * @param $wc_order - * @return array - * @since 0.6.0 - */ - public function mutate_shipping_information_to_json_format($wc_order): array - { - $whitechar_encounter = false; - $shipping_address_street = ''; - $shipping_address_streetNr = ''; - - $store_address = $wc_order->get_shipping_address_1(); - $store_address_inverted = strrev( $store_address ); - $store_address_array = str_split( $store_address_inverted ); - - //Split the address into street and street number - foreach ( $store_address_array as $char ) { - if ( ! $whitechar_encounter ) { - $shipping_address_street .= $char; - } elseif ( ctype_space( $char ) ) { - $whitechar_encounter = true; - } else { - $shipping_address_street .= $char; - } - } - - return array( - 'country' => $wc_order->get_shipping_country(), - 'state' => $wc_order->get_shipping_state(), - 'city' => $wc_order->get_shipping_city(), - 'ZIP code' => $wc_order->get_shipping_postcode(), - 'street' => $shipping_address_street, - 'street number' => $shipping_address_streetNr, - ); - } - - /** - * Processes the refund transaction if requested by the system administrator of the webshop - * - * If the refund request is finished successfully it returns an refund url, which can be send to the customer to finish the refund transaction. - * If an error it will throw a WP_Error message and inform the system administrator. - * - * @param $order_id - Order id for logging. - * @param null $amount - Amount that is requested to be refunded. - * @param string $reason - Reason for the refund request. - * @return bool|WP_Error - Returns true or throws an WP_Error message in case of error. - * @since 0.6.0 - */ - public function process_refund( $order_id, $amount = null, $reason = '' ) - { - $wc_order = wc_get_order( $order_id ); - $refund_json = $this->convert_refund_to_json( $wc_order, $amount, $reason ); - - $user_id = wc_get_order($order_id)->get_customer_id(); - if ( $user_id === 0 ){ - $user_id = 'Guest'; - } - - $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Refund process of order: ' . $order_id . ' started with the refunded amount: ' . $amount . ' ' . $wc_order->get_currency() . ' and the reason: ' . $reason ); - - // Gets the url of the backend from the WooCommerce Settings - $backend_url = $this->get_option( 'GNU_Taler_Backend_URL' ); - - //Get the current status of the order - $wc_order_status = $wc_order->get_status(); - - //Checks if current status is already set as paid - if ( $wc_order_status === 'processing' || $wc_order_status === 'on hold' || $wc_order_status === 'completed' ) { - - $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Refund request sent to the GNU Taler Backend' ); - $refund_request = $this->send_refund_request( $backend_url, $refund_json ); - - if( $refund_request['boolean'] ) { - //Set the status as refunded and post the link to confirm the refund process via the GNU Taler payment method - $wc_order->update_status( 'refunded' ); - $wc_order->add_order_note( 'The refund process finished successfully, please send the following url to the customer via an email to confirm the refund transaction.' ); - $wc_order->add_order_note( $refund_request['url'] ); - $this->add_log_entry( 'transaction', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - Successfully received refund redirect url from GNU Taler backend, customer can now refund the given amount.' ); - return true; - } - $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - An error occurred during the refund process - ' . $refund_request['http_code'] . ' - ' . $refund_request['error_message'] ); - return new WP_Error( 'error', 'An error occurred during the refund process, please try again or send the following message to your system administrator: ' . $refund_request['http_code'] . ' - ' . $refund_request['error_message'] ); - } - $this->add_log_entry( 'error', 'Userid: ' . $user_id . ' - Orderid: ' . $order_id . ' - The status of the order does not allow a refund' ); - return new WP_Error( 'error', 'The status of the order does not allow for a refund.' ); - } - - /** - * Sends the refund transaction to the GNU Taler Backend - * - * If the refund process finishes successfully it returns a boolean value true and sends the system administrator the refund url for the customer. - * If an error occurs it returns a WP_Error which will be displayed . - * - * @param $backend_url - URL where the request will be sent. - * @param $json - JSON array with the data of the refund request for the backend. - * @return array|void - Array with boolean true|false, url or error message with http status code. - * @since 0.6.0 - */ - public function send_refund_request( $backend_url, $json ): array - { - $refund_url = ''; - $refund_confirmation = $this->call_api( 'POST', $backend_url, json_encode($json, JSON_UNESCAPED_SLASHES), 'create_refund' ); - - $message = $refund_confirmation['message']; - $refund_boolean = $refund_confirmation['result']; - - if ($refund_boolean) { - //Here we check what kind of http code came back from the backend - $refund_confirmation_array = explode(',', $message); - foreach ( $refund_confirmation_array as $value ) { - - //Looping through the return value and checking if "refund_redirect_url" can be found - if ( strpos( $value, 'refund_redirect_url' ) ) { - $refund_url = explode( '"', $value )[3]; - } - } - return array( - 'boolean' => true, - 'url' => $refund_url, - ); - } - return array( - 'boolean' => false, - 'url' => $refund_url, - 'http_code' => $refund_confirmation['http_code'], - 'error_message' => $refund_confirmation['message'], - ); - } - - /** - * Converts the information of the refund request into a JSON format that can be send to the GNU Taler Backend. - * - * The amount of the refund request can, at the moment, only be refunded in the currency 'KUDOS', which is the currency that the GNU Taler Payment system uses. - * This will change in the future. - * - * @param $order - Order where the refund request originated from. - * @param $amount - Amount to be refunded. - * @param $reason - Reason of refund. - * @return array - returns the JSON Format. - * @since 0.6.0 - */ - public function convert_refund_to_json( $order, $amount, $reason ): array - { - return array( - 'order_id' => $order->get_order_key() . '-' . $order->get_order_number(), - 'refund' => $order->get_currency() . ':' . $amount, - 'instance' => 'default', - 'reason' => $reason, - ); - } - - /** - * - * Creates or opens the log files and writes a log entry. - * - * @param $type - What kind of log it is. - * @param $message - What the message of the log entry is. - * @return void - Returns void. - * @since 0.6.0 - */ - public function add_log_entry( $type, $message ): void - { - $file = null; - $timestamp = date( 'r' ); - if ( $type === 'error' ) { - $file = fopen( __DIR__ . '/log/GNUTaler_Error.log', 'ab' ); - } - elseif ( $type === 'transaction' ) { - $file = fopen( __DIR__ . '/log/GNUTaler_User_Transactions.log', 'ab' ); - } - else - { - $file = fopen( __DIR__ . '/log/GNUTaler_' . $type . '.log', 'ab' ); - } - if ( $file !== null ){ - fwrite( $file, $timestamp . ' - ' . $message . PHP_EOL ); - fclose( $file ); - } - } - } -} diff --git a/src/GNU-taler-payment/functions/functions.php b/src/GNU-taler-payment/functions/functions.php deleted file mode 100644 index 1a8dd6f..0000000 --- a/src/GNU-taler-payment/functions/functions.php +++ /dev/null @@ -1,224 +0,0 @@ - false, - 'http_code' => $http_code, - 'message' => $error_msg, - ); - } - if ( $http_code === 200 ) { - return array( - 'result' => true, - 'http_code' => $http_code, - 'message' => $result, - ); - } - if ( preg_match( '(4[0-9]{2})', $http_code ) ) { - switch ($http_code) { - case 400: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Bad request', - ); - break; - case 401: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Unauthorized', - ); - break; - case 403: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Forbidden', - ); - break; - case 404: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Page Not Found', - ); - break; - default: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => '4xx Client Error', - ); - break; - } - } elseif ( preg_match( '(5[0-9]{2})', $http_code ) ) { - switch ( $http_code ) { - case '500': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Internal Server Error', - ); - break; - case '502': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Bad Gateway', - ); - break; - case '503': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Service Unavailable', - ); - break; - case '504': - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'Gateway Timeout', - ); - break; - default: - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => '5xx Client Error', - ); - break; - } - } else { - return array( - 'result' => false, - 'http_code' => $http_code, - 'message' => 'http status error', - ); - } -} - -/** - * Initialises the curl request and sets some necessary options depending on the method. - * - * Depending of the method chosen different options for the curl request will be set. - * Not depending on the method the settings for a return value, Authorization and Content-Type are being set. - * - * @param $method - POST, GET, PUT or another method. - * @param $body - Content of the request. - * @param $url - URL where the request will be send - * @param $api_key - * @return false|resource - Either the configured curl request will be returned or false if an error appears. - * @since 0.6.0 - */ -function curl_init_request( $method, $body, $url, $api_key ) -{ - $curl = curl_init(); - - switch ( $method ) { - case 'POST': - curl_setopt( $curl, CURLOPT_POST, 1 ); - if ( $body ) { - curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); - } - break; - case 'PUT': - curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, 'PUT' ); - if ( $body ) { - curl_setopt( $curl, CURLOPT_POSTFIELDS, $body ); - } - break; - case 'GET': - curl_setopt( $curl, CURLOPT_VERBOSE, 1 ); - break; - default: - curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $method ); - break; - } - - // OPTIONS: - curl_setopt( $curl, CURLOPT_URL, $url ); - curl_setopt( $curl, CURLOPT_HTTPHEADER, array( - 'Authorization: ' . $api_key, - 'Content-Type: application/json', - ) ); - curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 ); - curl_setopt ($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ); - - return $curl; -} - -/** - * Creates the final url depending on the purpose. - * - * @param $url - URL where the request will be send. - * @param $purpose - What will be added to the url. - * @param $body - Content of the request. - * @return string - return the final url. - * @since 0.6.0 - */ -function create_api_url ($url, $purpose, $body ): string -{ - if ( $purpose === 'create_order' ) { - return $url . '/order'; - } - if ( $purpose === 'confirm_payment' ) { - return $url . '/check-payment?order_id=' . $body; - } - if ( $purpose === 'create_refund' ) { - return $url . '/refund'; - } - return $url; -} - - diff --git a/src/GNU-taler-payment/functions/functionsTest.php b/src/GNU-taler-payment/functions/functionsTest.php deleted file mode 100644 index a18dab2..0000000 --- a/src/GNU-taler-payment/functions/functionsTest.php +++ /dev/null @@ -1,157 +0,0 @@ - array( - 'amount' => 'KUDOS:0.1', - 'fulfillment_url' => 'http://gnutaler.hofmd.ch', - 'summary' => 'Test_order', - 'order_id' => $wc_order_test_request, - ) - ); - $purpose_1 = 'create_order'; - - $body_request_2 = $wc_order_test_request; - $purpose_2 = 'confirm_payment'; - - $result_create_order = call_api( $method_post, $backend_url, json_encode($body_request_1), $purpose_1, $api_key ); - $result_confirm_payment = call_api( $method_get, $backend_url, $body_request_2, $purpose_2, $api_key ); - $result_verify_backend_url = call_api( $method_get, $backend_url, '', '', $api_key ); - $result_method_different = call_api( $method_different, $backend_url, json_encode($body_request_1), $purpose_1, $api_key ); - - Assert::assertTrue($result_create_order['result']); - Assert::assertEquals($wc_order_test_request, json_decode($result_create_order['message'], true)['order_id']); - Assert::assertTrue($result_confirm_payment['result']); - Assert::assertEquals(false, json_decode($result_confirm_payment['message'], true)['paid']); - Assert::assertTrue($result_verify_backend_url['result']); - Assert::assertEquals('Hello, I\'m a merchant\'s Taler backend. This HTTP server is not for humans.', trim($result_verify_backend_url['message'])); - Assert::assertFalse($result_method_different['result']); - Assert::assertEquals('Bad request', $result_method_different['message']); - } - - - /** - * Tests the create_api_url function - */ - public function test_create_api_url(): void - { - $url_test = 'https://backend.demo.taler.net'; - $wc_test_order = ''; - try { - $wc_test_order = 'wc_test_' . random_int(0, 1000); - } catch (Exception $e) { - } - $purpose_create_order = 'create_order'; - $purpose_confirm_payment = 'confirm_payment'; - $purpose_create_refund = 'create_refund'; - - $create_order_url = create_api_url($url_test, $purpose_create_order, ''); - $confirm_payment_url = create_api_url($url_test, $purpose_confirm_payment, $wc_test_order); - $create_refund_url = create_api_url($url_test, $purpose_create_refund, ''); - - Assert::assertEquals('https://backend.demo.taler.net/order', $create_order_url); - Assert::assertEquals('https://backend.demo.taler.net/check-payment?order_id=' . $wc_test_order, $confirm_payment_url); - Assert::assertEquals('https://backend.demo.taler.net/refund', $create_refund_url); - } - - /** - * Tests the curl_error_handling function with the http status code 200 - */ - public function test_curl_error_handling_code_200(): void - { - $api_key = 'ApiKey sandbox'; - $test_url = 'https://backend.demo.taler.net'; - - $curl_error_message_array = call_api('GET', $test_url, '', '', $api_key); - - Assert::assertTrue($curl_error_message_array['result']); - Assert::assertEquals(200, $curl_error_message_array['http_code']); - } - - /** - * Tests the curl_error_handling function with the http status code 400 - */ - public function test_curl_error_handling_code_400(): void - { - $api_key = 'ApiKey sandbox'; - $api_key_wrong = 'ApiKey ____***££££èèè'; - $test_url = 'https://backend.demo.taler.net'; - $test_url_wrong = 'https://backend.demo.taler.net/test_if_this_exits'; - $body = json_encode(array( - 'order' => array( - 'wrong_field' => 'Wrong value', - ) - )); - - $curl_error_message_array_400 = call_api('POST', $test_url, $body, 'create_order', $api_key); - $curl_error_message_array_401 = call_api('GET', $test_url, '', '', $api_key_wrong); - $curl_error_message_array_403 = call_api('GET', 'https://httpstat.us/403', '', '', ''); - $curl_error_message_array_404 = call_api('GET', $test_url_wrong, '', '', $api_key); - - Assert::assertFalse($curl_error_message_array_400['result']); - Assert::assertEquals(400, $curl_error_message_array_400['http_code']); - Assert::assertFalse($curl_error_message_array_401['result']); - Assert::assertEquals(401, $curl_error_message_array_401['http_code']); - Assert::assertFalse($curl_error_message_array_403['result']); - Assert::assertEquals(403, $curl_error_message_array_403['http_code']); - Assert::assertFalse($curl_error_message_array_404['result']); - Assert::assertEquals(404, $curl_error_message_array_404['http_code']); - - } - - - /** - * Tests the curl_error_handling function with the http status code 500 - */ - public function test_curl_error_handling_code_500(): void - { - $api_key = 'ApiKey sandbox'; - $test_url = 'https://backend.demo.taler.net'; - $test_url_500 = 'https://httpstat.us/500'; - $test_url_502 = 'https://httpstat.us/502'; - $test_url_503 = 'https://httpstat.us/503'; - $test_url_504 = 'https://httpstat.us/504'; - - $curl_error_message_array_500 = call_api('GET', $test_url_500, '', '', $api_key); - $curl_error_message_array_502 = call_api('GET', $test_url_502, '', '', $api_key); - $curl_error_message_array_503 = call_api('GET', $test_url_503, '', '', $api_key); - $curl_error_message_array_504 = call_api('GET', $test_url_504, '', '', $api_key); - - Assert::assertFalse($curl_error_message_array_500['result']); - Assert::assertEquals(500, $curl_error_message_array_500['http_code']); - Assert::assertFalse($curl_error_message_array_502['result']); - Assert::assertEquals(502, $curl_error_message_array_502['http_code']); - Assert::assertFalse($curl_error_message_array_503['result']); - Assert::assertEquals(503, $curl_error_message_array_503['http_code']); - Assert::assertFalse($curl_error_message_array_504['result']); - Assert::assertEquals(504, $curl_error_message_array_504['http_code']); - - } - -} diff --git a/src/GNU-taler-payment/js/WalletDetection.js b/src/GNU-taler-payment/js/WalletDetection.js deleted file mode 100644 index d2b1df5..0000000 --- a/src/GNU-taler-payment/js/WalletDetection.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Wallet detection script - * Detects which browser the user is using and if the GNU Taler wallet is installed - * If the wallet isn't detected or the customer uses a browser which isn't supported, then it removes the GNU Taler payment method from the possibilities. - * - * Currently only the Browser detection is working and the wallet detection isn't - * The reason is, that we couldn't figure out how to detect the wallet with the given functions of the taler-wallet-lib.js - */ - -function detectWallet() { - - sUsrAg = navigator.userAgent; - - if ((sUsrAg.indexOf("Firefox") > -1) || (sUsrAg.indexOf("Opera") > -1 || sUsrAg.indexOf("OPR") > -1) || (sUsrAg.indexOf("Chrome") > -1)) { - //Mozilla Firefox, Opera or Google Chrome - taler.onAbsent(() => { - //Does nothing - }); - } else if ((sUsrAg.indexOf("Trident") > -1) || (sUsrAg.indexOf("Edge") > -1) || (sUsrAg.indexOf("Safari") > -1)) { - //Microsoft Internet Explorer, Microsoft edge or Apple Safari - removePaymentMethod(); - } else { - //Unknown Browser - removePaymentMethod(); - } -} - -function removePaymentMethod() { - var observer = new MutationObserver(function (mutations, observer) { - mutations.forEach(() => { - document.getElementsByClassName("wc_payment_method payment_method_gnutaler").item(0).style.display = 'none'; - }); - }); - - // define what element should be observed by the observer - // and what types of mutations trigger the callback - observer.observe(document, { - subtree: true, - attributes: true - }); -} - -detectWallet(); \ No newline at end of file diff --git a/src/GNU-taler-payment/js/taler-wallet-lib.js b/src/GNU-taler-payment/js/taler-wallet-lib.js deleted file mode 100644 index 8b1812a..0000000 --- a/src/GNU-taler-payment/js/taler-wallet-lib.js +++ /dev/null @@ -1,270 +0,0 @@ -/* - @source https://www.git.taler.net/?p=web-common.git;a=blob_plain;f=taler-wallet-lib.ts;hb=HEAD - @license magnet:?xt=urn:btih:5de60da917303dbfad4f93fb1b985ced5a89eac2&dn=lgpl-2.1.txt LGPL v21 - - @licstart The following is the entire license notice for the - JavaScript code in this page. - - Copyright (C) 2015, 2016 INRIA - - The JavaScript code in this page is free software: you can - redistribute it and/or modify it under the terms of the GNU - Lesser General Public License (GNU LGPL) as published by the Free Software - Foundation, either version 2.1 of the License, or (at your option) - any later version. The code is distributed WITHOUT ANY WARRANTY; - without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU LGPL for more details. - - As additional permission under GNU LGPL version 2.1 section 7, you - may distribute non-source (e.g., minimized or compacted) forms of - that code without the copy of the GNU LGPL normally required by - section 4, provided you include this license notice and a URL - through which recipients can access the Corresponding Source. - - @licend The above is the entire license notice - for the JavaScript code in this page. - - @author Marcello Stanisci - @author Florian Dold -*/ - -var taler; -(function (taler) { - "use strict"; - var logVerbose = false; - try { - logVerbose = !!localStorage.getItem("taler-log-verbose"); - } - catch (e) { - // can't read from local storage - } - var presentHandlers = []; - var absentHandlers = []; - // Are we running as the content script of an - // extension (and not just from a normal page)? - var runningInExtension = false; - var callSeqId = 1; - var installed = false; - var probeExecuted = false; - var pageLoaded = false; - var errorHandler = undefined; - function onError(handler) { - if (errorHandler) { - console.warn("Overriding error handler"); - } - errorHandler = handler; - } - taler.onError = onError; - /** - * Error handler for things that go wrong in the merchant - * frontend browser code. - */ - function raise_error(reason, detail) { - if (errorHandler) { - errorHandler(reason, detail); - return; - } - alert("Failure: " + reason + ". No error handler installed. Open the developer console for more information."); - console.error(reason, detail); - console.warn("No custom error handler set."); - } - function callWallet(funcName, args, onResult) { - var detail = JSON.parse(JSON.stringify(args || {})); - var callId = callSeqId++; - detail.callId = callId; - var onTimeout = function () { - console.warn("timeout for invocation of " + funcName); - }; - var timeoutHandle = setTimeout(onTimeout, 1000); - var handler = function (evt) { - if (evt.detail.callId !== callId) { - return; - } - if (onResult) { - onResult(evt.detail); - } - clearTimeout(timeoutHandle); - document.removeEventListener(funcName + "-result", handler); - }; - document.addEventListener(funcName + "-result", handler); - var evt = new CustomEvent(funcName, { detail: detail }); - document.dispatchEvent(evt); - } - /** - * Confirm that a reserve was created. - * - * Used by tightly integrated bank portals. - */ - function confirmReserve(reservePub) { - if (!installed) { - logVerbose && console.log("delaying confirmReserve"); - taler.onPresent(function () { - confirmReserve(reservePub); - }); - return; - } - callWallet("taler-confirm-reserve", { reserve_pub: reservePub }); - } - taler.confirmReserve = confirmReserve; - function createReserve(callbackUrl, amount, wtTypes, suggestedExchangeUrl) { - if (!installed) { - logVerbose && console.log("delaying createReserve"); - taler.onPresent(function () { - createReserve(callbackUrl, amount, wtTypes, suggestedExchangeUrl); - }); - return; - } - var args = { - callback_url: callbackUrl, - amount: amount, - wt_types: wtTypes, - suggested_exchange_url: suggestedExchangeUrl - }; - callWallet("taler-create-reserve", args); - } - taler.createReserve = createReserve; - function onPresent(f) { - presentHandlers.push(f); - } - taler.onPresent = onPresent; - function onAbsent(f) { - absentHandlers.push(f); - } - taler.onAbsent = onAbsent; - function pay(p) { - if (!installed) { - logVerbose && console.log("delaying call to 'pay' until GNU Taler wallet is present"); - taler.onPresent(function () { - pay(p); - }); - return; - } - callWallet("taler-pay", p); - } - taler.pay = pay; - function refund(refundUrl) { - if (!installed) { - logVerbose && console.log("delaying call to 'refund' until GNU Taler wallet is present"); - taler.onPresent(function () { - refund(refundUrl); - }); - return; - } - callWallet("taler-refund", refundUrl); - } - taler.refund = refund; - function addAuditor(d) { - if (!installed) { - logVerbose && console.log("delaying call to 'addAuditor' until GNU Taler wallet is present"); - taler.onPresent(function () { - addAuditor(d); - }); - return; - } - callWallet("taler-add-auditor", d); - } - taler.addAuditor = addAuditor; - /** - * Check if an auditor is already added to the wallet. - * - * Same-origin restrictions apply. - */ - function checkAuditor(url) { - if (!installed) { - logVerbose && console.log("delaying call to 'checkAuditor' until GNU Taler wallet is present"); - return new Promise(function (resolve, reject) { - taler.onPresent(function () { - resolve(checkAuditor(url)); - }); - }); - } - return new Promise(function (resolve, reject) { - taler.onPresent(function () { - callWallet("taler-check-auditor", url, function (x) { return resolve(x); }); - }); - }); - } - taler.checkAuditor = checkAuditor; - function initTaler() { - function handleUninstall() { - installed = false; - // not really true, but we want "uninstalled" to be shown - firstTimeoutCalled = true; - announce(); - } - function handleProbe() { - probeExecuted = true; - if (!installed) { - logVerbose && console.log("taler install detected"); - installed = true; - announce(); - } - } - function probeTaler() { - probeExecuted = false; - var eve = new Event("taler-probe"); - document.dispatchEvent(eve); - } - var firstTimeoutCalled = false; - function onProbeTimeout() { - if (!probeExecuted) { - if (installed || !firstTimeoutCalled) { - installed = false; - firstTimeoutCalled = true; - logVerbose && console.log("taler uninstall detected"); - announce(); - } - } - // try again, maybe it'll be installed ... - probeTaler(); - } - /** - * Announce presence/absence - * - * Only called after document.readyState is at least "interactive". - */ - function announce() { - if (!pageLoaded) { - logVerbose && console.log("page not loaded yet, announcing later"); - return; - } - if (installed) { - logVerbose && console.log("announcing installed"); - for (var i = 0; i < presentHandlers.length; i++) { - presentHandlers[i](); - } - } - else { - if (firstTimeoutCalled) { - logVerbose && console.log("announcing uninstalled"); - for (var i = 0; i < absentHandlers.length; i++) { - absentHandlers[i](); - } - } - else { - logVerbose && console.log("announcing nothing"); - } - } - } - function onPageLoad() { - pageLoaded = true; - // We only start the timeout after the page is interactive. - window.setInterval(onProbeTimeout, 300); - announce(); - } - probeTaler(); - document.addEventListener("taler-probe-result", handleProbe, false); - document.addEventListener("taler-uninstall", handleUninstall, false); - // Handle the case where the JavaScript is loaded after the page - // has been loaded for the first time. - if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", onPageLoad, false); - } - else { - onPageLoad(); - } - } - logVerbose && console.log("running taler-wallet-lib from page"); - initTaler(); -})(taler || (taler = {})); -// @license-end \ No newline at end of file diff --git a/src/GNU-taler-payment/readme.txt b/src/GNU-taler-payment/readme.txt deleted file mode 100644 index e298a0e..0000000 --- a/src/GNU-taler-payment/readme.txt +++ /dev/null @@ -1,59 +0,0 @@ -=== GNU Taler Payment Gateway for Woocommerce === -Contributors: hofmd2, sakaeo -Donate link: https://donations.demo.taler.net/ -Tags: woocommerce, e-commerce, GNU Taler, Taler, Payment Gateway -Requires at least: 5.1 -Tested up to: 5.2.1 -Stable tag: 5.2 -Requires PHP: 7.2 -License: GNU General Public License v3.0 -License URI: http://www.gnu.org/licenses/gpl-3.0.html - -Online payment plugin for Woocommerce powered by GNU Taler - -== Description == - -This plugin provides a safe and secure way to pay via the GNU Taler system. The plugin sends a request to and receives a respones from the GNU Taler Backend. -After that the plugin confirms the transaction again and redirect the customer to his own wallet to confirm the transaction. -The plugin provides the possibilitiy for the admininstrator to send the costumer a refund. -For that the plugin sends a refund request to the GNU Taler backend and receives a refund-url, which will be forwarded to the customer via an email to confirm the refund. - -The GNU Taler payment system has some certificate and includes latest fraud and risk management. - -== Installation == - -1. Ensure you have latest version of WooCommerce plugin installed -2. Upload the plugin files to the `/wp-content/plugins/plugin-name` directory, or install the plugin through the WordPress plugins screen directly. -3. Activate the GNU Taler Payment for Woocommerce plugin through the 'Plugins' screen in WordPress. -4. Use WooCommerce settings-> payment tab -> GNU Taler Payment for Woocommerce Settings to configure the plugin. - -== Frequently Asked Questions == - -= Do I have to have a GNU Taler account to use the plugin? = - -Yes, you need to have an account. -You can join the GNU Taler family on: https://bank.demo.taler.net/ - -= Does the customer need to have the GNU Taler Wallet installed to pay with GNU Taler? = - -Yes, the customer needs the GNU Taler Wallet. -The customer can download it here: https://bank.demo.taler.net/ - - -= Can the plugin work without Woocommerce = - -For the plugin to work perfectly you need to have the Woocommerce plugin installed - -== Screenshots == - -1. No screenshots - -== Changelog == - -= 0.6.0 = -* First Public Release - -== Upgrade Notice == - -= 0.6.0 = - -- cgit v1.2.3