Skip to content

feat: route refunds through Session's own two links, and branch the non-originating screen - #2182

Draft
Bilb wants to merge 4 commits into
devfrom
qa/refund-session-links
Draft

feat: route refunds through Session's own two links, and branch the non-originating screen#2182
Bilb wants to merge 4 commits into
devfrom
qa/refund-session-links

Conversation

@Bilb

@Bilb Bilb commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #2178 (now merged). Three connected corrections to the refund CTA.

The links

The refund action used the provider's refund_platform_url / refund_support_url. It now uses two Session-owned short links, chosen on the quick-refund window alone:

  • window open → ProUrls.QUICK_REFUND (getsession.org/android-refund)
  • window closed → ProUrls.SUPPORT (getsession.org/pro-support)

Being ours, the destinations can be repointed without a client release, and all three clients now agree on them. This matters because the old support value for Google Play redirects to the Play store — so a screen whose copy promises the request is handled by Session Support was sending the user to the one place a >48h request cannot be actioned.

The non-originating screen now branches

It rendered one screen for both the <48h and >48h states: the former's button under the latter's link. The window was already resolved at the dispatch site and simply was not passed on. This threads it through and branches the button, the body copy and the link together. Past the window the body is proPlanPlatformRefundLong, which is the same sentence iOS already shows for this state.

The CTA names the store, not the platform

getPlatformDisplayName() exists for exactly this and was already used by the cancel, choose-plan and no-billing screens — only the two refund screens still passed the raw platform name, rendering "Open Google Website" where the designs say "Open Google Play Store Website". iOS and Desktop both apply the same rule.

Verification

Built as a QA APK and run against an emulator: all four @android pro_refund_screens specs pass, including the non-originating window-closed case that previously had no assertable URL. iOS and Desktop pass the equivalent assertions against their own builds.

🤖 Generated with Claude Code

Bilb and others added 4 commits August 24, 2026 15:24
…on-originating screen

Three connected corrections to the refund CTA.

**The links.** The refund action used the provider's `refund_platform_url`/`refund_support_url`. It now
uses two Session-owned short links chosen on the quick-refund window alone: `ProUrls.QUICK_REFUND`
while the store will still take the request, `ProUrls.SUPPORT` once it will not. Being ours, the
destinations can be repointed without a client release, and all three clients now agree on them. The
old support value for Google Play redirected to the Play store, so a screen promising the request was
handled by Session Support sent the user to the one place it cannot be actioned.

**The non-originating screen now branches.** It served both the <48h and >48h states with one
rendering: the former's button under the latter's link. The window was already resolved at the
dispatch site and simply was not passed on, so this threads it through and branches the button, the
body copy and the link together. Past the window the copy is `proPlanPlatformRefundLong`, which is the
same sentence iOS already shows for this state.

**The CTA names the store, not the platform.** `getPlatformDisplayName()` exists for exactly this and
was already used by the cancel, choose-plan and no-billing screens; only the two refund screens still
passed the raw platform name, rendering "Open Google Website" where the designs say "Open Google Play
Store Website". iOS and Desktop both apply the same rule.

Verified against a QA build: all four @android pro_refund_screens specs pass, and iOS and Desktop pass
the same assertions against their own builds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The quick-refund link redirects into the Play store, so it is only a usable route for a plan bought
there. An App Store plan reports its refund window open for the whole subscription, so gating on the
window alone sent an Apple subscriber to the wrong store's refund flow — reachable on the
non-originating screen, which is the one that shows plans bought elsewhere.

Gated on the provider slug as well as the window. iOS and Desktop take the same gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…g it

libsession owns the per-provider url table and says so in `pro_backend.h`: "libsession owns them as the
single source of truth rather than each client duplicating them". The store refund route now reads
`providerUrls(slug).refundSupportUrl` through the wrapper this app already used for the other four
provider urls, and the copy added earlier is gone.

Worth knowing for anyone reading the call site: the slot's NAME is misleading. For Google Play,
libsession's `refund_support_url` is the Session short link that redirects into the Play store — so the
value the window-OPEN route needs sits under libsession's "support" name, while the window-CLOSED route
uses `ProUrls.SUPPORT`, which mirrors `url_pro_support`. Those two are different destinations with
confusingly similar names.

`ProUrls.SUPPORT` stays a copy: the `url_pro_*` registry is a C struct of `const char*` with no Kotlin
accessor, which is what that file already documents.

Verified against a QA build: all four @android pro_refund_screens specs pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Added in the previous commit to stop an Apple plan reaching the Play-store link — a case that cannot
happen. `providerData` is the ORIGINATING provider's table, so an Apple plan already yields Apple's own
refund page there. The check replaced that correct page with Session's support form, which contradicts
the design's "Apple processes all refund requests, we do not get a say".

The window alone is the right condition; the per-provider behaviour falls out of libsession's table
rather than a client check.

Verified against a QA build: all four @android pro_refund_screens specs pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Bilb
Bilb marked this pull request as draft August 24, 2026 07:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant