Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Purchase Connector React Native #582

Open
wants to merge 20 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions .github/workflows/build-apps-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@ on:

jobs:
Build-RN-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: install react-native-appsflyer on an Android app
run: |
cd demos/appsflyer-react-native-app
yarn install
yarn add ../../ --save
- name: Build apk
run: |
cd demos/appsflyer-react-native-app/android
chmod +x ./gradlew
./gradlew assembleRelease

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'

- name: install react-native-appsflyer on an Android app
run: |
cd demos/appsflyer-react-native-app
yarn install
yarn add ../../ --save

- name: Build apk
run: |
cd demos/appsflyer-react-native-app/android
chmod +x ./gradlew
./gradlew assembleRelease
# Build-RN-ios:
# runs-on: macos-latest
# steps:
Expand Down
10 changes: 2 additions & 8 deletions .github/workflows/responseToSupportIssue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,5 @@ jobs:
issue-number: ${{ github.event.issue.number }}
body: |
👋 Hi @${{ github.event.issue.user.login }} and Thank you for reaching out to us.
In order for us to provide optimal support, please submit a ticket to our support team at support@appsflyer.com.
When submitting the ticket, please specify:
- ✅ your AppsFlyer sign-up (account) email
- ✅ app ID
- ✅ production steps
- ✅ logs
- ✅ code snippets
- ✅ and any additional relevant information.
You can contact AppsFlyer support through the Customer Assistant Chatbot for assistance with troubleshooting issues or product guidance.
To do so, please follow [this article](https://support.appsflyer.com/hc/en-us/articles/23583984402193-Using-the-Customer-Assistant-Chatbot).
8 changes: 4 additions & 4 deletions .github/workflows/scripts/updateReadme.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

ios_sdk_version=$(cat react-native-appsflyer.podspec | grep '\'AppsFlyerFramework\' | grep -Eo '[0-9].[0-9]+.[0-9]+')
android_sdk_version=$(cat android/build.gradle | grep 'com.appsflyer:af-android-sdk' | grep -Eo '[0-9].[0-9]+.[0-9]+')
sed -i -e -r "s/Android AppsFlyer SDK \*\*v[0-9].[0-9]+.[0-9]+\*\*/Android AppsFlyer SDK \*\*v$android_sdk_version\*\*/g" README.md
sed -i -e -r "s/iOS AppsFlyer SDK \*\*v[0-9].[0-9]+.[0-9]+\*\*/iOS AppsFlyer SDK \*\*v$ios_sdk_version\*\*/g" README.md
ios_sdk_version=$(cat react-native-appsflyer.podspec | grep '\'AppsFlyerFramework\' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')
android_sdk_version=$(cat android/build.gradle | grep 'com.appsflyer:af-android-sdk' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')
sed -i -r "s/Android AppsFlyer SDK \*\*v[0-9]+\.[0-9]+\.[0-9]+\*\*/Android AppsFlyer SDK \*\*v$android_sdk_version\*\*/g" README.md
sed -i -r "s/iOS AppsFlyer SDK \*\*v[0-9]+\.[0-9]+\.[0-9]+\*\*/iOS AppsFlyer SDK \*\*v$ios_sdk_version\*\*/g" README.md
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 6.15.1
Release date: *2024-09-15*

- React Native >> Update Plugin to v6.15.1
- React native plugin >> UDL failed deferred deep linking

## 6.14.3
Release date: *2024-04-28*

Expand Down
4 changes: 4 additions & 0 deletions Docs/RN_UnifiedDeepLink.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ order: 9
hidden: false
---

> 📘 **UDL privacy protection**
>
> For new users, the UDL method only returns parameters relevant to deferred deep linking: `deep_link_value` and `deep_link_sub1` to `deep_link_sub10`. If you try to get any other parameters (`media_source`, `campaign`, `af_sub1-5`, etc.), they return `null`.

### UDL flow

1. The SDK is triggered by:
Expand Down
6 changes: 5 additions & 1 deletion Docs/RN_UserInvite.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ The link that is generated for the user invite will use this OneLink ID as the b
| oneLinkID | string | oneLinkID |
| callback | function | success callback |


> 📘 Note
>
> - Make sure to call `setAppInviteOneLinkID()` **before** calling `start`.
> - The OneLink template must be assigned to the app.

##### 2. `generateInviteLink(parameters, success, error)`
A complete list of supported parameters is available [here](https://support.appsflyer.com/hc/en-us/articles/115004480866-User-Invite-Tracking). Custom parameters can be passed using a userParams{} nested object, as in the example above.

Expand Down
23 changes: 23 additions & 0 deletions PurchaseConnector/constants/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class AppsFlyerConstants {
static readonly RE_CONFIGURE_ERROR_MSG: string = "[PurchaseConnector] Re configure instance is not permitted. Returned the existing instance";
static readonly MISSING_CONFIGURATION_EXCEPTION_MSG: string = "Could not create an instance without configuration";

// Adding method constants
static readonly SUBSCRIPTION_VALIDATION_SUCCESS: string = 'subscriptionValidationSuccess';
static readonly SUBSCRIPTION_VALIDATION_FAILURE: string = 'subscriptionValidationFailure';
static readonly IN_APP_PURCHASE_VALIDATION_SUCCESS: string = 'inAppPurchaseValidationSuccess';
static readonly IN_APP_PURCHASE_VALIDATION_FAILURE: string = 'inAppPurchaseValidationFailure';
static readonly DID_RECEIVE_PURCHASE_REVENUE_VALIDATION_INFO: string =
"onDidReceivePurchaseRevenueValidationInfo";

// Adding key constants
static readonly RESULT: string = "result";
static readonly ERROR: string = "error";
static readonly VALIDATION_INFO: string = "validationInfo";
static readonly CONFIGURE_KEY: string = "configure";
static readonly LOG_SUBS_KEY: string = "logSubscriptions";
static readonly LOG_IN_APP_KEY: string = "logInApps";
static readonly SANDBOX_KEY: string = "sandbox";
}

export default AppsFlyerConstants;
34 changes: 34 additions & 0 deletions PurchaseConnector/models/auto_renewing_plan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { SubscriptionItemPriceChangeDetailsJson, SubscriptionItemPriceChangeDetails } from "./subscription_item_price_change_details";

export type AutoRenewingPlanJson = {
autoRenewEnabled?: boolean;
priceChangeDetails?: SubscriptionItemPriceChangeDetailsJson;
};

export class AutoRenewingPlan {
autoRenewEnabled?: boolean;
priceChangeDetails?: SubscriptionItemPriceChangeDetails;

constructor(
autoRenewEnabled?: boolean,
priceChangeDetails?: SubscriptionItemPriceChangeDetails
) {
this.autoRenewEnabled = autoRenewEnabled;
this.priceChangeDetails = priceChangeDetails;
}

static fromJson(json: AutoRenewingPlanJson): AutoRenewingPlan {
return new AutoRenewingPlan(
json.autoRenewEnabled,
json.priceChangeDetails &&
SubscriptionItemPriceChangeDetails.fromJson(json.priceChangeDetails)
);
}

toJson(): AutoRenewingPlanJson {
return {
autoRenewEnabled: this.autoRenewEnabled,
priceChangeDetails: this.priceChangeDetails?.toJson(),
};
}
}
141 changes: 141 additions & 0 deletions PurchaseConnector/models/canceled_state_context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
export class CanceledStateContext {
developerInitiatedCancellation?: DeveloperInitiatedCancellation;
replacementCancellation?: ReplacementCancellation;
systemInitiatedCancellation?: SystemInitiatedCancellation;
userInitiatedCancellation?: UserInitiatedCancellation;

constructor(
developerInitiatedCancellation?: DeveloperInitiatedCancellation,
replacementCancellation?: ReplacementCancellation,
systemInitiatedCancellation?: SystemInitiatedCancellation,
userInitiatedCancellation?: UserInitiatedCancellation
) {
this.developerInitiatedCancellation = developerInitiatedCancellation;
this.replacementCancellation = replacementCancellation;
this.systemInitiatedCancellation = systemInitiatedCancellation;
this.userInitiatedCancellation = userInitiatedCancellation;
}

static fromJson(json: any): CanceledStateContext {
return new CanceledStateContext(
json.developerInitiatedCancellation != null
? DeveloperInitiatedCancellation.fromJson(
json.developerInitiatedCancellation
)
: undefined,
json.replacementCancellation != null
? ReplacementCancellation.fromJson(json.replacementCancellation)
: undefined,
json.systemInitiatedCancellation != null
? SystemInitiatedCancellation.fromJson(json.systemInitiatedCancellation)
: undefined,
json.userInitiatedCancellation != null
? UserInitiatedCancellation.fromJson(json.userInitiatedCancellation)
: undefined
);
}

toJson(): Record<string, any> {
return {
developerInitiatedCancellation:
this.developerInitiatedCancellation?.toJson(),
replacementCancellation: this.replacementCancellation?.toJson(),
systemInitiatedCancellation: this.systemInitiatedCancellation?.toJson(),
userInitiatedCancellation: this.userInitiatedCancellation?.toJson(),
};
}
}

/**
* TODO: Need to check each state context further...
*/
class DeveloperInitiatedCancellation {
constructor() {}

static fromJson(json: any): DeveloperInitiatedCancellation {
// Here you would implement the conversion from JSON to DeveloperInitiatedCancellation instance
return new DeveloperInitiatedCancellation();
}

toJson(): Record<string, unknown> {
// Here you would implement the conversion from DeveloperInitiatedCancellation instance to JSON
return {};
}
}

class ReplacementCancellation {
constructor() {}

static fromJson(json: any): ReplacementCancellation {
// Here you would implement the conversion from JSON to ReplacementCancellation instance
return new ReplacementCancellation();
}

toJson(): Record<string, unknown> {
return {};
}
}

class SystemInitiatedCancellation {
constructor() {}

static fromJson(json: any): SystemInitiatedCancellation {
// Here you would implement the conversion from JSON to SystemInitiatedCancellation instance
return new SystemInitiatedCancellation();
}

toJson(): Record<string, unknown> {
// Here you would implement the conversion from SystemInitiatedCancellation instance to JSON
return {};
}
}

class UserInitiatedCancellation {
cancelSurveyResult?: CancelSurveyResult; // Made optional as per Dart's CancelSurveyResult? declaration
cancelTime: string;

constructor(
cancelSurveyResult: CancelSurveyResult | undefined,
cancelTime: string
) {
this.cancelSurveyResult = cancelSurveyResult;
this.cancelTime = cancelTime;
}

static fromJson(json: any): UserInitiatedCancellation {
return new UserInitiatedCancellation(
json.cancelSurveyResult != null
? CancelSurveyResult.fromJson(json.cancelSurveyResult)
: undefined,
json.cancelTime
);
}

toJson(): Record<string, unknown> {
return {
cancelSurveyResult: this.cancelSurveyResult?.toJson(),
cancelTime: this.cancelTime,
};
}
}

class CancelSurveyResult {
reason: string;
reasonUserInput: string;

constructor(reason: string, reasonUserInput: string) {
this.reason = reason;
this.reasonUserInput = reasonUserInput;
}

static fromJson(json: any): CancelSurveyResult {
return new CancelSurveyResult(json.reason, json.reasonUserInput);
}

toJson(): Record<string, string> {
return {
reason: this.reason,
reasonUserInput: this.reasonUserInput,
};
}
}
21 changes: 21 additions & 0 deletions PurchaseConnector/models/deferred_item_replacement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export type DeferredItemReplacementJson = {
productId: string;
};

export class DeferredItemReplacement {
productId: string;

constructor(productId: string) {
this.productId = productId;
}

static fromJson(json: DeferredItemReplacementJson): DeferredItemReplacement {
return new DeferredItemReplacement(json.productId);
}

toJson(): DeferredItemReplacementJson {
return {
productId: this.productId,
};
}
}
39 changes: 39 additions & 0 deletions PurchaseConnector/models/external_account_identifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export type ExternalAccountIdentifiersJson = {
externalAccountId: string;
obfuscatedExternalAccountId: string;
obfuscatedExternalProfileId: string;
};

export class ExternalAccountIdentifiers {
externalAccountId: string;
obfuscatedExternalAccountId: string;
obfuscatedExternalProfileId: string;

constructor(
externalAccountId: string,
obfuscatedExternalAccountId: string,
obfuscatedExternalProfileId: string
) {
this.externalAccountId = externalAccountId;
this.obfuscatedExternalAccountId = obfuscatedExternalAccountId;
this.obfuscatedExternalProfileId = obfuscatedExternalProfileId;
}

static fromJson(
json: ExternalAccountIdentifiersJson
): ExternalAccountIdentifiers {
return new ExternalAccountIdentifiers(
json.externalAccountId,
json.obfuscatedExternalAccountId,
json.obfuscatedExternalProfileId
);
}

toJson(): ExternalAccountIdentifiersJson {
return {
externalAccountId: this.externalAccountId,
obfuscatedExternalAccountId: this.obfuscatedExternalAccountId,
obfuscatedExternalProfileId: this.obfuscatedExternalProfileId,
};
}
}
Loading
Loading