Функционал подарочных сертификатов можно реализовать с помощью купонов на скидку на сумму подарочного сертификата. То есть продавать эти купоны на разные суммы. Это стандартный функционал в битрикс.
Но на одном из проектов возникла задача убрать из заказа скидку по купону и добавить оплату с внутреннего счета на ту же сумму, потому что в 1с оплата подарочным сертификатом уже зачислена как аванс, и в заказе должна приходить вся сумма, а не сумма со скидкой.
Чтобы удалить скидку я использовала событие сохранения заказа OnSaleOrderSaved.
Получала из объекта заказа скидки, получала из заказа пользователя, находила id правила, чтобы проверить, что это подарочный сертификат, дальше находила сумму купона,
и убирала из заказа эту скидку.
Далее создавала или сразу зачисляла на счет пользователя сумму купона и оплачивала заказ с внутреннего счета.
1с программиста такая оплата устроила.
Main\EventManager::getInstance()->addEventHandler( 'sale', 'OnSaleOrderSaved', 'ConvertCoupon' ); function ConvertCoupon($event){ AddMessage2Log("ConvertCoupon"); $order = $event->getParameter("ENTITY"); \Bitrix\Main\Loader::includeModule('sale'); $userId=$order->getUserId(); $discountData = $order->getDiscount()->getApplyResult(); foreach($discountData['FULL_DISCOUNT_LIST'] as $i=>$d){ if($i==43){ $sumCoupon=$d['ACTIONS']['CHILDREN'][0]['DATA']['Value']; } } foreach($discountData["COUPON_LIST"] as $k=>$c){ if($c["DATA"]["DISCOUNT_ID"]==43){ \Bitrix\Sale\DiscountCouponsManager::clearApplyCoupon($k); $discount=$order->getDiscount(); $discount->setOrderRefresh(true); $discount->setApplyResult(array()); $basket = $order->getBasket(); $basket->refreshData(array('PRICE', 'COUPONS')); $discount->setUseMode(1); $discount->calculate(); $order->save(); if(!CSaleUserAccount::GetByUserID($userId, "RUB")){ $arFields = Array("USER_ID" => $userId, "CURRENCY" => "RUB", "CURRENT_BUDGET" => $sumCoupon); $useraccId=CSaleUserAccount::Add($arFields); } else{ CSaleUserAccount::UpdateAccount( $userId, $sumCoupon, "RUB", "MANUAL", 0 ); } Bitrix\Sale\Compatible\OrderCompatibility::payFromBudget($order,false,true); $order->save(); } } }