There are probably multiple ways to do this. Let's suppose that you only look for these cuts when CPLEX identifies a potential new incumbent (integer-feasible solution). It makes sense to put the cut generation code in the lazy constraint callback (or at least to call it from there). If a new cut is identified, add it in the lazy constraint callback and also push it onto a global stack.
In the user cut callback, beyond any other cut generators you may have there, program a check of the stack. If the stack is not empty, pop the cut(s) there and add them (presumably as global rather than local cuts). The user cut callback will automatically be called at the next feasible node visited after the node where the lazy constraint callback generated the cuts. (Minor technicality: if the next feasible node has an integer solution to the LP relaxation, I'm not sure the user cut callback will be called there; but it will definitely be called the next time a node is feasible and does not have an integer relaxed solution.)
#CPLEXOptimizers#DecisionOptimization