From 2d060cb45ec655aa1cc21ad3ad23bdd17515da64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Wed, 25 Sep 2024 17:04:00 +0800 Subject: [PATCH 01/18] =?UTF-8?q?=E8=A6=86=E7=9B=96in=5Fapp=5Fpurchase?= =?UTF-8?q?=E5=BA=93=E5=88=B0=E6=9C=80=E6=96=B0=E7=89=88=E6=9C=AC3.1.11?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- packages/in_app_purchase/in_app_purchase/CHANGELOG.md | 4 ++++ .../in_app_purchase/in_app_purchase/lib/in_app_purchase.dart | 2 +- packages/in_app_purchase/in_app_purchase/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md index 652ebc3b4..c9dd5bd0f 100644 --- a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.1.11 + +* Updates documentation reference of `finishPurchase` to `completePurchase`. + ## 3.1.10 * Updates example code for current versions of Flutter. diff --git a/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart b/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart index 64e0095dc..9ca7232fb 100644 --- a/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart +++ b/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart @@ -195,7 +195,7 @@ class InAppPurchase implements InAppPurchasePlatformAdditionProvider { /// Restored purchases are delivered through the [purchaseStream] with a /// status of [PurchaseStatus.restored]. You should listen for these purchases, /// validate their receipts, deliver the content and mark the purchase complete - /// by calling the [finishPurchase] method for each purchase. + /// by calling the [completePurchase] method for each purchase. /// /// This does not return consumed products. If you want to restore unused /// consumable products, you need to persist consumable product information diff --git a/packages/in_app_purchase/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/pubspec.yaml index ba95a3212..9426a86be 100644 --- a/packages/in_app_purchase/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase description: A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store and Google Play. repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 3.1.10 +version: 3.1.11 environment: sdk: ">=2.19.0 <4.0.0" -- Gitee From 6c3c5a5073b041f8cb0992a7d81122eb35ae8e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Wed, 25 Sep 2024 17:23:56 +0800 Subject: [PATCH 02/18] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E9=80=82=E9=85=8DOH?= =?UTF-8?q?=E7=9A=84in=5Fapp=5Fpurchase=E5=BA=93=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- OAT.xml | 14 +- .../in_app_purchase/in_app_purchase/README.md | 17 + .../in_app_purchase/example/lib/main.dart | 32 +- .../in_app_purchase/example/ohos/.gitignore | 19 + .../example/ohos/AppScope/app.json5 | 10 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../example/ohos/build-profile.json5 | 27 ++ .../example/ohos/entry/.gitignore | 7 + .../example/ohos/entry/build-profile.json5 | 29 ++ .../example/ohos/entry/hvigorfile.ts | 17 + .../example/ohos/entry/oh-package.json5 | 12 + .../main/ets/entryability/EntryAbility.ets | 24 + .../ohos/entry/src/main/ets/pages/Index.ets | 38 ++ .../example/ohos/entry/src/main/module.json5 | 53 +++ .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../main/resources/en_US/element/string.json | 16 + .../main/resources/zh_CN/element/string.json | 16 + .../src/ohosTest/ets/test/Ability.test.ets | 50 +++ .../entry/src/ohosTest/ets/test/List.test.ets | 20 + .../ohosTest/ets/testability/TestAbility.ets | 63 +++ .../ohosTest/ets/testability/pages/Index.ets | 49 +++ .../ets/testrunner/OpenHarmonyTestRunner.ts | 64 +++ .../ohos/entry/src/ohosTest/module.json5 | 51 +++ .../resources/base/element/color.json | 8 + .../resources/base/element/string.json | 16 + .../ohosTest/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/test_pages.json | 5 + .../example/ohos/hvigor/hvigor-config.json5 | 20 + .../example/ohos/hvigorfile.ts | 21 + .../example/ohos/oh-package.json5 | 21 + .../in_app_purchase/example/pubspec.yaml | 5 +- .../in_app_purchase/lib/in_app_purchase.dart | 3 + .../in_app_purchase/pubspec.yaml | 6 + .../in_app_purchase_ohos/AUTHORS | 67 +++ .../in_app_purchase_ohos/CHANGELOG.md | 3 + .../in_app_purchase_ohos/LICENSE | 25 ++ .../in_app_purchase_ohos/README.md | 26 ++ .../in_app_purchase_ohos/build.yaml | 8 + .../in_app_purchase_ohos/example/README.md | 9 + .../in_app_purchase_test.dart | 20 + .../example/lib/consumable_store.dart | 52 +++ .../example/lib/main.dart | 414 ++++++++++++++++++ .../example/ohos/.gitignore | 19 + .../example/ohos/AppScope/app.json5 | 10 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../example/ohos/build-profile.json5 | 27 ++ .../example/ohos/entry/.gitignore | 7 + .../example/ohos/entry/build-profile.json5 | 29 ++ .../example/ohos/entry/hvigorfile.ts | 17 + .../example/ohos/entry/oh-package.json5 | 13 + .../main/ets/entryability/EntryAbility.ets | 24 + .../ohos/entry/src/main/ets/pages/Index.ets | 38 ++ .../example/ohos/entry/src/main/module.json5 | 53 +++ .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../main/resources/en_US/element/string.json | 16 + .../main/resources/zh_CN/element/string.json | 16 + .../src/ohosTest/ets/test/Ability.test.ets | 50 +++ .../entry/src/ohosTest/ets/test/List.test.ets | 20 + .../ohosTest/ets/testability/TestAbility.ets | 63 +++ .../ohosTest/ets/testability/pages/Index.ets | 49 +++ .../ets/testrunner/OpenHarmonyTestRunner.ts | 64 +++ .../ohos/entry/src/ohosTest/module.json5 | 51 +++ .../resources/base/element/color.json | 8 + .../resources/base/element/string.json | 16 + .../ohosTest/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/test_pages.json | 5 + .../example/ohos/hvigor/hvigor-config.json5 | 20 + .../example/ohos/hvigorfile.ts | 21 + .../example/ohos/oh-package.json5 | 22 + .../in_app_purchase_ohos/example/pubspec.yaml | 33 ++ .../lib/iap_kit_wrappers.dart | 9 + .../lib/in_app_purchase_ohos.dart | 7 + .../in_app_purchase_ohos/lib/src/channel.dart | 9 + .../lib/src/iap_kit_wrappers/README.md | 5 + .../src/iap_kit_wrappers/enum_converters.dart | 143 ++++++ .../iap_kit_wrappers/enum_converters.g.dart | 42 ++ .../ik_payment_queue_wrapper.dart | 264 +++++++++++ .../ik_payment_queue_wrapper.g.dart | 50 +++ .../ik_payment_transaction_wrappers.dart | 172 ++++++++ .../ik_payment_transaction_wrappers.g.dart | 36 ++ .../iap_kit_wrappers/ik_product_wrapper.dart | 279 ++++++++++++ .../ik_product_wrapper.g.dart | 69 +++ .../iap_kit_wrappers/ik_receipt_manager.dart | 18 + .../iap_kit_wrappers/ik_request_maker.dart | 46 ++ .../src/in_app_purchase_ohos_platform.dart | 219 +++++++++ ...n_app_purchase_ohos_platform_addition.dart | 33 ++ .../types/app_gallery_product_details.dart | 43 ++ .../types/app_gallery_purchase_details.dart | 79 ++++ .../src/types/app_gallery_purchase_param.dart | 18 + .../lib/src/types/types.dart | 7 + .../in_app_purchase_ohos/ohos/.gitignore | 6 + .../ohos/BuildProfile.ets | 32 ++ .../in_app_purchase_ohos/ohos/Index.ets | 17 + .../ohos/build-profile.json5 | 31 ++ .../ohos/consumer-rules.txt | 0 .../in_app_purchase_ohos/ohos/hvigorfile.ts | 21 + .../ohos/obfuscation-rules.txt | 23 + .../ohos/oh-package.json5 | 11 + .../ohos/src/main/ets/common/JWTUtil.ts | 49 +++ .../ohos/src/main/ets/common/TsUtil.ts | 24 + .../ets/components/InAppPurchasePlugin.ets | 69 +++ .../ets/components/MethodCallHandlerImpl.ets | 288 ++++++++++++ .../src/main/ets/components/MethodNames.ets | 26 ++ .../src/main/ets/components/ProductType.ets | 22 + .../src/main/ets/components/PurchaseData.ets | 20 + .../ets/components/PurchaseOrderPayload.ets | 50 +++ .../main/ets/components/TransactionState.ts | 23 + .../ohos/src/main/module.json5 | 11 + .../main/resources/base/element/string.json | 8 + .../main/resources/en_US/element/string.json | 8 + .../main/resources/zh_CN/element/string.json | 8 + .../src/ohosTest/ets/test/Ability.test.ets | 50 +++ .../ohos/src/ohosTest/ets/test/List.test.ets | 20 + .../ohos/src/ohosTest/module.json5 | 13 + .../ohos/src/test/List.test.ets | 20 + .../ohos/src/test/LocalUnit.test.ets | 48 ++ .../in_app_purchase_ohos/pubspec.yaml | 35 ++ 125 files changed, 4588 insertions(+), 15 deletions(-) create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/.gitignore create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/app.json5 create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/resources/base/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/resources/base/media/app_icon.png create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/build-profile.json5 create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/.gitignore create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/build-profile.json5 create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/hvigorfile.ts create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/oh-package.json5 create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/ets/pages/Index.ets create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/module.json5 create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/resources/base/element/color.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/resources/base/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/resources/base/media/icon.png create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/resources/base/profile/main_pages.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/resources/en_US/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/main/resources/zh_CN/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/test/List.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/module.json5 create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/color.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/media/icon.png create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/hvigor/hvigor-config.json5 create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/hvigorfile.ts create mode 100644 packages/in_app_purchase/in_app_purchase/example/ohos/oh-package.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/AUTHORS create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/CHANGELOG.md create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/LICENSE create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/README.md create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/build.yaml create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/README.md create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/integration_test/in_app_purchase_test.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/lib/consumable_store.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/lib/main.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/.gitignore create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/app.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/resources/base/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/resources/base/media/app_icon.png create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/build-profile.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/.gitignore create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/build-profile.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/hvigorfile.ts create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/oh-package.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/pages/Index.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/module.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/resources/base/element/color.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/resources/base/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/resources/base/media/icon.png create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/resources/en_US/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/module.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/hvigor/hvigor-config.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/hvigorfile.ts create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/oh-package.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/pubspec.yaml create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/iap_kit_wrappers.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/in_app_purchase_ohos.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/channel.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.g.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.g.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.g.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.g.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_receipt_manager.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_request_maker.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform_addition.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_product_details.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_details.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_param.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/types.dart create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/.gitignore create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/BuildProfile.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/Index.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/build-profile.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/consumer-rules.txt create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/hvigorfile.ts create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/obfuscation-rules.txt create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/oh-package.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/TsUtil.ts create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/InAppPurchasePlugin.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodCallHandlerImpl.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodNames.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseData.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseOrderPayload.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/TransactionState.ts create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/module.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/base/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/en_US/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/zh_CN/element/string.json create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/Ability.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/List.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/module.json5 create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/List.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/LocalUnit.test.ets create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/pubspec.yaml diff --git a/OAT.xml b/OAT.xml index e6853d4d5..b475178b8 100644 --- a/OAT.xml +++ b/OAT.xml @@ -85,8 +85,8 @@ - - + + @@ -286,6 +286,16 @@ + + + + + + + + + + diff --git a/packages/in_app_purchase/in_app_purchase/README.md b/packages/in_app_purchase/in_app_purchase/README.md index 59cb2c2dd..f33c4d30c 100644 --- a/packages/in_app_purchase/in_app_purchase/README.md +++ b/packages/in_app_purchase/in_app_purchase/README.md @@ -5,6 +5,23 @@ A storefront-independent API for purchases in Flutter apps. This plugin supports in-app purchases (_IAP_) through an _underlying store_, which can be the App Store (on iOS and macOS) or Google Play (on Android). + + +#### ohos ˵ + +ohos ƽ̨Ŀǰӿڣ + +* purchaseStream +* isAvailable +* queryProductDetails +* buyNonConsumable +* buyConsumable +* completePurchase + +Ŀǰ֧ûӦóдָֻ֧̣֧ȹܣδ + + + | | Android | iOS | macOS | |-------------|---------|-------|--------| | **Support** | SDK 16+ | 11.0+ | 10.15+ | diff --git a/packages/in_app_purchase/in_app_purchase/example/lib/main.dart b/packages/in_app_purchase/in_app_purchase/example/lib/main.dart index 5afb52ac9..c60f060c1 100644 --- a/packages/in_app_purchase/in_app_purchase/example/lib/main.dart +++ b/packages/in_app_purchase/in_app_purchase/example/lib/main.dart @@ -92,6 +92,7 @@ class _MyAppState extends State<_MyApp> { final ProductDetailsResponse productDetailResponse = await _inAppPurchase.queryProductDetails(_kProductIds.toSet()); + var productDetails = productDetailResponse.productDetails; if (productDetailResponse.error != null) { setState(() { _queryProductError = productDetailResponse.error!.message; @@ -149,13 +150,18 @@ class _MyAppState extends State<_MyApp> { if (_queryProductError == null) { stack.add( ListView( - children: [ - _buildConnectionCheckTile(), - _buildProductList(), - _buildConsumableBox(), - _buildRestoreButton(), - ], - ), + children: Platform.operatingSystem == 'ohos' + ? [ + _buildConnectionCheckTile(), + _buildProductList(), + _buildConsumableBox(), + ] + : [ + _buildConnectionCheckTile(), + _buildProductList(), + _buildConsumableBox(), + _buildRestoreButton(), + ]), ); } else { stack.add(Center( @@ -164,7 +170,7 @@ class _MyAppState extends State<_MyApp> { } if (_purchasePending) { stack.add( - const Stack( + Stack( children: [ Opacity( opacity: 0.3, @@ -259,10 +265,12 @@ class _MyAppState extends State<_MyApp> { subtitle: Text( productDetails.description, ), - trailing: previousPurchase != null && Platform.isIOS - ? IconButton( - onPressed: () => confirmPriceChange(context), - icon: const Icon(Icons.upgrade)) + trailing: previousPurchase != null + ? Platform.isIOS + ? IconButton( + onPressed: () => confirmPriceChange(context), + icon: const Icon(Icons.upgrade)) + : SizedBox.shrink() : TextButton( style: TextButton.styleFrom( backgroundColor: Colors.green[800], diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/.gitignore b/packages/in_app_purchase/in_app_purchase/example/ohos/.gitignore new file mode 100644 index 000000000..6ca13b317 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/.gitignore @@ -0,0 +1,19 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +*.har +**/BuildProfile.ets +**/oh-package-lock.json5 + +**/src/main/resources/rawfile/flutter_assets/ +**/libs/arm64-v8a/libapp.so +**/libs/arm64-v8a/libflutter.so +**/libs/arm64-v8a/libvmservice_snapshot.so diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/app.json5 b/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/app.json5 new file mode 100644 index 000000000..a13c8bfdc --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.example.in_app_purchase_ohos", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/resources/base/element/string.json b/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/resources/base/element/string.json new file mode 100644 index 000000000..810f4a362 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "example" + } + ] +} diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/resources/base/media/app_icon.png b/packages/in_app_purchase/in_app_purchase/example/ohos/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 000000000..cef0447cd --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 000000000..1def08f2e --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/module.json5 b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/module.json5 new file mode 100644 index 000000000..fab77ce2e --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/module.json5 @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/color.json b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 000000000..3c712962d --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/string.json b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 000000000..65d8fa5a7 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/media/icon.png b/packages/in_app_purchase/in_app_purchase/example/ohos/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 + +Google Inc. +The Chromium Authors +German Saprykin +Benjamin Sauer +larsenthomasj@gmail.com +Ali Bitek +Pol Batlló +Anatoly Pulyaevskiy +Hayden Flinner +Stefano Rodriguez +Salvatore Giordano +Brian Armstrong +Paul DeMarco +Fabricio Nogueira +Simon Lightfoot +Ashton Thomas +Thomas Danner +Diego Velásquez +Hajime Nakamura +Tuyển Vũ Xuân +Miguel Ruivo +Sarthak Verma +Mike Diarmid +Invertase +Elliot Hesp +Vince Varga +Aawaz Gyawali +EUI Limited +Katarina Sheremet +Thomas Stockx +Sarbagya Dhaubanjar +Ozkan Eksi +Rishab Nayak +ko2ic +Jonathan Younger +Jose Sanchez +Debkanchan Samadder +Audrius Karosevicius +Lukasz Piliszczuk +SoundReply Solutions GmbH +Rafal Wachol +Pau Picas +Christian Weder +Alexandru Tuca +Christian Weder +Rhodes Davis Jr. +Luigi Agosti +Quentin Le Guennec +Koushik Ravikumar +Nissim Dsilva +Giancarlo Rocha +Ryo Miyake +Théo Champion +Kazuki Yamaguchi +Eitan Schwartz +Chris Rutkowski +Juan Alvarez +Aleksandr Yurkovskiy +Anton Borries +Alex Li +Rahul Raj <64.rahulraj@gmail.com> +Maurits van Beusekom diff --git a/packages/in_app_purchase/in_app_purchase_ohos/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_ohos/CHANGELOG.md new file mode 100644 index 000000000..4fac17c46 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0 + +* Initial open-source release. diff --git a/packages/in_app_purchase/in_app_purchase_ohos/LICENSE b/packages/in_app_purchase/in_app_purchase_ohos/LICENSE new file mode 100644 index 000000000..c6823b81e --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/in_app_purchase/in_app_purchase_ohos/README.md b/packages/in_app_purchase/in_app_purchase_ohos/README.md new file mode 100644 index 000000000..7d43fcbc2 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/README.md @@ -0,0 +1,26 @@ +# in\_app\_purchase\_ohos + +The Ohos implementation of [`in_app_purchase`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `in_app_purchase` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +## Contributing + +This plugin uses +[json_serializable](https://pub.dev/packages/json_serializable) for the +many data structs passed between the underlying platform layers and Dart. After +editing any of the serialized data structs, rebuild the serializers by running +`flutter packages pub run build_runner build --delete-conflicting-outputs`. +`flutter packages pub run build_runner watch --delete-conflicting-outputs` will +watch the filesystem for changes. + +If you would like to contribute to the plugin, check out our +[contribution guide](https://github.com/flutter/packages/blob/main/CONTRIBUTING.md). + + +[1]: https://pub.dev/packages/in_app_purchase +[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin diff --git a/packages/in_app_purchase/in_app_purchase_ohos/build.yaml b/packages/in_app_purchase/in_app_purchase_ohos/build.yaml new file mode 100644 index 000000000..651a557fc --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/build.yaml @@ -0,0 +1,8 @@ +# See https://pub.dev/packages/build_config +targets: + $default: + builders: + json_serializable: + options: + any_map: true + create_to_json: false diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/README.md b/packages/in_app_purchase/in_app_purchase_ohos/example/README.md new file mode 100644 index 000000000..96b8bb17d --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/integration_test/in_app_purchase_test.dart b/packages/in_app_purchase/in_app_purchase_ohos/example/integration_test/in_app_purchase_test.dart new file mode 100644 index 000000000..28f99f748 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/integration_test/in_app_purchase_test.dart @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:in_app_purchase_ohos/in_app_purchase_ohos.dart'; +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('Can create InAppPurchaseStoreKit instance', + (WidgetTester tester) async { + InAppPurchaseOhosPlatform.registerPlatform(); + final InAppPurchasePlatform androidPlatform = + InAppPurchasePlatform.instance; + expect(androidPlatform, isNotNull); + }); +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/lib/consumable_store.dart b/packages/in_app_purchase/in_app_purchase_ohos/example/lib/consumable_store.dart new file mode 100644 index 000000000..f8791d3b1 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/lib/consumable_store.dart @@ -0,0 +1,52 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'package:shared_preferences/shared_preferences.dart'; + +// ignore: avoid_classes_with_only_static_members +/// A store of consumable items. +/// +/// This is a development prototype that stores consumables in the shared +/// preferences. Do not use this in real world apps. +class ConsumableStore { + static const String _kPrefKey = 'consumables'; + static Future _writes = Future.value(); + + /// Adds a consumable with ID `id` to the store. + /// + /// The consumable is only added after the returned Future is complete. + static Future save(String id) { + _writes = _writes.then((void _) => _doSave(id)); + return _writes; + } + + /// Consumes a consumable with ID `id` from the store. + /// + /// The consumable was only consumed after the returned Future is complete. + static Future consume(String id) { + _writes = _writes.then((void _) => _doConsume(id)); + return _writes; + } + + /// Returns the list of consumables from the store. + static Future> load() async { + return (await SharedPreferences.getInstance()).getStringList(_kPrefKey) ?? + []; + } + + static Future _doSave(String id) async { + final List cached = await load(); + final SharedPreferences prefs = await SharedPreferences.getInstance(); + cached.add(id); + await prefs.setStringList(_kPrefKey, cached); + } + + static Future _doConsume(String id) async { + final List cached = await load(); + final SharedPreferences prefs = await SharedPreferences.getInstance(); + cached.remove(id); + await prefs.setStringList(_kPrefKey, cached); + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/lib/main.dart b/packages/in_app_purchase/in_app_purchase_ohos/example/lib/main.dart new file mode 100644 index 000000000..d79a39189 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/lib/main.dart @@ -0,0 +1,414 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:in_app_purchase_ohos/in_app_purchase_ohos.dart'; +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; + +import 'consumable_store.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + + // When using the Ohos plugin directly it is mandatory to register + // the plugin as default instance as part of initializing the app. + InAppPurchaseOhosPlatform.registerPlatform(); + + runApp(_MyApp()); +} + +const String _kConsumableId = 'consumable'; +const String _kUpgradeId = 'upgrade'; +const String _kSilverSubscriptionId = 'subscription_silver'; +const String _kGoldSubscriptionId = 'subscription_gold'; +const List _kProductIds = [ + _kConsumableId, + _kUpgradeId, + _kSilverSubscriptionId, + _kGoldSubscriptionId, +]; + +class _MyApp extends StatefulWidget { + @override + State<_MyApp> createState() => _MyAppState(); +} + +class _MyAppState extends State<_MyApp> { + final InAppPurchaseOhosPlatform _iapStoreKitPlatform = + InAppPurchasePlatform.instance as InAppPurchaseOhosPlatform; + late StreamSubscription> _subscription; + List _notFoundIds = []; + List _products = []; + List _purchases = []; + List _consumables = []; + bool _isAvailable = false; + bool _purchasePending = false; + bool _loading = true; + String? _queryProductError; + + @override + void initState() { + final Stream> purchaseUpdated = + _iapStoreKitPlatform.purchaseStream; + _subscription = + purchaseUpdated.listen((List purchaseDetailsList) { + _listenToPurchaseUpdated(purchaseDetailsList); + }, onDone: () { + _subscription.cancel(); + }, onError: (Object error) { + // handle error here. + }); + + initStoreInfo(); + super.initState(); + } + + Future initStoreInfo() async { + final bool isAvailable = await _iapStoreKitPlatform.isAvailable(); + if (!isAvailable) { + setState(() { + _isAvailable = isAvailable; + _products = []; + _purchases = []; + _notFoundIds = []; + _consumables = []; + _purchasePending = false; + _loading = false; + }); + return; + } + final ProductDetailsResponse productDetailResponse = + await _iapStoreKitPlatform.queryProductDetails(_kProductIds.toSet()); + if (productDetailResponse.error != null) { + setState(() { + _queryProductError = productDetailResponse.error!.message; + _isAvailable = isAvailable; + _products = productDetailResponse.productDetails; + _purchases = []; + _notFoundIds = productDetailResponse.notFoundIDs; + _consumables = []; + _purchasePending = false; + _loading = false; + }); + return; + } + + if (productDetailResponse.productDetails.isEmpty) { + setState(() { + _queryProductError = null; + _isAvailable = isAvailable; + _products = productDetailResponse.productDetails; + _purchases = []; + _notFoundIds = productDetailResponse.notFoundIDs; + _consumables = []; + _purchasePending = false; + _loading = false; + }); + return; + } + + final List consumables = await ConsumableStore.load(); + setState(() { + _isAvailable = isAvailable; + _products = productDetailResponse.productDetails; + _notFoundIds = productDetailResponse.notFoundIDs; + _consumables = consumables; + _purchasePending = false; + _loading = false; + }); + } + + @override + void dispose() { + _subscription.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final List stack = []; + if (_queryProductError == null) { + stack.add( + ListView( + children: [ + _buildConnectionCheckTile(), + _buildProductList(), + _buildConsumableBox(), + // _buildRestoreButton(), + ], + ), + ); + } else { + stack.add(Center( + child: Text(_queryProductError!), + )); + } + if (_purchasePending) { + stack.add( + // const Stack( + Stack( + children: [ + Opacity( + opacity: 0.3, + child: ModalBarrier(dismissible: false, color: Colors.grey), + ), + Center( + child: CircularProgressIndicator(), + ), + ], + ), + ); + } + + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('IAP Example'), + ), + body: Stack( + children: stack, + ), + ), + ); + } + + Card _buildConnectionCheckTile() { + if (_loading) { + return const Card(child: ListTile(title: Text('Trying to connect...'))); + } + final Widget storeHeader = ListTile( + leading: Icon(_isAvailable ? Icons.check : Icons.block, + color: _isAvailable + ? Colors.green + : ThemeData.light().colorScheme.error), + title: + Text('The store is ${_isAvailable ? 'available' : 'unavailable'}.'), + ); + final List children = [storeHeader]; + + if (!_isAvailable) { + children.addAll([ + const Divider(), + ListTile( + title: Text('Not connected', + style: TextStyle(color: ThemeData.light().colorScheme.error)), + subtitle: const Text( + 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.'), + ), + ]); + } + return Card(child: Column(children: children)); + } + + Card _buildProductList() { + if (_loading) { + return const Card( + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching products...'))); + } + if (!_isAvailable) { + return const Card(); + } + const ListTile productHeader = ListTile(title: Text('Products for Sale')); + final List productList = []; + if (_notFoundIds.isNotEmpty) { + productList.add(ListTile( + title: Text('[${_notFoundIds.join(", ")}] not found', + style: TextStyle(color: ThemeData.light().colorScheme.error)), + subtitle: const Text( + 'This app needs special configuration to run. Please see example/README.md for instructions.'))); + } + + // This loading previous purchases code is just a demo. Please do not use this as it is. + // In your app you should always verify the purchase data using the `verificationData` inside the [PurchaseDetails] object before trusting it. + // We recommend that you use your own server to verify the purchase data. + final Map purchases = + Map.fromEntries( + _purchases.map((PurchaseDetails purchase) { + if (purchase.pendingCompletePurchase) { + _iapStoreKitPlatform.completePurchase(purchase); + } + return MapEntry(purchase.productID, purchase); + })); + productList.addAll(_products.map( + (ProductDetails productDetails) { + final PurchaseDetails? previousPurchase = purchases[productDetails.id]; + return ListTile( + title: Text( + productDetails.title, + ), + subtitle: Text( + productDetails.description, + ), + trailing: previousPurchase != null + ? SizedBox.shrink() + : TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + foregroundColor: Colors.white, + ), + onPressed: () { + final PurchaseParam purchaseParam = PurchaseParam( + productDetails: productDetails, + ); + if (productDetails.id == _kConsumableId) { + _iapStoreKitPlatform.buyConsumable( + purchaseParam: purchaseParam); + } else { + _iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam); + } + }, + child: Text(productDetails.price), + )); + }, + )); + + return Card( + child: Column( + children: [productHeader, const Divider()] + productList)); + } + + Card _buildConsumableBox() { + if (_loading) { + return const Card( + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching consumables...'))); + } + if (!_isAvailable || _notFoundIds.contains(_kConsumableId)) { + return const Card(); + } + const ListTile consumableHeader = + ListTile(title: Text('Purchased consumables')); + final List tokens = _consumables.map((String id) { + return GridTile( + child: IconButton( + icon: const Icon( + Icons.stars, + size: 42.0, + color: Colors.orange, + ), + splashColor: Colors.yellowAccent, + onPressed: () => consume(id), + ), + ); + }).toList(); + return Card( + child: Column(children: [ + consumableHeader, + const Divider(), + GridView.count( + crossAxisCount: 5, + shrinkWrap: true, + padding: const EdgeInsets.all(16.0), + children: tokens, + ) + ])); + } + + Widget _buildRestoreButton() { + if (_loading) { + return Container(); + } + + return Padding( + padding: const EdgeInsets.all(4.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + style: TextButton.styleFrom( + backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: Colors.white, + ), + onPressed: () => _iapStoreKitPlatform.restorePurchases(), + child: const Text('Restore purchases'), + ), + ], + ), + ); + } + + Future consume(String id) async { + await ConsumableStore.consume(id); + final List consumables = await ConsumableStore.load(); + setState(() { + _consumables = consumables; + }); + } + + void showPendingUI() { + setState(() { + _purchasePending = true; + }); + } + + Future deliverProduct(PurchaseDetails purchaseDetails) async { + // IMPORTANT!! Always verify purchase details before delivering the product. + if (purchaseDetails.productID == _kConsumableId) { + await ConsumableStore.save(purchaseDetails.purchaseID!); + final List consumables = await ConsumableStore.load(); + setState(() { + _purchasePending = false; + _consumables = consumables; + }); + } else { + setState(() { + _purchases.add(purchaseDetails); + _purchasePending = false; + }); + } + } + + void handleError(IAPError error) { + setState(() { + _purchasePending = false; + }); + } + + Future _verifyPurchase(PurchaseDetails purchaseDetails) { + // IMPORTANT!! Always verify a purchase before delivering the product. + // For the purpose of an example, we directly return true. + return Future.value(true); + } + + void _handleInvalidPurchase(PurchaseDetails purchaseDetails) { + // handle invalid purchase here if _verifyPurchase` failed. + } + + void _listenToPurchaseUpdated(List purchaseDetailsList) { + purchaseDetailsList.forEach(_handleReportedPurchaseState); + } + + Future _handleReportedPurchaseState( + PurchaseDetails purchaseDetails) async { + print('InAppPurchasePlugin purchaseDetails.status =$purchaseDetails'); + if (purchaseDetails.status == PurchaseStatus.pending) { + showPendingUI(); + } else { + if (purchaseDetails.status == PurchaseStatus.error) { + handleError(purchaseDetails.error!); + } else if (purchaseDetails.status == PurchaseStatus.purchased || + purchaseDetails.status == PurchaseStatus.restored) { + final bool valid = await _verifyPurchase(purchaseDetails); + if (valid) { + await deliverProduct(purchaseDetails); + } else { + _handleInvalidPurchase(purchaseDetails); + return; + } + }else if(purchaseDetails.status == PurchaseStatus.canceled){ + + } + + if (purchaseDetails.pendingCompletePurchase) { + await _iapStoreKitPlatform.completePurchase(purchaseDetails); + } + } + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/.gitignore b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/.gitignore new file mode 100644 index 000000000..6ca13b317 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/.gitignore @@ -0,0 +1,19 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +*.har +**/BuildProfile.ets +**/oh-package-lock.json5 + +**/src/main/resources/rawfile/flutter_assets/ +**/libs/arm64-v8a/libapp.so +**/libs/arm64-v8a/libflutter.so +**/libs/arm64-v8a/libvmservice_snapshot.so diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/app.json5 b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/app.json5 new file mode 100644 index 000000000..a13c8bfdc --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.example.in_app_purchase_ohos", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/resources/base/element/string.json b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/resources/base/element/string.json new file mode 100644 index 000000000..810f4a362 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "example" + } + ] +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/resources/base/media/app_icon.png b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 000000000..cef0447cd --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 000000000..1def08f2e --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/module.json5 b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/module.json5 new file mode 100644 index 000000000..fab77ce2e --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/module.json5 @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 000000000..3c712962d --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 000000000..65d8fa5a7 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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.19.0 <4.0.0" + flutter: ">=3.7.0" + +dependencies: + flutter: + sdk: flutter + in_app_purchase_ohos: + # When depending on this package from a real application you should use: + # in_app_purchase_ohos: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + in_app_purchase_platform_interface: ^1.0.0 + shared_preferences: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + path: packages/shared_preferences/shared_preferences + +dev_dependencies: + # build_runner: ^2.4.5 + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/iap_kit_wrappers.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/iap_kit_wrappers.dart new file mode 100644 index 000000000..eade8d181 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/iap_kit_wrappers.dart @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export 'src/iap_kit_wrappers/ik_payment_queue_wrapper.dart'; +export 'src/iap_kit_wrappers/ik_payment_transaction_wrappers.dart'; +export 'src/iap_kit_wrappers/ik_product_wrapper.dart'; +export 'src/iap_kit_wrappers/ik_receipt_manager.dart'; +export 'src/iap_kit_wrappers/ik_request_maker.dart'; diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/in_app_purchase_ohos.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/in_app_purchase_ohos.dart new file mode 100644 index 000000000..bee9e1c9a --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/in_app_purchase_ohos.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export 'src/in_app_purchase_ohos_platform.dart'; +export 'src/in_app_purchase_ohos_platform_addition.dart'; +export 'src/types/types.dart'; diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/channel.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/channel.dart new file mode 100644 index 000000000..c8b9d647a --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/channel.dart @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; + +/// Method channel for the plugin's platform<-->Dart calls. +const MethodChannel channel = + MethodChannel('plugins.flutter.io/in_app_purchase'); \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md new file mode 100644 index 000000000..f861c653b --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md @@ -0,0 +1,5 @@ +# iap_kit_wrappers + +This exposes Dart endpoints through to the +[IAPKit](https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/iap-iap-V5) APIs. Can be used +as an alternative to [in_app_purchase](../in_app_purchase/README.md). \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.dart new file mode 100644 index 000000000..76e193235 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.dart @@ -0,0 +1,143 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; +import 'package:json_annotation/json_annotation.dart'; + +import '../../iap_kit_wrappers.dart'; + +part 'enum_converters.g.dart'; + +/// Serializer for [IKPaymentTransactionStateWrapper]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@IKTransactionStatusConverter()`. +class IKTransactionStatusConverter + implements JsonConverter { + /// Default const constructor. + const IKTransactionStatusConverter(); + + @override + IKPaymentTransactionStateWrapper fromJson(int? json) { + if (json == null) { + return IKPaymentTransactionStateWrapper.unspecified; + } + return $enumDecode( + _$IKPaymentTransactionStateWrapperEnumMap + .cast(), + json); + } + + /// Converts an [IKPaymentTransactionStateWrapper] to a [PurchaseStatus]. + PurchaseStatus toPurchaseStatus( + IKPaymentTransactionStateWrapper object, IKError? error) { + print('MethodCallHandlerImpl toPurchaseStatus. $object'); + switch (object) { + case IKPaymentTransactionStateWrapper.purchasing: + case IKPaymentTransactionStateWrapper.deferred: + return PurchaseStatus.pending; + case IKPaymentTransactionStateWrapper.purchased: + return PurchaseStatus.purchased; + case IKPaymentTransactionStateWrapper.restored: + return PurchaseStatus.restored; + case IKPaymentTransactionStateWrapper.failed: + // According to the Apple documentation the error code "2" indicates + // the user cancelled the payment (IKErrorPaymentCancelled) and error + // code "15" indicates the cancellation of the overlay (IKErrorOverlayCancelled). + if (error != null && (error.code == 2 || error.code == 15)) { + return PurchaseStatus.canceled; + } + return PurchaseStatus.error; + case IKPaymentTransactionStateWrapper.unspecified: + return PurchaseStatus.error; + } + } + + @override + int toJson(IKPaymentTransactionStateWrapper object) => + _$IKPaymentTransactionStateWrapperEnumMap[object]!; +} + +/// Serializer for [IKSubscriptionPeriodUnit]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@IKSubscriptionPeriodUnitConverter()`. +class IKSubscriptionPeriodUnitConverter + implements JsonConverter { + /// Default const constructor. + const IKSubscriptionPeriodUnitConverter(); + + @override + IKSubscriptionPeriodUnit fromJson(int? json) { + if (json == null) { + return IKSubscriptionPeriodUnit.day; + } + return $enumDecode( + _$IKSubscriptionPeriodUnitEnumMap + .cast(), + json); + } + + @override + int toJson(IKSubscriptionPeriodUnit object) => + _$IKSubscriptionPeriodUnitEnumMap[object]!; +} + +/// Serializer for [IKProductDiscountPaymentMode]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@IKProductDiscountPaymentModeConverter()`. +class IKProductDiscountPaymentModeConverter + implements JsonConverter { + /// Default const constructor. + const IKProductDiscountPaymentModeConverter(); + + @override + IKProductDiscountPaymentMode fromJson(int? json) { + if (json == null) { + return IKProductDiscountPaymentMode.payAsYouGo; + } + return $enumDecode( + _$IKProductDiscountPaymentModeEnumMap + .cast(), + json); + } + + @override + int toJson(IKProductDiscountPaymentMode object) => + _$IKProductDiscountPaymentModeEnumMap[object]!; +} + +// Define a class so we generate serializer helper methods for the enums +// See https://github.com/google/json_serializable.dart/issues/778 +@JsonSerializable() +class _SerializedEnums { + late IKPaymentTransactionStateWrapper response; + late IKSubscriptionPeriodUnit unit; + late IKProductDiscountPaymentMode discountPaymentMode; +} + +/// Serializer for [IKProductDiscountType]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@IKProductDiscountTypeConverter()`. +class IKProductDiscountTypeConverter + implements JsonConverter { + /// Default const constructor. + const IKProductDiscountTypeConverter(); + + @override + IKProductDiscountType fromJson(int? json) { + if (json == null) { + return IKProductDiscountType.introductory; + } + return $enumDecode( + _$IKProductDiscountTypeEnumMap.cast(), + json); + } + + @override + int toJson(IKProductDiscountType object) => + _$IKProductDiscountTypeEnumMap[object]!; +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.g.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.g.dart new file mode 100644 index 000000000..1fd872ac6 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/enum_converters.g.dart @@ -0,0 +1,42 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'enum_converters.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_SerializedEnums _$SerializedEnumsFromJson(Map json) => _SerializedEnums() + ..response = + $enumDecode(_$IKPaymentTransactionStateWrapperEnumMap, json['response']) + ..unit = $enumDecode(_$IKSubscriptionPeriodUnitEnumMap, json['unit']) + ..discountPaymentMode = $enumDecode( + _$IKProductDiscountPaymentModeEnumMap, json['discountPaymentMode']); + +const _$IKPaymentTransactionStateWrapperEnumMap = { + IKPaymentTransactionStateWrapper.purchasing: 0, + IKPaymentTransactionStateWrapper.purchased: 1, + IKPaymentTransactionStateWrapper.failed: 2, + IKPaymentTransactionStateWrapper.restored: 3, + IKPaymentTransactionStateWrapper.deferred: 4, + IKPaymentTransactionStateWrapper.unspecified: -1, +}; + +const _$IKSubscriptionPeriodUnitEnumMap = { + IKSubscriptionPeriodUnit.day: 0, + IKSubscriptionPeriodUnit.week: 1, + IKSubscriptionPeriodUnit.month: 2, + IKSubscriptionPeriodUnit.year: 3, +}; + +const _$IKProductDiscountPaymentModeEnumMap = { + IKProductDiscountPaymentMode.payAsYouGo: 0, + IKProductDiscountPaymentMode.payUpFront: 1, + IKProductDiscountPaymentMode.freeTrail: 2, + IKProductDiscountPaymentMode.unspecified: -1, +}; + +const _$IKProductDiscountTypeEnumMap = { + IKProductDiscountType.introductory: 0, + IKProductDiscountType.subscription: 1, +}; diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.dart new file mode 100644 index 000000000..c4fdc94af --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.dart @@ -0,0 +1,264 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:json_annotation/json_annotation.dart'; + +import '../../iap_kit_wrappers.dart'; +import '../channel.dart'; +import '../in_app_purchase_ohos_platform.dart'; + +part 'ik_payment_queue_wrapper.g.dart'; + +class IKPaymentQueueWrapper { + /// Returns the default payment queue. + /// + /// We do not support instantiating a custom payment queue, hence the + /// singleton. However, you can override the observer. + factory IKPaymentQueueWrapper() { + return _singleton; + } + + IKPaymentQueueWrapper._(); + + static final IKPaymentQueueWrapper _singleton = IKPaymentQueueWrapper._(); + + IKTransactionObserverWrapper? _observer; + + Future> transactions() async { + return _getTransactionList((await channel + .invokeListMethod('iap#transactions'))!); + } + + static Future queryEnvironmentStatus() async => + (await channel.invokeMethod('iap#queryEnvironmentStatus')) ?? false; + + void setTransactionObserver(IKTransactionObserverWrapper observer) { + _observer = observer; + channel.setMethodCallHandler(handleObserverCallbacks); + } + + Future startObservingTransactionQueue() => + channel.invokeMethod('iap#startObservingTransactionQueue'); + + Future stopObservingTransactionQueue() => + channel.invokeMethod('iap#stopObservingTransactionQueue'); + + Future addPayment(IKPaymentWrapper payment) async { + assert(_observer != null, + '[in_app_purchase]: Trying to add a payment without an observer. One must be set using `IKPaymentQueueWrapper.setTransactionObserver` before the app launches.'); + final Map requestMap = payment.toMap(); + await channel.invokeMethod( + 'iap#createPurchase', + requestMap, + ); + } + + Future finishTransaction( + IKPaymentTransactionWrapper transaction) async { + final Map requestMap = transaction.toFinishMap(); + await channel.invokeMethod( + 'iap#finishPurchase', + requestMap, + ); + } + + // 暂未实现 + Future restoreTransactions({String? applicationUserName}) async { + await channel.invokeMethod( + 'iap#restoreTransactions', applicationUserName); + } + + /// Triage a method channel call from the platform and triggers the correct observer method. + /// + /// This method is public for testing purposes only and should not be used + /// outside this class. + @visibleForTesting + Future handleObserverCallbacks(MethodCall call) async { + assert(_observer != null, + '[in_app_purchase]: (Fatal)The observer has not been set but we received a purchase transaction notification. Please ensure the observer has been set using `setTransactionObserver`. Make sure the observer is added right at the App Launch.'); + print('MethodCallHandlerImpl handleObserverCallbacks : ' + call.method); + final IKTransactionObserverWrapper observer = _observer!; + switch (call.method) { + case 'updatedTransactions': + { + print('MethodCallHandlerImpl handleObserverCallbacks'); + final List transactions = + _getTransactionList(call.arguments as List); + return Future(() { + observer.updatedTransactions(transactions: transactions); + }); + } + case 'removedTransactions': + { + final List transactions = + _getTransactionList(call.arguments as List); + return Future(() { + observer.removedTransactions(transactions: transactions); + }); + } + default: + break; + } + throw PlatformException( + code: 'no_such_callback', + message: 'Did not recognize the observer callback ${call.method}.'); + } + + // Get transaction wrapper object list from arguments. + List _getTransactionList( + List transactionsData) { + return transactionsData.map((dynamic map) { + return IKPaymentTransactionWrapper.fromJson( + Map.castFrom( + map as Map)); + }).toList(); + } +} + +@immutable +@JsonSerializable() +class IKError { + /// Creates a new [IKError] object with the provided information. + const IKError( + {required this.code, required this.domain, required this.userInfo}); + + /// Constructs an instance of this from a key-value map of data. + /// + /// The map needs to have named string keys with values matching the names and + /// types of all of the members on this class. The `map` parameter must not be + /// null. + factory IKError.fromJson(Map map) { + return _$IKErrorFromJson(map); + } + + /// Error code + @JsonKey(defaultValue: 0) + final int code; + + /// Error + @JsonKey(defaultValue: '') + final String domain; + + /// A map that contains more detailed information about the error. + @JsonKey(defaultValue: {}) + final Map userInfo; + + @override + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is IKError && + other.code == code && + other.domain == domain && + const DeepCollectionEquality.unordered() + .equals(other.userInfo, userInfo); + } + + @override + int get hashCode => Object.hash( + code, + domain, + userInfo, + ); +} + +/// Dart wrapper around IAP Kit +/// [PurchaseParameter](https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/iap-iap-V5#section1340120344598). +/// +/// Used as the parameter to initiate a payment. In general, a developer should +/// not need to create the payment object explicitly; instead, use +/// [IKPaymentQueueWrapper.addPayment] directly with a product identifier to +/// initiate a payment. +@immutable +@JsonSerializable(createToJson: true) +class IKPaymentWrapper { + /// Creates a new [IKPaymentWrapper] with the provided information. + const IKPaymentWrapper({ + required this.productId, + this.productType, + this.developerPayload, + this.reservedInfo, + this.promotionalOfferId, + this.applicationUserName, + this.jwsRepresentation, + }); + + /// Constructs an instance of this from a key value map of data. + /// + /// The map needs to have named string keys with values matching the names and + /// types of all of the members on this class. The `map` parameter must not be + /// null. + factory IKPaymentWrapper.fromJson(Map map) { + return _$IKPaymentWrapperFromJson(map); + } + + /// Creates a Map object describes the payment object. + Map toMap() { + return { + 'productId': productId, + 'productType': productType, + 'developerPayload': developerPayload, + 'reservedInfo': reservedInfo, + 'promotionalOfferId': promotionalOfferId, + 'applicationUserName': applicationUserName, + 'jwsRepresentation': jwsRepresentation, + }; + } + + /// 待支付的商品ID。商品ID来源于开发者在AppGallery Connect中配置商品信息时设置的“商品ID”,具体请参见配置商品信息。 + final String productId; + + /// 需要查询的商品类型 + final ProductType? productType; + + /// 商户侧保留信息 + final String? developerPayload; + + /// 要求JSON String格式,商户可以将额外需要传入的字段以key-value的形式设置在JSON String中,并通过该参数传入。 + final String? reservedInfo; + + /// 优惠ID。优惠ID来源于开发者在AppGallery Connect中配置商品信息时设置的促销优惠标识符, + /// 具体请参见设置促销价格。传递该字段且要生效,需传递jwsRepresentation字段包含促销优惠信息。 + final String? promotionalOfferId; + + /// 用户账户相关联的混淆字符串,唯一标识用户。传递优惠ID场景,可以传递该字段。 + final String? applicationUserName; + + /// 包含购买参数信息的JWS格式签名数据。购买参数,如促销优惠等。 + final String? jwsRepresentation; + + @override + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is IKPaymentWrapper && + other.productId == productId && + other.productType == productType && + other.developerPayload == developerPayload && + other.reservedInfo == reservedInfo && + other.promotionalOfferId == promotionalOfferId && + other.applicationUserName == applicationUserName && + other.jwsRepresentation == jwsRepresentation; + } + + @override + int get hashCode => Object.hash(productId, productType, developerPayload, + reservedInfo, promotionalOfferId); + + @override + String toString() => _$IKPaymentWrapperToJson(this).toString(); +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.g.dart new file mode 100644 index 000000000..1cd277f1c --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_queue_wrapper.g.dart @@ -0,0 +1,50 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ik_payment_queue_wrapper.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +IKError _$IKErrorFromJson(Map json) => IKError( + code: json['code'] as int? ?? 0, + domain: json['domain'] as String? ?? '', + userInfo: (json['userInfo'] as Map?)?.map( + (k, e) => MapEntry(k as String, e), + ) ?? + {}, + ); + +IKPaymentWrapper _$IKPaymentWrapperFromJson(Map json) => IKPaymentWrapper( + productId: json['productId'] as String? ?? '', + productType: _$IKProductTypeFromInt(json['productType'] as int? ?? 0), + developerPayload: json['developerPayload'] as String?, + reservedInfo: json['reservedInfo'] as String?, + promotionalOfferId: json['promotionalOfferId'] as String?, + applicationUserName: json['applicationUserName'] as String?, + jwsRepresentation: json['jwsRepresentation'] as String?, + ); + +Map _$IKPaymentWrapperToJson(IKPaymentWrapper instance) => + { + 'productId': instance.productId, + 'productType': instance.productType, + 'developerPayload': instance.developerPayload, + 'reservedInfo': instance.reservedInfo, + 'promotionalOfferId': instance.promotionalOfferId, + 'applicationUserName': instance.applicationUserName, + 'jwsRepresentation': instance.jwsRepresentation, + }; + +ProductType _$IKProductTypeFromInt(int type) { + switch (type) { + case 0: + return ProductType.CONSUMABLE; + case 1: + return ProductType.NONCONSUMABLE; + case 3: + return ProductType.AUTORENEWABLE; + default: + return ProductType.CONSUMABLE; + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.dart new file mode 100644 index 000000000..dc34cd955 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.dart @@ -0,0 +1,172 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:json_annotation/json_annotation.dart'; + +import 'enum_converters.dart'; +import 'ik_payment_queue_wrapper.dart'; +import 'ik_product_wrapper.dart'; + +part 'ik_payment_transaction_wrappers.g.dart'; + +/// Callback handlers for transaction status changes. +abstract class IKTransactionObserverWrapper { + /// Triggered when any transactions are updated. + void updatedTransactions( + {required List transactions}); + + /// Triggered when any transactions are removed from the payment queue. + void removedTransactions( + {required List transactions}); +} + +/// The state of a transaction. +enum IKPaymentTransactionStateWrapper { + /// Indicates the transaction is being processed in App Store. + /// + /// You should update your UI to indicate that you are waiting for the + /// transaction to update to another state. Never complete a transaction that + /// is still in a purchasing state. + @JsonValue(0) + purchasing, + + /// The user's payment has been succesfully processed. + /// + /// You should provide the user the content that they purchased. + @JsonValue(1) + purchased, + + /// The transaction failed. + /// + /// Check the [IKPaymentTransactionWrapper.error] property from + /// [IKPaymentTransactionWrapper] for details. + @JsonValue(2) + failed, + + /// This transaction is restoring content previously purchased by the user. + /// + /// The previous transaction information can be obtained in + /// [IKPaymentTransactionWrapper.originalTransaction] from + /// [IKPaymentTransactionWrapper]. + @JsonValue(3) + restored, + + /// The transaction is in the queue but pending external action. Wait for + /// another callback to get the final state. + /// + /// You should update your UI to indicate that you are waiting for the + /// transaction to update to another state. + @JsonValue(4) + deferred, + + /// Indicates the transaction is in an unspecified state. + @JsonValue(-1) + unspecified, +} + +/// Created when a payment is added to the [IKPaymentQueueWrapper]. +/// +/// Transactions are delivered to your app when a payment is finished +/// processing. Completed transactions provide a receipt and a transaction +/// identifier that the app can use to save a permanent record of the processed +/// payment. +@JsonSerializable(createToJson: true) +@immutable +class IKPaymentTransactionWrapper { + /// Creates a new [IKPaymentTransactionWrapper] with the provided information. + // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the + // federated package, and remove this. + // ignore: prefer_const_constructors_in_immutables + IKPaymentTransactionWrapper({ + required this.payment, + required this.transactionState, + this.originalTransaction, + this.transactionTimeStamp, + this.transactionIdentifier, + this.error, + }); + + /// Constructs an instance of this from a key value map of data. + /// + /// The map needs to have named string keys with values matching the names and + /// types of all of the members on this class. The `map` parameter must not be + /// null. + factory IKPaymentTransactionWrapper.fromJson(Map map) { + return _$IKPaymentTransactionWrapperFromJson(map); + } + + /// Current transaction state. + @IKTransactionStatusConverter() + final IKPaymentTransactionStateWrapper transactionState; + + /// The payment that has been created and added to the payment queue which + /// generated this transaction. + final IKPaymentWrapper payment; + + /// The original Transaction. + /// + /// Only available if the [transactionState] is [SKPaymentTransactionStateWrapper.restored]. + /// Otherwise the value is `null`. + /// + /// When the [transactionState] + /// is [IKPaymentTransactionStateWrapper.restored], the current transaction + /// object holds a new [transactionIdentifier]. + final IKPaymentTransactionWrapper? originalTransaction; + + /// The timestamp of the transaction. + /// + /// Seconds since epoch. It is only defined when the [transactionState] is + /// [IKPaymentTransactionStateWrapper.purchased] or + /// [IKPaymentTransactionStateWrapper.restored]. + /// Otherwise, the value is `null`. + final double? transactionTimeStamp; + + /// The unique string identifer of the transaction. + /// + /// It is only defined when the [transactionState] is + /// [IKPaymentTransactionStateWrapper.purchased] or + /// [IKPaymentTransactionStateWrapper.restored]. You may wish to record this + /// string as part of an audit trail for App Store purchases. The value of + /// this string corresponds to the same property in the receipt. + /// + /// The value is `null` if it is an unsuccessful transaction. + final String? transactionIdentifier; + + /// The error object + /// + /// Only available if the [transactionState] is + /// [IKPaymentTransactionStateWrapper.failed]. + final IKError? error; + + @override + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is IKPaymentTransactionWrapper && + other.payment == payment && + other.transactionState == transactionState && + other.originalTransaction == originalTransaction && + other.transactionTimeStamp == transactionTimeStamp && + other.transactionIdentifier == transactionIdentifier && + other.error == error; + } + + @override + int get hashCode => Object.hash(payment, transactionState, + originalTransaction, transactionTimeStamp, transactionIdentifier, error); + + @override + String toString() => _$IKPaymentTransactionWrapperToJson(this).toString(); + + /// The payload that is used to finish this transaction. + Map toFinishMap() => { + 'transactionIdentifier': transactionIdentifier, + 'productIdentifier': payment.productId, + }; +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.g.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.g.dart new file mode 100644 index 000000000..9a51a4267 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_payment_transaction_wrappers.g.dart @@ -0,0 +1,36 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ik_payment_transaction_wrappers.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +IKPaymentTransactionWrapper _$IKPaymentTransactionWrapperFromJson(Map json) => + IKPaymentTransactionWrapper( + payment: IKPaymentWrapper.fromJson( + Map.from(json['payment'] as Map)), + transactionState: const IKTransactionStatusConverter() + .fromJson(json['transactionState'] as int?), + originalTransaction: json['originalTransaction'] == null + ? null + : IKPaymentTransactionWrapper.fromJson( + Map.from(json['originalTransaction'] as Map)), + transactionTimeStamp: (json['transactionTimeStamp'] as num?)?.toDouble(), + transactionIdentifier: json['transactionIdentifier'] as String?, + error: json['error'] == null + ? null + : IKError.fromJson(Map.from(json['error'] as Map)), + ); + +Map _$IKPaymentTransactionWrapperToJson( + IKPaymentTransactionWrapper instance) => + { + 'transactionState': const IKTransactionStatusConverter() + .toJson(instance.transactionState), + 'payment': instance.payment, + 'originalTransaction': instance.originalTransaction, + 'transactionTimeStamp': instance.transactionTimeStamp, + 'transactionIdentifier': instance.transactionIdentifier, + 'error': instance.error, + }; diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.dart new file mode 100644 index 000000000..057e60ac2 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.dart @@ -0,0 +1,279 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:collection/collection.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'enum_converters.dart'; + +// WARNING: Changes to `@JsonSerializable` classes need to be reflected in the +// below generated file. Run `flutter packages pub run build_runner watch` to +// rebuild and watch for further changes. +part 'ik_product_wrapper.g.dart'; + +/// Represents the response object returned by [IKRequestMaker.startProductRequest]. +/// Contains information about a list of products and a list of invalid product identifiers. +@JsonSerializable() +@immutable +class IKProductResponseWrapper { + /// Creates an [IKProductResponseWrapper] with the given product details. + // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the + // federated package, and remove this. + // ignore: prefer_const_constructors_in_immutables + IKProductResponseWrapper( + {required this.products, required this.invalidProductIdentifiers}); + + /// Constructing an instance from a map from the Objective-C layer. + /// + /// This method should only be used with `map` values returned by [IKRequestMaker.startProductRequest]. + factory IKProductResponseWrapper.fromJson(Map map) { + var maptt = _$SkProductResponseWrapperFromJson(map); + return _$SkProductResponseWrapperFromJson(map); + } + + /// Stores all matching successfully found products. + /// + /// One product in this list matches one valid product identifier passed to the [IKRequestMaker.startProductRequest]. + /// Will be empty if the [IKRequestMaker.startProductRequest] method does not pass any correct product identifier. + @JsonKey(defaultValue: []) + final List products; + + /// Stores product identifiers in the `productIdentifiers` from [IKRequestMaker.startProductRequest] that are not recognized by the AppGallery. + /// Will be empty if all the product identifiers are valid. + @JsonKey(defaultValue: []) + final List invalidProductIdentifiers; + + @override + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is IKProductResponseWrapper && + const DeepCollectionEquality().equals(other.products, products) && + const DeepCollectionEquality() + .equals(other.invalidProductIdentifiers, invalidProductIdentifiers); + } + + @override + int get hashCode => Object.hash(products, invalidProductIdentifiers); +} + +/// Used as a property in the [IKProductSubscriptionPeriodWrapper]. Minimum is a day and maximum is a year. +// The values of the enum options are matching the [IKProductPeriodUnit]'s values. Should there be an update or addition +// in the [IKProductPeriodUnit], this need to be updated to match. +enum IKSubscriptionPeriodUnit { + /// An interval lasting one day. + @JsonValue(0) + day, + + /// An interval lasting one month. + @JsonValue(1) + + /// An interval lasting one week. + week, + @JsonValue(2) + + /// An interval lasting one month. + month, + + /// An interval lasting one year. + @JsonValue(3) + year, +} + +/// A period is defined by a [numberOfUnits] and a [unit], e.g for a 3 months period [numberOfUnits] is 3 and [unit] is a month. +/// It is used as a property in [IKProductDiscountWrapper] and [IKProductWrapper]. +@JsonSerializable() +@immutable +class IKProductSubscriptionPeriodWrapper { + /// Creates an [IKProductSubscriptionPeriodWrapper] for a `numberOfUnits`x`unit` period. + // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the + // federated package, and remove this. + // ignore: prefer_const_constructors_in_immutables + IKProductSubscriptionPeriodWrapper( + {required this.numberOfUnits, required this.unit}); + + /// Constructing an instance from a map from the Objective-C layer. + /// + /// This method should only be used with `map` values returned by [IKProductDiscountWrapper.fromJson] or [IKProductWrapper.fromJson]. + factory IKProductSubscriptionPeriodWrapper.fromJson( + Map? map) { + if (map == null) { + return IKProductSubscriptionPeriodWrapper( + numberOfUnits: 0, unit: IKSubscriptionPeriodUnit.day); + } + return _$IKProductSubscriptionPeriodWrapperFromJson(map); + } + + /// The number of [unit] units in this period. + /// + /// Must be greater than 0 if the object is valid. + @JsonKey(defaultValue: 0) + final int numberOfUnits; + + /// The time unit used to specify the length of this period. + @IKSubscriptionPeriodUnitConverter() + final IKSubscriptionPeriodUnit unit; + + @override + bool operator ==(Object other) { + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is IKProductSubscriptionPeriodWrapper && + other.numberOfUnits == numberOfUnits && + other.unit == unit; + } + + @override + int get hashCode => Object.hash(numberOfUnits, unit); +} + +/// This is used as a property in the [IKProductDiscountWrapper]. +// The values of the enum options are matching the [IKProductDiscountPaymentMode]'s values. Should there be an update or addition +// in the [IKProductDiscountPaymentMode], this need to be updated to match. +enum IKProductDiscountPaymentMode { + /// Allows user to pay the discounted price at each payment period. + @JsonValue(0) + payAsYouGo, + + /// Allows user to pay the discounted price upfront and receive the product for the rest of time that was paid for. + @JsonValue(1) + payUpFront, + + /// User pays nothing during the discounted period. + @JsonValue(2) + freeTrail, + + /// Unspecified mode. + @JsonValue(-1) + unspecified, +} + + +/// This is used as a property in the [IKProductDiscountWrapper]. +/// The values of the enum options are matching the [IKProductDiscountType]'s +/// values. +/// +/// Values representing the types of discount offers an app can present. +enum IKProductDiscountType { + /// A constant indicating the discount type is an introductory offer. + @JsonValue(0) + introductory, + + /// A constant indicating the discount type is a promotional offer. + @JsonValue(1) + subscription, +} + +/// Dart wrapper around IAP Kit [Product](https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/iap-iap-V5#section346874219313). +/// +/// A list of [IKProductWrapper] is returned in the [IKRequestMaker.startProductRequest] method, and +/// should be stored for use when making a payment. +@JsonSerializable() +@immutable +class IKProductWrapper { + /// Creates an [IKProductWrapper] with the given product details. + // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the + // federated package, and remove this. + // ignore: prefer_const_constructors_in_immutables + IKProductWrapper({ + required this.id, + required this.type, + required this.name, + required this.description, + required this.localPrice, + required this.microPrice, + required this.originalLocalPrice, + required this.originalMicroPrice, + required this.currency, + this.status, + // this.subscriptionInfo, + // this.promotionalOffers, + this.jsonRepresentation, + }); + + /// Constructing an instance from a map from the ets layer. + /// + /// This method should only be used with `map` values returned by [IKProductResponseWrapper.fromJson]. + factory IKProductWrapper.fromJson(Map map) { + return _$IKProductWrapperFromJson(map); + } + + /// 商品ID + final String id; + + /// 商品类型 + final ProductType type; + + /// 商品名称,为配置商品信息时配置的名称。用于显示在应用内支付收银台 + final String name; + + /// 商品描述,即配置商品信息时配置的描述信息 + final String description; + + /// 商品的展示价格,包含商品币种和价格,格式为“币种+商品价格”,例如 EUR 0.15。部分国家/地区会返回“货币符号+商品价格”,例如中国大陆返回“¥0.15”。此价格含税。可选。 + final String localPrice; + + /// 商品实际价格乘以1,000,000后的微单位价格。例如某个商品实际价格是1.99美元,则该商品对应的微单位价格为:1.99*1000000=1990000。 + final int microPrice; + + /// 商品的原价,包含商品币种和价格,格式为“币种+商品价格”,例如 EUR 0.15。部分国家/地区会返回“货币符号+商品价格”,例如中国大陆返回“¥0.15”。此价格含税。 + final String originalLocalPrice; + + /// 商品原价的微单位价格。商品原价乘以1,000,000后的微单位价格。例如某个商品原价是1.99美元,则该商品对应的微单位价格为:1.99*1000000=1990000。 + final int originalMicroPrice; + + /// 用于支付该商品的币种,必须符合ISO 4217标准,例如USD、CNY、MYR。 + final String currency; + + /// 商品状态 + final ProductStatus? status; + + /// 自动续期订阅商品相关的信息。可选。 + // final SubscriptionInfo? subscriptionInfo; + + /// 订阅商品支持的优惠信息列表 + // final PromotionalOffer[]? promotionalOffers; + + /// 商品详细信息的原始JSON字符串 + final String? jsonRepresentation; +} + +/// 商品状态枚举 +enum ProductType { + /// 消耗型商品 + @JsonValue(0) + CONSUMABLE, + + /// 非消耗型商品 + @JsonValue(1) + NONCONSUMABLE, + + /// 自动续期订阅商品 + @JsonValue(3) + AUTORENEWABLE, +} + +/// 商品状态枚举 +enum ProductStatus { + /// 有效状态。 + @JsonValue(0) + VALID, + + /// 取消状态,即删除。此状态的商品不可续订,也不可订阅。 + @JsonValue(1) + CANCELED, + + /// 下线状态,不能订阅,但老用户仍可续订。 + @JsonValue(3) + OFFLINE, +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.g.dart new file mode 100644 index 000000000..072612e1c --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_product_wrapper.g.dart @@ -0,0 +1,69 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ik_product_wrapper.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +IKProductResponseWrapper _$SkProductResponseWrapperFromJson(Map json) => + IKProductResponseWrapper( + products: (json['products'] as List?) + ?.map((e) => IKProductWrapper.fromJson( + Map.from(e as Map))) + .toList() ?? + [], + invalidProductIdentifiers: + (json['invalidProductIdentifiers'] as List?) + ?.map((e) => e as String) + .toList() ?? + [], + ); + +IKProductSubscriptionPeriodWrapper _$IKProductSubscriptionPeriodWrapperFromJson( + Map json) => + IKProductSubscriptionPeriodWrapper( + numberOfUnits: json['numberOfUnits'] as int? ?? 0, + unit: const IKSubscriptionPeriodUnitConverter() + .fromJson(json['unit'] as int?), + ); + +IKProductWrapper _$IKProductWrapperFromJson(Map json) => IKProductWrapper( + id: json['id'] as String? ?? '', + type: _$IKProductTypeFromInt(json['type'] as int? ?? 0), + name: json['name'] as String? ?? '', + description: json['description'] as String? ?? '', + localPrice: json['localPrice'] as String? ?? '', + microPrice: json['microPrice'] as int? ?? 0, + originalLocalPrice: json['originalLocalPrice'] as String? ?? '', + originalMicroPrice: json['originalMicroPrice'] as int? ?? 0, + currency: json['currency'] as String? ?? '', + status: _$IKProductStatusFromInt(json['status'] as int? ?? 0), + jsonRepresentation: json['jsonRepresentation'] as String?, + ); + +ProductType _$IKProductTypeFromInt(int type) { + switch (type) { + case 0: + return ProductType.CONSUMABLE; + case 1: + return ProductType.NONCONSUMABLE; + case 3: + return ProductType.AUTORENEWABLE; + default: + return ProductType.CONSUMABLE; + } +} + +ProductStatus _$IKProductStatusFromInt(int type) { + switch (type) { + case 0: + return ProductStatus.VALID; + case 1: + return ProductStatus.CANCELED; + case 3: + return ProductStatus.OFFLINE; + default: + return ProductStatus.VALID; + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_receipt_manager.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_receipt_manager.dart new file mode 100644 index 000000000..68feb9e10 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_receipt_manager.dart @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import '../channel.dart'; + +// ignore: avoid_classes_with_only_static_members +/// This class contains static methods to manage StoreKit receipts. +class IKReceiptManager { + /// Retrieve the receipt data from your application's main bundle. + static Future retrieveReceiptData() async { + return (await channel.invokeMethod( + 'iap#retrieveReceiptData')) ?? + ''; + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_request_maker.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_request_maker.dart new file mode 100644 index 000000000..0eebfe836 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/ik_request_maker.dart @@ -0,0 +1,46 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/services.dart'; + +import '../channel.dart'; +import 'ik_product_wrapper.dart'; + +/// A request maker that handles all the requests made by IKRequest subclasses. +class IKRequestMaker { + /// Fetches product information for a list of given product identifiers. + /// + /// The `productIdentifiers` should contain legitimate product identifiers that you declared for the products in the iTunes Connect. Invalid identifiers + /// will be stored and returned in [SkProductResponseWrapper.invalidProductIdentifiers]. Duplicate values in `productIdentifiers` will be omitted. + /// If `productIdentifiers` is null, an `storekit_invalid_argument` error will be returned. If `productIdentifiers` is empty, a [SkProductResponseWrapper] + /// will still be returned with [SkProductResponseWrapper.products] being null. + /// + /// [SkProductResponseWrapper] is returned if there is no error during the request. + /// A [PlatformException] is thrown if the platform code making the request fails. + Future startProductRequest( + List productIdentifiers) async { + final Map? productResponseMap = + await channel.invokeMapMethod( + 'iap#queryProducts', + productIdentifiers, + ); + if (productResponseMap == null) { + throw PlatformException( + code: 'storekit_no_response', + message: 'StoreKit: Failed to get response from platform.', + ); + } + return IKProductResponseWrapper.fromJson(productResponseMap); + } + + Future startRefreshReceiptRequest( + {Map? receiptProperties}) { + return channel.invokeMethod( + 'iap#refreshReceipt', + receiptProperties, + ); + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform.dart new file mode 100644 index 000000000..2fa17d603 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform.dart @@ -0,0 +1,219 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; + +import '../iap_kit_wrappers.dart'; +import '../in_app_purchase_ohos.dart'; + +/// [IAPError.code] code for failed purchases. +const String kPurchaseErrorCode = 'purchase_error'; + +/// Indicates store front is AppGallery. +const String kIAPSource = 'app_gallery'; + +/// An [InAppPurchasePlatform] that wraps IAP Kit. +/// +/// This translates various `IAP Kit` calls and responses into the +/// generic plugin API. +class InAppPurchaseOhosPlatform extends InAppPurchasePlatform { + /// Creates an [InAppPurchaseOhosPlatform] object. + /// + /// This constructor should only be used for testing, for any other purpose + /// get the connection from the [instance] getter. + @visibleForTesting + InAppPurchaseOhosPlatform(); + + static late IKPaymentQueueWrapper _skPaymentQueueWrapper; + static late _TransactionObserver _observer; + + @override + Stream> get purchaseStream => + _observer.purchaseUpdatedController.stream; + + /// Callback handler for transaction status changes. + @visibleForTesting + static IKTransactionObserverWrapper get observer => _observer; + + /// Registers this class as the default instance of [InAppPurchasePlatform]. + static void registerPlatform() { + // Register the [InAppPurchaseOhosPlatformAddition] containing + // IapKit-specific functionality. + InAppPurchasePlatformAddition.instance = + InAppPurchaseOhosPlatformAddition(); + + // Register the platform-specific implementation of the idiomatic + // InAppPurchase API. + InAppPurchasePlatform.instance = InAppPurchaseOhosPlatform(); + + _skPaymentQueueWrapper = IKPaymentQueueWrapper(); + + // Create a purchaseUpdatedController and notify the native side when to + // start of stop sending updates. + final StreamController> updateController = + StreamController>.broadcast( + onListen: () => _skPaymentQueueWrapper.startObservingTransactionQueue(), + onCancel: () => _skPaymentQueueWrapper.stopObservingTransactionQueue(), + ); + _observer = _TransactionObserver(updateController); + _skPaymentQueueWrapper.setTransactionObserver(observer); + } + + @override + Future isAvailable() => IKPaymentQueueWrapper.queryEnvironmentStatus(); + + @override + Future buyNonConsumable({required PurchaseParam purchaseParam}) async { + await _skPaymentQueueWrapper.addPayment( + IKPaymentWrapper(productId: purchaseParam.productDetails.id)); + return true; // There's no error feedback from ohos here to return. + } + + @override + Future buyConsumable( + {required PurchaseParam purchaseParam, bool autoConsume = true}) { + assert(autoConsume == true, 'On ohos, we should always auto consume'); + return buyNonConsumable(purchaseParam: purchaseParam); + } + + @override + Future completePurchase(PurchaseDetails purchase) { + assert( + purchase is AppGalleryPurchaseDetails, + 'On ohos, the `purchase` should always be of type `AppGalleryPurchaseDetails`.', + ); + + return _skPaymentQueueWrapper.finishTransaction( + (purchase as AppGalleryPurchaseDetails).ikPaymentTransaction, + ); + } + + @override + Future restorePurchases({String? applicationUserName}) async { + return _observer + .restoreTransactions( + queue: _skPaymentQueueWrapper, + applicationUserName: applicationUserName) + .whenComplete(() => _observer.cleanUpRestoredTransactions()); + } + + /// Query the product detail list. + /// + /// This method only returns [ProductDetailsResponse]. + /// To get detailed Store Kit product list, use [SkProductResponseWrapper.startProductRequest] + /// to get the [IKProductResponseWrapper]. + @override + Future queryProductDetails( + Set identifiers) async { + final IKRequestMaker requestMaker = IKRequestMaker(); + IKProductResponseWrapper response; + PlatformException? exception; + try { + response = await requestMaker.startProductRequest(identifiers.toList()); + print('InAppPurchasePlugin productDetailResponse response'); + } on PlatformException catch (e) { + exception = e; + response = IKProductResponseWrapper( + products: const [], + invalidProductIdentifiers: identifiers.toList()); + } + List productDetails = + []; + productDetails = response.products + .map((IKProductWrapper productWrapper) => + AppGalleryProductDetails.fromIKProduct(productWrapper)) + .toList(); + List invalidIdentifiers = response.invalidProductIdentifiers; + if (productDetails.isEmpty) { + invalidIdentifiers = identifiers.toList(); + } + final ProductDetailsResponse productDetailsResponse = + ProductDetailsResponse( + productDetails: productDetails, + notFoundIDs: invalidIdentifiers, + error: exception == null + ? null + : IAPError( + source: kIAPSource, + code: exception.code, + message: exception.message ?? '', + details: exception.details), + ); + return productDetailsResponse; + } +} + +enum _TransactionRestoreState { + notRunning, + waitingForTransactions, + receivedTransaction, +} + +class _TransactionObserver implements IKTransactionObserverWrapper { + _TransactionObserver(this.purchaseUpdatedController); + + final StreamController> purchaseUpdatedController; + + Completer? _restoreCompleter; + late String _receiptData; + _TransactionRestoreState _transactionRestoreState = + _TransactionRestoreState.notRunning; + + Future restoreTransactions({ + required IKPaymentQueueWrapper queue, + String? applicationUserName, + }) { + _transactionRestoreState = _TransactionRestoreState.waitingForTransactions; + _restoreCompleter = Completer(); + queue.restoreTransactions(applicationUserName: applicationUserName); + return _restoreCompleter!.future; + } + + void cleanUpRestoredTransactions() { + _restoreCompleter = null; + } + + @override + void updatedTransactions( + {required List transactions}) { + _handleTransationUpdates(transactions); + } + + @override + void removedTransactions( + {required List transactions}) {} + + Future getReceiptData() async { + try { + _receiptData = await IKReceiptManager.retrieveReceiptData(); + } catch (e) { + _receiptData = ''; + } + return _receiptData; + } + + Future _handleTransationUpdates( + List transactions) async { + print('MethodCallHandlerImpl _handleTransationUpdates '); + if (_transactionRestoreState == + _TransactionRestoreState.waitingForTransactions && + transactions.any((IKPaymentTransactionWrapper transaction) => + transaction.transactionState == + IKPaymentTransactionStateWrapper.restored)) { + _transactionRestoreState = _TransactionRestoreState.receivedTransaction; + } + + final String receiptData = await getReceiptData(); + final List purchases = transactions + .map((IKPaymentTransactionWrapper transaction) => + AppGalleryPurchaseDetails.fromIKTransaction( + transaction, receiptData)) + .toList(); + purchaseUpdatedController.add(purchases); + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform_addition.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform_addition.dart new file mode 100644 index 000000000..88a032535 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/in_app_purchase_ohos_platform_addition.dart @@ -0,0 +1,33 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; + +import '../iap_kit_wrappers.dart'; +import '../in_app_purchase_ohos.dart'; + +/// Contains InApp Purchase features that are only available on ohos. +class InAppPurchaseOhosPlatformAddition + extends InAppPurchasePlatformAddition { + + /// Retry loading purchase data after an initial failure. + /// + /// If no results, a `null` value is returned. + Future refreshPurchaseVerificationData() async { + await IKRequestMaker().startRefreshReceiptRequest(); + try { + final String receipt = await IKReceiptManager.retrieveReceiptData(); + return PurchaseVerificationData( + localVerificationData: receipt, + serverVerificationData: receipt, + source: kIAPSource); + } catch (e) { + // ignore: avoid_print + print( + 'Something is wrong while fetching the receipt, this normally happens when the app is ' + 'running on a simulator: $e'); + return null; + } + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_product_details.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_product_details.dart new file mode 100644 index 000000000..907dd3288 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_product_details.dart @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; + +import '../../iap_kit_wrappers.dart'; + +/// The class represents the information of a product as registered in the AppGallery Connect +/// AppGallery. +class AppGalleryProductDetails extends ProductDetails { + /// Creates a new AppStore specific product details object with the provided + /// details. + AppGalleryProductDetails({ + required super.id, + required super.title, + required super.description, + required super.price, + required super.rawPrice, + required super.currencyCode, + required this.skProduct, + required super.currencySymbol, + }); + + factory AppGalleryProductDetails.fromIKProduct(IKProductWrapper product) { + return AppGalleryProductDetails( + id: product.id, + title: product.name, + description: product.description, + price: product.localPrice, + rawPrice: product.microPrice / 1000000.0, + currencyCode: product.currency, + currencySymbol: product.localPrice.isNotEmpty + ? product.localPrice.replaceAll(RegExp(r'[0-9.]+'), "") + : product.currency, + skProduct: product, + ); + } + + /// Points back to the [IKProductWrapper] object that was used to generate + /// this [AppGalleryProductDetails] object. + final IKProductWrapper skProduct; +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_details.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_details.dart new file mode 100644 index 000000000..b77ba6d56 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_details.dart @@ -0,0 +1,79 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; + +import '../../iap_kit_wrappers.dart'; +import '../../in_app_purchase_ohos.dart'; +import '../iap_kit_wrappers/enum_converters.dart'; + +/// The class represents the information of a purchase made with the IAP Kit +/// AppGallery. +class AppGalleryPurchaseDetails extends PurchaseDetails { + /// Creates a new AppStore specific purchase details object with the provided + /// details. + AppGalleryPurchaseDetails({ + super.purchaseID, + required super.productID, + required super.verificationData, + required super.transactionDate, + required this.ikPaymentTransaction, + required PurchaseStatus status, + }) : super(status: status) { + this.status = status; + } + + factory AppGalleryPurchaseDetails.fromIKTransaction( + IKPaymentTransactionWrapper transaction, + String base64EncodedReceipt, + ) { + print('MethodCallHandlerImpl AppGalleryPurchaseDetails.fromIKTransaction '); + final AppGalleryPurchaseDetails purchaseDetails = AppGalleryPurchaseDetails( + productID: transaction.payment.productId, + purchaseID: transaction.transactionIdentifier, + ikPaymentTransaction: transaction, + status: const IKTransactionStatusConverter() + .toPurchaseStatus(transaction.transactionState, transaction.error), + transactionDate: transaction.transactionTimeStamp != null + ? (transaction.transactionTimeStamp! * 1000).toInt().toString() + : null, + verificationData: PurchaseVerificationData( + localVerificationData: base64EncodedReceipt, + serverVerificationData: base64EncodedReceipt, + source: kIAPSource), + ); + var statuus = purchaseDetails.status; + if (purchaseDetails.status == PurchaseStatus.error || + purchaseDetails.status == PurchaseStatus.canceled) { + purchaseDetails.error = IAPError( + source: kIAPSource, + code: kPurchaseErrorCode, + message: transaction.error?.domain ?? '', + details: transaction.error?.userInfo, + ); + } + return purchaseDetails; + } + + /// Points back to the [IKPaymentTransactionWrapper] which was used to + /// generate this [AppStorePurchaseDetails] object. + final IKPaymentTransactionWrapper ikPaymentTransaction; + + late PurchaseStatus _status; + + /// The status that this [PurchaseDetails] is currently on. + @override + PurchaseStatus get status => _status; + + @override + set status(PurchaseStatus status) { + _pendingCompletePurchase = status == PurchaseStatus.purchased; + _status = status; + } + + bool _pendingCompletePurchase = false; + + @override + bool get pendingCompletePurchase => _pendingCompletePurchase; +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_param.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_param.dart new file mode 100644 index 000000000..556acab09 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/app_gallery_purchase_param.dart @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; + +/// Apple AppStore specific parameter object for generating a purchase. +class AppGalleryPurchaseParam extends PurchaseParam { + /// Creates a new [AppGalleryPurchaseParam] object with the given data. + AppGalleryPurchaseParam({ + required super.productDetails, + super.applicationUserName, + this.quantity = 1, + }); + + /// Quantity of the product user requested to buy. + final int quantity; +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/types.dart b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/types.dart new file mode 100644 index 000000000..1704a2e9c --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/types/types.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +export 'app_gallery_product_details.dart'; +export 'app_gallery_purchase_details.dart'; +export 'app_gallery_purchase_param.dart'; diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/.gitignore b/packages/in_app_purchase/in_app_purchase_ohos/ohos/.gitignore new file mode 100644 index 000000000..e2713a277 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/BuildProfile.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/BuildProfile.ets new file mode 100644 index 000000000..fde84590b --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/BuildProfile.ets @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/Index.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/Index.ets new file mode 100644 index 000000000..8e39f7c8d --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/Index.ets @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { InAppPurchasePlugin } from './src/main/ets/components/InAppPurchasePlugin' +export default InAppPurchasePlugin \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/build-profile.json5 b/packages/in_app_purchase/in_app_purchase_ohos/ohos/build-profile.json5 new file mode 100644 index 000000000..e6773f9f5 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/build-profile.json5 @@ -0,0 +1,31 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + }, + "consumerFiles": [ + "./consumer-rules.txt" + ] + } + }, + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest" + } + ] +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/consumer-rules.txt b/packages/in_app_purchase/in_app_purchase_ohos/ohos/consumer-rules.txt new file mode 100644 index 000000000..e69de29bb diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/hvigorfile.ts b/packages/in_app_purchase/in_app_purchase_ohos/ohos/hvigorfile.ts new file mode 100644 index 000000000..12a327db0 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/hvigorfile.ts @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { harTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/obfuscation-rules.txt b/packages/in_app_purchase/in_app_purchase_ohos/ohos/obfuscation-rules.txt new file mode 100644 index 000000000..272efb6ca --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/oh-package.json5 b/packages/in_app_purchase/in_app_purchase_ohos/ohos/oh-package.json5 new file mode 100644 index 000000000..4c93b2c90 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "in_app_purchase", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "Index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": { + "@ohos/flutter_ohos": "file:../libs/flutter.har" + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts new file mode 100644 index 000000000..b21fd80e5 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts @@ -0,0 +1,49 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + */ +import { util } from '@kit.ArkTS'; + +const centerLineRegex: RegExp = new RegExp('-', 'g'); +const underLineRegex: RegExp = new RegExp('_', 'g'); +const textDecoder = util.TextDecoder.create("utf-8", { ignoreBOM: true }); +const base64 = new util.Base64Helper(); +const TAG: string = 'JWTUtil'; + +const BASE64_PAD_MOD = 4; +const BASE64_PAD_INVALID = 1; + +export class JWTUtil { + public static base64Decode(input: string) { + return textDecoder.decodeWithStream(base64.decodeSync(input)); + } + + private static base64UrlDecode(input: string) { + input = input + .replace(centerLineRegex, '+') + .replace(underLineRegex, '/'); + + // Pad out with standard base64 required padding characters + const pad = input.length % BASE64_PAD_MOD; + if (pad) { + if (pad === BASE64_PAD_INVALID) { + throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); + } + input += new Array(5 - pad).join('='); + } + return this.base64Decode(input); + } + + public static decodeJwtObj(data: string) { + let jwt: string[] = data.split("."); + let exp: string = ""; + if (jwt.length < 3) { + return exp; + } + try { + exp = JWTUtil.base64UrlDecode(jwt[1]); + } catch (err) { + console.error(TAG, 'decodeJwtObj parse err: ' + JSON.stringify(err)); + } + return exp; + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/TsUtil.ts b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/TsUtil.ts new file mode 100644 index 000000000..17ddb00ee --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/TsUtil.ts @@ -0,0 +1,24 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +export function ObjToMap(obj: Object): Map { + const map = new Map(); + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + map.set(key, obj[key]); + } + } + return map +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/InAppPurchasePlugin.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/InAppPurchasePlugin.ets new file mode 100644 index 000000000..acc2a6683 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/InAppPurchasePlugin.ets @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { + AbilityAware, + AbilityPluginBinding, + FlutterPlugin, + FlutterPluginBinding, + BinaryMessenger, + Log, + MethodChannel, +} from '@ohos/flutter_ohos'; +import { common } from '@kit.AbilityKit'; +import { MethodCallHandlerImpl } from './MethodCallHandlerImpl'; + +const TAG = "InAppPurchasePlugin" + +export class InAppPurchasePlugin implements FlutterPlugin, AbilityAware { + private methodChannel: MethodChannel | null = null + private methodCallHandler: MethodCallHandlerImpl | null = null + private context: common.UIAbilityContext | null = null + + onAttachedToEngine(binding: FlutterPluginBinding): void { + this.setUpMethodChannel(binding.getBinaryMessenger(), binding.getApplicationContext()); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void { + this.teardownMethodChannel(); + } + + onAttachedToAbility(binding: AbilityPluginBinding): void { + this.context = binding.getAbility().context + this.methodCallHandler?.setContext(this.context) + } + + onDetachedFromAbility(): void { + this.methodCallHandler?.setContext(null) + } + + getUniqueClassName(): string { + return TAG + } + + setUpMethodChannel(messenger: BinaryMessenger, context: common.Context) { + this.methodChannel = new MethodChannel(messenger, "plugins.flutter.io/in_app_purchase"); + this.methodCallHandler = + new MethodCallHandlerImpl(context, this.methodChannel); + this.methodChannel.setMethodCallHandler(this.methodCallHandler); + } + + teardownMethodChannel() { + this.methodChannel?.setMethodCallHandler(null); + this.methodChannel = null; + this.methodCallHandler = null; + this.context = null; + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodCallHandlerImpl.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodCallHandlerImpl.ets new file mode 100644 index 000000000..28b3aeff9 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodCallHandlerImpl.ets @@ -0,0 +1,288 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { MethodCall, MethodCallHandler, MethodChannel, MethodResult, Log, Any } from '@ohos/flutter_ohos'; +import { MethodNames } from './MethodNames'; +import { iap } from '@kit.IAPKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { common } from '@kit.AbilityKit'; +import { ProductType } from './ProductType'; +import { JWTUtil } from '../common/JWTUtil'; +import { PurchaseOrderPayload, PurchaseSubGroupStatusPayload } from './PurchaseOrderPayload'; +import { HashMap } from '@kit.ArkTS'; +import { TransactionState } from './TransactionState'; +import { PurchaseData } from './PurchaseData'; +import { ObjToMap } from '../common/TsUtil'; + +const TAG = "MethodCallHandlerImpl" + +export class IKError { + code: number = 0 + domain: string = '' + userInfo: Map = new Map() +} + +export class MethodCallHandlerImpl implements MethodCallHandler { + private context: common.UIAbilityContext | null = null + private methodChannel: MethodChannel + private observer: MethodChannel | null = null + private productDetailsMap: HashMap = new HashMap() + + constructor(context: common.Context, methodChannel: MethodChannel) { + this.methodChannel = methodChannel + } + + setContext(context: common.UIAbilityContext | null) { + this.context = context + } + + onMethodCall(call: MethodCall, result: MethodResult): void { + switch (call.method) { + case MethodNames.START_OBSERVING_TRANSACTION_QUEUE: + this.startObserver() + break; + case MethodNames.STOP_OBSERVING_TRANSACTION_QUEUE: + this.stopObserver() + break; + case MethodNames.QUERY_ENVIRONMENT_STATUS: + this.isFeatureSupported(result) + break; + case MethodNames.QUERY_PRODUCTS: + let productList: Array = call.args as Array ?? [] + this.queryProductDetails(productList, result) + break; + case MethodNames.CREATE_PURCHASE: + this.purchaseGoods(call.args, result) + break; + case MethodNames.RETRIEVE_RECEIPT_DATA: + result.success(null) + break; + case MethodNames.FINISH_PURCHASE: + this.iapFinishPurchase(call, result) + break; + default: + result.notImplemented(); + } + } + + isFeatureSupported(result: MethodResult): void { + try { + iap.queryEnvironmentStatus(this.context).then(() => { + result.success(true); + }).catch((err: BusinessError) => { + Log.e(TAG, `Failed to query environment status. Code is ${err.code}, message is ${err.message}`); + result.success(false); + }) + } catch (e) { + Log.e(TAG, `Failed to query environment status. err: ${JSON.stringify(e)}`); + result.success(false); + } + } + + queryProductDetails(list: Array, result: MethodResult) { + let productList: Array> = [] + let count: number = 0 + let validProductsList: Array = [] + let invalidProductIdentifiers: Array = [] + ProductType.forEach((type) => { + const queryProductParam: iap.QueryProductsParameter = { + productType: type, + productIds: list + }; + iap.queryProducts(this.context, queryProductParam).then((result) => { + let resultTemp = result.map((value) => { + validProductsList.push(value.id) + this.productDetailsMap.set(value.id, value) + return ObjToMap(value) + }) + productList.push(...resultTemp) + }).catch((err: BusinessError) => { + Log.e(TAG, `Failed to query products. Code is ${err.code}, message is ${err.message}`); + }).finally(() => { + count++ + if (count === ProductType.length) { + let productDetailsResponse: HashMap = new HashMap() + productDetailsResponse.set('products', productList) + list.forEach((id) => { + if (!validProductsList.includes(id)) { + invalidProductIdentifiers.push(id) + } + }) + productDetailsResponse.set('invalidProductIdentifiers', invalidProductIdentifiers) + result.success(productDetailsResponse) + } + }) + }) + } + + purchaseGoods(args: Any, result: MethodResult) { + let map: Map = args as Map + let id: string = map.get('productId') as string + // 拉起支付接口前更新状态为支付中 + let mapRes: Map = new Map() + mapRes.set('payment', args) + mapRes.set('transactionState', TransactionState.purchasing) + this.observer?.invokeMethod('updatedTransactions', [mapRes]) + this.createPurchase(id, map, result) + } + + createPurchase(id: string, args: Map, result: MethodResult) { + try { + const type = this.productDetailsMap.get(id).type + let createPurchaseParam: iap.PurchaseParameter = { + productId: id, + productType: type, + } + iap.createPurchase(this.context, createPurchaseParam).then(async (createPurchaseResult) => { + let type: number = JSON.parse(createPurchaseResult.purchaseData).type + if (type == iap.ProductType.AUTORENEWABLE) { + let jwsSubscriptionStatus: string = JSON.parse(createPurchaseResult.purchaseData).jwsSubscriptionStatus; + let purchaseStr = JWTUtil.decodeJwtObj(jwsSubscriptionStatus); + let purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseSubGroupStatusPayload; + let map: Map = new Map(); + map.set('payment', args) + map.set('transactionIdentifier', + purchaseOrderPayload.lastSubscriptionStatus?.lastPurchaseOrder.purchaseOrderId) + map.set('transactionState', TransactionState.purchased) + this.observer?.invokeMethod('updatedTransactions', [map]) + } else if (type == iap.ProductType.CONSUMABLE || type == iap.ProductType.NONCONSUMABLE) { + let jwsPurchaseOrder: string = JSON.parse(createPurchaseResult.purchaseData).jwsPurchaseOrder; + let purchaseStr = JWTUtil.decodeJwtObj(jwsPurchaseOrder); + let purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload; + let map: Map = new Map(); + map.set('payment', args) + map.set('transactionIdentifier', purchaseOrderPayload.purchaseOrderId) + map.set('transactionState', TransactionState.purchased) + this.observer?.invokeMethod('updatedTransactions', [map]) + } + result.success(null) + }).catch((err: BusinessError) => { + Log.e(TAG, `Failed to create purchase1. Code is ${err.code}, message is ${err.message}`); + this.errorPurchase(args, err); + }) + } catch (err) { + const e: BusinessError = err as BusinessError; + const msg: string = `Failed to create purchase. Code is ${e.code}, message is ${e.message}`; + Log.e(TAG, msg); + this.errorPurchase(args, err); + } + } + + errorPurchase(args: Map, err: BusinessError) { + let map: Map = new Map(); + let iKError: IKError = new IKError() + if (err) { + iKError.code = err.code + iKError.domain = err.message + } + map.set('error', iKError) + map.set('payment', args) + map.set('transactionState', TransactionState.failed) + this.observer?.invokeMethod('updatedTransactions', [map]) + } + + finishPurchase(productType: iap.ProductType, purchaseToken: string, purchaseOrderId: string, result?: MethodResult) { + let finishPurchaseParam: iap.FinishPurchaseParameter = { + productType: productType, + purchaseToken: purchaseToken, + purchaseOrderId: purchaseOrderId + }; + iap.finishPurchase(this.context, finishPurchaseParam).then(() => { + Log.i(TAG, 'Succeeded in finishing purchase.'); + result?.success(true); + }).catch((err: BusinessError) => { + Log.e(TAG, `Failed to finish purchase. Code is ${err.code}, message is ${err.message}`); + result?.error('' + err.code, err.message, err); + }); + } + + queryPurchasesAsync(productType: iap.ProductType, result: MethodResult) { + let param: iap.QueryPurchasesParameter = { + productType: productType, + queryType: iap.PurchaseQueryType.UNFINISHED + }; + iap.queryPurchases(this.context, param).then((res: iap.QueryPurchaseResult) => { + let purchaseDataList: string[] = res.purchaseDataList; + if (purchaseDataList === undefined || purchaseDataList.length <= 0) { + /* 购买成功后, 查询不到购买订单 返回失败. */ + Log.i(TAG, 'queryPurchases, purchaseDataList empty'); + result.error('UNAVAILABLE', 'purchaseDataList empty!', null); + return; + } + this.purchaseCompletionByTypeProcessing(purchaseDataList, result) + }).catch((err: BusinessError) => { + Log.e(TAG, `Failed to query purchases. Code is ${err.code}, message is ${err.message}`); + result.error('' + err.code, err.message, err); + }); + } + + purchaseCompletionByTypeProcessing(purchaseDataList: string[], result: MethodResult) { + for (let i = 0; i < purchaseDataList.length; i++) { + let purchaseData = purchaseDataList[i]; + let type: number = JSON.parse(purchaseData).type + let purchaseToken = '' + let purchaseOrderId = '' + //自动订阅类型 + if (type == iap.ProductType.AUTORENEWABLE) { + let jwsSubscriptionStatus = (JSON.parse(purchaseData) as PurchaseData).jwsSubscriptionStatus; + if (!jwsSubscriptionStatus) { + Log.e(TAG, 'queryPurchases, jwsSubscriptionStatus invalid'); + continue; + } + let purchaseStr = JWTUtil.decodeJwtObj(jwsSubscriptionStatus); + let purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseSubGroupStatusPayload; + if (purchaseOrderPayload.lastSubscriptionStatus) { + purchaseToken = purchaseOrderPayload.lastSubscriptionStatus.purchaseToken + purchaseOrderId = purchaseOrderPayload.lastSubscriptionStatus.lastPurchaseOrder.purchaseOrderId + } + } else { + //非自动订阅类型 + let jwsPurchaseOrder = (JSON.parse(purchaseData) as PurchaseData).jwsPurchaseOrder; + if (!jwsPurchaseOrder) { + Log.e(TAG, 'queryPurchases, jwsPurchaseOrder invalid'); + continue; + } + let purchaseStr = JWTUtil.decodeJwtObj(jwsPurchaseOrder); + let purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload; + purchaseToken = purchaseOrderPayload.purchaseToken + purchaseOrderId = purchaseOrderPayload.purchaseOrderId + } + this.finishPurchase(type, purchaseToken, purchaseOrderId, result); + } + } + + iapFinishPurchase(call: MethodCall, result: MethodResult) { + let finishPurchaseMap: Map = call.args as Map + let productIdentifier: string = finishPurchaseMap.get('productIdentifier') as string + let product: iap.Product = this.productDetailsMap.get(productIdentifier) + // let productType: string = finishPurchaseMap.get('productType') as string + let productType: iap.ProductType = product.type + if (!product) { + Log.i(TAG, `Failed to get productType.`); + result.error('UNAVAILABLE', 'productType is null!', null); + return; + } else { + this.queryPurchasesAsync(productType, result); + } + } + + startObserver() { + this.observer = this.methodChannel + } + + stopObserver() { + this.observer = null + } +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodNames.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodNames.ets new file mode 100644 index 000000000..1c6e415b1 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/MethodNames.ets @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +export class MethodNames { + static QUERY_ENVIRONMENT_STATUS: string = "iap#queryEnvironmentStatus"; + static QUERY_PRODUCTS: string = "iap#queryProducts"; + static CREATE_PURCHASE: string = "iap#createPurchase"; + static START_OBSERVING_TRANSACTION_QUEUE: string = "iap#startObservingTransactionQueue"; + static STOP_OBSERVING_TRANSACTION_QUEUE: string = "iap#stopObservingTransactionQueue"; + static RETRIEVE_RECEIPT_DATA: string = "iap#retrieveReceiptData"; + static TRANSACTIONS: string = "iap#transactions"; + static FINISH_PURCHASE: string = "iap#finishPurchase"; + static RESTORE_TRANSACTIONS: string = "iap#restoreTransactions"; +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets new file mode 100644 index 000000000..64d363a5c --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets @@ -0,0 +1,22 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { iap } from '@kit.IAPKit' + +export const ProductType: Array = [ + iap.ProductType.CONSUMABLE, + iap.ProductType.NONCONSUMABLE, + iap.ProductType.AUTORENEWABLE +] \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseData.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseData.ets new file mode 100644 index 000000000..8440c438e --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseData.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +export interface PurchaseData { + type: number; + jwsPurchaseOrder?: string; + jwsSubscriptionStatus?: string; +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseOrderPayload.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseOrderPayload.ets new file mode 100644 index 000000000..05fa8036f --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/PurchaseOrderPayload.ets @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { Any } from '@ohos/flutter_ohos'; + +export class PurchaseOrderPayload { + applicationId: string = ''; + countryCode: string = ''; + environment: string = ''; + payOrderId: string = ''; + price: number = 0; + productId: string = ''; + productType: number = 0; + purchaseOrderId: string = ''; + purchaseTime: number = 0; + purchaseToken: string = ''; + signedTime: number = 0; +} + +export class PurchaseSubGroupStatusPayload { + environment: string = ''; + applicationId: string = ''; + packageName: string = ''; + subGroupId: string = ''; + lastSubscriptionStatus?: PurchaseSubscriptionStatus; + historySubscriptionStatusList?: Any[] = []; +} + +export class PurchaseSubscriptionStatus { + subGroupGenerationId: string = ''; + subscriptionId: string = ''; + purchaseToken: string = ''; + status: string = ''; + expiresTime: number = 0; + lastPurchaseOrder?: Any = {}; + recentPurchaseOrderList?: Any[] = []; + renewalInfo?: Any = {}; +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/TransactionState.ts b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/TransactionState.ts new file mode 100644 index 000000000..a9a82a173 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/TransactionState.ts @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +export enum TransactionState { + purchasing = 0, + purchased = 1, + failed = 2, + restored = 3, + deferred = 4, + unspecified = -1, +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/module.json5 b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/module.json5 new file mode 100644 index 000000000..098fbca2f --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "in_app_purchase_ohos", + "type": "har", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ] + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/base/element/string.json b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/base/element/string.json new file mode 100644 index 000000000..f51a9c846 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/en_US/element/string.json b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/en_US/element/string.json new file mode 100644 index 000000000..f51a9c846 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/en_US/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/zh_CN/element/string.json b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/zh_CN/element/string.json new file mode 100644 index 000000000..f51a9c846 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/Ability.test.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 000000000..40eab016e --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/List.test.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 000000000..a88ef7e80 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/module.json5 b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/module.json5 new file mode 100644 index 000000000..7b2341f33 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/ohosTest/module.json5 @@ -0,0 +1,13 @@ +{ + "module": { + "name": "in_app_purchase_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/List.test.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/List.test.ets new file mode 100644 index 000000000..e3f190437 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/LocalUnit.test.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/LocalUnit.test.ets new file mode 100644 index 000000000..13b2128b8 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_ohos/pubspec.yaml new file mode 100644 index 000000000..1eef2cb8b --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/pubspec.yaml @@ -0,0 +1,35 @@ +name: in_app_purchase_ohos +description: An implementation for the Ohos platform of the Flutter `in_app_purchase` plugin. This uses the ohoa IAPKit APIs. +repository: https://gitee.com/openharmony-sig/flutter_packages/tree/master/packages/in_app_purchase/in_app_purchase_ohos +issue_tracker: https://gitee.com/openharmony-sig/flutter_packages/issues +version: 0.1.0 + +environment: + sdk: ">=2.19.0 <4.0.0" + flutter: ">=3.7.0" + +flutter: + plugin: + implements: in_app_purchase + platforms: + ohos: + pluginClass: InAppPurchasePlugin + +dependencies: + collection: ^1.15.0 + flutter: + sdk: flutter + in_app_purchase_platform_interface: ^1.3.0 + json_annotation: ^4.8.0 + +dev_dependencies: + build_runner: ^2.0.0 + flutter_test: + sdk: flutter + json_serializable: ^6.3.1 + mockito: 5.4.0 + test: ^1.16.0 + +topics: + - in-app-purchase + - payment -- Gitee From 9d0b9212de60a18fadc1e2160dcd1588db9eeb7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Wed, 25 Sep 2024 18:00:55 +0800 Subject: [PATCH 03/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- .../example/ohos/entry/hvigorfile.ts | 2 +- .../main/ets/entryability/EntryAbility.ets | 2 +- .../ohos/entry/src/main/ets/pages/Index.ets | 2 +- .../ets/plugins/GeneratedPluginRegistrant.ets | 45 +++++++++++++++++++ .../src/ohosTest/ets/test/Ability.test.ets | 2 +- .../entry/src/ohosTest/ets/test/List.test.ets | 2 +- .../ohosTest/ets/testability/TestAbility.ets | 2 +- .../ohosTest/ets/testability/pages/Index.ets | 2 +- .../ets/testrunner/OpenHarmonyTestRunner.ts | 2 +- .../example/ohos/hvigorfile.ts | 2 +- 10 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/hvigorfile.ts b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/hvigorfile.ts index 894fc15c6..5bda56eea 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/hvigorfile.ts +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/hvigorfile.ts @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets index 8bc48be87..b5888ed90 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/pages/Index.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/pages/Index.ets index 1125f9fdd..5d9647743 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/pages/Index.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/pages/Index.ets @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets new file mode 100644 index 000000000..0569b3bbc --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { FlutterEngine, Log } from '@ohos/flutter_ohos'; +import InAppPurchasePlugin from 'in_app_purchase_ohos'; +import IntegrationTestPlugin from 'integration_test'; +import SharedPreferencesPlugin from 'shared_preferences_ohos'; + +/** + * Generated file. Do not edit. + * This file is generated by the Flutter tool based on the + * plugins that support the Ohos platform. + */ + +const TAG = "GeneratedPluginRegistrant"; + +export class GeneratedPluginRegistrant { + + static registerWith(flutterEngine: FlutterEngine) { + try { + flutterEngine.getPlugins()?.add(new InAppPurchasePlugin()); + flutterEngine.getPlugins()?.add(new IntegrationTestPlugin()); + flutterEngine.getPlugins()?.add(new SharedPreferencesPlugin()); + } catch (e) { + Log.e( + TAG, + "Tried to register plugins with FlutterEngine (" + + flutterEngine + + ") failed."); + Log.e(TAG, "Received exception while registering", e); + } + } +} diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets index 25d4c71ff..bdb2d4b34 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets index f4140030e..5ed99383f 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets index 4ca645e60..465211ee2 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets index cef0447cd..bdf1e5f90 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts index 1def08f2e..58d9c312f 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/hvigorfile.ts b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/hvigorfile.ts index 8f2d2aafe..38626e385 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/hvigorfile.ts +++ b/packages/in_app_purchase/in_app_purchase_ohos/example/ohos/hvigorfile.ts @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Copyright (c) 2024 SwanLink (Jiangsu) Technology Development Co., LTD. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at -- Gitee From 0e9108cbb89ba7f2bb1368769feabda3f57f3686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Wed, 25 Sep 2024 18:01:49 +0800 Subject: [PATCH 04/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9OAT=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- OAT.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OAT.xml b/OAT.xml index b475178b8..c13fec4e9 100644 --- a/OAT.xml +++ b/OAT.xml @@ -296,6 +296,10 @@ + + + + -- Gitee From 5f4b9724d642ed81f491a72a8242d6c8b7a574fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Wed, 25 Sep 2024 19:17:33 +0800 Subject: [PATCH 05/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- OAT.xml | 3 ++- .../ohos/src/main/ets/components/ProductType.ets | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/OAT.xml b/OAT.xml index c13fec4e9..eb6cffc64 100644 --- a/OAT.xml +++ b/OAT.xml @@ -85,7 +85,7 @@ - + @@ -300,6 +300,7 @@ + diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets index 64d363a5c..6ec33044a 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import { iap } from '@kit.IAPKit' +import { iap } from '@kit.IAPKit'; export const ProductType: Array = [ iap.ProductType.CONSUMABLE, -- Gitee From 137d44aa79a0f8678206bb8d2aeb3eb84d0144c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Thu, 26 Sep 2024 09:06:54 +0800 Subject: [PATCH 06/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- .../ohos/src/main/ets/components/ProductType.ets | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets index 6ec33044a..7ca4c1205 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/components/ProductType.ets @@ -13,8 +13,7 @@ * limitations under the License. */ -import { iap } from '@kit.IAPKit'; - +import { iap } from '@kit.IAPKit' export const ProductType: Array = [ iap.ProductType.CONSUMABLE, iap.ProductType.NONCONSUMABLE, -- Gitee From 9a36dfc4790d7038e9d730638cd54d7943ca4074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Thu, 26 Sep 2024 14:33:23 +0800 Subject: [PATCH 07/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- .../in_app_purchase/in_app_purchase/example/pubspec.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml index 367aaead8..2adb24360 100644 --- a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml @@ -29,5 +29,11 @@ dev_dependencies: integration_test: sdk: flutter +dependency_overrides: + in_app_purchase_ohos: + git: + url: "https://gitee.com/openharmony-sig/flutter_packages.git" + path: "packages/in_app_purchase/in_app_purchase_ohos" + flutter: uses-material-design: true -- Gitee From 194adc3ae2647b554dc7646e1aeadc0849ba7b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Thu, 26 Sep 2024 17:21:50 +0800 Subject: [PATCH 08/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- .../in_app_purchase/in_app_purchase/example/pubspec.yaml | 6 ------ packages/in_app_purchase/in_app_purchase/pubspec.yaml | 4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml index 2adb24360..367aaead8 100644 --- a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml @@ -29,11 +29,5 @@ dev_dependencies: integration_test: sdk: flutter -dependency_overrides: - in_app_purchase_ohos: - git: - url: "https://gitee.com/openharmony-sig/flutter_packages.git" - path: "packages/in_app_purchase/in_app_purchase_ohos" - flutter: uses-material-design: true diff --git a/packages/in_app_purchase/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/pubspec.yaml index 7a4af79d7..2c30df665 100644 --- a/packages/in_app_purchase/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/pubspec.yaml @@ -25,9 +25,7 @@ dependencies: sdk: flutter in_app_purchase_android: ^0.3.0 in_app_purchase_ohos: - git: - url: "https://gitee.com/openharmony-sig/flutter_packages.git" - path: "packages/in_app_purchase/in_app_purchase_ohos" + path: ../in_app_purchase_ohos/ in_app_purchase_platform_interface: ^1.0.0 in_app_purchase_storekit: ^0.3.4 -- Gitee From 6c478a822cfc8938522fdad55ecbaa56c22f2787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Thu, 26 Sep 2024 19:33:52 +0800 Subject: [PATCH 09/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- .../in_app_purchase/in_app_purchase/example/pubspec.yaml | 6 +++++- packages/in_app_purchase/in_app_purchase/pubspec.yaml | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml index 367aaead8..d7983d335 100644 --- a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml @@ -23,7 +23,11 @@ dependencies: url: https://gitee.com/openharmony-sig/flutter_packages.git path: packages/shared_preferences/shared_preferences -dev_dependencies: +dependency_overrides: + in_app_purchase_ohos: + path: ../../in_app_purchase_ohos + + dev_dependencies: flutter_test: sdk: flutter integration_test: diff --git a/packages/in_app_purchase/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/pubspec.yaml index 2c30df665..7a4af79d7 100644 --- a/packages/in_app_purchase/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/pubspec.yaml @@ -25,7 +25,9 @@ dependencies: sdk: flutter in_app_purchase_android: ^0.3.0 in_app_purchase_ohos: - path: ../in_app_purchase_ohos/ + git: + url: "https://gitee.com/openharmony-sig/flutter_packages.git" + path: "packages/in_app_purchase/in_app_purchase_ohos" in_app_purchase_platform_interface: ^1.0.0 in_app_purchase_storekit: ^0.3.4 -- Gitee From 869a27509aa884e79a103c4ce513391ed877f437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Thu, 26 Sep 2024 19:58:59 +0800 Subject: [PATCH 10/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- packages/in_app_purchase/in_app_purchase/example/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml index d7983d335..edc13ff9b 100644 --- a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml @@ -27,7 +27,7 @@ dependency_overrides: in_app_purchase_ohos: path: ../../in_app_purchase_ohos - dev_dependencies: +dev_dependencies: flutter_test: sdk: flutter integration_test: -- Gitee From c5a922daf7fc4547188b35d5dbde307b7d0ccbd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Fri, 27 Sep 2024 09:51:12 +0800 Subject: [PATCH 11/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- packages/in_app_purchase/in_app_purchase/pubspec.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/pubspec.yaml index 7a4af79d7..2c30df665 100644 --- a/packages/in_app_purchase/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/pubspec.yaml @@ -25,9 +25,7 @@ dependencies: sdk: flutter in_app_purchase_android: ^0.3.0 in_app_purchase_ohos: - git: - url: "https://gitee.com/openharmony-sig/flutter_packages.git" - path: "packages/in_app_purchase/in_app_purchase_ohos" + path: ../in_app_purchase_ohos/ in_app_purchase_platform_interface: ^1.0.0 in_app_purchase_storekit: ^0.3.4 -- Gitee From 1482a28a8855420925439688ca374a6464b752b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Fri, 27 Sep 2024 14:47:54 +0800 Subject: [PATCH 12/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- OAT.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OAT.xml b/OAT.xml index eb6cffc64..681f49a48 100644 --- a/OAT.xml +++ b/OAT.xml @@ -60,6 +60,14 @@ path=".*" rule="may" type="copyright"/> + Date: Fri, 27 Sep 2024 15:33:37 +0800 Subject: [PATCH 13/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- OAT.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OAT.xml b/OAT.xml index 681f49a48..6c97f87cc 100644 --- a/OAT.xml +++ b/OAT.xml @@ -68,6 +68,14 @@ path=".*" rule="may" type="copyright"/> + Date: Fri, 27 Sep 2024 17:23:44 +0800 Subject: [PATCH 14/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- .../in_app_purchase_ohos/README.md | 8 +++----- .../lib/src/iap_kit_wrappers/README.md | 2 +- .../ohos/src/main/ets/common/JWTUtil.ts | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_ohos/README.md b/packages/in_app_purchase/in_app_purchase_ohos/README.md index 7d43fcbc2..e80e0ba08 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/README.md +++ b/packages/in_app_purchase/in_app_purchase_ohos/README.md @@ -14,13 +14,11 @@ This plugin uses [json_serializable](https://pub.dev/packages/json_serializable) for the many data structs passed between the underlying platform layers and Dart. After editing any of the serialized data structs, rebuild the serializers by running -`flutter packages pub run build_runner build --delete-conflicting-outputs`. -`flutter packages pub run build_runner watch --delete-conflicting-outputs` will -watch the filesystem for changes. +`flutter pub run build_runner build --delete-conflicting-outputs`. +`flutter packages pub run build_runner watch --delete-conflicting-outputs` will monitor the filesystem for changes. If you would like to contribute to the plugin, check out our -[contribution guide](https://github.com/flutter/packages/blob/main/CONTRIBUTING.md). - +[contribution guide](https://github.com/flutter/plugins/blob/main/CONTRIBUTING.md). [1]: https://pub.dev/packages/in_app_purchase [2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md index f861c653b..640c7fdb9 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md @@ -1,5 +1,5 @@ # iap_kit_wrappers This exposes Dart endpoints through to the -[IAPKit](https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/iap-iap-V5) APIs. Can be used +[IAPKit](https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/iap-iap-V5) APIs. It provides functionality as an alternative to [in_app_purchase](../in_app_purchase/README.md). \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts index b21fd80e5..6f87f4dbc 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts +++ b/packages/in_app_purchase/in_app_purchase_ohos/ohos/src/main/ets/common/JWTUtil.ts @@ -1,6 +1,17 @@ /* - * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. - */ +* Copyright (c) 2024 Huawei Technologies Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ import { util } from '@kit.ArkTS'; const centerLineRegex: RegExp = new RegExp('-', 'g'); -- Gitee From 9c2d4cd6b2f522c7fcbde5dbaa1b17e805c4bfee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Sun, 29 Sep 2024 09:20:16 +0800 Subject: [PATCH 15/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- packages/in_app_purchase/in_app_purchase_ohos/README.md | 4 ++-- .../in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_ohos/README.md b/packages/in_app_purchase/in_app_purchase_ohos/README.md index e80e0ba08..92a7ab630 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/README.md +++ b/packages/in_app_purchase/in_app_purchase_ohos/README.md @@ -15,9 +15,9 @@ This plugin uses many data structs passed between the underlying platform layers and Dart. After editing any of the serialized data structs, rebuild the serializers by running `flutter pub run build_runner build --delete-conflicting-outputs`. -`flutter packages pub run build_runner watch --delete-conflicting-outputs` will monitor the filesystem for changes. +`flutter pub run build_runner watch --delete-conflicting-outputs` will monitor the filesystem for changes. -If you would like to contribute to the plugin, check out our +If you would like to contribute to the plugin, please refer to our [contribution guide](https://github.com/flutter/plugins/blob/main/CONTRIBUTING.md). [1]: https://pub.dev/packages/in_app_purchase diff --git a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md index 640c7fdb9..8a99aab65 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md +++ b/packages/in_app_purchase/in_app_purchase_ohos/lib/src/iap_kit_wrappers/README.md @@ -1,5 +1,5 @@ # iap_kit_wrappers This exposes Dart endpoints through to the -[IAPKit](https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/iap-iap-V5) APIs. It provides functionality +IAP Kit APIs. It offers functionality as an alternative to [in_app_purchase](../in_app_purchase/README.md). \ No newline at end of file -- Gitee From 0d400c2a1c6478699cd7a7533989a56ae0c69064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Sun, 29 Sep 2024 09:39:55 +0800 Subject: [PATCH 16/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- packages/in_app_purchase/in_app_purchase_ohos/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_ohos/README.md b/packages/in_app_purchase/in_app_purchase_ohos/README.md index 92a7ab630..5317662d3 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/README.md +++ b/packages/in_app_purchase/in_app_purchase_ohos/README.md @@ -15,7 +15,7 @@ This plugin uses many data structs passed between the underlying platform layers and Dart. After editing any of the serialized data structs, rebuild the serializers by running `flutter pub run build_runner build --delete-conflicting-outputs`. -`flutter pub run build_runner watch --delete-conflicting-outputs` will monitor the filesystem for changes. +`flutter pub run build_runner watch --delete-conflicting-outputs` will track the filesystem for changes. If you would like to contribute to the plugin, please refer to our [contribution guide](https://github.com/flutter/plugins/blob/main/CONTRIBUTING.md). -- Gitee From 3f377ebfea196cfdf744c741b89f86ae9aee4afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Sun, 29 Sep 2024 09:59:08 +0800 Subject: [PATCH 17/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- packages/in_app_purchase/in_app_purchase_ohos/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_ohos/README.md b/packages/in_app_purchase/in_app_purchase_ohos/README.md index 5317662d3..7e8b2763b 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/README.md +++ b/packages/in_app_purchase/in_app_purchase_ohos/README.md @@ -15,7 +15,7 @@ This plugin uses many data structs passed between the underlying platform layers and Dart. After editing any of the serialized data structs, rebuild the serializers by running `flutter pub run build_runner build --delete-conflicting-outputs`. -`flutter pub run build_runner watch --delete-conflicting-outputs` will track the filesystem for changes. +`flutter pub run build_runner watch --delete-conflicting-outputs` will monitor the filesystem for modifications. If you would like to contribute to the plugin, please refer to our [contribution guide](https://github.com/flutter/plugins/blob/main/CONTRIBUTING.md). -- Gitee From 52a7ad4b7136d4951bb7f81b292ac4c86fc47016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E5=8D=9A=E6=96=87?= Date: Sun, 29 Sep 2024 11:03:36 +0800 Subject: [PATCH 18/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 袁博文 --- .../in_app_purchase/in_app_purchase_ohos/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_ohos/README.md b/packages/in_app_purchase/in_app_purchase_ohos/README.md index 7e8b2763b..971c114cb 100644 --- a/packages/in_app_purchase/in_app_purchase_ohos/README.md +++ b/packages/in_app_purchase/in_app_purchase_ohos/README.md @@ -10,15 +10,15 @@ so you do not need to add it to your `pubspec.yaml`. ## Contributing -This plugin uses +This plugin utilizes [json_serializable](https://pub.dev/packages/json_serializable) for the -many data structs passed between the underlying platform layers and Dart. After -editing any of the serialized data structs, rebuild the serializers by running +numerous data structures communicated between the underlying platform layers and Dart. After +modifying any of the serialized data structures, regenerate the serializers by executing `flutter pub run build_runner build --delete-conflicting-outputs`. -`flutter pub run build_runner watch --delete-conflicting-outputs` will monitor the filesystem for modifications. +`flutter pub run build_runner watch --delete-conflicting-outputs` will supervise the filesystem for changes. -If you would like to contribute to the plugin, please refer to our -[contribution guide](https://github.com/flutter/plugins/blob/main/CONTRIBUTING.md). +If you are interested in contributing to the plugin, please consult our +[contribution guidelines](https://github.com/flutter/plugins/blob/main/CONTRIBUTING.md). [1]: https://pub.dev/packages/in_app_purchase [2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin -- Gitee