sjbillingclient 0.1.4__py3-none-any.whl → 0.2.0__py3-none-any.whl

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.
@@ -1,8 +1,16 @@
1
- from jnius import JavaClass, MetaJavaClass, JavaStaticMethod
1
+ from jnius import JavaClass, MetaJavaClass, JavaStaticMethod, JavaMethod
2
2
 
3
- __all__ = ("PendingPurchasesParams",)
3
+ __all__ = ("PendingPurchasesParams", "PendingPurchasesParamsBuilder")
4
4
 
5
5
 
6
6
  class PendingPurchasesParams(JavaClass, metaclass=MetaJavaClass):
7
7
  __javaclass__ = f"com/android/billingclient/api/PendingPurchasesParams"
8
8
  newBuilder = JavaStaticMethod("()Lcom/android/billingclient/api/PendingPurchasesParams$Builder;")
9
+
10
+
11
+ class PendingPurchasesParamsBuilder(JavaClass, metaclass=MetaJavaClass):
12
+ __javaclass__ = f"com/android/billingclient/api/PendingPurchasesParams$Builder"
13
+
14
+ build = JavaMethod("()Lcom/android/billingclient/api/PendingPurchasesParams;")
15
+ enableOneTimeProducts = JavaMethod("()Lcom/android/billingclient/api/PendingPurchasesParams$Builder;")
16
+ enablePrepaidPlans = JavaMethod("()Lcom/android/billingclient/api/PendingPurchasesParams$Builder;")
@@ -1,4 +1,4 @@
1
- from jnius import JavaClass, MetaJavaClass, JavaStaticMethod
1
+ from jnius import JavaClass, MetaJavaClass, JavaStaticMethod, JavaMethod
2
2
 
3
3
  __all__ = ("QueryProductDetailsParams", "QueryProductDetailsParamsProduct")
4
4
 
@@ -11,3 +11,11 @@ class QueryProductDetailsParams(JavaClass, metaclass=MetaJavaClass):
11
11
  class QueryProductDetailsParamsProduct(JavaClass, metaclass=MetaJavaClass):
12
12
  __javaclass__ = f"com/android/billingclient/api/QueryProductDetailsParams$Product"
13
13
  newBuilder = JavaStaticMethod("()Lcom/android/billingclient/api/QueryProductDetailsParams$Product$Builder;")
14
+
15
+
16
+ class QueryProductDetailsResult(JavaClass, metaclass=MetaJavaClass):
17
+ __javaclass__ = f"com/android/billingclient/api/QueryProductDetailsResult"
18
+ create = JavaStaticMethod("(Ljava/util/List;Ljava/util/List;)"
19
+ "Lcom/android/billingclient/api/QueryProductDetailsResult;")
20
+ getProductDetailsList = JavaMethod("()Ljava/util/List;")
21
+ getUnfetchedProductList = JavaMethod("()Ljava/util/List;")
@@ -10,6 +10,7 @@ class ProductDetailsResponseListener(PythonJavaClass):
10
10
  def __init__(self, callback):
11
11
  self.callback = callback
12
12
 
13
- @java_method("(Lcom/android/billingclient/api/BillingResult;Ljava/util/List;)V")
14
- def onProductDetailsResponse(self, billing_result, product_details_list):
15
- self.callback(billing_result, product_details_list)
13
+ @java_method("(Lcom/android/billingclient/api/BillingResult;"
14
+ "Lcom/android/billingclient/api/QueryProductDetailsResult;)V")
15
+ def onProductDetailsResponse(self, billing_result, product_details_result):
16
+ self.callback(billing_result, product_details_result)
@@ -42,6 +42,7 @@ from sjbillingclient.jclass.billing import BillingClient as SJBillingClient, Pro
42
42
  BillingFlowParams
43
43
  from android.activity import _activity as activity # noqa
44
44
  from sjbillingclient.jclass.consume import ConsumeParams
45
+ from sjbillingclient.jclass.purchase import PendingPurchasesParams
45
46
  from sjbillingclient.jclass.queryproduct import QueryProductDetailsParams, QueryProductDetailsParamsProduct
46
47
  from sjbillingclient.jinterface.acknowledge import AcknowledgePurchaseResponseListener
47
48
  from sjbillingclient.jinterface.billing import BillingClientStateListener
@@ -49,7 +50,6 @@ from sjbillingclient.jinterface.consume import ConsumeResponseListener
49
50
  from sjbillingclient.jinterface.product import ProductDetailsResponseListener
