Neu Aliexpress und Amazon Rechnungen runterladen - freies Tampermonkey Script

musaza

Aktives Mitglied
13. Januar 2018
83
15
Ich wollte mal ein kleines ChatGPT-Script mit euch teilen, das ich mir „herausgepromptet“ habe 🙂 War mir blöd, monatlich einer Firma, die diese Dateien automatisiert runterladen könnte, schlappe 30 Euro im Monat zu bezahlen...


Hintergrund​


  • Ich habe kein Amazon Business Konto und konnte deshalb die Kaufrechnungen nicht gebündelt herunterladen – nur einzeln.
  • Bei AliExpress gibt es den Button „Rechnung“ seit April 2025 nicht mehr. Davor konnte man Rechnungen mit MwSt. herunterladen, danach nur noch Eigenbelege (Netto), die man dem Finanzamt vorlegen muss.
    → Mit den hier vorgestellten Scripts bekomme ich jetzt wieder alle Rechnungen, bzw. sogar eine Ordner-Summary als PDF.

Installation​


  • Browser: Firefox
  • Einstellung: PDFs sollen heruntergeladen und nicht im Browser geöffnet werden
  • Add-on: Tampermonkey installieren
  • Dann: im Tampermonkey-Addon auf „Neues Userscript erstellen“ klicken und die Scripts jeweils einfügen.

Bedienung​


  • AliExpress:
    Rechts unten erscheint ein Button „Rechnungen (sichtbar) laden“.
    Alle sichtbaren Rechnungen werden heruntergeladen. Wenn ihr mehr wollt, einfach weiterscrollen, bis alle Bestellungen geladen sind.
  • Amazon:
    Alle Rechnungen der jeweils sichtbaren Seite werden heruntergeladen.
    Für weitere Seiten müsst ihr einfach weiterblättern.
    Wichtig: Die URL muss https://www.amazon.de/your-orders/orders lauten – dann erscheint links unten der Button „Alle Rechnungs-PDF laden“.

Hinweis​


Ich teile hier nur die Idee und wie es bei mir funktioniert hat.


  • Gewährleistung oder Haftung übernehme ich nicht – jeder ist für seine Daten selbst verantwortlich.
  • Die Scripts generieren nichts Eigenes, sie laden nur herunter, was die Plattformen ohnehin bereitstellen.
  • Support kann ich leider nicht bieten – aber: wenn ihr die Scripts erweitert oder verbessert, teilt es gerne hier! Vielleicht baut ja jemand auch etwas für eBay 😉 oder alles andere in gewissen erleichterungen auf diversen Plattformen




Hier der Aliexpress Script:

// ==UserScript==
// @name AliExpress: Rechnungen aller sichtbaren Bestellungen laden
// @namespace ae-invoice-bulk
// @version 1.0
// @description Lädt die Rechnungen (PDF) für alle sichtbaren Bestellungen mit passendem Dateinamen herunter.
// @author you
// @match https://www.aliexpress.com/p/order/index.html*
// @match https://www.aliexpress.com/p/order/index.htm*
// @ICON https://www.aliexpress.com/favicon.ico
// @run-at document-idle
// @grant GM_xmlhttpRequest
// @grant GM_download
// @connect trade.aliexpress.com
// ==/UserScript==

