diff --git a/.gitignore b/.gitignore index aab04fb..d0ecc48 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ build/ example/pubspec.lock +coverage/lcov.info diff --git a/lib/src/hyperpay.dart b/lib/src/hyperpay.dart index a5965ed..4313828 100644 --- a/lib/src/hyperpay.dart +++ b/lib/src/hyperpay.dart @@ -173,6 +173,42 @@ class HyperpayPlugin { } } + /// Performs client side payment where payment configuration is + /// kept hidden on the server + /// + /// In contrast to [pay], [easyPay] assumes that the config is + /// on the server such that the mobile applications can request + /// a [checkoutId] from the server and then submits a custom + /// payment form to this funcion while taking into account + /// [brand] and [card] entered by user + /// + /// [easyPay] does not provide a feedback on the status of payment, + /// since all config is moved to the server; it is the server + /// that should provide a separate api for the mobile application + /// to request information about the status of a particular transaction. + /// + static Future easyPay({ + required String checkoutId, + required BrandType brand, + required CardInfo card, + }) async { + try { + await _channel.invokeMethod( + 'start_payment_transaction', + { + 'checkoutID': checkoutId, + 'brand': brand.name.toUpperCase(), + 'card': card.toMap(), + }, + ); + log('Transaction submitted, validate its status with the server', + name: "HyperpayPlugin/pay"); + } catch (e) { + log('$e', name: "HyperpayPlugin/pay"); + rethrow; + } + } + /// Perform a transaction natively with Apple Pay. /// /// This method will throw a [NOT_SUPPORTED] error on any platform other than iOS. diff --git a/pubspec.lock b/pubspec.lock index 8181dc2..2566e35 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,27 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "47.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "4.7.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" async: dependency: transitive description: @@ -36,6 +57,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.16.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.2" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" fake_async: dependency: transitive description: @@ -43,6 +85,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.4" flutter: dependency: "direct main" description: flutter @@ -53,6 +102,20 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" http: dependency: "direct main" description: @@ -60,6 +123,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -67,6 +137,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.1" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.5" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" matcher: dependency: transitive description: @@ -88,6 +179,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + mocktail: + dependency: "direct dev" + description: + name: mocktail + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" path: dependency: transitive description: @@ -95,11 +214,67 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.11" source_span: dependency: transitive description: @@ -135,6 +310,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.1" + test: + dependency: transitive + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.21.4" test_api: dependency: transitive description: @@ -142,6 +324,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.12" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.16" typed_data: dependency: transitive description: @@ -156,6 +345,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "9.4.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" sdks: - dart: ">=2.17.0 <3.0.0" + dart: ">=2.18.0 <3.0.0" flutter: ">=1.20.0" diff --git a/pubspec.yaml b/pubspec.yaml index caa10ed..ba4f319 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: sdk: flutter dev_dependencies: + mocktail: ^0.3.0 flutter_test: sdk: flutter diff --git a/test/hyperpay_test.dart b/test/hyperpay_test.dart index 4705907..4d307dd 100644 --- a/test/hyperpay_test.dart +++ b/test/hyperpay_test.dart @@ -3,6 +3,10 @@ import 'dart:io'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart'; +import 'package:hyperpay/hyperpay.dart'; +import 'package:mocktail/mocktail.dart'; + +class HyperPayPluginMock extends Mock implements HyperpayPlugin {} Client httpclinet = Client(); void main() { @@ -11,10 +15,21 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); + late HyperpayPlugin plugin; + late BrandType brand; + late CardInfo cardInfo; setUp(() { channel.setMockMethodCallHandler((MethodCall methodCall) async { return '42'; }); + plugin = HyperPayPluginMock(); + brand = BrandType.visa; + cardInfo = CardInfo( + holder: 'Big Danny', + cardNumber: '4200000000000000', + cvv: '000', + expiryMonth: '12', + expiryYear: '55'); }); tearDown(() { @@ -22,5 +37,23 @@ void main() { }); test('Pay using checkout ID', () async {}); + test('easyPay using checkout ID returns', () async { + when( + () => plugin.easyPay( + checkoutId: any(named: 'checkoutId'), brand: brand, card: cardInfo), + ).thenAnswer((_) => Future.value()); + + expectLater(plugin.easyPay(checkoutId: '42', brand: brand, card: cardInfo), + completes); + }); + test('easyPay using checkout ID throws', () async { + when( + () => plugin.easyPay( + checkoutId: any(named: 'checkoutId'), brand: brand, card: cardInfo), + ).thenAnswer((_) => Future.error(Exception())); + + expectLater(plugin.easyPay(checkoutId: '42', brand: brand, card: cardInfo), + throwsException); + }); test('Get a specific payment status', () async {}); }