科尔多瓦应用内购买中央凹插件在IOS上只返回id



当通过中央凹(https://github.com/j3k0/cordova-plugin-purchase/)使用Cordova应用购买插件时,交易对象仅包含一个"id"。

为什么它不像Android那样返回其余的细节?

我在 TestFlight 上与具有最新更新的实体 iPhone 5 上的沙盒用户进行了测试。

iOS 响应:

{  
   "id":"subscription_1",
   "alias":"Subscription 20",
   "type":"paid subscription",
   "state":"approved",
   "title":"Subscription",
   "description":"Subscription",
   "price":"$19.99",
   "currency":null,
   "loaded":true,
   "canPurchase":false,
   "owned":false,
   "downloading":false,
   "downloaded":false,
   "transaction":{  
      "type":"ios-appstore",
      "id":"1000000200491361"
   },
   "valid":true,
   "transactions":[  
      "1000000200450592",
      "1000000200450626",
      "1000000200450699",
      "1000000200450768",
      "1000000200450968",
      "1000000200451015",
      "1000000200451978",
      "1000000200452019",
      "1000000200452040",
      "1000000200452082",
      "1000000200452130",
      "1000000200452155",
      "1000000200471605",
      "1000000200471725",
      "1000000200471771",
      "1000000200491361"
   ]
}

安卓响应:

{  
   "id":"iap_id",
   "alias":"Subscription 20",
   "type":"paid subscription",
   "state":"approved",
   "title":"Standard Subscription",
   "description":"Standard Subscription",
   "price":"$19.99",
   "currency":"USD",
   "loaded":true,
   "canPurchase":false,
   "owned":false,
   "downloading":false,
   "downloaded":false,
   "transaction":{  
      "type":"android-playstore",
      "purchaseToken":"bhgenijimhhgenhadngmajnp.AO-J1OxzqrUBfYXMJinFFjbRSUhL6E7bcbfnp0uZpEWi_ziPiimWbFt4n7IjRMN_1_yrP5m0jVI5l0t9OzfhsfLGyoJ-5E1ey9KLewlEGEGBM_B4EbinjZ5tWTrl",
      "receipt":"{"packageName":"com.package.first","productId":"iap_id","purchaseTime":1458232471621,"purchaseState":0,"purchaseToken":"bhgenijimhhgenhadngmajnp.AO-J1OxzqrUBfYXMJinFFjbRSUhL6E7bcbfnp0uZpEWi_ziPiimWbFt4n7IjRMN_1_yrP5m0jVI5l0t9OzfhsfLGyoJ-5E1ey9KLewlEGEGBM_B4EbinjZ5tWTrl","autoRenewing":false}",
      "signature":"PmKBJWBlVcIg//lZuMaG0zIEQZMcPrJjPUipJ/m0Ccm69mAmh1nPNyy6/Du6FMDEWijEI9jpbnQjLz4/bWBuqjr2CCLImcBFnHkA+ZvslDlh5ZzjwxtC7kD6PwuOMlelqS82JhIRMv1ZwxIYdEA8+Y5XiIClmJ5qvtCcgjU8b2HXDy3lIj5GfWCXJkoE0BMVHLJZemTK4asB5VzxU2xbUrk6ugBmc5jJ0LdlDue12NhFI62edhZoMhOoWd7TJP+IadUb8fIUb4AGct3zI5ccM1pHrzwvUuU0VWxLUs5qr2zCNkz4kw=="
   },
   "valid":true
}

在 Android 上,包含交易详细信息的收据在购买后立即可用,因此它包含在"交易"字段中。

在 iOS 上,SDK 需要显式加载它。如果我是对的,这仅在配置收据验证时由插件完成。我想这就是你试图实现的目标。您应该尝试从您自己的"store.validator"方法中访问这些字段。

请参阅 https://github.com/j3k0/cordova-plugin-purchase/blob/master/doc/api.md#validator

好的,这就是我到目前为止所拥有的。 这适用于 iOS,我稍后将不得不返回并使用 Android 进行测试,但现在这有效,以下是 store.validator 方法中的产品对象:

var product = {
  "id": "propicks",
  "alias": "propicks",
  "type": "consumable",
  "state": "approved",
  "title": "BEST BETS & More!",
  "description": "BEST BETS, Pick Confidence, & ML Odds!",
  "price": "$2.99",
  "currency": "USD",
  "loaded": true,
  "canPurchase": false,
  "owned": false,
  "downloading": false,
  "downloaded": false,
  "transaction": {
    "type": "ios-appstore",
    "id": "1000000263098271",
    "appStoreReceipt": "MIIT...",
    "transactionReceipt": "ew..."
      },
  "valid": true,
  "transactions": [ "1000000263098271" ]
}

经过一些测试,product.transaction.transactionReceipt似乎始终是唯一的收据,因此这是我正在与Apple验证的收据。 我使用的是耗材,因此订阅可能会有所不同。

这是我的store.validator方法:

store.validator = function(product, callback) {
    app.kendoConsole.log('in STORE.VALIDATOR FUNCTION');
    var myData = {
      transactionReceipt: product.transaction.transactionReceipt,
      purchaseType: product.transaction.type
    };
    $.ajax({
      url: app.config.checkIosReceiptUrl,
      data: myData,
      type: "POST",
      beforeSend: function() {
        app.utils.showLoading(kendo.format("Verifying Receipt..."));
      },
      complete: function() {
        app.utils.hideLoading();
      },
      error: function(jqXHR, textStatus, errorThrown) {
        app.utils.hideLoading();
        app.utils.handleAjaxErrors(jqXHR);
      },
      success: function(data) {
        if (data.success) {
          callback(true, {}); // success!   
        } else {
          callback(false, "Validation Failed.");
        }
      }
    });

好的,最后在服务器上,我的 C# 代码来 ping Apple,并确保收据在我的系统中始终是唯一的,不允许重播购买!

 [HttpPost]
    public JsonResult CheckIOS_Receipt( string transactionReceipt, string purchaseType )
    {
        bool isReceiptValid = false;
        // first check my database to make sure this receipt is unique.
        bool isNewPurchaseToken = InAppPurchaseBLL.IsNewPurchaseToken( transactionReceipt, purchaseType );
        if ( isNewPurchaseToken ) {
            var hasPassedReceiptValidationWithStore = InAppPurchaseBLL.IsAppleVerifiedPurchase( transactionReceipt );
            if ( hasPassedReceiptValidationWithStore ) {

                // at this point, I should save the purchase token.
                isReceiptValid = true;
            }
        }
        JsonResult data = Json( new { success = isReceiptValid } );
        return data;
    }

    /// <summary>
    /// Hit apple server and return true or false if token is legit.
    /// </summary>
    /// <param name="validPurchaseToken"></param>
    /// <param name="isTest"></param>
    public static bool IsAppleVerifiedPurchase( string validPurchaseToken, bool isTest = false ) {
        bool isAppleVerified = false;
        try {
            var json = new JObject( new JProperty( "receipt-data", validPurchaseToken ) ).ToString();
            ASCIIEncoding ascii = new ASCIIEncoding();
            byte[] postBytes = Encoding.UTF8.GetBytes( json );
            string appleURI;
            if ( isTest ) {
                appleURI = "https://sandbox.itunes.apple.com/verifyReceipt";
                //appleURI = ConfigurationManager.AppSettings[ "Apple_Test_Receipt_Validation_URL" ];
            }
            else {
                appleURI = "https://buy.itunes.apple.com/verifyReceipt";
                //appleURI = ConfigurationManager.AppSettings[ "Apple_Production_Receipt_Validation_URL" ];
            }

            WebRequest request = HttpWebRequest.Create( appleURI );
            request.Method = "POST";
            request.ContentType = "application/json";
            request.ContentLength = postBytes.Length;
            using ( var stream = request.GetRequestStream() ) {
                stream.Write( postBytes, 0, postBytes.Length );
                stream.Flush();
            }
            var sendresponse = request.GetResponse();
            string sendresponsetext = "";
            using ( var streamReader = new StreamReader( sendresponse.GetResponseStream() ) ) {
                sendresponsetext = streamReader.ReadToEnd().Trim();
            }
            if ( sendresponse.IsNotNullOrEmptyString() ) {
                JObject jsonResponse = JObject.Parse( sendresponsetext );
                int status = -1;
                int.TryParse( jsonResponse[ "status" ].ToString(), out status );
                /*
                * When validating receipts on your server, your server needs to be able to handle a 
                * production-signed app getting its receipts from Apple’s test environment. 
                * The recommended approach is for your production server to always validate receipts against 
                * the production App Store first. If validation fails with the error code “Sandbox receipt used in production”, 
                * validate against the test environment instead.
                * */
                switch ( status ) {
                    case 21007:
                        /*
                         * This receipt is from the test environment, but it was sent to the production environment 
                         * for verification. Send it to the test environment instead. 
                         * */
                         // This means I'm testing on my device and still need to validate against the sandbox url.
                        return IsAppleVerifiedPurchase( validPurchaseToken, isTest: true );
                    case 21008:
                        /*
                         * This receipt is from the production environment, but it was sent to the test environment 
                         * for verification. Send it to the production environment instead.
                         * */
                        // so I don't see this ever happening but if it does, resend it to the production envirnoment instead of the sandbox.
                        return IsAppleVerifiedPurchase( validPurchaseToken, isTest: false );

                    case 0:
                        // sweet success!  the receipt is valid. Status should be either 0 or one of the error codes described here:
                        // https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW5
                        isAppleVerified = true;
                        break;
                    default:
                        isAppleVerified = false;
                        break;
                }
            }
        }
        catch ( Exception ex ) {
            ex.Message.ToString();
        }
        return isAppleVerified;
    }

最新更新