First call is the validation call and this call will add automatically a param, that is the ajax param. the second call does not add this param, therefore, on your controller, you check for the param existance and if it exists, you run only the validation, otherwise, you let it pass and reach the submission code of your controller. This is perfectly normal.
Here’s a sample controller code to illustrate the above:
$request = Yii::app()->request;
$paymentForm = new StripePaymentForm('validation');
// $paymentForm->modelName is not generated by yii, it's something custom
if($request->isAjaxRequest && $request->isPostRequest && $request->getPost('ajax') == strtolower($paymentForm->modelName)) {
// this is step one, only the validation
echo CActiveForm::validate($paymentForm);
Yii::app()->end();
}
// this is step two, the save action
$paymentForm->attributes = (array)$request->getPost($paymentForm->modelName, array());
if ($paymentForm->save()) {
// saved
} else {
// not saved
}