(function () {
'use strict';

/*** UI-Button einfügen ***/
function addButton() {
const btn = document.createElement('button');
btn.textContent = 'Rechnungen (sichtbar) laden';
btn.style.position = 'fixed';
btn.style.right = '16px';
btn.style.bottom = '16px';
btn.style.zIndex = '999999';
btn.style.padding = '10px 14px';
btn.style.borderRadius = '8px';
btn.style.border = 'none';
btn.style.background = '#1677ff';
btn.style.color = '#fff';
btn.style.fontWeight = '600';
btn.style.cursor = 'pointer';
btn.title = 'Lädt die Rechnungen für alle aktuell sichtbaren Bestellungen';

btn.addEventListener('click', run);
document.body.appendChild(btn);
}

/*** Hilfen ***/
const MONTHS_DE = {
jan: 1, januar: 1,
feb: 2, februar: 2,
mär: 3, maerz: 3, märz: 3, mar: 3, march: 3,
apr: 4, april: 4,
mai: 5,
jun: 6, juni: 6,
jul: 7, juli: 7,
aug: 8, august: 8,
sep: 9, sept: 9, september: 9,
okt: 10, oktober: 10,
nov: 11, november: 11,
dez: 12, dezember: 12
};

function pad2(n) { return String(n).padStart(2, '0'); }

function parseGermanDateToYYYYMMDD(txt) {
// erwartet z. B. "24. Aug 2025"
const m = txt.trim().match(/(\d{1,2})\.\s*([A-Za-zäöüÄÖÜ]+)\s*(\d{4})/);
if (!m) return null;
const d = parseInt(m[1], 10);
const monKey = m[2].toLowerCase()
.replace('ä', 'ä') // bleibt
.replace('ö', 'o')
.replace('ü', 'u')
.replace('ß', 'ss')
.replace('mär', 'mär'); // gängigste Abk.
const mon = MONTHS_DE[monKey] || MONTHS_DE[monKey.slice(0,3)];
const y = parseInt(m[3], 10);
if (!mon) return null;
return `${y}${pad2(mon)}${pad2(d)}`;
}

function extractOrderInfo(orderEl) {
// Bestellnummer
const orderIdMatch = orderEl.textContent.match(/Bestellnummer:\s*(\d{6,})/);
const orderId = orderIdMatch ? orderIdMatch[1] : null;

// Kaufdatum
const dateDiv = Array.from(orderEl.querySelectorAll('.order-item-header-right-info div'))
.find(d => /Bestellung aufgegeben am/i.test(d.textContent));
const dateText = dateDiv ? dateDiv.textContent.replace(/.*?:\s*/, '') : '';
const yyyymmdd = parseGermanDateToYYYYMMDD(dateText);

// Gesamtbetrag
let totalText = '';
const totalEl = orderEl.querySelector('[data-pl="order_item_content_price_total"]');
if (totalEl) {
// enthält „Gesamt: 21,39 €“
totalText = totalEl.innerText || totalEl.textContent || '';
} else {
// Fallback: suche irgendein „Gesamt:“ mit € in der Nähe
const hint = Array.from(orderEl.querySelectorAll('span,div'))
.find(n => /Gesamt/i.test(n.textContent) && /€/.test(n.textContent));
totalText = hint ? hint.textContent : '';
}
const amountMatch = totalText.replace(/\s+/g, ' ').match(/([\d.,]+)\s*€/);
let amountStr = amountMatch ? amountMatch[1] : '';
// Normalisieren -> Zahl und danach wieder nach DE-Format
if (amountStr) {
const val = parseFloat(amountStr.replace(/\./g, '').replace(',', '.'));
if (!isNaN(val)) amountStr = val.toFixed(2).replace('.', ',');
}

return { orderId, yyyymmdd, amountStr };
}

function fetchInvoiceId(orderId) {
const url = `https://trade.aliexpress.com/ajax/invoice/queryInvoiceIdAjax.htm?orderIds=${orderId}`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url,
onload: (res) => {
try {
const data = JSON.parse(res.responseText);
// Antwort ist i. d. R. ["908704618996"] oder []
resolve(Array.isArray(data) && data[0] ? String(data[0]) : null);
} catch (e) {
reject(e);
}
},
onerror: reject,
ontimeout: reject
});
});
}

