mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-24 20:49:28 +00:00
Add anypay. Add purschase gift card.
This commit is contained in:
parent
716c0821bb
commit
6c947cdb63
10 changed files with 248 additions and 56 deletions
38
lib/anypay/any_pay_payment.dart
Normal file
38
lib/anypay/any_pay_payment.dart
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:cake_wallet/anypay/any_pay_payment_instruction.dart';
|
||||||
|
|
||||||
|
class AnyPayPayment {
|
||||||
|
AnyPayPayment({
|
||||||
|
@required this.time,
|
||||||
|
@required this.expires,
|
||||||
|
@required this.memo,
|
||||||
|
@required this.paymentUrl,
|
||||||
|
@required this.paymentId,
|
||||||
|
@required this.chain,
|
||||||
|
@required this.network,
|
||||||
|
@required this.instructions});
|
||||||
|
|
||||||
|
factory AnyPayPayment.fromMap(Map<String, dynamic> obj) {
|
||||||
|
final instructions = (obj['instructions'] as List<dynamic>)
|
||||||
|
.map((dynamic instruction) => AnyPayPaymentInstruction.fromMap(instruction as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
return AnyPayPayment(
|
||||||
|
time: DateTime.parse(obj['time'] as String),
|
||||||
|
expires: DateTime.parse(obj['expires'] as String),
|
||||||
|
memo: obj['memo'] as String,
|
||||||
|
paymentUrl: obj['paymentUrl'] as String,
|
||||||
|
paymentId: obj['paymentId'] as String,
|
||||||
|
chain: obj['chain'] as String,
|
||||||
|
network: obj['network'] as String,
|
||||||
|
instructions: instructions);
|
||||||
|
}
|
||||||
|
|
||||||
|
final DateTime time;
|
||||||
|
final DateTime expires;
|
||||||
|
final String memo;
|
||||||
|
final String paymentUrl;
|
||||||
|
final String paymentId;
|
||||||
|
final String chain;
|
||||||
|
final String network;
|
||||||
|
final List<AnyPayPaymentInstruction> instructions;
|
||||||
|
}
|
30
lib/anypay/any_pay_payment_instruction.dart
Normal file
30
lib/anypay/any_pay_payment_instruction.dart
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:cake_wallet/anypay/any_pay_payment_instruction_output.dart';
|
||||||
|
|
||||||
|
class AnyPayPaymentInstruction {
|
||||||
|
AnyPayPaymentInstruction({
|
||||||
|
@required this.type,
|
||||||
|
@required this.requiredFeeRate,
|
||||||
|
@required this.txKey,
|
||||||
|
@required this.txHash,
|
||||||
|
@required this.outputs});
|
||||||
|
|
||||||
|
factory AnyPayPaymentInstruction.fromMap(Map<String, dynamic> obj) {
|
||||||
|
final outputs = (obj['outputs'] as List<dynamic>)
|
||||||
|
.map((dynamic out) =>
|
||||||
|
AnyPayPaymentInstructionOutput.fromMap(out as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
return AnyPayPaymentInstruction(
|
||||||
|
type: obj['type'] as String,
|
||||||
|
requiredFeeRate: obj['requiredFeeRate'] as int,
|
||||||
|
txKey: obj['tx_key'] as bool,
|
||||||
|
txHash: obj['tx_hash'] as bool,
|
||||||
|
outputs: outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String type;
|
||||||
|
final int requiredFeeRate;
|
||||||
|
final bool txKey;
|
||||||
|
final bool txHash;
|
||||||
|
final List<AnyPayPaymentInstructionOutput> outputs;
|
||||||
|
}
|
10
lib/anypay/any_pay_payment_instruction_output.dart
Normal file
10
lib/anypay/any_pay_payment_instruction_output.dart
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
class AnyPayPaymentInstructionOutput {
|
||||||
|
const AnyPayPaymentInstructionOutput(this.address, this.amount);
|
||||||
|
|
||||||
|
factory AnyPayPaymentInstructionOutput.fromMap(Map<String, dynamic> obj) {
|
||||||
|
return AnyPayPaymentInstructionOutput(obj['address'] as String, obj['amount'] as int);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String address;
|
||||||
|
final int amount;
|
||||||
|
}
|
48
lib/anypay/anypay_api.dart
Normal file
48
lib/anypay/anypay_api.dart
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cake_wallet/anypay/any_pay_payment.dart';
|
||||||
|
|
||||||
|
class AnyPayApi {
|
||||||
|
static const contentTypePaymentRequest = 'application/payment-request';
|
||||||
|
static const xPayproVersion = '2';
|
||||||
|
|
||||||
|
static String chainByScheme(String scheme) {
|
||||||
|
switch (scheme.toLowerCase()) {
|
||||||
|
case 'monero':
|
||||||
|
return CryptoCurrency.xmr.title;
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CryptoCurrency currencyByScheme(String scheme) {
|
||||||
|
switch (scheme.toLowerCase()) {
|
||||||
|
case 'monero':
|
||||||
|
return CryptoCurrency.xmr;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<AnyPayPayment> pay(String uri) async {
|
||||||
|
final fragments = uri.split(':?r=');
|
||||||
|
final scheme = fragments.first;
|
||||||
|
final url = fragments[1];
|
||||||
|
final headers = <String, String>{
|
||||||
|
'Content-Type': contentTypePaymentRequest,
|
||||||
|
'X-Paypro-Version': xPayproVersion,
|
||||||
|
'Accept': '*/*',};
|
||||||
|
final body = <String, dynamic>{
|
||||||
|
'chain': chainByScheme(scheme),
|
||||||
|
'currency': currencyByScheme(scheme).title};
|
||||||
|
final response = await post(url, headers: headers, body: utf8.encode(json.encode(body)));
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final decodedBody = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
return AnyPayPayment.fromMap(decodedBody);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:cake_wallet/core/yat_service.dart';
|
import 'package:cake_wallet/core/yat_service.dart';
|
||||||
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||||
import 'package:cake_wallet/entities/wake_lock.dart';
|
import 'package:cake_wallet/entities/wake_lock.dart';
|
||||||
import 'package:cake_wallet/ionia/ionia.dart';
|
import 'package:cake_wallet/ionia/ionia_service.dart';
|
||||||
import 'package:cake_wallet/ionia/ionia_api.dart';
|
import 'package:cake_wallet/ionia/ionia_api.dart';
|
||||||
import 'package:cake_wallet/monero/monero.dart';
|
import 'package:cake_wallet/monero/monero.dart';
|
||||||
import 'package:cake_wallet/haven/haven.dart';
|
import 'package:cake_wallet/haven/haven.dart';
|
||||||
|
@ -129,7 +129,6 @@ import 'package:cake_wallet/entities/template.dart';
|
||||||
import 'package:cake_wallet/exchange/exchange_template.dart';
|
import 'package:cake_wallet/exchange/exchange_template.dart';
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
|
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
|
||||||
import 'package:cake_wallet/ionia/ionia_merchant_service.dart';
|
|
||||||
import 'package:cake_wallet/ionia/ionia_token_service.dart';
|
import 'package:cake_wallet/ionia/ionia_token_service.dart';
|
||||||
|
|
||||||
final getIt = GetIt.instance;
|
final getIt = GetIt.instance;
|
||||||
|
@ -226,8 +225,6 @@ Future setup(
|
||||||
|
|
||||||
getIt.registerFactory(() => IoniaTokenService(getIt.get<FlutterSecureStorage>()));
|
getIt.registerFactory(() => IoniaTokenService(getIt.get<FlutterSecureStorage>()));
|
||||||
|
|
||||||
getIt.registerFactory(() => IoniaMerchantService(getIt.get<IoniaTokenService>(), isDevEnv: true));
|
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) =>
|
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) =>
|
||||||
WalletNewVM(getIt.get<AppStore>(),
|
WalletNewVM(getIt.get<AppStore>(),
|
||||||
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:cake_wallet/ionia/ionia_merchant.dart';
|
||||||
|
import 'package:cake_wallet/ionia/ionia_order.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:cake_wallet/ionia/ionia_user_credentials.dart';
|
import 'package:cake_wallet/ionia/ionia_user_credentials.dart';
|
||||||
|
@ -11,6 +13,8 @@ class IoniaApi {
|
||||||
static final verifyEmailUri = Uri.https(baseUri, '/$pathPrefix/VerifyEmail');
|
static final verifyEmailUri = Uri.https(baseUri, '/$pathPrefix/VerifyEmail');
|
||||||
static final createCardUri = Uri.https(baseUri, '/$pathPrefix/CreateCard');
|
static final createCardUri = Uri.https(baseUri, '/$pathPrefix/CreateCard');
|
||||||
static final getCardsUri = Uri.https(baseUri, '/$pathPrefix/GetCards');
|
static final getCardsUri = Uri.https(baseUri, '/$pathPrefix/GetCards');
|
||||||
|
static final getMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/GetMerchants');
|
||||||
|
static final getPurchaseMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/PurchaseGiftCard');
|
||||||
|
|
||||||
// Create user
|
// Create user
|
||||||
|
|
||||||
|
@ -122,4 +126,69 @@ class IoniaApi {
|
||||||
|
|
||||||
return IoniaVirtualCard.fromMap(data);
|
return IoniaVirtualCard.fromMap(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Merchants
|
||||||
|
|
||||||
|
Future<List<IoniaMerchant>> getMerchants({
|
||||||
|
@required String username,
|
||||||
|
@required String password,
|
||||||
|
@required String clientId}) async {
|
||||||
|
final headers = <String, String>{
|
||||||
|
'clientId': clientId,
|
||||||
|
'username': username,
|
||||||
|
'password': password};
|
||||||
|
final response = await post(getMerchantsUrl, headers: headers);
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
final decodedBody = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
final isSuccessful = decodedBody['Successful'] as bool ?? false;
|
||||||
|
|
||||||
|
if (!isSuccessful) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
final data = decodedBody['Data'] as List<dynamic>;
|
||||||
|
return data.map((dynamic e) {
|
||||||
|
final element = e as Map<String, dynamic>;
|
||||||
|
return IoniaMerchant.fromJsonMap(element);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purchase Gift Card
|
||||||
|
|
||||||
|
Future<IoniaOrder> purchaseGiftCard({
|
||||||
|
@required String merchId,
|
||||||
|
@required double amount,
|
||||||
|
@required String currency,
|
||||||
|
@required String username,
|
||||||
|
@required String password,
|
||||||
|
@required String clientId}) async {
|
||||||
|
final headers = <String, String>{
|
||||||
|
'clientId': clientId,
|
||||||
|
'username': username,
|
||||||
|
'password': password,
|
||||||
|
'Content-Type': 'application/json'};
|
||||||
|
final body = <String, dynamic>{
|
||||||
|
'Amount': amount,
|
||||||
|
'Currency': currency,
|
||||||
|
'MerchantId': merchId};
|
||||||
|
final response = await post(getPurchaseMerchantsUrl, headers: headers, body: json.encode(body));
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final decodedBody = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
final isSuccessful = decodedBody['Successful'] as bool ?? false;
|
||||||
|
|
||||||
|
if (!isSuccessful) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final data = decodedBody['Data'] as Map<String, dynamic>;
|
||||||
|
return IoniaOrder.fromMap(data);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,51 +0,0 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:cake_wallet/ionia/ionia_merchant.dart';
|
|
||||||
import 'package:cake_wallet/ionia/ionia_token_service.dart';
|
|
||||||
|
|
||||||
class IoniaMerchantService {
|
|
||||||
IoniaMerchantService(this._tokenService, {@required this.isDevEnv});
|
|
||||||
|
|
||||||
static String devApiUrl = "https://apidev.dashdirect.org/partner";
|
|
||||||
|
|
||||||
final bool isDevEnv;
|
|
||||||
|
|
||||||
final TokenService _tokenService;
|
|
||||||
|
|
||||||
String get apiUrl => isDevEnv ? devApiUrl : '';
|
|
||||||
|
|
||||||
String get getMerchantsUrl => '$apiUrl/GetMerchants';
|
|
||||||
|
|
||||||
Future<List<IoniaMerchant>> getMerchants() async {
|
|
||||||
final token = await _tokenService.getToken();
|
|
||||||
// FIX ME: remove hardcoded values
|
|
||||||
final headers = <String, String>{
|
|
||||||
'Authorization': token.toString(),
|
|
||||||
'firstName': 'cake',
|
|
||||||
'lastName': 'cake',
|
|
||||||
'email': 'cake@test'};
|
|
||||||
final response = await post(getMerchantsUrl, headers: headers);
|
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
final decodedBody = json.decode(response.body) as Map<String, dynamic>;
|
|
||||||
final isSuccessful = decodedBody['Successful'] as bool ?? false;
|
|
||||||
|
|
||||||
if (!isSuccessful) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
final data = decodedBody['Data'] as List<dynamic>;
|
|
||||||
return data.map((dynamic e) {
|
|
||||||
final element = e as Map<String, dynamic>;
|
|
||||||
return IoniaMerchant.fromJsonMap(element);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> purchaseGiftCard() async {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
23
lib/ionia/ionia_order.dart
Normal file
23
lib/ionia/ionia_order.dart
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
class IoniaOrder {
|
||||||
|
IoniaOrder({@required this.id,
|
||||||
|
@required this.uri,
|
||||||
|
@required this.currency,
|
||||||
|
@required this.amount,
|
||||||
|
@required this.paymentId});
|
||||||
|
factory IoniaOrder.fromMap(Map<String, dynamic> obj) {
|
||||||
|
return IoniaOrder(
|
||||||
|
id: obj['order_id'] as String,
|
||||||
|
uri: obj['uri'] as String,
|
||||||
|
currency: obj['currency'] as String,
|
||||||
|
amount: obj['amount'] as double,
|
||||||
|
paymentId: obj['payment_id'] as String);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
final String uri;
|
||||||
|
final String currency;
|
||||||
|
final double amount;
|
||||||
|
final String paymentId;
|
||||||
|
}
|
|
@ -1,4 +1,7 @@
|
||||||
|
import 'package:cake_wallet/ionia/ionia_merchant.dart';
|
||||||
|
import 'package:cake_wallet/ionia/ionia_order.dart';
|
||||||
import 'package:cake_wallet/ionia/ionia_virtual_card.dart';
|
import 'package:cake_wallet/ionia/ionia_virtual_card.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
import 'package:cake_wallet/ionia/ionia_api.dart';
|
import 'package:cake_wallet/ionia/ionia_api.dart';
|
||||||
|
@ -59,4 +62,29 @@ class IoniaService {
|
||||||
final password = await secureStorage.read(key: ioniaPasswordStorageKey);
|
final password = await secureStorage.read(key: ioniaPasswordStorageKey);
|
||||||
return ioniaApi.getCards(username: username, password: password, clientId: clientId);
|
return ioniaApi.getCards(username: username, password: password, clientId: clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Merchants
|
||||||
|
|
||||||
|
Future<List<IoniaMerchant>> getMerchants() async {
|
||||||
|
final username = await secureStorage.read(key: ioniaUsernameStorageKey);
|
||||||
|
final password = await secureStorage.read(key: ioniaPasswordStorageKey);
|
||||||
|
return ioniaApi.getMerchants(username: username, password: password, clientId: clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purchase Gift Card
|
||||||
|
|
||||||
|
Future<IoniaOrder> purchaseGiftCard({
|
||||||
|
@required String merchId,
|
||||||
|
@required double amount,
|
||||||
|
@required String currency}) async {
|
||||||
|
final username = await secureStorage.read(key: ioniaUsernameStorageKey);
|
||||||
|
final password = await secureStorage.read(key: ioniaPasswordStorageKey);
|
||||||
|
return ioniaApi.purchaseGiftCard(
|
||||||
|
merchId: merchId,
|
||||||
|
amount: amount,
|
||||||
|
currency: currency,
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
clientId: clientId);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:cake_wallet/ionia/ionia.dart';
|
import 'package:cake_wallet/ionia/ionia_service.dart';
|
||||||
import 'package:cake_wallet/ionia/ionia_create_state.dart';
|
import 'package:cake_wallet/ionia/ionia_create_state.dart';
|
||||||
import 'package:cake_wallet/ionia/ionia_virtual_card.dart';
|
import 'package:cake_wallet/ionia/ionia_virtual_card.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
Loading…
Reference in a new issue