Error (#2796)

* Expose SKError code to client apps

* Format

* Update changelog

* Fix failing tests

* Added version updates in pubspec

* Fix test
diff --git a/packages/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/CHANGELOG.md
index 7c28907..b7b025c 100644
--- a/packages/in_app_purchase/CHANGELOG.md
+++ b/packages/in_app_purchase/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.3.4
+
+* Expose SKError code to client apps.
+
 ## 0.3.3+2
 
 * Post-v2 Android embedding cleanups.
diff --git a/packages/in_app_purchase/lib/src/in_app_purchase/app_store_connection.dart b/packages/in_app_purchase/lib/src/in_app_purchase/app_store_connection.dart
index f5ab95c..871879d 100644
--- a/packages/in_app_purchase/lib/src/in_app_purchase/app_store_connection.dart
+++ b/packages/in_app_purchase/lib/src/in_app_purchase/app_store_connection.dart
@@ -215,17 +215,7 @@
     purchaseUpdatedController
         .add(transactions.map((SKPaymentTransactionWrapper transaction) {
       PurchaseDetails purchaseDetails =
-          PurchaseDetails.fromSKTransaction(transaction, receiptData)
-            ..status = SKTransactionStatusConverter()
-                .toPurchaseStatus(transaction.transactionState)
-            ..error = transaction.error != null
-                ? IAPError(
-                    source: IAPSource.AppStore,
-                    code: kPurchaseErrorCode,
-                    message: transaction.error.domain,
-                    details: transaction.error.userInfo,
-                  )
-                : null;
+          PurchaseDetails.fromSKTransaction(transaction, receiptData);
       return purchaseDetails;
     }).toList());
   }
diff --git a/packages/in_app_purchase/lib/src/in_app_purchase/purchase_details.dart b/packages/in_app_purchase/lib/src/in_app_purchase/purchase_details.dart
index e9dca78..2321bd0 100644
--- a/packages/in_app_purchase/lib/src/in_app_purchase/purchase_details.dart
+++ b/packages/in_app_purchase/lib/src/in_app_purchase/purchase_details.dart
@@ -196,6 +196,14 @@
         _platform = _kPlatformIOS {
     status = SKTransactionStatusConverter()
         .toPurchaseStatus(transaction.transactionState);
+    if (status == PurchaseStatus.error) {
+      error = IAPError(
+        source: IAPSource.AppStore,
+        code: kPurchaseErrorCode,
+        message: transaction.error.domain,
+        details: transaction.error.userInfo,
+      );
+    }
   }
 
   /// Generate a [PurchaseDetails] object based on an Android [Purchase] object.
@@ -211,6 +219,13 @@
         this.billingClientPurchase = purchase,
         _platform = _kPlatformAndroid {
     status = PurchaseStateConverter().toPurchaseStatus(purchase.purchaseState);
+    if (status == PurchaseStatus.error) {
+      error = IAPError(
+        source: IAPSource.GooglePlay,
+        code: kPurchaseErrorCode,
+        message: null,
+      );
+    }
   }
 }
 
diff --git a/packages/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/pubspec.yaml
index 53a9264..12c7b45 100644
--- a/packages/in_app_purchase/pubspec.yaml
+++ b/packages/in_app_purchase/pubspec.yaml
@@ -1,7 +1,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.
 homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase
-version: 0.3.3+2
+version: 0.3.4
 
 dependencies:
   async: ^2.0.8
diff --git a/packages/in_app_purchase/test/in_app_purchase_connection/app_store_connection_test.dart b/packages/in_app_purchase/test/in_app_purchase_connection/app_store_connection_test.dart
index 9f963c4..cb2e0e7 100644
--- a/packages/in_app_purchase/test/in_app_purchase_connection/app_store_connection_test.dart
+++ b/packages/in_app_purchase/test/in_app_purchase_connection/app_store_connection_test.dart
@@ -228,7 +228,7 @@
           .buyNonConsumable(purchaseParam: purchaseParam);
 
       IAPError completerError = await completer.future;
-      expect(completerError.code, kPurchaseErrorCode);
+      expect(completerError.code, 'purchase_error');
       expect(completerError.source, IAPSource.AppStore);
       expect(completerError.message, 'ios_domain');
       expect(completerError.details, {'message': 'an error message'});