yandex_pay_api 0.5.0

Yandex Pay API
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
use crate::orders::ItemReceipt;
use crate::serde_help::*;
use crate::*;
use builder_pattern::Builder;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет данные ответа для получения деталей заказа.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#orderresponsedata>
pub struct OrderResponseData {
    pub delivery: Option<Delivery>,
    pub operations: Vec<OrderResponseOperation>,
    pub order: Option<BaseMerchantApiOrder>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет данные о доставке.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#delivery>
pub struct Delivery {
    #[serde(with = "string_as_float")]
    pub price: f64,
    #[serde(with = "option_string_as_float")]
    pub actual_price: Option<f64>,
    #[serde(with = "option_iso8601")]
    pub created: Option<Time>,
    pub status: DeliveryStatus,
    #[serde(with = "option_iso8601")]
    pub updated: Option<Time>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные статусы доставки.
pub enum DeliveryStatus {
    New,
    Estimating,
    Expired,
    ReadyForApproval,
    Collecting,
    Preparing,
    Delivering,
    Delivered,
    Returning,
    Returned,
    Failed,
    Cancelled,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет данные операции в ответе на запрос деталей заказа.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#orderresponseoperation>
pub struct OrderResponseOperation {
    #[serde(with = "string_as_float")]
    pub amount: f64,
    #[serde(rename = "operationId")]
    pub operation_id: String,
    #[serde(rename = "operationType")]
    pub operation_type: OperationType,
    #[serde(rename = "orderId")]
    pub order_id: String,
    pub approval_code: Option<String>,
    #[serde(with = "option_iso8601")]
    pub created: Option<Time>,
    pub external_operation_id: Option<String>,
    pub params: Option<serde_json::Value>,
    pub reason: Option<String>,
    pub status: OperationStatus,
    #[serde(with = "option_iso8601")]
    pub updated: Option<Time>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы операций.
pub enum OperationType {
    Authorize,
    BindCard,
    Refund,
    Capture,
    Void,
    Recurring,
    Prepayment,
    Submit,
}

#[derive(Debug, Serialize, Clone, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные статусы операции.
pub enum OperationStatus {
    Pending,
    Success,
    Fail,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет данные заказа.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#basemerchantapiorder>
pub struct BaseMerchantApiOrder {
    /// Корзина
    pub cart: Cart,
    #[serde(default)]
    /// Трехбуквенный код валюты заказа (ISO 4217)
    /// Максимальная длина: 2048
    /// Пример: `RUB`
    pub currency_code: CurrencyCode,

    /// Дата и время создания заказа (ISO 8601)
    #[serde(with = "option_iso8601")]
    pub created: Option<Time>,
    #[serde(default)]
    /// Флаг, идет ли заказ по флоу "отложенной оплаты"
    /// Значение по умолчанию: `false`
    pub is_prepayment: bool,

    /// Идентификатор продавца
    /// Максимальная длина: 2048
    pub merchant_id: Option<String>,

    /// Произвольные данные, переданные при инициализации кнопки
    /// Максимальная длина: 2048
    pub metadata: Option<String>,

    /// Полная стоимость заказа к оплате с учётом возвратов, доставки, скидок и промокодов
    /// Пример: `123.45`
    #[serde(with = "string_as_float")]
    pub order_amount: f64,

    /// Id существующего заказа на стороне продавца, переданный при инициализации кнопки
    /// Максимальная длина: 2048
    pub order_id: String,

    /// Выбранный способ оплаты
    pub payment_method: Option<PaymentMethod>,

    /// Статус оплаты
    /// Возможные значения: `PENDING`, `AUTHORIZED`, `CAPTURED`, `VOIDED`, `REFUNDED`, `CONFIRMED`, `PARTIALLY_REFUNDED`, `FAILED`, `null`
    pub payment_status: Option<PaymentStatus>,

    /// Ссылка на оплату заказа
    /// Максимальная длина: 2048
    pub payment_url: Option<String>,

    /// Причина (применимо для статусов VOIDED/FAILED)
    /// Максимальная длина: 2048
    pub reason: Option<String>,