50
51
  from sjbillingclient.jinterface.purchases import PurchasesUpdatedListener
51
52
 
52
-
53
53
  ERROR_NO_BASE_PLAN = "You don't have a base plan"
54
54
  ERROR_NO_BASE_PLAN_ID = "You don't have a base plan id"
55
55
  ERROR_INVALID_PRODUCT_TYPE = "product_type not supported. Must be one of `ProductType.SUBS`, `ProductType.INAPP`"
@@ -77,7 +77,13 @@ class BillingClient:
77
77
  :ivar __acknowledge_purchase_response_listener: Listener handling responses for acknowledging purchases.
78
78
  :type __acknowledge_purchase_response_listener: AcknowledgePurchaseResponseListener | None
79
79
  """
80
- def __init__(self, on_purchases_updated) -> None:
80
+
81
+ def __init__(
82
+ self,
83
+ on_purchases_updated,
84
+ enable_one_time_products: bool = True,
85
+ enable_prepaid_plans: bool = False
86
+ ) -> None:
81
87
  """
82
88
  Initializes an instance of the class with the given purchase update callback.
83
89
 
@@ -92,10 +98,15 @@ class BillingClient:
92
98
  self.__acknowledge_purchase_response_listener = None
93
99
 
94
100
  self.__purchase_update_listener = PurchasesUpdatedListener(on_purchases_updated)
101
+ pending_purchase_params = PendingPurchasesParams.newBuilder()
102
+ if enable_one_time_products:
103
+ pending_purchase_params.enableOneTimeProducts()
104
+ if enable_prepaid_plans:
105
+ pending_purchase_params.enablePrepaidPlans()
95
106
  self.__billing_client = (
96
107
  SJBillingClient.newBuilder(activity.context)
97
108
  .setListener(self.__purchase_update_listener)
98
- .enablePendingPurchases()
109
+ .enablePendingPurchases(pending_purchase_params.build())
99
110
  .build()
100
111
  )
101
112
 
@@ -177,6 +188,28 @@ class BillingClient:
177
188
  .setProductType(product_type)
178
189
  .build())
179
190
 
191
+ @staticmethod
192
+ def get_unfetched_product(unfetched_product) -> Dict:
193
+ """
194
+ Retrieves detailed product information for an unfetched product.
195
+
196
+ This function takes an object representing an unfetched product and extracts
197
+ important details such as the product ID, product type, and status code.
198
+ The extracted details are then returned as a dictionary.
199
+
200
+ :param unfetched_product: The product object that has not yet been fetched.
201
+ Must provide methods to retrieve product ID, type, and status code.
202
+ :type unfetched_product: Any
203
+ :return: A dictionary containing detailed information about the unfetched
204
+ product, including its ID, type, and status code.
205
+ :rtype: Dict
206
+ """
207
+ return {
208
+ "product_id": unfetched_product.getProductId(),
209
+ "product_type": unfetched_product.getProductType(),
210
+ "status_code": unfetched_product.getStatusCode(),
211
+ }
212
+
180
213
  def get_product_details(self, product_details, product_type: str) -> List[Dict]:
