373 lines
14 KiB
Plaintext
373 lines
14 KiB
Plaintext
*-- Script Visual FoxPro 9 pentru accesul la GoMag API cu paginare completa
|
|
*-- Autor: Claude AI
|
|
*-- Data: 26.08.2025
|
|
|
|
*-- Setari principale
|
|
LOCAL lcApiBaseUrl, lcApiUrl, lcApiKey, lcUserAgent, lcContentType
|
|
LOCAL loHttp, lcResponse, lcJsonResponse
|
|
LOCAL laHeaders[10], lnHeaderCount
|
|
Local lcApiShop, lcCsvFileName, lcErrorResponse, lcFileName, lcLogContent, lcLogFileName, lcPath
|
|
Local lcStatusText, lnStatusCode, loError
|
|
Local lnLimit, lnCurrentPage, llHasMorePages, loAllJsonData, lnTotalPages, lnTotalProducts
|
|
PRIVATE gcAppPath, loJsonData
|
|
|
|
|
|
|
|
gcAppPath = ADDBS(JUSTPATH(SYS(16,0)))
|
|
SET DEFAULT TO (m.gcAppPath)
|
|
lcPath = gcAppPath + 'nfjson;'
|
|
SET PATH TO (m.lcPath) ADDITIVE
|
|
|
|
SET PROCEDURE TO nfjsonread.prg ADDITIVE
|
|
|
|
*-- Configurare API - MODIFICA aceste valori conform documentatiei GoMag
|
|
lcApiBaseUrl = "https://api.gomag.ro/api/v1/product/read/json?enabled=1" && URL de baza pentru lista de produse
|
|
lcApiKey = "4c5e46df8f6c4f054fe2787de7a13d4a" && Cheia ta API de la GoMag
|
|
lcApiShop = "https://www.coffeepoint.ro" && URL-ul magazinului tau (ex: http://yourdomain.gomag.ro)
|
|
lcUserAgent = "Mozilla/5.0" && User-Agent diferit de PostmanRuntime conform documentatiei
|
|
lcContentType = "application/json"
|
|
lnLimit = 100 && Numarul maxim de produse per pagina (1-100)
|
|
lnCurrentPage = 1 && Pagina de start
|
|
llHasMorePages = .T. && Flag pentru paginare
|
|
loAllJsonData = NULL && Obiect pentru toate datele
|
|
|
|
*-- Verificare daca avem WinHttp disponibil
|
|
TRY
|
|
loHttp = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
|
|
CATCH TO loError
|
|
? "Eroare la crearea obiectului WinHttp: " + loError.Message
|
|
RETURN .F.
|
|
ENDTRY
|
|
|
|
*-- Bucla pentru preluarea tuturor produselor (paginare)
|
|
loAllJsonData = CREATEOBJECT("Empty")
|
|
ADDPROPERTY(loAllJsonData, "products", CREATEOBJECT("Empty"))
|
|
ADDPROPERTY(loAllJsonData, "total", 0)
|
|
ADDPROPERTY(loAllJsonData, "pages", 0)
|
|
lnTotalProducts = 0
|
|
|
|
DO WHILE llHasMorePages
|
|
*-- Construire URL cu paginare
|
|
lcApiUrl = lcApiBaseUrl + "&page=" + TRANSFORM(lnCurrentPage) + "&limit=" + TRANSFORM(lnLimit)
|
|
|
|
? "Preluare pagina " + TRANSFORM(lnCurrentPage) + "..."
|
|
|
|
*-- Configurare request
|
|
TRY
|
|
*-- Initializare request GET
|
|
loHttp.Open("GET", lcApiUrl, .F.)
|
|
|
|
*-- Setare headers conform documentatiei GoMag
|
|
loHttp.SetRequestHeader("User-Agent", lcUserAgent)
|
|
loHttp.SetRequestHeader("Content-Type", lcContentType)
|
|
loHttp.SetRequestHeader("Accept", "application/json")
|
|
loHttp.SetRequestHeader("Apikey", lcApiKey) && Header pentru API Key
|
|
loHttp.SetRequestHeader("ApiShop", lcApiShop) && Header pentru shop URL
|
|
|
|
*-- Setari timeout
|
|
loHttp.SetTimeouts(30000, 30000, 30000, 30000) && 30 secunde pentru fiecare
|
|
|
|
*-- Trimitere request
|
|
loHttp.Send()
|
|
|
|
*-- Verificare status code
|
|
lnStatusCode = loHttp.Status
|
|
lcStatusText = loHttp.StatusText
|
|
|
|
IF lnStatusCode = 200
|
|
*-- Success - preluare raspuns
|
|
lcResponse = loHttp.ResponseText
|
|
|
|
*-- Parsare JSON cu nfjson
|
|
SET PATH TO nfjson ADDITIVE
|
|
loJsonData = nfJsonRead(lcResponse)
|
|
|
|
IF !ISNULL(loJsonData)
|
|
*-- Prima pagina - setam informatiile generale
|
|
IF lnCurrentPage = 1
|
|
IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N'
|
|
loAllJsonData.total = VAL(TRANSFORM(loJsonData.total))
|
|
ENDIF
|
|
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
|
|
loAllJsonData.pages = VAL(TRANSFORM(loJsonData.pages))
|
|
ENDIF
|
|
? "Total produse: " + TRANSFORM(loAllJsonData.total)
|
|
? "Total pagini: " + TRANSFORM(loAllJsonData.pages)
|
|
ENDIF
|
|
|
|
*-- Adaugare produse din pagina curenta
|
|
IF TYPE('loJsonData.products') = 'O'
|
|
DO MergeProducts WITH loAllJsonData, loJsonData
|
|
ENDIF
|
|
|
|
*-- Verificare daca mai sunt pagini
|
|
IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N'
|
|
lnTotalPages = VAL(TRANSFORM(loJsonData.pages))
|
|
IF lnCurrentPage >= lnTotalPages
|
|
llHasMorePages = .F.
|
|
ENDIF
|
|
ELSE
|
|
*-- Daca nu avem info despre pagini, verificam daca sunt produse
|
|
IF TYPE('loJsonData.products') != 'O'
|
|
llHasMorePages = .F.
|
|
ENDIF
|
|
ENDIF
|
|
|
|
lnCurrentPage = lnCurrentPage + 1
|
|
|
|
ELSE
|
|
*-- Salvare raspuns JSON raw in caz de eroare de parsare
|
|
lcFileName = "gomag_error_page" + TRANSFORM(lnCurrentPage) + "_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json"
|
|
STRTOFILE(lcResponse, lcFileName)
|
|
llHasMorePages = .F.
|
|
ENDIF
|
|
|
|
ELSE
|
|
*-- Eroare HTTP - salvare in fisier de log
|
|
lcLogFileName = "gomag_error_page" + TRANSFORM(lnCurrentPage) + "_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".log"
|
|
lcLogContent = "HTTP Error " + TRANSFORM(lnStatusCode) + ": " + lcStatusText + CHR(13) + CHR(10)
|
|
|
|
*-- Incearca sa citesti raspunsul pentru detalii despre eroare
|
|
TRY
|
|
lcErrorResponse = loHttp.ResponseText
|
|
IF !EMPTY(lcErrorResponse)
|
|
lcLogContent = lcLogContent + "Error Details:" + CHR(13) + CHR(10) + lcErrorResponse
|
|
ENDIF
|
|
CATCH
|
|
lcLogContent = lcLogContent + "Could not read error details"
|
|
ENDTRY
|
|
|
|
STRTOFILE(lcLogContent, lcLogFileName)
|
|
llHasMorePages = .F.
|
|
ENDIF
|
|
|
|
CATCH TO loError
|
|
*-- Salvare erori in fisier de log pentru pagina curenta
|
|
lcLogFileName = "gomag_error_page" + TRANSFORM(lnCurrentPage) + "_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".log"
|
|
lcLogContent = "Script Error on page " + TRANSFORM(lnCurrentPage) + ":" + CHR(13) + CHR(10) +;
|
|
"Error Number: " + TRANSFORM(loError.ErrorNo) + CHR(13) + CHR(10) +;
|
|
"Error Message: " + loError.Message + CHR(13) + CHR(10) +;
|
|
"Error Line: " + TRANSFORM(loError.LineNo)
|
|
STRTOFILE(lcLogContent, lcLogFileName)
|
|
llHasMorePages = .F.
|
|
ENDTRY
|
|
|
|
*-- Pauza scurta intre cereri pentru a evita rate limiting
|
|
IF llHasMorePages
|
|
INKEY(1) && Pauza de 1 secunda
|
|
ENDIF
|
|
|
|
ENDDO
|
|
|
|
*-- Creare fisier CSV cu toate produsele
|
|
IF !ISNULL(loAllJsonData) AND TYPE('loAllJsonData.products') = 'O'
|
|
lcCsvFileName = "gomag_all_products_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".csv"
|
|
DO CreateCsvFromJson WITH loAllJsonData, lcCsvFileName
|
|
? "Fisier CSV creat: " + lcCsvFileName
|
|
|
|
*-- Salvare si a datelor JSON complete
|
|
lcJsonFileName = "gomag_all_products_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json"
|
|
DO SaveCompleteJson WITH loAllJsonData, lcJsonFileName
|
|
? "Fisier JSON complet creat: " + lcJsonFileName
|
|
ENDIF
|
|
|
|
*-- Curatare
|
|
loHttp = NULL
|
|
|
|
*-- Functie pentru unirea produselor din toate paginile
|
|
PROCEDURE MergeProducts
|
|
PARAMETERS tloAllData, tloPageData
|
|
|
|
LOCAL lnPropCount, lnIndex, lcPropName, loProduct
|
|
|
|
*-- Verifica daca avem produse in pagina curenta
|
|
IF TYPE('tloPageData.products') = 'O'
|
|
*-- Itereaza prin toate produsele din pagina
|
|
lnPropCount = AMEMBERS(laPageProducts, tloPageData.products, 0)
|
|
|
|
FOR lnIndex = 1 TO lnPropCount
|
|
lcPropName = laPageProducts(lnIndex)
|
|
loProduct = EVALUATE('tloPageData.products.' + lcPropName)
|
|
|
|
IF TYPE('loProduct') = 'O'
|
|
*-- Adauga produsul la colectia principala
|
|
ADDPROPERTY(tloAllData.products, lcPropName, loProduct)
|
|
ENDIF
|
|
ENDFOR
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
*-- Functie pentru salvarea datelor JSON complete
|
|
PROCEDURE SaveCompleteJson
|
|
PARAMETERS tloJsonData, tcFileName
|
|
|
|
LOCAL lcJsonContent
|
|
|
|
*-- Construieste JSON simplu pentru salvare
|
|
lcJsonContent = '{' + CHR(13) + CHR(10)
|
|
lcJsonContent = lcJsonContent + ' "total": ' + TRANSFORM(tloJsonData.total) + ',' + CHR(13) + CHR(10)
|
|
lcJsonContent = lcJsonContent + ' "pages": ' + TRANSFORM(tloJsonData.pages) + ',' + CHR(13) + CHR(10)
|
|
lcJsonContent = lcJsonContent + ' "products": {' + CHR(13) + CHR(10)
|
|
|
|
*-- Adauga produsele (versiune simplificata)
|
|
LOCAL lnPropCount, lnIndex, lcPropName, loProduct
|
|
lnPropCount = AMEMBERS(laProducts, tloJsonData.products, 0)
|
|
|
|
FOR lnIndex = 1 TO lnPropCount
|
|
lcPropName = laProducts(lnIndex)
|
|
loProduct = EVALUATE('tloJsonData.products.' + lcPropName)
|
|
|
|
IF TYPE('loProduct') = 'O'
|
|
lcJsonContent = lcJsonContent + ' "' + lcPropName + '": {'
|
|
|
|
IF TYPE('loProduct.id') = 'C'
|
|
lcJsonContent = lcJsonContent + '"id": "' + loProduct.id + '",'
|
|
ENDIF
|
|
IF TYPE('loProduct.sku') = 'C'
|
|
lcJsonContent = lcJsonContent + '"sku": "' + loProduct.sku + '",'
|
|
ENDIF
|
|
IF TYPE('loProduct.name') = 'C'
|
|
lcJsonContent = lcJsonContent + '"name": "' + STRTRAN(loProduct.name, '"', '\"') + '",'
|
|
ENDIF
|
|
|
|
*-- Elimina ultima virgula
|
|
IF RIGHT(lcJsonContent, 1) = ','
|
|
lcJsonContent = LEFT(lcJsonContent, LEN(lcJsonContent) - 1)
|
|
ENDIF
|
|
|
|
lcJsonContent = lcJsonContent + '}'
|
|
|
|
IF lnIndex < lnPropCount
|
|
lcJsonContent = lcJsonContent + ','
|
|
ENDIF
|
|
|
|
lcJsonContent = lcJsonContent + CHR(13) + CHR(10)
|
|
ENDIF
|
|
ENDFOR
|
|
|
|
lcJsonContent = lcJsonContent + ' }' + CHR(13) + CHR(10)
|
|
lcJsonContent = lcJsonContent + '}' + CHR(13) + CHR(10)
|
|
|
|
STRTOFILE(lcJsonContent, tcFileName)
|
|
|
|
ENDPROC
|
|
|
|
*-- Functie pentru crearea fisierului CSV din datele JSON
|
|
PROCEDURE CreateCsvFromJson
|
|
PARAMETERS tloJsonData, tcCsvFileName
|
|
|
|
LOCAL lcCsvContent, lcCsvHeader, lcCsvRow
|
|
LOCAL lnProductCount, lnIndex
|
|
LOCAL loProduct
|
|
|
|
lcCsvContent = ""
|
|
lcCsvHeader = "ID,SKU,Name,Brand,Weight,Stock,Base_Price,Price,VAT_Included,Enabled,VAT,Currency,Ecotax" + CHR(13) + CHR(10)
|
|
lcCsvContent = lcCsvHeader
|
|
|
|
*-- Verifica daca avem produse in raspuns
|
|
IF TYPE('tloJsonData.products') = 'O'
|
|
*-- Itereaza prin toate produsele
|
|
lnPropCount = AMEMBERS(laProducts, tloJsonData.products, 0)
|
|
|
|
? "Procesare " + TRANSFORM(lnPropCount) + " produse pentru CSV..."
|
|
|
|
FOR lnIndex = 1 TO lnPropCount
|
|
lcPropName = laProducts(lnIndex)
|
|
loProduct = EVALUATE('tloJsonData.products.' + lcPropName)
|
|
|
|
IF TYPE('loProduct') = 'O'
|
|
*-- Extrage datele produsului
|
|
lcCsvRow = ;
|
|
IIF(TYPE('loProduct.id')='C', STRTRAN(loProduct.id, ',', ';'), '') + ',' +;
|
|
IIF(TYPE('loProduct.sku')='C', STRTRAN(loProduct.sku, ',', ';'), '') + ',' +;
|
|
IIF(TYPE('loProduct.name')='C', '"' + STRTRAN(STRTRAN(loProduct.name, '"', '""'), ',', ';') + '"', '') + ',' +;
|
|
IIF(TYPE('loProduct.brand')='C', STRTRAN(loProduct.brand, ',', ';'), '') + ',' +;
|
|
IIF(TYPE('loProduct.weight')='C', loProduct.weight, IIF(TYPE('loProduct.weight')='N', TRANSFORM(loProduct.weight), '')) + ',' +;
|
|
IIF(TYPE('loProduct.stock')='C', loProduct.stock, IIF(TYPE('loProduct.stock')='N', TRANSFORM(loProduct.stock), '')) + ',' +;
|
|
IIF(TYPE('loProduct.base_price')='C', loProduct.base_price, IIF(TYPE('loProduct.base_price')='N', TRANSFORM(loProduct.base_price), '')) + ',' +;
|
|
IIF(TYPE('loProduct.price')='C', loProduct.price, IIF(TYPE('loProduct.price')='N', TRANSFORM(loProduct.price), '')) + ',' +;
|
|
IIF(TYPE('loProduct.vat_included')='C', loProduct.vat_included, IIF(TYPE('loProduct.vat_included')='N', TRANSFORM(loProduct.vat_included), '')) + ',' +;
|
|
IIF(TYPE('loProduct.enabled')='C', loProduct.enabled, IIF(TYPE('loProduct.enabled')='N', TRANSFORM(loProduct.enabled), '')) + ',' +;
|
|
IIF(TYPE('loProduct.vat')='C', loProduct.vat, IIF(TYPE('loProduct.vat')='N', TRANSFORM(loProduct.vat), '')) + ',' +;
|
|
IIF(TYPE('loProduct.currency')='C', loProduct.currency, '') + ',' +;
|
|
IIF(TYPE('loProduct.ecotax')='C', loProduct.ecotax, IIF(TYPE('loProduct.ecotax')='N', TRANSFORM(loProduct.ecotax), '')) +;
|
|
CHR(13) + CHR(10)
|
|
|
|
lcCsvContent = lcCsvContent + lcCsvRow
|
|
ENDIF
|
|
ENDFOR
|
|
ENDIF
|
|
|
|
*-- Salvare fisier CSV
|
|
STRTOFILE(lcCsvContent, tcCsvFileName)
|
|
? "CSV salvat cu " + TRANSFORM(lnPropCount) + " produse"
|
|
|
|
ENDPROC
|
|
|
|
*-- Functii helper pentru testare (optionale)
|
|
|
|
*-- Test conectivitate internet
|
|
FUNCTION TestConnectivity
|
|
LOCAL loHttp, llResult
|
|
|
|
llResult = .T.
|
|
|
|
TRY
|
|
loHttp = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
|
|
loHttp.Open("GET", "https://www.google.com", .F.)
|
|
loHttp.SetTimeouts(5000, 5000, 5000, 5000)
|
|
loHttp.Send()
|
|
|
|
IF loHttp.Status != 200
|
|
llResult = .F.
|
|
ENDIF
|
|
|
|
CATCH
|
|
llResult = .F.
|
|
ENDTRY
|
|
|
|
loHttp = NULL
|
|
RETURN llResult
|
|
|
|
ENDFUNC
|
|
|
|
*-- Functie pentru codificare URL
|
|
FUNCTION UrlEncode
|
|
PARAMETERS tcString
|
|
|
|
LOCAL lcResult, lcChar, lnI
|
|
|
|
lcResult = ""
|
|
|
|
FOR lnI = 1 TO LEN(tcString)
|
|
lcChar = SUBSTR(tcString, lnI, 1)
|
|
|
|
DO CASE
|
|
CASE ISALPHA(lcChar) OR ISDIGIT(lcChar) OR INLIST(lcChar, "-", "_", ".", "~")
|
|
lcResult = lcResult + lcChar
|
|
OTHERWISE
|
|
lcResult = lcResult + "%" + RIGHT("0" + TRANSFORM(ASC(lcChar), "@0"), 2)
|
|
ENDCASE
|
|
ENDFOR
|
|
|
|
RETURN lcResult
|
|
|
|
ENDFUNC
|
|
|
|
*-- Scriptul cu paginare completa pentru preluarea tuturor produselor
|
|
*-- Caracteristici principale:
|
|
*-- - Paginare automata pentru toate produsele (100 per pagina)
|
|
*-- - Pauze intre cereri pentru respectarea rate limiting
|
|
*-- - Creare fisier CSV cu toate produsele
|
|
*-- - Salvare fisier JSON complet cu toate datele
|
|
*-- - Logging separat pentru fiecare pagina in caz de eroare
|
|
*-- - Afisare progres in timpul executiei
|
|
|
|
*-- INSTRUCTIUNI DE UTILIZARE:
|
|
*-- 1. Modifica lcApiKey cu cheia ta API de la GoMag
|
|
*-- 2. Modifica lcApiShop cu URL-ul magazinului tau
|
|
*-- 3. Ruleaza scriptul - va prelua automat toate produsele
|
|
*-- 4. Verifica fisierele generate: CSV si JSON cu toate produsele
|
|
|
|
*-- Script completat cu paginare - verificati fisierele generate |