diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml
index e6b8d0a..6f55f38 100644
--- a/.github/workflows/pull_request.yaml
+++ b/.github/workflows/pull_request.yaml
@@ -48,12 +48,11 @@ jobs:
- name: 'Install Tools'
run: |
flutter pub global activate melos
- flutter pub global activate flutter_plugin_tools
- name: 'Clean Workspace'
run: melos clean
- name: 'Bootstrap Workspace'
run: melos bootstrap
- - name: 'Melos Format'
+ - name: 'Format Code'
run: melos run format
- name: 'Validate Formatting'
run: |
diff --git a/melos.yaml b/melos.yaml
index f425a78..2d06eb4 100644
--- a/melos.yaml
+++ b/melos.yaml
@@ -12,7 +12,7 @@ ide:
scripts:
format: >
- melos exec -c 1 -- \
+ melos exec -c 6 -- \
dartfmt -w .
# Run `dart analyze` in all packages.
@@ -28,7 +28,7 @@ scripts:
lint:pana: >
melos exec -c 1 --fail-fast --no-private --ignore="*example*" -- \
- pana || pub global activate pana
+ pana
# Additional cleanup lifecycle script, executed when `melos clean` is ran.
postclean: >
diff --git a/packages/tinkoff_acquiring/CHANGELOG.md b/packages/tinkoff_acquiring/CHANGELOG.md
index bed3f3a..49114d6 100644
--- a/packages/tinkoff_acquiring/CHANGELOG.md
+++ b/packages/tinkoff_acquiring/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 3.0.1
+
+* Add SendClosingReceipt endpoint
+* Small fixes
+
# 3.0.0
* **BREAKING**: Splitting the library into two packages:
diff --git a/packages/tinkoff_acquiring/README.md b/packages/tinkoff_acquiring/README.md
index 9584504..319bace 100644
--- a/packages/tinkoff_acquiring/README.md
+++ b/packages/tinkoff_acquiring/README.md
@@ -2,7 +2,7 @@
-[Read this in Russian](README.ru.md)
+[Read this in Russian][readme_ru]
Acquiring SDK allows you to integrate [Tinkoff Internet Acquiring][acquiring] into mobile applications for iOS and Android platforms.
@@ -20,8 +20,8 @@ Acquiring SDK allows you to integrate [Tinkoff Internet Acquiring][acquiring] in
Add this to your package's pubspec.yaml file:
```yaml
dependencies:
- tinkoff_acquiring: 3.0.0
- tinkoff_acquiring_flutter: 3.0.0 # for UI
+ tinkoff_acquiring: 3.0.1
+ tinkoff_acquiring_flutter: 3.0.1 # for UI
```
## Before usage
@@ -58,10 +58,12 @@ final TinkoffAcquiring acquiring = TinkoffAcquiring(
## Example
-The [Example](../../example/lib/main.dart) is in the corresponding folder
+The [Example][example] is in the corresponding folder
## SDK workflow
![](https://acdn.tinkoff.ru/static/pages/files/d3cd0230-03a1-47e6-bacf-dfdf9c8c1bea.png)
[documentation]: https://www.tinkoff.ru/kassa/develop/api/payments/
-[acquiring]: https://www.tinkoff.ru/business/internet-acquiring/
\ No newline at end of file
+[acquiring]: https://www.tinkoff.ru/business/internet-acquiring/
+[example]: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter/tree/main/example
+[readme_ru]: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter/blob/main/packages/tinkoff_acquiring/README.ru.md
\ No newline at end of file
diff --git a/packages/tinkoff_acquiring/README.ru.md b/packages/tinkoff_acquiring/README.ru.md
index cc4f417..65824cc 100644
--- a/packages/tinkoff_acquiring/README.ru.md
+++ b/packages/tinkoff_acquiring/README.ru.md
@@ -18,8 +18,8 @@ Acquiring SDK позволяет интегрировать [Интернет-Э
Для подключения добавьте в файл Pubspec зависимости:
```yaml
dependencies:
- tinkoff_acquiring: 3.0.0
- tinkoff_acquiring_flutter: 3.0.0 # for UI
+ tinkoff_acquiring: 3.0.1
+ tinkoff_acquiring_flutter: 3.0.1 # for UI
```
## Подготовка к работе
@@ -56,10 +56,11 @@ final TinkoffAcquiring acquiring = TinkoffAcquiring(
## Пример работы
-Пример работы SDK доступен в [Example](../../example/lib/main.dart)
+Пример работы SDK доступен в [Example][example]
## Схема работы SDK
![](https://acdn.tinkoff.ru/static/pages/files/d3cd0230-03a1-47e6-bacf-dfdf9c8c1bea.png)
[documentation]: https://www.tinkoff.ru/kassa/develop/api/payments/
-[acquiring]: https://www.tinkoff.ru/business/internet-acquiring/
\ No newline at end of file
+[acquiring]: https://www.tinkoff.ru/business/internet-acquiring/
+[example]: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter/tree/main/example
\ No newline at end of file
diff --git a/packages/tinkoff_acquiring/example/README.md b/packages/tinkoff_acquiring/example/README.md
index 6d02c02..a42bb9b 100644
--- a/packages/tinkoff_acquiring/example/README.md
+++ b/packages/tinkoff_acquiring/example/README.md
@@ -1 +1,3 @@
-The [Example](../../../example/lib/main.dart) is in the corresponding folder
\ No newline at end of file
+The [Example][example] is in the corresponding folder
+
+[example]: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter/tree/main/example
\ No newline at end of file
diff --git a/packages/tinkoff_acquiring/lib/src/constants.dart b/packages/tinkoff_acquiring/lib/src/constants.dart
index 6c15bf9..b8f9058 100644
--- a/packages/tinkoff_acquiring/lib/src/constants.dart
+++ b/packages/tinkoff_acquiring/lib/src/constants.dart
@@ -110,6 +110,7 @@ abstract class ApiMethods {
static const String addCard = 'AddCard';
static const String attachCard = 'AttachCard';
static const String check3DSVersion = 'Check3dsVersion';
+ static const String sendClosingReceipt = 'SendClosingReceipt';
}
abstract class Ignore {
diff --git a/packages/tinkoff_acquiring/lib/src/core/models/models.dart b/packages/tinkoff_acquiring/lib/src/core/models/models.dart
index 199febd..f4bf637 100644
--- a/packages/tinkoff_acquiring/lib/src/core/models/models.dart
+++ b/packages/tinkoff_acquiring/lib/src/core/models/models.dart
@@ -30,6 +30,8 @@ export './remove_customer/remove_customer_request.dart';
export './remove_customer/remove_customer_response.dart';
export './resend/resend_request.dart';
export './resend/resend_response.dart';
+export './send_closing_receipt/send_closing_receipt_request.dart';
+export './send_closing_receipt/send_closing_receipt_response.dart';
export './submit_3ds_authorization/submit_3ds_authorization_response.dart';
export './check_3ds_version/check_3ds_version_request.dart';
export './check_3ds_version/check_3ds_version_response.dart';
diff --git a/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_request.dart b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_request.dart
new file mode 100644
index 0000000..34696e0
--- /dev/null
+++ b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_request.dart
@@ -0,0 +1,69 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import '../../../constants.dart';
+import '../../../utils/extensions.dart';
+import '../base/acquiring_request.dart';
+import '../common/receipt.dart';
+
+part 'send_closing_receipt_request.g.dart';
+
+/// Метод позволяет отправить закрывающий чек в кассу.
+/// Условия работы метода:
+/// 1. Закрывающий чек может быть отправлен если платежная сессия по первому чеку находится в статусе CONFIRMED.
+/// 2. В платежной сессии был передан объект Receipt.
+/// 3. В объекте Receipt был передан хотя бы один объект Receipt.Items.PaymentMethod = "full_prepayment" или "prepayment" или "advance"
+///
+/// [SendClosingReceiptRequest](https://www.tinkoff.ru/kassa/develop/api/payments/SendClosingReceipt-request/)
+@JsonSerializable(includeIfNull: false)
+class SendClosingReceiptRequest extends AcquiringRequest {
+ /// Создает экземпляр метода по отправке закрывающего чека в кассу
+ SendClosingReceiptRequest({
+ required this.paymentId,
+ required this.receipt,
+ String? signToken,
+ }) : super(signToken) {
+ validate();
+ }
+
+ /// Преобразование json в модель
+ factory SendClosingReceiptRequest.fromJson(Map json) =>
+ _$SendClosingReceiptRequestFromJson(json);
+
+ @override
+ String get apiMethod => ApiMethods.sendClosingReceipt;
+
+ @override
+ Map toJson() => _$SendClosingReceiptRequestToJson(this);
+
+ @override
+ Map get equals => {
+ ...super.equals,
+ JsonKeys.paymentId: paymentId,
+ JsonKeys.receipt: receipt,
+ };
+
+ @override
+ SendClosingReceiptRequest copyWith({
+ int? paymentId,
+ Receipt? receipt,
+ }) {
+ return SendClosingReceiptRequest(
+ paymentId: paymentId ?? this.paymentId,
+ receipt: receipt ?? this.receipt,
+ );
+ }
+
+ @override
+ void validate() {
+ assert(paymentId.length <= 20);
+ receipt.validate();
+ }
+
+ /// Идентификатор платежа в системе банка
+ @JsonKey(name: JsonKeys.paymentId)
+ final int paymentId;
+
+ /// Данные чека
+ @JsonKey(name: JsonKeys.receipt)
+ final Receipt receipt;
+}
diff --git a/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_request.g.dart b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_request.g.dart
new file mode 100644
index 0000000..0accb8e
--- /dev/null
+++ b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_request.g.dart
@@ -0,0 +1,32 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'send_closing_receipt_request.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+SendClosingReceiptRequest _$SendClosingReceiptRequestFromJson(
+ Map json) {
+ return SendClosingReceiptRequest(
+ paymentId: json['PaymentId'] as int,
+ receipt: Receipt.fromJson(json['Receipt'] as Map),
+ signToken: json['Token'] as String?,
+ );
+}
+
+Map _$SendClosingReceiptRequestToJson(
+ SendClosingReceiptRequest instance) {
+ final val = {};
+
+ void writeNotNull(String key, dynamic value) {
+ if (value != null) {
+ val[key] = value;
+ }
+ }
+
+ writeNotNull('Token', instance.signToken);
+ val['PaymentId'] = instance.paymentId;
+ val['Receipt'] = instance.receipt;
+ return val;
+}
diff --git a/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_response.dart b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_response.dart
new file mode 100644
index 0000000..316d4d5
--- /dev/null
+++ b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_response.dart
@@ -0,0 +1,34 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import '../base/acquiring_response.dart';
+import '../enums/status.dart';
+
+part 'send_closing_receipt_response.g.dart';
+
+/// Ответ от сервера на закрывающий чек в кассу
+///
+/// [SendClosingReceiptResponse](https://www.tinkoff.ru/kassa/develop/api/payments/SendClosingReceipt-response/)
+@JsonSerializable()
+class SendClosingReceiptResponse extends AcquiringResponse {
+ /// Создает экземпляр ответа от сервера на закрывающий чек в кассу
+ SendClosingReceiptResponse({
+ Status? status,
+ bool? success,
+ String? errorCode,
+ String? message,
+ String? details,
+ }) : super(
+ status: status,
+ success: success,
+ errorCode: errorCode,
+ message: message,
+ details: details,
+ );
+
+ /// Преобразование json в модель
+ factory SendClosingReceiptResponse.fromJson(Map json) =>
+ _$SendClosingReceiptResponseFromJson(json);
+
+ @override
+ Map toJson() => _$SendClosingReceiptResponseToJson(this);
+}
diff --git a/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_response.g.dart b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_response.g.dart
new file mode 100644
index 0000000..857f63a
--- /dev/null
+++ b/packages/tinkoff_acquiring/lib/src/core/models/send_closing_receipt/send_closing_receipt_response.g.dart
@@ -0,0 +1,87 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'send_closing_receipt_response.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+SendClosingReceiptResponse _$SendClosingReceiptResponseFromJson(
+ Map json) {
+ return SendClosingReceiptResponse(
+ status: _$enumDecodeNullable(_$StatusEnumMap, json['Status']),
+ success: json['Success'] as bool?,
+ errorCode: json['ErrorCode'] as String?,
+ message: json['Message'] as String?,
+ details: json['Details'] as String?,
+ );
+}
+
+Map _$SendClosingReceiptResponseToJson(
+ SendClosingReceiptResponse instance) =>
+ {
+ 'Success': instance.success,
+ 'Status': _$StatusEnumMap[instance.status],
+ 'ErrorCode': instance.errorCode,
+ 'Message': instance.message,
+ 'Details': instance.details,
+ };
+
+K _$enumDecode(
+ Map enumValues,
+ Object? source, {
+ K? unknownValue,
+}) {
+ if (source == null) {
+ throw ArgumentError(
+ 'A value must be provided. Supported values: '
+ '${enumValues.values.join(', ')}',
+ );
+ }
+
+ return enumValues.entries.singleWhere(
+ (e) => e.value == source,
+ orElse: () {
+ if (unknownValue == null) {
+ throw ArgumentError(
+ '`$source` is not one of the supported values: '
+ '${enumValues.values.join(', ')}',
+ );
+ }
+ return MapEntry(unknownValue, enumValues.values.first);
+ },
+ ).key;
+}
+
+K? _$enumDecodeNullable(
+ Map enumValues,
+ dynamic source, {
+ K? unknownValue,
+}) {
+ if (source == null) {
+ return null;
+ }
+ return _$enumDecode(enumValues, source, unknownValue: unknownValue);
+}
+
+const _$StatusEnumMap = {
+ Status.newest: 'NEW',
+ Status.formShowed: 'FORM_SHOWED',
+ Status.deadlineExpired: 'DEADLINE_EXPIRED',
+ Status.canceled: 'CANCELED',
+ Status.preAuthorizing: 'PREAUTHORIZING',
+ Status.authorizing: 'AUTHORIZING',
+ Status.authorized: 'AUTHORIZED',
+ Status.authFail: 'AUTH_FAIL',
+ Status.rejected: 'REJECTED',
+ Status.threeDsChecking: '3DS_CHECKING',
+ Status.threeDsChecked: '3DS_CHECKED',
+ Status.reversing: 'REVERSING',
+ Status.partialReversed: 'PARTIAL_REVERSED',
+ Status.reversed: 'REVERSED',
+ Status.confirming: 'CONFIRMING',
+ Status.confirmed: 'CONFIRMED',
+ Status.refunding: 'REFUNDING',
+ Status.partialRefunded: 'PARTIAL_REFUNDED',
+ Status.refunded: 'REFUNDED',
+};
diff --git a/packages/tinkoff_acquiring/lib/src/core/network/network_client.dart b/packages/tinkoff_acquiring/lib/src/core/network/network_client.dart
index b89cb7a..8b064ec 100644
--- a/packages/tinkoff_acquiring/lib/src/core/network/network_client.dart
+++ b/packages/tinkoff_acquiring/lib/src/core/network/network_client.dart
@@ -47,23 +47,25 @@ class NetworkClient {
_response =
response({JsonKeys.cardInfo: json});
} else {
- Exception('ApiMethod for list error');
+ throw Exception('ApiMethod for list error');
}
} else if (json is Map) {
_response = response(json as Map);
} else {
- Exception('REST type error');
+ throw Exception('REST type error');
}
_config.logger.log(message: _response.toString(), name: 'Response');
_completer.complete(_response);
} else {
- _completer.completeError(rawResponse);
+ throw http.ClientException(
+ rawResponse.reasonPhrase ?? '', rawResponse.request?.url);
}
})
.timeout(NetworkSettings.timeout)
.catchError((Object error) {
- _config.logger.log(message: '', name: 'HTTP Error', error: error);
+ _config.logger
+ .log(message: '', name: 'HTTP Error', error: error.toString());
_completer.completeError(error);
});
diff --git a/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring.dart b/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring.dart
index 2e8cf71..07449c0 100644
--- a/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring.dart
+++ b/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring.dart
@@ -133,6 +133,15 @@ class TinkoffAcquiring {
);
}
+ /// Отправить закрывающий чек в кассу
+ Future sendClosingReceipt(
+ SendClosingReceiptRequest request) {
+ return _network(
+ request,
+ (Map json) => SendClosingReceiptResponse.fromJson(json),
+ );
+ }
+
/// Проверяет 3DS протокол
Future check3DSVersion(
Check3DSVersionRequest request) {
diff --git a/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring_config.dart b/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring_config.dart
index a57f5b0..b401b60 100644
--- a/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring_config.dart
+++ b/packages/tinkoff_acquiring/lib/src/core/tinkoff_acquiring_config.dart
@@ -1,5 +1,4 @@
import 'package:tinkoff_acquiring/src/constants.dart';
-
import '../utils/logger.dart';
/// {@template tinkoff_acquiring_config}
diff --git a/packages/tinkoff_acquiring/pubspec.yaml b/packages/tinkoff_acquiring/pubspec.yaml
index c27deed..6c1b715 100644
--- a/packages/tinkoff_acquiring/pubspec.yaml
+++ b/packages/tinkoff_acquiring/pubspec.yaml
@@ -1,6 +1,6 @@
name: tinkoff_acquiring
description: Flutter Tinkoff Acquiring SDK is a simple way to integrate payments into your mobile application.
-version: 3.0.0
+version: 3.0.1
repository: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter
issue_tracker: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter/issues
homepage: https://madbrains.ru/
diff --git a/packages/tinkoff_acquiring/test_components/sdk_single_test.dart b/packages/tinkoff_acquiring/test_components/sdk_single_test.dart
index e3c6a18..0a5560e 100644
--- a/packages/tinkoff_acquiring/test_components/sdk_single_test.dart
+++ b/packages/tinkoff_acquiring/test_components/sdk_single_test.dart
@@ -180,4 +180,43 @@ void start() {
final ResendResponse value = await acquiring.resend(ResendRequest());
expect(value.runtimeType, ResendResponse);
});
+
+ test('sendClosingReceipt', () async {
+ final SendClosingReceiptResponse value =
+ await acquiring.sendClosingReceipt(SendClosingReceiptRequest(
+ paymentId: 700000021787,
+ receipt: Receipt(
+ taxation: Taxation.esn,
+ items: [
+ Items(
+ name: 'testItem',
+ quantity: '1',
+ price: amount.toString(),
+ amount: amount.toString(),
+ tax: Tax.vat20,
+ paymentMethod: PaymentMethod.fullPayment,
+ paymentObject: PaymentObject.composite,
+ shopCode: 'shop',
+ agentData: AgentData(
+ agentSign: AgentSign.bankPayingAgent,
+ operationName: 'testOperation',
+ phones: [phone],
+ receiverPhones: [phone],
+ transferPhones: [phone],
+ operatorName: 'testOperator',
+ operatorAddress: 'testAddress',
+ operatorInn: 'testtestInn',
+ ),
+ supplierInfo: SupplierInfo(
+ [phone],
+ 'testName',
+ 'testtestInn',
+ ),
+ ),
+ ],
+ email: email,
+ ),
+ ));
+ expect(value.runtimeType, SendClosingReceiptResponse);
+ });
}
diff --git a/packages/tinkoff_acquiring_flutter/CHANGELOG.md b/packages/tinkoff_acquiring_flutter/CHANGELOG.md
index 8c18cd1..ce9ae11 100644
--- a/packages/tinkoff_acquiring_flutter/CHANGELOG.md
+++ b/packages/tinkoff_acquiring_flutter/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 3.0.1
+
+* Update `tinkoff_acquiring` dependencie
+
# 3.0.0
* **BREAKING**: Splitting the library into two packages:
diff --git a/packages/tinkoff_acquiring_flutter/README.md b/packages/tinkoff_acquiring_flutter/README.md
index 1a197f0..7f4d4c0 100644
--- a/packages/tinkoff_acquiring_flutter/README.md
+++ b/packages/tinkoff_acquiring_flutter/README.md
@@ -1 +1,3 @@
-Extension for [tinkoff_acquiring](../../packages/tinkoff_acquiring/README.md) please go there for documentation.
\ No newline at end of file
+Extension for [tinkoff_acquiring][repo] please go there for documentation.
+
+[repo]: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter
\ No newline at end of file
diff --git a/packages/tinkoff_acquiring_flutter/example/README.md b/packages/tinkoff_acquiring_flutter/example/README.md
index 6d02c02..a42bb9b 100644
--- a/packages/tinkoff_acquiring_flutter/example/README.md
+++ b/packages/tinkoff_acquiring_flutter/example/README.md
@@ -1 +1,3 @@
-The [Example](../../../example/lib/main.dart) is in the corresponding folder
\ No newline at end of file
+The [Example][example] is in the corresponding folder
+
+[example]: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter/tree/main/example
\ No newline at end of file
diff --git a/packages/tinkoff_acquiring_flutter/pubspec.yaml b/packages/tinkoff_acquiring_flutter/pubspec.yaml
index 29640c3..710ae36 100644
--- a/packages/tinkoff_acquiring_flutter/pubspec.yaml
+++ b/packages/tinkoff_acquiring_flutter/pubspec.yaml
@@ -1,6 +1,6 @@
name: tinkoff_acquiring_flutter
description: Flutter Tinkoff Acquiring SDK is a simple way to integrate payments into your mobile application.
-version: 3.0.0
+version: 3.0.1
repository: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter
issue_tracker: https://github.com/MadBrains/Tinkoff-Acquiring-SDK-Flutter/issues
homepage: https://madbrains.ru/
@@ -14,7 +14,7 @@ dependencies:
sdk: flutter
flutter_localizations:
sdk: flutter
- tinkoff_acquiring: ^3.0.0
+ tinkoff_acquiring: ^3.0.1
webview_flutter: ^2.0.4
dev_dependencies: