This app processes returns for brands using the Loop Returns system. It's currently only configured to operate for Princess Polly but can easily be modified to accept returns for any brand using Loop Returns.
The app will validate the incoming order return payload data and either reject or accept it. If the payload is accepted, then a Selenium based browser automation process is triggered to begin generating the return label using the data from the webhook payload.
Currently the code ends at the point that the tracking number is parsed out, but can be confirgued to return the label link and tracking number to another endpoint or upload it to S3 or...anything else.
- Streamline returns for e‑commerce brands using Loop Returns.
- Automate label generation and tracking number extraction.
- Persist return data for auditing and further processing.
A webhook listener accepts a payload containing the return information:
{
"brandID": "66b161c9cc1ed9a84f56e9c4",
"flip_order_id": "FLIP-1234567",
"soid": "US12345678",
"returned_product": [
{
"vendor_sku": "139234-1275036"
},
{
"vendor_sku": "139222-1274952"
}
],
"expected_return_label": "FLIP-1234567_return_label",
"auth": "flipshop-returns"
}
NOTE: if only the flip_order_id is able to be sent via webhook, I can retrieve the brandID, soid, and returned_product skus with additional calls to api.flipfit.com.
- Receives and validates incoming JSON payloads, persists payload files, and triggers label generation.
- Drives a browser via Selenium to submit return requests to the Loop Returns portal, capture return label URLs, download return label PDFs, and parse tracking numbers.
- Centralizes environment configuration (URLs, credentials, directories) and logging setup.
- selenium_setup.py: WebDriver & network log utilities.
- pdf_utils.py: PDF download, conversion and text parsing.
- webhooks.py listens on
/hooksfor POST requests with order return details. - Employs at least 5 workers for concurrent requests.
- Ensures JSON structure, required keys (brandID, flip_order_id, soid, returned_product, expected_return_label, auth), correct content‑type, auth token, and a safe flip_order_id pattern.
Writes payload JSON to:
returns/FLIP-<order_id>/return_<order_id>.json
- Spawns generate_label.py with the payload data.
- Navigates to the Loop Returns portal.
- Submits order lookup (soid) and credentials.
- Captures & parses network logs to extract returnable SKUs and product titles.
- Selenium selects items to return on the page by matching the SKUs from the payload and the skus parsed from the logs.
- Verifies all payload SKUs and retunable SKUs are selected before proceeding.
- Proceeds through return flow (refund type, policy agreement).
- Downlaods a return label as a PDF and retrieves the return label URL.
- Converts label PDF to text.
- Extracts the tracking number from the PDF text.
- Possibility: Return label URL and tracking number to Magic in some way.
- Possibility: Upload PDFs to cloud storage (e.g., S3).
├── webhooks.py # Flask listener
├── generate_label.py # Selenium automation script
├── config.py # Environment and logging configuration
├── utils/ # Helper modules
│ ├── selenium_setup.py # WebDriver & performance‑log utilities
│ └── pdf_utils.py # PDF download & parsing
├── returns/ # Persisted webhook payloads & generated PDFs
│ └── FLIP-<order_id>/
│ └── return_<order_id>.json
├── logs/ # Timestamped log files
└── requirements.txt # Python dependencies
Environment Variables (via .env):
-
RETURN_URL (loop returns portal URL)
-
LOGIN_EMAIL (email for loop returns portal login)
-
EXPECTED_AUTH (webhook authentication)
-
Logging: File and console logging at INFO level, with timestamped filenames in logs/.
-
Adding Brands: Parameterize brandID checking and portal URLs to support multiple brands beyond Princess Polly.
-
Future Hooks: Extend generate_label.py to send results (label URL, tracking number) to another HTTP endpoint, message queue, or cloud storage.
-
Can lock down the endpoint to only accept payloads from trusted IPs.
- Flask
- Requests
- Selenium
- Webdriver-manager
- Pdfminer.six
- Python-dotenv
- Ngrok