1 Есть внутренний счет. Разрешите оплату с внутреннего счета и начисляйте балы на него.
2 Создайте скидку прототип с ограничением по пользователю и укажите пользователя 1 и сумму скидки 1. Дальше можете просто извлекать эту скидку, заменять id пользвоателя на своего.
Пусть в $dctPrototype скидка-прототип (полученная из \Bitrix\Sale\Internals\DiscountTable::getList(['filter'=>$arFilter])->fetch();) тогда примерно так:
// грууппы этого правила для скидки
$lstGruopsIDs = array_column(
\Bitrix\Sale\Internals\DiscountGroupTable::getList(['filter'=>['DISCOUNT_ID'=>$dctPrototype['ID']]])->fetchAll(),
'GROUP_ID'
);
// переменовываем
$dctPrototype['NAME'] = 'Автоматическая скидка';
// так надо
$dctPrototype['VERSION'] = intval($dctPrototype['VERSION']);
// удаляем лишние поля
unset($dctPrototype['MODIFIED_BY'],$dctPrototype['ID']);
// заменяем id пользователя
$dctPrototype['CONDITIONS_LIST']['CHILDREN'][0]['DATA']['value'][0] = $UserId;
$dctPrototype['UNPACK'] = str_replace(
'Bitrix\Main\Discount\UserConditionControl::checkBasket($arOrder, array(1), \'Equal\')',
'Bitrix\Main\Discount\UserConditionControl::checkBasket($arOrder, array('.$UserId.'), \'Equal\')',
$dctPrototype['UNPACK']
);
// добавляем
$result = \Bitrix\Sale\Internals\DiscountTable::add($dctPrototype);
if ($result->isSuccess()) {
$DISCOUNT_ID = $result->getId();
// добавляем группы
foreach ($lstGruopsIDs as $GROUP_ID) {
\Bitrix\Sale\Internals\DiscountGroupTable::add([
'ACTIVE'=>'Y',
'DISCOUNT_ID'=>$DISCOUNT_ID,
'GROUP_ID'=>$GROUP_ID
]);
}
}