1
0
mirror of synced 2025-01-18 08:51:41 +03:00
This commit is contained in:
Alex Lushpai 2017-06-07 16:29:57 +03:00
parent 4c654b5eba
commit 295c58e4a8
19 changed files with 4193 additions and 1 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017 retailCRM
Copyright (c) 2017 RetailDriver LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -0,0 +1 @@
<?php // Silence is golden

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
<?php
/**
* PHP version 5.3
*
* WC_Retailcrm_Exception_Curl class
*
* @category Retailcrm
* @package WC_Retailcrm_Exception_Curl
* @author Retailcrm <dev@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://retailcrm.ru/docs/Developers/ApiVersion4
*/
class WC_Retailcrm_Exception_Curl extends \RuntimeException
{
}

View File

@ -0,0 +1,17 @@
<?php
/**
* PHP version 5.3
*
* WC_Retailcrm_Exception_Json class
*
* @category Retailcrm
* @package WC_Retailcrm_Exception_Json
* @author Retailcrm <dev@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://retailcrm.ru/docs/Developers/ApiVersion4
*/
class WC_Retailcrm_Exception_Json extends \DomainException
{
}

View File

@ -0,0 +1,63 @@
<?php
/**
* Retailcrm Integration.
*
* @package WC_Retailcrm_Proxy
* @category Integration
* @author Retailcrm
*/
if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) :
/**
* Class WC_Retailcrm_Proxy
*/
class WC_Retailcrm_Proxy
{
public function __construct($api_url, $api_key)
{
$this->logger = new WC_Logger();
if ( ! class_exists( 'WC_Retailcrm_Client' ) ) {
include_once( __DIR__ . '/class-wc-retailcrm-client.php' );
}
if ($api_url && $api_key) {
$this->retailcrm = new WC_Retailcrm_Client($api_url, $api_key);
}
}
public function __call($method, $arguments)
{
try {
$response = call_user_func_array(array($this->retailcrm, $method), $arguments);
if ($response->isSuccessful()) {
$result = ' Ok';
} else {
$result = sprintf(
$method ." : Error: [HTTP-code %s] %s",
$response->getStatusCode(),
$response->getErrorMsg()
);
if (isset($response['errors'])) {
foreach ($response['errors'] as $error) {
$result .= " $error";
}
}
}
$this->logger->add('retailcrm', sprintf("[%s] %s", $method, $result));
} catch (WC_Retailcrm_Exception_Curl $exception) {
$this->logger->add('retailcrm', sprintf("[%s] %s - %s", $method, $exception->getMessage(), $result));
} catch (WC_Retailcrm_Exception_Json $exception) {
$this->logger->add('retailcrm', sprintf("[%s] %s - %s", $method, $exception->getMessage(), $result));
} catch (InvalidArgumentException $exception) {
$this->logger->add('retailcrm', sprintf("[%s] %s - %s", $method, $exception->getMessage(), $result));
}
return $response;
}
}
endif;

View File

@ -0,0 +1,118 @@
<?php
/**
* PHP version 5.3
*
* Request class
*
* @category Integration
* @package WC_Retailcrm_Request
* @author Retailcrm <dev@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://retailcrm.ru/docs/Developers/ApiVersion4
*/
if ( ! class_exists( 'WC_Retailcrm_Exception_Curl' ) ) {
include_once( __DIR__ . '/class-wc-retailcrm-exception-curl.php' );
}
if ( ! class_exists( 'WC_Retailcrm_Response' ) ) {
include_once( __DIR__ . '/class-wc-retailcrm-response.php' );
}
class WC_Retailcrm_Request
{
const METHOD_GET = 'GET';
const METHOD_POST = 'POST';
protected $url;
protected $defaultParameters;
/**
* Client constructor.
*
* @param string $url api url
* @param array $defaultParameters array of parameters
*
* @throws \InvalidArgumentException
*/
public function __construct($url, array $defaultParameters = array())
{
if (false === stripos($url, 'https://')) {
throw new \InvalidArgumentException(
'API schema requires HTTPS protocol'
);
}
$this->url = $url;
$this->defaultParameters = $defaultParameters;
}
/**
* Make HTTP request
*
* @param string $path request url
* @param string $method (default: 'GET')
* @param array $parameters (default: array())
*
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*
* @throws \InvalidArgumentException
* @throws WC_Retailcrm_Exception_Curl
*
* @return WC_Retailcrm_Response
*/
public function makeRequest(
$path,
$method,
array $parameters = array()
) {
$allowedMethods = array(self::METHOD_GET, self::METHOD_POST);
if (!in_array($method, $allowedMethods, false)) {
throw new \InvalidArgumentException(
sprintf(
'Method "%s" is not valid. Allowed methods are %s',
$method,
implode(', ', $allowedMethods)
)
);
}
$parameters = array_merge($this->defaultParameters, $parameters);
$url = $this->url . $path;
if (self::METHOD_GET === $method && count($parameters)) {
$url .= '?' . http_build_query($parameters, '', '&');
}
$curlHandler = curl_init();
curl_setopt($curlHandler, CURLOPT_URL, $url);
curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curlHandler, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curlHandler, CURLOPT_FAILONERROR, false);
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curlHandler, CURLOPT_TIMEOUT, 30);
curl_setopt($curlHandler, CURLOPT_CONNECTTIMEOUT, 30);
if (self::METHOD_POST === $method) {
curl_setopt($curlHandler, CURLOPT_POST, true);
curl_setopt($curlHandler, CURLOPT_POSTFIELDS, $parameters);
}
$responseBody = curl_exec($curlHandler);
$statusCode = curl_getinfo($curlHandler, CURLINFO_HTTP_CODE);
$errno = curl_errno($curlHandler);
$error = curl_error($curlHandler);
curl_close($curlHandler);
if ($errno) {
throw new WC_Retailcrm_Exception_Curl($error, $errno);
}
return new WC_Retailcrm_Response($statusCode, $responseBody);
}
}

View File

@ -0,0 +1,170 @@
<?php
/**
* PHP version 5.3
*
* Response class
*
* @category Integration
* @package WC_Retailcrm_Response
* @author Retailcrm <dev@retailcrm.ru>
* @license https://opensource.org/licenses/MIT MIT License
* @link http://retailcrm.ru/docs/Developers/ApiVersion4
*/
if ( ! class_exists( 'WC_Retailcrm_Exception_Json' ) ) {
include_once( __DIR__ . '/class-wc-retailcrm-exception-json.php' );
}
class WC_Retailcrm_Response implements \ArrayAccess
{
// HTTP response status code
protected $statusCode;
// response assoc array
protected $response;
/**
* ApiResponse constructor.
*
* @param int $statusCode HTTP status code
* @param mixed $responseBody HTTP body
*
* @throws WC_Retailcrm_Exception_Json
*/
public function __construct($statusCode, $responseBody = null)
{
$this->statusCode = (int) $statusCode;
if (!empty($responseBody)) {
$response = json_decode($responseBody, true);
if (!$response && JSON_ERROR_NONE !== ($error = json_last_error())) {
throw new WC_Retailcrm_Exception_Json(
"Invalid JSON in the API response body. Error code #$error",
$error
);
}
$this->response = $response;
}
}
/**
* Return HTTP response status code
*
* @return int
*/
public function getStatusCode()
{
return $this->statusCode;
}
/**
* HTTP request was successful
*
* @return bool
*/
public function isSuccessful()
{
return $this->statusCode < 400;
}
/**
* Allow to access for the property throw class method
*
* @param string $name method name
* @param mixed $arguments method parameters
*
* @throws \InvalidArgumentException
*
* @return mixed
*/
public function __call($name, $arguments)
{
// convert getSomeProperty to someProperty
$propertyName = strtolower(substr($name, 3, 1)) . substr($name, 4);
if (!isset($this->response[$propertyName])) {
throw new \InvalidArgumentException("Method \"$name\" not found");
}
return $this->response[$propertyName];
}
/**
* Allow to access for the property throw object property
*
* @param string $name property name
*
* @throws \InvalidArgumentException
*
* @return mixed
*/
public function __get($name)
{
if (!isset($this->response[$name])) {
throw new \InvalidArgumentException("Property \"$name\" not found");
}
return $this->response[$name];
}
/**
* Offset set
*
* @param mixed $offset offset
* @param mixed $value value
*
* @throws \BadMethodCallException
* @return void
*/
public function offsetSet($offset, $value)
{
throw new \BadMethodCallException('This activity not allowed');
}
/**
* Offset unset
*
* @param mixed $offset offset
*
* @throws \BadMethodCallException
* @return void
*/
public function offsetUnset($offset)
{
throw new \BadMethodCallException('This call not allowed');
}
/**
* Check offset
*
* @param mixed $offset offset
*
* @return bool
*/
public function offsetExists($offset)
{
return isset($this->response[$offset]);
}
/**
* Get offset
*
* @param mixed $offset offset
*
* @throws \InvalidArgumentException
*
* @return mixed
*/
public function offsetGet($offset)
{
if (!isset($this->response[$offset])) {
throw new \InvalidArgumentException("Property \"$offset\" not found");
}
return $this->response[$offset];
}
}

