Neu Aliexpress und Amazon Rechnungen runterladen - freies Tampermonkey Script

musaza

Aktives Mitglied
13. Januar 2018
83
14
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();
})();
 
Ähnliche Themen
Titel Forum Antworten Datum
Neu Shopify Kategorie /(Produkt Taxonomie) und kategoriespezifische Attribute in JTL Wawi pflegen Shopify-Connector 0
Neu JTL-ShippingLabels und DHL JTL-ShippingLabels - Fehler und Bugs 2
Neu Ihr Token bei JTL-eazyAuction ist ausgelaufen - Verletzung von Nebenpflichten (Treue- und Informationspflicht) durch JTL Einrichtung und Installation von JTL-eazyAuction 1
Neu Zahlungsarten und Bulletpoints in Kaufpreisnähe Plugins für JTL-Shop 3
Neu JTL Wawi und Etikettendrucker Brother QL-820NWBc Installation von JTL-Wawi 2
Neu Kunden mit Kundenkonto bestellen als Gast und Aufträge sind dann nicht im Konto sichtbar Allgemeine Fragen zu JTL-Shop 4
Neu Zahlungsmodul und das VoP ab dem 5.10. Arbeitsabläufe in JTL-Wawi 0
X-Rechnung hat Validierungsfehler und wird abgelehnt JTL-Wawi 1.10 0
Neu Staging und Konten bitte eine Erklärung. Installation von JTL-Wawi 0
Neu tWarenkorbpos und tBestellung älter als 10 Jahre löschen JTL-Shop - Fehler und Bugs 0
Neu Rollende Kommissionierung – Pflicht zur Bestätigung von Lagerplatz und Pickmenge Arbeitsabläufe in JTL-WMS / JTL-Packtisch+ 0
Neu Discount Regeln in JTL hinterlegen und zu Woocommerce synchronisieren WooCommerce-Connector 0
Eigene Felder im Block "Firmen- und E-Mail Einstellungen verwalten" JTL-Wawi 1.10 3
neue Zahlungsart "Barter", trotzdem erscheint "Zahlung per Überweisung und QR-Code" JTL-Wawi 1.10 1
Neu Nach Update auf PayPal 2.1.0 doppelte Zahlungsarten und Ratepay Plugin erforderlich Plugins für JTL-Shop 0
Neu Version 2.1.0 von SpamProtector und SpamProtector Lite Plugins für JTL-Shop 10
Neu Automatisch generierte Eigene Felder PAYPAL_FUNDING_SOURCE und AmazonPay-Referenz User helfen Usern - Fragen zu JTL-Wawi 0
Neu Paypal Zahlung erfolgreich, Auftrag mit Status Neu im Shop und fehlt in WAWI JTL-Shop - Fehler und Bugs 4
Titel auf verschiedenen Plattformen und Artikeltitel auf gedruckter Rechnung oder Lieferschein. JTL-Wawi 1.10 8
Neu Suchen Wawi- und Shopspezialist (m/w/d) für Pflege von Bestandssystem inhouse in PLZ 24* Dienstleistung, Jobs und Ähnliches 0
Neu Import aus Billbee und Schnittstelle zu Strato Smartwebshop Schnittstellen Import / Export 4
Worker Arbeitet mal und mal nicht. JTL-Wawi 1.10 1
Neu Sortieren und Ausgeben / Speichern / Drucken der externen Belege seit 1.10. Amazon-Anbindung - Fehler und Bugs 0
Neu Lagerplätze und Bestände lassen sich teils nicht im WMS Lager importieren? Evtl. BUG --> JTL 1.10.10.4? User helfen Usern - Fragen zu JTL-Wawi 1
Neu 2x Banner im Backend anlegen, einbinden und anzeigen User helfen Usern - Fragen zu JTL-Wawi 7
Neu Google Shopping: Verständnisfrage zu Wertname und Werttyp Technische Fragen zu Plugins und Templates 0
Keine Verbindung zwischen Kasse und Server möglich JTL-Wawi 1.10 2
Neu Warenein- und -ausgang JTL Packtisch von Kundenwaren Arbeitsabläufe in JTL-Wawi 0
Kauf und Leasingoptinen in einem Artikel geht das? JTL-Wawi 1.9 0
Neu Error 500 nach Update und Auswahl vom Theme AVIA Installation / Updates von JTL-Shop 4
Neu JTL Wawi braucht viel RAM und CPU wenn der Prozess lange läuft, ohne dass gearbeitet wird JTL-Wawi - Fehler und Bugs 3
Neu Rechnungs- und Auftragsübersicht Rabatt anzeigen JTL-Wawi - Ideen, Lob und Kritik 2
Neu WMS Lager und Standardlager Fragen rund um LS-POS 0
Neu Workflow Versandart prüfen und im Auftrag setzen - speziell für Stücklistenartikel User helfen Usern - Fragen zu JTL-Wawi 0
Neu Felder Company2 und Address2 fehlen in Shipmentaddress-Antwort Schnittstellen Import / Export 0
Neu Trinkgeld Im Z-Bon und Kassenbuch falsch berechnet JTL-POS - Fehler und Bugs 2
Neu Rechnungsexport und Gutschriftenexport in der Ameise erzeugt doppelte Rechnungen / Gutschriften JTL-Ameise - Fehler und Bugs 1
Zahlungsarten, Skontotext und berechnung einfügen JTL-Wawi 1.9 4
Neu Nova Template und Google Analytics, Ads Technische Fragen zu Plugins und Templates 3
WAWI Autostart und Benutzer anmelden JTL-Wawi 1.10 15
Neu Verschiedene Startseiten für angemeldete und nicht angemeldete Benutzer möglich? Allgemeine Fragen zu JTL-Shop 6
Neu Preise in CNY, Zahlung in USD und durschschn. EK in EUR Arbeitsabläufe in JTL-Wawi 0
Neu Rechnung- UND ALLE Lieferadressen in Kundenübersicht sichtbar JTL-Wawi - Ideen, Lob und Kritik 11
Neu Wawi und VCS Rechnung unterschiedliche Steuersätze Amazon-Anbindung - Fehler und Bugs 0
Neu Ich habe eben einen neuen Shop erstellt und alle Artikel übertragen, aber leider werden mir bei den Versandarten die Versandklassen nicht angezeigt User helfen Usern - Fragen zu JTL-Wawi 1
In Diskussion Workflow zur Zählen von Retouren und Bestellungen von einem Kunden JTL-Workflows - Ideen, Lob und Kritik 1
In Diskussion Ich habe eine neue TSE-Karte gekauft (Swissbit TSE). Wo finde ich den PIN und PUK? Einrichtung / Updates von JTL-POS 3
Neu Frage zur eBay-Artikelbeschreibung bei Variationskombinationen (Kindartikel mit eigenem Text und Bildern) eBay-Anbindung - Fehler und Bugs 5
Neu ecomdata offline? Shop und JTL Wawi nicht erreichbar User helfen Usern - Fragen zu JTL-Wawi 16
Neu alte Aufträge ausliefern ohne Label drucken und Abgleich mit eBay User helfen Usern - Fragen zu JTL-Wawi 2

Ähnliche Themen