问题
I got a kind of strange issue in WooCommerce: I have find out that a Javascript file that is selecting country field from checkout and choosing at the same time some plugin right field. (Like: in checkout billing country is - Switzerland and payment gateway should get billing_country field info and show available payment options by that country).
Issue probably has been made by this script (tested it, as soon as .js code deleted - WooCommerce checkout field works perfectly, but then payment gateway doesn't getting info from billing_country field and doesn't know what to chose - so shows "other").
The jQuery Code:
jQuery( document ).ready(function($) {
const COUNTRY_SELECTION = '.country_select';
$(COUNTRY_SELECTION).on("click", function() {
var id, countryBilling, countryOption;
$('.payment-countries').hide('slow');
countryBilling = $('#billing_country');
countryOption = countryBilling.find('option');
if (typeof countryBilling.val() === "undefined" || countryBilling.val() === null) {
id = countryOption.eq(1).val();
} else {
id = countryBilling.val().toLowerCase();
}
idcheck = $('#' + id).attr('class');
if(!idcheck){
id = 'other';
idcheck = $('#' + id).attr('class');
if(!idcheck) {
id = countryOption.eq(1).val();
}
}
countryOption.attr("selected", false);
$('#paysera_country').find('option[value=\"' + id + '\"]').attr("selected", true);
$('#' + id).show('slow');
});
$(document).on('change', '#paysera_country' ,function(){
$('.payment-countries').hide('slow');
$('#' + $('#paysera_country').val()).show('slow');
});
$(document).on('change', 'input[name="payment[pay_type]"]' ,function(){
$('.payment').removeClass('activePayseraPayment');
$(this).parent().parent().addClass('activePayseraPayment');
});
});
Same payment plugin payment methods classes (If I'm getting right: this is related with JS):
<?php
defined('ABSPATH') or exit;
if(!class_exists('Wc_Paysera_Html_Form')) {
require_once 'class-wc-paysera-html-form.php';
}
/**
* Build Paysera payment methods list
*/
class Wc_Paysera_Payment_Methods
{
/**
* Code used for empty fields
*/
const EMPTY_CODE = '';
/**
* HTML NewLine break
*/
const LINE_BREAK = '<div style="clear:both"><br /></div>';
/**
* Min. number of countries in list
*/
const COUNTRY_SELECT_MIN = 1;
/**
* Default language if not in the list
*/
const DEFAULT_LANG = 'en';
/**
* Default bool answer
*/
const DEFAULT_ANSWER = false;
/**
* Default total
*/
const DEFAULT_TOTAL = 0;
/**
* Default currency
*/
const DEFAULT_CURRENCY = 'EUR';
/**
* Default project id
*/
const DEFAULT_PROJECT_ID = 0;
/**
* @var int
*/
protected $projectID;
/**
* @var string
*/
protected $billingCountry;
/**
* @var string
*/
protected $lang;
/**
* @var boolean
*/
protected $displayList;
/**
* @var array
*/
protected $countriesSelected;
/**
* @var boolean
*/
protected $gridView;
/**
* @var string
*/
protected $description;
/**
* @var double
*/
protected $cartTotal;
/**
* @var string
*/
protected $cartCurrency;
/**
* Available languages of payments
*/
protected $availableLang;
/**
* @return self
*/
static public function create()
{
return new self();
}
/**
* Wc_Paysera_Payment_Methods constructor
*/
public function __construct() {
$this->projectID = $this::DEFAULT_PROJECT_ID;
$this->lang = $this::DEFAULT_LANG;
$this->billingCountry = $this::EMPTY_CODE;
$this->displayList = $this::DEFAULT_ANSWER;
$this->countriesSelected = $this::EMPTY_CODE;
$this->gridView = $this::DEFAULT_ANSWER;
$this->description = $this::DEFAULT_ANSWER;
$this->cartTotal = $this::DEFAULT_TOTAL;
$this->cartCurrency = $this::DEFAULT_CURRENCY;
}
/**
* @param boolean [Optional] $print
*
* @return boolean|string
*/
public function build($print = true)
{
$buildHtml = Wc_Paysera_Html_Form::create();
if ($this->isDisplayList()) {
$payseraCountries = $this->getPayseraCountries(
$this->getProjectID(),
$this->getCartTotal(),
$this->getCartCurrency(),
$this->listLang()
);
$countries = $this->getCountriesList($payseraCountries);
if (count($countries) > $this::COUNTRY_SELECT_MIN) {
$paymentsHtml = $buildHtml->buildCountriesList(
$countries,
$this->getBillingCountry()
);
$paymentsHtml .= $this::LINE_BREAK;
} else {
$paymentsHtml = $this::EMPTY_CODE;
}
$paymentsHtml .= $buildHtml->buildPaymentsList(
$countries,
$this->isGridView(),
$this->getBillingCountry()
);
$paymentsHtml .= $this::LINE_BREAK;
} else {
$paymentsHtml = $this->getDescription();
}
if ($print) {
print_r($paymentsHtml);
return $print;
} else {
return $paymentsHtml;
}
}
/**
* @param integer $project
* @param string $currency
* @param string $lang
*
* @return WebToPay_PaymentMethodCountry[]
*/
protected function getPayseraCountries($project, $amount, $currency, $lang)
{
$countries = WebToPay::getPaymentMethodList(
$project,
$currency
)->filterForAmount(
$amount,
$currency
)->setDefaultLanguage(
$lang
)->getCountries();
return $countries;
}
/**
* @param array $countries
*
* @return array
*/
protected function getCountriesList($countries)
{
$countriesList = [];
$showSelectedCountries = is_array($this->getCountriesSelected());
$selectedCountriesCodes = $this->getCountriesSelected();
foreach ($countries as $country) {
$checkForCountry = true;
if ($showSelectedCountries) {
$checkForCountry = in_array($country->getCode(), $selectedCountriesCodes);
}
if ($checkForCountry) {
$countriesList[] = [
'code' => $country->getCode(),
'title' => $country->getTitle(),
'groups' => $country->getGroups()
];
}
}
return $countriesList;
}
/**
* @return string
*/
protected function listLang()
{
if (in_array($this->getLang(), $this->getAvailableLang())) {
$listLang = $this->getLang();
} else {
$listLang = $this::DEFAULT_LANG;
}
return $listLang;
}
/**
* @return string
*/
public function getBillingCountry()
{
return $this->billingCountry;
}
/**
* @param string $billingCountry
*
* @return self
*/
public function setBillingCountry($billingCountry)
{
$this->billingCountry = $billingCountry;
return $this;
}
/**
* @return string
*/
public function getLang()
{
return $this->lang;
}
/**
* @param string $lang
*
* @return self
*/
public function setLang($lang)
{
$this->lang = $lang;
return $this;
}
/**
* @return boolean
*/
public function isDisplayList()
{
return $this->displayList;
}
/**
* @param boolean $displayList
*
* @return self
*/
public function setDisplayList($displayList)
{
$this->displayList = $displayList;
return $this;
}
/**
* @return array
*/
public function getCountriesSelected()
{
return $this->countriesSelected;
}
/**
* @param array $countriesSelected
*
* @return self
*/
public function setCountriesSelected($countriesSelected)
{
$this->countriesSelected = $countriesSelected;
return $this;
}
/**
* @return boolean
*/
public function isGridView()
{
return $this->gridView;
}
/**
* @param boolean $gridView
*
* @return self
*/
public function setGridView($gridView)
{
$this->gridView = $gridView;
return $this;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $description
*
* @return self
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @return double
*/
public function getCartTotal()
{
return $this->cartTotal;
}
/**
* @param double $cartTotal
*
* @return self
*/
public function setCartTotal($cartTotal)
{
$this->cartTotal = $cartTotal;
return $this;
}
/**
* @return string
*/
public function getCartCurrency()
{
return $this->cartCurrency;
}
/**
* @param string $cartCurrency
*
* @return self
*/
public function setCartCurrency($cartCurrency)
{
$this->cartCurrency = $cartCurrency;
return $this;
}
/**
* @return int
*/
public function getProjectID()
{
return $this->projectID;
}
/**
* @param int $projectID
*
* @return self
*/
public function setProjectID($projectID)
{
$this->projectID = $projectID;
return $this;
}
/**
* @return array
*/
public function getAvailableLang()
{
return $this->availableLang;
}
/**
* @param array $availableLang
*
* @return self
*/
public function setAvailableLang($availableLang)
{
$this->availableLang = $availableLang;
return $this;
}
}
HTML form code (which is included in payment-methods.php)
<?php
defined('ABSPATH') or exit;
/**
* Build HTML code for Paysera Payments
*/
class Wc_Paysera_Html_Form
{
/**
* Code used for empty fields
*/
const EMPTY_CODE = '';
/**
* Selected field name
*/
const FIELD_SELECTED = 'selected';
/**
* ID of other payments group
*/
const CODE_OTHER = 'other';
/**
* @return self
*/
static public function create()
{
return new self();
}
/**
* @param array $countries
* @param string $billingCountryCode
*
* @return string
*/
public function buildCountriesList(
$countries,
$billingCountryCode
) {
$defaultLangCode = $this->getDefaultLangCode(
$countries,
$billingCountryCode
);
$selectionField = '<select id="paysera_country"
class="payment-country-select" >';
foreach ($countries as $country) {
if ($country['code'] == $defaultLangCode) {
$selected = $this::FIELD_SELECTED;
} else {
$selected = $this::EMPTY_CODE;
}
$selectionField .= '<option value="'
. $country['code'] . '" '
. $selected
. '>';
$selectionField .= $country['title'];
$selectionField .= '</option>';
}
$selectionField .= '</select>';
return $selectionField;
}
/**
* @param array $countries
* @param boolean $gridViewIsActive
* @param string $billingCountryCode
*
* @return string
*/
public function buildPaymentsList(
$countries,
$gridViewIsActive,
$billingCountryCode
) {
$paymentsCode = $this::EMPTY_CODE;
$defaultLangCode = $this->getDefaultLangCode(
$countries,
$billingCountryCode
);
foreach ($countries as $country) {
$paymentsCode .= '<div id="' . $country['code'] . '"';
if ($gridViewIsActive) {
$paymentsCode .= ' class="payment-countries paysera-payments grid"';
} else {
$paymentsCode .= ' class="payment-countries paysera-payments"';
}
$paymentsCode .= ' style="display:';
if (($country['code'] == $defaultLangCode)) {
$paymentsCode .= 'block';
} else {
$paymentsCode .= 'none';
}
$paymentsCode .= '">';
$paymentsCode .= $this->buildGroupList(
$country['groups'],
$country['code']
);
$paymentsCode .= '</div>';
}
return $paymentsCode;
}
/**
* @param array $methods
* @param string $countryCode
*
* @return string
*/
protected function buildMethodsList(
$methods,
$countryCode
) {
$paymentMethodCode = $this::EMPTY_CODE;
foreach ($methods as $method) {
$paymentMethodCode .= '<div id="' . $method->getKey() . '" class="payment">';
$paymentMethodCode .= '<label>';
$paymentMethodCode .= '<input class="rd_pay" ';
$paymentMethodCode .= 'type="radio" ';
$paymentMethodCode .= 'rel="r' . $countryCode . $method->getKey() . '" ';
$paymentMethodCode .= 'name="payment[pay_type]" ';
$paymentMethodCode .= 'value="' . $method->getKey() . '" /> ';
$paymentMethodCode .= '<span class="paysera-text">';
$paymentMethodCode .= $method->getTitle();
$paymentMethodCode .= '</span>';
$paymentMethodCode .= '<div class="paysera-image">';
$paymentMethodCode .= '<img src="' . $method->getLogoUrl() . '" ';
$paymentMethodCode .= 'alt="' . $method->getTitle() . '" />';
$paymentMethodCode .= '</div>';
$paymentMethodCode .= '</label>';
$paymentMethodCode .= '</div>';
}
return $paymentMethodCode;
}
/**
* @param array $groups
* @param string $countryCode
*
* @return string
*/
protected function buildGroupList(
$groups,
$countryCode
) {
$paymentGroupCode = $this::EMPTY_CODE;
foreach ($groups as $group) {
$paymentGroupCode .= '<div class="payment-group-wrapper">';
$paymentGroupCode .= '<div class="payment-group-title">';
$paymentGroupCode .= $group->getTitle();
$paymentGroupCode .= '</div>';
$paymentGroupCode .= $this->buildMethodsList(
$group->getPaymentMethods(),
$countryCode
);
$paymentGroupCode .= '</div>';
}
return $paymentGroupCode;
}
/**
* @param array $countries
* @param string $countryCode
*
* @return string
*/
protected function getDefaultLangCode(
$countries,
$countryCode
) {
$countryCodes = [];
foreach ($countries as $country) {
$countryCodes[] = $country['code'];
}
if (in_array($countryCode, $countryCodes)) {
$defaultLang = $countryCode;
} elseif (in_array($this::CODE_OTHER, $countryCodes)) {
$defaultLang = $this::CODE_OTHER;
} else {
$defaultLang = reset($countries)['code'];
}
return $defaultLang;
}
}
Part of payment-gateway main class (pasting part which is related with billing_country)
public function payment_fields()
{
if(!class_exists('Wc_Paysera_Payment_Methods')) {
require_once 'class-wc-paysera-payment-methods.php';
}
$localLang = $this->getLocalLang($this::LANG_DELIMITER);
$billingCountry = WC()->customer->get_billing_country();
$cartTotal = round(WC()->cart->total * 100);
$currency = get_woocommerce_currency();
$htmlFields = Wc_Paysera_Payment_Methods::create()
->setProjectID($this->getProjectID())
->setLang($localLang)
->setBillingCountry(strtolower($billingCountry))
->setDisplayList($this->getPaymentType())
->setCountriesSelected($this->getCountriesSelected())
->setGridView($this->getGridView())
->setDescription($this->getDescription())
->setCartTotal($cartTotal)
->setCartCurrency($currency)
->setAvailableLang(array('lt', 'lv', 'ru', 'en', 'pl', 'bg', 'et'))
;
$htmlFields->build(true);
wp_enqueue_style(
'custom-frontend-style',
WCGatewayPayseraPluginUrl.$this::PAYSERA_STYLESHEET
);
wp_enqueue_script(
'custom-frontend-script',
WCGatewayPayseraPluginUrl.$this::PAYSERA_FRONTEND_ACTION_JS,
array('jquery')
);
}
I've noticed, after this part of jQuery call - main issue appears:
wp_enqueue_script(
'custom-frontend-script',
WCGatewayPayseraPluginUrl.$this::PAYSERA_FRONTEND_ACTION_JS,
array('jquery')
);
If I'm removing this part - plugin doesn't recognize which country is selected in billing_country and doesn't know which country to show in payment gateway country list.
I tried some JS code checkers (few different) some of them show all good, some of them shows "undefined" jQuery variable and etc.
来源:https://stackoverflow.com/questions/61509094/jquery-script-issue-blocking-country-selection-in-woocommerce