View File

@ -0,0 +1 @@
<?php // Silence is golden

View File

@ -0,0 +1,212 @@
<?php
/**
* Retailcrm Integration.
*
* @package WC_Retailcrm_Base
* @category Integration
* @author Retailcrm
*/
if ( ! class_exists( 'WC_Retailcrm_Base' ) ) :
/**
* Class WC_Retailcrm_Base
*/
class WC_Retailcrm_Base extends WC_Integration {
protected $api_url;
protected $api_key;
/**
* Init and hook in the integration.
*/
public function __construct() {
//global $woocommerce;
$this->id = 'integration-retailcrm';
$this->method_title = __( 'Retailcrm', 'woocommerce-integration-retailcrm' );
$this->method_description = __( 'Интеграция с системой управления Retailcrm.', 'woocommerce-integration-retailcrm' );
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Actions.
add_action( 'woocommerce_update_options_integration_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* Initialize integration settings form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
array( 'title' => __( 'Общие настройки', 'woocommerce' ), 'type' => 'title', 'desc' => '', 'id' => 'general_options' ),
'api_url' => array(
'title' => __( 'API URL', 'woocommerce-integration-retailcrm' ),
'type' => 'text',
'description' => __( 'Введите адрес вашей CRM (https://yourdomain.retailcrm.ru).', 'woocommerce-integration-retailcrm' ),
'desc_tip' => true,
'default' => ''
),
'api_key' => array(
'title' => __( 'API Ключ', 'woocommerce-integration-retailcrm' ),
'type' => 'text',
'description' => __( 'Введите ключ API. Вы можете найти его в интерфейсе администратора Retailcrm.', 'woocommerce-integration-retailcrm' ),
'desc_tip' => true,
'default' => ''
)
);
if ($this->get_option( 'api_url' ) != '' && $this->get_option( 'api_key' ) != '') {
if ( ! class_exists( 'WC_Retailcrm_Client' ) ) {
include_once( __DIR__ . '/api/class-wc-retailcrm-client.php' );
}
$retailcrm = new WC_Retailcrm_Client(
$this->get_option( 'api_url' ),
$this->get_option( 'api_key' )
);
/**
* Shipping options
*/
$shipping_option_list = array();
$retailcrm_shipping_list = $retailcrm->deliveryTypesList();
foreach ($retailcrm_shipping_list['deliveryTypes'] as $retailcrm_shipping_type) {
$shipping_option_list[$retailcrm_shipping_type['code']] = $retailcrm_shipping_type['name'];
}
$wc_shipping = new WC_Shipping();
$wc_shipping_list = $wc_shipping->get_shipping_methods();
$this->form_fields[] = array(
'title' => __( 'Способы доставки', 'woocommerce' ),
'type' => 'title',
'description' => '',
'id' => 'shipping_options'
);
foreach ( $wc_shipping_list as $shipping ) {
if ( isset( $shipping->enabled ) && $shipping->enabled == 'yes' ) {
$key = $shipping->id;
$name = $key;
$this->form_fields[$name] = array(
'title' => __( $shipping->method_title, 'textdomain' ),
'description' => __( $shipping->method_description, 'textdomain' ),
'css' => 'min-width:350px;',
'class' => 'select',
'type' => 'select',
'options' => $shipping_option_list,
'desc_tip' => true,
);
}
}
/**
* Payment options
*/
$payment_option_list = array();
$retailcrm_payment_list = $retailcrm->paymentTypesList();
foreach ($retailcrm_payment_list['paymentTypes'] as $retailcrm_payment_type) {
$payment_option_list[$retailcrm_payment_type['code']] = $retailcrm_payment_type['name'];
}
$wc_payment = new WC_Payment_Gateways();
$wc_payment_list = $wc_payment->get_available_payment_gateways();
$this->form_fields[] = array(
'title' => __( 'Способы оплаты', 'woocommerce' ),
'type' => 'title',
'description' => '',
'id' => 'payment_options'
);
foreach ( $wc_payment_list as $payment ) {
if ( isset( $payment->enabled ) && $payment->enabled == 'yes' ) {
$key = $payment->id;
$name = $key;
$this->form_fields[$name] = array(
'title' => __( $payment->method_title, 'textdomain' ),
'description' => __( $payment->method_description, 'textdomain' ),
'css' => 'min-width:350px;',
'class' => 'select',
'type' => 'select',
'options' => $payment_option_list,
'desc_tip' => true,
);
}
}
/**
* Statuses options
*/
$statuses_option_list = array();
$retailcrm_statuses_list = $retailcrm->statusesList();
foreach ($retailcrm_statuses_list['statuses'] as $retailcrm_status) {
$statuses_option_list[$retailcrm_status['code']] = $retailcrm_status['name'];
}
$wc_statuses = wc_get_order_statuses();
$this->form_fields[] = array(
'title' => __( 'Статусы', 'woocommerce' ),
'type' => 'title',
'description' => '',
'id' => 'statuses_options'
);
foreach ( $wc_statuses as $idx => $name ) {
$uid = str_replace('wc-', '', $idx);
$this->form_fields[$uid] = array(
'title' => __( $name, 'textdomain' ),
'css' => 'min-width:350px;',
'class' => 'select',
'type' => 'select',
'options' => $statuses_option_list,
'desc_tip' => true,
);
}
$this->form_fields[] = array(
'title' => __( 'Настройки остатков', 'woocommerce' ),
'type' => 'title',
'description' => '',
'id' => 'invent_options'
);
$this->form_fields['sync'] = array(
'label' => __( 'Выгружать остатки из CRM', 'textdomain' ),
'title' => 'Остатки',
'class' => 'checkbox',
'type' => 'checkbox',
'description' => 'Отметьте данный пункт, если хотите выгружать остатки товаров из CRM в магазин.'
);
$this->form_fields[] = array(
'title' => __( 'Настройки выгрузки', 'woocommerce' ),
'type' => 'title',
'description' => '',
'id' => 'upload_options'
);
$this->form_fields['uploadToCrm'] = array(
'label' => __( 'Выгрузить все заказы и клиентов', 'textdomain' ),
'title' => 'Выгрузка заказов и клиентов',
'class' => 'checkbox',
'type' => 'checkbox',
'description' => 'Поставьте галочку, и нажмите сохранить, чтобы выгрузить все существующие заказы и клиентов.'
);
}
}
}
endif;

