@capgo/native-purchases 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,6 +9,14 @@ npm install native-purchases
9
9
  npx cap sync
10
10
  ```
11
11
 
12
+ ## Android
13
+
14
+ Add this to manifest
15
+
16
+ ```xml
17
+ <uses-permission android:name="com.android.vending.BILLING" />
18
+ ```
19
+
12
20
  ## API
13
21
 
14
22
  <docgen-index>
@@ -1,29 +1,31 @@
1
1
  package ee.forgr.nativepurchases;
2
2
 
3
3
  import android.util.Log;
4
- import androidx.annotation.NonNull;
5
4
 
6
5
  import com.android.billingclient.api.AcknowledgePurchaseParams;
6
+ import com.android.billingclient.api.BillingClientStateListener;
7
+ import com.android.billingclient.api.ProductDetails;
8
+ import com.android.billingclient.api.ProductDetailsResponseListener;
7
9
  import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
8
10
  import com.android.billingclient.api.BillingClient;
9
11
  import com.android.billingclient.api.BillingFlowParams;
10
12
  import com.android.billingclient.api.BillingResult;
11
13
  import com.android.billingclient.api.Purchase;
12
14
  import com.android.billingclient.api.PurchasesUpdatedListener;
13
- import com.android.billingclient.api.SkuDetails;
14
- import com.android.billingclient.api.SkuDetailsParams;
15
- import com.android.billingclient.api.SkuDetailsResponseListener;
15
+ import com.android.billingclient.api.QueryProductDetailsParams;
16
16
  import com.getcapacitor.JSObject;
17
17
  import com.getcapacitor.Plugin;
18
18
  import com.getcapacitor.PluginCall;
19
19
  import com.getcapacitor.PluginMethod;
20
20
  import com.getcapacitor.annotation.CapacitorPlugin;
21
21
  import com.google.common.base.CaseFormat;
22
+ import com.google.common.collect.ImmutableList;
23
+
22
24
  import java.util.ArrayList;
23
- import java.util.HashMap;
24
- import java.util.Iterator;
25
25
  import java.util.List;
26
26
  import java.util.Map;
27
+ import java.util.concurrent.CountDownLatch;
28
+
27
29
  import org.json.JSONArray;
28
30
  import org.json.JSONException;
29
31
  import org.json.JSONObject;
@@ -32,31 +34,9 @@ import org.json.JSONObject;
32
34
  public class NativePurchasesPlugin extends Plugin {
33
35
 
34
36
  public final String PLUGIN_VERSION = "2.0.13";
35
-
36
37
  private BillingClient billingClient;
37
- private PluginCall purchaseCall;
38
-
39
- @Override
40
- public void load() {
41
- super.load();
42
- billingClient = BillingClient.newBuilder(getContext())
43
- .setListener(new PurchasesUpdatedListener() {
44
- @Override
45
- public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
46
- if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
47
- for (Purchase purchase : purchases) {
48
- handlePurchase(purchase);
49
- }
50
- } else {
51
- // Handle any other error codes.
52
- }
53
- }
54
- })
55
- .enablePendingPurchases()
56
- .build();
57
- }
58
38
 
59
- private void handlePurchase(Purchase purchase) {
39
+ private void handlePurchase(Purchase purchase, PluginCall purchaseCall) {
60
40
  if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
61
41
  // Grant entitlement to the user, then acknowledge the purchase
62
42
  acknowledgePurchase(purchase.getPurchaseToken());
@@ -69,6 +49,10 @@ public class NativePurchasesPlugin extends Plugin {
69
49
  // purchase, and to complete it, they should follow instructions that are
70
50
  // given to them. You can also choose to remind the user to complete the
71
51
  // purchase if you detect that it is still pending.
52
+ purchaseCall.reject("Purchase is pending");
53
+ } else {
54
+ // Handle any other error codes.
55
+ purchaseCall.reject("Purchase is not purchased");
72
56
  }
73
57
  }
74
58
 
@@ -81,39 +65,98 @@ public class NativePurchasesPlugin extends Plugin {
81
65
  @Override
82
66
  public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
83
67
  // Handle the result of the acknowledge purchase
68
+ Log.i("NativePurchases", "onAcknowledgePurchaseResponse" + billingResult);
84
69
  }
85
70
  });
86
71
  }
87
72
 
73
+ private void initBillingClient(PluginCall purchaseCall) {
74
+ CountDownLatch semaphoreReady = new CountDownLatch(1);
75
+ billingClient = BillingClient.newBuilder(getContext())
76
+ .setListener(new PurchasesUpdatedListener() {
77
+ @Override
78
+ public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
79
+ Log.i("NativePurchases", "onPurchasesUpdated" + billingResult);
80
+ if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
81
+ for (Purchase purchase : purchases) {
82
+ handlePurchase(purchase, purchaseCall);
83
+ }
84
+ } else {
85
+ // Handle any other error codes.
86
+ Log.i("NativePurchases", "onPurchasesUpdated" + billingResult);
87
+ purchaseCall.reject("Purchase is not purchased");
88
+ }
89
+ return;
90
+ }})
91
+ .enablePendingPurchases()
92
+ .build();
93
+ billingClient.startConnection(new BillingClientStateListener() {
94
+ @Override
95
+ public void onBillingSetupFinished(BillingResult billingResult) {
96
+ if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
97
+ // The BillingClient is ready. You can query purchases here.
98
+ semaphoreReady.countDown();
99
+ }
100
+ }
101
+ @Override
102
+ public void onBillingServiceDisconnected() {
103
+ // Try to restart the connection on the next request to
104
+ // Google Play by calling the startConnection() method.
105
+ }
106
+ });
107
+ try {
108
+ semaphoreReady.await();
109
+ } catch (InterruptedException e) {
110
+ e.printStackTrace();
111
+ }
112
+ }
88
113
  @PluginMethod
89
114
  public void purchaseProduct(PluginCall call) {
90
- String productIdentifier = call.getString("productIdentifier");
91
- Log.d("CapacitorPurchases", "purchaseProduct: " + productIdentifier);
92
- purchaseCall = call;
115
+ String productIdentifier = call.getString("productIdentifier");
116
+ // cannot use quantity, because it's done in native modal
117
+ Log.d("CapacitorPurchases", "purchaseProduct: " + productIdentifier);
118
+ if (productIdentifier.isEmpty()) {
119
+ // Handle error: productIdentifier is empty
120
+ call.reject("productIdentifier is empty");
121
+ return;
122
+ }
123
+ ImmutableList<QueryProductDetailsParams.Product> productList = ImmutableList.of(QueryProductDetailsParams.Product.newBuilder()
124
+ .setProductId(productIdentifier)
125
+ .setProductType(BillingClient.ProductType.INAPP)
126
+ .build());
127
+ QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
128
+ .setProductList(productList)
129
+ .build();
130
+ this.initBillingClient(call);
131
+ billingClient.queryProductDetailsAsync(
132
+ params,
133
+ new ProductDetailsResponseListener() {
134
+ public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
135
+ Log.i("NativePurchases", "onProductDetailsResponse" + billingResult + productDetailsList);
136
+ // Process the result
137
+ ProductDetails productDetails = productDetailsList.get(0);
138
+ ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList =
139
+ ImmutableList.of(
140
+ BillingFlowParams.ProductDetailsParams.newBuilder()
141
+ .setProductDetails(productDetails)
142
+ .build()
143
+ );
93
144
 
94
- if (billingClient.isReady()) {
95
- List<String> skuList = new ArrayList<>();
96
- skuList.add(productIdentifier);
97
- SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
98
- params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
145
+ BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
146
+ .setProductDetailsParamsList(productDetailsParamsList)
147
+ .build();
99
148
 
100
- billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
101
- @Override
102
- public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
103
- if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
104
- for (SkuDetails skuDetails : skuDetailsList) {
105
- BillingFlowParams flowParams = BillingFlowParams.newBuilder()
106
- .setSkuDetails(skuDetails)
107
- .build();
108
- billingClient.launchBillingFlow(getActivity(), flowParams);
109
- }
110
- }
111
- }
112
- });
113
- }
114
- }
149
+ // Launch the billing flow
150
+ BillingResult billingResult2 = billingClient.launchBillingFlow(getActivity(), billingFlowParams);
151
+ Log.i("NativePurchases", "onProductDetailsResponse2" + billingResult2);
152
+ }
153
+ }
154
+ );
155
+ }
115
156
 
116
- @PluginMethod
157
+
158
+
159
+ @PluginMethod
117
160
  public void restorePurchases(PluginCall call) {
118
161
  Log.d("NativePurchases", "restorePurchases");
119
162
 
@@ -158,38 +201,59 @@ public void getProducts(PluginCall call) {
158
201
  }
159
202
 
160
203
  Log.d("NativePurchases", "getProducts: " + productIdentifiers);
204
+ // Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
205
+ // Get the offerToken of the selected offer
206
+ // String offerToken = productDetails
207
+ // .getSubscriptionOfferDetails()
208
+ // .get(selectedOfferIndex)
209
+ // .getOfferToken();
210
+ // Set the parameters for the offer that will be presented
211
+ // in the billing flow creating separate productDetailsParamsList variable
212
+ // ImmutableList<ProductDetailsParams> productDetailsParamsList =
213
+ // ImmutableList.of(
214
+ // BillingFlowParams.ProductDetailsParams.newBuilder()
215
+ // .setProductDetails(p)
216
+ // .setOfferToken(offerToken)
217
+ // .build()
218
+ // );
219
+ //
220
+ // BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
221
+ // .setProductDetailsParamsList(productDetailsParamsList)
222
+ // .build();
223
+ //
224
+ //// Launch the billing flow
225
+ // BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
161
226
 
162
- if (billingClient.isReady()) {
163
- SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
164
- params.setSkusList(productIdentifiers).setType(BillingClient.SkuType.INAPP);
165
-
166
- billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
167
- @Override
168
- public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
169
- if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
170
- JSObject ret = new JSObject();
171
- JSONArray products = new JSONArray();
172
-
173
- for (SkuDetails skuDetails : skuDetailsList) {
174
- JSObject product = new JSObject();
175
- product.put("productId", skuDetails.getSku());
176
- product.put("title", skuDetails.getTitle());
177
- product.put("description", skuDetails.getDescription());
178
- product.put("price", skuDetails.getPrice());
179
- product.put("priceAmountMicros", skuDetails.getPriceAmountMicros());
180
- product.put("priceCurrencyCode", skuDetails.getPriceCurrencyCode());
181
- product.put("type", skuDetails.getType());
182
- products.put(product);
183
- }
184
-
185
- ret.put("products", products);
186
- call.resolve(ret);
187
- } else {
188
- // Handle any other error codes.
189
- }
190
- }
191
- });
192
- }
227
+ // SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
228
+ // params.setSkusList(productIdentifiers).setType(BillingClient.SkuType.INAPP);
229
+ //
230
+ // billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
231
+ // @Override
232
+ // public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
233
+ // if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
234
+ // JSObject ret = new JSObject();
235
+ // JSONArray products = new JSONArray();
236
+ //
237
+ // for (SkuDetails skuDetails : skuDetailsList) {
238
+ // JSObject product = new JSObject();
239
+ // product.put("productId", skuDetails.getSku());
240
+ // product.put("title", skuDetails.getTitle());
241
+ // product.put("description", skuDetails.getDescription());
242
+ // product.put("price", skuDetails.getPrice());
243
+ // product.put("priceAmountMicros", skuDetails.getPriceAmountMicros());
244
+ // product.put("priceCurrencyCode", skuDetails.getPriceCurrencyCode());
245
+ // product.put("type", skuDetails.getType());
246
+ // products.put(product);
247
+ // }
248
+ //
249
+ // ret.put("products", products);
250
+ // call.resolve(ret);
251
+ // } else {
252
+ // // Handle any other error codes.
253
+ // }
254
+ // }
255
+ // });
256
+ // }
193
257
  }
194
258
 
195
259
  //================================================================================
@@ -46,6 +46,7 @@ extension Product {
46
46
  "title": self.displayName,
47
47
  "price": self.price,
48
48
  "priceString": self.displayPrice,
49
+ "currencyCode": self.priceFormatStyle.currencyCode,
49
50
  "isFamilyShareable": self.isFamilyShareable,
50
51
  ]
51
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/native-purchases",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "In-app Subscriptions Made Easy",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",