Implementing Product Export from Website to 1C (CommerceML)
If import from 1C is catalog synchronization to website, export is the reverse task: sending orders, stock, or customer data back to 1C. Often required in online stores where 1C is accounting system and website is sales point.
What is transmitted to 1C
Most common scenarios:
| Data | CommerceML file | Frequency |
|---|---|---|
| New orders | sale.xml |
By event / every N minutes |
| Order status changes | sale.xml |
By event |
| Website stock | offers.xml |
By schedule |
| Customers | import.xml |
By schedule |
Exchange Protocol (Website Side)
1C requests data via CommerceML2 protocol:
GET /1c-exchange/?type=sale&mode=checkauth
GET /1c-exchange/?type=sale&mode=init
GET /1c-exchange/?type=sale&mode=query — get orders list
POST /1c-exchange/?type=sale&mode=success — confirm receipt
GET /1c-exchange/?type=sale&mode=file&filename=sale.xml — download file
Generating sale.xml
class SaleXmlGenerator
{
public function generate(Collection $orders): string
{
$xml = new \DOMDocument('1.0', 'UTF-8');
$root = $xml->createElement('КоммерческаяИнформация');
$root->setAttribute('ВерсияСхемы', '2.10');
$xml->appendChild($root);
foreach ($orders as $order) {
$orderNode = $xml->createElement('Документ');
$this->addElement($xml, $orderNode, 'Ід', $order->uuid);
$this->addElement($xml, $orderNode, 'Номер', $order->number);
$this->addElement($xml, $orderNode, 'Дата', $order->created_at->format('Y-m-d'));
$this->addElement($xml, $orderNode, 'Сумма', number_format($order->total, 2, '.', ''));
// Контрагент
$client = $xml->createElement('Контрагенты');
$agent = $xml->createElement('Контрагент');
$this->addElement($xml, $agent, 'Наименование', $order->customer_name);
$client->appendChild($agent);
$orderNode->appendChild($client);
// Товари
$products = $xml->createElement('Товары');
foreach ($order->items as $item) {
$product = $xml->createElement('Товар');
$this->addElement($xml, $product, 'Ід', $item->product->onec_guid);
$this->addElement($xml, $product, 'Наименование', $item->product->name);
$this->addElement($xml, $product, 'Количество', $item->quantity);
$products->appendChild($product);
}
$orderNode->appendChild($products);
$root->appendChild($orderNode);
}
return $xml->saveXML();
}
}
Confirming order receipt
1C after successful receipt sends list of processed order GUIDs. Site marks them as transmitted to 1C:
public function markAsSent(Request $request): Response
{
$guids = explode("\n", $request->getContent());
Order::whereIn('uuid', array_filter($guids))
->update(['sent_to_1c' => true, 'sent_to_1c_at' => now()]);
return response('success');
}
Updating statuses from 1C
1C can return order processing statuses (paid, shipped, cancelled). Site receives updated orders via POST /1c-exchange/?type=sale&mode=file:
public function processSaleResponse(string $xmlPath): void
{
$xml = simplexml_load_file($xmlPath);
foreach ($xml->Документ as $doc) {
$guid = (string) $doc->Ід;
$status = (string) $doc->Статус;
Order::where('uuid', $guid)->update([
'status' => $this->mapOnecStatus($status),
'onec_status' => $status,
]);
}
}
private function mapOnecStatus(string $onecStatus): string
{
return match($onecStatus) {
'Оплачен' => 'paid',
'Отгружен' => 'shipped',
'Отменён' => 'cancelled',
default => 'unknown',
};
}
Common Difficulties
- Empty product GUIDs — if product created on site, not imported from 1C, its GUID unknown in 1C. Need logic to create new product in 1C or match by SKU
- Encoding — some 1C versions require Windows-1251 files
- Testing — need access to client's test 1C database during development
Timeline
Export orders to 1C with receipt confirmation and status updates: 8–14 work days.