View File

@ -0,0 +1,121 @@
<?php
/**
* Retailcrm Integration.
*
* @package WC_Retailcrm_Customers
* @category Integration
* @author Retailcrm
*/
if ( ! class_exists( 'WC_Retailcrm_Customers' ) ) :
/**
* Class WC_Retailcrm_Customers
*/
class WC_Retailcrm_Customers
{
public function __construct()
{
$this->retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
}
$this->retailcrm = new WC_Retailcrm_Proxy(
$this->retailcrm_settings['api_url'],
$this->retailcrm_settings['api_key']
);
}
public function customersUpload()
{
$users = get_users();
$data_customers = array();
foreach ($users as $user) {
if ($user->roles[0] != 'customer') continue;
$customer = new WC_Customer($user->ID);
$data_customer = array(
'createdAt' => $user->data->user_registered,
'externalId' => $user->ID,
'firstName' => !empty($customer->get_first_name()) ? $customer->get_first_name() : $customer->get_username(),
'lastName' => $customer->get_last_name(),
'email' => $user->data->user_email,
'phones' => array(
array(
'number' => $customer->get_billing_phone()
)
),
'address' => array(
'index' => $customer->get_billing_postcode(),
'countryIso' => $customer->get_billing_country(),
'region' => $customer->get_billing_state(),
'city' => $customer->get_billing_city(),
'text' => $customer->get_billing_address_1() . ',' . $customer->get_billing_address_2()
)
);
$data_customers[] = $data_customer;
}
$data = array_chunk($data_customers, 50);
foreach ($data as $array_customers) {
$this->retailcrm->customersUpload($array_customers);
}
}
public function createCustomer($customer_id)
{
$customer = new WC_Customer($customer_id);
if ($customer->get_role() == 'customer'){
$data_customer = $this->processCustomer($customer);
$this->retailcrm->customersCreate($data_customer);
}
}
public function updateCustomer($customer_id)
{
$customer = new WC_Customer($customer_id);
if ($customer->get_role() == 'customer'){
$data_customer = $this->processCustomer($customer);
$this->retailcrm->customersEdit($data_customer);
}
}
protected function processCustomer($customer)
{
$createdAt = $customer->get_date_created();
$data_customer = array(
'createdAt' => $createdAt->date('Y-m-d H:i:s '),
'externalId' => $customer_id,
'firstName' => !empty($customer->get_first_name()) ? $customer->get_first_name() : $customer->get_username(),
'lastName' => $customer->get_last_name(),
'email' => $customer->get_email(),
'phones' => array(
array(
'number' => $customer->get_billing_phone()
)
),
'address' => array(
'index' => $customer->get_billing_postcode(),
'countryIso' => $customer->get_billing_country(),
'region' => $customer->get_billing_state(),
'city' => $customer->get_billing_city(),
'text' => $customer->get_billing_address_1() . ',' . $customer->get_billing_address_2()
)
);
return $data_customer;
}
}
endif;

View File

