iiko / front.api.sdk

iikoFront Api SDK (part of iikoRMS)
34 stars 22 forks source link

Проблема с "тихой" оплатой #517

Open FredRost opened 3 months ago

FredRost commented 3 months ago

Добрый день. Имеем плагин написанный для реализации оплаты заказов с внешней системы. Принцип в целом прост, приходит информация с номером карты гостя и товаром, далее формируется и оплачивается заказ, и отправляется подтверждение его оплаты. Ранее на версии айки ниже 8.8.8 всё работало безупречно и проблем не было, но после обновления клиента на версию 8.8.9 мы получаем ошибку: Не удалось привести тип объекта "Resto.Front.Api.Data.Payments.IikoCard51PaymentItemAdditionalData" к типу "Resto.Front.Api.Data.Payments.ExternalPaymentItemAdditionalData". При разборе ситуации выяснилось что в момент добавления данных в заказ методом PluginContext.Operations.AddPaymentItem, происходит та самая конвертация типов, но почему она происходит не совсем понятно.

Для конкретики укажу строки кода с задействованными перегрузками.

var additionalData = new IikoCard51PaymentItemAdditionalData { Credential = CardID, SearchScope = IikoCard51SearchScope.CardNumber }; var payment = PluginContext.Operations.AddPaymentItem(revorder.ResultSum, additionalData, queryLinq, revorder, PluginContext.Operations.GetCredentials());

То есть вторая перегрузка которая использует интерфейс IPaymentItemAdditionalData почему то принудительно пытается провести конвертацию IikoCard51PaymentItemAdditionalData в ExternalPaymentItemAdditionalData.

Прошу подсказать в чём именно проблема, повторюсь что версию апи мы не меняем, единственное что меняется это версия самого фронта.

GulnaraBikbova commented 2 months ago

Добрый день! Какую версию api используете?

FredRost commented 2 months ago

Пробовал на v7 и на v8 итог один, ошибка одна.

GulnaraBikbova commented 2 months ago

Ошибка вида "Не удалось привести тип объекта "Resto.Front.Api.Data.Payments.IikoCard51PaymentItemAdditionalData" к типу "Resto.Front.Api.Data.Payments.ExternalPaymentItemAdditionalData"." вероятнее всего вызвана неподходящим значением параметра paymentType. Т.е. если в качестве дополнительной информации передавать IikoCard51PaymentItemAdditionalData, то тип оплаты должен быть соответствующий -- кард. Чему в вашем примере равен paymentType? Также, пришлите, пожалуйста, стек-трейс ошибки приведения типов.

FredRost commented 2 months ago

var lowerdedPaymentName = PluginConfiguration.Instance.ConnectionSettings.PaymentTypeKey.ToLower(CultureInfo.CurrentCulture);

var queryLinq = PluginContext.Operations.GetPaymentTypes().First(a => a.Name.ToLower(CultureInfo.CurrentCulture).Contains(lowerdedPaymentName));

стек пока прислать не могу, повторные тесты запланированы на завтра

GulnaraBikbova commented 2 months ago

Спасибо за приложенный код. У вас не могло в бд появится тип оплаты с похожим именем, помимо типа оплаты Кард? Может быть наименование меняли у кардовского типа оплаты, что он перестал попадать в заданный фильтр..

Давайте попробуем залогировать тип оплаты queryLinq, передаваемый в AddPaymentItem(), например так: PluginContext.Log.Info($"Current paymentType Id = {paymentType.Id}, Name = {paymentType.Name}.");

FredRost commented 2 months ago