    /// Выбранный способ доставки
    pub shipping_method: Option<ShippingMethod>,

    /// Дата и время обновления заказа (ISO 8601)
    #[serde(with = "option_iso8601")]
    pub updated: Option<Time>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные статусы оплаты.
pub enum PaymentStatus {
    Pending,
    Authorized,
    Captured,
    Voided,
    Refunded,
    Confirmed,
    PartiallyRefunded,
    Failed,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет данные корзины.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#cart>
pub struct Cart {
    /// Позиции корзины
    pub items: Vec<CartItem>,

    /// Внутренний идентификатор корзины Яндекс Пэй.
    /// Максимальная длина: 2048
    pub cart_id: String,
    #[serde(default)]
    #[serde(skip_serializing_if = "Vec::is_empty")]
    /// Купоны, применённые к корзине
    pub coupons: Vec<Coupon>,
    #[serde(default)]
    #[serde(skip_serializing_if = "Vec::is_empty")]
    /// Скидки, применённые к корзине
    pub discounts: Vec<Discount>,

    /// Переданный продавцом идентификатор корзины
    /// Максимальная длина: 2048
    pub external_id: Option<String>,

    /// Измерения корзины
    pub measurements: Option<Measurements>,

    /// Итоговая стоимость корзины, которая пойдет в оплату
    pub total: CartTotal,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Представляет данные о выбранном способе оплаты.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#paymentmethod>
pub struct PaymentMethod {
    /// Тип способа оплаты
    pub method_type: MethodType,

    /// Последние 4 цифры карты
    /// Максимальная длина: 2048
    pub card_last4: Option<String>,

    /// Платежная система
    pub card_network: Option<CardNetwork>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы способов оплаты.
pub enum MethodType {
    Card,
    Split,
    Sbp,
    SplitSbp,
    CashOnDelivery,
    CardOnDelivery,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные платежные системы.
pub enum CardNetwork {
    Amex,
    Discover,
    Jcb,
    Mastercard,
    Maestro,
    Visaelectron,
    Visa,
    Mir,
    Unionpay,
    Uzcard,
    Humocard,
    Unknown,
    Undefined,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Представляет данные о выбранном способе доставки.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#shippingmethod>
pub struct ShippingMethod {
    /// Тип способа доставки
    pub method_type: ShippingMethodType,

    /// Опции курьерской доставки
    pub courier_option: Option<CourierOption>,

    /// Опции самовывоза
    pub pickup_option: Option<PickupOption>,

    /// Опции доставки Яндекс
    pub yandex_delivery_option: Option<YandexDeliveryOption>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы способов доставки.
pub enum ShippingMethodType {
    Direct,
    Pickup,
    Courier,
    YandexDelivery,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет данные о позиции корзины.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#cartitem>
pub struct CartItem {
    /// Id товара в системе продавца.
    /// Максимальная длина: 2048
    pub product_id: String,

    /// Количество товара в заказе.
    pub quantity: ItemQuantity,

    /// Описание товара.
    /// Максимальная длина: 2048
    pub description: Option<String>,

    /// Цена за единицу товара с учётом скидок на позицию.
    /// Пример: `123.45`
    #[serde(with = "option_string_as_float")]
    pub discounted_unit_price: Option<f64>,

    /// Промо параметры товара.
    pub features: Option<CartItemFeatures>,

    /// Цена за единицу товара с учётом всех скидок на позицию и на корзину.
    /// Пример: `123.45`
    #[serde(with = "option_string_as_float")]
    pub final_price: Option<f64>,

    /// Размеры и вес товара. Обязательно для товара типа PHYSICAL.
    pub measurements: Option<Measurements>,

    /// Количество баллов Плюса.
    /// Поле только для чтения. Переданные значения будут проигнорированы.
    /// Пример: `123.45`
    #[serde(with = "option_string_as_float")]
    pub points_amount: Option<f64>,

    /// Данные для формирования чека.
    pub receipt: Option<ItemReceipt>,

