浏览代码

Merge branch 'v1.0.1' of http://git.atmob.com:28999/Atmob-Flutter/ElectronicAssistant into v1.0.1

leon 1 年之前
父节点
当前提交
69273a0657

二进制
assets/images/icon_store_wechat_pay.webp


+ 6 - 6
lib/data/api/atmob_api.dart

@@ -1,6 +1,3 @@
-import 'dart:convert';
-import 'dart:io';
-
 import 'package:dio/dio.dart';
 import 'package:electronic_assistant/base/app_base_request.dart';
 import 'package:electronic_assistant/base/base_response.dart';
@@ -13,7 +10,6 @@ import 'package:electronic_assistant/data/api/request/chat_history_request.dart'
 import 'package:electronic_assistant/data/api/request/login_request.dart';
 import 'package:electronic_assistant/data/api/request/talk_create_request.dart';
 import 'package:electronic_assistant/data/api/request/talk_delete_request.dart';
-import 'package:electronic_assistant/data/api/request/talk_file_request.dart';
 import 'package:electronic_assistant/data/api/request/talk_generate_request.dart';
 import 'package:electronic_assistant/data/api/request/talk_paginate_request.dart';
 import 'package:electronic_assistant/data/api/request/talk_query_request.dart';
@@ -28,13 +24,13 @@ import 'package:electronic_assistant/data/api/response/chat_history_response.dar
 import 'package:electronic_assistant/data/api/response/example_info_response.dart';
 import 'package:electronic_assistant/data/api/response/home_info_response.dart';
 import 'package:electronic_assistant/data/api/response/login_response.dart';
+import 'package:electronic_assistant/data/api/response/store_index_response.dart';
 import 'package:electronic_assistant/data/api/response/talk_check_electric_response.dart';
-import 'package:electronic_assistant/data/api/response/talk_generate_response.dart';
 import 'package:electronic_assistant/data/api/response/talk_info_response.dart';
+import 'package:electronic_assistant/data/api/response/talk_original_response.dart';
 import 'package:electronic_assistant/data/api/response/talk_paginate_response.dart';
 import 'package:electronic_assistant/data/api/response/talk_query_response.dart';
 import 'package:electronic_assistant/data/api/response/tasks_running_response.dart';
-import 'package:electronic_assistant/data/api/response/talk_original_response.dart';
 import 'package:electronic_assistant/data/api/response/user_info_response.dart';
 import 'package:electronic_assistant/data/bean/talks.dart';
 import 'package:electronic_assistant/data/consts/constants.dart';
@@ -134,6 +130,10 @@ abstract class AtmobApi {
 
   @POST("/project/secretary/v1/agenda/update")
   Future<BaseResponse> agendaUpdate(@Body() AgendaUpdateRequest request);
+
+  @POST("/project/secretary/v1/item/list")
+  Future<BaseResponse<StoreIndexResponse>> storeIndex(
+      @Body() AppBaseRequest request);
 }
 
 final atmobApi = AtmobApi(defaultDio, baseUrl: Constants.baseUrl);

+ 20 - 0
lib/data/api/response/store_index_response.dart

@@ -0,0 +1,20 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import '../../bean/payment_way.dart';
+import '../../bean/store_item.dart';
+
+part 'store_index_response.g.dart';
+
+@JsonSerializable()
+class StoreIndexResponse {
+  @JsonKey(name: 'list')
+  List<StoreItem> items = [];
+
+  @JsonKey(name: "payOptions")
+  List<PaymentWay> paymentWays = [];
+
+  StoreIndexResponse(this.items, this.paymentWays);
+
+  factory StoreIndexResponse.fromJson(Map<String, dynamic> json) =>
+      _$StoreIndexResponseFromJson(json);
+}

+ 20 - 0
lib/data/bean/payment_way.dart

