apple_or_google_pay.dart 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import 'dart:async';
  2. import 'package:electronic_assistant/sdk/pay/assist/apple_or_google_pay_info.dart';
  3. import 'package:electronic_assistant/sdk/pay/assist/product_type.dart';
  4. import 'package:flutter/cupertino.dart';
  5. import 'package:in_app_purchase/in_app_purchase.dart';
  6. import '../code/agile_pay_code.dart';
  7. import 'agile_pay_state_info.dart';
  8. abstract class AppleOrGooglePay extends AgilePayStateInfo {
  9. final AppleOrGooglePayInfo _payInfo;
  10. late final StreamSubscription<List<PurchaseDetails>>
  11. _purchaseUpdatedSubscription;
  12. late final InAppPurchase _iap;
  13. final Duration timeout = const Duration(seconds: 10);
  14. AppleOrGooglePay(this._payInfo) {
  15. _iap = InAppPurchase.instance;
  16. _purchaseUpdatedSubscription =
  17. _iap.purchaseStream.listen((purchaseDetailsList) {
  18. listenToPurchaseUpdated(purchaseDetailsList);
  19. }, onDone: () {
  20. dispose();
  21. }, onError: (error) {});
  22. }
  23. void pay() async {
  24. sendPayBefore();
  25. try {
  26. final bool isAe = await isAvailable();
  27. if (!isAe) {
  28. sendError(AgilePayCode.payCodeNotConnectStore,
  29. AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
  30. return;
  31. }
  32. final ProductDetailsResponse response =
  33. await queryProductDetails({_payInfo.productId});
  34. if (response.notFoundIDs.isNotEmpty || response.productDetails.isEmpty) {
  35. sendError(
  36. AgilePayCode.payCodeProductNotFindStore,
  37. AgilePayCode.getMessageByCode(
  38. AgilePayCode.payCodeProductNotFindStore));
  39. return;
  40. }
  41. List<ProductDetails> products = response.productDetails;
  42. for (var element in products) {
  43. bool isSend;
  44. if (_payInfo.type == ProductType.consumable) {
  45. isSend = await buyConsumable(
  46. purchaseParam: PurchaseParam(
  47. productDetails: element,
  48. applicationUserName: _payInfo.accountToken));
  49. } else {
  50. isSend = await buyNonConsumable(
  51. purchaseParam: PurchaseParam(
  52. productDetails: element,
  53. applicationUserName: _payInfo.accountToken));
  54. }
  55. if (!isSend) {
  56. sendError(
  57. AgilePayCode.payCodeRequestSendError,
  58. AgilePayCode.getMessageByCode(
  59. AgilePayCode.payCodeRequestSendError));
  60. return;
  61. }
  62. return;
  63. }
  64. } catch (e) {
  65. if (e is TimeoutException) {
  66. sendError(AgilePayCode.payCodeNotConnectStore,
  67. AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
  68. return;
  69. }
  70. sendError(AgilePayCode.payCodeOtherError,
  71. AgilePayCode.getMessageByCode(AgilePayCode.payCodeOtherError));
  72. return;
  73. }
  74. }
  75. Future<bool> isAvailable() {
  76. return _iap.isAvailable().timeout(timeout);
  77. }
  78. Future<ProductDetailsResponse> queryProductDetails(Set<String> identifiers) {
  79. return InAppPurchase.instance.queryProductDetails(identifiers);
  80. }
  81. Future<bool> buyConsumable({required PurchaseParam purchaseParam}) {
  82. return _iap.buyConsumable(purchaseParam: purchaseParam);
  83. }
  84. Future<bool> buyNonConsumable({required PurchaseParam purchaseParam}) {
  85. return _iap.buyNonConsumable(purchaseParam: purchaseParam);
  86. }
  87. void dispose() {
  88. _purchaseUpdatedSubscription.cancel();
  89. }
  90. void listenToPurchaseUpdated(
  91. List<PurchaseDetails> purchaseDetailsList) async {
  92. try {
  93. for (var purchaseDetails in purchaseDetailsList) {
  94. debugPrint(
  95. 'agilePay-purchasePay--PurchaseUpdated-> ${purchaseDetails.toString()}');
  96. if (purchaseDetails.status == PurchaseStatus.pending) {
  97. verifyPendingPurchase(purchaseDetails);
  98. } else {
  99. if (purchaseDetails.status == PurchaseStatus.error) {
  100. verifyErrorPurchase(purchaseDetails);
  101. } else if (purchaseDetails.status == PurchaseStatus.purchased) {
  102. verifySuccessPurchase(purchaseDetails);
  103. } else if (purchaseDetails.status == PurchaseStatus.canceled) {
  104. verifyCancelPurchase(purchaseDetails);
  105. }
  106. if (purchaseDetails.pendingCompletePurchase) {
  107. await InAppPurchase.instance.completePurchase(purchaseDetails);
  108. }
  109. }
  110. }
  111. } catch (e) {
  112. sendError(AgilePayCode.payCodeOtherError,
  113. AgilePayCode.getMessageByCode(AgilePayCode.payCodeOtherError));
  114. } finally {
  115. dispose();
  116. }
  117. }
  118. void verifyPendingPurchase(PurchaseDetails purchaseDetails) {}
  119. void verifyCancelPurchase(PurchaseDetails purchaseDetails) {
  120. sendError(AgilePayCode.payCodeCancelError,
  121. AgilePayCode.getMessageByCode(AgilePayCode.payCodeCancelError));
  122. }
  123. void verifyErrorPurchase(PurchaseDetails purchaseDetails) {
  124. sendError(AgilePayCode.payCodePayError,
  125. AgilePayCode.getMessageByCode(AgilePayCode.payCodePayError));
  126. }
  127. void verifySuccessPurchase(PurchaseDetails purchaseDetails) {
  128. sendPaySuccess(purchaseDetails.verificationData.serverVerificationData);
  129. }
  130. }