The correct method is as follows.
1. Choose a parameter X, which represents multiples of D to include in the window when difficulty is static. X=2 is a good choice.
2. When a share is submitted, assign to it a score of 1/D, where D is the difficulty at the time the share is submitted.
3. When a block is found, pay (sB)/X for the last share (the one before the winning share), where s is the share's score and B is the block reward. Continue backwards, paying each share based on its score, until you reach a share which brings the total score of the shares counted above X. Pay that share the amount (sB)/(tX) * min (r,t), where r is the score required to bring the total to exactly X and t is the score of the winning share. Don't pay any older shares.
4. If the pool has just started, and a block is found before there are shares totaling a score of X, there will be leftover rewards and it should be decided what to do with them. It doesn't matter much, but I recommend that the operator keeps them (in a macroscopic view, if the pool ever changes, this is compensation for the funds needed to cash participants out). Other options include donating to charity, or distributing among the miners.
How does this (specifically steps 2 & 3) change when a pool fee is involved? Is B simply reduced by the fee amount (e.g. B is only 99% of what it otherwise was in a 1% fee pool)?