Skip to content

Conversation

Doy-lee
Copy link

@Doy-lee Doy-lee commented Aug 27, 2025

This PR goes ontop of #63 only need to review the delta between the two.

--

The commits here are a polish pass over the draft code that was dumped into src/pro.cpp. That file has been renamed to src/pro_backend.cpp. The role of this file now is to interop with the pro backend and adds a bunch of functions to construct the necessary HTTP POST payloads to send off to a Session Pro Backend to do one of the following operations:

  1. Redeem a payment the client has purchased for entitlement to Session Pro. This gets the Session Pro Backend after verifying it successfully, to generate a proof that the client can attach to their messages to enable Pro features.
  2. Authorise a new Ed25519 key pair to be the signatory of their Session Pro Proof that can be used on the protocol
  3. Retrieve the historical list of payments associated with a Session account
  4. Get the current list of global proofs which is maintained by the Session Pro backend that clients will reject proofs from until the designated expiry time.

Additionally for each payment provider, libsession exposes the various platform specific URLs to centralise those strings into the same repository, as per:

const session_pro_payment_provider_metadata SESSION_PRO_PAYMENT_PROVIDER_METADATA[SESSION_PRO_PAYMENT_PROVIDER_COUNT] = {
    /*SESSION_PRO_PAYMENT_PROVIDER_NIL*/ {
        .request_refund_support_url = string8_literal(""),
        .subscription_page_url      = string8_literal(""),
    },
    /*SESSION_PRO_PAYMENT_PROVIDER_GOOGLE_PLAY_STORE*/ {
        .request_refund_support_url = string8_literal("https://support.google.com/googleplay/workflow/9813244"),
        .subscription_page_url      = string8_literal("https://play.google.com/store/account/subscriptions?package=network.loki.messenger"),
    },
    /*SESSION_PRO_PAYMENT_PROVIDER_IOS_APP_STORE*/ {
        .request_refund_support_url = string8_literal("https://support.apple.com/118223"),
        .subscription_page_url      = string8_literal("https://account.apple.com/account/manage/section/subscriptions")
    }
};

The general usage pattern for the request and response code available in pro_backend.{hpp,h}

GetProProofRequest  request       = {...};                                           // Build the request object
std::string         request_json  = request.to_json();                               // Convert it to json
std::string         response_json = send_net_request(pro_backend_url, request_json); // Send POST request using your networking APIs
GetProProofResponse response      = GetProProofResponse::parse(response_json);

if (response.status == SESSION_PRO_BACKEND_SUCCESS_STATUS) {
  // Success! Use the values in the struct
} else {
  // Failure! Parsing errors or input validation errors. Errors are held in the errors array
  for (auto it : response.errors)
    fprintf(stderr, "ERROR: %s\n", it.c_str());
}

Doy-lee added 30 commits August 25, 2025 17:12
This simplifies the API and minimises the API surface with code
interacting with it since the public key is already bundled with the secret.

- Add helper function to derive keys from the original seed
- Use _hex_u literals to simplify test construction code
Design of the interface should be accomodating not opionated. This also
fixes a bug where the pro backend key wasn't been initialised yet in the
C interface
Due to BT encoding using sort order to order keys. Version at top means
we can conditionally handle version changes easily.
Was mistakenly removed, upon review of iOS code 1o1s are wrapped in an envelope.
With the new helper functions encrypt_and_wrap_for_{1o1,group,community}
its clearer that this API only really should be called in these
3 circumstances. Making it a kitchen sink black boxes the whole process
but seems to give people options (destinations) that are meaningless as
they don't do anything but we imply they might. I think it's better to
get rid of it and simplify the calling interface.
We assume that you are encrypting for the destination AND into the
correct namespace. Encrypting for 1o1 as a caller has the intent that
you want to "talk" to someone and in all cases this would have to be
encrypted which is the most obvious outcome of what you would expect to
get if you asked libsession to do it.

The namespace complicated things unnecessarily by making it appear as if
there's an alternative way to encrypt if you were targetting different
namespace. Technically this is true, if you target another
namesspace/mailbox there are different conventions on how an application
should consume data from that mailbox but that is not related to the
task of encrypting for a conversation (1o1, group, community, sync message).
@Doy-lee Doy-lee force-pushed the doyle-pro-backend-polish branch 3 times, most recently from f834337 to e5862ab Compare August 29, 2025 05:29
@Doy-lee Doy-lee force-pushed the doyle-pro-backend-polish branch from 410f0e7 to a83ab26 Compare August 29, 2025 05:50
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