function downloadInvoicePdf(invoiceId, orderId, filename) {
const url = `https://trade.aliexpress.com/ajax/invoice/invoiceExportAjax.htm?invoiceId=${encodeURIComponent(invoiceId)}&orderId=${encodeURIComponent(orderId)}`;
// Wir holen die PDF als Blob und übergeben sie dann an GM_download, damit Dateiname sicher gesetzt wird.
GM_xmlhttpRequest({
method: 'GET',
url,
responseType: 'blob',
onload: (res) => {
try {
const blob = res.response;
const objectUrl = URL.createObjectURL(blob);
GM_download({
url: objectUrl,
name: filename,
saveAs: false,
ontimeout: () => console.warn('Download timeout:', filename),
onerror: (e) => console.warn('Download error:', filename, e),
onload: () => {
// Object URL freigeben, wenn der Download gestartet wurde
setTimeout(() => URL.revokeObjectURL(objectUrl), 10000);
}
});
} catch (e) {
console.error('PDF-Verarbeitung fehlgeschlagen', e);
}
},
onerror: (e) => console.error('PDF-Request fehlgeschlagen', e),
ontimeout: (e) => console.error('PDF-Request Timeout', e)
});
}

async function run() {
const items = Array.from(document.querySelectorAll('.order-item'));
if (!items.length) {
alert('Keine sichtbaren Bestellungen gefunden.');
return;
}

let ok = 0, skipped = 0;
for (const el of items) {
const { orderId, yyyymmdd, amountStr } = extractOrderInfo(el);

if (!orderId) { console.warn('Order ohne Bestellnummer übersprungen.'); skipped++; continue; }
const datePart = yyyymmdd || '00000000';
const amountPart = amountStr || '0,00';

try {
const invoiceId = await fetchInvoiceId(orderId);
if (!invoiceId) {
console.warn(`Keine invoiceId für Order ${orderId} (evtl. keine Rechnung vorhanden).`);
skipped++;
continue;
}
const filename = `${datePart}_${orderId}__EUR_${amountPart}.pdf`;
console. log('Lade Rechnung:', filename, ' invoiceId:', invoiceId);
downloadInvoicePdf(invoiceId, orderId, filename);
ok++;
} catch (e) {
console.error('Fehler bei Order', orderId, e);
skipped++;
}
}
setTimeout(() => {
alert(`Fertig: ${ok} Rechnung(en) angestoßen. Übersprungen: ${skipped}.`);
}, 100);
}

/*** Start ***/
addButton();
})();
















und hier der Amazon Script:


// ==UserScript==
// @name Amazon DE – Alle Rechnungs-PDFs laden
// @namespace ama-pdf-bulk
// @version 1.0
// @description Lädt auf /your-orders/orders alle Rechnungs-/Korrektur-PDFs je Bestellung herunter – inkl. mehrfach vorhandener PDFs – und benennt sie nach Wunschschema.
// @author you
// @match https://www.amazon.de/your-orders/orders*
// @grant GM_download
// @grant GM_xmlhttpRequest
// @connect www.amazon.de
// ==/UserScript==

(function () {
'use strict';

// ---------- kleine Hilfen ----------
const $ = (sel, el = document) => el.querySelector(sel);
const $$ = (sel, el = document) => Array.from(el.querySelectorAll(sel));

const MONTHS_DE = {
'januar': 1, 'februar': 2, 'märz': 3, 'maerz': 3, 'april': 4,
'mai': 5, 'juni': 6, 'juli': 7, 'august': 8, 'september': 9,
'oktober': 10, 'november': 11, 'dezember': 12
};

const sanitizeForFilename = (s) =>
s.trim()
.replace(/\s+/g, '-') // Leerzeichen → Bindestrich
.replace(/[\u2013\u2014]/g, '-') // Gedankenstriche normalisieren
.replace(/[^A-Za-z0-9ÄÖÜäöüß\-]/g, ''); // ungültige Zeichen raus, Umlaute ok

function parseGermanOrderDateToYYYYMMDD(s) {
// Beispiele: "24. August 2025", "7. August 2025"
if (!s) return '00000000';
const m = s.trim()
.toLowerCase()
.replace(/\./g, '')
.replace('märz', 'maerz')
.match(/^(\d{1,2})\s+([a-zäöü]+)\s+(\d{4})$/i);
if (!m) return '00000000';
const dd = String(m[1]).padStart(2, '0');
const mon = MONTHS_DE[m[2]] || 0;
const mm = String(mon).padStart(2, '0');
const yyyy = m[3];
return `${yyyy}${mm}${dd}`;
}

function extractTextAfterLabel(container, labelText) {
// Sucht im "order-header" das Listenelement, dessen Mini-Label gleich labelText ist,
// und gibt den Wert im nachfolgenden .a-size-base zurück.
const items = $$('.order-header__header-list-item', container);
for (const li of items) {
const label = $('.a-size-mini .a-color-secondary', li);
const value = $('.a-size-base', li);
if (label && value && label.textContent.trim().toLowerCase() === labelText.toLowerCase()) {
return value.textContent.trim();
}
}
return '';
}

function absolute(url) {
try { return new URL(url, location.origin).href; } catch { return url; }
}

function gmGet(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url,
headers: { 'Accept': 'text/html,application/xhtml+xml' },
// Cookies mitnehmen (wichtig, weil die Popover-URL auth-gebunden ist)
anonymous: false,
// manche TM-Versionen nutzen withCredentials:
// @ts-ignore
withCredentials: true,
onload: (res) => resolve(res.responseText),
onerror: (e) => reject(e)
});
});
}