@ -0,0 +1,407 @@
<?php
/**
* Retailcrm Integration.
*
* @package WC_Retailcrm_History
* @category Integration
* @author Retailcrm
*/
if ( ! class_exists( 'WC_Retailcrm_History' ) ) :
/**
* Class WC_Retailcrm_History
*/
class WC_Retailcrm_History
{
protected $startDateOrders;
protected $startDateCustomers;
protected $startDate;
public function __construct()
{
$this->retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
}
$this->retailcrm = new WC_Retailcrm_Proxy(
$this->retailcrm_settings['api_url'],
$this->retailcrm_settings['api_key']
);
$this->startDate = new DateTime(date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s')))));
$this->startDateOrders = $this->startDate;
$this->startDateCustomers = $this->startDate;
}
public function getHistory()
{
if (isset($this->retailcrm_settings['history_orders'])) {
$this->startDateOrders = new DateTime($this->retailcrm_settings['history_orders']);
}
if (isset($this->retailcrm_settings['history_customers'])) {
$this->startDateCustomers = new DateTime($this->retailcrm_settings['history_orders']);
}
$this->ordersHistory($this->startDateOrders->format('Y-m-d H:i:s'));
$this->customersHistory($this->startDateCustomers->format('Y-m-d H:i:s'));
}
protected function customersHistory($date)
{
$response = $this->retailcrm->customersHistory(array('startDate' => $date));
if ($response->isSuccessful()) {
$generatedAt = $response->generatedAt;
foreach ($response['history'] as $record) {
$this->removeFuncsHook();
if ($record['field'] == 'first_name' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'first_name', $record['newValue']);
}
}
elseif ($record['field'] == 'last_name' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'last_name', $record['newValue']);
}
}
elseif ($record['field'] == 'email' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'billing_email', $record['newValue']);
}
}
elseif ($record['field'] == 'phones' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'billing_phone', $record['newValue']);
}
}
elseif ($record['field'] == 'address.region' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'billing_state', $record['newValue']);
}
}
elseif ($record['field'] == 'address.index' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'billing_postcode', $record['newValue']);
}
}
elseif ($record['field'] == 'address.country' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'billing_country', $record['newValue']);
}
}
elseif ($record['field'] == 'address.city' && $record['customer']['externalId']) {
if ($record['newValue']){
update_user_meta($record['customer']['externalId'], 'billing_city', $record['newValue']);
}
}
$this->addFuncsHook();
}
}
if (empty($response)) {
return;
}
$this->retailcrm_settings['history_customers'] = $generatedAt;
update_option('woocommerce_integration-retailcrm_settings', $this->retailcrm_settings);
}
protected function ordersHistory($date)
{
$options = array_flip(array_filter($this->retailcrm_settings));
$response = $this->retailcrm->ordersHistory(array('startDate' => $date));
if ($response->isSuccessful()) {
$generatedAt = $response->generatedAt;
foreach ($response['history'] as $record) {
$this->removeFuncsHook();
if ($record['field'] == 'status' && !empty($record['newValue']) && !empty($record['oldValue'])) {
$newStatus = $record['newValue']['code'];
if (!empty($options[$newStatus]) && !empty($record['order']['externalId'])) {
$order = new WC_Order($record['order']['externalId']);
$order->update_status($options[$newStatus]);
}
}
elseif($record['field'] == 'order_product' && $record['newValue']) {
$product = wc_get_product($record['item']['offer']['externalId']);
$order = new WC_Order($record['order']['externalId']);
$order->add_product($product, $record['item']['quantity']);
$this->update_total($order);
}
elseif($record['field'] == 'order_product.quantity' && $record['newValue']) {
$order = new WC_Order($record['order']['externalId']);
$product = wc_get_product($record['item']['offer']['externalId']);
$items = $order->get_items();
$args = array('qty' => $record['newValue']);
foreach ($items as $order_item_id => $item) {
if ($item['variation_id'] != 0 ) {
$offer_id = $item['variation_id'];
} else {
$offer_id = $item['product_id'];
}
if ($offer_id == $record['item']['offer']['externalId']) {
$order->update_product($order_item_id, $product, $args);
$this->update_total($order);
}
}
}
elseif ($record['field'] == 'order_product' && !$record['newValue']) {
$order = new WC_Order($record['order']['externalId']);
$items = $order->get_items();
foreach ($items as $order_item_id => $item) {
if ($item['variation_id'] != 0 ) {
$offer_id = $item['variation_id'];
} else {
$offer_id = $item['product_id'];
}
if ($offer_id == $record['item']['offer']['externalId']) {
wc_delete_order_item($order_item_id);
$this->update_total($order);
}
}
}
elseif ($record['field'] == 'delivery_type') {
$newValue = $record['newValue']['code'];
if (!empty($options[$newValue]) && !empty($record['order']['externalId'])) {
$order = new WC_Order($record['order']['externalId']);
$items = $order->get_items('shipping');
$wc_shipping = new WC_Shipping();
$wc_shipping_list = $wc_shipping->get_shipping_methods();
foreach ($wc_shipping_list as $method) {
if ($method->id == $options[$newValue]) {
$deliveryCost = $method->cost;
}
}
$item_id = $this->getShippingItemId($items);
$args = array(
'method_id' => $options[$newValue],
'cost' => $deliveryCost ? $deliveryCost : 0
);
$order->update_shipping( $item_id, $args );
$this->update_total($order);
}
}
elseif ($record['field'] == 'delivery_address.region') {
$order = new WC_Order($record['order']['externalId']);
$address = array(
'state' => $record['newValue']
);
$order->set_address($address, 'shipping');
}
elseif ($record['field'] == 'delivery_address.city') {
$order = new WC_Order($record['order']['externalId']);
$address = array(
'city' => $record['newValue']
);
$order->set_address($address, 'shipping');
}
elseif ($record['field'] == 'delivery_address.street') {
$order = new WC_Order($record['order']['externalId']);
$address = array(
'address_1' => $record['newValue']
);
$order->set_address($address, 'shipping');
}
elseif ($record['field'] == 'delivery_address.building') {
$order = new WC_Order($record['order']['externalId']);
$address = array(
'address_2' => $record['newValue']
);
$order->set_address($address, 'shipping');
}
elseif ($record['field'] == 'payment_type') {
$order = new WC_Order($record['order']['externalId']);
$newValue = $record['newValue']['code'];
if (!empty($options[$newValue]) && !empty($record['order']['externalId'])) {
$payment = new WC_Payment_Gateways();
$payment_types = $payment->get_available_payment_gateways();
if (isset($payment_types[$options[$newValue]])) {
$order->set_payment_method($payment_types[$options[$newValue]]);
}
}
}
elseif (isset($record['created']) &&
$record['created'] == 1 &&
!isset($record['order']['externalId'])) {
$args = array(
'status' => $options[$record['order']['status']],
'customer_id' => isset($record['order']['customer']['externalId']) ?
$record['order']['customer']['externalId'] :
null
);
$order_record = $record['order'];
$order_data = wc_create_order($args);
$order = new WC_Order($order_data->id);
$address_shipping = array(
'first_name' => $order_record['firstName'],
'last_name' => $order_record['lastName'],
'company' => '',
'email' => $order_record['email'],
'phone' => $order_record['phone'],
'address_1' => $order_record['delivery']['address']['text'],
'address_2' => '',
'city' => $order_record['delivery']['address']['city'],
'state' => $order_record['delivery']['address']['region'],
'postcode' => isset($order_record['delivery']['address']['postcode']) ? $order_record['delivery']['address']['postcode'] : '',
'country' => $order_record['delivery']['address']['countryIso']
);
$address_billing = array(
'first_name' => $order_record['customer']['firstName'],
'last_name' => $order_record['customer']['lastName'],
'company' => '',
'email' => $order_record['customer']['email'],
'phone' => $order_record['customer'][0]['number'],
'address_1' => $order_record['customer']['address']['text'],
'address_2' => '',
'city' => $order_record['customer']['address']['city'],
'state' => $order_record['customer']['address']['region'],
'postcode' => isset($order_record['customer']['address']['postcode']) ? $order_record['customer']['address']['postcode'] : '',
'country' => $order_record['customer']['address']['countryIso']
);
if ($order_record['paymentType']) {
$payment = new WC_Payment_Gateways();
$payment_types = $payment->get_available_payment_gateways();
if (isset($payment_types[$options[$order_record['paymentType']]])) {
$order->set_payment_method($payment_types[$options[$order_record['paymentType']]]);
}
}
$order->set_address($address_billing, 'billing');
$order->set_address($address_shipping, 'shipping');
$product_data = $order_record['items'];
foreach ($product_data as $product) {
$order->add_product(wc_get_product($product['offer']['externalId']), $product['quantity']);
}
$wc_shipping = new WC_Shipping();
$wc_shipping_types = $wc_shipping->get_shipping_methods();
foreach ($wc_shipping_types as $shipping_type) {
if ($shipping_type->id == $options[$order_record['delivery']['code']]) {
$shipping_method_id = $shipping_type->id;
$shipping_method_title = $shipping_type->title;
$shipping_total = $shipping_type->cost;
}
}
$shipping_rate = new WC_Shipping_Rate($shipping_method_id, isset($shipping_method_title) ? $shipping_method_title : '', isset($shipping_total) ? floatval($shipping_total) : 0, array(), $shipping_method_id);
$order->add_shipping($shipping_rate);
$this->update_total($order);
$ids[] = array(
'id' => (int)$order_record['id'],
'externalId' => (int)$order_data->id
);
$this->retailcrm->ordersFixExternalIds($ids);
}
$this->addFuncsHook();
}
}
if (empty($response)) {
return;
}
$this->retailcrm_settings['history_orders'] = $generatedAt;
update_option('woocommerce_integration-retailcrm_settings', $this->retailcrm_settings);
}
protected function removeFuncsHook()
{
remove_action('woocommerce_order_status_changed', 'retailcrm_update_order_status', 11, 1);
remove_action('woocommerce_saved_order_items', 'retailcrm_update_order_items', 10, 2);
remove_action('update_post_meta', 'retailcrm_update_order', 11, 4);
remove_action('woocommerce_payment_complete', 'retailcrm_update_order_payment', 11, 1);
remove_action('woocommerce_checkout_update_user_meta', 'update_customer', 10, 2);
}
protected function addFuncsHook()
{
if (!has_action('woocommerce_checkout_update_user_meta', 'update_customer')) {
add_action('woocommerce_checkout_update_user_meta', 'update_customer', 10, 2);
}
if (!has_action('woocommerce_order_status_changed', 'retailcrm_update_order_status')) {
add_action('woocommerce_order_status_changed', 'retailcrm_update_order_status', 11, 1);
}
if (!has_action('woocommerce_saved_order_items', 'retailcrm_update_order_items')) {
add_action('woocommerce_saved_order_items', 'retailcrm_update_order_items', 10, 2);
}
if (!has_action('update_post_meta', 'retailcrm_update_order')) {
add_action('update_post_meta', 'retailcrm_update_order', 11, 4);
}
if (!has_action('woocommerce_payment_complete', 'retailcrm_update_order_payment')) {
add_action('woocommerce_payment_complete', 'retailcrm_update_order_payment', 11, 1);
}
}
protected function getShippingItemId($items)
{
if ($items) {
foreach ($items as $key => $value) {
$item_id[] = $key;
}
}
return $item_id[0];
}
protected function update_total($order)
{
$order->update_taxes();
$order->calculate_totals();
}
}
endif;

View File