@@ -0,0 +1,20 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'payment_way.g.dart';
+
+@JsonSerializable()
+class PaymentWay {
+  @JsonKey(name: 'id')
+  late int id;
+  @JsonKey(name: 'payMethod')
+  late int payMethod;
+  @JsonKey(name: 'payPlatform')
+  late int payPlatform;
+  @JsonKey(name: 'title')
+  late String title;
+
+  PaymentWay(this.id, this.payMethod, this.payPlatform, this.title);
+
+  factory PaymentWay.fromJson(Map<String, dynamic> json) =>
+      _$PaymentWayFromJson(json);
+}

+ 56 - 0
lib/data/bean/store_item.dart

@@ -0,0 +1,56 @@
+import 'package:electronic_assistant/utils/expand.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part 'store_item.g.dart';
+
+@JsonSerializable()
+class StoreItem {
+  @JsonKey(name: "id")
+  late int id;
+  @JsonKey(name: "sort")
+  late int sort;
+  @JsonKey(name: "name")
+  late String name;
+  @JsonKey(name: "appleGoodsId")
+  late String appleGoodsId;
+  @JsonKey(name: "subscribable")
+  late int subscribable;
+  @JsonKey(name: "amount")
+  late int amount;
+  @JsonKey(name: "originalAmount")
+  late int originalAmount;
+  @JsonKey(name: "auth")
+  late String auth;
+  @JsonKey(name: "authValue")
+  late int authValue;
+  @JsonKey(name: "subscriptionMillis")
+  late int subscriptionMillis;
+  @JsonKey(name: "popular")
+  late bool popular;
+  @JsonKey(name: "content")
+  late String content;
+  @JsonKey(name: "itemDesc")
+  late String itemDesc;
+
+  StoreItem(
+      {required this.id,
+      required this.sort,
+      required this.name,
+      required this.appleGoodsId,
+      required this.subscribable,
+      required this.amount,
+      required this.originalAmount,
+      required this.auth,
+      required this.authValue,
+      required this.subscriptionMillis,
+      required this.popular,
+      required this.content,
+      required this.itemDesc});
+
+  get amountText => (amount / 100).toFormattedString(2);
+
+  get originalAmountText => (originalAmount / 100).toFormattedString(2);
+
+  factory StoreItem.fromJson(Map<String, dynamic> json) =>
+      _$StoreItemFromJson(json);
+}

+ 6 - 2
lib/data/consts/constants.dart