async function downloadAllForOrder(orderCard) {
try {
// Header-Infos ermitteln
const header = $('.order-header', orderCard) || orderCard;
const orderDateHuman = extractTextAfterLabel(header, 'Bestellung aufgegeben');
const orderDate = parseGermanOrderDateToYYYYMMDD(orderDateHuman);
const sumRaw = extractTextAfterLabel(header, 'Summe')
.replace(/[€\s\u00A0]/g, '') // Euro-Symbol & NBSP entfernen
.replace(/EUR/i, '')
.trim();
const sumForFile = sumRaw.replace(/[^\d,]/g, ''); // "58,42" behalten
const orderId = $('.yohtmlc-order-id span[dir="ltr"]', header)?.textContent.trim() || 'UNKNOWN';

// Link zum Popover (enthält alle Rechnungs-/Korrektur-Links als HTML)
const invoiceTrigger = $$('a.a-link-normal', header)
.find(a => /\/invoice\/invoice\.html/i.test(a.getAttribute('href') || '') ||
/\/shared-cs\/ajax\/invoice\/invoice\.html/i.test(a.getAttribute('href') || '') ||
a.textContent.trim().toLowerCase().startsWith('rechnung'));

if (!invoiceTrigger) {
console.warn('Keine Rechnungslinks für Bestellung gefunden:', orderId);
return;
}

// Popover-HTML abrufen
const popoverUrl = absolute(invoiceTrigger.getAttribute('href'));
const html = await gmGet(popoverUrl);

// HTML parsen und alle PDF-Links herausfischen
const dp = new DOMParser();
const doc = dp.parseFromString(html, 'text/html');

// robuste Suche: alle <a>, deren href .pdf enthält
const links = $$('a', doc).filter(a => {
const href = a.getAttribute('href') || '';
return /\.pdf(\?|$)/i.test(href);
});

if (!links.length) {
console.warn('Kein PDF-Link im Popover gefunden:', orderId, popoverUrl);
return;
}

for (let idx = 0; idx < links.length; idx++) {
const a = links[idx];
const href = absolute(a.getAttribute('href'));
let linkText = a.textContent.trim() || `Rechnung-${idx + 1}`;
// Einheitlich: Leerzeichen -> -, Sonderzeichen raus
linkText = sanitizeForFilename(linkText);

const filename = `${orderDate}_${linkText}_${orderId}__EUR_${sumForFile}.PDF`;

// Download starten
await new Promise((resolve) => {
GM_download({
url: href,
name: filename,
saveAs: false,
ontimeout: resolve,
onerror: resolve,
ontimeout: resolve,
onprogress: () => {},
onload: resolve
});
});

// kleine Pause, um Rate Limits zu vermeiden
await new Promise(r => setTimeout(r, 400));
}
} catch (e) {
console.error('Fehler bei Bestellung:', e);
}
}

