carono / yii2-1c-exchange
用于从1C交换商品和文档的Yii2模块
Requires
- php: >=5.6
- carono/commerceml: ^0.2.3
- yiisoft/yii2: ^2.0
Requires (Dev)
- yiidoc/yii2-redactor: ^2.0
README
- 简介
- 模块连接
- 交换模块属性
- 1С设置
- 授权设置
- 模型接口
- 交换协议描述
- 测试和错误查找
- 有用链接
- 模块事件
简介
这是什么模块,它应该执行哪些任务?
安装此模块应简化1C与您网站的集成。
模块包含一组必须实现的接口,以实现与1C交换商品和文档。假设您有1C:Предприятие 8, Управление торговлей", 版本11.3, 11.3.2(磁力链接),平台8.3.9.2033(及更高版本)。如果您的配置版本低于此,则模块可能仍然可以正常工作,因为1C与网站之间的交换在很大程度上不会随着版本的更新而变化。
连接模块到您的项目后,您可以通过链接获取当前文档 /exchange/article/index
模块连接
1. 通过Composer连接包
composer require carono/yii2-1c-exchange
2. 在应用程序配置中连接模块
'modules' => [
'exchange' => [
'class' => \carono\exchange1c\ExchangeModule::class
]
]
3. 如果使用Apache作为Web服务器,请勿忘记在web目录中创建和设置 .htaccess
交换模块属性
1С设置
1. 安装1C:Предприятие 8 Управление торговлей, 版本11.3, 11.3.2(磁力链接),平台8.3.9.2033(及更高版本)
设置将在演示版本上执行。
2. 通过“НСИ和行政”或通过搜索进入数据同步设置
3. 进入与网站交换的节点
4. 创建新节点并填写数据
- 名称
- 商品导出
- 网站地址,指定您的 网站/1c_exchange.php
- 用户名和密码,我们将使用该用户名导出商品(授权设置)
授权设置
模块中的授权通过 \yii\filters\auth\HttpBasicAuth 实现
'modules' => [
'exchange' => [
'class' => \carono\exchange1c\ExchangeModule::class,
'auth' => function ($username, $password) {
if ($user = \app\models\User::findByUsername($username)) {
if ($user->validatePassword($password)) {
return $user;
}
}
return false;
}
]
],groupClass 产品组
模块设置,指定工作组模型类
[
'exchange' => [
'class' => \carono\exchange1c\ExchangeModule::class,
'groupClass' => \app\models\Group::class,
]
]
迁移,创建用于存储产品的组,应该是具有无限嵌套的树形结构,建议使用 nested sets,但为了示例,我们使用更简单的例子
$this->createTable('{{%group}}', [
'id' => $this->primaryKey(),
'name' => $this->string()->comment('Наименование группы'),
'parent_id' => $this->integer()->comment('Родительская группа'),
'accounting_id' => $this->string()->comment('Код в 1С')->unique(),
]);
需要实现的接口列表 在这里
createTree1c
public static function createTree1c($groups)
在 createTree1c 函数中,我们需要实现创建整个产品树(父级->子级)。该方法仅在导入开始之前调用一次,因此在这个函数中需要完全创建所有组。
<?php
/**
* This class is generated using the package carono/codegen
*/
namespace app\models;
use carono\exchange1c\interfaces\GroupInterface;
/**
* This is the model class for table "group".
*/
class Group extends base\Group implements GroupInterface
{
/**
* Возвращаем имя поля в базе данных, в котором хранится ID из 1с
*
* @return string
*/
public static function getIdFieldName1c()
{
return 'accounting_id';
}
/**
* Создание дерева групп
* в параметр передаётся массив всех групп (import.xml > Классификатор > Группы)
* $groups[0]->parent - родительская группа
* $groups[0]->children - дочерние группы
*
* @param \Zenwalker\CommerceML\Model\Group[] $groups
* @return void
*/
public static function createTree1c($groups)
{
foreach ($groups as $group) {
self::createByML($group);
if ($children = $group->getChildren()) {
self::createTree1c($children);
}
}
}
/**
* Создаём группу по модели группы CommerceML
* проверяем все дерево родителей группы, если родителя нет в базе - создаём
*
* @param \Zenwalker\CommerceML\Model\Group $group
* @return Group|array|null
*/
public static function createByML(\Zenwalker\CommerceML\Model\Group $group)
{
/**
* @var \Zenwalker\CommerceML\Model\Group $parent
*/
if (!$model = Group::findOne(['accounting_id' => $group->id])) {
$model = new self;
$model->accounting_id = $group->id;
}
$model->name = $group->name;
if ($parent = $group->getParent()) {
$parentModel = self::createByML($parent);
$model->parent_id = $parentModel->id;
unset($parentModel);
} else {
$model->parent_id = null;
}
$model->save();
return $model;
}
}
您可以通过 这里 测试您的实现
productClass 产品模型
产品 - 产品模型是商品本身,图片,属性和规格,但不包括库存或价格。
对于不太熟悉1С中数据存储概念的开发者,需要额外的解释。在1С中存在产品和提议。产品是指商品本身,提议是指可以销售的东西,即提议参与销售。
示例
Labutene鞋子型号X是产品,它有自己的图片、各种属性(制造商、颜色、材料等),这些都是该产品的特性。
Labutene鞋子型号X,尺码32,售价20000元是提议,一个产品可能有多个提议,具有不同的属性,如尺寸和不同的价格,每个提议可能有不同的库存。
设置
在模块设置中添加您的产品模型 'productClass' => \app\models\Product::class
[
'exchange' => [
'class' => \carono\exchange1c\ExchangeModule::class,
'groupClass' => \app\models\Group::class,
'productClass' => \app\models\Product::class,
]
]
接口
在您的模型中实现接口 carono\exchange1c\interfaces\ProductInterface
setRequisite1c
public function setRequisite1c($name, $value)
设置产品的属性。属性列表位于 import.xml > 目录 > 商品 > 商品 > 属性值 > 属性值
为了存储属性,需要一个属性表,以及一个产品+属性+值汇总表
public function setRequisite1c($name, $value)
{
if (!$requisite = Requisite::findOne(['name' => $name])) {
$requisite = new Requisite();
$requisite->name = $name;
$requisite->save();
}
$this->addPivot($requisite, PvProductRequisite::class, ['value' => $value]);
}
setGroup1c
public function setGroup1c($group)
设置产品所在组。所有组都应该已经保存在数据库中,因为之前调用了方法 \carono\exchange1c\interfaces\GroupInterface::createTree1c,所有组树已经由您创建,因此不需要检查组的存在。
public function setGroup1c($group)
{
$id = Group::find()->select(['id'])->andWhere(['accounting_id' => $group->id])->scalar();
$this->updateAttributes(['group_id' => $id]);
}
createProperties1c
public static function createProperties1c($properties)
此函数在导入时调用一次,在此函数中需要创建所有属性及其值。
/**
* @param PropertyCollection $properties
* @return mixed
*/
public static function createProperties1c($properties)
{
/**
* @var \Zenwalker\CommerceML\Model\Property $property
*/
foreach ($properties as $property) {
$propertyModel = Property::createByMl($property);
foreach ($property->getAvailableValues() as $value) {
if (!$propertyValue = PropertyValue::findOne(['accounting_id' => $value->id])) {
$propertyValue = new PropertyValue();
$propertyValue->name = (string)$value->Значение;
$propertyValue->property_id = $propertyModel->id;
$propertyValue->accounting_id = (string)$value->ИдЗначения;
$propertyValue->save();
unset($propertyValue);
}
}
}
}
setProperty1c
public function setProperty1c($property)
产品属性及其值是单独的实体,因此它们需要分别存储在单独的表中,而值和产品存储在汇总表中。
所有属性已经填写,因为之前执行了 createProperties1c($properties),因此可以按id搜索属性和值。
属性值可以是单独的实体,也可以是简单的值,因此如果xml中存在 ИдЗначения 字段,则需要在值表中查找,否则应该是简单的字符串或数字。
* 在此函数中使用carono/yii2-migrate包中的特性
/**
* $property - Свойство товара (import.xml > Классификатор > Свойства > Свойство)
* $property->value - Разыменованное значение (string) (import.xml > Классификатор > Свойства > Свойство > Значение)
* $property->getValueModel() - Данные по значению, Ид значения, и т.д (import.xml > Классификатор > Свойства > Свойство > ВариантыЗначений > Справочник)
*
* @param MlProperty $property
* @return void
*/
public function setProperty1c($property)
{
$propertyModel = Property::findOne(['accounting_id' => $property->id]);
$propertyValue = $property->getValueModel();
if ($propertyAccountingId = (string)$propertyValue->ИдЗначения) {
$value = PropertyValue::findOne(['accounting_id' => $propertyAccountingId]);
$attributes = ['property_value_id' => $value->id];
} else {
$attributes = ['value' => $propertyValue->value];
}
$this->addPivot($propertyModel, PvProductProperty::class, $attributes);
}
addImage1c
public function addImage1c($path, $caption)
在此函数中,我们获取图片的绝对路径和图像名称(用于alt属性)
* 在此函数中使用carono/yii2-migrate包中的特性和carono/yii2-file-upload包中的文件管理
/**
* @param string $path
* @param string $caption
* @return mixed
*/
public function addImage1c($path, $caption)
{
if (!$this->getImages()->andWhere(['md5' => md5_file($path)])->exists()) {
$this->addPivot(FileUpload::startUpload($path)->process(), PvProductImage::class, ['caption' => $caption]);
}
}
getGroup1c
public function getGroup1c()
获取当前产品所在的组,该组应继承接口 \carono\exchange1c\interfaces\GroupInterface
/**
* @return GroupInterface
*/
public function getGroup1c()
{
return $this->group;
}
getOffer1c
public function getOffer1c($offer)
在此函数中发送XML数据提议,需要创建或找到您的提议模型(接口 \carono\exchange1c\interfaces\OfferInterface)并返回结果。
/**
* @param \Zenwalker\CommerceML\Model\Offer $offer
* @return OfferInterface
*/
public function getOffer1c($offer)
{
$offerModel = Offer::createByMl($offer);
$offerModel->product_id = $this->id;
if ($offerModel->getDirtyAttributes()) {
$offerModel->save();
}
return $offerModel;
}
提议解析示例
class Offer extends BaseOffer implements OfferInterface {
/**
* @param MlOffer $offer
* @return Offer
*/
public static function createByMl($offer)
{
if (!$offerModel = self::findOne(['accounting_id' => $offer->id])) {
$offerModel = new self;
$offerModel->name = (string)$offer->name;
$offerModel->accounting_id = (string)$offer->id;
}
$offerModel->remnant = (string)$offer->Количество;
return $offerModel;
}
}
createModel1c
public static function createModel1c($product)
在此函数中,我们需要找到或创建新产品并返回您的模型。
/**
* @param \Zenwalker\CommerceML\Model\Product $product
* @return self
*/
public static function createModel1c($product)
{
if (!$model = Product::findOne(['accounting_id' => $product->id])) {
$model = new Product();
$model->accounting_id = $product->id;
}
$model->name = $product->name;
$model->description = (string)$product->Описание;
$model->article = (string)$product->Артикул;
$model->save();
return $model;
}
offerClass 报价模型
提议是参与销售的货物模型,它有库存和价格集。
设置
在模块设置中添加您的提议模型 'offerClass' => \app\models\Offer::class
[
'exchange' => [
'class' => \carono\exchange1c\ExchangeModule::class,
'groupClass' => \app\models\Group::class,
'productClass' => \app\models\Product::class,
'offerClass' => \app\models\Offer::class,
]
]
接口
在您的模型中实现接口 carono\exchange1c\interfaces\OfferInterface
getGroup1c
public function getGroup1c()
在此,我们需要获取提议所在的组。通过产品关系获取它。
* 可能未来会被getProduct1c()替代
/**
* @return GroupInterface
*/
public function getGroup1c()
{
return $this->product->group;
}
createPriceTypes1c
public static function createPriceTypes1c($types)
在此方法中,需要创建所有价格类型。价格类型包含名称(零售、批发等)以及货币名称。
/**
* @param $types
* @return void
*/
public static function createPriceTypes1c($types)
{
foreach ($types as $type) {
PriceType::createByMl($type);
}
}
价格类型创建示例
class PriceType extends BasePriceType
{
/**
* @param Simple $type
* @return PriceType
*/
public static function createByMl($type)
{
if (!$priceType = self::findOne(['accounting_id' => $type->id])) {
$priceType = new self;
$priceType->accounting_id = $type->id;
}
$priceType->name = $type->name;
$priceType->currency = (string)$type->Валюта;
if ($priceType->getDirtyAttributes()) {
$priceType->save();
}
return $priceType;
}
}
setPrice1c
public function setPrice1c($price)
价格是单独的实体,因此应存储在单独的表中,并通过汇总表与提议关联。
/**
* offers.xml > ПакетПредложений > Предложения > Предложение > Цены
*
* Цена товара,
* К $price можно обратиться как к массиву, чтобы получить список цен (Цены > Цена)
* $price->type - тип цены (offers.xml > ПакетПредложений > ТипыЦен > ТипЦены)
*
* @param \Zenwalker\CommerceML\Model\Price $price
* @return void
*/
public function setPrice1c($price)
{
$priceType = PriceType::findOne(['accounting_id' => $price->getType()->id]);
$priceModel = Price::createByMl($price, $this, $priceType);
$this->addPivot($priceModel, PvOfferPrice::class);
}
创建价格示例
class Price extends BasePrice
{
/**
* @param MlPrice $price
* @param Offer $offer
* @param PriceType $type
* @return Price
*/
public static function createByMl($price, $offer, $type)
{
if (!$priceModel = $offer->getPrices()->andWhere(['type_id' => $type->id])->one()) {
$priceModel = new self();
}
$priceModel->value = $price->cost;
$priceModel->performance = $price->performance;
$priceModel->currency = $price->currency;
$priceModel->rate = $price->rate;
$priceModel->type_id = $type->id;
$priceModel->save();
return $priceModel;
}
}
setSpecification1c
public function setSpecification1c($specification)
提供特征的属性是独立实体,并且应通过汇总表进行连接。
/**
* offers.xml > ПакетПредложений > Предложения > Предложение > ХарактеристикиТовара > ХарактеристикаТовара
*
* Характеристики товара
* $name - Наименование
* $value - Значение
*
* @param \Zenwalker\CommerceML\Model\Simple $specification
* @return void
*/
public function setSpecification1c($specification)
{
$specificationModel = Specification::createByMl($specification);
$this->addPivot($specificationModel, PvOfferSpecification::class, ['value' => (string)$specification->Значение]);
}
特征解析示例
class Specification extends BaseSpecification
{
public static function createByMl($specification)
{
if (!$specificationModel = self::findOne(['accounting_id' => $specification->id])) {
$specificationModel = new self;
$specificationModel->name = $specification->name;
$specificationModel->accounting_id = $specification->id;
$specificationModel->save();
}
return $specificationModel;
}
}
partnerClass 用户模型
目前,此接口仅用于文档交换。唯一需要实现的是公共方法 public function getExportFields1c,它描述了交换时序列化的字段。需要返回一个数组,其中键是XML中的标签,值是您的数据。所有支持的标准数据都可以在规范中找到,更详细的信息请查看xsd文件,因为官方pdf文件中存在误差。关于此方法的更多信息可以在这里查看。
设置
在模块设置中添加您的提案模型 'partnerClass' => \app\models\Partner::class
[
'exchange' => [
'class' => \carono\exchange1c\ExchangeModule::class,
'groupClass' => \app\models\Group::class,
'productClass' => \app\models\Product::class,
'offerClass' => \app\models\Offer::class,
'partnerClass' => \app\models\Partner::class,
]
]
接口
在您的模型中实现接口 carono\exchange1c\interfaces\PartnerInterface
public function getExportFields1c($context = null)
{
return [
'Ид' => 'id',
'Наименование' => 'username',
'ПолноеНаименование' => 'full_name',
'Фамилия' => 'surname',
'Имя' => 'name',
];
}
documentClass 文档模型
1C中的文档,也就是网站上的订单。文档应通过汇总表与提案相关联。建议在汇总表和订单中均标明金额,以避免动态计算,因为提案的价格可能会改变,客户最终收到的账单可能是另一个金额。
设置
在模块设置中添加您的提案模型 'documentClass' => \app\models\Document::class
[
'exchange' => [
'class' => \carono\exchange1c\ExchangeModule::class,
'groupClass' => \app\models\Group::class,
'productClass' => \app\models\Product::class,
'offerClass' => \app\models\Offer::class,
'partnerClass' => \app\models\Partner::class,
'documentClass' => \app\models\Document::class,
]
]
接口
在您的模型中实现接口 carono\exchange1c\interfaces\DocumentInterface
findDocuments1c
public static function findDocuments1c()
获取所有准备好的文档(订单)。在此函数中,需要返回所有准备导入1C的文档。
请注意,如果在此函数中存在,1C将替换现有文档,因此在导入完成后,需要设置标志或更改状态,以避免在重复导入这些文档时发生。这意味着如果您已在1C中创建文档,开始使用它们或更改状态或填充数据,则在下一次导入时,它们将被重写,您将不得不从头开始。有关如何更新已导出的数据,请参阅事件部分。
/**
* @return DocumentInterface[]
*/
public static function findDocuments1c()
{
return self::find()->andWhere(['status_id' => 2])->all();
}
getOffers1c
public function getOffers1c()
获取已添加到此文档(订单)的所有提案
/**
* @return OfferInterface[]
*/
public function getOffers1c()
{
return $this->offers;
}
getRequisites1c
public function getRequisites1c()
我还不确定这个函数在哪里使用,目前无需填写。
getPartner1c
public function getPartner1c()
需要返回下订单的用户,该类必须实现 \carono\exchange1c\interfaces\PartnerInterface
/**
* Получаем контрагента у документа
*
* @return PartnerInterface
*/
public function getPartner1c()
{
return $this->user;
}
warehouseClass 仓库模型
目前未使用
getExportFields1c
public function getExportFields1c($context = null)
在1C中创建的对象具有接口 \carono\exchange1c\interfaces\ExportFieldsInterface 以及此方法。在此方法中,我们应该返回一个数组,该数组被序列化为1C的XML。数组的键是XML中的标签名称。
值可以是不同的类型,类似于rest api中的 fields 函数。
string - 传递属性名称,如果不存在该属性,则返回此字符串
Closure - 传递函数 function($model)
array - 使用数组可以自定义XML,或者当需要创建多个元素时。在此数组中,有一些保留的键:@content - 标签体,@name - 标签名,@attributes - 属性数组。
所有值都会递归处理,因此可以构建复杂的结构。
输入参数 $context - 是序列化对象的上下文,例如对于提案,上下文将是订单。
文档中合同方序列化示例。
public function getExportFields1c($context = null)
{
return [
'Ид' => 'id',
'Наименование' => 'login',
'ПолноеНаименование' => 'full_name',
'Фамилия' => 'surname',
'Имя' => 'name',
'Контакты' => [
[
'@name' => 'Контакт',
'Тип' => 'Почта',
'Значение' => $this->email,
],
[
'@name' => 'Контакт',
'Тип' => 'ТелефонРабочий',
'Значение' => $this->phone,
],
],
];
}
结果
<Контрагенты>
<Контрагент>
<Ид>13</Ид>
<Наименование>info@carono.ru</Наименование>
<ПолноеНаименование>Иванов Иван Иванович</ПолноеНаименование>
<Контакт>
<Тип>Почта</КонтактВид>
<Значение>info@carono.ru</Значение>
</Контакт>
<Контакт>
<Тип>ТелефонРабочий</КонтактВид>
<Значение>+8(908)123-45-67</Значение>
</Контакт>
</Контрагент>
</Контрагенты>
getIdFieldName1c
public static function getIdFieldName1c()
1C中的所有实体都有一个唯一的标识符 Ид,需要返回存储此值的字段名称。
/**
* Возвращаем имя поля в базе данных, в котором хранится ID из 1с
*
* @return string
*/
public static function getIdFieldName1c()
{
return 'accounting_id';
}
setRaw1cData
public function setRaw1cData($cml, $object)
如果由于某些原因,import.xml或offers.xml文件被修改
某些数据未进入解析器,在调用此方法之前会调用此方法,
$object и $cml 可以获取所有手动解析的数据。
遗憾的是,目前并非所有实体都能通过此方法。
交换协议描述
来源:[链接](http://v8.1c.ru/edi/edi_stnd/131/)
本开放协议由“1C”公司和“1C-Битрикс”公司共同开发。
该协议用于“1C:Предприятие”系统与网站管理系统之间交换商业数据的默认程序。
功能上,交换分为两个部分
第一部分确保将商品目录和数据发布到网站上。第二部分需要将网站信息传递到“1C:Предприятие”系统,并进行订单状态和参数的同步。
在两种情况下,交换的发起者都是“1C:Предприятие”系统。电子文件的交换遵循《CommerceML 2》标准中描述的规则和格式。
在初始化交互时,建立HTTP连接。“1C:Предприятие”系统请求网站所需的参数,例如最大包体积、支持压缩等。基于这些数据,“1C:Предприятие”系统形成XML消息并将其发送到网站。
导出到网站
发布到网站的数据以一个包的形式导出。
A. 会话开始
数据导出从“1C:Предприятие”系统发送以下类型的http请求开始
http://<网站>/<路径> /1c_exchange.php?type=catalog&mode=checkauth.
作为回应,网站管理系统向“1C:Предприятие”系统发送三行(使用换行符"\n"作为分隔符)
- 单词"success";
- Cookie名称;
- Cookie值。
备注。 “1C:Предприятие”系统对网站管理系统的所有后续请求都包含在请求头中的Cookie名称和值。
B. 网站请求参数
接下来是以下类型的请求:
http://<网站>/<路径> /1c_exchange.php?type=catalog&mode=init
作为回应,网站管理系统发送两行
1. zip=yes,如果服务器支持zip格式的交换 - 在这种情况下,在下一步中,文件应打包为zip格式
或者
zip=no - 在这种情况下,在下一步中,文件不打包,每个文件单独传输。
2. file_limit=<数字>,其中 <数字> - 单个请求允许传输的最大文件大小(以字节为单位)。如果“1C:Предприятие”系统需要传输更大的文件,则应将其分割成片段。
C. 导出交换文件到网站
然后,“1C:Предприятие”通过以下参数类型的请求
http://<网站>/<路径> /1c_exchange.php?type=catalog&mode=file&filename=<文件名>
将交换文件以CommerceML 2格式导出到网站,通过POST发送文件内容或其部分。
在文件成功写入的情况下,网站管理系统返回字符串success。
D. 数据逐步加载
最后一步是通过“1C:Предприятие”的请求以以下参数类型逐步加载数据http://<网站>/<路径> /1c_exchange.php?type=catalog&mode=import&filename=<文件名>
在加载过程中,网站管理系统可能以以下几种方式之一回应。
1. 如果第一行包含单词progress - 这意味着需要再次发送相同的请求。在这种情况下,第二行将返回当前处理状态、已加载数据量、导入状态等。
2. 如果返回包含单词success的字符串,这意味着文件处理成功完成的消息。
注意。 如果在处理请求过程中发生错误,则网站管理系统响应的第一行将包含单词“failure”,接下来的行将描述在处理请求过程中发生的错误。
如果发生无法处理的内核产品错误或SQL查询错误,则将返回HTML代码。
文件导出示例
订单信息交换
网站上的订单被上传到“1С:企业”系统。
处理订单的操作顺序
1. 订单在网站上完成
2. 在将订单传输到“1С:企业”系统时,订单将被设置为“网站订单”类别。
在“1С:企业”系统中创建订单时,记录订单号和日期,这些信息与网站上的订单匹配。根据设置,通过纳税人识别号或名称搜索合作伙伴。
3. 在加载订单时,将搜索与合作伙伴的合同。合同将在与客户存在的合同中搜索,具有按订单进行相互结算的标志(按设置的加载组织)。如果没有找到任何合同,则创建一个新的合同。
4. 在加载订单时,将加载从网站传输的所有属性。属性将在“1С:企业”系统中按名称搜索。如果没有找到具有该名称的属性,则将创建一个新的属性,其值类型为字符串或数字。
5. 订单可以在“1С:企业”系统中进行修改,此时修改将上传到网站
6. 如果订单在“1С:企业”系统中支付或发货,则只有在操作完全完成(全额支付和全额发货)时,订单的支付和发货状态才会上传到网站。在此之前,订单被视为未支付和未发货。
7. 在“1С:企业”系统中尝试更改已支付或已发货的订单时,网站上的订单不会作为更改上传。用户将收到有关此消息的通知。
8. 在每次将订单上传到网站后,网站端确定其类别的值(类别的链接)。这些值在“1С:企业”系统中设置,与网站上的订单分配的值相同
A. 会话开始
数据导出从“1C:Предприятие”系统发送以下类型的http请求开始
http://<网站>/<路径> /1c_exchange.php?type=sale&mode=checkauth.
作为回应,网站管理系统向“1C:Предприятие”系统发送三行(使用换行符"\n"作为分隔符)
- 单词"success";
- Cookie名称;
- Cookie值。
备注。 “1C:Предприятие”系统对网站管理系统的所有后续请求都包含在请求头中的Cookie名称和值。
B. 会话参数的确认
接下来是以下类型的请求:
http://<网站>/<路径> /1c_exchange.php?type=sale&mode=init
作为回应,网站管理系统发送两行
1. zip=yes,如果服务器支持zip格式的交换 - 在这种情况下,在下一步中,文件应打包为zip格式
或者
zip=no - 在这种情况下,在下一步中,文件不打包,每个文件单独传输。
2. file_limit=<数字>,其中 <数字> - 单个请求允许传输的最大文件大小(以字节为单位)。如果“1C:Предприятие”系统需要传输更大的文件,则应将其分割成片段。
C. 从网站获取交换文件
然后向网站发送以下类型的请求
http://<网站>/<路径> /1c_exchange.php?type=sale&mode=query.
网站以CommerceML 2格式传输订单信息。在成功接收和记录订单后,“1С:企业”将向网站发送以下类型的请求:
http://<网站>/<路径> /1c_exchange.php?type=sale&mode=success
D. 将交换文件发送到网站
然后“1С:企业”系统向网站发送以下类型的请求:
http://<网站>/<路径> /1c_exchange.php?type=sale&mode=file&filename=<文件名>,
该请求将文件交换文件上传到服务器,以POST的形式发送文件内容。
在成功记录文件后,网站管理系统将传输包含单词“success”的字符串。在接下来的行中,可能包含有关加载的注释。
注意。 如果在处理请求过程中发生错误,则网站管理系统响应的第一行将包含单词“failure”,接下来的行将描述在处理请求过程中发生的错误。
如果发生无法处理的内核产品错误或SQL查询错误,则将返回HTML代码。
交换信息文件的示例
此协议用于将“1С:企业”系统与“1С-Бит里克斯:网站管理”、“UMI.CMS”和其他系统集成。
测试和错误查找
此部分正在开发中
模块事件
beforeUpdateProduct
产品解析开始前的事件
afterUpdateProduct
产品解析完成后的事件
beforeUpdateOffer
解析提案开始前的事件
afterUpdateOffer
解析提案完成后的事件
beforeProductSync
解析所有产品开始前的事件
afterProductSync
解析所有产品完成后的事件
beforeOfferSync
解析所有提案开始前的事件
afterOfferSync
解析所有提案完成后的事件
afterFinishUploadFile
事件,在1C将档案或XML文件上传到您的网站后触发
afterExportOrders
从您的网站形成订单后的事件,在此方法中建议您实现状态更改或设置标志,以排除重复上传文档,因为它们将替换之前已上传的文档。