@ -0,0 +1,461 @@
<?php
/**
* Retailcrm Integration.
*
* @package WC_Retailcrm_Icml
* @category Integration
* @author Retailcrm
*/
if ( ! class_exists( 'WC_Retailcrm_Icml' ) ) :
/**
* Class WC_Retailcrm_Icml
*/
class WC_Retailcrm_Icml
{
protected $shop;
protected $file;
protected $tmpFile;
protected $properties = array(
'name',
'productName',
'price',
'purchasePrice',
'vendor',
'picture',
'url',
'xmlId',
'productActivity'
);
protected $xml;
/** @var SimpleXMLElement $categories */
protected $categories;
/** @var SimpleXMLElement $categories */
protected $offers;
protected $chunk = 500;
protected $fileLifeTime = 3600;
/**
* WC_Retailcrm_Icml constructor.
*
*/
public function __construct()
{
$this->shop = get_bloginfo( 'name' );
$this->file = ABSPATH . 'retailcrm.xml';
$this->tmpFile = sprintf('%s.tmp', $this->file);
}
/**
* Generate file
*/
public function generate()
{
$categories = $this->get_wc_categories_taxonomies();
$offers = $this->get_wc_products_taxonomies();
if (file_exists($this->tmpFile)) {
if (filectime($this->tmpFile) + $this->fileLifeTime < time()) {
unlink($this->tmpFile);
$this->writeHead();
}
} else {
$this->writeHead();
}
try {
if (!empty($categories)) {
$this->writeCategories($categories);
unset($categories);
}
if (!empty($offers)) {
$this->writeOffers($offers);
unset($offers);
}
$dom = dom_import_simplexml(simplexml_load_file($this->tmpFile))->ownerDocument;
$dom->formatOutput = true;
$formatted = $dom->saveXML();
unset($dom, $this->xml);
file_put_contents($this->tmpFile, $formatted);
rename($this->tmpFile, $this->file);
} catch (Exception $e) {
unlink($this->tmpFile);
}
}
/**
* Load tmp data
*
* @return \SimpleXMLElement
*/
private function loadXml()
{
return new SimpleXMLElement(
$this->tmpFile,
LIBXML_NOENT | LIBXML_NOCDATA | LIBXML_COMPACT | LIBXML_PARSEHUGE,
true
);
}
/**
* Generate xml header
*/
private function writeHead()
{
$string = sprintf(
'<?xml version="1.0" encoding="UTF-8"?><yml_catalog date="%s"><shop><name>%s</name><categories/><offers/></shop></yml_catalog>',
date('Y-m-d H:i:s'),
$this->shop
);
file_put_contents($this->tmpFile, $string, LOCK_EX);
}
/**
* Write categories in file
*
* @param $categories
*/
private function writeCategories($categories)
{
$chunkCategories = array_chunk($categories, $this->chunk);
foreach ($chunkCategories as $categories) {
$this->xml = $this->loadXml();
$this->categories = $this->xml->shop->categories;
$this->addCategories($categories);
$this->xml->asXML($this->tmpFile);
}
unset($this->categories);
}
/**
* Write products in file
*
* @param $offers
*/
private function writeOffers($offers)
{
$chunkOffers = array_chunk($offers, $this->chunk);
foreach ($chunkOffers as $offers) {
$this->xml = $this->loadXml();
$this->offers = $this->xml->shop->offers;
$this->addOffers($offers);
$this->xml->asXML($this->tmpFile);
}
unset($this->offers);
}
/**
* Add categories
*
* @param $categories
*/
private function addCategories($categories)
{
$categories = self::filterRecursive($categories);
foreach($categories as $category) {
if (!array_key_exists('name', $category) || !array_key_exists('id', $category)) {
continue;
}
/** @var SimpleXMLElement $e */
/** @var SimpleXMLElement $cat */
$cat = $this->categories;
$e = $cat->addChild('category', $category['name']);
$e->addAttribute('id', $category['id']);
if (array_key_exists('parentId', $category) && $category['parentId'] > 0) {
$e->addAttribute('parentId', $category['parentId']);
}
}
}
/**
* Add offers
*
* @param $offers
*/
private function addOffers($offers)
{
$offers = self::filterRecursive($offers);
foreach ($offers as $key => $offer) {
if (!array_key_exists('id', $offer)) {
continue;
}
$e = $this->offers->addChild('offer');
$e->addAttribute('id', $offer['id']);
if (!array_key_exists('productId', $offer) || empty($offer['productId'])) {
$offer['productId'] = $offer['id'];
}
$e->addAttribute('productId', $offer['productId']);
if (!empty($offer['quantity'])) {
$e->addAttribute('quantity', (int) $offer['quantity']);
} else {
$e->addAttribute('quantity', 0);
}
if (isset($offer['categoryId']) && $offer['categoryId']) {
if (is_array($offer['categoryId'])) {
foreach ($offer['categoryId'] as $categoryId) {
$e->addChild('categoryId', $categoryId);
}
} else {
$e->addChild('categoryId', $offer['categoryId']);
}
}
if (!array_key_exists('name', $offer) || empty($offer['name'])) {
$offer['name'] = 'Без названия';
}
if (!array_key_exists('productName', $offer) || empty($offer['productName'])) {
$offer['productName'] = $offer['name'];
}
unset($offer['id'], $offer['productId'], $offer['categoryId'], $offer['quantity']);
array_walk($offer, array($this, 'setOffersProperties'), $e);
if (array_key_exists('params', $offer) && !empty($offer['params'])) {
array_walk($offer['params'], array($this, 'setOffersParams'), $e);
}
unset($offers[$key]);
}
}
/**
* Set offer properties
*
* @param $value
* @param $key
* @param $e
*/
private function setOffersProperties($value, $key, &$e) {
if (in_array($key, $this->properties) && $key != 'params') {
/** @var SimpleXMLElement $e */
$e->addChild($key, htmlspecialchars($value));
}
}
/**
* Set offer params
*
* @param $value
* @param $key
* @param $e
*/
private function setOffersParams($value, $key, &$e) {
if (
array_key_exists('code', $value) &&
array_key_exists('name', $value) &&
array_key_exists('value', $value) &&
!empty($value['code']) &&
!empty($value['name']) &&
!empty($value['value'])
) {
/** @var SimpleXMLElement $e */
$param = $e->addChild('param', htmlspecialchars($value['value']));
$param->addAttribute('code', $value['code']);
$param->addAttribute('name', substr(htmlspecialchars($value['name']), 0, 200));
unset($key);
}
}
/**
* Filter result array
*
* @param $haystack
*
* @return mixed
*/
public static function filterRecursive($haystack)
{
foreach ($haystack as $key => $value) {
if (is_array($value)) {
$haystack[$key] = self::filterRecursive($haystack[$key]);
}
if (is_null($haystack[$key]) || $haystack[$key] === '' || count($haystack[$key]) == 0) {
unset($haystack[$key]);
} elseif (!is_array($value)) {
$haystack[$key] = trim($value);
}
}
return $haystack;
}
/**
* Get WC products
*
* @return array
*/
private function get_wc_products_taxonomies() {
$full_product_list = array();
$loop = new WP_Query(array('post_type' => array('product', 'product_variation'), 'posts_per_page' => -1));
while ($loop->have_posts()) : $loop->the_post();
$theid = get_the_ID();
if ( version_compare( get_option( 'woocommerce_db_version' ), '3.0', '<' ) ) {
$product = new WC_Product($theid);
$parent = new WC_Product($product->get_parent());
}
else {
if (get_post_type($theid) == 'product') {
$product = new WC_Product_Simple($theid);
}
elseif (get_post_type($theid) == 'product_variation') {
$post = get_post($theid);
if (get_post($post->post_parent)) {
$product = new WC_Product_Variation($theid);
$parent = new WC_Product_Simple($product->get_parent_id());
}
}
}
if ($this->get_parent_product($product) > 0) {
$image = wp_get_attachment_image_src( get_post_thumbnail_id( $parent->get_id() ), 'single-post-thumbnail' );
$term_list = wp_get_post_terms($parent->get_id(), 'product_cat', array('fields' => 'ids'));
$attributes = get_post_meta( $parent->get_id() , '_product_attributes' );
} else {
$image = wp_get_attachment_image_src( get_post_thumbnail_id( $theid ), 'single-post-thumbnail' );
$term_list = wp_get_post_terms($product->get_id(), 'product_cat', array('fields' => 'ids'));
$attributes = get_post_meta( $product->get_id() , '_product_attributes' );
}
$attributes = (isset($attributes[0])) ? $attributes[0] : $attributes;
$params = array();
$weight = $product->get_weight();
if (!empty($weight)) {
$params[] = array('code' => 'weight', 'name' => 'Weight', 'value' => $weight);
}
if (!empty($attributes)) {
foreach ($attributes as $attribute_name => $attribute) {
$attributeValue = get_post_meta($product->get_id(), 'attribute_'.$attribute_name);
$attributeValue = end($attributeValue);
if ($attribute['is_visible'] == 1 && !empty($attribute['value'])) {
$params[] = array(
'code' => $attribute_name,
'name' => $attribute['name'],
'value' => $attributeValue
);
}
}
}
if ($product->get_sku() != '') {
$params[] = array('code' => 'sku', 'name' => 'SKU', 'value' => $product->get_sku());
}
$product_data = array(
'id' => $product->get_id(),
'productId' => ($this->get_parent_product($product) > 0) ? $parent->get_id() : $product->get_id(),
'name' => $product->get_title(),
'productName' => ($this->get_parent_product($product) > 0) ? $parent->get_title() : $product->get_title(),
'price' => $this->get_price_with_tax($product),
'purchasePrice' => $product->get_regular_price(),
'picture' => $image[0],
'url' => ($this->get_parent_product($product) > 0) ? $parent->get_permalink() : $product->get_permalink(),
'quantity' => is_null($product->get_stock_quantity()) ? 0 : $product->get_stock_quantity(),
'categoryId' => $term_list
);
if (!empty($params)) {
$product_data['params'] = $params;
}
$full_product_list[] = $product_data;
unset($product_data);
endwhile;
return $full_product_list;
}
/**
* Get WC categories
*
* @return array
*/
private function get_wc_categories_taxonomies() {
$categories = array();
$taxonomy = 'product_cat';
$orderby = 'parent';
$show_count = 0; // 1 for yes, 0 for no
$pad_counts = 0; // 1 for yes, 0 for no
$hierarchical = 1; // 1 for yes, 0 for no
$title = '';
$empty = 0;
$args = array(
'taxonomy' => $taxonomy,
'orderby' => $orderby,
'show_count' => $show_count,
'pad_counts' => $pad_counts,
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $empty
);
$wcatTerms = get_categories( $args );
foreach ($wcatTerms as $term) {
$categories[] = array(
'id' => $term->term_id,
'parentId' => $term->parent,
'name' => $term->name
);
}
return $categories;
}
private function get_parent_product($product) {
global $woocommerce;
if ( version_compare( $woocommerce->version, '3.0', '<' ) ) {
return $product->get_parent();
} else {
return $product->get_parent_id();
}
}
private function get_price_with_tax($product) {
global $woocommerce;
if ( version_compare( $woocommerce->version, '3.0', '<' ) ) {
return $product->get_price_including_tax();
} else {
return wc_get_price_including_tax($product);
}
}
}
endif;