    /// Суммарная цена за позицию без учета скидок.
    /// Пример: `123.45`
    #[serde(with = "option_string_as_float")]
    pub subtotal: Option<f64>,

    /// Наименование товара.
    /// Максимальная длина: 2048
    pub title: Option<String>,

    /// Суммарная цена за позицию с учётом скидок на позицию.
    /// Пример: `123.45`
    #[serde(with = "option_string_as_float")]
    pub total: Option<f64>,

    /// Тип товара. Важен для интеграции с доставками.
    /// Значение по умолчанию: `UNSPECIFIED`
    pub item_type: Option<CartItemType>,

    /// Полная цена за единицу товара без учёта скидки.
    /// Пример: `123.45`
    #[serde(with = "option_string_as_float")]
    pub unit_price: Option<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы товара.
pub enum CartItemType {
    Physical,
    Digital,
    Unspecified,
}

#[derive(Debug, Clone, Serialize, Deserialize, Builder)]
#[serde(rename_all = "camelCase")]
/// Представляет данные о купоне.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#coupon>
pub struct Coupon {
    #[into]
    /// Код купона.
    /// Максимальная длина: 2048
    pub value: String,
    #[default(None)]
    /// Описание купона. Например, "Скидка 3%".
    /// Максимальная длина: 2048
    pub description: Option<String>,
    #[default(None)]
    /// Статус купона.
    pub status: Option<CouponStatus>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные статусы купона.
pub enum CouponStatus {
    Valid,
    Invalid,
    Expired,
}

#[derive(Debug, Clone, Serialize, Deserialize, Builder)]
#[serde(rename_all = "camelCase")]
/// Представляет данные о скидке.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#discount>
pub struct Discount {
    #[into]
    /// Сумма скидки.
    /// Пример: `123.45`
    #[serde(with = "string_as_float")]
    pub amount: f64,
    #[into]
    /// Текстовое описание.
    /// Максимальная длина: 2048
    pub description: String,
    #[into]
    /// Идентификатор скидки в системе мерчанта.
    /// Максимальная длина: 2048
    pub discount_id: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, Builder)]
#[serde(rename_all = "camelCase")]
/// Представляет измерения.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#measurements>
pub struct Measurements {
    #[into]
    /// Высота, в метрах.
    pub height: f64,
    #[into]
    /// Длина, в метрах.
    pub length: f64,
    #[into]
    /// Вес, в килограммах.
    pub weight: f64,
    #[into]
    /// Ширина, в метрах.
    pub width: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет опции курьерской доставки.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#courieroption>
pub struct CourierOption {
    /// Стоимость доставки
    /// Пример: `123.45`
    #[serde(with = "string_as_float")]
    pub amount: f64,

    /// Категория доставки
    pub category: CourierCategory,

    /// ID выбранного варианта доставки в системе продавца
    /// Максимальная длина: `2048`
    pub courier_option_id: String,

    /// Название способа доставки. Показывается пользователю в списке вариантов
    /// Максимальная длина: `2048`
    pub title: String,

    /// Индивидуальные методы оплаты для метода доставки. Этот параметр нужно использовать, если нужно ограничить методы оплаты, указанные в `availablePaymentMethods`. Если параметр не указан, то используются все методы оплаты, перечисленные в `availablePaymentMethods`.
    /// Возможные значения: `CARD`, `SPLIT`, `CASH_ON_DELIVERY`, `CARD_ON_DELIVERY`
    #[serde(default = "Vec::new")]
    pub allowed_payment_methods: Vec<AllowedPaymentMethodType>,

    /// Выбранные пользователем дата и интервал. Только для `type: FLEXIBLE`
    pub customer_choice: Option<FlexibleCustomerChoice>,

    /// Ближайшая дата доставки для `type: PLAIN`. Начало интервала выбора даты доставки для `type: FLEXIBLE`
    #[serde(with = "option_iso8601")]
    pub from_date: Option<Time>,

    /// Начало интервала времени доставки. Только для `type: PLAIN`
    pub from_time: Option<String>,

    /// Тип службы доставки
    pub provider: Option<DeliveryProvider>,

