In my laravel vue application I'm trying to fetch some data from Shopify Admin REST API and display them on the vuejs front end.
Following is my laravel controller.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Carbon\Carbon;
class ShopifyStatsController extends Controller
{
public function fetchStats(Request $request)
{
$startDate = $request->input('start_date');
$endDate = Carbon::parse($request->input('end_date'))->addDay()->format('Y-m-d');
if (!$startDate) {
$startDate = Carbon::now()->format('Y-m-d');
}
if(!$endDate) {
$endDate = Carbon::parse($startDate)->addDay()->format('Y-m-d');
}
// Set up cURL request
$access_token = 'ACCESS_TOKEN';
$apiKey = 'API_KEY';
$storeName = 'STROE_NAME';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://API_KEY:ACCESS_TOKEN#STROE_NAME.myshopify.com/admin/orders.json?status=any&created_at_min=$startDate&created_at_max=$endDate");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
$response = curl_exec($ch);
curl_close($ch);
$orders = json_decode($response);
//dd($orders);die;
$total_orders = ($orders->orders != null && !empty($orders->orders)) ? count($orders->orders) : 0;
$total_sales = ($orders->orders != null && !empty($orders->orders)) ? 0 : 0;
$total_items = ($orders->orders != null && !empty($orders->orders)) ? 0 : 0;
$completed_orders = ($orders->orders != null && !empty($orders->orders)) ? 0 : 0;
$to_be_fulfilled_orders = ($orders->orders != null && !empty($orders->orders)) ? 0 : 0;
foreach ($orders->orders as $order) {
$total_sales += $order->total_price;
$total_items += count($order->line_items);
if ($order->financial_status == "paid") {
$completed_orders++;
}
if ($order->fulfillment_status == null) {
$to_be_fulfilled_orders++;
}
}
$average_order_value = $total_orders > 0 ? $total_sales / $total_orders : 0;
// Bar chart for the best selling days
$start_date = date('Y-m-d', strtotime('-7 days'));
$end_date = date('Y-m-d');
$url = "https://API_KEY:ACCESS_TOKEN#STROE_NAME.myshopify.com/admin/orders.json?status=any&created_at_min=".date('Y-m-d', strtotime('-7 days'))."&created_at_max=".date('Y-m-d').""; // append the query to the URL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-Shopify-Access-Token:ACCESS_TOKEN', // access token
]);
// Send the request
$response = curl_exec($ch);
$response = json_decode($response, true);
curl_close($ch);
// Extract the data for each day from the response
$day_totals = array();
if (!empty($response['orders'])) {
foreach ($response['orders'] as $order) {
$order_date = date('Y-m-d', strtotime($order['created_at']));
if (!isset($day_totals[$order_date])) {
$day_totals[$order_date] = 0;
}
$day_totals[$order_date]++;
}
}
// Set 0 for days with no sales data
for ($date = $start_date; $date <= $end_date; $date = date('Y-m-d', strtotime($date . ' +1 day'))) {
if (!isset($day_totals[$date])) {
$day_totals[$date] = 0;
}
}
// Find the most selling day of the week
$most_sales_day = max($day_totals);
$most_selling_day = array_search($most_sales_day, $day_totals);
// Return the total sales value
return response()->json([
'total_sales' => $total_sales,
'total_orders' => $total_orders,
'total_items' => $total_items,
'completed_orders' => $completed_orders,
'average_order_value' => $average_order_value,
'day_totals' => $day_totals,
'most_selling_day' => $most_selling_day,
'most_sales_day' => $most_sales_day
]);
}
}
Here $day_totals will give me an array with day wise sales for a week, something like follows
array:8 [
"2023-01-09" => 1
"2023-01-04" => 0
"2023-01-05" => 0
"2023-01-06" => 0
"2023-01-07" => 0
"2023-01-08" => 0
"2023-01-10" => 0
"2023-01-11" => 0
]
Now I have created a reusable vue component called, ShopifyDayWiseSales.vue and this needs to show day wise sales for the week in a bar chart.
Following is my ShopifyDayWiseSales.vue component.
<template>
<div>
<apexchart type="bar" :options="chartOptions" :series="chartData"></apexchart>
</div>
</template>
<script>
import axios from 'axios';
import moment from 'moment';
export default {
data() {
return {
chartOptions: {
xaxis: {
categories: [],
},
yaxis: {
labels: {
formatter: function(val) {
return "$" + val;
},
},
},
},
chartData: [
{
name: "Total Sales",
data: [],
},
],
};
},
created() {
axios.get(`/shopify-stats`).then(response => {
console.log(response.data);
let chartData = {};
Object.entries(response.data.day_totals).forEach(([day, total]) => {
chartData[day] = total;
});
this.chartOptions.xaxis.categories = Object.keys(chartData);
this.chartData[0].data = Object.values(chartData);
console.log(chartData);
});
},
};
</script>
Here I'm using module to draw the graph.
My console log gives me this out put
2023-01-04: 0
2023-01-05: 0
2023-01-06: 0
2023-01-07: 0
2023-01-08: 0
2023-01-09: 1
2023-01-10: 0
2023-01-11: 0
Then I tried to use that component In my index.vue
<div >
<ShopifyDayWiseStats></ShopifyDayWiseStats>
</div>
But when I run this, It gives me an empty chart with not populated x and y axis.
In short word, my chart has not been drawn, I'm just wondering what's I'm doing wrong...
This what I'm currently getting
Related
I am trying to get the latitude and longitude of an address but don't know how to put a variable in http build query.
I basically want to get the lat and long of place and get figure out how to put a variable in http_build_query.
This is what I tried:
$queryString = http_build_query([
'access_key' => 'API_KEY',
'query' => $place,
'country' => 'US',
'region' => 'California',
'output' => 'json',
'limit' => 1,
]);
$ch = curl_init(sprintf('%s?%s', 'http://api.positionstack.com/v1/forward', $queryString));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$json = curl_exec($ch);
curl_close($ch);
$apiResult = json_decode($json, true);
print_r($apiResult);
foreach($apiResult as $result) {
foreach($result as $answer) {
$pickuplat = htmlspecialchars($answer['latitude']);
$pickuplong = htmlspecialchars($answer['longitude']);
}
}
Example without the var
$queryString = http_build_query([
'access_key' => 'API_KEY',
'query' => '1600 Pennsylvania Ave NW',
'country' => 'US',
'region' => 'California',
'output' => 'json',
'limit' => 1,
]);
$ch = curl_init(sprintf('%s?%s', 'http://api.positionstack.com/v1/forward', $queryString));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$json = curl_exec($ch);
curl_close($ch);
$apiResult = json_decode($json, true);
print_r($apiResult);
foreach($apiResult as $result) {
foreach($result as $answer) {
$pickuplat = htmlspecialchars($answer['latitude']);
$pickuplong = htmlspecialchars($answer['longitude']);
}
}
Please help!
Please accept my apology in advance if my question is long.
I am using a payment gateway of woocommerce.
When click on checkout it goes to an external link. Then there We have button to click and Then It goes to another link which make it enable to pay via cards.
Now What I want to do is that.
I want to minimize some step.
1- If possible I want to bypass detail page which appears after click on Checkout button.
2- Is this possible to hide amount on detail page. As my website currecny is different and this payment gateway the show in different.
3- If above 1,2 not possible. Can simply put external pages in a iframe.
So if user click on check out. It should show a ifram on new page current page with redirected link.
Below code is from gateway plugin.
<?php
add_action( 'plugins_loaded', 'init_pp_woo_gateway');
function mib_ppbycp_settings( $links ) {
$settings_link = 'Setup';
array_push( $links, $settings_link );
return $links;
}
$plugin = plugin_basename( __FILE__ );
add_filter( "plugin_action_links_$plugin", 'mib_ppbycp_settings' );
function init_pp_woo_gateway(){
if ( ! class_exists( 'WC_Payment_Gateway' ) ) return;
class WC_Gateway_MIB_PayPro extends WC_Payment_Gateway {
// Logging
public static $log_enabled = false;
public static $log = false;
var $merchant_id;
var $merchant_password;
var $test_mode;
var $plugin_url;
var $timeout;
var $checkout_url;
var $api_url;
var $timeout_in_days;
public function __construct(){
global $woocommerce;
$this -> plugin_url = WP_PLUGIN_URL . DIRECTORY_SEPARATOR . 'woocommerce-paypro-payment';
$this->id = 'mibwoo_pp';
$this->has_fields = false;
$this->checkout_url = 'https://marketplace.paypro.com.pk/';
$this->icon = 'https://thebalmainworld.com/wp-content/uploads/2020/10/Credit-Card-Icons-copy-1.png';
$this->method_title = 'Paypro';
$this->method_description = 'Pay via Debit/Credit card.';
$this->title = "Paypro";
$this->description = "Pay via Debit/Credit card.";
$this->merchant_id = $this->get_option( 'merchant_id' );
$this->merchant_password = trim($this->get_option( 'merchant_password' ));
$this->merchant_secret = $this->get_option( 'merchant_secret' );
$this->test_mode = $this->get_option('test_mode');
$this->timeout_in_days = $this->get_option('timeout_in_days');
$this->debug = $this->get_option('debug');
$this->pay_method = "Paypro";
if($this->timeout_in_days==='yes'){
$this->timeout = trim($this->get_option( 'merchant_timeout_days' ));
}
else{
$this->timeout = trim($this->get_option( 'merchant_timeout_minutes' ));
}
if($this->test_mode==='yes'){
$this->api_url = 'https://demoapi.paypro.com.pk';
}
else{
$this->api_url = 'https://api.paypro.com.pk';
}
$this->init_form_fields();
$this->init_settings();
self::$log_enabled = $this->debug;
// Save options
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
// Payment listener/API hook
add_action( 'woocommerce_api_wc_gateway_mib_paypro', array( $this, 'paypro_response' ) );
}
function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'yes'
),
'merchant_id' => array(
'title' => __( 'Merchant Username', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This Merchant Username Provided by PayPro', 'woocommerce' ),
'default' => '',
'desc_tip' => true,
),
'test_mode' => array(
'title' => __( 'Enable Test Mode', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'yes'
),
'merchant_password' => array(
'title' => __( 'Merchant Password', 'woocommerce' ),
'type' => 'password',
'description' => __( 'Merchant Password Provided by PayPro', 'woocommerce' ),
'default' => __( '', 'woocommerce' ),
'desc_tip' => true,
),
'merchant_secret' => array(
'title' => __( 'Secret Key', 'woocommerce' ),
'type' => 'password',
'description' => __( 'Any Secret Key Or Word with No Spaces', 'woocommerce' ),
'default' => __( rand(), 'woocommerce' ),
'desc_tip' => true,
),
'merchant_timeout_minutes' => array(
'title' => __( 'Timeout (In Minutes)', 'woocommerce' ),
'type' => 'number',
'description' => __( 'Timeout Before order expires it can be between 5 to 30 minutes', 'woocommerce' ),
'default' => __( 5, 'woocommerce' ),
'desc_tip' => true,
'custom_attributes' => array(
'min' => 5,
'max' => 30
)
),
'timeout_in_days' => array(
'title' => __( 'Enable Timeout in days', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Yes', 'woocommerce' ),
'default' => 'no'
),
'merchant_timeout_days' => array(
'title' => __( 'Timeout (In Days)', 'woocommerce' ),
'type' => 'number',
'description' => __( 'Minimum 1 day Max 3 Days. Remember, It works as due date you\'ve selected 1 day the expiration date of the PayPro id will be set as the day after today.', 'woocommerce' ),
'default' => __( 1, 'woocommerce' ),
'desc_tip' => true,
'custom_attributes' => array(
'min' => 1,
'max' => 3
)
),
'debug' => array(
'title' => __( 'Debug Log', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable logging', 'woocommerce' ),
'default' => 'no',
'description' => sprintf( __( 'Debug Information <em>%s</em>', 'woocommerce' ), wc_get_log_file_path( 'paypro' ) )
),
);
}
/**
* Logging method
* #param string $message
*/
public static function log( $message ) {
if ( self::$log_enabled ) {
if ( empty( self::$log ) ) {
self::$log = new WC_Logger();
}
$message = is_array($message) ? json_encode($message) : $message;
self::$log->add( 'paypro', $message );
}
}
/**
* Process the payment and return the result
*
* #access public
* #param int $order_id
* #return array
*/
function process_payment( $order_id ) {
$order = new WC_Order( $order_id );
$paypro_args = $this->get_paypro_args( $order );
$paypro_args = http_build_query( $paypro_args, '', '&' );
$this->log("========== Payment Processing Started: args =========");
$this->log($paypro_args);
//if demo is enabled
$checkout_url = $this->checkout_url;;
return array(
'result' => 'success',
// 'redirect' => 'http://localhost:8000/secureform?'.$paypro_args
'redirect' => 'https://marketplace.paypro.com.pk/secureform?'.$paypro_args
);
}
/**
* Get PayPro Args for passing to PP
*
* #access public
* #param mixed $order
* #return array
*/
function get_paypro_args( $order ) {
global $woocommerce;
$order_id = $order->get_id();
//Encrypting the username and password
$token1 = $this->merchant_id;
$token2 = $this->merchant_password;
$cipher_method = 'aes-128-ctr';
$secret_word = md5($this->merchant_secret);
$enc_key = openssl_digest($secret_word.date('d/m/y'), 'SHA256', TRUE);
$enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));
$crypted_token1 = openssl_encrypt($token1, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
$crypted_token2 = openssl_encrypt($token2, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
unset($token, $cipher_method, $enc_key, $enc_iv);
// PayPro Args
$paypro_args = array(
'mid' => $crypted_token1,
'mpw' => $crypted_token2,
'secret_public' => base64_encode($this->merchant_secret),
'is_encrypted' => 1,
'mode' => $this->test_mode,
'timeout_in_days' => $this->timeout_in_days,
'merchant_order_id' => $order_id,
'merchant_name' => get_bloginfo( 'name' ),
'request_is_valid' => 'true',
'request_from' => 'woocommerce',
// Billing Address info
'first_name' => $order->get_billing_first_name(),
'last_name' => $order->get_billing_last_name(),
'street_address' => $order->get_billing_address_1(),
'street_address2' => $order->get_billing_address_2(),
'city' => $order->get_billing_city(),
'state' => $order->get_billing_state(),
'zip' => $order->get_billing_postcode(),
'country' => $order->get_billing_country(),
'email' => $order->get_billing_email(),
'phone' => $order->get_billing_phone(),
);
if (!function_exists('is_plugin_active')) {
include_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
if(is_plugin_active( 'custom-order-numbers-for-woocommerce/custom-order-numbers-for-woocommerce.php' )){
$paypro_args['paypro_order_id'] = time().'-'.get_option( 'alg_wc_custom_order_numbers_counter', 1 );
}
else{
$paypro_args['paypro_order_id'] = time().'-'.$order_id;
}
// Shipping
if ($order->needs_shipping_address()) {
$paypro_args['ship_name'] = $order->get_shipping_first_name().' '.$order->get_shipping_last_name();
$paypro_args['company'] = $order->get_shipping_company();
$paypro_args['ship_street_address'] = $order->get_shipping_address_1();
$paypro_args['ship_street_address2'] = $order->get_shipping_address_2();
$paypro_args['ship_city'] = $order->get_shipping_city();
$paypro_args['ship_state'] = $order->get_shipping_state();
$paypro_args['ship_zip'] = $order->get_shipping_postcode();
$paypro_args['ship_country'] = $order->get_shipping_country();
}
$paypro_args['x_receipt_link_url'] = $this->get_return_url( $order );
$paypro_args['request_site_url'] = get_site_url();
$paypro_args['request_site_checkout_url'] = wc_get_checkout_url();
$paypro_args['return_url'] = $order->get_cancel_order_url();
$paypro_args['issueDate'] = date('d/m/Y');
$paypro_args['cartTotal'] = $order->get_total();
$paypro_args['store_currency'] = get_woocommerce_currency();
$paypro_args['store_currency_symbol'] = get_woocommerce_currency_symbol();
//Getting Cart Items
$billDetails= array();
$flag = 0;
foreach ($order->get_items() as $item => $values){
// Get the product name
$product_name = $values['name'];
// Get the item quantity
$item_quantity = $order->get_item_meta($item, '_qty', true);
// Get the item line total
$item_total = $order->get_item_meta($item, '_line_total', true);
$price = $item_total/$item_quantity;
$billDetails[$flag]['LineItem'] = esc_html($product_name);
$billDetails[$flag]['Quantity'] = $item_quantity;
$billDetails[$flag]['UnitPrice'] = $price;
$billDetails[$flag++]['SubTotal'] = $item_total;
}
$paypro_args['cartItemList'] = urlencode(json_encode($billDetails));
////
//setting payment method
if ($this->pay_method)
$paypro_args['pay_method'] = $this->pay_method;
//if test_mode is enabled
if ($this -> test_mode == 'yes'){
$paypro_args['test_mode'] = 'Y';
}
//if timeout_in_days is enabled
if ($this -> timeout_in_days == 'yes'){
$paypro_args['timeout'] = $this->timeout;
}
else{
$paypro_args['timeout'] = $this->timeout*60;
}
$paypro_args = apply_filters( 'woocommerce_paypro_args', $paypro_args );
return $paypro_args;
}
/**
* this function is return product object for two
* different version of WC
*/
function get_product_object(){
return $product;
}
/**
* Check for PayPro IPN Response
*
* #access public
* #return void
*/
function paypro_response() {
global $woocommerce;
// woocommerce_log($_REQUEST);
$this->log(__("== INS Response Received == ", "PayPro") );
$this->log( $_REQUEST );
$wc_order_id = '';
if( !isset($_REQUEST['merchant_order_id']) ) {
if( !isset($_REQUEST['vendor_order_id']) ) {
$this->log( '===== NO ORDER NUMBER FOUND =====' );
exit;
} else {
$wc_order_id = $_REQUEST['vendor_order_id'];
}
} else {
$wc_order_id = $_REQUEST['merchant_order_id'];
}
$this->log(" ==== ORDER -> {$wc_order_id} ====");
// echo $wc_order_id;
$wc_order_id = apply_filters('woocommerce_order_no_received', $wc_order_id, $_REQUEST);
$this->log( "Order Received ==> {$wc_order_id}" );
// exit;
$wc_order = new WC_Order( absint( $wc_order_id ) );
$this->log("Order ID {$wc_order_id}");
$this->log("WC API ==> ".$_GET['wc-api']);
// If redirect after payment
if( isset($_GET['key']) && (isset($_GET['wc-api']) && strtolower($_GET['wc-api']) == 'wc_gateway_mib_paypro') ) {
$this->verify_order_by_hash($wc_order_id);
exit;
}
$message_type = isset($_REQUEST['message_type']) ? $_REQUEST['message_type'] : '';
$sale_id = isset($_REQUEST['sale_id']) ? $_REQUEST['sale_id'] : '';
$invoice_id = isset($_REQUEST['invoice_id']) ? $_REQUEST['invoice_id'] : '';
$fraud_status = isset($_REQUEST['fraud_status']) ? $_REQUEST['fraud_status'] : '';
$this->log( "Message Type/Fraud Status: {$message_type}/{$fraud_status}" );
switch( $message_type ) {
case 'ORDER_CREATED':
$wc_order->add_order_note( sprintf(__('ORDER_CREATED with Sale ID: %d', 'woocommerce'), $sale_id) );
$this->log(sprintf(__('ORDER_CREATED with Sale ID: %d', 'woocommerce'), $sale_id));
break;
case 'FRAUD_STATUS_CHANGED':
if( $fraud_status == 'pass' ) {
// Mark order complete
$wc_order->payment_complete();
$wc_order->add_order_note( sprintf(__('Payment Status Clear with Invoice ID: %d', 'woocommerce'), $invoice_id) );
$this->log(sprintf(__('Payment Status Clear with Invoice ID: %d', 'woocommerce'), $invoice_id));
add_action('woocommerce_order_completed', $order, $sale_id, $invoice_id);
} elseif( $fraud_status == 'fail' ) {
$wc_order->update_status('failed');
$wc_order->add_order_note( __("Payment Declined", 'woocommerce') );
$this->log( __("Payment Declined", 'woocommerce') );
}
break;
}
exit;
}
function verify_order_by_hash($wc_order_id) {
global $woocommerce;
#ob_clean();
$paypro_id = $_REQUEST['paypro_id'];
$tpaycode = $_REQUEST['tpaycode'];
$order_id = $_REQUEST['merchant_order_id'];
$wc_order = wc_get_order( $wc_order_id );
// $order_total = isset($_REQUEST['total']) ? $_REQUEST['total'] : '';
$order_total = $wc_order->get_total();
$compare_string = $this->merchant_id . $paypro_id . $order_total;
$compare_hash1 = strtoupper(md5($compare_string));
$this->log("Compare String ===>" .$compare_string);
$compare_hash2 = $_REQUEST['key'];
if ($compare_hash1 != $compare_hash2) {
$this->log("Hash_1 ==> {$compare_hash1}");
$this->log("Hash_2 ==> {$compare_hash2}");
wp_die( "PayPro Hash Mismatch... check your secret word." );
} else {
//Curl Request
$url = $this->api_url.'/cpay/gos?userName=' . $this->merchant_id . '&password=' . $this->merchant_password . '&cpayId=' . $tpaycode;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
// Submit the GET request
$result = curl_exec($ch);
if (curl_errno($ch)) //catch if curl error exists and show it
echo 'Curl error: ' . curl_error($ch);
else {
//Check if the order ID passed is the same or fake
$res = json_decode($result, true);
$returnedOrderID = explode('-',$res[1]['OrderNumber']);
if ($returnedOrderID[1]===$order_id) {
if (strtoupper($res[1]['OrderStatus']) == "PAID") {
$wc_order->add_order_note( sprintf(__('Payment completed via PayPro Order Number %d', 'paypro'), $tpaycode) );
// Mark order complete
$wc_order->payment_complete();
// Empty cart and clear session
$woocommerce->cart->empty_cart();
$order_redirect = add_query_arg('paypro','processed', $this->get_return_url( $wc_order ));
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
} elseif (strtoupper($res[1]['OrderStatus']) == "BLOCKED") {
$wc_order->add_order_note( sprintf(__('Error processing the payment of Order Number %d', 'paypro'), $tpaycode) );
$order_redirect = add_query_arg('paypro','canceled', $wc_order->get_cancel_order_url());
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
}
elseif (strtoupper($res[1]['OrderStatus']) == "UNPAID") {
$wc_order->add_order_note( sprintf(__('Error processing the payment of Order Number %d', 'paypro'), $tpaycode) );
$order_redirect = add_query_arg('paypro','pending', $wc_order->get_cancel_order_url());
// Close cURL session handle
curl_close($ch);
wp_redirect( $order_redirect );
exit;
}
}
}
}
}
function get_price($price){
$price = wc_format_decimal($price, 2);
return apply_filters('mib_get_price', $price);
}
}
}
function add_mib_payment_gateway( $methods ) {
$methods[] = 'WC_Gateway_MIB_PayPro';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'add_mib_payment_gateway' );
function payproco_log( $log ) {
if ( true === WP_DEBUG ) {
if ( is_array( $log ) || is_object( $log ) ) {
$resp = error_log( print_r( $log, true ), 3, plugin_dir_path(__FILE__).'payproco.log' );
} else {
$resp = error_log( $log, 3, plugin_dir_path(__FILE__).'payproco.log' );
}
var_dump($resp);
}
}
I have run all my code to be active the subscription but its didn't, still is in authenticated process, please help me how can i active razorpay subscription. I created a plan using the api and get a response of planid
$key_id = '';
$key_secret = '';
$startTime = (time()+300);
$amount = '400';
$currency_code = 'INR';
//Create plan for user
$planReqdata = array(
'period' => 'daily',
'interval' => 7,
'item' => array(
'name' => 'Test daily 1 plan',
'description' => 'Description for the daily 1 plan',
'amount' => $amount,
'currency' => $currency_code
)
);
$planurl = 'https://api.razorpay.com/v1/plans';
$palnparams = http_build_query($planReqdata);
//cURL Request
$planch = curl_init();
//set the url, number of POST vars, POST planReqdata
curl_setopt($planch, CURLOPT_URL, $planurl);
curl_setopt($planch, CURLOPT_USERPWD, $key_id . ':' . $key_secret);
curl_setopt($planch, CURLOPT_TIMEOUT, 60);
curl_setopt($planch, CURLOPT_POST, 1);
curl_setopt($planch, CURLOPT_POSTFIELDS, $palnparams);
curl_setopt($planch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($planch, CURLOPT_SSL_VERIFYPEER, true);
$planResult = curl_exec($planch);
$planRes = json_decode($planResult);
//echo $planRes->id;
Using the plan id i have created a subscription and get a response of subscription id
//Create subscription for user
$subdata = array(
'plan_id' => $planRes->id,
'customer_notify' => 1,
'total_count' => 6,
'start_at' => $startTime,
'addons' => array(
array(
'item' => array(
'name' => 'Delivery charges',
'amount' => $amount,
'currency' => $currency_code
)
)
)
);
$suburl = 'https://api.razorpay.com/v1/subscriptions';
$subparams = http_build_query($subdata);
//cURL Request
$subch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($subch, CURLOPT_URL, $suburl);
curl_setopt($subch, CURLOPT_USERPWD, $key_id . ':' . $key_secret);
curl_setopt($subch, CURLOPT_TIMEOUT, 60);
curl_setopt($subch, CURLOPT_POST, 1);
curl_setopt($subch, CURLOPT_POSTFIELDS, $subparams);
curl_setopt($subch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($subch, CURLOPT_SSL_VERIFYPEER, true);
$subResult = curl_exec($subch);
$subres = json_decode($subResult);
//echo $subres->id;
Using the subscription id i have call checkout script
<button id = "rzp-button1">Pay</button>
<script src = "https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
var options = {
"key": "<?php echo $key_id; ?>",
"subscription_id": "<?php echo $subres->id; ?>",
"name": "Test.",
"description": "Daily Test Plan",
"image": "http://localhost/iac/images/logo.png",
"callback_url": "http://localhost/iac/subres.php",
"prefill": {
"name": "Atanu",
"email": "atanu#example.com",
"contact": "+919876543210"
},
"notes": {
"note_key_1": "Tea. Earl Grey. Hot",
"note_key_2": "Make it so."
},
"theme": {
"color": "#F37254"
}
};
var rzp1 = new Razorpay(options);
document.getElementById('rzp-button1').onclick = function(e) {
rzp1.open();
e.preventDefault();
}
</script>
And pass the response to the below code to fulfill the payment
$razorpayPaymentId = $_POST['razorpay_payment_id'];
$subscriptionId= $_POST['razorpay_subscription_id'];
$secret = '########';
$razorpaySignature = $_POST['razorpay_signature'];
$expectedSignature = hash_hmac('SHA256', $razorpayPaymentId . '|' . $subscriptionId, $secret);
//$expectedSignature = hash_hmac(self::SHA256, $razorpayPaymentId . '|' . $subscriptionId, $secret);
if ($expectedSignature === $razorpaySignature)
{
echo "Payment is successful!";
}
There is no issue, it's just that when you specify a start date, it will not charge an immediate subscription, so creating a subscription without a start date would immediately make an active subscription.
For further information on why, follow the section Make an Authorized Payment on the following link. There it explains the format of Subscription A which is an instant payment subscription format.
Razorpay Subscription: Make an Authorized Payment
Im trying to create a custom module plugin in drupal 7, but im having any issues that i cant resolve.
I've created other plugins previously, but this is provoke to me more problems that i supposed.
Well, im creating any charts with Progressbar.js library. The idea is generate one chart per plugin, filling the form fields from page_manager, for example, if i want to create 3 charts in any page of my site, i should call 3 plugins.
The problem is that when i go to the page where the charts must to show, only generate one chart (last plugin that i call from pane).
The logic of operation, is that I enter the values of the fields through the form of the plugin. These values are sent to the script to generate the graphics with the library ProgressBar.js and thus render the graphic to html.
I noticed that the plugin is not sending the data to the javascript script. Just send the data to the script the last plugin that I created. The previous two do not. When i use console.log in the script, only get values from last plugin, when it should show 3 logs with their respectives values.
This is directory of my custom module.
├── obs_home_page.features.inc
├── obs_home_page.info
├── obs_home_page.module
├── obs_home_page.pages_default.inc
├── plugins
│ └── content_types
│ ├── obs_home_page_show.inc
└── scripts
└── ProgressBar.js
obs_home_page.module:
<?php
/**
* #file
* Code for the Home page feature.
*/
include_once 'obs_home_page.features.inc';
function obs_home_page_ctools_plugin_directory($owner, $plugin) {
return 'plugins/' . $plugin;
}
obs_home_page_show.inc:
<?php
$plugin = array(
'single' => TRUE, // Just do this one, it is needed.
'title' => t('Relojes'), // Title to show up on the pane screen.
'description' => t('Reloj de derecho ipara la portada home'), // Description to show up on the pane screen.
'category' => t('Custom'), // A category to put this under.
'edit form' => 'obs_home_page_show_edit_form', // A function that will return the settings form for the pane.
'render callback' => 'obs_home_page_show_render', // A function that will return the renderable content.
'admin info' => 'obs_home_page_show_admin_info', // A function that will return the information displayed on the admin screen (optional).
'defaults' => array( // Array of defaults for the settings form.
'right' => '',
'maxValue' => '33',
'value' => '',
'description' => ''
),
'all contexts' => TRUE, // This is NEEDED to be able to use substitution strings in your pane.
);
/**
* An edit form for the pane's settings.
*/
function obs_home_page_show_edit_form($form, &$form_state) {
$conf = $form_state['conf'];
$form['right'] = array(
'#title' => t('Right'),
'#description' => t('Right ID'),
'#type' => 'textfield',
'#required' => TRUE,
'#default_value' => !empty($conf['right']) ? $conf['right'] : '',
);
$form['description'] = array(
'#title' => t('Description'),
'#description' => t('Right description'),
'#type' => 'textfield',
'#default_value' => !empty($conf['description']) ? $conf['description'] : '',
);
$form['maxValue'] = array(
'#title' => t('Max value'),
'#description' => t('Max value'),
'#type' => 'textfield',
'#size' => 11,
'#default_value' => !empty($conf['maxValue']) ? $conf['maxValue'] : '',
);
$form['value'] = array(
'#title' => t('Value'),
'#description' => t('Value'),
'#type' => 'textfield',
'#size' => 11,
'#required' => TRUE,
'#default_value' => !empty($conf['value']) ? $conf['value'] : '',
);
return $form;
}
/**
* Submit function, note anything in the formstate[conf] automatically gets saved
* Notice, the magic that automatically does that for you.
*/
function obs_home_page_show_edit_form_submit(&$form, &$form_state) {
foreach (array_keys($form_state['plugin']['defaults']) as $key) {
if (isset($form_state['values'][$key])) {
$form_state['conf'][$key] = $form_state['values'][$key];
}
}
}
/**
* Run-time rendering of the body of the block (content type)
* See ctools_plugin_examples for more advanced info
*/
function obs_home_page_show_render($subtype, $conf, $panel_args, $context) {
//Check context and validates input for each config field.
if (!empty($context) && !empty($conf['right']) && check_plain($conf['right'])) {
$right = ctools_context_keyword_substitute($conf['right'], array(), $context);
} else {
$right = arg(1); //fallback, uses the current nid
}
if (!empty($context) && !empty($conf['description']) && check_plain($conf['description'])) {
$description = ctools_context_keyword_substitute($conf['description'], array(), $context);
} else {
$description = null;
}
if (!empty($context) && !empty($conf['maxValue']) && check_plain($conf['maxValue'])) {
$maxValue = ctools_context_keyword_substitute($conf['maxValue'], array(), $context);
} else {
$maxValue = null;
}
if (!empty($context) && !empty($conf['value']) && check_plain($conf['value'])) {
$value = ctools_context_keyword_substitute($conf['value'], array(), $context);
} else {
$value = null;
}
$right = intval($conf['right']);
$maxValue = intval($conf['maxValue']);
$value = intval($conf['value']);
$tid = taxonomy_term_load($right);
$right_name = $tid->name;
$right_description = $tid->description;
if (empty($conf['description'])) {
$description = $right_description;
} else {
$description = $conf['description'];
}
$settings = array();
$settings['clock']['right'] = $right;
$settings['clock']['maxValue'] = $maxValue;
$settings['clock']['value'] = $value;
dsm($settings);
drupal_add_js($settings, 'setting');
drupal_add_js(drupal_get_path('module', 'obs_home_page') . '/scripts/ProgressBar.js');
dsm(drupal_get_path('module', 'obs_home_page') . '/scripts/ProgressBar.js');
$output = array(
'#type' => 'markup',
'#markup' => '<div class="home_page_progressbar">
<a href="'. base_path() .'taxonomy/term/'. $right .'">
<div id="progressbar-'. $right .'"></div>
<h2>'. $right_name .'</h2>
</a>
<div class="descripcion_clock_right_home">'. $description .'</div>
</div>',
);
$block = new stdClass();
$block->title = '';
$block->content = $output;
return $block;
}
/**
* 'admin info' callback for panel pane.
*/
function obs_home_page_show_admin_info($subtype, $conf, $contexts) {
if (!empty($conf)) {
$block = new stdClass;
$block->title = $conf['override_title'] ? $conf['override_title_text'] : '';
$block->content = t('<strong>Max Value:</strong> #maxValue<br />
<strong>Value:</strong> #value</p>',
array(
'#maxValue' => $conf['maxValue'],
'#value' => $conf['value'],
));
return $block;
}
}
ProgressBar.js:
/**
* #file Creacion de relojes para la portada home con libreria ProgressBar
*
*/
(function ($) {
Drupal.behaviors.obs_home_page = {
attach: function (context, settings) {
GenerarReloj(settings);
}
};
var GenerarReloj = function (settings) {
var right = parseInt(settings.clock.right);
var nominator = parseInt(settings.clock.value);
var denominator = parseInt(settings.clock.maxValue);
var bar_information = new ProgressBar.Circle('#progressbar-' + right, {
color: '#aaa',
// This has to be the same size as the maximum width to
// prevent clipping
strokeWidth: 10,
trailWidth: 10,
easing: 'easeInOut',
duration: 2000,
text: {
autoStyleContainer: false
},
from: { color: '#C5DC70', width: 10 },
to: { color: '#728530', width: 10 },
// Set default step function for all animate calls
step: function(state, circle) {
circle.path.setAttribute('stroke', state.color);
circle.path.setAttribute('stroke-width', state.width);
var value = Math.round(circle.value() * denominator);
if (value === 0) {
circle.setText('');
} else {
circle.setText(value);
}
}
});
// bar.text.style.fontFamily = '"Raleway", Helvetica, sans-serif';
bar_information.text.style.fontSize = '3rem';
var quotient = nominator / denominator;
bar_information.animate(quotient); // Number from 0.0 to 1.0
}
})(jQuery);
I have used dropzone js to upload multiple image.
My code looks like below.
var s_currency = $('select[name="currency"]');
Dropzone.autoDiscover = false;
if($('#dropzoneDragArea').length > 0){
var expenseDropzone = new Dropzone("#expense-form", {
autoProcessQueue: false,
clickable: '#dropzoneDragArea',
acceptedFiles:allowed_files,
previewsContainer: '.dropzone-previews',
addRemoveLinks: true,
//maxFiles: 1,
//parallelUploads: 1,
uploadMultiple: true,
dictDefaultMessage:drop_files_here_to_upload,
dictFallbackMessage:browser_not_support_drag_and_drop,
dictRemoveFile:remove_file,
dictMaxFilesExceeded:you_can_not_upload_any_more_files,
error:function(file,response){
alert_float('danger',response);
},
success:function(file,response){
response = $.parseJSON(response);
this.options.autoProcessQueue = true;
if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0) {
window.location.assign(response.url);
}
},
});
}
$(document).ready(function(){
_validate_form($('form'),{category:'required',date:'required',amount:'required',currency:'required'},expenseSubmitHandler);
$('input[name="billable"]').on('change',function(){
do_billable_checkbox();
});
});
function expenseSubmitHandler(form){
s_currency.removeAttr('disabled');
$('input[name="billable"]').prop('disabled',false);
$.post(form.action, $(form).serialize()).success(function(response) {
response = $.parseJSON(response);
if (response.expenseid) {
if(typeof(expenseDropzone) !== 'undefined'){
//console.log(expenseDropzone.getQueuedFiles().length);return;
if (expenseDropzone.getQueuedFiles().length > 0) {
expenseDropzone.options.url = admin_url + 'expenses/add_expense_attachment/' + response.expenseid;
expenseDropzone.processQueue();
} else {
window.location.assign(response.url);
}
} else {
window.location.assign(response.url);
}
} else {
window.location.assign(response.url);
}
});
return false;
}
<form action="http://127.0.0.1/perfex_crm_aug_25/admin/expenses/expense" id="expense-form" class="dropzone dropzone-manual" enctype="multipart/form-data" method="post" accept-charset="utf-8" novalidate="novalidate">
<div id="dropzoneDragArea" class="dz-default dz-message">
<span>Attach file here</span>
</div>
<div class="dropzone-previews"></div>
<button type="submit" class="btn btn-info pull-right mtop15">Submit</button>
</form>
My controler looks like this :
public function expense($id = '')
{
if (!has_permission('expenses', '', 'view')) {
access_denied('expenses');
}
if ($this->input->post()) {
if ($id == '') {
if (!has_permission('expenses', '', 'create')) {
set_alert('danger', _l('access_denied'));
echo json_encode(array(
'url' => admin_url('expenses/expense')
));
die;
}
$id = $this->expenses_model->add($this->input->post());
if ($id) {
set_alert('success', _l('added_successfuly', _l('expense')));
echo json_encode(array(
'url' => admin_url('expenses/list_expenses/' . $id),
'expenseid' => $id
));
die;
}
echo json_encode(array(
'url' => admin_url('expenses/expense')
));
die;
} else {
if (!has_permission('expenses', '', 'edit')) {
set_alert('danger', _l('access_denied'));
echo json_encode(array(
'url' => admin_url('expenses/expense/' . $id)
));
die;
}
$success = $this->expenses_model->update($this->input->post(), $id);
if ($success) {
set_alert('success', _l('updated_successfuly', _l('expense')));
}
echo json_encode(array(
'url' => admin_url('expenses/list_expenses/' . $id),
'expenseid' => $id
));
die;
}
}
if ($id == '') {
$title = _l('add_new', _l('expense_lowercase'));
} else {
$data['expense'] = $this->expenses_model->get($id);
$title = _l('edit', _l('expense_lowercase'));
//echo "<pre>";
//print_r($data['expense']);
}
if($this->input->get('customer_id')){
$data['customer_id'] = $this->input->get('customer_id');
$data['do_not_auto_toggle'] = true;
}
$this->load->model('taxes_model');
$this->load->model('payment_modes_model');
$this->load->model('currencies_model');
$this->load->model('projects_model');
$data['customers'] = $this->clients_model->get();
$data['taxes'] = $this->taxes_model->get();
$data['categories'] = $this->expenses_model->get_category();
$data['supplier'] = $this->expenses_model->get_supplier();
//print_r($data['supplier']);
$data['payment_modes'] = $this->payment_modes_model->get();
$data['currencies'] = $this->currencies_model->get();
$data['title'] = $title;
$this->load->view('admin/expenses/expense', $data);
}
I have also created helper for uploading image. That function looks like below :
function handle_lead_attachments($leadid)
{
if(isset($_FILES['file']) && _perfex_upload_error($_FILES['file']['error'])){
header('HTTP/1.0 400 Bad error');
echo _perfex_upload_error($_FILES['file']['error']);
die;
}
$CI =& get_instance();
if (isset($_FILES['file']['name']) && $_FILES['file']['name'] != '') {
do_action('before_upload_lead_attachment',$leadid);
$path = LEAD_ATTACHMENTS_FOLDER . $leadid . '/';
// Get the temp file path
$tmpFilePath = $_FILES['file']['tmp_name'];
// Make sure we have a filepath
if (!empty($tmpFilePath) && $tmpFilePath != '') {
// Setup our new file path
if (!file_exists($path)) {
mkdir($path);
fopen($path . 'index.html', 'w');
}
$filename = unique_filename($path, $_FILES["file"]["name"]);
$newFilePath = $path . $filename;
// Upload the file into the company uploads dir
if (move_uploaded_file($tmpFilePath, $newFilePath)) {
$CI =& get_instance();
$CI->db->insert('tblleadattachments', array(
'leadid' => $leadid,
'file_name' => $filename,
'filetype' => $_FILES["file"]["type"],
'addedfrom' => get_staff_user_id(),
'dateadded' => date('Y-m-d H:i:s')
));
$CI->load->model('leads_model');
$CI->leads_model->log_lead_activity($leadid, 'not_lead_activity_added_attachment');
return true;
}
}
}
return false;
}
Here, when I have upload one image than its working fine.But when I have tried to upload multiple image than it store other data image column has pass null value.
So what should I have to change in My code to upload multiple image. I have used perfex-crm project. I have to modify its expence module.