View File

@ -0,0 +1,75 @@
<?php
/**
* Retailcrm Integration.
*
* @package WC_Retailcrm_Inventories
* @category Integration
* @author Retailcrm
*/
if ( ! class_exists( 'WC_Retailcrm_Inventories' ) ) :
/**
* Class WC_Retailcrm_Inventories
*/
class WC_Retailcrm_Inventories
{
public function __construct()
{
$this->retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
}
$this->retailcrm = new WC_Retailcrm_Proxy(
$this->retailcrm_settings['api_url'],
$this->retailcrm_settings['api_key']
);
}
public function load_stocks()
{
$page = 1;
do {
$result = $this->retailcrm->storeInventories(array(), $page, 250);
$totalPageCount = $result['pagination']['totalPageCount'];
$page++;
foreach ($result['offers'] as $offer) {
if (isset($offer['externalId'])) {
$post = get_post($offer['externalId']);
if ($post->post_type == 'product') {
$product = new WC_Product_Simple($offer['externalId']);
update_post_meta($offer['externalId'], '_manage_stock', 'yes');
$product->set_stock($offer['quantity']);
} elseif ($post->post_type == 'product_variation') {
$args = array();
if ($post->post_parent) {
$args['parent_id'] = $post->post_parent;
$args['parent'] = new WC_Product_Simple($post->post_parent);
}
$product = new WC_Product_Variation($offer['externalId'], $args);
update_post_meta($offer['externalId'], '_manage_stock', 'yes');
$product->set_stock($offer['quantity']);
}
}
}
} while ($page < $totalPageCount);
}
public function updateQuantity()
{
$options = array_filter(get_option( 'woocommerce_integration-retailcrm_settings' ));
if ($options['sync'] == 'yes') {
$this->load_stocks();
} else {
return false;
}
}
}
endif;

View File