// ---------- Button in die Seite einfügen ----------
function addUi() {
if ($('#tm-load-all-invoices')) return;
const btn = document.createElement('button');
btn.id = 'tm-load-all-invoices';
btn.textContent = 'Alle Rechnungs-PDFs laden';
Object.assign(btn.style, {
position: 'fixed',
bottom: '16px',
left: '16px',
zIndex: 99999,
background: '#ffd814',
color: '#111',
border: '1px solid #888',
borderRadius: '8px',
padding: '10px 14px',
cursor: 'pointer',
fontSize: '14px',
fontWeight: 'bold',
boxShadow: '0 2px 6px rgba(0,0,0,.2)'
});
btn.addEventListener('click', async () => {
btn.disabled = true;
btn.textContent = 'Lade PDFs…';
const cards = $$('.order-card');
for (const card of cards) {
await downloadAllForOrder(card);
}
btn.textContent = 'Fertig ✓';
setTimeout(() => { btn.disabled = false; btn.textContent = 'Alle Rechnungs-PDFs laden'; }, 3000);
});
document.body.appendChild(btn);
}

// ---------- Start ----------
const obs = new MutationObserver(() => addUi());
obs.observe(document.documentElement, { childList: true, subtree: true });
addUi();
})();
 
  • Gefällt mir