@@ -17,11 +17,15 @@ class Constants {
 
   static String baseUrl = getBaseUrl();
 
-  static String privacyPolicy =
+  static const String privacyPolicy =
       "https://cdn.v8dashen.com/static/xt-xm-privacy.html";
 
-  static String userAgreement =
+  static const String userAgreement =
       "https://cdn.v8dashen.com/static/xt-xm-clause.html";
+
+  static const int paymentMethodAlipay = 1;
+
+  static const int paymentMethodWechat = 2;
 }
 
 String getBaseUrl() {

+ 22 - 0
lib/data/repositories/store_repository.dart

@@ -0,0 +1,22 @@
+import 'package:electronic_assistant/data/api/atmob_api.dart';
+import 'package:electronic_assistant/data/api/response/store_index_response.dart';
+import 'package:electronic_assistant/data/bean/store_item.dart';
+import 'package:electronic_assistant/utils/http_handler.dart';
+
+import '../../base/app_base_request.dart';
+
+class StoreRepository {
+  StoreRepository._();
+
+  factory StoreRepository() {
+    return storeRepository;
+  }
+
+  Future<StoreIndexResponse> storeIndex() {
+    return atmobApi
+        .storeIndex(AppBaseRequest())
+        .then(HttpHandler.handle(false));
+  }
+}
+
+final StoreRepository storeRepository = StoreRepository._();

+ 2 - 2
lib/module/record/record_task.dart

@@ -4,7 +4,7 @@ class RecordTaskHandler extends TaskHandler {
   @override
   Future<void> onDestroy(DateTime timestamp) {
     // TODO: implement onDestroy
-    throw UnimplementedError();
+    return Future.value();
   }
 
   @override
@@ -15,7 +15,7 @@ class RecordTaskHandler extends TaskHandler {
   @override
   Future<void> onStart(DateTime timestamp, TaskStarter starter) {
     // TODO: implement onStart
-    throw UnimplementedError();
+    return Future.value();
   }
 }
 

+ 39 - 9
lib/module/store/controller.dart

@@ -1,20 +1,50 @@
 import 'package:electronic_assistant/base/base_controller.dart';
-import 'package:electronic_assistant/data/repositories/account_repository.dart';
-import 'package:electronic_assistant/popup/talk_popup.dart';
-import 'package:electronic_assistant/utils/error_handler.dart';
-import 'package:electronic_assistant/utils/expand.dart';
-import 'package:electronic_assistant/utils/toast_util.dart';
-import 'package:electronic_assistant/widget/alert_dialog.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:electronic_assistant/data/bean/payment_way.dart';
+import 'package:electronic_assistant/data/repositories/store_repository.dart';
 import 'package:get/get.dart';
 
+import '../../data/bean/store_item.dart';
+
 class StoreController extends BaseController {
   final isExpanded = false.obs;
 
+  final RxList<StoreItem> storeItems = <StoreItem>[].obs;
+
+  final RxList<PaymentWay> paymentWays = <PaymentWay>[].obs;
+
+  final Rxn<StoreItem> currentSelectedStoreItem = Rxn<StoreItem>();
+
+  final Rxn<PaymentWay> currentSelectedPaymentWay = Rxn<PaymentWay>();
+
+  final RxBool isPaymentWayExpanded = false.obs;
+
   @override
   void onInit() {
-    // TODO: implement onInit
     super.onInit();
+    initStoreIndexData();
+  }
+
+  void initStoreIndexData() {
+    storeRepository.storeIndex().then((indexData) {
+      storeItems.clear();
+      storeItems.addAll(indexData.items);
+      currentSelectedStoreItem.value =
+          storeItems.isNotEmpty ? storeItems.first : null;
+
+      paymentWays.clear();
+      paymentWays.addAll(indexData.paymentWays);
+      currentSelectedPaymentWay.value =
+          paymentWays.isNotEmpty ? paymentWays.first : null;
+    });
+  }
+
+  onStoreItemClick(StoreItem storeItem) {
+    currentSelectedStoreItem.value = storeItem;
   }
+
+  void onPaymentWayItemClick(PaymentWay paymentWay) {
+    currentSelectedPaymentWay.value = paymentWay;
+  }
+
+  onBuyClick() {}
 }

文件差异内容过多而无法显示
+ 400 - 503
lib/module/store/view.dart


+ 11 - 76
lib/sdk/pay/applepay/apple_pay.dart

@@ -1,38 +1,31 @@
 import 'dart:async';
 
 import 'package:electronic_assistant/sdk/pay/applepay/apple_pay_info.dart';
+import 'package:flutter/widgets.dart';
 import 'package:in_app_purchase/in_app_purchase.dart';
 
-import '../assist/agile_pay_state_info.dart';
-import '../assist/product_type.dart';
+import '../assist/apple_or_google_pay.dart';
 import '../code/agile_pay_code.dart';
 import '../listener/i_agile_pay.dart';
 
-class ApplePay extends AgilePayStateInfo implements IAgilePay {
+class ApplePay extends AppleOrGooglePay implements IAgilePay {
   final ApplePayInfo _payInfo;
-  late final StreamSubscription<List<PurchaseDetails>>
-      _purchaseUpdatedSubscription;
-  late final InAppPurchase _iap;
 
-  final Duration timeout = const Duration(seconds: 15);
+  ApplePay(this._payInfo) : super(_payInfo);
 
-  ApplePay(this._payInfo) {
-    _iap = InAppPurchase.instance;
-    _purchaseUpdatedSubscription =
-        _iap.purchaseStream.listen((purchaseDetailsList) {
-      _listenToPurchaseUpdated(purchaseDetailsList);
-    }, onDone: () {
-      _purchaseUpdatedSubscription.cancel();
-    }, onError: (error) {});
-  }
-
-  void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
+  @override
+  void listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
     for (var purchaseDetails in purchaseDetailsList) {
+      debugPrint(
+          'agilePay-applePay--PurchaseUpdated-> ${purchaseDetails.toString()}');
       if (purchaseDetails.status == PurchaseStatus.pending) {
       } else if (purchaseDetails.status == PurchaseStatus.error) {
         _verifyErrorPurchase(purchaseDetails);
       } else if (purchaseDetails.status == PurchaseStatus.purchased) {
         _verifySuccessPurchase(purchaseDetails);
+      } else if (purchaseDetails.status == PurchaseStatus.canceled) {
+        sendError(AgilePayCode.payCodeCancelError,
+            AgilePayCode.getMessageByCode(AgilePayCode.payCodeCancelError));
       }
     }
   }
@@ -41,9 +34,6 @@ class ApplePay extends AgilePayStateInfo implements IAgilePay {
     if (purchaseDetails.error?.code == 'store_kit_network_error') {
       sendError(AgilePayCode.payCodeNetError,
           AgilePayCode.getMessageByCode(AgilePayCode.payCodeNetError));
-    } else if (purchaseDetails.error?.code == 'store_kit_payment_cancelled') {
-      sendError(AgilePayCode.payCodeCancelError,
-          AgilePayCode.getMessageByCode(AgilePayCode.payCodeCancelError));
     } else {
       sendError(AgilePayCode.payCodeOtherError,
           AgilePayCode.getMessageByCode(AgilePayCode.payCodeOtherError));
@@ -53,59 +43,4 @@ class ApplePay extends AgilePayStateInfo implements IAgilePay {
   void _verifySuccessPurchase(PurchaseDetails purchaseDetails) {
     sendPaySuccess(purchaseDetails.purchaseID);
   }
-
-  @override
-  void pay() async {
-    sendPayBefore();
-    try {
-      final bool isAvailable = await _iap.isAvailable().timeout(timeout);
-      if (!isAvailable) {
-        sendError(AgilePayCode.payCodeNotConnectStore,
-            AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
-        return;
-      }
-      final ProductDetailsResponse response = await InAppPurchase.instance
-          .queryProductDetails({_payInfo.productId});
-      if (response.notFoundIDs.isNotEmpty || response.productDetails.isEmpty) {
-        sendError(
-            AgilePayCode.payCodeProductNotFindStore,
-            AgilePayCode.getMessageByCode(
-                AgilePayCode.payCodeProductNotFindStore));
-        return;
-      }
-      List<ProductDetails> products = response.productDetails;
-      for (var element in products) {
-        bool isSend;
-        if (_payInfo.type == ProductType.consumable) {
-          isSend = await _iap.buyConsumable(
-              purchaseParam: PurchaseParam(productDetails: element));
-        } else {
-          isSend = await _iap.buyNonConsumable(
-              purchaseParam: PurchaseParam(productDetails: element));
-        }
-        if (!isSend) {
-          sendError(
-              AgilePayCode.payCodeRequestSendError,
-              AgilePayCode.getMessageByCode(
-                  AgilePayCode.payCodeRequestSendError));
-          return;
-        }
-        return;
-      }
-    } catch (e) {
-      if (e is TimeoutException) {
-        sendError(AgilePayCode.payCodeNotConnectStore,
-            AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
-        return;
-      }
-      sendError(AgilePayCode.payCodeOtherError,
-          AgilePayCode.getMessageByCode(AgilePayCode.payCodeOtherError));
-      return;
-    }
-  }
-
-  @override
-  void dispose() {
-    _purchaseUpdatedSubscription.cancel();
-  }
 }

+ 3 - 10
lib/sdk/pay/applepay/apple_pay_info.dart

@@ -1,13 +1,6 @@
+import '../assist/apple_or_google_pay_info.dart';
 import '../assist/product_type.dart';
 
-class ApplePayInfo {
-  final String _productId;
-
-  final ProductType _type;
-
-  ApplePayInfo(this._productId, this._type);
-
-  String get productId => _productId;
-
-  ProductType get type => _type;
+class ApplePayInfo extends AppleOrGooglePayInfo {
+  ApplePayInfo(super.productId, super.type);
 }

+ 83 - 0
lib/sdk/pay/assist/apple_or_google_pay.dart

@@ -0,0 +1,83 @@
+import 'dart:async';
+
+import 'package:electronic_assistant/sdk/pay/assist/apple_or_google_pay_info.dart';
+import 'package:electronic_assistant/sdk/pay/assist/product_type.dart';
+import 'package:in_app_purchase/in_app_purchase.dart';
+
+import '../code/agile_pay_code.dart';
+import 'agile_pay_state_info.dart';
+
+abstract class AppleOrGooglePay extends AgilePayStateInfo {
+  final AppleOrGooglePayInfo _payInfo;
+
+  late final StreamSubscription<List<PurchaseDetails>>
+      _purchaseUpdatedSubscription;
+  late final InAppPurchase _iap;
+
+  final Duration timeout = const Duration(seconds: 10);
+
+  AppleOrGooglePay(this._payInfo) {
+    _iap = InAppPurchase.instance;
+    _purchaseUpdatedSubscription =
+        _iap.purchaseStream.listen((purchaseDetailsList) {
+      listenToPurchaseUpdated(purchaseDetailsList);
+    }, onDone: () {
+      _purchaseUpdatedSubscription.cancel();
+    }, onError: (error) {});
+  }
+
+  void pay() async {
+    sendPayBefore();
+    try {
+      final bool isAvailable = await _iap.isAvailable().timeout(timeout);
+      if (!isAvailable) {
+        sendError(AgilePayCode.payCodeNotConnectStore,
+            AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
+        return;
+      }
+      final ProductDetailsResponse response = await InAppPurchase.instance
+          .queryProductDetails({_payInfo.productId});
+      if (response.notFoundIDs.isNotEmpty || response.productDetails.isEmpty) {
+        sendError(
+            AgilePayCode.payCodeProductNotFindStore,
+            AgilePayCode.getMessageByCode(
+                AgilePayCode.payCodeProductNotFindStore));
+        return;
+      }
+      List<ProductDetails> products = response.productDetails;
+      for (var element in products) {
+        bool isSend;
+        if (_payInfo.type == ProductType.consumable) {
+          isSend = await _iap.buyConsumable(
+              purchaseParam: PurchaseParam(productDetails: element));
+        } else {
+          isSend = await _iap.buyNonConsumable(
+              purchaseParam: PurchaseParam(productDetails: element));
+        }
+        if (!isSend) {
+          sendError(
+              AgilePayCode.payCodeRequestSendError,
+              AgilePayCode.getMessageByCode(
+                  AgilePayCode.payCodeRequestSendError));
+          return;
+        }
+        return;
+      }
+    } catch (e) {
+      if (e is TimeoutException) {
+        sendError(AgilePayCode.payCodeNotConnectStore,
+            AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
+        return;
+      }
+      sendError(AgilePayCode.payCodeOtherError,
+          AgilePayCode.getMessageByCode(AgilePayCode.payCodeOtherError));
+      return;
+    }
+  }
+
+  void dispose() {
+    _purchaseUpdatedSubscription.cancel();
+  }
+
+  void listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList);
+}

+ 13 - 0
lib/sdk/pay/assist/apple_or_google_pay_info.dart

@@ -0,0 +1,13 @@
+import 'package:electronic_assistant/sdk/pay/assist/product_type.dart';
+
+class AppleOrGooglePayInfo {
+  final String _productId;
+
+  final ProductType _type;
+
+  AppleOrGooglePayInfo(this._productId, this._type);
+
+  String get productId => _productId;
+
+  ProductType get type => _type;
+}

+ 24 - 14
lib/sdk/pay/wxpay/wechat_pay.dart

@@ -45,20 +45,26 @@ class WechatPay extends AgilePayStateInfo implements IAgilePay {
   void pay() async {
     sendPayBefore();
     try {
-      bool isInstall = await isInstalled();
-      if (isInstall) {
-        try {
-          WechatKitPlatform.instance.pay(
-              appId: _payInfo.appId,
-              partnerId: _payInfo.partnerId,
-              prepayId: _payInfo.prepayId,
-              package: _payInfo.package,
-              nonceStr: _payInfo.noncestr,
-              timeStamp: _payInfo.timestamp,
-              sign: _payInfo.sign);
-        } catch (e) {
-          sendError(AgilePayCode.payCodePayError,
-              AgilePayCode.getMessageByCode(AgilePayCode.payCodePayError));
+      if (await check()) {
+        if (await isInstalled()) {
+          await WechatKitPlatform.instance.registerApp(
+              appId: _payInfo.appId, universalLink: _payInfo.universalLink);
+          try {
+            WechatKitPlatform.instance.pay(
+                appId: _payInfo.appId,
+                partnerId: _payInfo.partnerId,
+                prepayId: _payInfo.prepayId,
+                package: _payInfo.package,
+                nonceStr: _payInfo.noncestr,
+                timeStamp: _payInfo.timestamp,
+                sign: _payInfo.sign);
+          } catch (e) {
+            sendError(AgilePayCode.payCodePayError,
+                AgilePayCode.getMessageByCode(AgilePayCode.payCodePayError));
+          }
+        } else {
+          sendError(AgilePayCode.payCodeWxEnvError,
+              AgilePayCode.getMessageByCode(AgilePayCode.payCodeWxEnvError));
         }
       } else {
         sendError(AgilePayCode.payCodeWxEnvError,
@@ -70,6 +76,10 @@ class WechatPay extends AgilePayStateInfo implements IAgilePay {
     }
   }
 
+  Future<bool> check() async {
+    return WechatKitPlatform.instance.isSupportApi();
+  }
+
   @override
   void dispose() {
     _respSubs.cancel();

+ 7 - 1
lib/sdk/pay/wxpay/wechat_pay_info.dart

@@ -6,9 +6,15 @@ class WechatPayInfo {
   String _noncestr; // 随机字符串
   String _timestamp; // 时间戳
   String _sign; // 签名
+  String? _universalLink;
 
   WechatPayInfo(this._appId, this._partnerId, this._prepayId, this._package,
-      this._noncestr, this._timestamp, this._sign);
+      this._noncestr, this._timestamp, this._sign,
+      {String? universalLink}) {
+    _universalLink = universalLink;
+  }
+
+  String? get universalLink => _universalLink;
 
   String get appId => _appId;
 

+ 10 - 0
lib/utils/expand.dart

@@ -85,3 +85,13 @@ extension DurationFormatting on Duration {
     return [if (inHours > 0) hours, minutes, seconds].join(':');
   }
 }
+
+extension DoubleExtension on double {
+  String toFormattedString(int fractionDigits) {
+    if (this == toInt()) {
+      return toInt().toString();
+    } else {
+      return toStringAsFixed(fractionDigits);
+    }
+  }
+}

+ 2 - 0
lib/utils/http_handler.dart

@@ -5,6 +5,8 @@ import 'package:electronic_assistant/data/consts/error_code.dart';
 import 'package:electronic_assistant/data/repositories/account_repository.dart';
 
 class HttpHandler {
+  HttpHandler._();
+
   static FutureOr<T> Function(BaseResponse<T> value) handle<T>(
       bool allowEmptyData) {
     return (BaseResponse<T> response) {

+ 1 - 1
plugin/gravity_engine/android/build.gradle

@@ -53,7 +53,7 @@ android {
 
     dependencies {
         //flutter
-//        compileOnly files("$flutterSdk/bin/cache/artifacts/engine/android-arm/flutter.jar")
+        compileOnly files("$flutterSdk/bin/cache/artifacts/engine/android-arm/flutter.jar")
 
         //AndroidX
 //        compileOnly "androidx.annotation:annotation:1.8.2"