Plugin Directory

Changeset 3458758


Ignore:
Timestamp:
02/11/2026 08:20:41 AM (8 weeks ago)
Author:
coinsnap
Message:
  1. 1.0.2
Location:
coinsnap-bitcoin-invoice-form
Files:
52 added
13 edited

Legend:

Unmodified
Added
Removed
  • coinsnap-bitcoin-invoice-form/trunk/assets/css/admin.css

    r3439284 r3458758  
    22 * Bitcoin Invoice Form - Admin Styles
    33 */
     4
     5.coinsnapConnectionStatus{
     6    font-size:1.3em;
     7        font-weight: 600;
     8        margin-top:1em;
     9        margin-bottom:1em;
     10}
     11
     12.coinsnapConnectionStatus span:before {
     13    content:"";
     14    border-radius: 50%;
     15    display:inline-block;
     16    vertical-align: baseline;
     17    width:10px; height:10px;
     18    margin:0 5px 0 0;
     19}
     20
     21.coinsnapConnectionStatus span.error {
     22    color: #d63638;
     23}
     24
     25.coinsnapConnectionStatus span.error:before {
     26    background:#d63638;
     27}
     28
     29.coinsnapConnectionStatus span.success {
     30    color: #00a32a;
     31}
     32
     33.coinsnapConnectionStatus span.success:before {
     34    background:#00a32a;
     35}
     36
     37.button.btcpay-apikey-link {margin:10px 0;}
    438
    539/* General Admin Styles - matching wp-bitcoin-newsletter */
  • coinsnap-bitcoin-invoice-form/trunk/assets/js/admin.js

    r3439284 r3458758  
    4949        // Initialize other admin features
    5050        initAdminFeatures();
     51       
     52       
     53       
     54        $('#coinsnapbif_btcpay_wizard_button').click(function(e) {
     55        e.preventDefault();
     56        const host = $('#btcpay_url').val();
     57    if (isCoinsnapBIFValidUrl(host)) {
     58            let data = {
     59                'action': 'coinsnapbif_btcpay_apiurl_handler',
     60                'host': host,
     61                'apiNonce': coinsnapbif_ajax.nonce
     62            };
     63           
     64            $.post(coinsnapbif_ajax.ajax_url, data, function(response) {
     65                if (response.data.url) {
     66                    window.location = response.data.url;
     67        }
     68            }).fail( function() {
     69        alert('Error processing your request. Please make sure to enter a valid BTCPay Server instance URL.')
     70            });
     71    }
     72        else {
     73            alert('Please enter a valid url including https:// in the BTCPay Server URL input field.')
     74        }
    5175    });
     76   
     77    if($('#coinsnap_bitcoin_invoice_polls_currency').length){
     78       
     79        setStep();
     80        $('#coinsnap_bitcoin_invoice_polls_currency').change(
     81            function(){
     82                setStep();
     83            }   
     84        );
     85       
     86    }
     87   
     88    /*
     89    if($('.coinsnapConnectionStatus').length){
     90       
     91        console.log('Connection check is activated');
     92       
     93        let ajaxurl = coinsnapbif_ajax.ajax_url;
     94        let data = {
     95            action: 'coinsnapbif_connection_handler',
     96            apiNonce: coinsnapbif_ajax.nonce,
     97            apiPost: coinsnapbif_ajax.post
     98        };
     99
     100        jQuery.post( ajaxurl, data, function( response ){
     101
     102            var connectionCheckResponse = $.parseJSON(response);
     103            let resultClass = (connectionCheckResponse.result === true)? 'success' : 'error';
     104            $('.coinsnapConnectionStatus').html('<span class="'+resultClass+'">'+ connectionCheckResponse.message +'</span>');
     105           
     106        });
     107    }
     108    */
     109  });
     110 
     111  function setStep(){
     112        let step = 0.01;
     113        let currency = $('#coinsnap_bitcoin_invoice_polls_currency').val();
     114        if(currency === 'RUB' || currency === 'JPY' || currency === 'SATS'){
     115            step = 1;
     116        }
     117        $('#coinsnap_bitcoin_invoice_polls_amount').attr('step', step);
     118    }
     119 
     120    function isCoinsnapBIFValidUrl(serverUrl) {
     121        if(serverUrl.indexOf('http') > -1){
     122            try {
     123                const url = new URL(serverUrl);
     124                if (url.protocol !== 'https:' && url.protocol !== 'http:') {
     125                    return false;
     126                }
     127            }
     128            catch (e) {
     129                console.error(e);
     130                return false;
     131            }
     132            return true;
     133        }
     134        else {
     135            return false;
     136        }
     137    }
    52138
    53139    /**
  • coinsnap-bitcoin-invoice-form/trunk/coinsnap-bitcoin-invoice-form.php

    r3445785 r3458758  
    44 * Plugin URI:         https://coinsnap.io/modules/bitcoin-invoice/
    55 * Description:        Generate and embed customizable Bitcoin Invoice Forms on your website. Customers can complete and pay invoices directly on your site with payment processing via Coinsnap or BTCPay Server.
    6  * Version:            1.0.1
     6 * Version:            1.0.2
    77 * Author:             Coinsnap
    88 * Author URI:         https://coinsnap.io/
     
    2525
    2626if(!defined('COINSNAPBIF_REFERRAL_CODE' ) ) { define( 'COINSNAPBIF_REFERRAL_CODE', 'D85536' );}
    27 if(!defined('COINSNAPBIF_VERSION' ) ) { define( 'COINSNAPBIF_VERSION', '1.0.1' );}
     27if(!defined('COINSNAPBIF_VERSION' ) ) { define( 'COINSNAPBIF_VERSION', '1.0.2' );}
    2828if(!defined('COINSNAPBIF_PHP_VERSION' ) ) { define( 'COINSNAPBIF_PHP_VERSION', '7.4' );}
    2929if(!defined('COINSNAP_CURRENCIES')){define( 'COINSNAP_CURRENCIES', array("EUR","USD","SATS","BTC","CAD","JPY","GBP","CHF","RUB") );}
  • coinsnap-bitcoin-invoice-form/trunk/readme.txt

    r3445785 r3458758  
    44Tags: Lightning, bitcoin, invoice form, BTCPay
    55Tested up to: 6.9
    6 Stable tag: 1.0.1
     6Stable tag: 1.0.2
    77License: GPL2
    88License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    235235* Updated plugin URI.
    236236* Updated default field labels for invoice form.
     237
     238= 1.0.2 :: 2026-02-11 =
     239* Update: added Coinsnap and BTCPay server connection check in admin.
     240* Update: added webhook check and registration functionality.
     241* Fixed: payment provider override functionality for a specific form.
  • coinsnap-bitcoin-invoice-form/trunk/src/Admin/class-coinsnapbif-admin-settings.php

    r3439284 r3458758  
    1919class CoinsnapBIF_Admin_Settings {
    2020    public const OPTION_KEY = 'bif_settings';
     21        public const WEBHOOK_KEY = 'coinsnapbif_webhook';
    2122
    2223    /** Register hooks to initialize settings. */
     
    2425        add_action( 'admin_init', array( __CLASS__, 'register_settings' ) );
    2526    }
    26 
    27     /**
     27       
     28        /**
    2829     * Get merged settings with defaults.
    2930     *
     
    257258        echo '<form method="post" action="options.php">';
    258259        settings_fields( 'coinsnapbif_settings_group' );
     260               
     261                echo '<div class="coinsnapConnectionStatus"></div>';
    259262
    260263        // Render general settings section
  • coinsnap-bitcoin-invoice-form/trunk/src/Admin/class-coinsnapbif-admin-transactions-page.php

    r3439284 r3458758  
    3636
    3737        $table_name = Installer::table_name();
    38         $per_page   = 5;
     38        $per_page   = 10;
    3939        $_paged = filter_input(INPUT_GET,'paged',FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    4040        $_nonce = filter_input(INPUT_GET,'_wpnonce',FILTER_SANITIZE_FULL_SPECIAL_CHARS);
  • coinsnap-bitcoin-invoice-form/trunk/src/Providers/Payment/class-btcpayprovider.php

    r3439284 r3458758  
    2121 */
    2222class BTCPayProvider implements PaymentProviderInterface {
    23     /**
     23   
     24    /**
     25     * Get store data from BTCPay server
     26     *
     27     * @param void.
     28     * @return array().
     29     */
     30    public function get_store(): array {
     31        //  BTCPay server connection credentials check
     32       
     33        $s = Settings::get_settings();
     34        $host = rtrim( (string) $s['btcpay_host'], '/' );
     35    $api_key = (string) $s['btcpay_api_key'];
     36    $store   = (string) $s['btcpay_store_id'];
     37   
     38        if ( ! $host || ! $api_key || ! $store ) {
     39            return array('error' => true,'message'=>__('Connection credentials error','coinsnap-bitcoin-invoice-form'));
     40        }
     41       
     42        $url = $host . sprintf( CoinsnapBIF_Constants::BTCPAY_STORE_ENDPOINT, rawurlencode( $store ) );
     43               
     44        $args = array(
     45            'method'  => 'GET',
     46            'headers' => array(
     47                'Authorization' => 'token ' . $api_key,
     48                'Content-Type'  => 'application/json',
     49            ),
     50            'timeout' => 20
     51        );
     52       
     53        $res = wp_remote_request( $url, $args );
     54               
     55        if ( is_wp_error( $res ) ) {
     56            return array('error' => true,'message'=>__('Store data error','coinsnap-bitcoin-invoice-form'));
     57        }
     58               
     59        $code = wp_remote_retrieve_response_code( $res );
     60        $result = json_decode( wp_remote_retrieve_body( $res ), true );
     61        if ( $code >= 200 && $code < 300 && is_array($result) ) {
     62            return ['code' => $code, 'result' => $result];
     63        }
     64        else {
     65            return array('error' => true,'message'=>__('BTCPay server request error','coinsnap-bitcoin-invoice-form'));
     66        }
     67    }
     68   
     69   
     70    /**
     71     * Check existing webhook on BTCPay server.
     72     *
     73     * @param void.
     74     * @return bool.
     75     */
     76    public function check_webhook(): bool {
     77       
     78        $webhookExists = false;
     79        $s = Settings::get_settings();
     80           
     81        //  BTCPay server connection credentials check
     82       
     83        $host = rtrim( (string) $s['btcpay_host'], '/' );
     84    $api_key = (string) $s['btcpay_api_key'];
     85    $store   = (string) $s['btcpay_store_id'];
     86        $webhook_url = rtrim( (string) get_home_url(), '/' )  . '/wp-json/' . CoinsnapBIF_Constants::REST_NAMESPACE . CoinsnapBIF_Constants::REST_ROUTE_WEBHOOK_BTCPAY;
     87   
     88        if ( ! $host || ! $api_key || ! $store ) {
     89            return false;
     90        }
     91               
     92        if ($storedWebhook = get_option(Settings::WEBHOOK_KEY)['btcpay']) {
     93           
     94            $url     = $host . sprintf( CoinsnapBIF_Constants::BTCPAY_WEBHOOKS_ENDPOINT, rawurlencode( $store ) );
     95               
     96            $args    = array(
     97                'method'  => 'GET',
     98                'headers' => array(
     99                    'Authorization' => 'token ' . $api_key,
     100                    'Content-Type'  => 'application/json',
     101                ),
     102                'timeout' => 20,
     103            );
     104       
     105            $res     = wp_remote_request( $url, $args );
     106               
     107            if ( is_wp_error( $res ) ) {
     108                return false;
     109            }
     110               
     111            $code = wp_remote_retrieve_response_code( $res );
     112            $storeWebhooks = json_decode( wp_remote_retrieve_body( $res ), true );
     113            if ( $code >= 200 && $code < 300 && is_array($storeWebhooks) ) {
     114       
     115            //  Registered webhooks analysis   
     116                foreach($storeWebhooks as $webhook){
     117                   
     118                //  If webhook is registered this site   
     119                    if(strpos( $webhook['url'], $webhook_url ) !== false){
     120                       
     121                        //  Return TRUE if stored webhook ID equals registered webhook ID
     122                        if($webhook['id'] === $storedWebhook['id']){
     123                            $webhookExists = true;
     124                        }
     125                       
     126                        //  If not - we delete this webhook from server
     127                        else {
     128                           
     129                            $url     = $host . sprintf( CoinsnapBIF_Constants::BTCPAY_WEBHOOKS_ENDPOINT, rawurlencode( $store ) ) . '/' . $webhook['id'];
     130                            $args    = array(
     131                                'method'  => 'DELETE',
     132                                'headers' => array(
     133                                    'Authorization' => 'token ' . $api_key,
     134                                    'Content-Type'  => 'application/json',
     135                                ),
     136                                'timeout' => 20,
     137                            );
     138                            $res     = wp_remote_request( $url, $args );
     139                            $code = wp_remote_retrieve_response_code( $res );
     140                            if ($code !== 204 && $code !== 200) {
     141                               
     142                            }
     143                        }
     144                    }
     145                }
     146                   
     147                return $webhookExists;
     148            }
     149            return false;
     150        }
     151        else {
     152            return false;
     153        }
     154    }
     155   
     156    /**
     157     * Webhook registration on BTCPay Server.
     158     *
     159     * @param void.
     160     * @return array { id: string, secret: string, url: string }
     161     */
     162    public function register_webhook(): array {
     163       
     164        //  BTCPay server connection credentials check
     165       
     166        $s = Settings::get_settings();
     167        $host = rtrim( (string) $s['btcpay_host'], '/' );
     168    $api_key = (string) $s['btcpay_api_key'];
     169    $store   = (string) $s['btcpay_store_id'];
     170        $webhook_url = rtrim( (string) get_home_url(), '/' )  . '/wp-json/' . CoinsnapBIF_Constants::REST_NAMESPACE . CoinsnapBIF_Constants::REST_ROUTE_WEBHOOK_BTCPAY;
     171   
     172        if ( ! $host || ! $api_key || ! $store ) {
     173            return array('error' => true,'message'=>__('Connection credentials error','coinsnap-bitcoin-invoice-form'));
     174        }
     175       
     176        $data = [
     177            'url' => $webhook_url,
     178            'authorizedEvents' => ['everything' => false,'specificEvents' => ['InvoiceCreated','InvoiceExpired','InvoiceSettled','InvoiceProcessing']],
     179        ];
     180       
     181        $url = $host . sprintf( CoinsnapBIF_Constants::BTCPAY_WEBHOOKS_ENDPOINT, rawurlencode( $store ) );
     182               
     183        $args = array(
     184            'method'  => 'POST',
     185            'headers' => array(
     186                'Authorization' => 'token ' . $api_key,
     187                'Content-Type'  => 'application/json',
     188            ),
     189            'timeout' => 20,
     190            'body'    => wp_json_encode($data)
     191        );
     192       
     193        $res = wp_remote_request( $url, $args );
     194               
     195        if ( is_wp_error( $res ) ) {
     196            return array('error' => true,'message'=>__('Webhook creation error','coinsnap-bitcoin-invoice-form'));
     197        }
     198               
     199        $code = wp_remote_retrieve_response_code( $res );
     200        $result = json_decode( wp_remote_retrieve_body( $res ), true );
     201        if ( $code >= 200 && $code < 300 && is_array($result) ) {
     202            return ['code' => $code, 'result' => $result];
     203        }
     204        else {
     205            return array('error' => true,'message'=>__('BTCPay server request error','coinsnap-bitcoin-invoice-form'),'code' => $code, 'result' => $result);
     206        }
     207   
     208    }
     209   
     210        /**
    24211     * Create a payment invoice.
    25212     *
  • coinsnap-bitcoin-invoice-form/trunk/src/Providers/Payment/class-coinsnapprovider.php

    r3445785 r3458758  
    2222 */
    2323class CoinsnapProvider implements PaymentProviderInterface {
    24     /**
     24   
     25    /**
     26     * Get store data from Coinsnap server
     27     *
     28     * @param void.
     29     * @return array().
     30     */
     31    public function get_store(): array {
     32        //  Coinsnap server connection credentials check
     33       
     34        $settings = Settings::get_settings();
     35        $api_base = rtrim( $settings['coinsnap_api_base'] ? $settings['coinsnap_api_base'] : CoinsnapBIF_Constants::COINSNAP_DEFAULT_API_BASE, '/' );
     36    $api_key = (string) $settings['coinsnap_api_key'];
     37    $store   = (string) $settings['coinsnap_store_id'];
     38       
     39   
     40        if ( ! $api_base || ! $api_key || ! $store ) {
     41            return array('error' => true,'message'=>__('Connection credentials error','coinsnap-bitcoin-invoice-form'));
     42        }
     43       
     44        $url = $api_base . sprintf( CoinsnapBIF_Constants::COINSNAP_STORE_ENDPOINT_V1, rawurlencode( $store ) );
     45               
     46        $args = array(
     47            'method'  => 'GET',
     48            'headers' => array(
     49                'X-Api-Key'     => $api_key,
     50                'Authorization' => 'token ' . $api_key,
     51                'Content-Type'  => 'application/json',
     52                'accept'        => 'application/json',
     53            ),
     54            'timeout' => 20
     55        );
     56       
     57        $res = wp_remote_request( $url, $args );
     58               
     59        if ( is_wp_error( $res ) ) {
     60            return array('error' => true,'message'=>__('Store data error','coinsnap-bitcoin-invoice-form'));
     61        }
     62               
     63        $code = wp_remote_retrieve_response_code( $res );
     64        $result = json_decode( wp_remote_retrieve_body( $res ), true );
     65        if ( $code >= 200 && $code < 300 && is_array($result) ) {
     66            return ['code' => $code, 'result' => $result];
     67        }
     68        else {
     69            return array('error' => true,'message'=>__('Coinsnap server request error','coinsnap-bitcoin-invoice-form'));
     70        }
     71    }
     72   
     73   
     74    /**
     75     * Check existing webhook on Coinsnap server.
     76     *
     77     * @param void.
     78     * @return bool.
     79     */
     80    public function check_webhook(): bool {
     81       
     82        $webhookExists = false;
     83        $settings = Settings::get_settings();
     84           
     85        //  Coinsnap server connection credentials check
     86       
     87        $api_base = rtrim( $settings['coinsnap_api_base'] ? $settings['coinsnap_api_base'] : CoinsnapBIF_Constants::COINSNAP_DEFAULT_API_BASE, '/' );
     88    $api_key = (string) $settings['coinsnap_api_key'];
     89    $store   = (string) $settings['coinsnap_store_id'];
     90        $webhook_url = $api_base . sprintf( CoinsnapBIF_Constants::COINSNAP_WEBHOOKS_ENDPOINT_V1, rawurlencode( $store ) ) . '/' . $webhook['id'];
     91   
     92        if ( ! $api_base || ! $api_key || ! $store ) {
     93            return false;
     94        }
     95               
     96        if ($storedWebhook = get_option(Settings::WEBHOOK_KEY)['coinsnap']) {
     97               
     98           
     99           
     100            $url     = $api_base . sprintf( CoinsnapBIF_Constants::COINSNAP_WEBHOOKS_ENDPOINT_V1, rawurlencode( $store ) );
     101               
     102            $args    = array(
     103                'method'  => 'GET',
     104                'headers' => array(
     105                    'X-Api-Key'     => $api_key,
     106                'Authorization' => 'token ' . $api_key,
     107                'Content-Type'  => 'application/json',
     108                'accept'        => 'application/json',
     109                ),
     110                'timeout' => 20,
     111            );
     112       
     113            $res     = wp_remote_request( $url, $args );
     114               
     115            if ( is_wp_error( $res ) ) {
     116                return false;
     117            }
     118               
     119            $code = wp_remote_retrieve_response_code( $res );
     120            $storeWebhooks = json_decode( wp_remote_retrieve_body( $res ), true );
     121            if ( $code >= 200 && $code < 300 && is_array($storeWebhooks) ) {
     122       
     123            //  Registered webhooks analysis   
     124                foreach($storeWebhooks as $webhook){
     125                   
     126                //  If webhook is registered this site   
     127                    if(strpos( $webhook['url'], $webhook_url ) !== false){
     128                       
     129                        //  Return TRUE if stored webhook ID equals registered webhook ID
     130                        if($webhook['id'] === $storedWebhook['id']){
     131                            $webhookExists = true;
     132                        }
     133                       
     134                        //  If not - we delete this webhook from server
     135                        else {
     136                           
     137                            $url     = $webhook_url;
     138                            $args    = array(
     139                                'method'  => 'DELETE',
     140                                'headers' => array(
     141                                    'X-Api-Key'     => $api_key,
     142                'Authorization' => 'token ' . $api_key,
     143                'Content-Type'  => 'application/json',
     144                'accept'        => 'application/json',
     145                                ),
     146                                'timeout' => 20,
     147                            );
     148                            $res     = wp_remote_request( $url, $args );
     149                            $code = wp_remote_retrieve_response_code( $res );
     150                            if ($code !== 204 && $code !== 200) {
     151                               
     152                            }
     153                        }
     154                    }
     155                }
     156                   
     157                return $webhookExists;
     158            }
     159            return false;
     160        }
     161        else {
     162            return false;
     163        }
     164    }
     165   
     166    /**
     167     * Webhook registration on Coinsnap Server.
     168     *
     169     * @param void.
     170     * @return array { id: string, secret: string, url: string }
     171     */
     172    public function register_webhook(): array {
     173       
     174        //  Coinsnap server connection credentials check
     175       
     176        $settings = Settings::get_settings();
     177        $api_base = rtrim( $settings['coinsnap_api_base'] ? $settings['coinsnap_api_base'] : CoinsnapBIF_Constants::COINSNAP_DEFAULT_API_BASE, '/' );
     178    $api_key = (string) $settings['coinsnap_api_key'];
     179    $store   = (string) $settings['coinsnap_store_id'];
     180        $webhook_url = $api_base . sprintf( CoinsnapBIF_Constants::COINSNAP_WEBHOOKS_ENDPOINT_V1, rawurlencode( $store ) ) . '/' . $webhook['id'];
     181   
     182        if ( ! $api_base || ! $api_key || ! $store ) {
     183            return array('error' => true,'message'=>__('Connection credentials error','coinsnap-bitcoin-invoice-form'));
     184        }
     185       
     186        $data = [
     187            'url' => $webhook_url,
     188            'authorizedEvents' => ['everything' => false,'specificEvents' => ['New','Expired','Settled','Processing']],
     189        ];
     190       
     191        $url = $api_base . sprintf( CoinsnapBIF_Constants::COINSNAP_WEBHOOKS_ENDPOINT_V1, rawurlencode( $store ) );
     192               
     193        $args = array(
     194            'method'  => 'POST',
     195            'headers' => array(
     196                'X-Api-Key'     => $api_key,
     197                'Authorization' => 'token ' . $api_key,
     198                'Content-Type'  => 'application/json',
     199                'accept'        => 'application/json',
     200            ),
     201            'timeout' => 20,
     202            'body'    => wp_json_encode($data)
     203        );
     204       
     205        $res = wp_remote_request( $url, $args );
     206               
     207        if ( is_wp_error( $res ) ) {
     208            return array('error' => true,'message'=>__('Webhook creation error','coinsnap-bitcoin-invoice-form'));
     209        }
     210               
     211        $code = wp_remote_retrieve_response_code( $res );
     212        $result = json_decode( wp_remote_retrieve_body( $res ), true );
     213        if ( $code >= 200 && $code < 300 && is_array($result) ) {
     214            return ['code' => $code, 'result' => $result];
     215        }
     216        else {
     217            return array('error' => true,'message'=>__('Coinsnap server request error','coinsnap-bitcoin-invoice-form'),'code' => $code, 'result' => $result);
     218        }
     219   
     220    }
     221   
     222   
     223    /**
    25224     * Create a payment invoice.
    26225     *
  • coinsnap-bitcoin-invoice-form/trunk/src/Providers/Payment/class-paymentproviderinterface.php

    r3439284 r3458758  
    4040     */
    4141    public function check_invoice_status( string $invoice_id ): array;
     42       
     43        /**
     44     * Check webhook.
     45     *
     46     * @return bool
     47     */
     48    public function check_webhook(): bool;
     49       
     50        /**
     51     * Webhook registration.
     52     *
     53     * @return array
     54     */
     55    public function register_webhook(): array;
     56       
     57        /**
     58     * Getting Store data.
     59     *
     60     * @return array
     61     */
     62    public function get_store(): array;
    4263}
  • coinsnap-bitcoin-invoice-form/trunk/src/Services/class-coinsnapbif-services-payment-service.php

    r3445785 r3458758  
    1313use CoinsnapBIF\Util\CoinsnapBIF_Logger;
    1414use CoinsnapBIF\Util\CoinsnapBIF_Util_Provider_Factory;
    15 use CoinsnapBIF\Admin\CoinsnapBIF_Admin_Settings;
     15use CoinsnapBIF\Admin\CoinsnapBIF_Admin_Settings as Settings;
    1616
    1717if ( ! defined( 'ABSPATH' ) ) {
     
    226226                    'currency'           => $currency,
    227227                    'description'        => $invoice_data['description'],
    228                     'payment_provider'   => $payment_config['provider_override'] ?? CoinsnapBIF_Admin_Settings::get_settings()['payment_provider'],
     228                    'payment_provider'   => (!empty($payment_config['provider_override']))? $payment_config['provider_override'] : Settings::get_settings()['payment_provider'],
    229229                    'payment_invoice_id' => $payment_result['invoice_id'],
    230230                    'payment_url'        => $payment_result['payment_url'] ?? '',
  • coinsnap-bitcoin-invoice-form/trunk/src/Util/class-coinsnapbif-util-provider-factory.php

    r3439284 r3458758  
    2929     * @return PaymentProviderInterface Provider instance.
    3030     */
    31     public static function payment_for_form( $form_id ): PaymentProviderInterface {
     31    public static function payment_for_form( $form_id = 0 ): PaymentProviderInterface {
    3232        // Ensure we always work with an integer ID.
    3333        $form_id = (int) $form_id;
    3434
    3535        $settings = Settings::get_settings();
    36         $payment  = get_post_meta( $form_id, '_bif_payment', true );
    37         $override = is_array( $payment ) && ! empty( $payment['provider_override'] ) ? $payment['provider_override'] : '';
    38         $key      = $override ? $override : $settings['payment_provider'];
     36               
     37                if($form_id > 0){
     38                    $payment  = get_post_meta( $form_id, '_coinsnapbif_payment', true );
     39                    $override = (is_array( $payment ) && ! empty( $payment['provider_override'] )) ? $payment['provider_override'] : '';
     40                }
     41       
     42        $key      = (isset($override) && !empty($override)) ? $override : $settings['payment_provider'];
    3943        switch ( $key ) {
    4044            case 'btcpay':
  • coinsnap-bitcoin-invoice-form/trunk/src/class-coinsnapbif-constants.php

    r3439284 r3458758  
    2424    /** CoinSnap endpoints (relative to API base). */
    2525    public const COINSNAP_DEFAULT_API_BASE      = 'https://app.coinsnap.io';
     26    public const COINSNAP_STORE_ENDPOINT_V1 = '/api/v1/stores/%s';
    2627    public const COINSNAP_INVOICES_ENDPOINT_V1  = '/api/v1/stores/%s/invoices';
    2728    public const COINSNAP_INVOICES_ENDPOINT_ALT = '/api/stores/%s/invoices';
     29        public const COINSNAP_WEBHOOKS_ENDPOINT_V1 = '/api/v1/stores/%s/webhooks';
    2830
    2931    /** CoinSnap API header names. */
     
    3133
    3234    /** BTCPay endpoint (relative to host). */
    33     public const BTCPAY_INVOICES_ENDPOINT = '/api/v1/stores/%s/invoices';
     35    public const BTCPAY_STORE_ENDPOINT = '/api/v1/stores/%s';
     36        public const BTCPAY_INVOICES_ENDPOINT = '/api/v1/stores/%s/invoices';
     37        public const BTCPAY_WEBHOOKS_ENDPOINT = '/api/v1/stores/%s/webhooks';
    3438
    3539    /** DB table suffixes. */
  • coinsnap-bitcoin-invoice-form/trunk/src/class-coinsnapbif-plugin.php

    r3439284 r3458758  
    1616use CoinsnapBIF\Admin\CoinsnapBIF_Admin_Logs_Page as LogsPage;
    1717use CoinsnapBIF\Rest\CoinsnapBIF_Rest_Routes as RestRoutes;
     18use CoinsnapBIF\Util\CoinsnapBIF_Util_Provider_Factory;
    1819use CoinsnapBIF\Util\CoinsnapBIF_Logger;
    1920use CoinsnapBIF\CoinsnapBIF_Constants;
     
    2728 */
    2829class CoinsnapBIF_Plugin {
    29     /**
    30      * Singleton instance.
    31      *
    32      * @var CoinsnapBIF_Plugin|null
    33      */
    34     private static $instance;
    35 
    36     /**
    37      * Get singleton instance.
    38      *
    39      * @return CoinsnapBIF_Plugin
    40      */
    41     public static function instance(): CoinsnapBIF_Plugin {
    42         if ( ! self::$instance ) {
    43             self::$instance = new self();
    44         }
    45         return self::$instance;
    46     }
    47 
    48     /**
    49      * Register hooks on load.
    50      */
    51     public function boot(): void {
    52         // Initialize logger first.
    53         CoinsnapBIF_Logger::init();
    54 
    55         add_action( 'init', array( InvoiceFormPostType::class, 'register' ) );
    56         add_action( 'init', array( InvoiceFormShortcode::class, 'register' ) );
    57 
    58         add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
    59         AdminSettings::register();
    60         TransactionsPage::register();
    61         LogsPage::register();
    62         add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
    63 
    64         add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend' ) );
    65         add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin' ) );
    66     }
    67 
    68     /**
    69      * Register admin menus and submenus.
    70      */
    71     public function register_admin_menu(): void {
     30    /**
     31     * Singleton instance.
     32     *
     33     * @var CoinsnapBIF_Plugin|null
     34     */
     35    private static $instance;
     36
     37    /**
     38     * Get singleton instance.
     39     *
     40     * @return CoinsnapBIF_Plugin
     41     */
     42    public static function instance(): CoinsnapBIF_Plugin {
     43        if ( ! self::$instance ) {
     44            self::$instance = new self();
     45    }
     46        return self::$instance;
     47    }
     48
     49    /**
     50     * Register hooks on load.
     51     */
     52    public function boot(): void {
     53        // Initialize logger first.
     54    CoinsnapBIF_Logger::init();
     55
     56    add_action( 'init', array( InvoiceFormPostType::class, 'register' ) );
     57    add_action( 'init', array( InvoiceFormShortcode::class, 'register' ) );
     58       
     59        if (is_admin()) {
     60            add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
     61            add_action('admin_notices', array($this, 'coinsnapbif_notice'));
     62            add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin' ) );
     63            add_action('wp_ajax_coinsnapbif_btcpay_apiurl_handler', [$this, 'btcpayApiUrlHandler']);
     64            add_action('wp_ajax_coinsnapbif_connection_handler', [$this, 'coinsnapConnectionHandler']);
     65        }
     66   
     67    AdminSettings::register();
     68    TransactionsPage::register();
     69    LogsPage::register();
     70    add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
     71    add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend' ) );
     72   
     73    }
     74   
     75    public function coinsnapbif_notice(string $hook){
     76       
     77        $post_id = (filter_input(INPUT_GET,'post',FILTER_SANITIZE_FULL_SPECIAL_CHARS ))? filter_input(INPUT_GET,'post',FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : 0;
     78        $post_type = (filter_input(INPUT_GET,'post_type',FILTER_SANITIZE_FULL_SPECIAL_CHARS ))? filter_input(INPUT_GET,'post_type',FILTER_SANITIZE_FULL_SPECIAL_CHARS ) :
     79            ((!empty($post_id))? get_post_type($post_id) : '');
     80        $page = (filter_input(INPUT_GET,'page',FILTER_SANITIZE_FULL_SPECIAL_CHARS ))? filter_input(INPUT_GET,'page',FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : '';
     81       
     82        if(stripos($page,'coinsnapbif') !== false || stripos($post_type,'coinsnapbif') !== false){
     83       
     84            $coinsnap_url = $this->getApiUrl();
     85            $coinsnap_api_key = $this->getApiKey();
     86            $coinsnap_store_id = $this->getStoreId();
     87            $coinsnap_provider = ($this->getPaymentProvider() === 'btcpay')? 'BTCPay server' : 'Coinsnap';
     88               
     89            if(!isset($coinsnap_url) || empty($coinsnap_url)){
     90                    echo '<div class="notice notice-error"><p>';
     91                    esc_html_e('Bitcoin Invoice Form: Server URL is not set', 'coinsnap-bitcoin-invoice-form');
     92                    echo '</p></div>';
     93            }
     94
     95            if(!isset($coinsnap_store_id) || empty($coinsnap_store_id)){
     96                    echo '<div class="notice notice-error"><p>';
     97                    esc_html_e('Bitcoin Invoice Form: Store ID is not set', 'coinsnap-bitcoin-invoice-form');
     98                    echo '</p></div>';
     99            }
     100
     101            if(!isset($coinsnap_api_key) || empty($coinsnap_api_key)){
     102                    echo '<div class="notice notice-error"><p>';
     103                    esc_html_e('Bitcoin Invoice Form: API Key is not set', 'coinsnap-bitcoin-invoice-form');
     104                    echo '</p></div>';
     105            }
     106               
     107            if(!empty($coinsnap_url) && !empty($coinsnap_api_key) && !empty($coinsnap_store_id)){
     108               
     109                // Create payment provider and get store data
     110                $payment_provider = CoinsnapBIF_Util_Provider_Factory::payment_for_form( $form_id );
     111                $store = $payment_provider->get_store();
     112               
     113                try {
     114                    if ($store['code'] === 200){
     115                        echo '<div class="notice notice-success"><p>';
     116                        esc_html_e('Bitcoin Invoice Form: Established connection to ', 'coinsnap-bitcoin-invoice-form');
     117                        echo esc_html($coinsnap_provider);
     118                        echo '</p></div>';
     119
     120                        if ( !$payment_provider->check_webhook() ) {
     121
     122                            $register_webhook_result = $payment_provider->register_webhook();
     123
     124                            if (isset($register_webhook_result['error'])) {
     125                                    echo '<div class="notice notice-error"><p>';
     126                                    esc_html_e('Bitcoin Invoice Form: Unable to create webhook on ', 'coinsnap-bitcoin-invoice-form');
     127                                    echo esc_html($coinsnap_provider);
     128                                    echo '</p></div>';
     129                            }
     130                            else {
     131                                $stored_webhook = get_option(AdminSettings::WEBHOOK_KEY, []);
     132                                $stored_webhook[$this->getPaymentProvider()] = [
     133                                        'id' => $register_webhook_result['result']['id'],
     134                                        'secret' => $register_webhook_result['result']['secret'],
     135                                        'url' => $register_webhook_result['result']['url']
     136                                    ];
     137
     138                                update_option(AdminSettings::WEBHOOK_KEY,$stored_webhook);
     139
     140                                echo '<div class="notice notice-success"><p>';
     141                                    esc_html_e('Bitcoin Invoice Form: Successfully registered a new webhook on ', 'coinsnap-bitcoin-invoice-form');
     142                                    echo esc_html($coinsnap_provider);
     143                                    echo '</p></div>';
     144                            }
     145                        }
     146                        else {
     147                                echo '<div class="notice notice-info"><p>';
     148                                esc_html_e('Bitcoin Invoice Form: Webhook already exists, skipping webhook creation', 'coinsnap-bitcoin-invoice-form');
     149                                echo '</p></div>';
     150                        }
     151                    }
     152                }
     153                catch (\Exception $e) {
     154                    echo '<div class="notice notice-error"><p>';
     155                    esc_html_e('Bitcoin Invoice Form: API connection is not established', 'coinsnap-bitcoin-invoice-form');
     156                    echo '</p></div>';
     157                }
     158            }
     159        }
     160    }
     161       
     162    public function btcpayApiUrlHandler(){
     163           
     164    }
     165       
     166    public function coinsnapConnectionHandler(){
     167       
     168        $_nonce = filter_input(INPUT_POST,'apiNonce',FILTER_SANITIZE_FULL_SPECIAL_CHARS);
     169        if ( !wp_verify_nonce( $_nonce, 'coinsnap-ajax-nonce' ) ) {
     170            wp_die('Unauthorized!', '', ['response' => 401]);
     171        }
     172       
     173        $response = [
     174            'result' => false,
     175            'message' => __('Coinsnap Bitcoin Invoice Form: Empty gateway URL or API Key', 'coinsnap-bitcoin-invoice-form')
     176        ];
     177       
     178       
     179        $_provider = $this->getPaymentProvider();
     180        $post_id = ('' !== filter_input(INPUT_POST,'apiPost',FILTER_SANITIZE_FULL_SPECIAL_CHARS))? filter_input(INPUT_POST,'apiPost',FILTER_SANITIZE_FULL_SPECIAL_CHARS) : 0;
     181       
     182        if($post_id > 0){
     183            $meta_payment = get_post_meta($post_id, '_coinsnapbif_payment', true);
     184            $currency = $meta_payment['currency'];
     185        }
     186        else {
     187            $currency = 'EUR';
     188        }
     189       
     190       
     191        /*
     192       
     193        $client = new Coinsnap_Paywall_Client();
     194       
     195        if($_provider === 'btcpay'){
     196            try {
     197               
     198                $storePaymentMethods = $client->getStorePaymentMethods($this->getApiUrl(), $this->getApiKey(), $this->getStoreId());
     199
     200                if ($storePaymentMethods['code'] === 200) {
     201                    if($storePaymentMethods['result']['onchain'] && !$storePaymentMethods['result']['lightning']){
     202                        $checkInvoice = $client->checkPaymentData(0,$currency,'bitcoin','calculation');
     203                    }
     204                    elseif($storePaymentMethods['result']['lightning']){
     205                        $checkInvoice = $client->checkPaymentData(0,$currency,'lightning','calculation');
     206                    }
     207                }
     208            }
     209            catch (\Exception $e) {
     210                $response = [
     211                        'result' => false,
     212                        'message' => __('Coinsnap Bitcoin Paywall: API connection is not established', 'coinsnap-bitcoin-invoice-form')
     213                ];
     214                $this->sendJsonResponse($response);
     215            }
     216        }
     217        else {
     218            $checkInvoice = $client->checkPaymentData(0,$currency,'coinsnap','calculation');
     219        }
     220       
     221        if(isset($checkInvoice) && $checkInvoice['result']){
     222            $connectionData = __('Min order amount is', 'coinsnap-bitcoin-invoice-form') .' '. $checkInvoice['min_value'].' '.$currency;
     223        }
     224        else {
     225            $connectionData = __('No payment method is configured', 'coinsnap-bitcoin-invoice-form');
     226        }
     227       
     228        $_message_disconnected = ($_provider !== 'btcpay')?
     229            __('Coinsnap Bitcoin Paywall: Coinsnap server is disconnected', 'coinsnap-bitcoin-invoice-form') :
     230            __('Coinsnap Bitcoin Paywall: BTCPay server is disconnected', 'coinsnap-bitcoin-invoice-form');
     231        $_message_connected = ($_provider !== 'btcpay')?
     232            __('Coinsnap Bitcoin Paywall: Coinsnap server is connected', 'coinsnap-bitcoin-invoice-form') :
     233            __('Coinsnap Bitcoin Paywall: BTCPay server is connected', 'coinsnap-bitcoin-invoice-form');
     234       
     235        if( wp_verify_nonce($_nonce,'coinsnap-ajax-nonce') ){
     236            $response = ['result' => false,'message' => $_message_disconnected];
     237
     238            try {
     239                $this_store = $client->getStore($this->getApiUrl(), $this->getApiKey(), $this->getStoreId());
     240               
     241                if ($this_store['code'] !== 200) {
     242                    $this->sendJsonResponse($response);
     243                }
     244               
     245                else {
     246                    $response = ['result' => true,'message' => $_message_connected.' ('.$connectionData.')'];
     247                    $this->sendJsonResponse($response);
     248                }
     249            }
     250            catch (\Exception $e) {
     251                $response['message'] =  __('Coinsnap Bitcoin Paywall: API connection is not established', 'coinsnap-bitcoin-invoice-form');
     252            }
     253
     254            $this->sendJsonResponse($response);
     255        }   
     256       
     257         */   
     258        $this->sendJsonResponse($response);
     259    }
     260   
     261    public function sendJsonResponse(array $response): void {
     262        echo wp_json_encode($response);
     263        exit();
     264    }
     265       
     266    private function getPaymentProvider() {
     267        $coinsnapbif_options = get_option('bif_settings', []);
     268        $form_id = (filter_input(INPUT_GET,'post',FILTER_SANITIZE_FULL_SPECIAL_CHARS ))? filter_input(INPUT_GET,'post',FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : 0;
     269       
     270        if($form_id > 0){
     271            $payment  = get_post_meta( $form_id, '_coinsnapbif_payment', true );
     272            $override = (is_array( $payment ) && ! empty( $payment['provider_override'] )) ? $payment['provider_override'] : '';
     273        }
     274       
     275    $provider = (isset($override) && !empty($override)) ? $override : (($coinsnapbif_options['payment_provider'] === 'btcpay')? 'btcpay' : 'coinsnap');
     276        return $provider;
     277    }
     278
     279    private function getApiKey() {
     280        $coinsnapbif_options = get_option('bif_settings', []);
     281        return ($this->getPaymentProvider() === 'btcpay')? $coinsnapbif_options['btcpay_api_key']  : $coinsnapbif_options['coinsnap_api_key'];
     282    }
     283   
     284    private function getStoreId() {
     285    $coinsnapbif_options = get_option('bif_settings', []);
     286        return ($this->getPaymentProvider() === 'btcpay')? $coinsnapbif_options['btcpay_store_id'] : $coinsnapbif_options['coinsnap_store_id'];
     287    }
     288   
     289    public function getApiUrl() {
     290        $coinsnapbif_options = get_option('bif_settings', []);
     291        return ($this->getPaymentProvider() === 'btcpay')? $coinsnapbif_options['btcpay_host'] : COINSNAP_SERVER_URL;
     292    }
     293
     294    /**
     295     * Register admin menus and submenus.
     296     */
     297    public function register_admin_menu(): void {
    72298        add_menu_page(
    73299            __( 'Bitcoin Invoice Forms', 'coinsnap-bitcoin-invoice-form' ),
     
    158384            )
    159385        );
     386               
     387                $post_id = (filter_input(INPUT_GET,'post',FILTER_SANITIZE_FULL_SPECIAL_CHARS ))? filter_input(INPUT_GET,'post',FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : '';
     388               
     389                wp_localize_script('coinsnapbif-admin', 'coinsnapbif_ajax', array(
     390                    'ajax_url' => admin_url('admin-ajax.php'),
     391                    'nonce'  => wp_create_nonce( 'coinsnap-ajax-nonce' ),
     392                    'post' => $post_id
     393                ));
    160394
    161395        wp_enqueue_style( 'coinsnapbif-admin' );
Note: See TracChangeset for help on using the changeset viewer.