Custom new tab in Woocommerce my account pages - php

This question is about my woocommerce shop. I am trying to add new tab in my-account page (ticket tab). Eeverything going right, but when I hit the "ticket" tab I getting "404 not found" error!
I thought it should be work, but its no working.
Here is changes log:
add ticket code to woocommerce/includes/wc-template-functions.php
if ( ! function_exists( 'woocommerce_account_ticket' ) ) {
/**
* My Account > Ticket template.
*/
function woocommerce_account_ticket() {
wc_get_template( 'myaccount/ticket.php' );
}
}
add ticket code to woocommerce/includes/wc-template-hooks.php
add_action( 'woocommerce_account_ticket_endpoint', 'woocommerce_account_ticket' );
add ticket code to woocommerce/includes/admin/settings/class-wc-settings-accounts.php
array(
'title' => __( 'Ticket', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account → ticket" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_ticket_endpoint',
'type' => 'text',
'default' => 'ticket',
'desc_tip' => true,
),
add ticket code to woocommerce/includes/wc-account-functions.php
function wc_get_account_menu_items() {
$endpoints = array(
'ticket' => get_option( 'woocommerce_myaccount_ticket_endpoint', 'ticket' ),
);
$items = array(
'ticket' => __( 'Ticket', 'woocommerce' ),
);
add ticket code to woocommerce/includes/class-wc-query.php
'ticket' => get_option( 'woocommerce_myaccount_ticket_endpoint', 'ticket' ),
I don't want to update my woocommerce plugin, so there is no problem about playing with main plugin codes.

Related

Make Woocommerce (3.8.0) admin email include my custom field data from the checkout page

I have created some custom fields on the woocommerce checkout page. My code is correct and the fields display properly
I have saved the field data and displayed them in the admin panel. My code is correct and the fields display properly.
I have written code to include this data in the admin email whenever a new product is ordered.
My code is NOT correct and the information is not displayed in the email.
All other stackoverflow answers regarding this topic rely on a deprecated filter
woocommerce_email_order_meta_keys
There is no stackoverflow that answers with the woocommerce 3.8.0 woocommerce_email_order_meta_fields
filter.
I am running woocommerce 3.8.0 and wordpress 5.3.
I am saving these files in wp-content/themes/child-theme/functions.php
WTF is wrong with my code? I have checked it again and again and I can't figure out what is wrong. Can someone tell me what I am doing wrong? I am a ruby on rails developer trying to teach myself php and wordpress.
add_filter('woocommerce_email_order_meta_fields','custom_woocommerce_email_order_meta_fields', 10, 3 );
function custom_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['custom_field_1'] = array(
'label' => __( 'custom_field_1' ),
'value' => get_post_meta( $order->id, 'custom_field_1', true ),
);
$fields['custom_field_2'] = array(
'label' => __( 'custom_field_2' ),
'value' => get_post_meta( $order->id, 'custom_field_2', true ),
);
$fields['custom_field_3'] = array(
'label' => __( 'custom_field_3' ),
'value' => get_post_meta( $order->id, 'custom_field_3', true ),
);
$fields['custom_field_4'] = array(
'label' => __( 'custom_field_4' ),
'value' => get_post_meta( $order->id, 'custom_field_4', true ),
);
return $fields;
}
My custom form fields in the woocommerce checkout page is here
add_filter( 'woocommerce_checkout_fields', 'isca_custom_checkout_fields' );`
function isca_custom_checkout_fields($fields){
$fields['isca_extra_fields'] = array(
'custom_field_1' => array(
'class' => array(
'form-row-first'
),
'type' => 'text',
'required' => true,
'placeholder' => __( 'Name' )
),
'custom_field_2' => array(
'class' => array(
'form-row-last'
),
'type' => 'text',
'required' => true,
'placeholder' => __( 'Nickname' )
),
'custom_field_3' => array(
'class' => array(
'form-row-first'
),
'type' => 'text',
'required' => true,
'placeholder' => __( 'Favorite Exercise' )
),
'custom_field_4' => array(
'class' => array(
'form-row-last'
),
'type' => 'text',
'required' => false,
'placeholder' => __( 'Favorite Stretch' )
),
);
return $fields;
}
I then add it to the woocomerce checkout page with this code
add_action( 'woocommerce_after_checkout_billing_form' ,'isca_extra_checkout_fields' );
function isca_extra_checkout_fields(){
$checkout = WC()->checkout(); ?>
<br/>
<div class="extra-fields">
<h3><?php _e( 'Fitness Information' ); ?></h3>
<?php
foreach ( $checkout->checkout_fields['isca_extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
</div>
<?php }
WordPress has an option to turn on debug mode, so that errors and warnings can be identified and resolved. Errors will be logged in a file named debug.log in the wp-content folder of the WordPress folder while your code make any errors. So while developing in WordPress, you have to turn on three options.
Goto wp-config.php and add these three lines of code
define('WP_DEBUG', true);
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', true );
your custom_woocommerce_email_order_meta_fields function has an error. You called order id incorrectly. The error log will show that. Order properties shouldn't be called directly. So you have to change $order->id to $order->get_id(). So change the function to
function custom_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
if( !$sent_to_admin ){
return;
}
$fields['custom_field_1'] = array(
'label' => __( 'custom field 1' ),
'value' => get_post_meta( $order->get_id(), 'custom_field_1', true ),
);
$fields['custom_field_2'] = array(
'label' => __( 'custom field 2' ),
'value' => get_post_meta( $order->get_id(), 'custom_field_2', true ),
);
$fields['custom_field_3'] = array(
'label' => __( 'custom field 3' ),
'value' => get_post_meta( $order->get_id(), 'custom_field_3', true ),
);
$fields['custom_field_4'] = array(
'label' => __( 'custom field 4' ),
'value' => get_post_meta( $order->get_id(), 'custom_field_4', true ),
);
return $fields;
}
Also you haven't written any code to save the custom fields you added to checkout page. You are trying to find the values that aren't saved in the order meta. You need to write the code to save the custom added checkout fields to the order meta as below.
add_action('woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta');
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ($_POST['custom_field_1']) update_post_meta( $order_id, 'custom_field_1', esc_attr($_POST['custom_field_1']));
if ($_POST['custom_field_2']) update_post_meta( $order_id, 'custom_field_2', esc_attr($_POST['custom_field_2']));
if ($_POST['custom_field_3']) update_post_meta( $order_id, 'custom_field_3', esc_attr($_POST['custom_field_3']));
if ($_POST['custom_field_4']) update_post_meta( $order_id, 'custom_field_4', esc_attr($_POST['custom_field_4']));
}
Done . . . Now everything is added perfectly to the email (tested and confirmed). Also since you have said these fields are shown in the admin emails, you have to check that condition using
if( !$sent_to_admin ){
return;
}
which i have added in the custom_woocommerce_email_order_meta_fields function.

How to add iframe payment gateway in woocommerce?

I am trying to add another WooCommerce payment method called xxxx Bank Gateway on checkout page and when selected, this payment method will load an iframe like below (the iframe will redirect to the banks site lets call it $url).
How can I declare the content that will be displayed below the Checkout option?
//Frontend:
<input id="payment_method_xxxx" type="radio" class="input-radio" name="payment_method" value="xxxx" data-order_button_text="">
<label for="payment_method_xxx">
xxx Payment </label>
Here is my code so far:
<?php
/*
Plugin Name: xxxxxxx WooCommerce Payment Gateway
Plugin URI: http://www.xxxxxxx.com/
Description: xxxxxxx enables merchants to authorize, settle and manage credit card and electronic check transactions via Web sites, retail stores, mail order/telephone order (MOTO) call centers and mobile devices.
Version: 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
/*
* This action hook registers our PHP class as a WooCommerce payment gateway
*/
add_filter( 'woocommerce_payment_gateways', 'xxxxxxx_add_gateway_class' );
function xxxxxxx_add_gateway_class( $gateways ) {
$gateways[] = 'WC_xxxxxxx_Gateway'; // your class name is here
return $gateways;
}
/*
* The class itself, please note that it is inside plugins_loaded action hook
*/
add_action( 'plugins_loaded', 'xxxxxxx_init_gateway_class' );
function xxxxxxx_init_gateway_class() {
class WC_xxxxxxx_Gateway extends WC_Payment_Gateway {
/**
* Constructor
*/
public function __construct() {
// global ID
$this->id = 'xxxxxxx'; // payment gateway plugin ID
$this->icon = ''; // URL of the icon that will be displayed on checkout page near your gateway name
$this->has_fields = true; // in case you need a custom credit card form
// Show Title
$this->method_title = 'xxxxxxx Gateway';
// Show Description
$this->method_description = 'Description of xxxxxxx payment gateway'; // will be displayed on the options page
// setting defines
$this->init_form_fields();
$this->init_settings();
$this->title = $this->get_option( 'title' );
// further check of SSL if you want
//add_action( 'admin_notices', array( $this, 'do_ssl_check' ) );
// This action hook saves the settings
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ));
}
public function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => 'Enable/Disable',
'label' => 'Enable Epcipay Gateway',
'type' => 'checkbox',
'description' => '',
'default' => 'no'
),
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'xxxxxxx Payment', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'title' => __( 'Description', 'woocommerce' ),
'type' => 'textarea',
'default' => ''
),
'terminal_id' => array(
'title' => 'Terminal Id',
'type' => 'text'
),
'api_key' => array(
'title' => 'API Key',
'type' => 'password',
),
'password' => array(
'title' => 'Password',
'type' => 'text'
),
'pageid' => array(
'title' => 'Page Id',
'type' => 'text'
)
);
}
public function payment_fields() {
//how to add script tag to show the hosted checkout
// credit card form loaded from third party server -- Iframe
}
}

Adding subtitles to products in Woocommerce

I'd like to be able to add a subtitle to my products in Woocommerce only on the shop page. I have it set up as a catalog right now, since I'm not actively selling my products yet, so I have disabled the add to cart button and the prices. I would like to be able to say how many colors the product comes in as a subtitle. I have read up on adding meta boxes with Woocommerce, and found this solution and added it to my functions.php, but it doesn't appear to be working on my site (I can't find where to enter the information for the product!)
add_filter( 'cmb_meta_boxes', 'bhww_core_cpt_metaboxes' );
function bhww_core_cpt_metaboxes( $meta_boxes ) {
//global $prefix;
$prefix = '_bhww_'; // Prefix for all fields
// Add metaboxes to the 'Product' CPT
$meta_boxes[] = array(
'id' => 'bhww_woo_tabs_metabox',
'title' => 'Additional Product Information - <strong>Optional</strong>',
'pages' => array( 'product' ), // Which post type to associate with?
'context' => 'normal',
'priority' => 'default',
'show_names' => true,
'fields' => array(
array(
'name' => __( 'Colors', 'cmb' ),
'desc' => __( 'Anything you enter here will be displayed on the Colors tab.', 'cmb' ),
'id' => $prefix . 'ingredients_wysiwyg',
'type' => 'wysiwyg',
'options' => array( 'textarea_rows' => 5, ),
),
),
);
return $meta_boxes;
}

Wordpress - Woocommerce plugin development

i'm actually developping an ERP for a client and i'm quite a neophyte with the development on wordpress. I separated all in different classes to add new tabs and panels for the selection of the product type and right now I try to add those informations to the database with the meta data, I want to serialize the informations of the product that I want to add then serialize the informations of the product and the informations of the tab that I created.
Here's my code :
<?php
/**
* Created by PhpStorm.
* User: Rockerz
* Date: 15/06/17
* Time: 21:18
*/
class WC_Product_Rental_Schedule_Tab_view {
public static function Inithook_schedule(){
add_action( 'woocommerce_product_data_panels',
['WC_Product_Rental_Schedule_Tab_view','Render_Schedule'] );
}
/**
* XXX Rename it Render_Product_Tab_Form
* Custom Tab Panels informations
*/
public static function Render_Schedule(){
global $post;
?><div id='product_dyu' class='panel woocommerce_options_panel'>
<div class='options_group'>
<?php
woocommerce_wp_text_input(
array(
'id' => 'date_in',
'label' => __( 'Date in', 'woocommerce' ),
'desc_tip' => 'true',
'description' => __( 'Date in', 'woocommerce' ),
'type' => 'date',
)
);
woocommerce_wp_text_input(
array(
'id' => 'date_out',
'label' => __( 'Date out', 'woocommerce' ),
'desc_tip' => 'true',
'description' => __( 'Date out', 'woocommerce' ),
'type' => 'date',
)
);
woocommerce_wp_select( array(
'id' => 'status',
'name' => 'status[]',
'class' => 'status',
'label' => __('Status', 'woocommerce'),
'options' => array(
'1' => 'Pending',
'2' => 'In-Stock',
'3' => 'Rent',
'4' => 'deprecated',
'5' => 'Sold',
))
);
$users = get_users(array('fields'=>array('ID', 'user_nicename')));
$selectUser = array(
'id' => 'users',
'name' => 'users[]',
'class' => 'users',
'label' => __('Users', 'woocommerce'),
);
foreach($users as $user){
$selectUser['options'][$user->ID] = $user->user_nicename;
}
woocommerce_wp_select($selectUser);
?>
</div>
</div>
<?php
}
}
this is the informations of the panel that I want to add to the database.
I don't know how to add those infos to the database with the meta, all I know is that I have to serialize all this before adding it to the DB.
You probably will not need to serialize anything yourself. WordPress abstracts that away with its APIs. Look into update_post_meta(). For adding the meta data to the posts (woocommerce products are a custom post type.)
So when do you use it?
You can hook it to the woocommerce_process_product_meta hook that is fired when a product is saved. I'm not sure why you are using a static function for your init but I'm going to assume you know. That said add the hook.
You can then use the function you are hooking on to check the $_POST variable for the ids of your inputs. That would look something like this:
//This goes in you init or constructor
add_action( 'woocommerce_process_product_meta', array( __CLASS__, 'save_fields' ), 1, 2 );
//This processes and saves data in post_meta
function save_fields( $post_id, $product ) {
$status = $_POST['status'];
if ( ! empty( $status ) ) {
update_post_meta( $post_id, '{META_KEY_NAME}', esc_attr( $status ) );
}
}
Extra tip:
Besides my answer I see you're using PhpStorm. One of the most valuable tools I used when learning my way around Woocommerce was PhpStorm's "go to definition" feature. The official docs are just autogenerated from the DocBlocks and leave a lot to be desired. I found it invaluable to read through and jump around the code.

How to create simple Offline payment gateway for WooCommerce?

Good afternoon, I want to make simple copy of Cash on Delivery (COD) payment method in my store and rename it to Coupon on Delivery.
How to implement it?
Up
I have tried this code, but it shows error 500 on WC settings page:
<?php
/**
* Plugin Name: My New WooCommerce Gateway
* Plugin URI:
* Description: WooCommerce gateway to ....
* Author: .....
* Version: 1.0
* Author URI: https://example.org/
* Text Domain: woocommerce-my-gateway
* Domain Path: /languages/
*/
add_action( 'plugins_loaded', 'init_my_gateway_class' );
function init_my_gateway_class() {
if ( !class_exists( 'WooCommerce' ) ) return;
class WC_Gateway_COD_Renamed extends WC_Payment_Gateway {
}
}
function add_my_gateway_class( $methods ) {
$methods[] = 'WC_Gateway_my_gateway';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_my_gateway_class' );
function my_load_textdomain(){
load_plugin_textdomain( 'woocommerce-my-gateway', false, dirname( plugin_dir_path( __FILE__ ) . '/languages/' ) );
}
add_action('plugins_loaded', 'my_load_textdomain');
Source of code
In your main plugin file you can include the class and filter the gateways at the same time:
function add_my_gateway_class( $methods ) {
include( 'class-wc-gateway-cod-renamed.php');
$methods[] = 'WC_Gateway_COD_Renamed';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_my_gateway_class' );
There's no real need to check if WooCommerce is active this way as woocommerce_payment_gateways only exists if WooCommerce is running.
Then in another file called class-wc-gateway-cod-renamed.php you can define your class:
class WC_Gateway_COD_Renamed extends WC_Gateway_COD {
/**
* Setup general properties for the gateway.
*/
protected function setup_properties() {
$this->id = 'coupon-on-delivery';
$this->icon = apply_filters( 'woocommerce_coupon-on-deliver_icon', '' );
$this->method_title = __( 'Coupon on delivery', 'your-plugin' );
$this->method_description = __( 'Have your customers pay with a coupon upon delivery.', 'your-plugin' );
$this->has_fields = false;
}
/**
* Initialise Gateway Settings Form Fields.
*/
public function init_form_fields() {
$shipping_methods = array();
foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
$shipping_methods[ $method->id ] = $method->get_method_title();
}
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'your-plugin' ),
'label' => __( 'Enable coupon on delivery', 'your-plugin' ),
'type' => 'checkbox',
'description' => '',
'default' => 'no',
),
'title' => array(
'title' => __( 'Title', 'your-plugin' ),
'type' => 'text',
'description' => __( 'Payment method description that the customer will see on your checkout.', 'your-plugin' ),
'default' => __( 'coupon on delivery', 'your-plugin' ),
'desc_tip' => true,
),
'description' => array(
'title' => __( 'Description', 'your-plugin' ),
'type' => 'textarea',
'description' => __( 'Payment method description that the customer will see on your website.', 'your-plugin' ),
'default' => __( 'Pay with coupon upon delivery.', 'your-plugin' ),
'desc_tip' => true,
),
'instructions' => array(
'title' => __( 'Instructions', 'your-plugin' ),
'type' => 'textarea',
'description' => __( 'Instructions that will be added to the thank you page.', 'your-plugin' ),
'default' => __( 'Pay with coupon upon delivery.', 'your-plugin' ),
'desc_tip' => true,
),
'enable_for_methods' => array(
'title' => __( 'Enable for shipping methods', 'your-plugin' ),
'type' => 'multiselect',
'class' => 'wc-enhanced-select',
'css' => 'width: 400px;',
'default' => '',
'description' => __( 'If coupon upon delivery is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'your-plugin' ),
'options' => $shipping_methods,
'desc_tip' => true,
'custom_attributes' => array(
'data-placeholder' => __( 'Select shipping methods', 'your-plugin' ),
),
),
'enable_for_virtual' => array(
'title' => __( 'Accept for virtual orders', 'your-plugin' ),
'label' => __( 'Accept coupon if the order is virtual', 'your-plugin' ),
'type' => 'checkbox',
'default' => 'yes',
),
);
}
}
Extend the WC_Gateway_COD class so that you can inherit methods from it and only override the methods that have to do with the naming of things.
In WooCommerce plugin, you can enable payment gateway COD from admin section:
Admin >> WooCommerce >> Settings >> Checkout >> Cash on delivery.
Check option for enable COD.
Please refer below link for create offline payment gateway.
How to Create A WooCommerce Payment gateway

Categories