@ -0,0 +1,284 @@
<?php
/**
* Retailcrm Integration.
*
* @package WC_Retailcrm_Orders
* @category Integration
* @author Retailcrm
*/
if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) :
/**
* Class WC_Retailcrm_Orders
*/
class WC_Retailcrm_Orders
{
public function __construct()
{
$this->retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
}
$this->retailcrm = new WC_Retailcrm_Proxy(
$this->retailcrm_settings['api_url'],
$this->retailcrm_settings['api_key']
);
}
/**
* Upload orders to CRM
*/
public function ordersUpload()
{
$orders = get_posts(array(
'numberposts' => -1,
'post_type' => wc_get_order_types('view-orders'),
'post_status' => array_keys(wc_get_order_statuses())
));
$orders_data = array();
foreach ($orders as $data_order) {
$order_data = $this->processOrder($data_order->ID);
$order = new WC_Order($order_id);
$customer = $order->get_user();
if ($customer != false) {
$order_data['customer']['externalId'] = $customer->get('ID');
}
$orders_data[] = $order_data;
}
$uploadOrders = array_chunk($orders_data, 50);
foreach ($uploadOrders as $uploadOrder) {
$this->retailcrm->ordersUpload($uploadOrder);
}
}
/**
* Create order
*
* @param $order_id
*/
public function orderCreate($order_id)
{
$order_data = $this->processOrder($order_id);
$order = new WC_Order($order_id);
$customer = $order->get_user();
if ($customer != false) {
$search = $this->retailcrm->customersGet($customer->get('ID'));
if (!$search->isSuccessful()) {
$customer_data = array(
'externalId' => $customer->get('ID'),
'firstName' => $order_data['firstName'],
'lastName' => $order_data['lastName'],
'email' => $order_data['email']
);
$this->retailcrm->customersCreate($customer_data);
} else {
$order_data['customer']['externalId'] = $search['customer']['externalId'];
}
}
$this->retailcrm->ordersCreate($order_data);
}
/**
* Update shipping address
*
* @param $order_id, $address
*/
public function orderUpdateShippingAddress($order_id, $address) {
$address['externalId'] = $order_id;
$response = $this->retailcrm->ordersEdit($address);
}
/**
* Update order status
*
* @param $order_id
*/
public function orderUpdateStatus($order_id) {
$order = new WC_Order( $order_id );
$order_data = array(
'externalId' => $order_id,
'status' => $this->retailcrm_settings[$order->get_status()]
);
$response = $this->retailcrm->ordersEdit($order_data);
}
/**
* Update order payment type
*
* @param $order_id
*/
public function orderUpdatePaymentType($order_id, $payment_method) {
$order_data = array(
'externalId' => $order_id,
'paymentType' => $this->retailcrm_settings[$payment_method]
);
$response = $this->retailcrm->ordersEdit($order_data);
}
/**
* Update order payment
*
* @param $order_id
*/
public function orderUpdatePayment($order_id) {
$order = new WC_Order( $order_id );
$order_data = array(
'externalId' => $order_id,
'paymentStatus' => 'paid'
);
$response = $this->retailcrm->ordersEdit($order_data);
}
/**
* Update order items
*
* @param $order_id, $data
*/
public function orderUpdateItems($order_id, $data) {
$order = new WC_Order( $order_id );
$order_data['externalId'] = $order_id;
$shipping_method = end($data['shipping_method']);
$shipping_cost = end($data['shipping_cost']);
$products = $order->get_items();
$items = array();
foreach ($products as $order_item_id => $product) {
if ($product['variation_id'] > 0) {
$offer_id = $product['variation_id'];
} else {
$offer_id = $product['product_id'];
}
$_product = wc_get_product($offer_id);
$items[] = array(
'offer' => array('externalId' => $offer_id),
'productName' => $product['name'],
'initialPrice' => (float)$_product->get_price(),
'quantity' => $product['qty']
);
}
$order_data['items'] = $items;
if (!empty($shipping_method) && !empty($this->retailcrm_settings[$shipping_method])) {
$order_data['delivery']['code'] = $this->retailcrm_settings[$shipping_method];
}
if (!empty($shipping_cost)) {
$shipping_cost = str_replace(',', '.', $shipping_cost);
$order_data['delivery']['cost'] = $shipping_cost;
}
$response = $this->retailcrm->ordersEdit($order_data);
}
public function processOrder($order_id)
{
if ( !$order_id ){
return;
}
$order = new WC_Order( $order_id );
$order_data = array();
$order_data['externalId'] = $order->id;
$order_data['number'] = $order->get_order_number();
$order_data['createdAt'] = $order->order_date;
if (!empty($order->payment_method) && !empty($this->retailcrm_settings[$order->payment_method])) {
$order_data['paymentType'] = $this->retailcrm_settings[$order->payment_method];
}
if(!empty($order->get_items( 'shipping' )) && $order->get_items( 'shipping' ) != '') {
$shipping = end($order->get_items( 'shipping' ));
$shipping_code = explode(':', $shipping['method_id']);
$shipping_method = $shipping_code[0];
$shipping_cost = $shipping['cost'];
if (!empty($shipping_method) && !empty($this->retailcrm_settings[$shipping_method])) {
$order_data['delivery']['code'] = $this->retailcrm_settings[$shipping_method];
}
if (!empty($shipping_cost)) {
$order_data['delivery']['cost'] = $shipping_cost;
}
}
if ($order->is_paid()) {
$order_data['paymentStatus'] = 'paid';
}
$status = $order->get_status();
$order_data['status'] = $this->retailcrm_settings[$status];
$user_data = $order->get_address();
if (!empty($user_data)) {
if (!empty($user_data['first_name'])) $order_data['firstName'] = $user_data['first_name'];
if (!empty($user_data['last_name'])) $order_data['lastName'] = $user_data['last_name'];
if (!empty($user_data['phone'])) $order_data['phone'] = $user_data['phone'];
if (!empty($user_data['email'])) $order_data['email'] = $user_data['email'];
if (!empty($user_data['postcode'])) $order_data['delivery']['address']['index'] = $user_data['postcode'];
if (!empty($user_data['state'])) $order_data['delivery']['address']['region'] = $user_data['state'];
if (!empty($user_data['city'])) $order_data['delivery']['address']['city'] = $user_data['city'];
if (!empty($user_data['country'])) $order_data['delivery']['address']['countryIso'] = $user_data['country'];
$order_data['delivery']['address']['text'] = sprintf(
"%s %s %s %s %s",
$user_data['postcode'],
$user_data['state'],
$user_data['city'],
$user_data['address_1'],
$user_data['address_2']
);
}
$order_items = array();
foreach ($order->get_items() as $item) {
$uid = ($item['variation_id'] > 0) ? $item['variation_id'] : $item['product_id'] ;
$_product = wc_get_product($uid);
if ($_product) {
$order_item = array(
'offer' => array('externalId' => $uid),
'productName' => $item['name'],
'initialPrice' => (float)$_product->get_price(),
'quantity' => $item['qty'],
);
}
$order_items[] = $order_item;
}
$order_data['items'] = $order_items;
return $order_data;
}
}
endif;

View File

@ -0,0 +1 @@
<?php // Silence is golden

1
retailcrm/index.php Normal file
View File

@ -0,0 +1 @@
<?php // Silence is golden

353
retailcrm/retailcrm.php Normal file
View File

