Repository navigation
feat: ship 6.2.0 with emit, token promo offer signing and refundHandling - #169
Conversation
Bumps [org.robolectric:robolectric](https://github.com/robolectric/robolectric) from 4.11.1 to 4.17. - [Release notes](https://github.com/robolectric/robolectric/releases) - [Commits](robolectric/robolectric@robolectric-4.11.1...robolectric-4.17) --- updated-dependencies: - dependency-name: org.robolectric:robolectric dependency-version: '4.17' dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps com.android.application from 9.4.0 to 9.4.1. --- updated-dependencies: - dependency-name: com.android.application dependency-version: 9.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.7.1 to 9.8.0. - [Release notes](https://github.com/gradle/gradle/releases) - [Commits](gradle/gradle@v9.7.1...v9.8.0) --- updated-dependencies: - dependency-name: gradle-wrapper dependency-version: 9.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [org.mockito:mockito-core](https://github.com/mockito/mockito) from 5.21.0 to 5.24.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](mockito/mockito@v5.21.0...v5.24.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-version: 5.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.6.1 to 9.8.0. - [Release notes](https://github.com/gradle/gradle/releases) - [Commits](gradle/gradle@v9.6.1...v9.8.0) --- updated-dependencies: - dependency-name: gradle-wrapper dependency-version: 9.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
- Create AGENTS.md from CLAUDE.md, verified against the repo at 6.1.1 - Fix the iOS source path, add SwiftPM, extra channels, Dart src/ layout - Document Flutter/Java/Kotlin versions, minSdk pin and E2E workflows - Delete CLAUDE.md (AGENTS.md is the single source) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Add signPromotionalOfferWithToken and deprecate signPromotionalOffer, which signs over the anonymous user id. Android resolves with an empty map. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
@greptile review |
|
…android/org.robolectric-robolectric-4.17 deps(android): bump org.robolectric:robolectric from 4.11.1 to 4.17 in /purchasely/android
…example/android/com.android.application-9.4.1 deps(android): bump com.android.application from 9.4.0 to 9.4.1 in /purchasely/example/android
…android/gradle-wrapper-9.8.0 deps(android): bump gradle-wrapper from 9.7.1 to 9.8.0 in /purchasely/android
…android/org.mockito-mockito-core-5.24.0 deps(android): bump org.mockito:mockito-core from 5.21.0 to 5.24.0 in /purchasely/android
…example/android/gradle-wrapper-9.8.0 deps(android): bump gradle-wrapper from 9.6.1 to 9.8.0 in /purchasely/example/android
There was a problem hiding this comment.
🔵 Needs a closer look
The purchase-signing success and failure callbacks lack automated coverage and need final human validation.
1 open finding
What changed in this PR
Releases Purchasely Flutter SDK 6.2.0 with custom events, token-based promotional offer signing, and the refund-handling consent support from #162.
Changes:
- Aligns all packages and native SDK dependencies to 6.2.0.
- Adds
emit, iOS token signing, and refund-handling consent; preserves combined iOS consent purposes. - Updates documentation, examples, tests, and Android tooling.
| File | Description |
|---|---|
| VERSIONS.md | Records native SDK compatibility. |
| sdk_public_doc.md | Documents new APIs and release dependencies. |
| README.md | Updates installation version. |
| purchasely/test/purchasely_flutter_test.dart | Tests refund-handling consent mapping. |
| purchasely/test/platform_channel_test.dart | Tests new channel methods. |
| purchasely/pubspec.yaml | Sets version 6.2.0. |
| purchasely/lib/purchasely_flutter.dart | Exposes new APIs and consent purpose. |
| purchasely/ios/purchasely_flutter/Package.swift | Pins iOS SDK 6.2.0. |
| purchasely/ios/purchasely_flutter/Classes/SwiftPurchaselyFlutterPlugin.swift | Implements iOS APIs and consent mapping. |
| purchasely/ios/purchasely_flutter/Classes/PLYOfferSignature+ToMap.swift | Serializes lowercase purchase tokens. |
| purchasely/ios/purchasely_flutter.podspec | Updates plugin and native versions. |
| purchasely/example/pubspec.lock | Locks example to plugin 6.2.0. |
| purchasely/example/lib/main.dart | Demonstrates token-based signing. |
| purchasely/example/ios/RunnerTests/SwiftPurchaselyFlutterPluginTests.swift | Tests token validation and serialization. |
| purchasely/example/ios/Podfile.lock | Locks updated iOS dependencies. |
| purchasely/example/ios/Podfile | Updates dependency comments only. |
| purchasely/example/android/settings.gradle | Updates Android application plugin. |
| purchasely/example/android/gradle/wrapper/gradle-wrapper.properties | Updates example Gradle version. |
| purchasely/example/android/app/build.gradle | Aligns native extension dependencies. |
| purchasely/CHANGELOG.md | Documents features, deprecation, and consent fix. |
| purchasely/android/src/test/kotlin/io/purchasely/purchasely_flutter/PurchaselyFlutterPluginTest.kt | Tests events, signing fallback, and store ordinal. |
| purchasely/android/src/main/kotlin/io/purchasely/purchasely_flutter/PurchaselyFlutterPlugin.kt | Adds event forwarding and signing fallback; adopts STRIPE. |
| purchasely/android/gradle/wrapper/gradle-wrapper.properties | Updates plugin Gradle version. |
| purchasely/android/build.gradle | Updates native SDK and test dependencies. |
| purchasely_google/pubspec.yaml | Sets version 6.2.0. |
| purchasely_google/CHANGELOG.md | Records extension release. |
| purchasely_google/android/build.gradle | Pins Google Play SDK 6.2.0. |
| purchasely_android_player/pubspec.yaml | Sets version 6.2.0. |
| purchasely_android_player/CHANGELOG.md | Records extension release. |
| purchasely_android_player/android/build.gradle | Pins Player SDK 6.2.0. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
docs(agents): merge CLAUDE.md into AGENTS.md as single source
Extract the purpose-string mapping into an internal static function so a native test can pin that combined purposes keep every entry. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
@greptile review |
redemption_identity failed attempt 1 in every E2E iOS run since abb0008 appended it after the StoreKit suite: the first plain launch after the SKTestSession run got an empty App Store catalogue, so allProducts failed with "Unable to find the product." It passed on attempt 2, and the same call passes in batch 1 (T5) and in proxy_invalid. The runner header already says the StoreKit suite runs last. Move it back to the end, after redemption_identity and proxy_invalid. Side effect: those two suites now get the 300s TIMEOUT, not the 600s STOREKIT_TIMEOUT that leaked into them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Automatic reviews are disabled for this repository. |
Take the icon from purchasely.com (512 px, resized to 256 px) and fix the root README path, which pointed to a file that does not exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The bridge tests its own code, the format of each call to the native SDK, and the completion it can see. The native SDK tests what it does after the call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

What
purchasely,purchasely_google,purchasely_android_player) and pin native iOSPurchasely6.2.0 (CocoaPods and SwiftPM) and Androidio.purchasely:*6.2.0.StoreType.WEB_CHECKOUT_STRIPE->STRIPE(same ordinal, so the wire value does not change).REFUND_HANDLINGdata processing purpose (iOS only; Android ignores it). The cherry-picked commits keep their author. The Dart doc now states the platform difference: on iOSallNonEssentialsexcludesidentifiedAnalyticsandrefundHandling; on Android it includesidentifiedAnalytics.Purchasely.emit(String name, [Map<String, dynamic> properties = const {}]). It awaits the platform channel, so a codec or platform error reaches the caller.Purchasely.signPromotionalOfferWithToken(storeProductId, storeOfferId, {String? purchaseContextToken}). It signs over a purchase context token (native PR Purchasely-iOS-Sources#826, MOB-593) and returns the signature map pluspurchaseContextToken, in lowercase. Anulltoken makes the SDK generate one. An empty or malformed token gives aPlatformExceptionand no native call. On Android it answers an empty map, like the existing method.signPromotionalOffer@Deprecated. Its behavior does not change: it still signs over the anonymous user id.sdk_public_doc.md(including where the purchase must carrypurchaseContextToken: StoreKit 1applicationUsername, StoreKit 2appAccountToken), the three CHANGELOGs,VERSIONS.md.CLAUDE.mdmerged intoAGENTS.md).purchasely/images/icon.png, also the pub.dev screenshot), and the root README points to that file (its old path did not exist).Why
Release 6.2.0 of the bridge, on top of the published native iOS and Android 6.2.0. #162 failed iOS CI because the bridge pinned iOS 6.1.2, which has no
refundHandling; the 6.2.0 pin fixes it. Linear: MOB-581 (refundHandling), MOB-593 (token signing).How to verify
Run locally on the branch by the builder (full suites):
dart format --set-exit-if-changed .with Dart 3.5.4 in the three packages: 0 files changed (HEAD 6dc288b).flutter analyze --no-fatal-infos --no-fatal-warningsin the three packages: no issues (HEAD 6dc288b).cd purchasely && flutter test --coverage: 368 passed (HEAD 6dc288b).purchasely_google,purchasely_android_player: 2 passed each.cd purchasely/example/android && ./gradlew :purchasely_flutter:testDebugUnitTest --rerun-tasks: 33 tests, 0 failed.cd purchasely/example/ios && xcodebuild test -workspace Runner.xcworkspace -scheme Runner -only-testing:RunnerTests: 46 tests, 0 failures (HEAD cbda9c5).flutter build apk --debug|--release,flutter build appbundle --release, extension apps./gradlew assembleRelease,xcodebuild build -scheme Runner: all succeed.minSdk = 23guards: pass.The native Android and iOS suites ran on 2cf57f1. The only change after it is three doc/comment lines.
Notes
#availableguard says 12.2, the same as the existing method. The message stays identical to the existing one.SwiftPurchaselyFlutterPlugin.purchaseContextToken(from:),SwiftPurchaselyFlutterPlugin.dataProcessingPurposes(from:)(both internal and pure) andPLYOfferSignature.toMap(purchaseContextToken:). Production code uses all three.[]and an unknown value. The second pass gives 5/5 with no finding.ci_run_e2e_ios.shnow runs the StoreKit suite last (66e71c9). Since feat: prepare the bridge for native 6.1.0 (anonymous user id, proxy, Web2App redemption) #153 two suites ran after it, and on the next launch StoreKit returned no usable product, soredemption_identity(R2allProducts) failed on attempt 1 in every run and passed only on the retry. The script header already said StoreKit runs last. No Dart test or production code changes.emit(native class methods cannot be stubbed). The Androidemittest usesmockkStatic, becauseemitis@JvmStatic.flutter build iosandpod lib lintfail on this Xcode 27 host; a directxcodebuildbuild succeeds. E2E runs on CI only.Greptile
Requested: public SDK API (
emit,signPromotionalOfferWithToken) and promotional offer signing (payments) inpurchasely/lib/purchasely_flutter.dartand the iOS/Android plugins🤖 Generated with Claude Code