[2024-07-11 03:34:51,206] ERROR [13] - Не удалось привести тип объекта "Resto.Front.Api.Data.Payments.IikoCard51PaymentItemAdditionalData" к типу "Resto.Front.Api.Data.Payments.ExternalPaymentItemAdditionalData". Server stack trace: в Resto.Front.Api.V7.Extensions.PaymentTypeExtensions.CreatePaymentItem(IPaymentType paymentType, Guid id, IPaymentItemAdditionalData additionalData, IAuthData authData) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\Extensions\PaymentTypeExtensions.cs:строка 116 в Resto.Front.Api.V7.Editors.Actions.AddPaymentItemWithPredefinedId.Apply(Guid id, Decimal paymentSum, IPaymentItemAdditionalData additionalData, IPaymentType paymentType, IBaseOrderBuilder order, SessionContext context) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\Editors\Actions\AddPaymentItem.cs:строка 0 в Resto.Front.Api.V7.Editors.Actions.AddPaymentItem.Resto.Front.Api.V7.Editors.IEditActionBase.WriteChanges(SessionContext context, IDictionary2 createdEntities, IDictionary2 actionNumbersToCreatedApiEntities, Int32 i) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\Editors\Editors.g.cs:строка 3517 в Resto.Front.Api.V7.Editors.EditSessionWriter.WriteChanges() в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\Editors\EditSessionWriter.cs:строка 199 в Resto.Front.Api.V7.OperationServiceInternal.SubmitChanges(IUser user, IEditSession editSession) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\OperationServiceInternal.cs:строка 1986 в Resto.Front.Api.V7.OperationServiceInternal.Resto.Front.Api.IOperationServiceInternal.SubmitChanges(ICredentials credentials, IEditSession editSession) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\Operations.g.cs:строка 2473 в System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs) в System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

Exception rethrown at [0]: в System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) в Resto.Front.Api.IOperationServiceInternal.SubmitChanges(ICredentials credentials, IEditSession editSession) в Resto.Front.Api.OperationServiceFacade.Resto.Front.Api.IOperationService.SubmitChanges(ICredentials credentials, IEditSession editSession) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api.V7\OperationsInterfaces.g.cs:строка 4519 в Resto.Front.Api.Extensions.OperationServiceExtensions.AddPaymentItem(IOperationService operationService, Decimal paymentSum, IPaymentItemAdditionalData additionalData, IPaymentType paymentType, IOrder order, ICredentials credentials) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api.V7\Editors\OperationsInterfacesExtensions.g.cs:строка 691 в Lemma.PaymentProcessors.Robobar.Controllers.SetOperationsController.d__2.MoveNext() в E:\GitLab\robobar\Controllers\SetOperationsController.cs:строка 195

[2024-07-11 03:46:15,819] INFO [ 3] - Current paymentType Id = b69b8ef9-699e-4204-873b-94f09be6577e, Name = Робобар Пополнение карт (банк).

FredRost commented 2 months ago

Получилось обойти ошибку конвертации вот таким образом: var externaladditionalData = new ExternalPaymentItemAdditionalData() { CustomData = JsonSerializer.Serialize(additionalData) }; var payment = PluginContext.Operations.AddPaymentItem(revorder.ResultSum, externaladditionalData, queryLinq, revorder, PluginContext.Operations.GetCredentials()); но теперь я столкнулся с ошибкой другого вида...

[2024-07-11 03:46:17,146] INFO [ 3] - Failed to create order in iikoFront, contact administrator: Payment of order #400214 (cc4305d2-c9c2-4e74-b7dc-fdf36dc3395b) failed. Cannot process not “silent” payment item aa2cec3f-6d1f-43c7-97c5-3f6e9e115362 of payment type b69b8ef9-699e-4204-873b-94f09be6577e. Reason: NotProcessedNotSilentPaymentsNotSupported. Server stack trace: в Resto.Front.Api.V7.OperationServiceInternal.PayOrderAndPayOutOnUser(IUser user, IBaseOrderEntity order, IPaymentType paymentType, Decimal sum, ChequeAdditionalInfo apiChequeAdditionalInfo) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\OperationServiceInternal.cs:строка 1086 в Resto.Front.Api.V7.OperationServiceInternal.PayOrder(IUser user, IBaseOrderEntity order, ChequeAdditionalInfo apiChequeAdditionalInfo) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\OperationServiceInternal.cs:строка 1128 в Resto.Front.Api.V7.OperationServiceInternal.Resto.Front.Api.IOperationServiceInternal.PayOrder(ICredentials credentials, IOrder order, ChequeAdditionalInfo chequeAdditionalInfo) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api\V7\Operations.g.cs:строка 2687 в System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs) в System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

