Changeset c7a211d in Klonkt for src/services/PaidPatreonService.js
- Timestamp:
- 07/21/2026 02:57:49 AM (7 weeks ago)
- Branches:
- main
- Children:
- ec288dc
- Parents:
- 9019a3e
- git-author:
- Robin <roboburr@…> (07/21/2026 02:57:46 AM)
- git-committer:
- Robin <roboburr@…> (07/21/2026 02:57:49 AM)
- File:
-
- 1 edited
-
src/services/PaidPatreonService.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/PaidPatreonService.js
r9019a3e rc7a211d 135 135 } 136 136 137 // Pure: pick the membership for the owner's campaignout of a Patreon137 // Pure: pick the owner's-campaign membership out of a Patreon 138 138 // identity?include=memberships.campaign response (JSON:API). Returns 139 139 // { status, cents } or null. 140 // 141 // Memberships returned via a creator's OWN OAuth client are already scoped to 142 // that creator's campaign(s), so in practice there is one. We still prefer an 143 // exact campaign_id match (belt and suspenders for multi-campaign creators), 144 // but fall back to the sole membership when the configured campaign_id doesn't 145 // match: a wrong/typo'd campaign_id in the admin must not lock out real patrons. 140 146 export function pickCampaignMembership(identity, campaignId) { 141 147 const inc = (identity && identity.included) || []; 148 const members = []; 142 149 for (const it of inc) { 143 150 if (it.type !== 'member') continue; 144 151 const camp = it.relationships && it.relationships.campaign && it.relationships.campaign.data; 145 if (!camp || String(camp.id) !== String(campaignId)) continue;146 152 const a = it.attributes || {}; 147 return { status: a.patron_status || null, cents: a.currently_entitled_amount_cents || 0 }; 153 members.push({ 154 status: a.patron_status || null, 155 cents: a.currently_entitled_amount_cents || 0, 156 campaignId: camp ? String(camp.id) : null, 157 }); 148 158 } 149 return null; 159 if (!members.length) return null; 160 const exact = members.find((m) => m.campaignId && String(m.campaignId) === String(campaignId)); 161 const pick = exact || (members.length === 1 ? members[0] : null); 162 return pick ? { status: pick.status, cents: pick.cents } : null; 150 163 } 151 164 … … 173 186 if (!idRes.ok) return null; 174 187 const identity = await idRes.json(); 175 return pickCampaignMembership(identity, c.campaignId); // token goes out of scope, discarded 188 const membership = pickCampaignMembership(identity, c.campaignId); // token goes out of scope, discarded 189 // Diagnostic (no identity stored, only shapes): why did a real supporter get 190 // rejected? Logs the memberships Patreon returned vs the configured campaign. 191 // Nothing here is persisted; it's a one-line server log for the owner. 192 if (!membership || membership.status !== 'active_patron') { 193 const seen = ((identity && identity.included) || []) 194 .filter((it) => it.type === 'member') 195 .map((it) => { 196 const camp = it.relationships && it.relationships.campaign && it.relationships.campaign.data; 197 const a = it.attributes || {}; 198 return `${camp ? camp.id : '?'}:${a.patron_status || 'null'}:${a.currently_entitled_amount_cents || 0}c`; 199 }); 200 console.warn(`[paid] verifyPatron: config campaign=${c.campaignId} → memberships seen=[${seen.join(', ') || 'none'}] picked=${membership ? membership.status + '/' + membership.cents + 'c' : 'null'}`); 201 } 202 return membership; 176 203 } 177 204
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)