apple_or_google_pay.dart 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import 'dart:async';
  2. import 'package:clean/sdk/pay/assist/product_type.dart';
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:in_app_purchase/in_app_purchase.dart';
  5. import '../code/agile_pay_code.dart';
  6. import 'agile_pay_state_info.dart';
  7. import 'apple_or_google_pay_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. bool isCheck = false;
  15. AppleOrGooglePay([this._payInfo]) {
  16. _iap = InAppPurchase.instance;
  17. _purchaseUpdatedSubscription =
  18. _iap.purchaseStream.listen((purchaseDetailsList) {
  19. listenToPurchaseUpdated(purchaseDetailsList);
  20. }, onDone: () {
  21. dispose();
  22. }, onError: (error) {});
  23. }
  24. Future<void> check() async {
  25. isCheck = true;
  26. Stream purchaseStream = InAppPurchase.instance.purchaseStream;
  27. purchaseStream.listen((purchaseDetails) async {
  28. for (var purchaseDetail in purchaseDetails) {
  29. if (purchaseDetails.status == PurchaseStatus.pending) {
  30. verifyPendingPurchase(purchaseDetails);
  31. } else {
  32. if (purchaseDetails.status == PurchaseStatus.error) {
  33. } else if (purchaseDetails.status == PurchaseStatus.purchased) {
  34. } else if (purchaseDetails.status == PurchaseStatus.canceled) {
  35. } else if (purchaseDetails.status == PurchaseStatus.restored) {
  36. }
  37. if (purchaseDetails.pendingCompletePurchase) {
  38. await InAppPurchase.instance.completePurchase(purchaseDetails);
  39. dispose();
  40. }
  41. }
  42. }
  43. });
  44. }
  45. Future<void> restore() async {
  46. sendPayBefore();
  47. final bool isAe = await isAvailable();
  48. if (!isAe) {
  49. sendError(AgilePayCode.payCodeNotConnectStore,
  50. AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
  51. return;
  52. }
  53. await InAppPurchase.instance.restorePurchases();
  54. }
  55. void pay() async {
  56. sendPayBefore();
  57. try {
  58. final bool isAe = await isAvailable();
  59. if (!isAe) {
  60. sendError(AgilePayCode.payCodeNotConnectStore,
  61. AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
  62. return;
  63. }
  64. if (_payInfo == null) {
  65. sendError(AgilePayCode.payCodeOrderInfoError,
  66. AgilePayCode.getMessageByCode(AgilePayCode.payCodeOrderInfoError));
  67. return;
  68. }
  69. final ProductDetailsResponse response =
  70. await queryProductDetails({_payInfo.productId});
  71. if (response.notFoundIDs.isNotEmpty || response.productDetails.isEmpty) {
  72. sendError(
  73. AgilePayCode.payCodeProductNotFindStore,
  74. AgilePayCode.getMessageByCode(
  75. AgilePayCode.payCodeProductNotFindStore));
  76. return;
  77. }
  78. List<ProductDetails> products = response.productDetails;
  79. for (var element in products) {
  80. bool isSend;
  81. if (_payInfo.type == ProductType.consumable) {
  82. isSend = await buyConsumable(
  83. purchaseParam: PurchaseParam(
  84. productDetails: element,
  85. applicationUserName: _payInfo.accountToken));
  86. } else {
  87. isSend = await buyNonConsumable(
  88. purchaseParam: PurchaseParam(
  89. productDetails: element,
  90. applicationUserName: _payInfo.accountToken));
  91. }
  92. if (!isSend) {
  93. sendError(
  94. AgilePayCode.payCodeRequestSendError,
  95. AgilePayCode.getMessageByCode(
  96. AgilePayCode.payCodeRequestSendError));
  97. return;
  98. }
  99. return;
  100. }
  101. } catch (e) {
  102. if (e is TimeoutException) {
  103. sendError(AgilePayCode.payCodeNotConnectStore,
  104. AgilePayCode.getMessageByCode(AgilePayCode.payCodeNotConnectStore));
  105. return;
  106. }
  107. sendError(AgilePayCode.payCodeOtherError,
  108. AgilePayCode.getMessageByCode(AgilePayCode.payCodeOtherError));
  109. return;
  110. }
  111. }
  112. Future<bool> isAvailable() {
  113. return _iap.isAvailable().timeout(timeout);
  114. }
  115. Future<ProductDetailsResponse> queryProductDetails(Set<String> identifiers) {
  116. return InAppPurchase.instance.queryProductDetails(identifiers);
  117. }
  118. Future<bool> buyConsumable({required PurchaseParam purchaseParam}) {
  119. return _iap.buyConsumable(purchaseParam: purchaseParam);
  120. }
  121. Future<bool> buyNonConsumable({required PurchaseParam purchaseParam}) {
  122. return _iap.buyNonConsumable(purchaseParam: purchaseParam);
  123. }
  124. void dispose() {
  125. _purchaseUpdatedSubscription.cancel();
  126. }
  127. void listenToPurchaseUpdated(
  128. List<PurchaseDetails> purchaseDetailsList) async {
  129. for (var purchaseDetails in purchaseDetailsList) {
  130. debugPrint(
  131. 'agilePay-purchasePay--PurchaseUpdated-> ${purchaseDetails.toString()}');
  132. if (purchaseDetails.status == PurchaseStatus.pending) {
  133. verifyPendingPurchase(purchaseDetails);
  134. } else {
  135. if (purchaseDetails.status == PurchaseStatus.error) {
  136. verifyErrorPurchase(purchaseDetails);
  137. } else if (purchaseDetails.status == PurchaseStatus.purchased) {
  138. verifySuccessPurchase(purchaseDetails);
  139. } else if (purchaseDetails.status == PurchaseStatus.canceled) {
  140. verifyCancelPurchase(purchaseDetails);
  141. } else if (purchaseDetails.status == PurchaseStatus.restored) {
  142. print("订阅");
  143. }
  144. if (purchaseDetails.pendingCompletePurchase) {
  145. await InAppPurchase.instance.completePurchase(purchaseDetails);
  146. dispose();
  147. }
  148. }
  149. }
  150. }
  151. void verifyPendingPurchase(PurchaseDetails purchaseDetails) {}
  152. void verifyCancelPurchase(PurchaseDetails purchaseDetails) {
  153. sendError(AgilePayCode.payCodeCancelError,
  154. AgilePayCode.getMessageByCode(AgilePayCode.payCodeCancelError));
  155. }
  156. void verifyErrorPurchase(PurchaseDetails purchaseDetails) {
  157. sendError(AgilePayCode.payCodePayError,
  158. AgilePayCode.getMessageByCode(AgilePayCode.payCodePayError));
  159. }
  160. void verifySuccessPurchase(PurchaseDetails purchaseDetails) {
  161. sendPaySuccess(purchaseDetails.verificationData.serverVerificationData);
  162. }
  163. }