181
214
  """
182
215
  Retrieves the details of a product based on the provided product type. The function processes
@@ -292,6 +325,7 @@ class BillingClient:
292
325
  self._create_product_params(product_detail, offer_token)
293
326
  for product_detail in product_details
294
327
  ]
328
+ print(product_params_list)
295
329
 
296
330
  billing_flow_params = (BillingFlowParams.newBuilder()
297
331
  .setProductDetailsParamsList(JavaList.of(*product_params_list))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sjbillingclient
3
- Version: 0.1.4
3
+ Version: 0.2.0
4
4
  Summary:
5
5
  Author: Kenechukwu Akubue
6
6
  Author-email: kengoon19@gmail.com
@@ -36,7 +36,7 @@ SJBillingClient is a Python wrapper for the Google Play Billing Library that fac
36
36
 
37
37
  - Python 3.9+
38
38
  - pyjnius 1.6.1+
39
- - Android application with Google Play Billing Library (version 7.1.1 recommended)
39
+ - Android application with Google Play Billing Library (version 8.0.0 recommended)
40
40
 
41
41
  ## Installation
42
42
 
@@ -46,7 +46,7 @@ pip install sjbillingclient
46
46
 
47
47
  # In Buildozer (add to buildozer.spec)
48
48
  requirements = sjbillingclient
49
- android.gradle_dependencies = com.android.billingclient:billing:7.1.1
49
+ android.gradle_dependencies = com.android.billingclient:billing:8.0.0
50
50
  ```
51
51
 
52
52
  ## Quick Start
@@ -170,14 +170,28 @@ from kivy.uix.screenmanager import ScreenManager, Screen
170
170
  from sjbillingclient.jclass.billing import BillingResponseCode, ProductType
171
171
  from sjbillingclient.tools import BillingClient
172
172
 
173
- # Load the KV file
174
173
  Builder.load_file(join(dirname(__file__), basename(__file__).split(".")[0] + ".kv"))
175
174
 
176
175
 
177
176
  class HomeScreen(Screen):
177
+ """
178
+ A screen that demonstrates Google Play Billing integration with Kivy.
179
+
180
+ This screen provides functionality to make in-app purchases and subscriptions
181
+ using the Google Play Billing Library through the SJBillingClient wrapper.
182
+
183
+ Attributes:
184
+ billing_client (BillingClient): The client used to interact with Google Play Billing.
185
+ """
178
186
  billing_client = None
179
187
 
180
- def purchase_or_subscribe(self):
188
+ def support(self):
189
+ """
190
+ Initializes the billing client and starts a connection to the Google Play Billing service.
191
+
192
+ This method is called when the user wants to make a purchase or subscription.
193
+ If a billing client already exists, it ends the connection before creating a new one.
194
+ """
181
195
  if self.billing_client:
182
196
  self.billing_client.end_connection()
183
197
 
@@ -188,6 +202,17 @@ class HomeScreen(Screen):
188
202
  )
189
203
 
190
204
  def on_purchases_updated(self, billing_result, null, purchases):
205
+ """
206
+ Callback method that is called when purchases are updated.
207
+
208
+ This method handles the result of a purchase flow, either acknowledging
209
+ a subscription or consuming a one-time purchase.
210
+
211
+ Args:
212
+ billing_result: The result of the billing operation.
213
+ null: Boolean indicating if the purchases list is null.
214
+ purchases: List of purchases that were updated.
215
+ """
191
216
  if billing_result.getResponseCode() == BillingResponseCode.OK and not null:
192
217
  for purchase in purchases:
193
218
  if self.ids.subscribe.active:
@@ -197,40 +222,96 @@ class HomeScreen(Screen):
197
222
  )
198
223
  else:
199
224
  self.billing_client.consume_async(purchase, self.on_consume_response)
225
+ print(billing_result.getResponseCode(), billing_result.getDebugMessage())
200
226
 
201
227
  def on_acknowledge_purchase_response(self, billing_result):
228
+ """
229
+ Callback method that is called when a purchase acknowledgement is complete.
230
+
231
+ Args:
232
+ billing_result: The result of the acknowledgement operation.
233
+ """
202
234
  print(billing_result.getDebugMessage())
203
235
  if billing_result.getResponseCode() == BillingResponseCode.OK:
204
236
  self.toast("Thank you for subscribing to buy us a cup of coffee! monthly")
205
237
 
206
238
  def on_consume_response(self, billing_result):
239
+ """
240
+ Callback method that is called when a purchase consumption is complete.
241
+
242
+ Args:
243
+ billing_result: The result of the consumption operation.
244
+ """
207
245
  if billing_result.getResponseCode() == BillingResponseCode.OK:
208
246
  self.toast("Thank you for buying us a cup of coffee!")
209
247
 
210
- def on_product_details_response(self, billing_result, product_details_list):
211
- for product_details in product_details_list:
212
- self.billing_client.get_product_details(
213
- product_details,
214
- ProductType.SUBS if self.ids.subscribe.active else ProductType.INAPP)
248
+ def on_product_details_response(self, billing_result, product_details_result):
249
+ """
250
+ Callback method that is called when product details are retrieved.
251
+
252
+ This method processes the product details and launches the billing flow.
253
+
254
+ Args:
255
+ billing_result: The result of the product details query.
256
+ product_details_result: The result containing product details and unfetched products.
257
+ """
258
+ product_details_list = product_details_result.getProductDetailsList()
259
+ unfetched_product_list = product_details_result.getUnfetchedProductList()
260
+
215
261
  if billing_result.getResponseCode() == BillingResponseCode.OK:
262
+ for product_details in product_details_list:
263
+ self.billing_client.get_product_details(
264
+ product_details,
265
+ ProductType.SUBS if self.ids.subscribe.active else ProductType.INAPP)
266
+ for unfetched_product in unfetched_product_list:
267
+ print(self.billing_client.get_unfetched_product(unfetched_product))
216
268
  self.billing_client.launch_billing_flow(product_details=product_details_list)
217
269
 
218
270
  def on_billing_setup_finished(self, billing_result):
271
+ """
272
+ Callback method that is called when the billing setup is complete.
273
+
274
+ This method queries product details if the billing setup was successful.
275
+
276
+ Args:
277
+ billing_result: The result of the billing setup operation.
278
+ """
219
279
  product_id = self.ids.btn.product_id
220
280
  if billing_result.getResponseCode() == BillingResponseCode.OK:
221
281
  self.billing_client.query_product_details_async(
222
- product_type=ProductType.SUBS if self.ids.subscribe.active else ProductType.INAPP,
282
+ product_type=ProductType.SUBS if self.ids.subscribe else ProductType.INAPP,
223
283
  products_ids=[product_id],
224
284
  on_product_details_response=self.on_product_details_response,
225
285
  )
226
286
 
227
287
  def toast(self, message):
288
+ """
289
+ Display a toast message.
290
+
291
+ This is a simple implementation that just prints the message.
292
+ In a real app, you would use platform-specific toast functionality.
293
+
294
+ Args:
295
+ message: The message to display.
296
+ """
228
297
  # Implementation of toast message (platform specific)
229
298
  print(message)
230
299
 
231
300
 
232
301
  class BillingApp(App):
302
+ """
303
+ Main application class for the SJBillingClient demo.
304
+
305
+ This class sets up the application and creates the screen manager
306
+ with the HomeScreen.
307
+ """
233
308
  def build(self):
309
+ """
310
+ Build the application UI.
311
+
312
+ Returns:
313
+ ScreenManager: The root widget of the application.
314
+ """
234
315
  # Create screen manager
235
316
  sm = ScreenManager()
236
317
  sm.add_widget(HomeScreen(name='home'))
@@ -276,7 +357,7 @@ if __name__ == '__main__':
276
357
  product_id: 'coffee_product_id'
277
358
  size_hint_y: None
278
359
  height: '60dp'
279
- on_release: root.purchase_or_subscribe()
360
+ on_release: root.support()
280
361
 
281
362
  Widget:
282
363
  # Spacer
@@ -284,13 +365,20 @@ if __name__ == '__main__':
284
365
 
285
366
  This example demonstrates:
286
367
 
287
- 1. A `HomeScreen` class that handles all billing operations
368
+ 1. A `HomeScreen` class that extends `Screen` and handles all billing operations
288
369
  2. A `BillingApp` class that sets up the Kivy application and screen manager
289
370
  3. A Kivy layout file that defines the UI with:
290
371
  - A checkbox to toggle between one-time purchase and subscription
291
372
  - A button to initiate the purchase flow
292
373
 
293
- The `purchase_or_subscribe` method is called when the button is pressed, which initializes the billing client and starts the connection. The various callback methods handle different stages of the billing process, including acknowledging purchases and consuming one-time purchases.
374
+ The `support` method is called when the button is pressed, which initializes the billing client and starts the connection. The various callback methods handle different stages of the billing process, including:
375
+ - Handling purchase updates with `on_purchases_updated`
376
+ - Acknowledging subscription purchases with `acknowledge_purchase`
377
+ - Consuming one-time purchases with `consume_async`
378
+ - Processing product details with `on_product_details_response`, including handling unfetched products
379
+ - Querying product details with `query_product_details_async`
380
+
381
+ This example is designed to be copy-and-paste runnable, with no need for the user to add or remove anything to test it.
294
382
 
295
383
  ## API Reference
296
384
 
@@ -298,16 +386,89 @@ The `purchase_or_subscribe` method is called when the button is pressed, which i
298
386
 
299
387
  The main class for interacting with Google Play Billing.
300
388
 
389
+ #### Constructor
390
+
391
+ - `__init__(on_purchases_updated, enable_one_time_products=True, enable_prepaid_plans=False)`:
392
+ - Initializes a new BillingClient instance
393
+ - `on_purchases_updated`: Callback function that will be triggered when purchases are updated
394
+ - `enable_one_time_products`: Boolean to enable one-time products (default: True)
395
+ - `enable_prepaid_plans`: Boolean to enable prepaid plans (default: False)
396
+
397
+ #### Connection Methods
398
+
399
+ - `start_connection(on_billing_setup_finished, on_billing_service_disconnected)`:
400
+ - Starts a connection with the billing client
401
+ - `on_billing_setup_finished`: Callback when billing setup is complete
402
+ - `on_billing_service_disconnected`: Callback when billing service is disconnected
403
+
404
+ - `end_connection()`:
405
+ - Ends the connection with the billing client
406
+
407
+ #### Product Details Methods
408
+
409
+ - `query_product_details_async(product_type, products_ids, on_product_details_response)`:
410
+ - Queries product details asynchronously
411
+ - `product_type`: Type of products (INAPP or SUBS)
412
+ - `products_ids`: List of product IDs to query
413
+ - `on_product_details_response`: Callback for product details response
414
+
415
+ - `get_product_details(product_details, product_type)`:
416
+ - Gets formatted product details
417
+ - `product_details`: Product details object
418
+ - `product_type`: Type of product (INAPP or SUBS)
419
+ - Returns a list of dictionaries with product details
420
+
421
+ - `get_unfetched_product(unfetched_product)`:
422
+ - Gets details about an unfetched product
423
+ - `unfetched_product`: Unfetched product object
424
+ - Returns a dictionary with product ID, type, and status code
425
+
426
+ #### Purchase Methods
427
+
428
+ - `launch_billing_flow(product_details, offer_token=None)`:
429
+ - Launches the billing flow for purchase
430
+ - `product_details`: List of product details objects
431
+ - `offer_token`: Optional token for subscription offers
432
+
433
+ - `consume_async(purchase, on_consume_response)`:
434
+ - Consumes a purchase asynchronously
435
+ - `purchase`: Purchase object to consume
436
+ - `on_consume_response`: Callback for consume response
437
+
438
+ - `acknowledge_purchase(purchase_token, on_acknowledge_purchase_response)`:
439
+ - Acknowledges a purchase
440
+ - `purchase_token`: Token of the purchase to acknowledge
441
+ - `on_acknowledge_purchase_response`: Callback for acknowledge response
442
+
443
+ ### PendingPurchasesParams
444
+
445
+ Parameters for handling pending purchases.
446
+
447
+ #### Methods
448
+
449
+ - `newBuilder()`: Creates a new builder for PendingPurchasesParams
450
+ - `build()`: Builds the PendingPurchasesParams object
451
+ - `enableOneTimeProducts()`: Enables one-time products
452
+ - `enablePrepaidPlans()`: Enables prepaid plans
453
+
454
+ ### QueryProductDetailsParams
455
+
456
+ Parameters for querying product details.
457
+
458
+ #### Methods
459
+
460
+ - `newBuilder()`: Creates a new builder for QueryProductDetailsParams
461
+ - `setProductList(product_list)`: Sets the list of products to query
462
+ - `build()`: Builds the QueryProductDetailsParams object
463
+
464
+ ### QueryProductDetailsResult
465
+
466
+ Result of a product details query.
467
+
301
468
  #### Methods
302
469
 
303
- - `__init__(on_purchases_updated)`: Initialize with a callback for purchase updates
304
- - `start_connection(on_billing_setup_finished, on_billing_service_disconnected)`: Start billing connection
305
- - `end_connection()`: End billing connection
306
- - `query_product_details_async(product_type, products_ids, on_product_details_response)`: Query product details
307
- - `get_product_details(product_details, product_type)`: Get formatted product details
308
- - `launch_billing_flow(product_details, offer_token=None)`: Launch purchase flow
309
- - `consume_async(purchase, on_consume_response)`: Consume a purchase
310
- - `acknowledge_purchase(purchase_token, on_acknowledge_purchase_response)`: Acknowledge a purchase
470
+ - `getProductDetailsList()`: Gets the list of product details
471
+ - `getUnfetchedProductList()`: Gets the list of unfetched products
311
472
 
312
473
  ### ProductType
313
474
 
@@ -320,10 +481,17 @@ Constants for product types:
320
481
 
321
482
  Constants for billing response codes:
322
483
 
323
- - `BillingResponseCode.OK`: Success
324
- - `BillingResponseCode.USER_CANCELED`: User canceled
325
- - `BillingResponseCode.SERVICE_UNAVAILABLE`: Service unavailable
326
- - And many others
484
+ - `BillingResponseCode.OK`: Success (0)
485
+ - `BillingResponseCode.USER_CANCELED`: User canceled (1)
486
+ - `BillingResponseCode.SERVICE_UNAVAILABLE`: Service unavailable (2)
487
+ - `BillingResponseCode.BILLING_UNAVAILABLE`: Billing unavailable (3)
488
+ - `BillingResponseCode.ITEM_UNAVAILABLE`: Item unavailable (4)
489
+ - `BillingResponseCode.DEVELOPER_ERROR`: Developer error (5)
490
+ - `BillingResponseCode.ERROR`: General error (6)
491
+ - `BillingResponseCode.ITEM_ALREADY_OWNED`: Item already owned (7)
492
+ - `BillingResponseCode.ITEM_NOT_OWNED`: Item not owned (8)
493
+ - `BillingResponseCode.SERVICE_DISCONNECTED`: Service disconnected (10)
494
+ - `BillingResponseCode.FEATURE_NOT_SUPPORTED`: Feature not supported (12)
327
495
 
328
496
  ## Contributing
329
497
 
@@ -3,15 +3,15 @@ sjbillingclient/jclass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
3
3
  sjbillingclient/jclass/acknowledge.py,sha256=FeaiOsIR2_WxJQC56gaeCtOPTEWb7Dz7AuWE6VYVMJI,358
4
4
  sjbillingclient/jclass/billing.py,sha256=Hkk_yvnPQel0Fw_SFVdhP3unmhRkWNDVUa4RM1qhzdY,5499
5
5
  sjbillingclient/jclass/consume.py,sha256=Hh8sLGosVvs22NhdQRudFc_NP_ahvrJSJdJTM-_nLBQ,310
6
- sjbillingclient/jclass/purchase.py,sha256=sLEihOLiyvwDIWBhHSpmMj1swNr4RJizceQOKmBqHM4,346
7
- sjbillingclient/jclass/queryproduct.py,sha256=0JkaC9E1Juxl79t7gJCUfrQntWiLWjfScSEI-mss8Lg,671
6
+ sjbillingclient/jclass/purchase.py,sha256=trFRSDHdMUPZsAxdyU7HuChT0qicDO-EjfPp9d6unrA,844
7
+ sjbillingclient/jclass/queryproduct.py,sha256=Akuxy3fO1djerVPidqmjUclKVtIDmlaNJxZDbyUWOUw,1115
8
8
  sjbillingclient/jinterface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  sjbillingclient/jinterface/acknowledge.py,sha256=OG5GWYO1TXfC7nscn8pPjsrdm2BGOCASRCzscKfyPFM,522
10
10
  sjbillingclient/jinterface/billing.py,sha256=lwBGN8Xe0Qbc1DCRSShrhL8oGqRbjugwrgNspEK-nmc,1265
11
11
  sjbillingclient/jinterface/consume.py,sha256=DiugwpRreoVLpPjeHSkNMgncg5f3HnIBCUh0OIyrWhI,524
12
- sjbillingclient/jinterface/product.py,sha256=rtlc-4hxToCa3buwNp8QufMYkoiUZHp_YXKeE-QZZyk,562
12
+ sjbillingclient/jinterface/product.py,sha256=kr_oPhRnQd0xbZItFLtACjBhZsnUV8q-kooqG_biVPs,627
13
13
  sjbillingclient/jinterface/purchases.py,sha256=BG6xF3H-35_XhiRr2kWDb1jzsxJ-hIw-jaEi-uSkTmY,574
14
- sjbillingclient/tools/__init__.py,sha256=g0k73jc9mcbAe86gM8Q_r9fp5dxHJWIbeqzO9Ne3xA4,19622
15
- sjbillingclient-0.1.4.dist-info/METADATA,sha256=6q45Ork4P_V9HG7Gtjx--ksqH5pxQ6UPOe0rRRA8VbM,12093
16
- sjbillingclient-0.1.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
17
- sjbillingclient-0.1.4.dist-info/RECORD,,
14
+ sjbillingclient/tools/__init__.py,sha256=PqsUr6tIBdAUN4NNKvWR3aRdNQ-ZN84MAzkBKcm6sik,21127
15
+ sjbillingclient-0.2.0.dist-info/METADATA,sha256=DICVzpmYPMuAUP9Co-yyBchoBMpT-oOOOTokqC6zAwY,18430
16
+ sjbillingclient-0.2.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
17
+ sjbillingclient-0.2.0.dist-info/RECORD,,