Exception rethrown at [0]: в System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) в Resto.Front.Api.IOperationServiceInternal.PayOrder(ICredentials credentials, IOrder order, ChequeAdditionalInfo chequeAdditionalInfo) в Resto.Front.Api.OperationServiceFacade.Resto.Front.Api.IOperationService.PayOrder(ICredentials credentials, IOrder order, ChequeAdditionalInfo chequeAdditionalInfo) в K:\BuildAgent\work\master-installer\dev\iikoFront.Net\Api\Resto.Front.Api.V7\OperationsInterfaces.g.cs:строка 4533 в Lemma.PaymentProcessors.Robobar.Controllers.SetOperationsController.d__2.MoveNext() в E:\GitLab\robobar\Controllers\SetOperationsController.cs:строка 229

GulnaraBikbova commented 2 months ago

Нужно определиться, какой тип оплаты вы хотите добавить: безналичный расчет системой iikocard или внешний? Вы пытаетесь провести оплату "Робобар Пополнение карт (банк)". Приложите, пожалуйста, скрин настроек данного типа оплаты из BackOffice. Если это оплата iikocard, то настройки должны быть такими и в качестве доп. параметров должен быть передан IikoCard51PaymentItemAdditionalData.

Исходя из ошибки, iikoFront воспринимает тип оплаты с Id = b69b8ef9-699e-4204-873b-94f09be6577e, Name = Робобар Пополнение карт (банк), как внешний тип оплаты, поэтому ожидает дополнительные параметры вида ExternalPaymentItemAdditionalData.

FredRost commented 2 months ago

photo_2024-07-11_16-07-45 photo_2024-07-11_16-07-41 Используются эти 2 типа оплаты, ранее до обновления они и работали. Необходимо первый привести к виду второго, правильно я понимаю?

FredRost commented 2 months ago

Кажется я нашёл проблему, буду изучать, по результату напишу.

GulnaraBikbova commented 2 months ago

Спасибо, за приложенную информацию. Стало понятнее.

Необходимо первый привести к виду второго, правильно я понимаю? Нет, имеющиеся типы оплат перенастраивать не нужно.

var lowerdedPaymentName = PluginConfiguration.Instance.ConnectionSettings.PaymentTypeKey.ToLower(CultureInfo.CurrentCulture); var queryLinq = PluginContext.Operations.GetPaymentTypes().First(a => a.Name.ToLower(CultureInfo.CurrentCulture).Contains(lowerdedPaymentName));

Полагаю lowerdedPaymentName у вас равен "робобар".
Тогда PluginContext.Operations.GetPaymentTypes() должен возвращать 2 варианта типов оплат: безналичный тип расчета кардом "РОБОБАР" и внешний тип оплаты "Робобар Пополнение карт (банк)". После обновления первым в списке возвращаемых типов оказался внешний тип оплаты "Робобар Пополнение карт (банк)" вместо безналичного типа расчета кардом "РОБОБАР".

Т.о. чтобы не полагаться на удачу, ищите нужный вам тип оплаты "РОБОБАР", например так: var queryLinq = PluginContext.Operations.GetPaymentTypes().Single(a => a.Name.ToLower(CultureInfo.CurrentCulture) == lowerdedPaymentName);

Также, по добавлению оплат есть документация: 1) Оплатные действия 2) Внешние типы оплаты

FredRost commented 2 months ago

Вы правы, просто до обновления находился один, а после второй. Видимо что то изменилось в порядке возвращаемых типов оплат... В воскресенье будем проводить тесты, надеюсь вопрос будет закрыт. Спасибо за достаточно оперативный ответ