@ -0,0 +1,353 @@
<?php
/**
* Version: 1.0
* Plugin Name: WooCommerce Retailcrm
* Plugin URI: https://wordpress.org/plugins/retailcrm/
* Description: Интеграционный плагин для WooCommerce & Retailcrm
* Author: RetailDriver LLC
* Author URI: http://retailcrm.ru/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if (!class_exists( 'WC_Integration_Retailcrm')) :
/**
* Class WC_Integration_Retailcrm
*/
class WC_Integration_Retailcrm {
/**
* Construct the plugin.
*/
public function __construct() {
add_action( 'plugins_loaded', array( $this, 'init' ) );
}
/**
* Initialize the plugin.
*/
public function init() {
if ( class_exists( 'WC_Integration' ) ) {
include_once 'include/class-wc-retailcrm-base.php';
add_filter( 'woocommerce_integrations', array( $this, 'add_integration' ) );
} else {
// throw an admin error if you like
}
}
/**
* Add a new integration to WooCommerce.
*
* @param $integrations
*
* @return array
*/
public function add_integration( $integrations ) {
$integrations[] = 'WC_Retailcrm_Base';
return $integrations;
}
}
$WC_Integration_Retailcrm = new WC_Integration_Retailcrm( __FILE__ );
endif;
function check_custom_icml()
{
if (file_exists( __DIR__ . '/include-custom/class-wc-retailcrm-icml.php' )) {
$file = '/include-custom/class-wc-retailcrm-icml.php';
} else {
$file = '/include/class-wc-retailcrm-icml.php';
}
return $file;
}
function check_custom_order()
{
if (file_exists( __DIR__ . '/include-custom/class-wc-retailcrm-orders.php' )) {
$file = '/include-custom/class-wc-retailcrm-orders.php';
} else {
$file = '/include/class-wc-retailcrm-orders.php';
}
return $file;
}
/**
* Activation action
*/
function retailcrm_install()
{
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option( 'active_plugins')))) {
generate_icml();
}
}
/**
* Deactivation action
*/
function retailcrm_deactivation()
{
if ( wp_next_scheduled ( 'retailcrm_icml' )) {
wp_clear_scheduled_hook('retailcrm_icml');
}
}
/**
* Load stocks from CRM
*/
function load_stocks()
{
if ( ! class_exists( 'WC_Retailcrm_Inventories' ) ) {
include_once( __DIR__ . '/include/class-wc-retailcrm-inventories.php' );
}
$inventories = new WC_Retailcrm_Inventories();
$inventories->updateQuantity();
}
/**
* Generate ICML file
*/
function generate_icml()
{
if ( ! class_exists( 'WC_Retailcrm_Icml' ) ) {
include_once( __DIR__ . check_custom_icml() );
}
$icml = new WC_Retailcrm_Icml();
$icml->generate();
}
/**
* Create order
*
* @param $order_id
*/
function retailcrm_process_order($order_id)
{
if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
include_once( __DIR__ . check_custom_order() );
}
$order_class = new WC_Retailcrm_Orders();
$order_class->orderCreate($order_id);
}
/**
* Update order status
*
* @param $order_id
*/
function retailcrm_update_order_status($order_id)
{
if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
include_once( __DIR__ . check_custom_order() );
}
$order_class = new WC_Retailcrm_Orders();
$order_class->orderUpdateStatus($order_id);
}
/**
* Update order payment
*
* @param $order_id
*/
function retailcrm_update_order_payment($order_id)
{
if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
include_once( __DIR__ . check_custom_order() );
}
$order_class = new WC_Retailcrm_Orders();
$order_class->orderUpdatePayment($order_id);
}
/**
* Update order
*
* @param $meta_id, $order_id, $meta_key, $_meta_value
*/
function retailcrm_update_order($meta_id, $order_id, $meta_key, $_meta_value)
{
if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
include_once( __DIR__ . check_custom_order() );
}
$order_class = new WC_Retailcrm_Orders();
if ($meta_key == '_payment_method') {
$order_class->orderUpdatePaymentType($order_id, $_meta_value);
}
$address = array();
if ($meta_key == '_shipping_first_name') $address['firstName'] = $_meta_value;
if ($meta_key == '_shipping_last_name') $address['lastName'] = $_meta_value;
if ($meta_key == '_billing_phone') $address['phone'] = $_meta_value;
if ($meta_key == '_billing_email') $address['email'] = $_meta_value;
if ($meta_key == '_shipping_city') $address['delivery']['address']['city'] = $_meta_value;
if ($meta_key == '_shipping_state') $address['delivery']['address']['region'] = $_meta_value;
if ($meta_key == '_shipping_postcode') $address['delivery']['address']['index'] = $_meta_value;
if ($meta_key == '_shipping_country') $address['delivery']['address']['countryIso'] = $_meta_value;
if ($meta_key == '_shipping_address_1') $address['delivery']['address']['text'] = $_meta_value;
if ($meta_key == '_shipping_address_2') $address['delivery']['address']['text'] .= $_meta_value;
if (!empty($address)) {
$order_class->orderUpdateShippingAddress($order_id, $address);
}
}
/**
* Update order items
*
* @param $order_id, $data
*/
function retailcrm_update_order_items($order_id, $data)
{
if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
include_once( __DIR__ . check_custom_order() );
}
$order_class = new WC_Retailcrm_Orders();
$order_class->orderUpdateItems($order_id, $data);
}
function retailcrm_history_get()
{
if ( ! class_exists( 'WC_Retailcrm_History' ) ) {
include_once( __DIR__ . '/include/class-wc-retailcrm-history.php' );
}
$history_class = new WC_Retailcrm_History();
$history_class->getHistory();
}
function create_customer($customer_id) {
if ( ! class_exists( 'WC_Retailcrm_Customers' ) ) {
include_once( __DIR__ . '/include/class-wc-retailcrm-customers.php' );
}
$customer_class = new WC_Retailcrm_Customers();
$customer_class->createCustomer($customer_id);
}
function update_customer($customer_id, $data) {
if ( ! class_exists( 'WC_Retailcrm_Customers' ) ) {
include_once( __DIR__ . '/include/class-wc-retailcrm-customers.php' );
}
$customer_class = new WC_Retailcrm_Customers();
$customer_class->updateCustomer($customer_id);
}
function register_icml_generation() {
// Make sure this event hasn't been scheduled
if( !wp_next_scheduled( 'retailcrm_icml' ) ) {
// Schedule the event
wp_schedule_event( time(), 'three_hours', 'retailcrm_icml' );
}
}
function register_retailcrm_history() {
// Make sure this event hasn't been scheduled
if( !wp_next_scheduled( 'retailcrm_history' ) ) {
// Schedule the event
wp_schedule_event( time(), 'five_minutes', 'retailcrm_history' );
}
}
function check_inventories() {
if( !wp_next_scheduled( 'retailcrm_inventories' ) ) {
// Schedule the event
wp_schedule_event( time(), 'fiveteen_minutes', 'retailcrm_inventories' );
}
}
function filter_cron_schedules($param) {
return array(
'five_minutes' => array(
'interval' => 300, // seconds
'display' => __('Every 5 minutes')
),
'three_hours' => array(
'interval' => 10800, // seconds
'display' => __('Every 3 hours')
),
'fiveteen_minutes' => array(
'interval' => 900, // seconds
'display' => __('Every 1 hour')
)
);
}
function upload_to_crm() {
if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
include_once( __DIR__ . check_custom_order() );
}
if ( ! class_exists( 'WC_Retailcrm_Customers' ) ) {
include_once( __DIR__ . '/include/class-wc-retailcrm-customers.php' );
}
$options = array_filter(get_option( 'woocommerce_integration-retailcrm_settings' ));
if ($options['uploadToCrm'] == 'yes' && !isset($options['uploaded'])) {
$options['uploadToCrm'] = 'no';
$options['uploaded'] = 'yes';
$orders = new WC_Retailcrm_Orders();
$customers = new WC_Retailcrm_Customers();
$customers->customersUpload();
$orders->ordersUpload();
update_option('woocommerce_integration-retailcrm_settings', $options);
}
if (isset($options['uploaded'])) {
$options['uploadToCrm'] = 'no';
update_option('woocommerce_integration-retailcrm_settings', $options);
}
}
function ajax_upload() {
$ajax_url = admin_url('admin-ajax.php');
?>
<script type="text/javascript" >
jQuery(document).ready(function($) {
$.ajax({
type: "POST",
url: "<?php echo $ajax_url; ?>?action=do_upload",
success: function (response) {
console.log('AJAX response : ',response);
}
});
});
</script>
<?php
}
register_activation_hook( __FILE__, 'retailcrm_install' );
register_deactivation_hook( __FILE__, 'retailcrm_deactivation' );
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option( 'active_plugins')))) {
load_plugin_textdomain('wc_retailcrm', false, dirname(plugin_basename( __FILE__ )) . '/');
add_filter('cron_schedules', 'filter_cron_schedules', 10, 1);
add_action('woocommerce_thankyou', 'retailcrm_process_order', 10, 1);
add_action('woocommerce_order_status_changed', 'retailcrm_update_order_status', 11, 1);
add_action('woocommerce_saved_order_items', 'retailcrm_update_order_items', 10, 2);
add_action('update_post_meta', 'retailcrm_update_order', 11, 4);
add_action('woocommerce_payment_complete', 'retailcrm_update_order_payment', 11, 1);
add_action('retailcrm_history', 'retailcrm_history_get');
add_action('retailcrm_icml', 'generate_icml');
add_action('retailcrm_inventories', 'load_stocks');
add_action( 'init', 'check_inventories');
add_action( 'init', 'register_icml_generation');
add_action( 'init', 'register_retailcrm_history');
add_action( 'wp_ajax_do_upload', 'upload_to_crm' );
add_action('admin_print_footer_scripts', 'ajax_upload', 99);
add_action( 'woocommerce_created_customer', 'create_customer', 10, 1 );
add_action( 'woocommerce_checkout_update_user_meta', 10, 2 );
}

30
retailcrm/uninstall.php Normal file
View File

@ -0,0 +1,30 @@
<?php
/**
* Fired when the plugin is uninstalled.
*
* When populating this file, consider the following flow
* of control:
*
* - This method should be static
* - Check if the $_REQUEST content actually is the plugin name
* - Run an admin referrer check to make sure it goes through authentication
* - Verify the output of $_GET makes sense
* - Repeat with other user roles. Best directly by using the links/query string parameters.
* - Repeat things for multisite. Once for a single site in the network, once sitewide.
*
*
* @link https://wordpress.org/plugins/retailcrm/
* @since 1.0
*
* @package Retailcrm
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
// If uninstall not called from WordPress, then exit.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
exit;
}