在App Purchase中:无法跟踪进程CANCEL或SUCCESS

时间:2016-08-11 09:53:03

标签: ios transactions swift2 in-app-purchase

当我使用IAP在sandBox中测试时,我有2个案例:

  • 案例1:如果我成功购买商品。 package com.example.shyamali.maptest; import android.Manifest; import android.app.ProgressDialog; import android.content.pm.PackageManager; import android.graphics.Color; import android.location.Location; import android.net.Uri; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; import com.google.maps.android.SphericalUtil; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,GoogleMap.OnMarkerDragListener,GoogleMap.OnMapLongClickListener,View.OnClickListener { //Our Map private GoogleMap mMap; //To store longitude and latitude from map private double longitude; private double latitude; //From -> the first coordinate from where we need to calculate the distance private double fromLongitude; private double fromLatitude; //To -> the second coordinate to where we need to calculate the distance private double toLongitude; private double toLatitude; //Google ApiClient private GoogleApiClient googleApiClient; //Our buttons private Button buttonSetTo; private Button buttonSetFrom; private Button buttonCalcDistance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); // Obtain the SupportMapFragment and get notified when the map is ready to be used. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); //Initializing googleapi client // ATTENTION: This "addApi(AppIndex.API)"was auto-generated to implement the App Indexing API. // See https://g.co/AppIndexing/AndroidStudio for more information. googleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .addApi(AppIndex.API).build(); buttonSetTo = (Button) findViewById(R.id.buttonSetTo); buttonSetFrom = (Button) findViewById(R.id.buttonSetFrom); buttonCalcDistance = (Button) findViewById(R.id.buttonCalcDistance); buttonSetTo.setOnClickListener(this); buttonSetFrom.setOnClickListener(this); buttonCalcDistance.setOnClickListener(this); } @Override protected void onStart() { googleApiClient.connect(); super.onStart(); // ATTENTION: This was auto-generated to implement the App Indexing API. // See https://g.co/AppIndexing/AndroidStudio for more information. Action viewAction = Action.newAction( Action.TYPE_VIEW, // TODO: choose an action type. "Maps Page", // TODO: Define a title for the content shown. // TODO: If you have web page content that matches this app activity's content, // make sure this auto-generated web page URL is correct. // Otherwise, set the URL to null. Uri.parse("http://host/path") ); AppIndex.AppIndexApi.start(googleApiClient, viewAction); } @Override protected void onStop() { googleApiClient.disconnect(); super.onStop(); // ATTENTION: This was auto-generated to implement the App Indexing API. // See https://g.co/AppIndexing/AndroidStudio for more information. Action viewAction = Action.newAction( Action.TYPE_VIEW, // TODO: choose an action type. "Maps Page", // TODO: Define a title for the content shown. // TODO: If you have web page content that matches this app activity's content, // make sure this auto-generated web page URL is correct. // Otherwise, set the URL to null. Uri.parse("http://host/path") ); AppIndex.AppIndexApi.end(googleApiClient, viewAction); } //Getting current location private void getCurrentLocation() { mMap.clear(); //Creating a location object if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); if (location != null) { //Getting longitude and latitude longitude = location.getLongitude(); latitude = location.getLatitude(); //moving the map to location moveMap(); } } //Function to move the map private void moveMap() { //Creating a LatLng Object to store Coordinates LatLng latLng = new LatLng(latitude, longitude); //Adding marker to map mMap.addMarker(new MarkerOptions() .position(latLng) //setting position .draggable(true) //Making the marker draggable .title("Current Location")); //Adding a title //Moving the camera mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); //Animating the camera mMap.animateCamera(CameraUpdateFactory.zoomTo(15)); } public String makeURL (double sourcelat, double sourcelog, double destlat, double destlog ){ StringBuilder urlString = new StringBuilder(); urlString.append("https://maps.googleapis.com/maps/api/directions/json"); urlString.append("?origin=");// from urlString.append(Double.toString(sourcelat)); urlString.append(","); urlString .append(Double.toString( sourcelog)); urlString.append("&destination=");// to urlString .append(Double.toString( destlat)); urlString.append(","); urlString.append(Double.toString(destlog)); urlString.append("&sensor=false&mode=driving&alternatives=true"); urlString.append("&key=AIzaSyCJVpM7-ayGMraxFRzq4U8Dt1uRNsmiaws"); return urlString.toString(); } private void getDirection(){ //Getting the URL String url = makeURL(fromLatitude, fromLongitude, toLatitude, toLongitude); //Showing a dialog till we get the route final ProgressDialog loading = ProgressDialog.show(this, "Getting Route", "Please wait...", false, false); //Creating a string request StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() { @Override public void onResponse(String response) { loading.dismiss(); //Calling the method drawPath to draw the path drawPath(response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { loading.dismiss(); } }); //Adding the request to request queue RequestQueue requestQueue = Volley.newRequestQueue(this); requestQueue.add(stringRequest); } //The parameter is the server response public void drawPath(String result) { //Getting both the coordinates LatLng from = new LatLng(fromLatitude,fromLongitude); LatLng to = new LatLng(toLatitude,toLongitude); //Calculating the distance in meters Double distance = SphericalUtil.computeDistanceBetween(from, to); //Displaying the distance Toast.makeText(this,String.valueOf(distance+" Meters"),Toast.LENGTH_SHORT).show(); try { //Parsing json final JSONObject json = new JSONObject(result); JSONArray routeArray = json.getJSONArray("routes"); JSONObject routes = routeArray.getJSONObject(0); JSONObject overviewPolylines = routes.getJSONObject("overview_polyline"); String encodedString = overviewPolylines.getString("points"); List<LatLng> list = decodePoly(encodedString); Polyline line = mMap.addPolyline(new PolylineOptions() .addAll(list) .width(20) .color(Color.RED) .geodesic(true) ); } catch (JSONException e) { } } private List<LatLng> decodePoly(String encoded) { List<LatLng> poly = new ArrayList<LatLng>(); int index = 0, len = encoded.length(); int lat = 0, lng = 0; while (index < len) { int b, shift = 0, result = 0; do { b = encoded.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = encoded.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lng += dlng; LatLng p = new LatLng( (((double) lat / 1E5)), (((double) lng / 1E5) )); poly.add(p); } return poly; } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; LatLng latLng = new LatLng(-34, 151); mMap.addMarker(new MarkerOptions().position(latLng).draggable(true)); mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); mMap.setOnMarkerDragListener(this); mMap.setOnMapLongClickListener(this); } @Override public void onConnected(Bundle bundle) { getCurrentLocation(); } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } @Override public void onMapLongClick(LatLng latLng) { //Clearing all the markers mMap.clear(); //Adding a new marker to the current pressed position mMap.addMarker(new MarkerOptions() .position(latLng) .draggable(true)); latitude = latLng.latitude; longitude = latLng.longitude; } @Override public void onMarkerDragStart(Marker marker) { } @Override public void onMarkerDrag(Marker marker) { } @Override public void onMarkerDragEnd(Marker marker) { //Getting the coordinates latitude = marker.getPosition().latitude; longitude = marker.getPosition().longitude; //Moving the map moveMap(); } @Override public void onClick(View v) { if(v == buttonSetFrom){ fromLatitude = latitude; fromLongitude = longitude; Toast.makeText(this,"From set",Toast.LENGTH_SHORT).show(); } if(v == buttonSetTo){ toLatitude = latitude; toLongitude = longitude; Toast.makeText(this,"To set",Toast.LENGTH_SHORT).show(); } if(v == buttonCalcDistance){ getDirection(); } } } 切换为transaction.state密钥。
  • 案例2:如果我在Iphone要求我登录Apple ID或接受付款时取消。 Purchased也切换到transaction.state密钥。

如何解决我的问题?如何知道用户是否取消? 谢谢!

更新 当我在模拟器中测试时,当我取消In App Purchase请求时,Purchased切换到SKPaymentTransactionState

但是,当我在真实设备中进行测试时,当我取消In App Purchase请求Apple ID时Failed切换到SKPaymentTransactionStatePurchased总是transaction.error

我不知道为什么。

更新

  • 我无法跟踪TransactionState,因为我已经使用了我已经越狱并使用本地验证收据的老板设备。我的天啊。
  • 感谢您的帮助

1 个答案:

答案 0 :(得分:0)

试试这个

if (transaction.error.code == SKErrorPaymentCancelled)
    {
            NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    }

更多信息,

switch (transaction.error.code) {
    case SKErrorUnknown:
        //Unknown error
        break;
    case SKErrorClientInvalid:
        // client is not allowed to issue the request, etc.
        break;
    case SKErrorPaymentCancelled:
        // user cancelled the request, etc.
        break;
    case SKErrorPaymentInvalid:
        // purchase identifier was invalid, etc.
        break;
    case SKErrorPaymentNotAllowed:
        // this device is not allowed to make the payment
        break;
    default:
        break;
}