2024-03-15 21:27:45 +03:00
|
|
|
package bitrix
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
|
|
|
"github.com/sirupsen/logrus"
|
2024-05-03 11:57:53 +03:00
|
|
|
"io"
|
|
|
|
"log"
|
2024-03-15 21:27:45 +03:00
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ClientsResource struct {
|
|
|
|
EntityId string `json:"entityId"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type OrderResource struct {
|
|
|
|
ID string `json:"id,omitempty"`
|
|
|
|
Clients []ClientsResource `json:"clients"`
|
|
|
|
Lid string `json:"lid,omitempty"`
|
|
|
|
DateInsert time.Time `json:"dateInsert,omitempty"`
|
|
|
|
DateUpdate time.Time `json:"dateUpdate,omitempty"`
|
|
|
|
PersonTypeID string `json:"personTypeId,omitempty"`
|
|
|
|
StatusID string `json:"statusId,omitempty"`
|
|
|
|
DateStatus time.Time `json:"dateStatus,omitempty"`
|
|
|
|
EmpStatusID any `json:"empStatusId,omitempty"`
|
|
|
|
Marked string `json:"marked,omitempty"`
|
|
|
|
DateMarked any `json:"dateMarked,omitempty"`
|
|
|
|
EmpMarkedID any `json:"empMarkedId,omitempty"`
|
|
|
|
ReasonMarked any `json:"reasonMarked,omitempty"`
|
|
|
|
Price float64 `json:"price,omitempty"`
|
|
|
|
DiscountValue string `json:"discountValue,omitempty"`
|
|
|
|
TaxValue string `json:"taxValue,omitempty"`
|
|
|
|
UserDescription string `json:"userDescription,omitempty"`
|
|
|
|
AdditionalInfo any `json:"additionalInfo,omitempty"`
|
|
|
|
Comments string `json:"comments,omitempty"`
|
|
|
|
CompanyID string `json:"companyId,omitempty"`
|
|
|
|
ResponsibleID any `json:"responsibleId,omitempty"`
|
|
|
|
StatGid any `json:"statGid,omitempty"`
|
|
|
|
DatePayBefore any `json:"datePayBefore,omitempty"`
|
|
|
|
DateBill any `json:"dateBill,omitempty"`
|
|
|
|
RecurringID any `json:"recurringId,omitempty"`
|
|
|
|
LockedBy string `json:"lockedBy,omitempty"`
|
|
|
|
DateLock time.Time `json:"dateLock,omitempty"`
|
|
|
|
RecountFlag string `json:"recountFlag,omitempty"`
|
|
|
|
AffiliateID any `json:"affiliateId,omitempty"`
|
|
|
|
DeliveryDocNum any `json:"deliveryDocNum,omitempty"`
|
|
|
|
DeliveryDocDate any `json:"deliveryDocDate,omitempty"`
|
|
|
|
Updated1C string `json:"updated1c,omitempty"`
|
|
|
|
OrderTopic any `json:"orderTopic,omitempty"`
|
|
|
|
XMLID any `json:"xmlId,omitempty"`
|
|
|
|
ID1C any `json:"id1c,omitempty"`
|
|
|
|
Version1C any `json:"version1c,omitempty"`
|
|
|
|
Version string `json:"version,omitempty"`
|
|
|
|
ExternalOrder string `json:"externalOrder,omitempty"`
|
|
|
|
StoreID any `json:"storeId,omitempty"`
|
|
|
|
Canceled string `json:"canceled,omitempty"`
|
|
|
|
EmpCanceledID any `json:"empCanceledId,omitempty"`
|
|
|
|
DateCanceled any `json:"dateCanceled,omitempty"`
|
|
|
|
ReasonCanceled any `json:"reasonCanceled,omitempty"`
|
|
|
|
BasketItems []BasketResource `json:"basketItems,omitempty"`
|
|
|
|
Properties []propertyValueResource `json:"properties,omitempty"`
|
|
|
|
Payments []PaymentResource `json:"payments,omitempty"`
|
|
|
|
Shipments []any `json:"shipments,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type propertyValueResource struct {
|
|
|
|
Id string `json:"id"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Value []string `json:"value"`
|
|
|
|
Code string `json:"code"`
|
|
|
|
OrderPropsId string `json:"orderPropsId"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type PaymentResource struct {
|
|
|
|
Id string `json:"id"`
|
|
|
|
OrderId string `json:"orderId"`
|
|
|
|
Paid string `json:"paid"`
|
|
|
|
DatePaid interface{} `json:"datePaid"`
|
|
|
|
EmpPaidId interface{} `json:"empPaidId"`
|
|
|
|
PaySystemId string `json:"paySystemId"`
|
|
|
|
PsStatus interface{} `json:"psStatus"`
|
|
|
|
PsStatusCode interface{} `json:"psStatusCode"`
|
|
|
|
PsInvoiceId interface{} `json:"psInvoiceId"`
|
|
|
|
PsStatusDescription interface{} `json:"psStatusDescription"`
|
|
|
|
PsStatusMessage interface{} `json:"psStatusMessage"`
|
|
|
|
PsSum interface{} `json:"psSum"`
|
|
|
|
PsCurrency interface{} `json:"psCurrency"`
|
|
|
|
PsResponseDate interface{} `json:"psResponseDate"`
|
|
|
|
PayVoucherNum string `json:"payVoucherNum"`
|
|
|
|
PayVoucherDate interface{} `json:"payVoucherDate"`
|
|
|
|
DatePayBefore interface{} `json:"datePayBefore"`
|
|
|
|
DateBill time.Time `json:"dateBill"`
|
|
|
|
XmlId interface{} `json:"xmlId"`
|
|
|
|
Sum string `json:"sum"`
|
|
|
|
PriceCod string `json:"priceCod"`
|
|
|
|
Currency string `json:"currency"`
|
|
|
|
PaySystemName string `json:"paySystemName"`
|
|
|
|
ResponsibleId interface{} `json:"responsibleId"`
|
|
|
|
EmpResponsibleId interface{} `json:"empResponsibleId"`
|
|
|
|
DateResponsibleId interface{} `json:"dateResponsibleId"`
|
|
|
|
Comments interface{} `json:"comments"`
|
|
|
|
CompanyId string `json:"companyId"`
|
|
|
|
PayReturnNum string `json:"payReturnNum"`
|
|
|
|
PayReturnDate interface{} `json:"payReturnDate"`
|
|
|
|
EmpReturnId interface{} `json:"empReturnId"`
|
|
|
|
PayReturnComment string `json:"payReturnComment"`
|
|
|
|
IsReturn string `json:"isReturn"`
|
|
|
|
Marked string `json:"marked"`
|
|
|
|
DateMarked interface{} `json:"dateMarked"`
|
|
|
|
EmpMarkedId interface{} `json:"empMarkedId"`
|
|
|
|
ReasonMarked interface{} `json:"reasonMarked"`
|
|
|
|
Updated1C string `json:"updated1c"`
|
|
|
|
Id1C interface{} `json:"id1c"`
|
|
|
|
Version1C interface{} `json:"version1c"`
|
|
|
|
ExternalPayment string `json:"externalPayment"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type BasketResource struct {
|
|
|
|
Module string `json:"module"`
|
|
|
|
ProductId string `json:"productId"`
|
|
|
|
Id string `json:"id"`
|
|
|
|
Lid string `json:"lid"`
|
|
|
|
Quantity string `json:"quantity"`
|
|
|
|
Weight string `json:"weight"`
|
|
|
|
Price float64 `json:"price"`
|
|
|
|
CustomPrice string `json:"customPrice"`
|
|
|
|
BasePrice string `json:"basePrice"`
|
|
|
|
ProductPriceId string `json:"productPriceId"`
|
|
|
|
PriceTypeId string `json:"priceTypeId"`
|
|
|
|
Currency string `json:"currency"`
|
|
|
|
BarcodeMulti string `json:"barcodeMulti"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
CatalogXmlId string `json:"catalogXmlId"`
|
|
|
|
VatRate string `json:"vatRate"`
|
|
|
|
Notes string `json:"notes"`
|
|
|
|
DiscountPrice string `json:"discountPrice"`
|
|
|
|
ProductProviderClass string `json:"productProviderClass"`
|
|
|
|
Dimensions string `json:"dimensions"`
|
|
|
|
Type interface{} `json:"type"`
|
|
|
|
SetParentId interface{} `json:"setParentId"`
|
|
|
|
DetailPageUrl string `json:"detailPageUrl"`
|
|
|
|
MeasureCode string `json:"measureCode"`
|
|
|
|
MeasureName string `json:"measureName"`
|
|
|
|
OrderId string `json:"orderId"`
|
|
|
|
ProductXmlId string `json:"productXmlId"`
|
|
|
|
Subscribe string `json:"subscribe"`
|
|
|
|
Recommendation interface{} `json:"recommendation"`
|
|
|
|
VatIncluded string `json:"vatIncluded"`
|
|
|
|
Sort string `json:"sort"`
|
|
|
|
DiscountName interface{} `json:"discountName"`
|
|
|
|
DiscountValue interface{} `json:"discountValue"`
|
|
|
|
DiscountCoupon interface{} `json:"discountCoupon"`
|
|
|
|
Properties []struct {
|
|
|
|
Id string `json:"id"`
|
|
|
|
BasketId string `json:"basketId"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Value string `json:"value"`
|
|
|
|
Code string `json:"code"`
|
|
|
|
Sort string `json:"sort"`
|
|
|
|
} `json:"properties"`
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
type bitrix struct {
|
2024-05-03 11:57:53 +03:00
|
|
|
EP string
|
|
|
|
EPCustom string
|
2024-03-29 03:00:21 +03:00
|
|
|
}
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
type Bitrix interface {
|
|
|
|
CreateAnonymousUser() (int, error)
|
|
|
|
CreateOrder(userId int) (int, error)
|
|
|
|
ApprovePayment(paymentId int, paySystemId int) error
|
|
|
|
CancelOrder(orderId int) error
|
|
|
|
GetOrderInfo(orderId int) (*OrderResource, error)
|
|
|
|
CreatePayment(orderId int, sum float64) error
|
2024-05-03 11:57:53 +03:00
|
|
|
AddProductToOrder(orderId int, productId int, price float64, quantity int, productName string) error
|
2024-03-15 21:27:45 +03:00
|
|
|
UpdateContact(contactId int, email string, name string, phone string) error
|
2024-05-03 11:57:53 +03:00
|
|
|
GetTotalForProduct(fuserId int, coupon *string) (*GetTotalOrderResponse, error)
|
2024-03-15 21:27:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
type createAnonymousUserRequest struct {
|
|
|
|
Email string `json:"EMAIL"`
|
|
|
|
Name string `json:"NAME"`
|
|
|
|
Password string `json:"PASSWORD"`
|
|
|
|
ConfirmPassword string `json:"CONFIRM_PASSWORD"`
|
|
|
|
UFDepartment []int `json:"UF_DEPARTMENT"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type createAnonymousUserResponse struct {
|
|
|
|
Result int `json:"result"`
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
func (b bitrix) CreateAnonymousUser() (int, error) {
|
2024-03-15 21:27:45 +03:00
|
|
|
uid, _ := uuid.NewUUID()
|
|
|
|
req := createAnonymousUserRequest{
|
|
|
|
Email: fmt.Sprintf("anonymous%s@anonym.ru", uid.String()),
|
|
|
|
Name: "Анонимный пользователь",
|
|
|
|
Password: uid.String(),
|
|
|
|
ConfirmPassword: uid.String(),
|
|
|
|
UFDepartment: []int{0},
|
|
|
|
}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
resp, err := http.Post(b.EP+"/user.add", "application/json", bytes.NewBuffer(query))
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
result := createAnonymousUserResponse{}
|
|
|
|
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
|
|
|
|
|
|
return result.Result, err
|
|
|
|
}
|
|
|
|
|
|
|
|
type createOrderRequestWrapper struct {
|
|
|
|
Fields createOrderRequest `json:"fields"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type createOrderRequest struct {
|
|
|
|
Lid string `json:"lid"`
|
|
|
|
PersonTypeId int `json:"personTypeId"`
|
|
|
|
Currency string `json:"currency"`
|
|
|
|
UserId int `json:"userId"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type createOrderResponse struct {
|
|
|
|
Result struct {
|
|
|
|
Order struct {
|
|
|
|
Id int `json:"id"`
|
|
|
|
} `json:"order"`
|
|
|
|
} `json:"result"`
|
|
|
|
}
|
|
|
|
|
2024-05-03 11:57:53 +03:00
|
|
|
type GetTotalOrderResponse struct {
|
|
|
|
Price float64 `json:"price"`
|
|
|
|
BasePrice float64 `json:"basePrice"`
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
func (b bitrix) CreateOrder(userId int) (int, error) {
|
2024-03-15 21:27:45 +03:00
|
|
|
req := createOrderRequestWrapper{createOrderRequest{
|
|
|
|
Lid: "s2",
|
|
|
|
PersonTypeId: 5,
|
|
|
|
Currency: "RUB",
|
|
|
|
UserId: userId,
|
|
|
|
}}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
resp, _ := http.Post(b.EP+"/sale.order.add", "application/json", bytes.NewBuffer(query))
|
2024-03-15 21:27:45 +03:00
|
|
|
result := createOrderResponse{}
|
|
|
|
|
|
|
|
err := json.NewDecoder(resp.Body).Decode(&result)
|
|
|
|
|
|
|
|
return result.Result.Order.Id, err
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
func (b bitrix) ApprovePayment(paymentId int, paySystemId int) error {
|
2024-03-15 21:27:45 +03:00
|
|
|
req := map[string]interface{}{
|
|
|
|
"id": paymentId,
|
|
|
|
"fields": map[string]interface{}{"paid": "Y", "paySystemId": paySystemId},
|
|
|
|
}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-05-03 11:57:53 +03:00
|
|
|
resp, err := http.Post(b.EP+"/sale.payment.update", "application/json", bytes.NewBuffer(query))
|
|
|
|
|
|
|
|
str, _ := io.ReadAll(resp.Body)
|
|
|
|
log.Println(str)
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
func (b bitrix) CancelOrder(orderId int) error {
|
2024-03-15 21:27:45 +03:00
|
|
|
req := map[string]interface{}{
|
|
|
|
"id": orderId,
|
|
|
|
"fields": map[string]interface{}{"canceled": "Y"},
|
|
|
|
}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
_, err := http.Post(b.EP+"/sale.order.update", "application/json", bytes.NewBuffer(query))
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
func (b bitrix) GetOrderInfo(orderId int) (*OrderResource, error) {
|
2024-03-15 21:27:45 +03:00
|
|
|
req := map[string]interface{}{
|
|
|
|
"id": orderId,
|
|
|
|
}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
response, err := http.Post(b.EP+"/sale.order.get", "application/json", bytes.NewBuffer(query))
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
result := struct {
|
|
|
|
Result struct {
|
|
|
|
Order map[string]interface{} `json:"order"`
|
|
|
|
} `json:"result"`
|
|
|
|
}{}
|
|
|
|
|
|
|
|
err = json.NewDecoder(response.Body).Decode(&result)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Error: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
resultParsed := OrderResource{}
|
|
|
|
mapstructure.Decode(result.Result.Order, &resultParsed)
|
|
|
|
return &resultParsed, err
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
func (b bitrix) CreatePayment(orderId int, sum float64) error {
|
2024-03-15 21:27:45 +03:00
|
|
|
req := map[string]interface{}{
|
|
|
|
"fields": map[string]interface{}{
|
|
|
|
"orderId": orderId,
|
|
|
|
"sum": sum,
|
|
|
|
"paid": "N",
|
|
|
|
"paySystemId": 8,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
_, err := http.Post(b.EP+"/sale.payment.add", "application/json", bytes.NewBuffer(query))
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-05-03 11:57:53 +03:00
|
|
|
func (b bitrix) AddProductToOrder(orderId int, productId int, price float64, quantity int, productName string) error {
|
2024-03-15 21:27:45 +03:00
|
|
|
req := map[string]interface{}{
|
|
|
|
"fields": map[string]interface{}{
|
2024-05-03 11:57:53 +03:00
|
|
|
"name": productName,
|
|
|
|
"orderId": orderId,
|
|
|
|
"module": "catalog",
|
|
|
|
"productId": productId,
|
|
|
|
"quantity": quantity,
|
|
|
|
"currency": "RUB",
|
|
|
|
"vatIncluded": "Y",
|
|
|
|
"vatRate": 0.2,
|
|
|
|
"basePrice": price,
|
|
|
|
"productXmlId": fmt.Sprintf("%d", productId),
|
|
|
|
"detailPageUrl": fmt.Sprintf("\\/CRM_PRODUCT_CATALOG\\/detail.php?ID=%d", productId),
|
2024-03-15 21:27:45 +03:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-05-03 11:57:53 +03:00
|
|
|
_, err := http.Post(b.EP+"/sale.basketitem.add", "application/json", bytes.NewBuffer(query))
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
func (b bitrix) UpdateContact(contactId int, email string, name string, phone string) error {
|
2024-03-15 21:27:45 +03:00
|
|
|
req := map[string]interface{}{
|
|
|
|
"id": contactId,
|
|
|
|
"fields": map[string]interface{}{
|
|
|
|
"EMAIL": append([]map[string]interface{}{}, map[string]interface{}{
|
|
|
|
"VALUE_TYPE": "other",
|
|
|
|
"VALUE": email,
|
|
|
|
"TYPE_ID": "EMAIL",
|
|
|
|
}),
|
2024-03-29 03:00:21 +03:00
|
|
|
"NAME": strings.Split(name, " ")[1],
|
|
|
|
"LAST_NAME": strings.Split(name, " ")[0],
|
2024-03-15 21:27:45 +03:00
|
|
|
"PHONE": append([]map[string]interface{}{}, map[string]interface{}{
|
|
|
|
"VALUE_TYPE": "other",
|
|
|
|
"VALUE": phone,
|
|
|
|
"TYPE_ID": "PHONE",
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
query, _ := json.Marshal(req)
|
|
|
|
|
2024-03-29 03:00:21 +03:00
|
|
|
_, err := http.Post(b.EP+"/crm.contact.update", "application/json", bytes.NewBuffer(query))
|
2024-03-15 21:27:45 +03:00
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-05-03 11:57:53 +03:00
|
|
|
func (b bitrix) GetTotalForProduct(fuserId int, coupon *string) (*GetTotalOrderResponse, error) {
|
|
|
|
var result *http.Response
|
|
|
|
var err error
|
|
|
|
|
|
|
|
if coupon != nil {
|
|
|
|
result, err = http.Get(b.EPCustom + fmt.Sprintf("/order/total?fuserId=%d&coupon=%s", fuserId, *coupon))
|
|
|
|
} else {
|
|
|
|
result, err = http.Get(b.EPCustom + fmt.Sprintf("/order/total?fuserId=%d", fuserId))
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer result.Body.Close()
|
|
|
|
|
|
|
|
returnedValue := new(GetTotalOrderResponse)
|
|
|
|
json.NewDecoder(result.Body).Decode(returnedValue)
|
|
|
|
|
|
|
|
return returnedValue, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-03-15 21:27:45 +03:00
|
|
|
func Initialize() Bitrix {
|
2024-03-29 03:00:21 +03:00
|
|
|
return &bitrix{
|
2024-05-03 11:57:53 +03:00
|
|
|
EP: os.Getenv("BITRIX_API_EP"),
|
|
|
|
EPCustom: os.Getenv("BTIRIX_API_CUSTOM"),
|
2024-03-29 03:00:21 +03:00
|
|
|
}
|
2024-03-15 21:27:45 +03:00
|
|
|
}
|