Reduced to 44 overs a side, after a long rain delay, Pakistan were set a target of 192, and reached it comfortably with 28 balls to spare.
Dale Steyn and Lonwabo Tsotsobe opened with a tight spell of bowling but it was Ryan McLaren who made the breakthrough when Nasir Jamshed (10) tried to guide the ball down to third man but got a thick edge to Graeme Smith at slip.
VIDEO: 2nd ODI - Proteas v Pakistan - highlights
Steyn politely informed Hafeez that it was the fifth time on the tour he had taken his wicket -- this time for 31 after Kyle Abbott took a diving catch at mid-on.
Robin Peterson entered the fray and dismissed Kamran Akmal for 18, after he had played and missed and saw the ball roll back onto his stumps.
Younus Khan, playing in his 250th ODI, and captain Misbah-ul-Huq pulled things back for Pakistan, after they were looking shaky on 69 for three, adding 46 runs together.
Younus, however, also succumbed to Peterson and was caught by Hashim Amla at deep square leg for 32.
Misbah and Shoaib Malik took the side home with an unbeaten 77-run stand which included seven fours and three sixes.
Misbah was not out on 57 and Malik on 35.
Earlier, South Africa were bowled out for 191 in 43.2 overs after they had resumed at 177 for seven after the long rain delay.
A crucial seventh-wicket stand between Farhaan Behardien and Robin Peterson took them to a fairly respectable total after a poor start.
The pair came together at 106 for six, in the 21st over and added a patient 67 runs off 108 deliveries.
Pakistan were rewarded for their decision to include an extra seam bowler in their attack and Mohammad Irfan duly obliged with a career best four for 33.
His first scalp was Hashim Amla, looking to hit the ball through cover, but getting a faint edge through to the keeper for 17.
Colin Ingram went out off the next delivery, also given out caught behind after the decision was referred sent for review. A puzzled Ingram walked off, apparently given out on noise alone, as replays showed no evidence of the ball hitting the bat.
Irfan was on a hat-trick which was not to be but he did not have to wait long for his third scalp.
Skipper AB de Villiers (4) was trying to run the ball down to third man but Irfan got some extra bounce which caught the edge of the bat and Younus Khan took the catch at second slip.
When Graeme Smith (10) fell to Junaid Khan, the Proteas were 43 for four with all three of their senior batsmen back in the change room in only the eighth over.
There was nothing Du Plessis (17) could have done to prevent Irfan’s fourth wicket. The ball bounced up at him and the batsman was unable to keep it down as he moved one hand off the bat. The ball hit his glove and sent Irfan diving low to his left to take a one-handed catch.
Behardien and Ryan McLaren shared a sixth-wicket stand of 44 runs, before Mohammad Hafeez trapped McLaren (17) between middle and leg after a similar, unsuccessful appeal off the previous ball.
Behardien went on to score his maiden ODI half-century but Hafeez got the better of him and he was caught on the square-leg boundary for 58.
Peterson added a valuable 44 to the total while Saeed Ajmal, Junaid and Hafeez all finished with two wickets apiece.