diff --git a/app/Field.php b/app/Field.php new file mode 100644 index 0000000..b13919a --- /dev/null +++ b/app/Field.php @@ -0,0 +1,193 @@ + + */ + protected $_settings = []; + + /** + * @var array + */ + protected $_settings_only = [ + 'default', + ]; + + /** + * @var array + */ + protected $_use_merge_tags_include = [ + 'calculations' + ]; + + /** + * @var string|null + */ + private ?string $transactionHash; + + /** + * constructor. + */ + public function __construct() + { + parent::__construct(); + $this->_nicename = Helpers::exists() ? 'CryptoPay' : 'CryptoPay Lite'; + $this->_name = $this->_type = 'cryptopay'; + $this->_settings['default']['use_merge_tags'] = [ + 'include' => [ + 'calcs' + ], + 'exclude' => [ + 'form', + 'fields', + 'label' + ], + ]; + + $this->transactionHash = Session::get('ninjaforms_transaction_hash'); + + add_filter('ninja_forms_localize_field_' . $this->_type, [$this, 'loadScripts']); + } + + /** + * @param array $field + * @return array + */ + public function loadScripts(array $field): array + { + add_action('wp_footer', function (): void { + Helpers::run('addStyle', 'main.min.css'); + if (Helpers::exists()) { + Helpers::run('ksesEcho', (new Payment('ninjaforms'))->modal()); + } else { + Helpers::run('ksesEcho', (new PaymentLite('ninjaforms'))->modal()); + } + + wp_enqueue_script( + 'ninja-forms-cryptopay', + NINJA_FORMS_CRYPTOPAY_URL . 'assets/js/main.js', + ['jquery', 'wp-i18n', Helpers::run('getProp', 'mainJsKey')], + NINJA_FORMS_CRYPTOPAY_VERSION, + true + ); + + $paidTransaction = null; + + if ($this->transactionHash) { + $model = Helpers::run('getModelByAddon', 'ninjaforms'); + + $transaction = $model->findOneBy([ + 'hash' => $this->transactionHash, + ]); + + if ($transaction) { + $paidTransaction = [ + 'hash' => $transaction->getHash(), + 'formId' => $transaction->getParams()->get('formId'), + ]; + } + } + + wp_localize_script( + 'ninja-forms-cryptopay', + 'ninja_forms_field_cryptopay', + [ + 'paidTransaction' => $paidTransaction, + 'alreadyPaidMessage' => esc_html__('A payment has already been made for this form, but the form has not been sent. Therefore please only submit the form.', 'ninjaforms-cryptopay'), // phpcs:ignore + 'paymentCompletedMessage' => esc_html__('Payment completed successfully.', 'ninjaforms-cryptopay') + ] + ); + }); + + return $field; + } + + /** + * @param array $field + * @param array $data + * @return mixed + */ + public function validate($field, $data): mixed + { + $errors = parent::validate($field, $data); + if (!empty($errors)) { + return $errors; + } + + $message = esc_html__( + 'Payment is not verified. Sending form has been aborted.', + 'ninjaforms-cryptopay' + ); + + $transactionHash = $data['extra']['cryptopay_transaction_hash'] ?? ''; + $sTransactionHash = Session::get('ninjaforms_transaction_hash'); + + if ($sTransactionHash !== $transactionHash) { + return $message; + } + + $model = Helpers::run('getModelByAddon', 'ninjaforms'); + + $transaction = $model->findOneBy([ + 'hash' => $transactionHash, + ]); + + if (!$transaction) { + return $message; + } else { + Session::remove('ninjaforms_transaction_hash'); + return null; + } + } +} diff --git a/app/Gateway.php b/app/Gateway.php new file mode 100644 index 0000000..12578fd --- /dev/null +++ b/app/Gateway.php @@ -0,0 +1,46 @@ + + */ + // phpcs:ignore + protected $_settings = []; + + /** + * GatewayLite constructor. + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @param array $actionSettings + * @param string $formId + * @param array $data + * @return void + */ + // phpcs:ignore + public function process($actionSettings, $formId, $data): void + { + return; + } +} diff --git a/app/Loader.php b/app/Loader.php index 48af6b1..05aa74c 100644 --- a/app/Loader.php +++ b/app/Loader.php @@ -4,6 +4,10 @@ namespace BeycanPress\CryptoPay\NinjaForms; +use BeycanPress\CryptoPay\Integrator\Hook; +use BeycanPress\CryptoPay\Integrator\Helpers; +use BeycanPress\CryptoPay\Integrator\Session; + class Loader { /** @@ -11,5 +15,77 @@ class Loader */ public function __construct() { + Helpers::registerIntegration('ninjaforms'); + + Helpers::createTransactionPage( + esc_html__('Ninja Forms Transactions', 'ninjaforms-cryptopay'), + 'ninjaforms', + 10, + [], + ['orderId'] + ); + + Hook::addAction('payment_finished_ninjaforms', [$this, 'paymentFinished']); + Hook::addFilter('payment_redirect_urls_ninjaforms', [$this, 'paymentRedirectUrls']); + + add_filter('ninja_forms_register_fields', [$this, 'registerFields']); + add_filter('ninja_forms_field_template_file_paths', [$this, 'addTemplatePath']); + //add_filter('ninja_forms_register_payment_gateways', [$this, 'registerGateways']); + } + + /** + * @param object $data + * @return void + */ + public function paymentFinished(object $data): void + { + Session::set('ninjaforms_transaction_hash', $data->getHash()); + } + + /** + * @param object $data + * @return array + */ + public function paymentRedirectUrls(object $data): array + { + return [ + 'success' => '#success', + 'failed' => '#failed' + ]; + } + + /** + * @param array $fields + * @return array + */ + public function registerFields(array $fields): array + { + $field = new Field(); + $fields[$field->get_name()] = $field; + + return $fields; + } + + /** + * @param array $paths + * @return array + */ + public function addTemplatePath(array $paths): array + { + $paths[] = NINJA_FORMS_CRYPTOPAY_DIR . 'views/'; + + return $paths; + } + + /** + * @param array $gateways + * @return array + */ + public function registerGateways(array $gateways): array + { + $gateway = new Gateway(); + $gateways[$gateway->get_slug()] = $gateway; + + return $gateways; } } diff --git a/assets/js/main.js b/assets/js/main.js index e69de29..5cea844 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -0,0 +1,96 @@ +(($) => { + $(document).ready(() => { + const { + paidTransaction, + alreadyPaidMessage, + paymentCompletedMessage + } = ninja_forms_field_cryptopay; + const helpers = window.cpHelpers || window.cplHelpers + const app = window.CryptoPayApp || window.CryptoPayLiteApp + const modal = window.CryptoPayModal || window.CryptoPayLiteModal + + const order = {} + const params = {} + + let startedApp; + let notPaidYet = true; + + const getFormById = (formId) => { + return nfRadio.channel('app').request('get:form', formId); + } + + const submitForm = (formId) => { + const model = getFormById(formId); + nfRadio.channel('form-' + model.get('id')).request('submit', model); + } + + const addExtraData = (formId, key, value) => { + nfRadio.channel('form-' + formId).request('add:extra', key, value); + } + + app.events.add('confirmationCompleted', async ({transaction}) => { + modal.close(); + notPaidYet = false; + helpers.closePopup(); + await helpers.sleep(100); + $('.overlay').remove(); + addExtraData( + params.formId, + 'cryptopay_transaction_hash', + transaction.id || transaction.hash + ); + helpers.successPopup(paymentCompletedMessage) + submitForm(params.formId); + }) + + const formController = Marionette.Object.extend({ + initialize: function(e) { + this.listenTo(Backbone.Radio.channel('form'), 'render:view', this.registerHandlers); + }, + registerHandlers: function(e) { + const formId = e.model.get('id'); + if (paidTransaction && formId == paidTransaction.formId) { + addExtraData( + formId, + 'cryptopay_transaction_hash', + paidTransaction.hash + ); + const element = $('.nf-field-container.cryptopay-container'); + element.find('.nf-after-field').append(alreadyPaidMessage) + } else { + this.listenTo(Backbone.Radio.channel('fields'), 'change:model', this.fieldModelChange); + this.listenTo(Backbone.Radio.channel('forms'), 'after:submitValidation', this.validated); + Backbone.Radio.channel('form-' + formId).reply('maybe:submit', this.maybeSubmit, this, formId); + } + }, + fieldModelChange: function(model) { + if ('cryptopay' != model.get('type')) { + return; + } + + params.formId = model.get('formID'); + const form = getFormById(params.formId); + order.amount = parseFloat(model.attributes.value); + order.currency = form.get('settings').currency; + + if (startedApp) { + startedApp.reStart(order, params); + } else { + startedApp = app.start(order, params); + } + }, + maybeSubmit: function(event) { + if (notPaidYet && this.checkError(event)) { + modal.open(); + return false; + } + return true; + }, + checkError(event) { + return !event.attributes.errors.length && !Object.values(event.attributes.fieldErrors).length; + } + }); + + new formController(); + }); +})(jQuery); \ No newline at end of file diff --git a/languages/ninjaforms-cryptopay.pot b/languages/ninjaforms-cryptopay.pot new file mode 100644 index 0000000..5cbb80d --- /dev/null +++ b/languages/ninjaforms-cryptopay.pot @@ -0,0 +1,55 @@ +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Ninja Forms - CryptoPay Gateway\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-03-24 02:58+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: \n" +"Language: \n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Loco https://localise.biz/\n" +"X-Loco-Version: 2.6.7; wp-6.4.3\n" +"X-Domain: ninjaforms-cryptopay" + +#: app/Field.php:147 +msgid "" +"A payment has already been made for this form, but the form has not been " +"sent. Therefore please only submit the form." +msgstr "" + +#. Description of the plugin +msgid "Adds Cryptocurrency payment gateway (CryptoPay) for Ninja Forms." +msgstr "" + +#. Author of the plugin +msgid "BeycanPress LLC" +msgstr "" + +#. Author URI of the plugin +msgid "https://beycanpress.com" +msgstr "" + +#. URI of the plugin +msgid "https://beycanpress.com/cryptopay/" +msgstr "" + +#. Name of the plugin +msgid "Ninja Forms - CryptoPay Gateway" +msgstr "" + +#: app/Loader.php:21 +msgid "Ninja Forms Transactions" +msgstr "" + +#: app/Field.php:148 +msgid "Payment completed successfully." +msgstr "" + +#: app/Field.php:168 +msgid "Payment is not verified. Sending form has been aborted." +msgstr "" diff --git a/views/fields-cryptopay.html b/views/fields-cryptopay.html new file mode 100644 index 0000000..9fa0ee6 --- /dev/null +++ b/views/fields-cryptopay.html @@ -0,0 +1,8 @@ + + \ No newline at end of file