    /// Чек на доставку
    pub receipt: Option<ItemReceipt>,

    /// Кодирует интервалы времени доставки, доступные для выбора. Только для `type: FLEXIBLE`
    pub time_intervals: Option<FlexibleTimeIntervals>,

    /// Самая поздняя дата доставки для `type: PLAIN`. Конец интервала выбора даты доставки для `type: FLEXIBLE`
    #[serde(with = "option_iso8601")]
    pub to_date: Option<Time>,

    /// Конец интервала времени доставки. Только для `type: PLAIN`
    pub to_time: Option<String>,
    #[serde(default)]
    /// Тип опции. Для `FLEXIBLE` вариантов доставки пользователю дается возможность выбрать желаемые дату и интервал:
    ///
    /// - Дата доставки выбирается покупателем в отрезке `[fromDate, toDate]`
    /// - Чтобы предоставить пользователю выбор интервала в течение дня, заполните `timeIntervals`
    ///
    /// Для `PLAIN` вариантов такой выбор отсутствует.
    /// Значение по умолчанию: `PLAIN`
    pub option_type: CourierOptionType,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные категории курьерской доставки.
pub enum CourierCategory {
    Express,
    Today,
    Standard,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы опций курьерской доставки.
pub enum CourierOptionType {
    #[default]
    Plain,
    Flexible,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы служб доставки.
pub enum DeliveryProvider {
    Boxberry,
    Cdek,
    RussianPost,
    Ems,
    Courier,
    Dhl,
    ExpressDelivery,
    Fivepost,
    OzonRocket,
    Dpd,
    SberLogistics,
    Pek,
    Pickpoint,
    Kce,
    PonyExpress,
    YandexDelivery,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет опции самовывоза.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#pickupoption>
pub struct PickupOption {
    /// Адрес в виде строки.
    /// Максимальная длина: 2048
    pub address: String,

    /// Координаты местоположения.
    pub location: Location,

    /// Уникальный id точки самовывоза в системе продавца.
    /// Максимальная длина: 2048
    pub pickup_point_id: String,

    /// Название точки самовывоза.
    /// Максимальная длина: 2048
    pub title: String,

    /// Индивидуальные методы оплаты для выбранного способа самовывоза.
    #[serde(default = "Vec::new")]
    pub allowed_payment_methods: Vec<AllowedPaymentMethodType>,

    /// Стоимость доставки в точку.
    /// Пример: `123.45`
    #[serde(with = "option_string_as_float")]
    pub amount: Option<f64>,

    /// Дополнительное описание.
    /// Максимальная длина: 2048
    pub description: Option<String>,
    #[serde(with = "option_iso8601")]
    /// Ближайшая возможная дата доставки.

    /// Формат: `YYYY-MM-DD`
    pub from_date: Option<Time>,
    #[serde(default = "Vec::new")]
    /// Телефоны для связи.
    /// Максимальная длина: 2048
    pub phones: Vec<String>,

    /// Тип точки вывоза.
    pub provider: Option<PickupProvider>,

    /// Чек на доставку.
    pub receipt: Option<ItemReceipt>,
    #[serde(default = "Vec::new")]
    /// График работы точки.
    pub schedule: Vec<PickupSchedule>,

    /// Срок хранения товара в точке самовывоза в днях.
    pub storage_period: Option<i32>,

    #[serde(with = "option_iso8601")]
    /// Самая поздняя дата доставки.
    /// Формат: `YYYY-MM-DD`
    pub to_date: Option<Time>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы методов оплаты.
pub enum AllowedPaymentMethodType {
    Card,
    Split,
    CashOnDelivery,
    CardOnDelivery,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Возможные типы точек самовывоза.
pub enum PickupProvider {
    YandexMarket,
    Boxberry,
    Cdek,
    InStore,
    RussianPost,
    Pickpoint,
    Dpd,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет график работы точки самовывоза.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#pickupschedule>
pub struct PickupSchedule {
    /// День недели или диапазон дней.
    /// Пример: "пн-пт"
    /// Максимальная длина: 2048
    pub label: String,

