Hindab, kas Stripe'i makse vaidlustamine tasub end ära, ning kogub ja esitab tõendid.
Kogu oskus — vaikeversiooni hoitakse GitHubis; sinu muudatused jäävad sinu enda klooni.
Hinda esmalt majanduslikku poolt. Kui vaidlustamine on põhjendatud ja heaks kiidetud, koosta tõendipakett ja esita see Stripe'ile. Töötab iga SaaS-i puhul, mis kasutab Stripe'i ja kasutajate andmebaasi, kus on sisselogimis- või kasutuslogid.
Kasuta seda oskust, kui kasutaja:
du_*) ja palub selle „vastustada“ / „ümber lükata“ / „vaidlustada“fraudulent, product_not_received, product_unacceptable või subscription_canceledSTRIPE_SECRET_KEY=sk_live_... # Stripe restricted/secret key with disputes:write scope
DATABASE_URL=postgres://... # READ-ONLY connection to your app's user database (optional but recommended)
TERMS_URL=https://yoursite.com/terms # URL to your published cancellation/refund policy
EVIDENCE_DIR=~/disputes # Where to save the per-customer evidence folders
Andmebaasi turvalisus: kõik päringud on ainult SELECT-päringud. Ära kunagi lase sellel oskusel teha UPDATE/DELETE/INSERT-päringuid.
Kasutaja esitab ühe järgmistest:
- Stripe'i vaidluse ID (du_xxxxx) – eelistatud
- Kliendi e-posti aadress – oskus otsib vaidluse üles
- Makse ID (ch_xxxxx või py_xxxxx)
Vaidlusega nõustumine võib olla õige tulemus. Ära kunagi esita tõendeid ainult seetõttu, et juhtum on olemas.
evidence_details.submission_count > 0. Erista
esmaostud uuendustest ja kitsenda sama põhjuseni, kui valim seda võimaldab. Teata
võitudest, kaotustest, avatud juhtumitest ja valimi suurusest. Ütle välja, kui täpselt
kattuvat pretsedenti pole.curl -s -u "$STRIPE_SECRET_KEY:" \
"https://api.stripe.com/v1/disputes/$DISPUTE_ID" | python3 -m json.tool
Too välja: amount, reason, charge, evidence_details.due_by, evidence_details.submission_count, status.
Kui submission_count > 0, on vaidlus juba vaidlustatud – PEATU ja hoiata kasutajat.
# Charge → tells you the payment method, risk score, billing details, customer ID
curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/charges/$CHARGE_ID"
# Customer → name, email, default payment source
curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/customers/$CUSTOMER_ID"
# All invoices for the customer → look for previously-undisputed payments
curl -s -u "$STRIPE_SECRET_KEY:" \
"https://api.stripe.com/v1/invoices?customer=$CUSTOMER_ID&limit=100"
# Subscription (if recurring)
curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/subscriptions/$SUB_ID"
Varasemad vaidlustamata maksed sama kaardiga on fraudulent-väidete puhul kasulik
lisakinnitus. Loe need alati kokku, kuid ära käsitle neid iseenesest tõendina.
Kohanda need päringud oma skeemiga. Kasulik tõendite kuju:
-- User profile and self-reported cancel reason
SELECT id, email, created_at, plan_tier, stripe_customer_id,
cancel_reason, cancelled_at, delete_reason
FROM users WHERE email ILIKE :email;
-- Login activity (timestamps + country + device)
SELECT created_at, country_code, device
FROM user_activity WHERE user_id = :uid ORDER BY created_at;
-- Things the customer created/used in your product
SELECT name, type, created_at, updated_at
FROM projects WHERE user_id = :uid AND deleted = false ORDER BY created_at;
-- Checkout / payment-related actions (proves intent)
SELECT timestamp, endpoint, payload FROM action_logs
WHERE user_id = :uid
AND endpoint ~* '(subscribe|checkout|stripe|upgrade|pay)'
ORDER BY timestamp DESC;
product_not_received-väidete puhul kontrolli kasutaja enda märgitud cancel_reason-it. Kui
ta tühistas põhjusega „Poor user experience“ või millegagi, mis kasutamist tunnistab, on see
väli väitega otseses vastuolus. Tsiteeri seda sõna-sõnalt, kuid ära tuleta ühe fakti põhjal võiduprotsenti.
FOLDER="$EVIDENCE_DIR/$(echo $CUSTOMER_NAME | tr '[:upper:] ' '[:lower:]-')-$(date +%Y-%m)"
mkdir -p "$FOLDER"
# Invoice PDFs (URLs come from the Stripe invoice objects)
curl -sL "$INVOICE_PDF_URL" -o "$FOLDER/invoice.pdf"
Playwrighti (Node) abil:
node -e "
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
await page.goto(process.env.TERMS_URL, { waitUntil: 'networkidle' });
await page.pdf({ path: process.argv[1], format: 'A4', printBackground: true });
await browser.close();
})();
" "$FOLDER/cancellation_policy.pdf"
Koosta lühike, hõlpsasti ülevaadatav HTML-tegevuslogi ja teisenda see seejärel WeasyPrinti abil PDF-iks:
from weasyprint import HTML
HTML('activity_log.html').write_pdf('activity_log.pdf')
HTML peab sisaldama <meta charset="UTF-8">, et vältida moonutatud tähemärke klientide nimedes/aadressides.
Hõlpsasti ülevaadatav paigutus:
fraudulent-väite)cancel_reason-it vaidluse märgitud põhjuse vastu, kui need on vastuolus.Eelista konkreetseid numbreid omadussõnadele. „29 sisselogimissessiooni, 3 nimega projekti, 29 960 kasutatud krediiti“ on kasulikum kui „kasutas põhjalikult“.
open "$FOLDER"
Näita vastuväite teksti, tõendifaile ja oma võidutõenäosuse hinnangut. Oota kasutaja selgesõnalist heakskiitu.
Failid lähevad aadressile files.stripe.com, MITTE api.stripe.com – erinev host:
curl -s -u "$STRIPE_SECRET_KEY:" \
-F "purpose=dispute_evidence" \
-F "file=@$FOLDER/activity_log.pdf" \
https://files.stripe.com/v1/files
Tagastab {"id": "file_xxx", ...}. Salvesta id – sellele viitad tõendiväljades.
Üks file_id vaidluse kohta. Stripe lükkab tagasi veaga 400 "That file is already attached to something else", kui proovid file_id-d eri vaidlustes taaskasutada (eriti service_documentation puhul). Kui vaidlustad sama kliendi N vaidlust, laadi iga ühise PDF-i üles N koopiana – sama sisu, iga kord uus file_id.
submit=true on lõplik)curl -s -u "$STRIPE_SECRET_KEY:" \
-X POST "https://api.stripe.com/v1/disputes/$DISPUTE_ID" \
-d "evidence[uncategorized_text]=$REBUTTAL_TEXT" \
-d "evidence[uncategorized_file]=$ACTIVITY_LOG_FILE_ID" \
-d "evidence[receipt]=$INVOICE_FILE_ID" \
-d "evidence[cancellation_policy]=$TERMS_FILE_ID" \
-d "evidence[cancellation_policy_disclosure]=$CANCEL_DISCLOSURE_TEXT" \
-d "evidence[refund_policy]=$TERMS_FILE_ID" \
-d "evidence[refund_policy_disclosure]=$REFUND_DISCLOSURE_TEXT" \
-d "evidence[cancellation_rebuttal]=$CANCEL_REBUTTAL_TEXT" \
-d "evidence[access_activity_log]=$ACCESS_LOG_SUMMARY" \
-d "evidence[service_date]=$SERVICE_START_DATE" \
-d "evidence[product_description]=$PRODUCT_DESCRIPTION" \
-d "evidence[customer_email_address]=$CUSTOMER_EMAIL" \
-d "evidence[customer_name]=$CUSTOMER_NAME" \
-d "evidence[customer_purchase_ip]=$PURCHASE_IP" \
-d "evidence[billing_address]=$BILLING_ADDRESS" \
-d "submit=true" \
"https://api.stripe.com/v1/disputes/$DISPUTE_ID"
Kontrolli vastust:
- status peaks olema under_review
- evidence_details.has_evidence peaks olema true
- evidence_details.submission_count peaks olema 1
fraudulentEesmärk: tõesta, et ostu tegi kaardiomanik.
- Varasemad vaidlustamata maksed sama kaardiga (tugevaim)
- OAuth-sisselogimine (Google/Apple) = isikutuvastusega registreerumine
- Järjepidev IP / riik / seade eri sessioonides
- Mitu ostukorvi katset enne ostu = päris inimene, kes kaalub
- Stripe'i enda riskihinnang oli normal
- Tellimus on endiselt aktiivne ega ole tühistatud
product_not_receivedEesmärk: tõesta kättetoimetamist + kasutamist. - Sisselogimiste logi - Tootes loodud elemendid / tehtud toimingud - Kliendi enda märgitud tühistamise põhjus, kui ta tühistas – tsiteeritud sõna-sõnalt vaidlusväite vastu - Kviitung ja tervituskiri
product_unacceptableEesmärk: näita, et toode vastas oma kirjeldusele ja klient kasutas seda.
- Sama mis product_not_received puhul PLUSS sinu kasutustingimuste sõnastus kvaliteedi / tagasimaksepoliitika kohta
- Too esile, et klient ei avanud kunagi tugipiletit
subscription_canceledEesmärk: tõesta, et klient ei tühistanud kunagi (või tühistas pärast uuendamist).
- Tellimuse objekt, mis näitab uuendamise kuupäeval cancel_at_period_end=false
- Kogu sisselogimis-/kasutustegevus pärast uuendamise kuupäeva
- Tingimuste sõnastus, mille kohaselt aastatellimuste uuendamine nõuab selgesõnalist tühistamist
uncategorized_text[Kliendi nimi] lõi [Toote nimi] konto [kuupäev] meetodil [autentimismeetod] ja tellis paketi [pakett] ($[summa]/[intervall]) sama [kaardibränd]-kaardiga. Esimest [N] makset ei vaidlustatud kunagi. Klient kasutas teenust aktiivselt: [N] sisselogimissessiooni riigist [riik] seadmes [seade], [N] loodud elementi ([loend]) ja [N] kasutatud [ühikut]. Vaidlustatud makse on [uuendus-/esialgne] makse kuupäeval [kuupäev]. Tellimus oli [staatus] ja on endiselt [aktiivne/tühistatud]. Klient ei võtnud kunagi tühistamiseks ega tagasimakse taotlemiseks ühendust klienditoega. Meie tühistamis- ja tagasimaksepoliitika on avaldatud aadressil [TERMS_URL]. Tegu ei ole pettusliku tehinguga – see on õiguspärane ost kaardiomanikult, kes [tegi/on teinud] sellel kontol [N] muud vaidlustamata makset.
cancellation_policy_disclosureMeie tühistamispoliitika on avaldatud aadressil [TERMS_URL]. Tellijad võivad igal ajal tühistada ja säilitavad juurdepääsu arveldusperioodi lõpuni. See klient ei tühistanud kunagi.
refund_policy_disclosureMeie tagasimaksepoliitika on avaldatud aadressil [TERMS_URL]. Pakume [N]-päevast raha tagasi garantiid. Klient ei taotlenud tagasimakset selle aja jooksul ega ka mitte kunagi hiljem.
files.stripe.com, MITTE api.stripe.comsubmit=true on lõplikevidence_details.due_by (unixi ajatempel). Pärast seda ei saa enam esitadaKlient registreerub, kasutab toodet põgusalt, tühistab mõne tunni jooksul, märkides rakendusesiseses tühistamisvormis põhjuseks „Poor user experience“, ja esitab paar päeva hiljem tagasinõude väitega „toodet ei saadud kätte“.
Tühistamisvormi põhjus on tagasinõude väitega otseses vastuolus. Tsiteeri seda vastuväites sõna-sõnalt, rakendades samal ajal siiski tasude ja varasemate tulemuste otsustusväravat.
Kontrolli ALATI ESMALT users.cancel_reason-it (või oma vastet), kui vaidluse põhjus on product_not_received või product_unacceptable.