Reaktionen: sah
Ähnliche Themen
Titel Forum Antworten Datum
Neu Workflow mit UND / ODER - Bedingung erstellen JTL-Workflows - Ideen, Lob und Kritik 7
Ameise-Export: Umsatzsteuer stimmt nicht mit Differenz aus Netto und Brutto überein (insbesondere bei mehreren Steuersätzen) JTL-Wawi 1.11 0
Neu Amazon DIVID- und Lucid-Nummer User helfen Usern 0
Neu Bestände in-house und beim Lieferanten + Proforma-Rechnungen, wie? Arbeitsabläufe in JTL-Wawi 3
Neu Vater und Kinderartikel User helfen Usern - Fragen zu JTL-Wawi 11
Neu product_visibility bei JTL-Wawi und Shopware 6 Shopware-Connector 1
Probleme mit Worker und JTL-App JTL-Wawi 2.0 3
Neu Shopware 5 connector und WawI 1.11.06 bis 1.11.8 Shopware-Connector 1
Bilder unter Versand- und Zahlungsart unterschiedlich groß Einrichtung JTL-Shop5 0
Neu Widerrufsbutton: Jeder, der den Button betätigt, kann das Widerrufsformular ausfüllen und absenden - auch ohne Bestellung? Allgemeine Fragen zu JTL-Shop 64
Neu Problem mit Dantezeile und fehlerhafte Angebotsgültigkeit. Druck-/ E-Mail-/ Exportvorlagen in JTL-Wawi 2
Neu JTL Pro Edition – Lizenzumstellungen und Abrechnungsfragen Smalltalk 42
Neu JTL Shop 5 und Klarna Plugins für JTL-Shop 0
Inaktive Verkaufskanäle lassen sich nicht löschen – erscheinen nach Löschen und Speichern erneut JTL-Wawi 1.11 0
Neu DP Internetmarke 2.0 vs. 1.0 – Vorteile, Stabilität und Umstieg? JTL-ShippingLabels - Ideen, Lob und Kritik 0
Neu Neuentwicklung - Helpdesk für JTL Wawi - Eure Ideen und Wünsche? User helfen Usern - Fragen zu JTL-Wawi 4
Neu POS im Kundencenter buchen, aber wie und wo? Allgemeine Fragen zu JTL-POS 2
Neu Probleme mit Ninepoint und TikTok Shop Schnittstellen Import / Export 6
Neu 5.6.1 Bug bei Versandarten mit Kalkulation durch Artikelmenge und Staffelpreisen JTL-Shop - Fehler und Bugs 2
Neu Ältere Young Fashion Kollektion: Mit Kaufland, TikTok & Influencer schnell hochziehen und abverkaufen? Dienstleistung, Jobs und Ähnliches 1
Neu JTL samt Kaufland & TikTok kurz hochschießen und dann schließen/abverkaufen? Business Jungle 7
Plan und Produce - Produktionsbuchung JTL-Wawi 2.0 1
Neu Best Practices für den Export und die Automatisierung von täglichen Berichten in JTL‑WaWi User helfen Usern - Fragen zu JTL-Wawi 2
Plötzliche Preissenkungen auf ebay und amazon JTL-Wawi 1.10 2
Neu Bankdaten in Wawi V1.11.7 werden vererbt und nicht aktualisiert User helfen Usern - Fragen zu JTL-Wawi 2
Kunde kauft über Amazon und dann über Ebay - Mailversand JTL-Wawi 1.10 10
Neu Workflow automatisch bei Warenausgang für Bestand und Puffer JTL-Wawi - Ideen, Lob und Kritik 12
Seit umzug auf neuen Server und vorherigem update auf 2.0, startet worker nicht... JTL-Wawi 2.0 4
Neu Alte Produktbilder erscheinen im JTL-Shop trotz Löschung und neuem Upload immer wieder – JTL-Wawi enthält nur neue Bilder JTL-Wawi - Fehler und Bugs 16
Neu Bilder importieren mit "vorhandene Bilder vor dem Import entfernen und neu importieren" > eigenartiges Verhalten JTL-Ameise - Fehler und Bugs 2
Neu Gewährleistungs- und Garantielabel ab 27.09.2026 Betrieb / Pflege von JTL-Shop 1
Neu Pickliste wird auf Packtisch und in Wawi unter Picklisten nicht angezeigt. JTL-WMS / JTL-Packtisch+ - Fehler und Bugs 1
Rechnungsversand per eMail hin und wieder nicht erfolgreich JTL-Wawi 1.9 1
Neu Buchungsdatenservice richtig nutzen und Einrichten User helfen Usern - Fragen zu JTL-Wawi 0
Neu Filter und Sortierung komplett ausschalten Allgemeine Fragen zu JTL-Shop 4
Neu Shop Bestellungen und Abonnements möglich? User helfen Usern - Fragen zu JTL-Wawi 1
Neu Für die Weiterentwicklung und Betreuung unserer bestehenden Systemlandschaft suchen wir einen erfahrenen Freelancer (m/w/d) mit fundierten Kenntnissen JTL-Wawi App 1
Permanente / Laufende Inventur ohne Lagerplatz und ohne WMS mobil JTL-Wawi 1.10 2
Neu welche Sync Benutzer Daten in Shop und WAWI bei neu-Hosting über JTL Allgemeine Fragen zu JTL-Shop 0
Neu Abgleich erstellt neue Artikel aber ohne Bestand und Bestandsführung WooCommerce-Connector 2
Ameisen-Vorlagen Attribute und Eigene Felder lassen sich nicht speichern JTL-Wawi 1.11 2
Neu JTL WMS und WMS APP - UDI Codes Arbeitsabläufe in JTL-WMS / JTL-Packtisch+ 0
Neu Bildsortierung und Personalisierung eBay-Anbindung - Fehler und Bugs 4
welche Sync Benutzer Daten in Shop und WAWI bei neu-Hosting über JTL JTL-Wawi 1.11 0
Neu In welcher Datenbank-Tabelle sind Wertelisten und deren IDS von Eigenen Felder gespeichert? User helfen Usern - Fragen zu JTL-Wawi 8
Neu Kundenkonto mit UID und Bestellung als Gast JTL-Shop - Fehler und Bugs 14
Neu 12.400 Versandumschläge B4 / 6.400 Braun und 6.000 Weiß mit Faltböden / Klappböden Dienstleistung, Jobs und Ähnliches 4
Neu Ständig neue Angebote von JTL und Fallen bei Unaufmerksamkeit Smalltalk 26
Export Zahlungen Amazon marketplace bei Kombi OSS und FBA erfolgt nach JTL2DATEV unvollständig JTL-Wawi 1.9 0
Neu Abfrage Pakete nach Gewicht, Menge und durchschnittliches Gewicht Eigene Übersichten in der JTL-Wawi 0

Ähnliche Themen