    /// Время открытия.
    /// Формат: `HH:mm`
    ///
    /// Пример: "08:00"
    pub from_time: String,

    /// Время закрытия.
    /// Формат: `HH:mm`
    ///
    /// Пример: "20:00"
    pub to_time: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет опции доставки Яндекс.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#yandexdeliveryoption>
pub struct YandexDeliveryOption {
    /// Стоимость доставки.

    /// Пример: `123.45`
    #[serde(with = "string_as_float")]
    pub amount: f64,

    /// Категория доставки.
    /// Возможные значения: `EXPRESS`, `TODAY`, `STANDARD`
    pub category: CourierCategory,

    /// Название способа доставки. Показывается пользователю в списке вариантов.
    /// Максимальная длина: `2048`
    pub title: String,

    /// Id предложения Яндекс Доставки.
    /// Максимальная длина: `2048`
    pub yandex_delivery_option_id: String,

    /// Индивидуальные методы оплаты для метода доставки.
    /// Этот параметр нужно использовать,
    /// если нужно ограничить методы оплаты, указанные в availablePaymentMethods.
    /// Если параметр не указан, то используются все методы оплаты, перечисленные в availablePaymentMethods.
    #[serde(default = "Vec::new")]
    pub allowed_payment_methods: Vec<AllowedPaymentMethodType>,

    /// Дата и время начала доставки.
    #[serde(with = "option_iso8601")]
    pub from_datetime: Option<Time>,

    /// Чек на доставку.
    pub receipt: Option<ItemReceipt>,

    /// Дата и время окончания доставки.
    #[serde(with = "option_iso8601")]
    pub to_datetime: Option<Time>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет выбор даты и времени доставки.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#flexiblecustomerchoice>
pub struct FlexibleCustomerChoice {
    #[serde(with = "iso8601")]
    /// Дата доставки.
    pub date: Time,

    /// Интервал времени доставки.
    pub time: Option<TimeInterval>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет интервалы времени доставки.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#flexibletimeintervals>
pub struct FlexibleTimeIntervals {
    #[serde(rename = "type")]
    /// Тип интервалов.
    /// Если указан тип GRID, то необходимо задать поле grid. Если указан тип VALUES, то необходимо задать поле values
    pub time_intervals_type: TimeIntervalsType,

    /// Сетка интервалов.
    /// Кодирует интервалы в виде сетки. Используйте этот формат, если необходимо задать больше 20 интервалов доставки. Пример: {"start": "09:00", "end": "21:00", "duration": "00:20", "step": "01:00"} трактуется как набор интервалов: [{"start": "09:00", "end": "09:20"}, {"start": "10:00", "end": "10:20"}, ..., {"start": "20:00", "end": "20:20"}]
    pub grid: Option<FlexibleTimeIntervalsGridDescriptor>,
    #[serde(default)]
    /// Список интервалов.
    /// Задаёт список интервалов напрямую. Подходит для небольшого количества интервалов доставки. Рекомендуемое максимальная количество интервалов - 20
    pub values: Vec<TimeInterval>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет интервал времени.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#timeinterval>
pub struct TimeInterval {
    /// Время начала интервала.
    pub start: String,

    /// Время конца интервала.
    pub end: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет сетку интервалов времени доставки.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#flexibletimeintervalsgriddescriptor>
pub struct FlexibleTimeIntervalsGridDescriptor {
    /// Продолжительность каждого интервала.
    pub duration: String,

    /// Максимальное время начала самого последнего интервала.
    pub end: String,

    /// Время начала самого первого интервала.
    pub start: String,

    /// Разница во времени между началами двух соседних интервалов.
    pub step: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
/// Тип интервалов.
pub enum TimeIntervalsType {
    Grid,
    Values,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
/// Представляет координаты местоположения.
/// <https://pay.yandex.ru/docs/ru/custom/backend/yandex-pay-api/order/merchant_v1_order-get#location>
pub struct Location {
    /// Широта.
    pub latitude: f64,

    /// Долгота.
    pub longitude: f64,
}