There's a way to go about this without using matrices or vectors, similar to this numpy implementation. We can think of longitude/latitude as two quaternion rotations composed together.
Let's work with a Z-up right-handed coordinate system. Let's call longitude φ and latitude θ, and the point represented by the two as (φ, θ). For visualization, the red axis corresponds to X, green to Y, and blue to Z.
We want to find the quaternion representing the rotation from (0, 0), in red, to (a, b), in green:
We can represent this rotation as a combination first of the longitudinal rotation, then of the latitudinal rotation, like so:
First, we rotated by a along the Z axis, which transforms the X and Y axes. Then, we rotated by b along the new local Y axis. Thus, we know two sets of axis/angle information for this rotation.
Luckily, the conversion from axis/angle to quaternions is already known. Given an angle α and an axis vector ω, the resulting quaternion is:
(cos(α/2), ω.x*sin(α/2), ω.y*sin(α/2), ω.z*sin(α/2))
So the first rotation is represented by a rotation of a degrees along the world (0, 0, 1) axis, giving us:
q1 = (cos(a/2), 0, 0, sin(a/2))
The second rotation is represented by a rotation of b degrees along the transformed/local (0, 1, 0) axis, giving us:
q2 = (cos(b/2), 0, sin(b/2), 0)
We can multiply these two quaternions to give us a single quaternion representing this compound rotation from (0, 0) to (a, b). The formula for quaternion multiplication is a bit lengthy, but you can find it here. The result:
q2*q1 = (cos(a/2)cos(b/2), -sin(a/2)sin(b/2), cos(a/2)sin(b/2), sin(a/2)cos(b/2))
Not that it means much, but we can confirm that this formula is the same as the numpy implementation mentioned before.
JCooper mentioned a great point that one degree of freedom is still left, along the X axis in this case. If θ stays within ±90 degrees, we can imagine that the Z axis always pointing upwards. This has the effect of constraining the X axis rotation and is hopefully what you want.
Hope this helps!
edit: Notice that this is essentially the same thing as working with 2 Euler angles. So to reverse this conversion, you can use any quaternion to Euler angle conversion, provided that the rotation order is the same.